<commit_before>#include "gtest/gtest.h"

#include <string>

#include SPECIFIC_HEADER

// Running tests

TEST(TEST_NAME, Example0)
{
  ASSERT_EQ(2, fast_knight("a1", "b3", "c5"));
}
TEST(TEST_NAME, Example1)
{
  ASSERT_EQ(3, fast_knight("b1", "c3", "a3"));
}
TEST(TEST_NAME, Example2)
{
  ASSERT_EQ(6, fast_knight("a1", "a2", "b2"));
}
TEST(TEST_NAME, Example3)
{
  ASSERT_EQ(3, fast_knight("a5", "b7", "e4"));
}
TEST(TEST_NAME, Example4)
{
  ASSERT_EQ(6, fast_knight("h8", "e2", "d2"));
}

int main(int argc, char **argv)
{
  ::testing::InitGoogleTest(&argc, argv);
  int ret { RUN_ALL_TESTS() };
  return ret;
}
<commit_msg>[topcoder-capturethemall] Extended tests<commit_after>#include "gtest/gtest.h"

#include <string>

#include SPECIFIC_HEADER

// Running tests

TEST(TEST_NAME, Example0)
{
  ASSERT_EQ(2, fast_knight("a1", "b3", "c5"));
}
TEST(TEST_NAME, Example1)
{
  ASSERT_EQ(3, fast_knight("b1", "c3", "a3"));
}
TEST(TEST_NAME, Example2)
{
  ASSERT_EQ(6, fast_knight("a1", "a2", "b2"));
}
TEST(TEST_NAME, Example3)
{
  ASSERT_EQ(3, fast_knight("a5", "b7", "e4"));
}
TEST(TEST_NAME, Example4)
{
  ASSERT_EQ(6, fast_knight("h8", "e2", "d2"));
}

TEST(TEST_NAME, Extended0)
{
  ASSERT_EQ(8, fast_knight("a1", "h8", "b2"));
}
TEST(TEST_NAME, Extended1)
{
  ASSERT_EQ(8, fast_knight("a1", "h8", "b1"));
}
TEST(TEST_NAME, Extended2)
{
  ASSERT_EQ(10, fast_knight("a1", "a8", "h8"));
}
TEST(TEST_NAME, Extended3)
{
  ASSERT_EQ(6, fast_knight("c8", "g6", "b7"));
}
TEST(TEST_NAME, Extended4)
{
  ASSERT_EQ(7, fast_knight("f5", "c1", "a3"));
}
TEST(TEST_NAME, Extended5)
{
  ASSERT_EQ(8, fast_knight("b2", "h4", "a1"));
}
TEST(TEST_NAME, Extended6)
{
  ASSERT_EQ(5, fast_knight("b6", "d3", "a5"));
}
TEST(TEST_NAME, Extended7)
{
  ASSERT_EQ(4, fast_knight("g7", "e3", "h6"));
}
TEST(TEST_NAME, Extended8)
{
  ASSERT_EQ(7, fast_knight("g2", "g7", "h8"));
}
TEST(TEST_NAME, Extended9)
{
  ASSERT_EQ(3, fast_knight("e4", "c3", "g1"));
}
TEST(TEST_NAME, Extended10)
{
  ASSERT_EQ(6, fast_knight("d1", "f1", "a8"));
}
TEST(TEST_NAME, Extended11)
{
  ASSERT_EQ(5, fast_knight("c3", "e6", "g6"));
}
TEST(TEST_NAME, Extended12)
{
  ASSERT_EQ(6, fast_knight("d2", "f4", "d8"));
}
TEST(TEST_NAME, Extended13)
{
  ASSERT_EQ(4, fast_knight("f1", "e4", "f5"));
}
TEST(TEST_NAME, Extended14)
{
  ASSERT_EQ(5, fast_knight("e3", "b2", "d7"));
}
TEST(TEST_NAME, Extended15)
{
  ASSERT_EQ(7, fast_knight("e8", "g3", "b6"));
}
TEST(TEST_NAME, Extended16)
{
  ASSERT_EQ(5, fast_knight("d1", "f5", "b8"));
}
TEST(TEST_NAME, Extended17)
{
  ASSERT_EQ(7, fast_knight("b8", "f3", "d1"));
}
TEST(TEST_NAME, Extended18)
{
  ASSERT_EQ(6, fast_knight("h6", "b8", "g5"));
}
TEST(TEST_NAME, Extended19)
{
  ASSERT_EQ(7, fast_knight("b2", "g4", "b5"));
}
TEST(TEST_NAME, Extended20)
{
  ASSERT_EQ(5, fast_knight("f4", "c5", "f7"));
}
TEST(TEST_NAME, Extended21)
{
  ASSERT_EQ(6, fast_knight("f4", "a3", "g1"));
}
TEST(TEST_NAME, Extended22)
{
  ASSERT_EQ(8, fast_knight("e6", "d1", "h8"));
}
TEST(TEST_NAME, Extended23)
{
  ASSERT_EQ(5, fast_knight("e3", "d3", "g3"));
}
TEST(TEST_NAME, Extended24)
{
  ASSERT_EQ(6, fast_knight("d3", "h3", "f5"));
}
TEST(TEST_NAME, Extended25)
{
  ASSERT_EQ(4, fast_knight("b7", "g4", "e8"));
}
TEST(TEST_NAME, Extended26)
{
  ASSERT_EQ(7, fast_knight("a8", "e1", "e2"));
}
TEST(TEST_NAME, Extended27)
{
  ASSERT_EQ(5, fast_knight("g6", "f2", "g1"));
}
TEST(TEST_NAME, Extended28)
{
  ASSERT_EQ(6, fast_knight("a6", "c8", "c3"));
}
TEST(TEST_NAME, Extended29)
{
  ASSERT_EQ(5, fast_knight("b6", "g6", "e6"));
}
TEST(TEST_NAME, Extended30)
{
  ASSERT_EQ(5, fast_knight("c2", "a1", "g7"));
}
TEST(TEST_NAME, Extended31)
{
  ASSERT_EQ(5, fast_knight("b1", "e1", "a4"));
}
TEST(TEST_NAME, Extended32)
{
  ASSERT_EQ(5, fast_knight("g6", "e1", "d2"));
}
TEST(TEST_NAME, Extended33)
{
  ASSERT_EQ(3, fast_knight("f3", "d2", "e5"));
}
TEST(TEST_NAME, Extended34)
{
  ASSERT_EQ(6, fast_knight("f2", "e8", "f8"));
}
TEST(TEST_NAME, Extended35)
{
  ASSERT_EQ(5, fast_knight("b3", "b8", "d8"));
}
TEST(TEST_NAME, Extended36)
{
  ASSERT_EQ(6, fast_knight("a6", "a4", "h1"));
}
TEST(TEST_NAME, Extended37)
{
  ASSERT_EQ(6, fast_knight("h3", "b7", "d2"));
}
TEST(TEST_NAME, Extended38)
{
  ASSERT_EQ(2, fast_knight("f5", "d4", "e6"));
}
TEST(TEST_NAME, Extended39)
{
  ASSERT_EQ(3, fast_knight("g7", "e6", "e4"));
}
TEST(TEST_NAME, Extended40)
{
  ASSERT_EQ(5, fast_knight("b6", "e8", "b2"));
}
TEST(TEST_NAME, Extended41)
{
  ASSERT_EQ(4, fast_knight("e6", "e3", "d1"));
}
TEST(TEST_NAME, Extended42)
{
  ASSERT_EQ(4, fast_knight("f5", "e6", "g2"));
}
TEST(TEST_NAME, Extended43)
{
  ASSERT_EQ(6, fast_knight("h8", "e2", "d2"));
}
TEST(TEST_NAME, Extended44)
{
  ASSERT_EQ(11, fast_knight("a1", "h1", "a8"));
}

int main(int argc, char **argv)
{
  ::testing::InitGoogleTest(&argc, argv);
  int ret { RUN_ALL_TESTS() };
  return ret;
}
<|endoftext|>


<commit_before>//
// Created by aj on 5/21/16.
//

#include "GPIOPin.h"
#include <fstream>
#include <iostream>

using namespace std;
using namespace Glib;

//TODO: Handle error conditions in all of these functions

/**
 * Instantiates a gpio pin
 */
GPIOPin::GPIOPin(ustring pinNum) {
    ofstream exportFile; //Can't use "export" because its a reserved word

    this->gpioPinNum = pinNum;
    this->GPIO_PIN_DIRECTORY = "/gpio" + pinNum;

    exportFile.open((GPIO_DIR + GPIO_EXPORT_FILE).c_str());

    exportFile << pinNum.c_str(); //Exports pin number

    exportFile.close();
}

/**
 * Unexports the pin for other uses
 */
GPIOPin::~GPIOPin() {
    ofstream unexport;
    unexport.open((GPIO_DIR + GPIO_UNEXPORT_FILE).c_str());

    unexport << this->gpioPinNum.c_str(); //Unexports pin number

    unexport.close();
}

/**
 * Sets up pin as an in or out
 * in: true for "in", false for "out"
 */
void GPIOPin::writeInOut(bool in) {
    ofstream direction;
    direction.open((GPIO_DIR + GPIO_PIN_DIRECTORY + GPIO_DIRECTION_FILE).c_str());

    if(in) {
        direction << "in";
    } else {
        direction << "out";
    }

    direction.close();
}

/**
 * Writes a value to the gpio pin
 */
void GPIOPin::writeValue(bool val) {
    ofstream value;
    value.open((GPIO_DIR + GPIO_PIN_DIRECTORY + GPIO_VALUE_FILE).c_str());

    cout << (GPIO_DIR + GPIO_PIN_DIRECTORY + GPIO_VALUE_FILE).c_str() << endl;
    cout << "Writing " << (int)val << endl;

    value << to_string((int)val); //Write value to file

    value.close();
}

/**
 * Writes a 1 to the gpio pin
 */
void GPIOPin::writeHigh() {
    writeValue(true);
}

/**
 * Writes a 0 to the gpio pin
 */
void GPIOPin::writeLow() {
    writeValue(false);
}

/**
 * Sets the pin as an input
 */
void GPIOPin::makeIn() {
    writeInOut(true);
}

/**
 * Sets the pin as an output
 */
void GPIOPin::makeOut() {
    writeInOut(false);
}

/**
 * Reads a value and returns a bool (int) indicating the value
 */
bool GPIOPin::readValue() {
    ifstream value;
    value.open((GPIO_DIR + GPIO_PIN_DIRECTORY + GPIO_VALUE_FILE).c_str());

    char val = (char) value.get();

    value.close();

    return val == '1';
}

/**
 * Toggles the current state
 * return: the state toggled from
 */
bool GPIOPin::toggle() {
    bool currVal = readValue();
    writeValue(!currVal);
    return currVal;
}

/**
 * Gives whether the gpio is an input or not
 * FIXME: Unimplemented
 */
bool GPIOPin::isInput() {
    return false; //UNIMPLEMENTED: DO NOT USE YET
}

/**
 * Default constructor
 * just instantiates pin 4
 * Not really useful unless you want pin 4
 */
GPIOPin::GPIOPin() : GPIOPin("4") { }

<commit_msg>Remove debug printing<commit_after>//
// Created by aj on 5/21/16.
//

#include "GPIOPin.h"
#include <fstream>

using namespace std;
using namespace Glib;

//TODO: Handle error conditions in all of these functions

/**
 * Instantiates a gpio pin
 */
GPIOPin::GPIOPin(ustring pinNum) {
    ofstream exportFile; //Can't use "export" because its a reserved word

    this->gpioPinNum = pinNum;
    this->GPIO_PIN_DIRECTORY = "/gpio" + pinNum;

    exportFile.open((GPIO_DIR + GPIO_EXPORT_FILE).c_str());

    exportFile << pinNum.c_str(); //Exports pin number

    exportFile.close();
}

/**
 * Unexports the pin for other uses
 */
GPIOPin::~GPIOPin() {
    ofstream unexport;
    unexport.open((GPIO_DIR + GPIO_UNEXPORT_FILE).c_str());

    unexport << this->gpioPinNum.c_str(); //Unexports pin number

    unexport.close();
}

/**
 * Sets up pin as an in or out
 * in: true for "in", false for "out"
 */
void GPIOPin::writeInOut(bool in) {
    ofstream direction;
    direction.open((GPIO_DIR + GPIO_PIN_DIRECTORY + GPIO_DIRECTION_FILE).c_str());

    if(in) {
        direction << "in";
    } else {
        direction << "out";
    }

    direction.close();
}

/**
 * Writes a value to the gpio pin
 */
void GPIOPin::writeValue(bool val) {
    ofstream value;
    value.open((GPIO_DIR + GPIO_PIN_DIRECTORY + GPIO_VALUE_FILE).c_str());

    value << to_string((int)val); //Write value to file

    value.close();
}

/**
 * Writes a 1 to the gpio pin
 */
void GPIOPin::writeHigh() {
    writeValue(true);
}

/**
 * Writes a 0 to the gpio pin
 */
void GPIOPin::writeLow() {
    writeValue(false);
}

/**
 * Sets the pin as an input
 */
void GPIOPin::makeIn() {
    writeInOut(true);
}

/**
 * Sets the pin as an output
 */
void GPIOPin::makeOut() {
    writeInOut(false);
}

/**
 * Reads a value and returns a bool (int) indicating the value
 */
bool GPIOPin::readValue() {
    ifstream value;
    value.open((GPIO_DIR + GPIO_PIN_DIRECTORY + GPIO_VALUE_FILE).c_str());

    char val = (char) value.get();

    value.close();

    return val == '1';
}

/**
 * Toggles the current state
 * return: the state toggled from
 */
bool GPIOPin::toggle() {
    bool currVal = readValue();
    writeValue(!currVal);
    return currVal;
}

/**
 * Gives whether the gpio is an input or not
 * FIXME: Unimplemented
 */
bool GPIOPin::isInput() {
    return false; //UNIMPLEMENTED: DO NOT USE YET
}

/**
 * Default constructor
 * just instantiates pin 4
 * Not really useful unless you want pin 4
 */
GPIOPin::GPIOPin() : GPIOPin("4") { }

<|endoftext|>


<commit_before>// Copyright (c) 2014 Arista Networks, Inc.  All rights reserved.
// Arista Networks, Inc. Confidential and Proprietary.

#include <unordered_set>

#include <eos/agent.h>
#include <eos/acl.h>
#include <eos/intf.h>
#include <eos/class_map.h>
#include <eos/policy_map.h>
#include <eos/sdk.h>
#include <eos/system.h>

#include <cstdio>

class policy_demo : public eos::agent_handler,
                    public eos::acl_handler,
                    public eos::policy_map_handler {
 public:
   explicit policy_demo(eos::sdk & sdk)
         : eos::agent_handler(sdk.get_agent_mgr()),
           eos::acl_handler(sdk.get_acl_mgr()),
           eos::policy_map_handler(sdk.get_policy_map_mgr()) {

      // Setup manager refs
      class_mgr = sdk.get_class_map_mgr();

      // Register for all ACL updates; when programming policies,
      // ACLs must be programmed before class maps before policy maps,
      // and they may fail independently of policy-map based PBR
      // programming. If ACL programming for ACLs used in class-maps
      // fails, the reported problem must be resolved before PBR
      // programming will complete.
      watch_all_acls(true);

   }

   ~policy_demo() {
   }

   void on_initialized() {
      printf("on_initialized - policy_demo starting\n");
      setup_policy();
   }

   // Configure PBR policymap pm1 with two class-maps and two single line raw
   // match rules.
   //
   // Service policy pm1
   //   Configured on: Management0
   //   Applied on:
   //   1: Class-map: cm1 (match-any)
   //     Match: 1 IP Access List acl1
   //         1 permit ip any 20.20.0.0/16 dscp 32
   //     Configured actions: drop
   //     Active routing action: No PBR action
   //   2: Class-map: cm2 (match-any)
   //     Match: 1 IPV6 Access List acl2
   //         1 permit ipv6 any 2001:db8:1234::/48 dscp 32
   //     Configured actions: drop
   //     Active routing action: No PBR action
   //   3: Single match statement
   //     Match:
   //         0 permit ip any 30.30.0.0/16 dscp 32
   //     Configured actions: set nexthop-group nexthopgroup2
   //     Active routing action: No PBR action
   //   4: Single match statement
   //     Match:
   //         0 permit ipv6 any 2001:db8:5678::/48 dscp 32
   //     Configured actions: set nexthop-group nexthopgroup2
   //     Active routing action: No PBR action

   void setup_policy() {
      eos::ip_addr_t dip;

      // Configure V4 ACL
      auto acl1 = eos::acl_key_t("acl1", eos::ACL_TYPE_IPV4);
      auto rule1 = eos::acl_rule_ip_t();
      rule1.action_is(eos::ACL_PERMIT);
      eos::parse_ip_addr("20.20.0.0", &dip);
      rule1.destination_addr_is(eos::ip_addr_mask_t(dip, 16));
      rule1.priority_value_is(32);
      rule1.match_ip_priority_is(true);
      get_acl_mgr()->acl_rule_set(acl1, 1, rule1);
      get_acl_mgr()->acl_commit();

      // Now build the class map for that ACL and commit it
      auto cmkey = eos::class_map_key_t("cm1", eos::POLICY_FEATURE_PBR);
      auto cm = eos::class_map_t(cmkey);
      cm.rule_set(1, eos::class_map_rule_t(acl1));
      class_mgr->class_map_is(cm);

      // Build a policy map
      auto pmkey = eos::policy_map_key_t("pm1", eos::POLICY_FEATURE_PBR);
      auto pm = eos::policy_map_t(pmkey);

      // Add the policy map rule matching our class map and dropping the traffic
      auto pmrule4 = eos::policy_map_rule_t(cmkey);
      auto action = eos::policy_map_action_t(eos::POLICY_ACTION_DROP);
      pmrule4.action_set(action);
      pm.rule_set(1, pmrule4);

      // Configure V6 ACL
      auto acl2 = eos::acl_key_t("acl2", eos::ACL_TYPE_IPV6);
      auto rule2 = eos::acl_rule_ip_t();
      rule2.action_is(eos::ACL_PERMIT);
      eos::parse_ip_addr("2001:db8:1234::", &dip);
      rule2.destination_addr_is(eos::ip_addr_mask_t(dip, 48));
      rule2.priority_value_is(129);
      rule2.priority_mask_is(255);
      get_acl_mgr()->acl_rule_set(acl2, 1, rule2);
      get_acl_mgr()->acl_commit();

      // Now build the class map for that ACL and commit it
      auto cmkey2 = eos::class_map_key_t("cm2", eos::POLICY_FEATURE_PBR);
      auto cm2 = eos::class_map_t(cmkey2);
      cm2.rule_set(1, eos::class_map_rule_t(acl2));
      class_mgr->class_map_is(cm2);

      // Add the policy map rule matching our class map and dropping the traffic
      auto pmrule6 = eos::policy_map_rule_t(cmkey2);
      pmrule6.action_set(action);
      pm.rule_set(2, pmrule6);

      // Add a V4 single line raw match rule.
      eos::acl_rule_ip_t raw_v4;
      eos::parse_ip_addr("30.30.0.0", &dip);
      raw_v4.destination_addr_is(eos::ip_addr_mask_t(dip, 16));
      raw_v4.priority_value_is(32);
      raw_v4.match_ip_priority_is(true);
      auto pmrule_raw_v4 = eos::policy_map_rule_t();
      pmrule_raw_v4.raw_rule_is(raw_v4, eos::POLICY_RULE_TYPE_IPV4);
      action = eos::policy_map_action_t(eos::POLICY_ACTION_NEXTHOP_GROUP);
      action.nexthop_group_name_is("nexthopgroup2");
      pmrule_raw_v4.action_set(action);
      pm.rule_set(3, pmrule_raw_v4);

      // Add a V6 single line raw match rule.
      eos::acl_rule_ip_t raw_v6;
      eos::parse_ip_addr("2001:db8:5678::", &dip);
      raw_v6.destination_addr_is(eos::ip_addr_mask_t(dip, 48));
      raw_v6.priority_value_is(129);
      raw_v6.priority_mask_is(255);
      auto pmrule_raw_v6 = eos::policy_map_rule_t();
      pmrule_raw_v6.raw_rule_is(raw_v6, eos::POLICY_RULE_TYPE_IPV6);
      action = eos::policy_map_action_t(eos::POLICY_ACTION_NEXTHOP_GROUP);
      action.nexthop_group_name_is("nexthopgroup2");
      pmrule_raw_v6.action_set(action);
      pm.rule_set(4, pmrule_raw_v6);

      // Commit the policy map
      get_policy_map_mgr()->policy_map_is(pm);

      // Finally, apply the policy map to the management interface to block access
      get_policy_map_mgr()->policy_map_apply(pmkey,
                                             eos::intf_id_t("Management0"),
                                             eos::ACL_IN,
                                             true);
   }

 private:
   eos::class_map_mgr * class_mgr;
};

int main(int argc, char ** argv) {
   eos::sdk sdk;
   policy_demo demo(sdk);

   printf("Starting PolicyDemo\n");
   sdk.main_loop(argc, argv);
}
<commit_msg>@3464246 patch fixes for BUG167603 and BUG167604 to our mainline branches<commit_after>// Copyright (c) 2014 Arista Networks, Inc.  All rights reserved.
// Arista Networks, Inc. Confidential and Proprietary.

#include <unordered_set>

#include <eos/agent.h>
#include <eos/acl.h>
#include <eos/intf.h>
#include <eos/class_map.h>
#include <eos/policy_map.h>
#include <eos/sdk.h>
#include <eos/system.h>
#include <eos/tracing.h>

#include <cstdio>

class policy_demo : public eos::agent_handler,
                    public eos::acl_handler,
                    public eos::policy_map_handler {
 public:
   eos::tracer t;
   explicit policy_demo(eos::sdk & sdk)
         : eos::agent_handler(sdk.get_agent_mgr()),
           eos::acl_handler(sdk.get_acl_mgr()),
           eos::policy_map_handler(sdk.get_policy_map_mgr()),
           t("PolicyDemo") {

      // Setup manager refs
      class_mgr = sdk.get_class_map_mgr();

      // Register for all ACL updates; when programming policies,
      // ACLs must be programmed before class maps before policy maps,
      // and they may fail independently of policy-map based PBR
      // programming. If ACL programming for ACLs used in class-maps
      // fails, the reported problem must be resolved before PBR
      // programming will complete.
      watch_all_acls(true);

   }

   ~policy_demo() {
   }

   void on_initialized() {
      printf("on_initialized - policy_demo starting\n");
      setup_policy();
   }

   // Configure PBR policymap pm1 with two class-maps and two single line raw
   // match rules.
   //
   // Service policy pm1
   //   Configured on: Management0
   //   Applied on:
   //   1: Class-map: cm1 (match-any)
   //     Match: 1 IP Access List acl1
   //         1 permit ip any 20.20.0.0/16 dscp 32
   //     Configured actions: drop
   //     Active routing action: No PBR action
   //   2: Class-map: cm2 (match-any)
   //     Match: 1 IPV6 Access List acl2
   //         1 permit ipv6 any 2001:db8:1234::/48 dscp 32
   //     Configured actions: drop
   //     Active routing action: No PBR action
   //   3: Single match statement
   //     Match:
   //         0 permit ip any 30.30.0.0/16 dscp 32
   //     Configured actions: set nexthop-group nexthopgroup2
   //     Active routing action: No PBR action
   //   4: Single match statement
   //     Match:
   //         0 permit ipv6 any 2001:db8:5678::/48 dscp 32
   //     Configured actions: set nexthop-group nexthopgroup2
   //     Active routing action: No PBR action

   void setup_policy() {
      eos::ip_addr_t dip;

      // Configure V4 ACL
      auto acl1 = eos::acl_key_t("acl1", eos::ACL_TYPE_IPV4);
      auto rule1 = eos::acl_rule_ip_t();
      rule1.action_is(eos::ACL_PERMIT);
      eos::parse_ip_addr("20.20.0.0", &dip);
      rule1.destination_addr_is(eos::ip_addr_mask_t(dip, 16));
      rule1.priority_value_is(32);
      rule1.match_ip_priority_is(true);
      get_acl_mgr()->acl_rule_set(acl1, 1, rule1);
      get_acl_mgr()->acl_commit();

      // Now build the class map for that ACL and commit it
      auto cmkey = eos::class_map_key_t("cm1", eos::POLICY_FEATURE_PBR);
      auto cm = eos::class_map_t(cmkey);
      cm.rule_set(1, eos::class_map_rule_t(acl1));
      cm.persistent_is(true);
      class_mgr->class_map_is(cm);
      t.trace0("class map cm input: %s", cm.to_string().c_str());
      auto cm_res = class_mgr->class_map(cmkey);
      t.trace0("class map cm outpt: %s", cm_res.to_string().c_str());

      // Build a policy map
      auto pmkey = eos::policy_map_key_t("pm1", eos::POLICY_FEATURE_PBR);
      auto pm = eos::policy_map_t(pmkey);

      // Add the policy map rule matching our class map and dropping the traffic
      auto pmrule4 = eos::policy_map_rule_t(cmkey);
      auto action = eos::policy_map_action_t(eos::POLICY_ACTION_DROP);
      pmrule4.action_set(action);
      pm.rule_set(1, pmrule4);

      // Configure V6 ACL
      auto acl2 = eos::acl_key_t("acl2", eos::ACL_TYPE_IPV6);
      auto rule2 = eos::acl_rule_ip_t();
      rule2.action_is(eos::ACL_PERMIT);
      eos::parse_ip_addr("2001:db8:1234::", &dip);
      rule2.destination_addr_is(eos::ip_addr_mask_t(dip, 48));
      rule2.priority_value_is(129);
      rule2.priority_mask_is(255);
      get_acl_mgr()->acl_rule_set(acl2, 1, rule2);
      get_acl_mgr()->acl_commit();

      // Now build the class map for that ACL and commit it
      auto cmkey2 = eos::class_map_key_t("cm2", eos::POLICY_FEATURE_PBR);
      auto cm2 = eos::class_map_t(cmkey2);
      cm2.rule_set(1, eos::class_map_rule_t(acl2));
      cm2.persistent_is(true);
      class_mgr->class_map_is(cm2);
      t.trace0("class map cm2 input: %s", cm2.to_string().c_str());
      auto cm2_res = class_mgr->class_map(cmkey2);
      t.trace0("class map cm2 outpt: %s", cm2_res.to_string().c_str());

      // Add the policy map rule matching our class map and dropping the traffic
      auto pmrule6 = eos::policy_map_rule_t(cmkey2);
      pmrule6.action_set(action);
      pm.rule_set(2, pmrule6);

      // Add a V4 single line raw match rule.
      eos::acl_rule_ip_t raw_v4;
      eos::parse_ip_addr("30.30.0.0", &dip);
      raw_v4.destination_addr_is(eos::ip_addr_mask_t(dip, 16));
      raw_v4.priority_value_is(32);
      raw_v4.match_ip_priority_is(true);
      auto pmrule_raw_v4 = eos::policy_map_rule_t();
      pmrule_raw_v4.raw_rule_is(raw_v4, eos::POLICY_RULE_TYPE_IPV4);
      action = eos::policy_map_action_t(eos::POLICY_ACTION_NEXTHOP_GROUP);
      action.nexthop_group_name_is("nexthopgroup2");
      pmrule_raw_v4.action_set(action);
      pm.rule_set(3, pmrule_raw_v4);

      // Add a V6 single line raw match rule.
      eos::acl_rule_ip_t raw_v6;
      eos::parse_ip_addr("2001:db8:5678::", &dip);
      raw_v6.destination_addr_is(eos::ip_addr_mask_t(dip, 48));
      raw_v6.priority_value_is(129);
      raw_v6.priority_mask_is(255);
      auto pmrule_raw_v6 = eos::policy_map_rule_t();
      pmrule_raw_v6.raw_rule_is(raw_v6, eos::POLICY_RULE_TYPE_IPV6);
      action = eos::policy_map_action_t(eos::POLICY_ACTION_NEXTHOP_GROUP);
      action.nexthop_group_name_is("nexthopgroup2");
      pmrule_raw_v6.action_set(action);
      pm.rule_set(4, pmrule_raw_v6);
      pm.persistent_is(true);

      // Commit the policy map
      get_policy_map_mgr()->policy_map_is(pm);

      // Finally, apply the policy map to the management interface to block access
      get_policy_map_mgr()->policy_map_apply(pmkey,
                                             eos::intf_id_t("Management0"),
                                             eos::ACL_IN,
                                             true);
   }

 private:
   eos::class_map_mgr * class_mgr;
};

int main(int argc, char ** argv) {
   eos::sdk sdk;
   policy_demo demo(sdk);

   printf("Starting PolicyDemo\n");
   sdk.main_loop(argc, argv);
}
<|endoftext|>


<commit_before>#include <stdio.h>
#include <ctype.h>
#include <metaScene.h>
#include <metaGroup.h>
#include <metaEllipse.h>

int testMetaScene(int , char * [])
{

  std::cout << "Creating test scene ..." << std::endl;
  MetaScene * s = new MetaScene(3);

  MetaEllipse * e1 = new MetaEllipse(3);
  e1->ID(0);
  e1->Radius(3);

  MetaEllipse * e2 = new MetaEllipse(3);
  e2->ID(1);
  e2->Radius(4);

  MetaGroup * g1 = new MetaGroup(3);
  g1->ID(2);

  e1->ParentID(2);
  e2->ParentID(2);

  s->AddObject(g1);
  s->AddObject(e1);
  s->AddObject(e2);

  std::cout << "...[ok]" << std::endl;

  std::cout << "Writing test file ..." << std::endl;

  s->Write("scene.scn");

  std::cout << "...[ok]" << std::endl;

  std::cout << "Clearing the scene..." << std::endl;
  s->Clear();
  std::cout << "...[ok]" << std::endl;

  std::cout << "Reading test file ..." << std::endl;

  s->Read("scene.scn");

  if(s->NObjects() != 3)
    {
    std::cout << "Number of obejcts: " << s->NObjects()
              << " != 3...[FAILED]" << std::endl;
    return 1;
    }

  std::cout << "...[ok]" << std::endl;

  s->Clear();

  std::cout << "Writing single object..." << std::endl;

  e1 = new MetaEllipse(3);
  e1->ID(0);
  e1->Radius(3);
  e1->Write("ellipse.elp");
  delete e1;

  std::cout << "[OK]" << std::endl;

  s->Clear();

  std::cout << "Reading test file ..." << std::endl;

  s->Read("ellipse.elp");

  if(s->NObjects() != 1)
    {
    std::cout << "Number of obejcts: " << s->NObjects()
              << " != 1...[FAILED]" << std::endl;
    delete s;
    return 1;
    }

  delete s;
  std::cout << "[OK]" << std::endl;
  return 0;
}
<commit_msg>ENH: Increasing coverage<commit_after>#include <stdio.h>
#include <ctype.h>
#include <metaScene.h>
#include <metaGroup.h>
#include <metaEllipse.h>

int testMetaScene(int , char * [])
{

  std::cout << "Creating test scene ..." << std::endl;
  MetaScene * s = new MetaScene(3);

  MetaEllipse * e1 = new MetaEllipse(3);
  e1->ID(0);
  e1->Radius(3);

  MetaEllipse * e2 = new MetaEllipse(3);
  e2->ID(1);
  e2->Radius(4);

  MetaGroup g0;
  MetaGroup * g1 = new MetaGroup(3);
  g1->ID(2);

  MetaGroup g2(g1);
  g2.PrintInfo();

  e1->ParentID(2);
  e2->ParentID(2);

  s->AddObject(g1);
  s->AddObject(e1);
  s->AddObject(e2);

  std::cout << "...[ok]" << std::endl;

  std::cout << "Writing test file ..." << std::endl;

  s->Write("scene.scn");

  std::cout << "...[ok]" << std::endl;

  std::cout << "Clearing the scene..." << std::endl;
  s->Clear();
  std::cout << "...[ok]" << std::endl;

  std::cout << "Reading test file ..." << std::endl;

  s->Read("scene.scn");

  if(s->NObjects() != 3)
    {
    std::cout << "Number of obejcts: " << s->NObjects()
              << " != 3...[FAILED]" << std::endl;
    return 1;
    }

  std::cout << "...[ok]" << std::endl;

  s->Clear();

  std::cout << "Writing single object..." << std::endl;

  e1 = new MetaEllipse(3);
  e1->ID(0);
  e1->Radius(3);
  e1->Write("ellipse.elp");
  delete e1;

  std::cout << "[OK]" << std::endl;

  s->Clear();

  std::cout << "Reading test file ..." << std::endl;

  s->Read("ellipse.elp");

  if(s->NObjects() != 1)
    {
    std::cout << "Number of obejcts: " << s->NObjects()
              << " != 1...[FAILED]" << std::endl;
    delete s;
    return 1;
    }

  delete s;
  std::cout << "[OK]" << std::endl;
  return 0;
}
<|endoftext|>


<commit_before>#pragma once
#include <cstddef>
#include <cstdint>
#include "types.hpp"
//基本方針：packできない時は変更を加えない
/**
\~japanese	@brief Stoneを省メモリに格納するクラスです
\~english	@brief Class for store Stone
\~japanese	@detail 格納できる要素数は32個です。64bitを2bitずつ使用します。この構造の実現のためにbit演算を多用します。
\~english	@detail The capacity of this class is 32(2 bit / elem, total 64bit).
\~
xx xx xx xx ... xx xx xx xx
MSB <---           ---> LSB : 64bit
front <-           --> back : 32 elem

ex.)
PackedStone{ Stone::Black, Stone::Black, Stone::White, Stone::None }
=> 00 00 ... 00 01 01 10 00
*/
class PackedStone
{
public:
	typedef std::size_t size_type;
	typedef std::uint64_t hold_type;
	typedef Stone value_type;
	/**
	\~japanese	@brief 一要素あたりの消費bit数
	\~english	@brief number of bit-consumption per 1 element.
	*/
	static constexpr std::uint8_t bit = 2;
private:
	/**
	\~japanese	@brief データ
	\~english	@brief data
	*/
	hold_type value_;
	/**
	\~japanese	@brief 要素数
	\~english	@brief Element count
	*/
	size_type size_;
public:
	/**
	\~japanese	@brief 容量
	\~english	@brief capacity
	*/
	static constexpr size_type cap = sizeof(hold_type) * CHAR_BIT / bit;
	constexpr PackedStone() noexcept : value_(), size_() {}
	/**
	\~japanese	@brief Stone型を1つ格納します
	\~english	@brief holds a single Stone object
	*/
	constexpr PackedStone(Stone s) noexcept : value_(s), size_(1) {}
	/**
	\~japanese	@brief Stone型を2つ格納します
	\~english	@brief holds two Stone object
	*/
	constexpr PackedStone(Stone s1, Stone s2) noexcept : value_((static_cast<hold_type>(s1) << bit) + s2), size_(2) {}

	constexpr PackedStone(const PackedStone& o) noexcept : value_(o.value_), size_(o.size_) {}
	constexpr PackedStone(PackedStone&& o) noexcept : value_(o.value_), size_(o.size_) {}
	PackedStone& operator=(const PackedStone& o) noexcept {
		this->value_ = o.value_;
		this->size_  = o.size_;
		return *this;
	}
	PackedStone& operator=(PackedStone&& o) noexcept {
		this->value_ = o.value_;
		this->size_ = o.size_;
		return *this;
	}
	/**
	\~japanese	@brief 第一引数のPackedStoneの後ろに新たにStoneを追加して格納します。格納できない場合は第一引数のPackedStoneをそのまま格納します
	\~english	@brief Store first argument and push back second argument. When it is failed, store first argument.
	*/
	constexpr PackedStone(const PackedStone& o, const Stone s) noexcept
		: value_((!o.is_packable()) ? o.value_ : (o.value_ << bit) | static_cast<hold_type>(s)), size_((!o.is_packable()) ? o.size_ : o.size_ + 1) {}
	/**
	\~japanese	@brief 第一引数のPackedStoneの前に新たにStoneを追加して格納します。格納できない場合は第一引数のStoneをそのまま格納します
	\~english	@brief Store first argument and push front second argument. When it is failed, store first argument.
	*/
	constexpr PackedStone(const Stone s, const PackedStone& o) noexcept
		: value_((!o.is_packable()) ? s : (static_cast<hold_type>(s) << (o.size_ * bit)) | o.value_), size_((!o.is_packable()) ? 1 : o.size_ + 1) {}
	/**
	\~japanese	@brief 容量を取得します。
	\~english	@brief Get capacity
	*/
	constexpr size_type capacity() const noexcept { return cap; }
	/**
	\~japanese	@brief 現在の大きさを取得します。
	\~english	@brief Get current size
	*/
	constexpr size_type size() const noexcept { return size_; }
	/**
	\~japanese	@brief 内部データを直接取り出します。
	\~english	@brief Get raw data
	*/
	constexpr hold_type data() const noexcept { return value_; }
	/**
	\~japanese	@brief Stoneをさらに格納できるか調べます
	\~english	@brief Check
	*/
	constexpr bool is_packable() const noexcept { return (size_ < cap); }
private:
	/**
	\~japanese	@brief 要素だけをand演算で取り出すためのmask
	\~english	@brief a mask for and operation to get element
	*/
	static constexpr hold_type mask = 0b11;
	/**
	\~japanese	@brief 要素bitを先頭に移動させるための左シフトの数を計算する
	\~english	@brief calc how many bit is needed to shift elem-bit to front-elem-bits
	*/
	constexpr std::uint8_t lshift_num_to_get_front() const noexcept { return static_cast<std::uint8_t>(this->size_ - 1); };
public:
	/**
	\~japanese	@brief Getter: 先頭要素を取得する
	\~english	@brief Getter: Get first elem
	*/
	constexpr Stone front() const noexcept {
		return static_cast<Stone>(this->value_ >> lshift_num_to_get_front());
	}
	/**
	\~japanese	@brief Setter: 先頭要素に書き込む
	\~english	@brief Setter: Set first elem
	\~japanese	@return 変更されたPackedStoneクラス
	\~english	@return modified PackedStone class.
	*/
	constexpr PackedStone front(Stone s) const noexcept {
		//                      ************* bit mask *************
		return{ (this->value_ & ~(mask << lshift_num_to_get_front())) | (static_cast<hold_type>(s) << lshift_num_to_get_front()), this->size_ };
	}
	/**
	\~japanese	@brief Getter: 末尾要素を取得する
	\~english	@brief Getter: Get last elem
	*/
	constexpr Stone back() const noexcept {
		return static_cast<Stone>(this->value_ & mask);
	}
	/**
	\~japanese	@brief Setter: 末尾要素に書き込む
	\~english	@brief Setter: Set last elem
	\~japanese	@return 変更されたPackedStoneクラス
	\~english	@return modified PackedStone class.
	*/
	constexpr PackedStone back(Stone s) const noexcept {
		return{ (this->value_ & ~mask) | s, this->size_ };
	}
	/**
	\~japanese	@brief 第一引数のPackedStoneの前に新たにStoneを追加して返却します。格納できない場合は第一引数のStoneをそのまま格納します
	\~english	@brief push front second argument and return. When it is failed, return first argument.
	*/
	constexpr PackedStone push_front(Stone s) const noexcept { return{ s, *this }; }
	/**
	\~japanese	@brief 第一引数のPackedStoneの後ろに新たにStoneを追加して返却します。格納できない場合は第一引数のPackedStoneをそのまま格納します
	\~english	@brief push back second argument and return. When it is failed, return first argument.
	*/
	constexpr PackedStone push_back(Stone s) const noexcept { return{ *this, s }; }
	/**
	\~japanese	@brief 先頭要素を削除したものを返却します
	\~english	@brief return this object which first element is removed
	*/
	constexpr PackedStone pop_front() const noexcept {
		return (this->size_) ? PackedStone{ this->value_ & (mask << lshift_num_to_get_front()), this->size_ - 1 } : *this;
	}
	/**
	\~japanese	@brief 末尾要素を削除したものを返却します
	\~english	@brief return this object which last element is removed
	*/
	constexpr PackedStone pop_back() const noexcept { return (this->size_) ? PackedStone{ this->value_ >> bit, this->size_ - 1 } : *this; }
private:
	constexpr PackedStone(hold_type n, size_type s) noexcept : value_(n), size_(s) {}
	/**
	\~japanese	@brief 左シフトビット演算子
	\~english	@brief left shift bitwise operator
	*/
	constexpr PackedStone operator<<(size_type n) const noexcept { return (is_packable()) ? PackedStone{ value_ << (bit * n), size_ } : *this; }
public:
	/**
	\~japanese	@brief 左シフトビット演算子
	\~english	@brief left shift bitwise operator
	*/
	constexpr PackedStone operator<<(std::uint8_t n) const noexcept { return *this << static_cast<size_type>(n); }
	/**
	\~japanese	@brief 第一引数のPackedStoneの後ろに新たにPackedStoneを追加して返却します。格納できない場合は第一引数のPackedStoneをそのまま格納します
	\~english	@brief push back second argument and return. When it is failed, return first argument.
	*/
	constexpr PackedStone operator|(PackedStone r) const noexcept {
		return (cap < this->size_ + r.size_) ? *this : PackedStone{(*this << r.size()).value_ + r.value_, this->size_ + r.size_};
	}
	/**
	\~japanese	@brief 第一引数のPackedStoneの後ろに新たにStoneを追加して返却します。格納できない場合は第一引数のPackedStoneをそのまま格納します
	\~english	@brief push back second argument and return. When it is failed, return first argument.
	*/
	constexpr PackedStone operator|(Stone r) const noexcept {
		return{ *this, r };
	}
private:
	static constexpr PackedStone pack_n(const PackedStone tmp, const Stone s, const size_type rest_count) noexcept {
		return (0 == rest_count) ? PackedStone{} : (rest_count - 1) ? pack_n(tmp | s, s, rest_count - 1) : tmp | s;
	}
	static constexpr PackedStone pack_n(const Stone s, const size_t rest_count) noexcept {
		return (0 == rest_count) ? PackedStone{} : (rest_count - 1) ? pack_n(s, s, rest_count - 1) : s;
	}
public:
	constexpr PackedStone(size_type n, const Stone val) : PackedStone(pack_n(val, n)) {}
	constexpr PackedStone assign(size_type n, const Stone val) const noexcept {
		return pack_n(val, n);
	}
};
/**
@relates PackedStone
\~japanese	@brief	二項演算子==のオーバーロード。厳密な比較が行われます
\~english	@brief	Overload of binary operator ==. This operator compares strict difference
*/
constexpr bool operator==(PackedStone l, PackedStone r) noexcept {
	return l.size() == r.size() && l.data() == r.data();
}
/**
@relates PackedStone
\~japanese	@brief	二項演算子!=のオーバーロード。厳密な比較が行われます
\~english	@brief	Overload of binary operator !=. This operator compares strict difference
*/
constexpr bool operator!=(PackedStone l, PackedStone r) noexcept {
	return !(l == r);
}
/**
@relates PackedStone
\~japanese	@brief Stone型を2つ格納します
\~english	@brief holds two Stone object
*/
constexpr PackedStone operator|(Stone l, Stone r) noexcept { return{ l, r }; }
/**
@relates PackedStone
\~japanese	@brief 第一引数のPackedStoneの前に新たにStoneを追加して格納します。格納できない場合は第一引数のStoneをそのまま格納します
\~english	@brief Store first argument and push front second argument. When it is failed, store first argument.
*/
constexpr PackedStone operator|(Stone l, PackedStone r) noexcept { return{ l, r }; }
namespace detail {
	struct PackPattern_n_operator_helper {
		struct Impl {
			size_t n;
		};
		Impl p;
		constexpr Impl operator*() const {
			return p;
		}
	};
	constexpr PackedStone operator*(const Stone s, PackPattern_n_operator_helper::Impl n) {
		return { n.n, s };
	}
}
constexpr detail::PackPattern_n_operator_helper operator "" _pack(unsigned long long n) { return{ { static_cast<size_t>((n < PackedStone::cap) ? n : 0) } }; }

typedef array<array<PackedStone, 5>, 2> Pattern;

<commit_msg>PackedStone::front(), PackedStone::front(Stone), PackedStone::pop_front()が正常に動作しなかった問題を修正<commit_after>#pragma once
#include <cstddef>
#include <cstdint>
#include "types.hpp"
//基本方針：packできない時は変更を加えない
/**
\~japanese	@brief Stoneを省メモリに格納するクラスです
\~english	@brief Class for store Stone
\~japanese	@detail 格納できる要素数は32個です。64bitを2bitずつ使用します。この構造の実現のためにbit演算を多用します。
\~english	@detail The capacity of this class is 32(2 bit / elem, total 64bit).
\~
xx xx xx xx ... xx xx xx xx
MSB <---           ---> LSB : 64bit
front <-           --> back : 32 elem

ex.)
PackedStone{ Stone::Black, Stone::Black, Stone::White, Stone::None }
=> 00 00 ... 00 01 01 10 00
*/
class PackedStone
{
public:
	typedef std::size_t size_type;
	typedef std::uint64_t hold_type;
	typedef Stone value_type;
	/**
	\~japanese	@brief 一要素あたりの消費bit数
	\~english	@brief number of bit-consumption per 1 element.
	*/
	static constexpr std::uint8_t bit = 2;
private:
	/**
	\~japanese	@brief データ
	\~english	@brief data
	*/
	hold_type value_;
	/**
	\~japanese	@brief 要素数
	\~english	@brief Element count
	*/
	size_type size_;
public:
	/**
	\~japanese	@brief 容量
	\~english	@brief capacity
	*/
	static constexpr size_type cap = sizeof(hold_type) * CHAR_BIT / bit;
	constexpr PackedStone() noexcept : value_(), size_() {}
	/**
	\~japanese	@brief Stone型を1つ格納します
	\~english	@brief holds a single Stone object
	*/
	constexpr PackedStone(Stone s) noexcept : value_(s), size_(1) {}
	/**
	\~japanese	@brief Stone型を2つ格納します
	\~english	@brief holds two Stone object
	*/
	constexpr PackedStone(Stone s1, Stone s2) noexcept : value_((static_cast<hold_type>(s1) << bit) + s2), size_(2) {}

	constexpr PackedStone(const PackedStone& o) noexcept : value_(o.value_), size_(o.size_) {}
	constexpr PackedStone(PackedStone&& o) noexcept : value_(o.value_), size_(o.size_) {}
	PackedStone& operator=(const PackedStone& o) noexcept {
		this->value_ = o.value_;
		this->size_  = o.size_;
		return *this;
	}
	PackedStone& operator=(PackedStone&& o) noexcept {
		this->value_ = o.value_;
		this->size_ = o.size_;
		return *this;
	}
	/**
	\~japanese	@brief 第一引数のPackedStoneの後ろに新たにStoneを追加して格納します。格納できない場合は第一引数のPackedStoneをそのまま格納します
	\~english	@brief Store first argument and push back second argument. When it is failed, store first argument.
	*/
	constexpr PackedStone(const PackedStone& o, const Stone s) noexcept
		: value_((!o.is_packable()) ? o.value_ : (o.value_ << bit) | static_cast<hold_type>(s)), size_((!o.is_packable()) ? o.size_ : o.size_ + 1) {}
	/**
	\~japanese	@brief 第一引数のPackedStoneの前に新たにStoneを追加して格納します。格納できない場合は第一引数のStoneをそのまま格納します
	\~english	@brief Store first argument and push front second argument. When it is failed, store first argument.
	*/
	constexpr PackedStone(const Stone s, const PackedStone& o) noexcept
		: value_((!o.is_packable()) ? s : (static_cast<hold_type>(s) << (o.size_ * bit)) | o.value_), size_((!o.is_packable()) ? 1 : o.size_ + 1) {}
	/**
	\~japanese	@brief 容量を取得します。
	\~english	@brief Get capacity
	*/
	constexpr size_type capacity() const noexcept { return cap; }
	/**
	\~japanese	@brief 現在の大きさを取得します。
	\~english	@brief Get current size
	*/
	constexpr size_type size() const noexcept { return size_; }
	/**
	\~japanese	@brief 内部データを直接取り出します。
	\~english	@brief Get raw data
	*/
	constexpr hold_type data() const noexcept { return value_; }
	/**
	\~japanese	@brief Stoneをさらに格納できるか調べます
	\~english	@brief Check
	*/
	constexpr bool is_packable() const noexcept { return (size_ < cap); }
private:
	/**
	\~japanese	@brief 要素だけをand演算で取り出すためのmask
	\~english	@brief a mask for and operation to get element
	*/
	static constexpr hold_type mask = 0b11;
	/**
	\~japanese	@brief 要素bitを先頭に移動させるための左シフトの数を計算する
	\~english	@brief calc how many bit is needed to shift elem-bit to front-elem-bits
	*/
	constexpr std::uint8_t lshift_num_to_get_front() const noexcept { return static_cast<std::uint8_t>(this->size_ - 1) * 2; };
public:
	/**
	\~japanese	@brief Getter: 先頭要素を取得する
	\~english	@brief Getter: Get first elem
	*/
	constexpr Stone front() const noexcept {
		return static_cast<Stone>(this->value_ >> lshift_num_to_get_front());
	}
	/**
	\~japanese	@brief Setter: 先頭要素に書き込む
	\~english	@brief Setter: Set first elem
	\~japanese	@return 変更されたPackedStoneクラス
	\~english	@return modified PackedStone class.
	*/
	constexpr PackedStone front(Stone s) const noexcept {
		//                      ************* bit mask *************
		return{ (this->value_ & ~(mask << lshift_num_to_get_front())) | (static_cast<hold_type>(s) << lshift_num_to_get_front()), this->size_ };
	}
	/**
	\~japanese	@brief Getter: 末尾要素を取得する
	\~english	@brief Getter: Get last elem
	*/
	constexpr Stone back() const noexcept {
		return static_cast<Stone>(this->value_ & mask);
	}
	/**
	\~japanese	@brief Setter: 末尾要素に書き込む
	\~english	@brief Setter: Set last elem
	\~japanese	@return 変更されたPackedStoneクラス
	\~english	@return modified PackedStone class.
	*/
	constexpr PackedStone back(Stone s) const noexcept {
		return{ (this->value_ & ~mask) | s, this->size_ };
	}
	/**
	\~japanese	@brief 第一引数のPackedStoneの前に新たにStoneを追加して返却します。格納できない場合は第一引数のStoneをそのまま格納します
	\~english	@brief push front second argument and return. When it is failed, return first argument.
	*/
	constexpr PackedStone push_front(Stone s) const noexcept { return{ s, *this }; }
	/**
	\~japanese	@brief 第一引数のPackedStoneの後ろに新たにStoneを追加して返却します。格納できない場合は第一引数のPackedStoneをそのまま格納します
	\~english	@brief push back second argument and return. When it is failed, return first argument.
	*/
	constexpr PackedStone push_back(Stone s) const noexcept { return{ *this, s }; }
	/**
	\~japanese	@brief 先頭要素を削除したものを返却します
	\~english	@brief return this object which first element is removed
	*/
	constexpr PackedStone pop_front() const noexcept {
		return (this->size_) ? PackedStone{ this->value_ & (mask << lshift_num_to_get_front()), this->size_ - 1 } : *this;
	}
	/**
	\~japanese	@brief 末尾要素を削除したものを返却します
	\~english	@brief return this object which last element is removed
	*/
	constexpr PackedStone pop_back() const noexcept { return (this->size_) ? PackedStone{ this->value_ >> bit, this->size_ - 1 } : *this; }
private:
	constexpr PackedStone(hold_type n, size_type s) noexcept : value_(n), size_(s) {}
	/**
	\~japanese	@brief 左シフトビット演算子
	\~english	@brief left shift bitwise operator
	*/
	constexpr PackedStone operator<<(size_type n) const noexcept { return (is_packable()) ? PackedStone{ value_ << (bit * n), size_ } : *this; }
public:
	/**
	\~japanese	@brief 左シフトビット演算子
	\~english	@brief left shift bitwise operator
	*/
	constexpr PackedStone operator<<(std::uint8_t n) const noexcept { return *this << static_cast<size_type>(n); }
	/**
	\~japanese	@brief 第一引数のPackedStoneの後ろに新たにPackedStoneを追加して返却します。格納できない場合は第一引数のPackedStoneをそのまま格納します
	\~english	@brief push back second argument and return. When it is failed, return first argument.
	*/
	constexpr PackedStone operator|(PackedStone r) const noexcept {
		return (cap < this->size_ + r.size_) ? *this : PackedStone{(*this << r.size()).value_ + r.value_, this->size_ + r.size_};
	}
	/**
	\~japanese	@brief 第一引数のPackedStoneの後ろに新たにStoneを追加して返却します。格納できない場合は第一引数のPackedStoneをそのまま格納します
	\~english	@brief push back second argument and return. When it is failed, return first argument.
	*/
	constexpr PackedStone operator|(Stone r) const noexcept {
		return{ *this, r };
	}
private:
	static constexpr PackedStone pack_n(const PackedStone tmp, const Stone s, const size_type rest_count) noexcept {
		return (0 == rest_count) ? PackedStone{} : (rest_count - 1) ? pack_n(tmp | s, s, rest_count - 1) : tmp | s;
	}
	static constexpr PackedStone pack_n(const Stone s, const size_t rest_count) noexcept {
		return (0 == rest_count) ? PackedStone{} : (rest_count - 1) ? pack_n(s, s, rest_count - 1) : s;
	}
public:
	constexpr PackedStone(size_type n, const Stone val) : PackedStone(pack_n(val, n)) {}
	constexpr PackedStone assign(size_type n, const Stone val) const noexcept {
		return pack_n(val, n);
	}
};
/**
@relates PackedStone
\~japanese	@brief	二項演算子==のオーバーロード。厳密な比較が行われます
\~english	@brief	Overload of binary operator ==. This operator compares strict difference
*/
constexpr bool operator==(PackedStone l, PackedStone r) noexcept {
	return l.size() == r.size() && l.data() == r.data();
}
/**
@relates PackedStone
\~japanese	@brief	二項演算子!=のオーバーロード。厳密な比較が行われます
\~english	@brief	Overload of binary operator !=. This operator compares strict difference
*/
constexpr bool operator!=(PackedStone l, PackedStone r) noexcept {
	return !(l == r);
}
/**
@relates PackedStone
\~japanese	@brief Stone型を2つ格納します
\~english	@brief holds two Stone object
*/
constexpr PackedStone operator|(Stone l, Stone r) noexcept { return{ l, r }; }
/**
@relates PackedStone
\~japanese	@brief 第一引数のPackedStoneの前に新たにStoneを追加して格納します。格納できない場合は第一引数のStoneをそのまま格納します
\~english	@brief Store first argument and push front second argument. When it is failed, store first argument.
*/
constexpr PackedStone operator|(Stone l, PackedStone r) noexcept { return{ l, r }; }
namespace detail {
	struct PackPattern_n_operator_helper {
		struct Impl {
			size_t n;
		};
		Impl p;
		constexpr Impl operator*() const {
			return p;
		}
	};
	constexpr PackedStone operator*(const Stone s, PackPattern_n_operator_helper::Impl n) {
		return { n.n, s };
	}
}
constexpr detail::PackPattern_n_operator_helper operator "" _pack(unsigned long long n) { return{ { static_cast<size_t>((n < PackedStone::cap) ? n : 0) } }; }

typedef array<array<PackedStone, 5>, 2> Pattern;

<|endoftext|>


<commit_before>/*
 * Motors_Controller.cpp
 *
 *  Created on: 18. 7. 2017
 *      Author: michp
 */

#include <Motors_Controller.h>

namespace flyhero {

Motors_Controller& Motors_Controller::Instance() {
	static Motors_Controller instance;

	return instance;
}

Motors_Controller::Motors_Controller() {
	this->motor_FR = 940;
	this->motor_FL = 940;
	this->motor_BR = 940;
	this->motor_BL = 940;

	this->roll_PID.Set_I_Max(50);
	this->pitch_PID.Set_I_Max(50);
	this->yaw_PID.Set_I_Max(50);

	this->invert_yaw = false;
	this->throttle = 1000;
}

void Motors_Controller::Set_PID_Constants(Axis axis, float Kp, float Ki, float Kd) {
	switch (axis) {
	case Roll:
		this->roll_PID.Set_Kp(Kp);
		this->roll_PID.Set_Ki(Ki);
		this->roll_PID.Set_Kd(Kd);
		break;
	case Pitch:
		this->pitch_PID.Set_Kp(Kp);
		this->pitch_PID.Set_Ki(Ki);
		this->pitch_PID.Set_Kd(Kd);
		break;
	case Yaw:
		this->yaw_PID.Set_Kp(Kp);
		this->yaw_PID.Set_Ki(Ki);
		this->yaw_PID.Set_Kd(Kd);
		break;
	}
}

void Motors_Controller::Set_Throttle(uint16_t throttle) {
	this->throttle = throttle;
}

void Motors_Controller::Set_Invert_Yaw(bool invert) {
	this->invert_yaw = invert;
}

void Motors_Controller::Update_Motors() {
	PWM_Generator& PWM_generator = PWM_Generator::Instance();

	if (this->throttle >= 1050) {
		float pitch_correction, roll_correction, yaw_correction;
		MPU6050::Sensor_Data euler_data;

		MPU6050::Instance().Get_Euler(euler_data.x, euler_data.y, euler_data.z);

		roll_correction = this->roll_PID.Get_PID(0 - euler_data.x);
		pitch_correction = this->pitch_PID.Get_PID(0 - euler_data.y);
		yaw_correction = this->yaw_PID.Get_PID(0 - euler_data.z);

		// not sure about yaw signs
		if (!this->invert_yaw) {
			this->motor_FL = throttle - roll_correction - yaw_correction; // PB2
			this->motor_BL = throttle + pitch_correction + yaw_correction; // PA15
			this->motor_FR = throttle - pitch_correction + yaw_correction; // PB10
			this->motor_BR = throttle + roll_correction - yaw_correction; // PA1
		}
		else {
			this->motor_FL = throttle - roll_correction + yaw_correction; // PB2
			this->motor_BL = throttle + pitch_correction - yaw_correction; // PA15
			this->motor_FR = throttle - pitch_correction - yaw_correction; // PB10
			this->motor_BR = throttle + roll_correction + yaw_correction; // PA1
		}

		if (this->motor_FL > 2000)
			this->motor_FL = 2000;
		else if (this->motor_FL < 1050)
			this->motor_FL = 940;

		if (this->motor_BL > 2000)
			this->motor_BL = 2000;
		else if (this->motor_BL < 1050)
			this->motor_BL = 940;

		if (this->motor_FR > 2000)
			this->motor_FR = 2000;
		else if (this->motor_FR < 1050)
			this->motor_FR = 940;

		if (this->motor_BR > 2000)
			this->motor_BR = 2000;
		else if (this->motor_BR < 1050)
			this->motor_BR = 940;

		PWM_generator.SetPulse(this->motor_FL, 3);
		PWM_generator.SetPulse(this->motor_BL, 2);
		PWM_generator.SetPulse(this->motor_FR, 4);
		PWM_generator.SetPulse(this->motor_BR, 1);
	}
	else {
		MPU6050::Instance().Reset_Integrators();

		PWM_generator.SetPulse(940, 1);
		PWM_generator.SetPulse(940, 2);
		PWM_generator.SetPulse(940, 3);
		PWM_generator.SetPulse(940, 4);
	}
}

uint16_t Motors_Controller::Get_Throttle() {
	return this->throttle;
}

uint16_t Motors_Controller::Get_Motor_FL() {
	return this->motor_FL;
}

uint16_t Motors_Controller::Get_Motor_FR() {
	return this->motor_FR;
}

uint16_t Motors_Controller::Get_Motor_BL() {
	return this->motor_BL;
}

uint16_t Motors_Controller::Get_Motor_BR() {
	return this->motor_BR;
}

} /* namespace flyhero */
<commit_msg>Undo 0c18011: PID correction formulas for motors<commit_after>/*
 * Motors_Controller.cpp
 *
 *  Created on: 18. 7. 2017
 *      Author: michp
 */

#include <Motors_Controller.h>

namespace flyhero {

Motors_Controller& Motors_Controller::Instance() {
	static Motors_Controller instance;

	return instance;
}

Motors_Controller::Motors_Controller() {
	this->motor_FR = 940;
	this->motor_FL = 940;
	this->motor_BR = 940;
	this->motor_BL = 940;

	this->roll_PID.Set_I_Max(50);
	this->pitch_PID.Set_I_Max(50);
	this->yaw_PID.Set_I_Max(50);

	this->invert_yaw = false;
	this->throttle = 1000;
}

void Motors_Controller::Set_PID_Constants(Axis axis, float Kp, float Ki, float Kd) {
	switch (axis) {
	case Roll:
		this->roll_PID.Set_Kp(Kp);
		this->roll_PID.Set_Ki(Ki);
		this->roll_PID.Set_Kd(Kd);
		break;
	case Pitch:
		this->pitch_PID.Set_Kp(Kp);
		this->pitch_PID.Set_Ki(Ki);
		this->pitch_PID.Set_Kd(Kd);
		break;
	case Yaw:
		this->yaw_PID.Set_Kp(Kp);
		this->yaw_PID.Set_Ki(Ki);
		this->yaw_PID.Set_Kd(Kd);
		break;
	}
}

void Motors_Controller::Set_Throttle(uint16_t throttle) {
	this->throttle = throttle;
}

void Motors_Controller::Set_Invert_Yaw(bool invert) {
	this->invert_yaw = invert;
}

void Motors_Controller::Update_Motors() {
	PWM_Generator& PWM_generator = PWM_Generator::Instance();

	if (this->throttle >= 1050) {
		float pitch_correction, roll_correction, yaw_correction;
		MPU6050::Sensor_Data euler_data;

		MPU6050::Instance().Get_Euler(euler_data.x, euler_data.y, euler_data.z);

		roll_correction = this->roll_PID.Get_PID(0 - euler_data.x);
		pitch_correction = this->pitch_PID.Get_PID(0 - euler_data.y);
		yaw_correction = this->yaw_PID.Get_PID(0 - euler_data.z);

		// not sure about yaw signs
		if (!this->invert_yaw) {
			this->motor_FL = throttle - roll_correction - pitch_correction - yaw_correction; // PB2
			this->motor_BL = throttle - roll_correction + pitch_correction + yaw_correction; // PA15
			this->motor_FR = throttle + roll_correction - pitch_correction + yaw_correction; // PB10
			this->motor_BR = throttle + roll_correction + pitch_correction - yaw_correction; // PA1
		}
		else {
			this->motor_FL = throttle - roll_correction - pitch_correction + yaw_correction; // PB2
			this->motor_BL = throttle - roll_correction + pitch_correction - yaw_correction; // PA15
			this->motor_FR = throttle + roll_correction - pitch_correction - yaw_correction; // PB10
			this->motor_BR = throttle + roll_correction + pitch_correction + yaw_correction; // PA1
		}

		if (this->motor_FL > 2000)
			this->motor_FL = 2000;
		else if (this->motor_FL < 1050)
			this->motor_FL = 940;

		if (this->motor_BL > 2000)
			this->motor_BL = 2000;
		else if (this->motor_BL < 1050)
			this->motor_BL = 940;

		if (this->motor_FR > 2000)
			this->motor_FR = 2000;
		else if (this->motor_FR < 1050)
			this->motor_FR = 940;

		if (this->motor_BR > 2000)
			this->motor_BR = 2000;
		else if (this->motor_BR < 1050)
			this->motor_BR = 940;

		PWM_generator.SetPulse(this->motor_FL, 3);
		PWM_generator.SetPulse(this->motor_BL, 2);
		PWM_generator.SetPulse(this->motor_FR, 4);
		PWM_generator.SetPulse(this->motor_BR, 1);
	}
	else {
		MPU6050::Instance().Reset_Integrators();

		PWM_generator.SetPulse(940, 1);
		PWM_generator.SetPulse(940, 2);
		PWM_generator.SetPulse(940, 3);
		PWM_generator.SetPulse(940, 4);
	}
}

uint16_t Motors_Controller::Get_Throttle() {
	return this->throttle;
}

uint16_t Motors_Controller::Get_Motor_FL() {
	return this->motor_FL;
}

uint16_t Motors_Controller::Get_Motor_FR() {
	return this->motor_FR;
}

uint16_t Motors_Controller::Get_Motor_BL() {
	return this->motor_BL;
}

uint16_t Motors_Controller::Get_Motor_BR() {
	return this->motor_BR;
}

} /* namespace flyhero */
<|endoftext|>


<commit_before>#include <array>
#include <chrono>
#include <cstdio>
#include <iostream>
#include <boost/math/constants/constants.hpp>
#include "bicycle.h"
#include "parameters.h"

#include "flatbuffers/flatbuffers.h"
#include "sample_log_generated.h"
#include "sample_util.h"

namespace {
    const double fs = 200; // sample rate [Hz]
    const double dt = 1.0/fs; // sample time [s]
    const double v0 = 4.0; // forward speed [m/s]
    const size_t N = 1000; // length of simulation in samples

    std::array<model::Bicycle::state_t, N> system_state;
    flatbuffers::FlatBufferBuilder builder;
    flatbuffers::FlatBufferBuilder log_builder;
    flatbuffers::Offset<fbs::SampleBuffer> sample_locations[N + 1];
} // namespace

flatbuffers::Offset<fbs::Bicycle> create_bicycle(flatbuffers::FlatBufferBuilder& fbb, const model::Bicycle& bicycle) {
    auto M = fbs::second_order_matrix(bicycle.M());
    auto C1 = fbs::second_order_matrix(bicycle.C1());
    auto K0 = fbs::second_order_matrix(bicycle.K0());
    auto K2 = fbs::second_order_matrix(bicycle.K2());
    return fbs::CreateBicycle(fbb, bicycle.v(), bicycle.dt(), &M, &C1, &K0, &K2);
}

int main(int argc, char* argv[]) {
    (void)argc;
    (void)argv;

    model::Bicycle bicycle(parameters::benchmark::M, parameters::benchmark::C1,
            parameters::benchmark::K0, parameters::benchmark::K2, v0, dt);

    model::Bicycle::state_t x; // roll rate, steer rate, roll angle, steer angle
    x << 0, 10, 10, 0; // define x0 in degrees
    x *= boost::math::constants::degree<double>(); // convert to radians
    std::cout << "initial state: [" << x.transpose() << "]' rad" << std::endl;
    std::cout << "states are: [roll angle, steer angle, roll rate, steer rate]'" << std::endl << std::endl;

    // flatbuffer objects must be serialized in depth first pre-order traversal
    size_t current_sample = 0;

    std::cout << "simulating discrete time system at constant speed (" <<
        N << " steps at " << fs << " Hz) ..." << std::endl;
    auto disc_start = std::chrono::system_clock::now();
    for (auto& state: system_state) {
        x = bicycle.x_next(x);
        state = x;

        builder.Clear();
        fbs::SampleBuilder sample_builder(builder);
        if (current_sample == 0) {
            auto bicycle_location = create_bicycle(builder, bicycle);
            sample_builder.add_bicycle(bicycle_location);
        }
        auto fbs_state = fbs::state(x);
        sample_builder.add_state(&fbs_state);
        sample_builder.add_timestamp(current_sample);
        auto location = sample_builder.Finish();
        builder.Finish(location);
        // sample is serialized

        unsigned char* p = nullptr;
        auto data = log_builder.CreateUninitializedVector<unsigned char>(builder.GetSize(), &p);
        std::memcpy(p, builder.GetBufferPointer(), builder.GetSize());

        fbs::SampleBufferBuilder log_sample_builder(log_builder);
        log_sample_builder.add_data(data);
        sample_locations[current_sample++] = log_sample_builder.Finish();
    }
    auto disc_stop = std::chrono::system_clock::now();
    auto disc_time = disc_stop - disc_start;

    std::cout << "final state: " << system_state.back().transpose() << std::endl;
    std::cout << "simulation duration: " <<
        std::chrono::duration_cast<std::chrono::microseconds>(disc_time).count() <<
        " us" << std::endl;

    auto samples_vector = log_builder.CreateVector(sample_locations, N);
    auto log_location = fbs::CreateSampleLog(log_builder, samples_vector);
    log_builder.Finish(log_location);

    {
        disc_start = std::chrono::system_clock::now();
        auto f = std::fopen("samples.bin", "wb");
        std::fwrite(log_builder.GetBufferPointer(), sizeof(char), log_builder.GetSize(), f);
        std::fclose(f);
        disc_stop = std::chrono::system_clock::now();
        disc_time = disc_stop - disc_start;
        std::cout << "write to file took: " <<
            std::chrono::duration_cast<std::chrono::microseconds>(disc_time).count() <<
            " us" << std::endl;
    }

    return EXIT_SUCCESS;
}
<commit_msg>Include file identifier when finishing sample log<commit_after>#include <array>
#include <chrono>
#include <cstdio>
#include <iostream>
#include <boost/math/constants/constants.hpp>
#include "bicycle.h"
#include "parameters.h"

#include "flatbuffers/flatbuffers.h"
#include "sample_log_generated.h"
#include "sample_util.h"

namespace {
    const double fs = 200; // sample rate [Hz]
    const double dt = 1.0/fs; // sample time [s]
    const double v0 = 4.0; // forward speed [m/s]
    const size_t N = 1000; // length of simulation in samples

    std::array<model::Bicycle::state_t, N> system_state;
    flatbuffers::FlatBufferBuilder builder;
    flatbuffers::FlatBufferBuilder log_builder;
    flatbuffers::Offset<fbs::SampleBuffer> sample_locations[N];
} // namespace

flatbuffers::Offset<fbs::Bicycle> create_bicycle(flatbuffers::FlatBufferBuilder& fbb, const model::Bicycle& bicycle) {
    auto M = fbs::second_order_matrix(bicycle.M());
    auto C1 = fbs::second_order_matrix(bicycle.C1());
    auto K0 = fbs::second_order_matrix(bicycle.K0());
    auto K2 = fbs::second_order_matrix(bicycle.K2());
    return fbs::CreateBicycle(fbb, bicycle.v(), bicycle.dt(), &M, &C1, &K0, &K2);
}

int main(int argc, char* argv[]) {
    (void)argc;
    (void)argv;

    model::Bicycle bicycle(parameters::benchmark::M, parameters::benchmark::C1,
            parameters::benchmark::K0, parameters::benchmark::K2, v0, dt);

    model::Bicycle::state_t x; // roll rate, steer rate, roll angle, steer angle
    x << 0, 10, 10, 0; // define x0 in degrees
    x *= boost::math::constants::degree<double>(); // convert to radians
    std::cout << "initial state: [" << x.transpose() << "]' rad" << std::endl;
    std::cout << "states are: [roll angle, steer angle, roll rate, steer rate]'" << std::endl << std::endl;

    // flatbuffer objects must be serialized in depth first pre-order traversal
    size_t current_sample = 0;

    std::cout << "simulating discrete time system at constant speed (" <<
        N << " steps at " << fs << " Hz) ..." << std::endl;
    auto disc_start = std::chrono::system_clock::now();
    for (auto& state: system_state) {
        x = bicycle.x_next(x);
        state = x;

        builder.Clear();
        fbs::SampleBuilder sample_builder(builder);
        if (current_sample == 0) {
            auto bicycle_location = create_bicycle(builder, bicycle);
            sample_builder.add_bicycle(bicycle_location);
        }
        auto fbs_state = fbs::state(x);
        sample_builder.add_state(&fbs_state);
        sample_builder.add_timestamp(current_sample);
        auto location = sample_builder.Finish();
        builder.Finish(location);
        // sample is serialized

        unsigned char* p = nullptr;
        auto data = log_builder.CreateUninitializedVector<unsigned char>(builder.GetSize(), &p);
        std::memcpy(p, builder.GetBufferPointer(), builder.GetSize());

        fbs::SampleBufferBuilder log_sample_builder(log_builder);
        log_sample_builder.add_data(data);
        sample_locations[current_sample++] = log_sample_builder.Finish();
    }
    auto disc_stop = std::chrono::system_clock::now();
    auto disc_time = disc_stop - disc_start;

    std::cout << "final state: " << system_state.back().transpose() << std::endl;
    std::cout << "simulation duration: " <<
        std::chrono::duration_cast<std::chrono::microseconds>(disc_time).count() <<
        " us" << std::endl;

    auto samples_vector = log_builder.CreateVector(sample_locations, N);
    auto log_location = fbs::CreateSampleLog(log_builder, samples_vector);
    log_builder.Finish(log_location, fbs::SampleLogIdentifier());

    {
        disc_start = std::chrono::system_clock::now();
        auto f = std::fopen("samples.bin", "wb");
        std::fwrite(log_builder.GetBufferPointer(), sizeof(char), log_builder.GetSize(), f);
        std::fclose(f);
        disc_stop = std::chrono::system_clock::now();
        disc_time = disc_stop - disc_start;
        std::cout << "write to file took: " <<
            std::chrono::duration_cast<std::chrono::microseconds>(disc_time).count() <<
            " us" << std::endl;
    }

    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include "Game.hpp"
#include "../Window/GlfwError.hpp"
#include "../Util/WarnGuard.hpp"
WARN_GUARD_ON
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include "../Graphics/Image/ImageLoader.hpp"
#include "../Graphics/Model/ModelLoader.hpp"
WARN_GUARD_OFF
#include "../Util/FileLoad.hpp"

///==============================================================
///= Game
///==============================================================
// BufferType for the files loaded
using BufferType = std::vector<std::uint8_t>;

Game::Game()
{
}

void Game::Init()
{
    // Setup window and input
    SetupWindow();

    // Initialize the renderer
    renderer.Init(mWindow.GetWidth(), mWindow.GetHeight());

    // Cube rotation state
    mRotationData.degreesInc = 0.05f;
    mRotationData.rotating = false;

    // Camera initial position
    mCamera.SetPos(glm::vec3(0, 0, 8));

    // Load the textures
    LoadTextures();

    // Load the models
    LoadModels();

    // Load the shaders
    LoadShaders();

    // Create world objects
    SetupWorld();
}

void Game::SetupWorld()
{
    // Retrieve the world from the renderer
    auto& world = renderer.GetWorld();

    //
    // Normal objects
    //
    std::vector<Renderer::WorldObject> normalObjects;
    // Create various Cube instances in the world
    std::vector<glm::vec3> cubePositions = {
        glm::vec3(0.0f, 0.0f, 0.0f),
        glm::vec3(4.0f, 10.0f, -20.0f),
        glm::vec3(-3.0f, -4.4f, -5.0f),
        glm::vec3(-7.6f, -4.0f, -14.0f),
        glm::vec3(4.4f, -3.5f, -4.0f),
        glm::vec3(-3.4f, 6.0f, -15.0f),
        glm::vec3(2.6f, -4.0f, -17.0f),
        glm::vec3(4.0f, 3.0f, -5.0f),
        glm::vec3(3.0f, 0.4f, -12.0f),
        glm::vec3(-3.5f, 2.0f, -3.0f)
    };
    for (std::size_t i = 0; i < cubePositions.size(); ++i)
    {
        const auto& pos = cubePositions[i];

        Transform trans;
        trans.Move(pos);
        trans.Scale(glm::vec3(2.0f));
        trans.RotateX(20.0f * i);
        trans.RotateY(7.0f * i);
        trans.RotateZ(10.0f * i);
        normalObjects.push_back({trans, "cube"});
    }

    // Add house
    {
        Transform trans;
        trans.Move(glm::vec3(0.0f, -10.0f, -40.0f));
        trans.Scale(glm::vec3(0.3f));
        normalObjects.push_back({trans, "house"});
    }
    world.insert({"normal", normalObjects});

    //
    // Light objects
    //
    std::vector<Renderer::WorldObject> lightObjects;

    // Add cube lights
    {
        Transform trans;
        trans.Move(glm::vec3(4.0f, 0.0f, 0.0f));
        trans.Scale(glm::vec3(0.3f));
        lightObjects.push_back({trans, "teapot"});
    }
    world.insert({"light", lightObjects});
    renderer.mLight = &world["light"].back();
}

void Game::SetupWindow()
{
    // Setup window
    bool success = mWindow.Create(800, 600, "TheRoom", Window::Mode::Windowed);
    if (!success)
        throw std::runtime_error(GetLastGlfwError().GetDescription());

    mWindow.SetShowFPS(true);
    mWindow.SetCloseHandler(mExitHandler);

    // Setup input event handlers
    mWindow.SetMouseButtonPressHandler(
        [this](MouseButton mb, ButtonAction ba)
        {
            if (mb == MouseButton::Left && ba == ButtonAction::Press)
                mWindow.SetMouseGrabEnabled(true);
        }
    );
    mWindow.SetKeyPressedHandler(
        [this](Key k, KeyAction ka)
        {
            // Exit
            if(k == Key::Escape && ka == KeyAction::Release)
                mExitHandler();
            // Ungrab mouse
            if(k == Key::RightControl && ka == KeyAction::Release)
                mWindow.SetMouseGrabEnabled(false);
            if(k == Key::R && ka == KeyAction::Release)
                mRotationData.rotating = !mRotationData.rotating;
        }
    );
}

void Game::LoadShaders()
{
    // Retrieve the shaderStore from the renderer
    auto& shaderStore = renderer.GetShaderStore();

    // The shader map
    std::unordered_map<std::string, std::vector<std::pair<ShaderStore::ShaderType,std::string>>> shaders =
    {
        {
            "geometry_pass",
            {
                { ShaderStore::ShaderType::Vertex,   "res/geometry_pass_vert.glsl" },
                { ShaderStore::ShaderType::Fragment, "res/geometry_pass_frag.glsl" },
            }
        },
        {
            "light_pass",
            {
                { ShaderStore::ShaderType::Vertex,   "res/light_pass_vert.glsl" },
                { ShaderStore::ShaderType::Fragment, "res/light_pass_frag.glsl" },
            }
        }
    };

    // Load shaders
    for (const auto& p : shaders)
    {
        // Will temporarily store the id's of the compiled shaders
        std::unordered_map<ShaderStore::ShaderType, GLuint> shaderIds;
        for (const auto& f : p.second)
        {
            // Load file
            auto shaderFile = FileLoad<BufferType>(f.second);
            if (!shaderFile)
                throw std::runtime_error("Could not find shader file: \n" + f.second);
            // Convert it to std::string containter
            std::string shaderSrc((*shaderFile).begin(), (*shaderFile).end());
            GLuint sId = shaderStore.LoadShader(shaderSrc, f.first);
            if (sId == 0)
                throw std::runtime_error("Shader compilation error: \n" + shaderStore.GetLastCompileError());
            // Insert loaded shader id to temp map
            shaderIds.insert({f.first, sId});
        }
        // Fetch vert and frag shader id's from temp map and link
        bool s = shaderStore.LinkProgram(p.first,
            shaderIds[ShaderStore::ShaderType::Vertex],
            shaderIds[ShaderStore::ShaderType::Fragment]);
        if (!s)
            throw std::runtime_error("OpenGL program link error: \n" + shaderStore.GetLastLinkError());
    }
}

void Game::LoadTextures()
{
    // Retrieve the textureStore from the renderer
    auto& textureStore = renderer.GetTextureStore();

    // The ImageLoader object
    ImageLoader imageLoader;

    // The texture map
    std::unordered_map<std::string, std::string> textures =
    {
        {"ext/mahogany_wood.jpg",            "mahogany_wood"},
        {"ext/mahogany_wood_spec.jpg",       "mahogany_wood_spec"},
        {"ext/WoodenCabin/WoodCabinDif.jpg", "house_diff"},
        {"ext/WoodenCabin/WoodCabinSM.jpg",  "house_spec"},
    };

    // Load the textures
    for (const auto& p : textures)
    {
        RawImage<> pb = imageLoader.LoadFile(p.first);
        textureStore.Load(p.second, pb);
    }

    // Add calculated textures
    RawImage<> pb({0xFF, 0xFF, 0xFF}, {1, 1, 3});
    textureStore.Load("white", pb);
    RawImage<> pb2({0x00, 0x00, 0x00}, {1, 1, 3});
    textureStore.Load("white_spec", pb2);
}

void Game::LoadModels()
{
    // Retrieve the model and texture stores from the renderer
    auto& modelStore = renderer.GetModelStore();
    auto& textureStore = renderer.GetTextureStore();

    // Model loader instance
    ModelLoader modelLoader;

    // Load the cube
    auto cubeFile = FileLoad<BufferType>("ext/Cube/cube.obj");
    if(!cubeFile)
        throw std::runtime_error("Couldn't load file (ext/Cube/cube.obj)");

    Model cube = modelLoader.Load(*cubeFile, "obj");
    if(cube.meshes.size() == 0)
        throw std::runtime_error("Couldn't load model (ext/Cube/cube.obj)");

    modelStore.Load("cube", std::move(cube));
    modelStore["cube"]->diffTexId = textureStore["mahogany_wood"]->texId;
    modelStore["cube"]->specTexId = textureStore["mahogany_wood_spec"]->texId;

    // Load teapot
    auto teapotFile = FileLoad<BufferType>("ext/teapot.obj");
    if(!teapotFile)
        throw std::runtime_error("Couldn't load file (ext/teapot.obj)");

    Model teapot = modelLoader.Load(*teapotFile, "obj");
    if(teapot.meshes.size() == 0)
        throw std::runtime_error("Couldn't load model (ext/teapot.obj)");

    modelStore.Load("teapot", std::move(teapot));
    modelStore["teapot"]->diffTexId = textureStore["white"]->texId;
    modelStore["teapot"]->specTexId = textureStore["white_spec"]->texId;

    // Load house
    auto houseFile = FileLoad<BufferType>("ext/WoodenCabin/WoodenCabin.dae");
    if(!houseFile)
        throw std::runtime_error("Couldn't load file (ext/WoodenCabin/WoodenCabin.dae)");

    Model house = modelLoader.Load(*houseFile, "dae");
    if(house.meshes.size() == 0)
        throw std::runtime_error("Couldn't load model (ext/WoodenCabin/WoodenCabin.dae)");

    modelStore.Load("house", std::move(house));
    modelStore["house"]->diffTexId = textureStore["house_diff"]->texId;
    modelStore["house"]->specTexId = textureStore["house_spec"]->texId;
}

std::vector<Camera::MoveDirection> Game::CameraMoveDirections()
{
    std::vector<Camera::MoveDirection> mds;
    if(mWindow.IsKeyPressed(Key::W))
        mds.push_back(Camera::MoveDirection::Forward);
    if(mWindow.IsKeyPressed(Key::A))
        mds.push_back(Camera::MoveDirection::Left);
    if(mWindow.IsKeyPressed(Key::S))
        mds.push_back(Camera::MoveDirection::BackWard);
    if(mWindow.IsKeyPressed(Key::D))
        mds.push_back(Camera::MoveDirection::Right);
    return mds;
}

std::tuple<float, float> Game::CameraLookOffset()
{
    std::tuple<double, double> curDiff = mWindow.GetCursorDiff();
    return std::make_tuple(
        static_cast<float>(std::get<0>(curDiff)),
        static_cast<float>(std::get<1>(curDiff))
    );
}

void Game::Update(float dt)
{
    (void) dt;

    // Poll window events
    mWindow.Update();

    // Update the interpolation state of the world
    renderer.Update(dt);

    // Update camera euler angles
    if (mWindow.MouseGrabEnabled())
        mCamera.Look(CameraLookOffset());

    // Update camera position
    mCamera.Move(CameraMoveDirections());

    // Update light position
    auto& trans = renderer.mLight->transform;
    float increase = 0.7f;
    if(mWindow.IsKeyPressed(Key::Kp8))
        trans.Move(glm::vec3(0.0f, increase, 0.0f));
    if(mWindow.IsKeyPressed(Key::Kp4))
        trans.Move(glm::vec3(-increase, 0.0f, 0.0f));
    if(mWindow.IsKeyPressed(Key::Kp2))
        trans.Move(glm::vec3(0.0f, -increase, 0.0f));
    if(mWindow.IsKeyPressed(Key::Kp6))
        trans.Move(glm::vec3(increase, 0.0f, 0.0f));
    if(mWindow.IsKeyPressed(Key::Kp5))
        trans.Move(glm::vec3(0.0f, 0.0f, -increase));
    if(mWindow.IsKeyPressed(Key::Kp0))
        trans.Move(glm::vec3(0.0f, 0.0f, increase));

    // Update cubes' rotations
    if (mRotationData.rotating)
    {
        for (auto& p : renderer.GetWorld())
            if (p.first == "normal")
                for (auto& gObj : p.second)
                    gObj.transform.RotateY(mRotationData.degreesInc);
    }
}

void Game::Render(float interpolation)
{
    // View calculation with camera
    auto lookOffset = mWindow.MouseGrabEnabled() ? CameraLookOffset() : std::make_tuple(0.0f, 0.0f);
    auto iCamState = mCamera.Interpolate(CameraMoveDirections(), lookOffset, interpolation);

    // Create the view matrix and pass it to the renderer
    glm::mat4 view = glm::lookAt(iCamState.position, iCamState.position + iCamState.front, iCamState.up);
    renderer.SetView(view);

    // Render
    renderer.Render(interpolation);

    // Show it
    mWindow.SwapBuffers();
}

void Game::Shutdown()
{
    // Renderer
    renderer.Shutdown();

    // Window
    mWindow.Destroy();
}

void Game::SetExitHandler(std::function<void()> f)
{
    mExitHandler = f;
}
<commit_msg>Eliminated code duplication on model loading<commit_after>#include "Game.hpp"
#include "../Window/GlfwError.hpp"
#include "../Util/WarnGuard.hpp"
WARN_GUARD_ON
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include "../Graphics/Image/ImageLoader.hpp"
#include "../Graphics/Model/ModelLoader.hpp"
WARN_GUARD_OFF
#include "../Util/FileLoad.hpp"

///==============================================================
///= Game
///==============================================================
// BufferType for the files loaded
using BufferType = std::vector<std::uint8_t>;

Game::Game()
{
}

void Game::Init()
{
    // Setup window and input
    SetupWindow();

    // Initialize the renderer
    renderer.Init(mWindow.GetWidth(), mWindow.GetHeight());

    // Cube rotation state
    mRotationData.degreesInc = 0.05f;
    mRotationData.rotating = false;

    // Camera initial position
    mCamera.SetPos(glm::vec3(0, 0, 8));

    // Load the textures
    LoadTextures();

    // Load the models
    LoadModels();

    // Load the shaders
    LoadShaders();

    // Create world objects
    SetupWorld();
}

void Game::SetupWorld()
{
    // Retrieve the world from the renderer
    auto& world = renderer.GetWorld();

    //
    // Normal objects
    //
    std::vector<Renderer::WorldObject> normalObjects;
    // Create various Cube instances in the world
    std::vector<glm::vec3> cubePositions = {
        glm::vec3(0.0f, 0.0f, 0.0f),
        glm::vec3(4.0f, 10.0f, -20.0f),
        glm::vec3(-3.0f, -4.4f, -5.0f),
        glm::vec3(-7.6f, -4.0f, -14.0f),
        glm::vec3(4.4f, -3.5f, -4.0f),
        glm::vec3(-3.4f, 6.0f, -15.0f),
        glm::vec3(2.6f, -4.0f, -17.0f),
        glm::vec3(4.0f, 3.0f, -5.0f),
        glm::vec3(3.0f, 0.4f, -12.0f),
        glm::vec3(-3.5f, 2.0f, -3.0f)
    };
    for (std::size_t i = 0; i < cubePositions.size(); ++i)
    {
        const auto& pos = cubePositions[i];

        Transform trans;
        trans.Move(pos);
        trans.Scale(glm::vec3(2.0f));
        trans.RotateX(20.0f * i);
        trans.RotateY(7.0f * i);
        trans.RotateZ(10.0f * i);
        normalObjects.push_back({trans, "cube"});
    }

    // Add house
    {
        Transform trans;
        trans.Move(glm::vec3(0.0f, -10.0f, -40.0f));
        trans.Scale(glm::vec3(0.3f));
        normalObjects.push_back({trans, "house"});
    }
    world.insert({"normal", normalObjects});

    //
    // Light objects
    //
    std::vector<Renderer::WorldObject> lightObjects;

    // Add cube lights
    {
        Transform trans;
        trans.Move(glm::vec3(4.0f, 0.0f, 0.0f));
        trans.Scale(glm::vec3(0.3f));
        lightObjects.push_back({trans, "teapot"});
    }
    world.insert({"light", lightObjects});
    renderer.mLight = &world["light"].back();
}

void Game::SetupWindow()
{
    // Setup window
    bool success = mWindow.Create(800, 600, "TheRoom", Window::Mode::Windowed);
    if (!success)
        throw std::runtime_error(GetLastGlfwError().GetDescription());

    mWindow.SetShowFPS(true);
    mWindow.SetCloseHandler(mExitHandler);

    // Setup input event handlers
    mWindow.SetMouseButtonPressHandler(
        [this](MouseButton mb, ButtonAction ba)
        {
            if (mb == MouseButton::Left && ba == ButtonAction::Press)
                mWindow.SetMouseGrabEnabled(true);
        }
    );
    mWindow.SetKeyPressedHandler(
        [this](Key k, KeyAction ka)
        {
            // Exit
            if(k == Key::Escape && ka == KeyAction::Release)
                mExitHandler();
            // Ungrab mouse
            if(k == Key::RightControl && ka == KeyAction::Release)
                mWindow.SetMouseGrabEnabled(false);
            if(k == Key::R && ka == KeyAction::Release)
                mRotationData.rotating = !mRotationData.rotating;
        }
    );
}

void Game::LoadShaders()
{
    // Retrieve the shaderStore from the renderer
    auto& shaderStore = renderer.GetShaderStore();

    // The shader map
    std::unordered_map<std::string, std::vector<std::pair<ShaderStore::ShaderType,std::string>>> shaders =
    {
        {
            "geometry_pass",
            {
                { ShaderStore::ShaderType::Vertex,   "res/geometry_pass_vert.glsl" },
                { ShaderStore::ShaderType::Fragment, "res/geometry_pass_frag.glsl" },
            }
        },
        {
            "light_pass",
            {
                { ShaderStore::ShaderType::Vertex,   "res/light_pass_vert.glsl" },
                { ShaderStore::ShaderType::Fragment, "res/light_pass_frag.glsl" },
            }
        }
    };

    // Load shaders
    for (const auto& p : shaders)
    {
        // Will temporarily store the id's of the compiled shaders
        std::unordered_map<ShaderStore::ShaderType, GLuint> shaderIds;
        for (const auto& f : p.second)
        {
            // Load file
            auto shaderFile = FileLoad<BufferType>(f.second);
            if (!shaderFile)
                throw std::runtime_error("Could not find shader file: \n" + f.second);
            // Convert it to std::string containter
            std::string shaderSrc((*shaderFile).begin(), (*shaderFile).end());
            GLuint sId = shaderStore.LoadShader(shaderSrc, f.first);
            if (sId == 0)
                throw std::runtime_error("Shader compilation error: \n" + shaderStore.GetLastCompileError());
            // Insert loaded shader id to temp map
            shaderIds.insert({f.first, sId});
        }
        // Fetch vert and frag shader id's from temp map and link
        bool s = shaderStore.LinkProgram(p.first,
            shaderIds[ShaderStore::ShaderType::Vertex],
            shaderIds[ShaderStore::ShaderType::Fragment]);
        if (!s)
            throw std::runtime_error("OpenGL program link error: \n" + shaderStore.GetLastLinkError());
    }
}

void Game::LoadTextures()
{
    // Retrieve the textureStore from the renderer
    auto& textureStore = renderer.GetTextureStore();

    // The ImageLoader object
    ImageLoader imageLoader;

    // The texture map
    std::unordered_map<std::string, std::string> textures =
    {
        {"ext/mahogany_wood.jpg",            "mahogany_wood"},
        {"ext/mahogany_wood_spec.jpg",       "mahogany_wood_spec"},
        {"ext/WoodenCabin/WoodCabinDif.jpg", "house_diff"},
        {"ext/WoodenCabin/WoodCabinSM.jpg",  "house_spec"},
    };

    // Load the textures
    for (const auto& p : textures)
    {
        RawImage<> pb = imageLoader.LoadFile(p.first);
        textureStore.Load(p.second, pb);
    }

    // Add calculated textures
    RawImage<> pb({0xFF, 0xFF, 0xFF}, {1, 1, 3});
    textureStore.Load("white", pb);
    RawImage<> pb2({0x00, 0x00, 0x00}, {1, 1, 3});
    textureStore.Load("white_spec", pb2);
}

void Game::LoadModels()
{
    // Retrieve the model and texture stores from the renderer
    auto& modelStore = renderer.GetModelStore();
    auto& textureStore = renderer.GetTextureStore();

    // Model loader instance
    ModelLoader modelLoader;

    struct ModelData
    {
        std::string
            filepath,
            extension,
            name,
            diffName,
            specName;
    };

    std::vector<ModelData> models = {
        {"ext/Cube/cube.obj",               "obj", "cube",   "mahogany_wood", "mahogany_wood_spec"} // Cube
    ,   {"ext/teapot.obj",                  "obj", "teapot", "white",         "white_spec"}         // Teapot
    ,   {"ext/WoodenCabin/WoodenCabin.dae", "dae", "house",  "house_diff",    "house_spec"}         // House
    };

    for(auto& m : models)
    {
        auto file = FileLoad<BufferType>(m.filepath);
        if(!file)
            throw std::runtime_error("Couldn't load file (" + m.filepath + ")");

        Model model = modelLoader.Load(*file, m.extension.c_str());
        if(model.meshes.size() == 0)
            throw std::runtime_error("Couldn't load model (" + m.filepath + ")");

        modelStore.Load(m.name, std::move(model));
        modelStore[m.name]->diffTexId = textureStore[m.diffName]->texId;
        modelStore[m.name]->specTexId = textureStore[m.specName]->texId;
    }
}

std::vector<Camera::MoveDirection> Game::CameraMoveDirections()
{
    std::vector<Camera::MoveDirection> mds;
    if(mWindow.IsKeyPressed(Key::W))
        mds.push_back(Camera::MoveDirection::Forward);
    if(mWindow.IsKeyPressed(Key::A))
        mds.push_back(Camera::MoveDirection::Left);
    if(mWindow.IsKeyPressed(Key::S))
        mds.push_back(Camera::MoveDirection::BackWard);
    if(mWindow.IsKeyPressed(Key::D))
        mds.push_back(Camera::MoveDirection::Right);
    return mds;
}

std::tuple<float, float> Game::CameraLookOffset()
{
    std::tuple<double, double> curDiff = mWindow.GetCursorDiff();
    return std::make_tuple(
        static_cast<float>(std::get<0>(curDiff)),
        static_cast<float>(std::get<1>(curDiff))
    );
}

void Game::Update(float dt)
{
    (void) dt;

    // Poll window events
    mWindow.Update();

    // Update the interpolation state of the world
    renderer.Update(dt);

    // Update camera euler angles
    if (mWindow.MouseGrabEnabled())
        mCamera.Look(CameraLookOffset());

    // Update camera position
    mCamera.Move(CameraMoveDirections());

    // Update light position
    auto& trans = renderer.mLight->transform;
    float increase = 0.7f;
    if(mWindow.IsKeyPressed(Key::Kp8))
        trans.Move(glm::vec3(0.0f, increase, 0.0f));
    if(mWindow.IsKeyPressed(Key::Kp4))
        trans.Move(glm::vec3(-increase, 0.0f, 0.0f));
    if(mWindow.IsKeyPressed(Key::Kp2))
        trans.Move(glm::vec3(0.0f, -increase, 0.0f));
    if(mWindow.IsKeyPressed(Key::Kp6))
        trans.Move(glm::vec3(increase, 0.0f, 0.0f));
    if(mWindow.IsKeyPressed(Key::Kp5))
        trans.Move(glm::vec3(0.0f, 0.0f, -increase));
    if(mWindow.IsKeyPressed(Key::Kp0))
        trans.Move(glm::vec3(0.0f, 0.0f, increase));

    // Update cubes' rotations
    if (mRotationData.rotating)
    {
        for (auto& p : renderer.GetWorld())
            if (p.first == "normal")
                for (auto& gObj : p.second)
                    gObj.transform.RotateY(mRotationData.degreesInc);
    }
}

void Game::Render(float interpolation)
{
    // View calculation with camera
    auto lookOffset = mWindow.MouseGrabEnabled() ? CameraLookOffset() : std::make_tuple(0.0f, 0.0f);
    auto iCamState = mCamera.Interpolate(CameraMoveDirections(), lookOffset, interpolation);

    // Create the view matrix and pass it to the renderer
    glm::mat4 view = glm::lookAt(iCamState.position, iCamState.position + iCamState.front, iCamState.up);
    renderer.SetView(view);

    // Render
    renderer.Render(interpolation);

    // Show it
    mWindow.SwapBuffers();
}

void Game::Shutdown()
{
    // Renderer
    renderer.Shutdown();

    // Window
    mWindow.Destroy();
}

void Game::SetExitHandler(std::function<void()> f)
{
    mExitHandler = f;
}
<|endoftext|>


<commit_before><commit_msg>[Fix] Entities' reorganization must take all of them into account<commit_after><|endoftext|>


<commit_before>#include <iostream>

template <typename Object_t, typename Underlying_t>
class Numerical
{
public:

	typedef Numerical<Object_t, Underlying_t> Numerical_t;

	explicit Numerical(const Underlying_t& value) : m_value(value) {}
	Numerical() : m_value() {}
  Numerical(const Numerical_t& n) : m_value(n.m_value) {}
  const Numerical& operator = (const Numerical_t& n) { m_value = n.m_value; return *this; }

	bool operator != (const Numerical_t& n) { return m_value != n.m_value; }
  bool operator == (const Numerical_t& n) { return m_value == n.m_value; }
  bool operator < (const Numerical_t& n) { return m_value < n.m_value; }
  bool operator > (const Numerical_t& n) { return m_value > n.m_value; }
  bool operator <= (const Numerical_t& n) { return m_value <= n.m_value; }
  bool operator >= (const Numerical_t& n) { return m_value >= n.m_value; }

	Numerical_t& operator ++ () { ++m_value; return *this; }

	Numerical_t operator + ( const Numerical_t& n) const { return Numerical_t(m_value + n.m_value); }
	Numerical_t operator - ( const Numerical_t& n) const { return Numerical_t(m_value - n.m_value); }
	Underlying_t operator / ( const Numerical_t& n) const { return m_value / n.m_value; }

	Underlying_t underlying_value() const { return m_value; }

private:
	Underlying_t m_value;
};

template <typename Object_t, typename Underlying_t>
std::ostream& operator << ( std::ostream& os, const Numerical<Object_t, Underlying_t>& n)
{
	return os << n.underlying_value();
}

template <typename Object_t>
using Int_t = Numerical<Object_t,int>;

template <typename Object_t>
using Double_t = Numerical<Object_t,double>;

template <typename Object_t>
using Index_t = Numerical<Object_t,size_t>;

class Apples {};
class Oranges {};

int main(int argc, char* argv[])
{
	Int_t<Apples> myAppleCount(5);
	Int_t<Apples> yourAppleCount(8);

  auto ourAppleCount = myAppleCount + yourAppleCount;
	std::cout << "My Apples: " << myAppleCount << "\n";
	std::cout << "Your Apples: " << yourAppleCount << "\n";
	std::cout << "Our Apples: " << ourAppleCount << "\n";

	std::cout << "\n";

	Int_t<Oranges> myOrangeCount(5);
	Int_t<Oranges> yourOrangeCount(8);

  auto ourOrangeCount = myOrangeCount + yourOrangeCount;
	std::cout << "My Oranges: " << myOrangeCount << "\n";
	std::cout << "Your Oranges: " << yourOrangeCount << "\n";
	std::cout << "Our Oranges: " << ourOrangeCount << "\n";

	std::cout << "\n";

  for ( Index_t<Oranges> i(1), ten_oranges(10); i<=ten_oranges; ++i )
	{
		std::cout << "Orange counter: " << i << "\n";
	}

	// One cannot add apples to oranges
	//auto ourFruitCount = ourAppleCount + ourOrangeCount;
}

<commit_msg>Added speed distance and time<commit_after>#include <iostream>

template <typename Object_t, typename Underlying_t>
class Numerical
{
	public:

		typedef Numerical<Object_t, Underlying_t> Numerical_t;

		explicit Numerical(const Underlying_t& value) : m_value(value) {}
		Numerical() : m_value() {}
		Numerical(const Numerical_t& n) : m_value(n.m_value) {}
		const Numerical& operator = (const Numerical_t& n) { m_value = n.m_value; return *this; }

		bool operator != (const Numerical_t& n) { return m_value != n.m_value; }
		bool operator == (const Numerical_t& n) { return m_value == n.m_value; }
		bool operator < (const Numerical_t& n) { return m_value < n.m_value; }
		bool operator > (const Numerical_t& n) { return m_value > n.m_value; }
		bool operator <= (const Numerical_t& n) { return m_value <= n.m_value; }
		bool operator >= (const Numerical_t& n) { return m_value >= n.m_value; }

		Numerical_t& operator ++ () { ++m_value; return *this; }

		Numerical_t operator + ( const Numerical_t& n) const { return Numerical_t(m_value + n.m_value); }
		Numerical_t operator - ( const Numerical_t& n) const { return Numerical_t(m_value - n.m_value); }
		Underlying_t operator / ( const Numerical_t& n) const { return m_value / n.m_value; }

		// If you want operator * implementing then add it yourself using inheritance

		Underlying_t underlying_value() const { return m_value; }

	private:
		Underlying_t m_value;
};

template <typename Object_t, typename Underlying_t>
std::ostream& operator << ( std::ostream& os, const Numerical<Object_t, Underlying_t>& n)
{
	return os << n.underlying_value();
}

template <typename Object_t>
using Int_t = Numerical<Object_t,int>;

template <typename Object_t>
using Double_t = Numerical<Object_t,double>;

template <typename Object_t>
using Index_t = Numerical<Object_t,size_t>;

class Apples {};
class Oranges {};

//////////////////////////////////////////////

class Distance;
class Time;
class Speed;

/////////////////////////////////////////////

class Distance : public Double_t<Distance>
{
	public:

		explicit Distance (double v) : Double_t<Distance>(v) {}

		Speed operator / (const Time& t) const;
};

/////////////////////////////////////////////

class Time : public Double_t<Time>
{
	public:

		explicit Time (double v) : Double_t<Time>(v) {}

		Distance operator * (const Speed& s) const;
};

/////////////////////////////////////////////

class Speed : public Double_t<Speed>
{
	public:
		explicit Speed (double v) : Double_t<Speed>(v) {}

		Distance operator * (const Time& t) const;
};

//////////////////////////////////////////////

Speed Distance::operator / (const Time& t) const
{
	return Speed(underlying_value()/t.underlying_value());
}

Distance Time::operator * (const Speed& s) const
{
	return Distance(underlying_value()*s.underlying_value());
}

Distance Speed::operator * (const Time& t) const
{
	return Distance(underlying_value()*t.underlying_value());
}

//////////////////////////////////////////////

int main(int argc, char* argv[])
{
	Int_t<Apples> myAppleCount(5);
	Int_t<Apples> yourAppleCount(8);

	auto ourAppleCount = myAppleCount + yourAppleCount;
	std::cout << "My Apples: " << myAppleCount << "\n";
	std::cout << "Your Apples: " << yourAppleCount << "\n";
	std::cout << "Our Apples: " << ourAppleCount << "\n";

	std::cout << "\n";

	Int_t<Oranges> myOrangeCount(5);
	Int_t<Oranges> yourOrangeCount(8);

	auto ourOrangeCount = myOrangeCount + yourOrangeCount;
	std::cout << "My Oranges: " << myOrangeCount << "\n";
	std::cout << "Your Oranges: " << yourOrangeCount << "\n";
	std::cout << "Our Oranges: " << ourOrangeCount << "\n";

	std::cout << "\n";

	for ( Index_t<Oranges> i(1), five_oranges(5); i<=five_oranges; ++i )
	{
		std::cout << "Orange counter: " << i << "\n";
	}

	// One cannot add apples to oranges
	//auto ourFruitCount = ourAppleCount + ourOrangeCount;

  Speed s = Distance(10.0) / Time(8.0);

	std::cout << "\n";

	std::cout << "Speed " << s << " = Distance " << Distance(10.0) << " / Time " << Time(8.0) << "\n";

}

<|endoftext|>