Go back to Richel Bilderbeek's homepage.

Go back to Richel Bilderbeek's C++ page.

 

 

 

 

 

(C++) RubiksClock

 

STLQt CreatorLubuntu

 

RubiksClock is a class for a Rubik's Clock.

Technical facts

 

 

 

 

 

 

./CppRubiksClock/CppRubiksClock.pri

 

INCLUDEPATH += \
    ../../Classes/CppRubiksClock

SOURCES += \
    ../../Classes/CppRubiksClock/rubiksclock.cpp \
    ../../Classes/CppRubiksClock/rubiksclockpegs.cpp \
    ../../Classes/CppRubiksClock/rubiksclockside.cpp \
    ../../Classes/CppRubiksClock/rubiksclocktimes.cpp

HEADERS  += \
    ../../Classes/CppRubiksClock/rubiksclock.h \
    ../../Classes/CppRubiksClock/rubiksclockpegs.h \
    ../../Classes/CppRubiksClock/rubiksclockside.h \
    ../../Classes/CppRubiksClock/rubiksclocktimes.h \
    ../../Classes/CppRubiksClock/rubiksclockfwd.h

OTHER_FILES += \
    ../../Classes/CppRubiksClock/Licence.txt

 

 

 

 

 

./CppRubiksClock/rubiksclock.h

 

//---------------------------------------------------------------------------
/*
RubiksClock, class for Rubik's clock
Copyright (C) 2011-2015 Richel Bilderbeek

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/CppRubiksClock.htm
//---------------------------------------------------------------------------
#ifndef RUBIKSCLOCK_H
#define RUBIKSCLOCK_H

#include <vector>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
#include <boost/checked_delete.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/signals2.hpp>
#include "rubiksclockfwd.h"
#include "rubiksclockside.h"
#include "widget.h"
#pragma GCC diagnostic pop

namespace ribi {
namespace ruco {

///Clock is a Rubik's Clock
struct Clock : public Widget
{
  Clock() noexcept;

  ///Set the geometry of all Widgets
  void SetGeometry(const Rect& r) noexcept;

  ///Change a peg, as seen from the front
  void TogglePeg(const Side side) noexcept;

  ///Change a wheel, as seen from the front
  void TurnWheel(const Side side, const int nSteps) noexcept;

  void Check() noexcept;

  ///Get the time dials of the back side
  const boost::shared_ptr<const Times> GetBackTimes() const noexcept { return m_back; }
  //const boost::shared_ptr<      Times> GetBackTimes()       noexcept { return m_back; }

  ///Get the time dials of the back side
  //Times& GetBackTimes() noexcept;

  ///Get the pegs of the back side
  const boost::shared_ptr<const Pegs> GetBackPegs() const noexcept;
  //const boost::shared_ptr<      Pegs> GetBackPegs()       noexcept;

  ///Get the time dials of the front side
  const boost::shared_ptr<const Times> GetFrontTimes() const noexcept { return m_front; }
  //const boost::shared_ptr<      Times> GetFrontTimes()       noexcept { return m_front; }

  ///Get the time dials of the front side
  //Times& GetFrontTimes() noexcept;

  ///Get the pegs of the front side
  const boost::shared_ptr<const Pegs> GetFrontPegs() const noexcept { return m_pegs; }

  ///Get the pegs of the front side
  //Pegs& GetFrontPegs() noexcept;

  ///Obtain this class its version
  static std::string GetVersion() noexcept;

  ///Obtain this class its version history
  static std::vector<std::string> GetVersionHistory() noexcept;

  ///Convert to a Canvas
  const boost::shared_ptr<TextCanvas> ToCanvas(const int radius) const noexcept;

  ///Convert to XML
  std::string ToXml() const noexcept;

  ///Respond to a change in the clock
  mutable boost::signals2::signal<void ()> m_signal_clock_changed;

  private:
  ~Clock() noexcept {}
  friend void boost::checked_delete<>(Clock*);
  friend void boost::checked_delete<>(const Clock*);

  boost::shared_ptr<Times> m_back;
  boost::shared_ptr<Times> m_front;
  boost::shared_ptr<Pegs > m_pegs;

  static const boost::shared_ptr<Pegs> CreatePegsFromIndex(const int index) noexcept;

  ///Change the top-left wheel, as seen from the front
  void TurnWheelTopLeft(const int nSteps) noexcept;

  ///Change the top-right wheel, as seen from the front
  void TurnWheelTopRight(const int nSteps) noexcept;

  ///Change the bottom-left wheel, as seen from the front
  void TurnWheelBottomLeft(const int nSteps) noexcept;

  ///Change the bottom-right wheel, as seen from the front
  void TurnWheelBottomRight(const int nSteps) noexcept;

  friend std::ostream& operator<<(std::ostream& os, const Clock& r) noexcept;

};

std::ostream& operator<<(std::ostream& os, const Clock& r) noexcept;

} //~namespace ruco
} //~namespace ribi

#endif // RUBIKSCLOCK_H

 

 

 

 

 

./CppRubiksClock/rubiksclock.cpp

 

//---------------------------------------------------------------------------
/*
RubiksClock, class for Rubik's clock
Copyright (C) 2011-2015 Richel Bilderbeek

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/CppRubiksClock.htm
//---------------------------------------------------------------------------
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
#include "rubiksclock.h"

#include <cassert>
#include <cstdlib>
#include <sstream>

#include <boost/numeric/conversion/cast.hpp>

#include "dial.h"
#include "dialwidget.h"
#include "geometry.h"
#include "rubiksclockdial.h"
#include "rubiksclockdialwidget.h"
#include "rubiksclockpegs.h"
#include "rubiksclocktimes.h"
#include "togglebutton.h"
#include "togglebuttonwidget.h"
//#include "trace.h"

#pragma GCC diagnostic pop

ribi::ruco::Clock::Clock() noexcept
  : m_signal_clock_changed{},
    m_back{new Times{false}},
    m_front{new Times{true}},
    m_pegs{new Pegs}
{
  Check();
}

void ribi::ruco::Clock::SetGeometry(const Rect& r) noexcept
{
  const int left   = Geometry().GetLeft(r);
  const int top    = Geometry().GetTop(r);
  const int width  = Geometry().GetWidth(r);
  const int height = Geometry().GetHeight(r);

  const double w3 = boost::numeric_cast<double>(width) / 3.0;
  const double h3 = boost::numeric_cast<double>(height) / 3.0;
  for (int x=0; x!=3; ++x)
  {
    const double x_d = boost::numeric_cast<double>(x);
    for (int y=0; y!=3; ++y)
    {
      const double y_d = boost::numeric_cast<double>(y);
      m_back->times[x][y]->SetGeometry(
        left + (x_d*w3),
        top + (y_d*h3),
        w3,
        h3
      );
      m_front->times[x][y]->SetGeometry(
        left + (x_d*w3),
        top + (y_d*h3),
        w3,
        h3
      );
    }
  }
  for (int x=0; x!=2; ++x)
  {
    const double x_d = boost::numeric_cast<double>(x);
    for (int y=0; y!=2; ++y)
    {
      const double y_d = boost::numeric_cast<double>(y);
      m_pegs->m_pegs[x][y]->SetGeometry(
        left + ((0.9+x_d)*w3),
        top + ((0.9+y_d)*h3),
        w3*0.2,
        h3*0.2
      );
    }
  }

}

void ribi::ruco::Clock::TogglePeg(const Side side) noexcept
{
  const int x = (side == Side::topLeft || side == Side::bottomLeft ? 0 : 1);
  const int y = (side == Side::topLeft || side == Side::topRight ? 0 : 1);
  m_pegs->m_pegs[x][y]->GetToggleButton()->Toggle();
  m_signal_clock_changed();
}

void ribi::ruco::Clock::TurnWheel(const Side side, const int nSteps) noexcept
{
  switch (side)
  {
    case Side::topLeft    : TurnWheelTopLeft(nSteps);     break;
    case Side::topRight   : TurnWheelTopRight(nSteps);    break;
    case Side::bottomLeft : TurnWheelBottomLeft(nSteps);  break;
    case Side::bottomRight: TurnWheelBottomRight(nSteps); break;
  }
  if (nSteps % 12 != 0)
  {
    m_signal_clock_changed();
  }
}

void ribi::ruco::Clock::TurnWheelTopLeft(const int nSteps) noexcept
{
  bool turnFront[3][3];
  bool turnBack[3][3];

  turnFront[0][0] = true;
  turnFront[1][0] = !m_pegs->m_pegs[0][0]->GetToggleButton()->IsPressed();
  turnFront[2][0] = (m_pegs->m_pegs[0][0]->GetToggleButton()->IsPressed() == m_pegs->m_pegs[1][0]->GetToggleButton()->IsPressed());
  turnFront[0][1] = !m_pegs->m_pegs[0][0]->GetToggleButton()->IsPressed();
  turnFront[1][1] = !m_pegs->m_pegs[0][0]->GetToggleButton()->IsPressed();
  turnFront[2][1] = (
    !m_pegs->m_pegs[0][0]->GetToggleButton()->IsPressed()
    && (  !m_pegs->m_pegs[1][0]->GetToggleButton()->IsPressed()
       || !m_pegs->m_pegs[1][1]->GetToggleButton()->IsPressed() ) );
  turnFront[0][2] = (m_pegs->m_pegs[0][0]->GetToggleButton()->IsPressed() == m_pegs->m_pegs[0][1]->GetToggleButton()->IsPressed());
  turnFront[1][2] = (
    !m_pegs->m_pegs[0][0]->GetToggleButton()->IsPressed()
    && (  !m_pegs->m_pegs[0][1]->GetToggleButton()->IsPressed()
       || !m_pegs->m_pegs[1][1]->GetToggleButton()->IsPressed() ) );
  turnFront[2][2] = (m_pegs->m_pegs[0][0]->GetToggleButton()->IsPressed() == m_pegs->m_pegs[1][1]->GetToggleButton()->IsPressed());

  turnBack[0][0] = (m_pegs->m_pegs[0][0]->GetToggleButton()->IsPressed() == m_pegs->m_pegs[1][0]->GetToggleButton()->IsPressed());
  turnBack[1][0] = (m_pegs->m_pegs[0][0]->GetToggleButton()->IsPressed());
  turnBack[2][0] = true;

  turnBack[0][1] = (
    m_pegs->m_pegs[0][0]->GetToggleButton()->IsPressed()
    && (    m_pegs->m_pegs[1][0]->GetToggleButton()->IsPressed()
       ||   m_pegs->m_pegs[1][1]->GetToggleButton()->IsPressed() ) );
  turnBack[1][1] = (m_pegs->m_pegs[0][0]->GetToggleButton()->IsPressed());
  turnBack[2][1] = (m_pegs->m_pegs[0][0]->GetToggleButton()->IsPressed());

  turnBack[0][2] = (m_pegs->m_pegs[0][0]->GetToggleButton()->IsPressed() == m_pegs->m_pegs[1][1]->GetToggleButton()->IsPressed());
  turnBack[1][2] = (
    m_pegs->m_pegs[0][0]->GetToggleButton()->IsPressed()
    && (  m_pegs->m_pegs[0][1]->GetToggleButton()->IsPressed()
       || m_pegs->m_pegs[1][1]->GetToggleButton()->IsPressed() ) );
  turnBack[2][2] = (m_pegs->m_pegs[0][0]->GetToggleButton()->IsPressed() == m_pegs->m_pegs[0][1]->GetToggleButton()->IsPressed());

  for (int y=0; y!=3; ++y)
  {
    for (int x=0; x!=3; ++x)
    {
      if (turnFront[x][y]) { m_front->times[x][y]->GetRubiksClockDial()->Turn(nSteps); }
      if (turnBack[x][y]) { m_back->times[x][y]->GetRubiksClockDial()->Turn(-nSteps); }
    }
  }

}

void ribi::ruco::Clock::TurnWheelTopRight(const int nSteps) noexcept
{
  bool turnFront[3][3];
  bool turnBack[3][3];

  turnFront[2][0] = true;
  turnFront[1][0] = !m_pegs->m_pegs[1][0]->GetToggleButton()->IsPressed();
  turnFront[0][0] = (m_pegs->m_pegs[0][0]->GetToggleButton()->IsPressed() == m_pegs->m_pegs[1][0]->GetToggleButton()->IsPressed());
  turnFront[2][1] = !m_pegs->m_pegs[1][0]->GetToggleButton()->IsPressed();
  turnFront[1][1] = !m_pegs->m_pegs[1][0]->GetToggleButton()->IsPressed();
  turnFront[0][1] = (
    !m_pegs->m_pegs[1][0]->GetToggleButton()->IsPressed()
    && (  !m_pegs->m_pegs[0][0]->GetToggleButton()->IsPressed()
       || !m_pegs->m_pegs[0][1]->GetToggleButton()->IsPressed() ) );
  turnFront[2][2] = (m_pegs->m_pegs[1][0]->GetToggleButton()->IsPressed() == m_pegs->m_pegs[1][1]->GetToggleButton()->IsPressed());
  turnFront[1][2] = (
    !m_pegs->m_pegs[1][0]->GetToggleButton()->IsPressed()
    && (  !m_pegs->m_pegs[1][1]->GetToggleButton()->IsPressed()
       || !m_pegs->m_pegs[0][1]->GetToggleButton()->IsPressed() ) );
  turnFront[0][2] = (m_pegs->m_pegs[1][0]->GetToggleButton()->IsPressed() == m_pegs->m_pegs[0][1]->GetToggleButton()->IsPressed());

  turnBack[2][0] = (m_pegs->m_pegs[1][0]->GetToggleButton()->IsPressed() == m_pegs->m_pegs[0][0]->GetToggleButton()->IsPressed());
  turnBack[1][0] = m_pegs->m_pegs[1][0]->GetToggleButton()->IsPressed();
  turnBack[0][0] = true;

  turnBack[2][1] = (
    m_pegs->m_pegs[1][0]->GetToggleButton()->IsPressed()
    && (    m_pegs->m_pegs[0][0]->GetToggleButton()->IsPressed()
       ||   m_pegs->m_pegs[0][1]->GetToggleButton()->IsPressed() ) );
  turnBack[1][1] = m_pegs->m_pegs[1][0]->GetToggleButton()->IsPressed();
  turnBack[0][1] = m_pegs->m_pegs[1][0]->GetToggleButton()->IsPressed();

  turnBack[2][2] = (m_pegs->m_pegs[1][0]->GetToggleButton()->IsPressed() == m_pegs->m_pegs[0][1]->GetToggleButton()->IsPressed());
  turnBack[1][2] = (
    m_pegs->m_pegs[1][0]->GetToggleButton()->IsPressed()
    && (  m_pegs->m_pegs[1][1]->GetToggleButton()->IsPressed()
       || m_pegs->m_pegs[0][1]->GetToggleButton()->IsPressed() ) );
  turnBack[0][2] = (m_pegs->m_pegs[1][0]->GetToggleButton()->IsPressed() == m_pegs->m_pegs[1][1]->GetToggleButton()->IsPressed());

  for (int y=0; y!=3; ++y)
  {
    for (int x=0; x!=3; ++x)
    {
      if (turnFront[x][y]) { m_front->times[x][y]->GetRubiksClockDial()->Turn(nSteps); }
      if (turnBack[x][y]) { m_back->times[x][y]->GetRubiksClockDial()->Turn(-nSteps); }
    }
  }
}

void ribi::ruco::Clock::TurnWheelBottomLeft(const int nSteps) noexcept
{
  bool turnFront[3][3];
  bool turnBack[3][3];

  turnFront[0][2] = true;
  turnFront[1][2] = !m_pegs->m_pegs[0][1]->GetToggleButton()->IsPressed();
  turnFront[2][2] = (m_pegs->m_pegs[0][1]->GetToggleButton()->IsPressed() == m_pegs->m_pegs[1][1]->GetToggleButton()->IsPressed());
  turnFront[0][1] = !m_pegs->m_pegs[0][1]->GetToggleButton()->IsPressed();
  turnFront[1][1] = !m_pegs->m_pegs[0][1]->GetToggleButton()->IsPressed();
  turnFront[2][1] = (
    !m_pegs->m_pegs[0][1]->GetToggleButton()->IsPressed()
    && (  !m_pegs->m_pegs[1][1]->GetToggleButton()->IsPressed()
       || !m_pegs->m_pegs[1][0]->GetToggleButton()->IsPressed() ) );
  turnFront[0][0] = (m_pegs->m_pegs[0][1]->GetToggleButton()->IsPressed() == m_pegs->m_pegs[0][0]->GetToggleButton()->IsPressed());
  turnFront[1][0] = (
    !m_pegs->m_pegs[0][1]->GetToggleButton()->IsPressed()
    && (  !m_pegs->m_pegs[0][0]->GetToggleButton()->IsPressed()
       || !m_pegs->m_pegs[1][0]->GetToggleButton()->IsPressed() ) );
  turnFront[2][0] = (m_pegs->m_pegs[0][1]->GetToggleButton()->IsPressed() == m_pegs->m_pegs[1][0]->GetToggleButton()->IsPressed());

  turnBack[0][2] = (m_pegs->m_pegs[0][1]->GetToggleButton()->IsPressed() == m_pegs->m_pegs[1][1]->GetToggleButton()->IsPressed());
  turnBack[1][2] = m_pegs->m_pegs[0][1]->GetToggleButton()->IsPressed();
  turnBack[2][2] = true;

  turnBack[0][1] = (
    m_pegs->m_pegs[0][1]->GetToggleButton()->IsPressed()
    && (    m_pegs->m_pegs[1][1]->GetToggleButton()->IsPressed()
       ||   m_pegs->m_pegs[1][0]->GetToggleButton()->IsPressed() ) );
  turnBack[1][1] = m_pegs->m_pegs[0][1]->GetToggleButton()->IsPressed();
  turnBack[2][1] = m_pegs->m_pegs[0][1]->GetToggleButton()->IsPressed();

  turnBack[0][0] = (m_pegs->m_pegs[0][1]->GetToggleButton()->IsPressed() == m_pegs->m_pegs[1][0]->GetToggleButton()->IsPressed());
  turnBack[1][0] = (
    m_pegs->m_pegs[0][1]->GetToggleButton()->IsPressed()
    && (  m_pegs->m_pegs[0][0]->GetToggleButton()->IsPressed()
       || m_pegs->m_pegs[1][0]->GetToggleButton()->IsPressed() ) );
  turnBack[2][0] = (m_pegs->m_pegs[0][1]->GetToggleButton()->IsPressed() == m_pegs->m_pegs[0][0]->GetToggleButton()->IsPressed());

  for (int y=0; y!=3; ++y)
  {
    for (int x=0; x!=3; ++x)
    {
      if (turnFront[x][y]) { m_front->times[x][y]->GetRubiksClockDial()->Turn(nSteps); }
      if (turnBack[x][y]) { m_back->times[x][y]->GetRubiksClockDial()->Turn(-nSteps); }
    }
  }
}

void ribi::ruco::Clock::TurnWheelBottomRight(const int nSteps) noexcept
{
  bool turnFront[3][3];
  bool turnBack[3][3];

  turnFront[2][2] = true;
  turnFront[1][2] = !m_pegs->m_pegs[1][1]->GetToggleButton()->IsPressed();
  turnFront[0][2] = (m_pegs->m_pegs[0][1]->GetToggleButton()->IsPressed() == m_pegs->m_pegs[1][1]->GetToggleButton()->IsPressed());
  turnFront[2][1] = !m_pegs->m_pegs[1][1]->GetToggleButton()->IsPressed();
  turnFront[1][1] = !m_pegs->m_pegs[1][1]->GetToggleButton()->IsPressed();
  turnFront[0][1] = (
    !m_pegs->m_pegs[1][1]->GetToggleButton()->IsPressed()
    && (  !m_pegs->m_pegs[0][1]->GetToggleButton()->IsPressed()
       || !m_pegs->m_pegs[0][0]->GetToggleButton()->IsPressed() ) );
  turnFront[2][0] = (m_pegs->m_pegs[1][1]->GetToggleButton()->IsPressed() == m_pegs->m_pegs[1][0]->GetToggleButton()->IsPressed());
  turnFront[1][0] = (
    !m_pegs->m_pegs[1][1]->GetToggleButton()->IsPressed()
    && (  !m_pegs->m_pegs[1][0]->GetToggleButton()->IsPressed()
       || !m_pegs->m_pegs[0][0]->GetToggleButton()->IsPressed()  ) );
  turnFront[0][0] = (m_pegs->m_pegs[1][1]->GetToggleButton()->IsPressed() == m_pegs->m_pegs[0][0]->GetToggleButton()->IsPressed());

  turnBack[2][2] = (m_pegs->m_pegs[1][1]->GetToggleButton()->IsPressed() == m_pegs->m_pegs[0][1]->GetToggleButton()->IsPressed());
  turnBack[1][2] = m_pegs->m_pegs[1][1]->GetToggleButton()->IsPressed();
  turnBack[0][2] = true;

  turnBack[2][1] = (
    m_pegs->m_pegs[1][1]->GetToggleButton()->IsPressed()
    && (    m_pegs->m_pegs[0][1]->GetToggleButton()->IsPressed()
       ||   m_pegs->m_pegs[0][0]->GetToggleButton()->IsPressed() ) );
  turnBack[1][1] = m_pegs->m_pegs[1][1]->GetToggleButton()->IsPressed();
  turnBack[0][1] = m_pegs->m_pegs[1][1]->GetToggleButton()->IsPressed();

  turnBack[2][0] = (m_pegs->m_pegs[1][1]->GetToggleButton()->IsPressed() == m_pegs->m_pegs[0][0]->GetToggleButton()->IsPressed());
  turnBack[1][0] = (
    m_pegs->m_pegs[1][1]->GetToggleButton()->IsPressed()
    && (  m_pegs->m_pegs[1][0]->GetToggleButton()->IsPressed()
       || m_pegs->m_pegs[0][0]->GetToggleButton()->IsPressed() ) );
  turnBack[0][0] = (m_pegs->m_pegs[1][1]->GetToggleButton()->IsPressed() == m_pegs->m_pegs[1][0]->GetToggleButton()->IsPressed());

  for (int y=0; y!=3; ++y)
  {
    for (int x=0; x!=3; ++x)
    {
      if (turnFront[x][y]) { m_front->times[x][y]->GetRubiksClockDial()->Turn(nSteps); }
      if (turnBack[x][y]) { m_back->times[x][y]->GetRubiksClockDial()->Turn(-nSteps); }
    }
  }
}



const boost::shared_ptr<const ribi::ruco::Pegs> ribi::ruco::Clock::GetBackPegs() const noexcept
{
  const boost::shared_ptr<Pegs> back(new Pegs);
  back->m_pegs[0][0].reset(new ToggleButtonWidget(!m_pegs->m_pegs[1][0]->GetToggleButton()->IsPressed(),255,255,0));
  back->m_pegs[1][0].reset(new ToggleButtonWidget(!m_pegs->m_pegs[0][0]->GetToggleButton()->IsPressed(),255,255,0));
  back->m_pegs[0][1].reset(new ToggleButtonWidget(!m_pegs->m_pegs[1][1]->GetToggleButton()->IsPressed(),255,255,0));
  back->m_pegs[1][1].reset(new ToggleButtonWidget(!m_pegs->m_pegs[0][1]->GetToggleButton()->IsPressed(),255,255,0));

  for (int x=0; x!=2; ++x)
  {
    for (int y=0; y!=2; ++y)
    {
      back->m_pegs[x][y]->SetGeometry(m_pegs->m_pegs[1-x][y]->GetGeometry());
    }
  }

  return back;
}

void ribi::ruco::Clock::Check() noexcept
{
  #ifndef NDEBUG
  const auto originalFront = m_front;
  const auto originalBack = m_back;
  const auto originalPegs = m_pegs;

  //Check the corner clocks
  assert( (m_front->times[0][0]->GetRubiksClockDial()->GetTime()
    + m_back->times[2][0]->GetRubiksClockDial()->GetTime()) % 12 == 0);
  assert( (m_front->times[2][0]->GetRubiksClockDial()->GetTime()
    + m_back->times[0][0]->GetRubiksClockDial()->GetTime()) % 12 == 0);
  assert( (m_front->times[0][2]->GetRubiksClockDial()->GetTime()
    + m_back->times[2][2]->GetRubiksClockDial()->GetTime()) % 12 == 0);
  assert( (m_front->times[2][2]->GetRubiksClockDial()->GetTime()
    + m_back->times[0][2]->GetRubiksClockDial()->GetTime()) % 12 == 0);
  //Check all peg combinations
  for (int i=0; i!=16; ++i)
  {
    m_pegs = CreatePegsFromIndex(i);
    //Check all wheels
    for (int j=0; j!=4; ++j)
    {
      //Check if after turning around in two steps, everything stays the same
      const auto front = m_front;
      const auto back = m_back;

      const Side side = static_cast<Side>(j);
      const int nSteps = std::rand() % 12;
      //Turn 1
      this->TurnWheel(side,nSteps);
      //Turn 11
      this->TurnWheel(side,12-nSteps);
      assert( m_front == front);
      assert( m_back == back);
    }
  }

  #endif
}

const boost::shared_ptr<ribi::ruco::Pegs> ribi::ruco::Clock::CreatePegsFromIndex(const int index) noexcept
{
  //Index 0: (p = pressed, u = unpressed)
  // u u
  // u u
  //Index 1: (p = pressed, u = unpressed)
  // p u
  // u u
  //Index 2: (p = pressed, u = unpressed)
  // u p
  // u u
  //Index 3: (p = pressed, u = unpressed)
  // p p
  // u u
  //Index 4: (p = pressed, u = unpressed)
  // u u
  // p u
  //Index 5: (p = pressed, u = unpressed)
  // p u
  // p u
  //Index 6: (p = pressed, u = unpressed)
  // u p
  // p u
  //Index 7: (p = pressed, u = unpressed)
  // p p
  // p u
  //Index 8: (p = pressed, u = unpressed)
  // u u
  // u p
  //Index 9: (p = pressed, u = unpressed)
  // p u
  // u p
  //Index 10: (p = pressed, u = unpressed)
  // u p
  // u p
  //Index 11: (p = pressed, u = unpressed)
  // p p
  // u p
  //Index 12: (p = pressed, u = unpressed)
  // u u
  // p p
  //Index 13: (p = pressed, u = unpressed)
  // p u
  // p p
  //Index 14: (p = pressed, u = unpressed)
  // u p
  // p p
  //Index 15: (p = pressed, u = unpressed)
  // p p
  // p p

  const boost::shared_ptr<Pegs> pegs {
    new Pegs
  };
  if ((index & 1) == 1) { pegs->m_pegs[0][0]->GetToggleButton()->Toggle(); }
  if ((index & 2) == 2) { pegs->m_pegs[0][1]->GetToggleButton()->Toggle(); }
  if ((index & 4) == 4) { pegs->m_pegs[1][0]->GetToggleButton()->Toggle(); }
  if ((index & 8) == 8) { pegs->m_pegs[1][1]->GetToggleButton()->Toggle(); }
  return pegs;
}

std::string ribi::ruco::Clock::GetVersion() noexcept
{
  return "2.1";
}

std::vector<std::string> ribi::ruco::Clock::GetVersionHistory() noexcept
{
  return {
    "2011-09-08: Version 1.0: initial version",
    "2014-01-23: Version 2.0: put into namespace ruco, forward declarations, use of smart pointers, use of multiple files",
    "2014-03-28: version 2.1: replaced Rect by Boost.Geometry its box class"
  };
}

std::string ribi::ruco::Clock::ToXml() const noexcept
{
  std::stringstream s;
  s
    << "<rubiks_clock>"
    << "<front>"
    << (*m_front)
    << "</front>"
    << "<back>"
    << (*m_back)
    << "</back>"
    << "<pegs>"
    << (*m_pegs)
    << "</pegs>"
    << "</rubiks_clock>";
  return s.str()
  ;
}

std::ostream& ribi::ruco::operator<<(std::ostream& os, const ribi::ruco::Clock& r) noexcept
{
  os
    << "<rubiks_clock>"
    << "<front>"
    << r.m_front
    << "</front>"
    << "<back>"
    << r.m_back
    << "</back>"
    << "<pegs>"
    << r.m_pegs
    << "</pegs>"
    << "</rubiks_clock>";
  return os;
}

 

 

 

 

 

./CppRubiksClock/rubiksclockfwd.h

 

#ifndef RUBIKSCLOCKFWD_H
#define RUBIKSCLOCKFWD_H

namespace ribi {

struct DrawCanvas;
struct TextCanvas;
struct TextCanvas;
struct ToggleButton;
struct ToggleButtonWidget;

namespace ruco {

struct Clock;
struct ClockDial;
struct ClockWidget;
struct DialWidget;
struct Pegs;
//struct RubiksClock; //Renamed to Clock
//struct RubiksClockWidget; //Renamed to ClockWidget
struct Times;

} //~namespace ribi
} //~namespace ruco

#endif // RUBIKSCLOCKFWD_H

 

 

 

 

 

./CppRubiksClock/rubiksclockpegs.h

 

#ifndef RUBIKSCLOCKPEGS_H
#define RUBIKSCLOCKPEGS_H

#include <iosfwd>
#include <string>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
#include <boost/shared_ptr.hpp>
#include "rubiksclockfwd.h"
#include "rubiksclockside.h"
#pragma GCC diagnostic pop

namespace ribi {
namespace ruco {

///The four Pegs on a Rubik's Clock
struct Pegs
{
  Pegs() noexcept;
  boost::shared_ptr<ToggleButtonWidget> m_pegs[2][2]; //Is peg pressed?
  static Pegs CreatePegsFromIndex(const int index) noexcept;
  const boost::shared_ptr<const ToggleButtonWidget> GetPeg(const Side side) const noexcept;
  std::string ToXml() const noexcept;

  private:
  ~Pegs() noexcept {}
  friend void boost::checked_delete<>(Pegs*);
  friend void boost::checked_delete<>(const Pegs*);
};

std::ostream& operator<<(std::ostream& os, const Pegs& p) noexcept;
bool operator==(const Pegs& lhs, const Pegs& rhs) noexcept;

} //~namespace ruco
} //~namespace ribi

#endif // RUBIKSCLOCKPEGS_H

 

 

 

 

 

./CppRubiksClock/rubiksclockpegs.cpp

 

#include "rubiksclockpegs.h"

#include <cassert>

#include "rubiksclockside.h"
#include "togglebutton.h"
#include "togglebuttonwidget.h"
#include "trace.h"

ribi::ruco::Pegs::Pegs() noexcept
{
  for (int y=0; y!=2; ++y)
  {
    for (int x=0; x!=2; ++x)
    {
      m_pegs[x][y].reset(new ToggleButtonWidget(false,255,255,0));
    }
  }
}

const boost::shared_ptr<const ribi::ToggleButtonWidget> ribi::ruco::Pegs::GetPeg(const Side side) const noexcept
{
  switch (side)
  {
    case Side::topLeft    : return m_pegs[0][0];
    case Side::bottomLeft : return m_pegs[1][0];
    case Side::topRight   : return m_pegs[0][1];
    case Side::bottomRight: return m_pegs[1][1];
  }
  assert(!"Should not get here");
  throw std::logic_error("ribi::ruco::Pegs::GetPeg");
}

bool operator==(const ribi::ruco::Pegs& lhs, const ribi::ruco::Pegs& rhs) noexcept
{
  for (int y=0; y!=2; ++y)
  {
    for (int x=0; x!=2; ++x)
    {
      if (lhs.m_pegs[x][y] != rhs.m_pegs[x][y]) return false;
    }
  }
  return true;
}


std::ostream& ribi::ruco::operator<<(std::ostream& os, const ribi::ruco::Pegs& p) noexcept
{
  os
    << "<rubiks_clock_pegs>";
  for (int x=0; x!=2; ++x)
  {
    for (int y=0; y!=2; ++y)
    {
      os
        << "<rubiks_clock_pegs>"
        << "<x>"
        << x
        << "</x>"
        << "<y>"
        << y
        << "</y>"
        << p.m_pegs[x][y].get()
        << "</rubiks_clock_dial>";
    }
  }
  os
    << "</rubiks_clock_pegs>";
  return os;
}

 

 

 

 

 

./CppRubiksClock/rubiksclockside.h

 

#ifndef RUBIKSCLOCKSIDE_H
#define RUBIKSCLOCKSIDE_H

namespace ribi {
namespace ruco {

enum class Side
{
  topLeft, topRight, bottomLeft, bottomRight
};

} //~namespace ruco {
} //~namespace ribi {


#endif // RUBIKSCLOCKSIDE_H

 

 

 

 

 

./CppRubiksClock/rubiksclockside.cpp

 

#include "rubiksclockside.h"

 

 

 

 

 

./CppRubiksClock/rubiksclocktimes.h

 

#ifndef RUBIKSCLOCKTIMES_H
#define RUBIKSCLOCKTIMES_H

#include <iosfwd>
#include <string>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
#include <boost/shared_ptr.hpp>

#include "rubiksclockside.h"
#pragma GCC diagnostic pop

namespace ribi {
namespace ruco {

struct ClockDialWidget;

///The nine times on a Rubik's Clock
struct Times
{
  Times(const bool is_front) noexcept;
  boost::shared_ptr<ClockDialWidget> times[3][3];
  std::string ToXml() const noexcept;

  private:
  ~Times() noexcept {}
  friend void boost::checked_delete<>(Times*);
  friend void boost::checked_delete<>(const Times*);
};

std::ostream& operator<<(std::ostream& os, const Times& t) noexcept;
bool operator==(const Times& lhs, const Times& rhs) noexcept;

} //~namespace ruco
} //~namespace ribi

#endif // RUBIKSCLOCKTIMES_H

 

 

 

 

 

./CppRubiksClock/rubiksclocktimes.cpp

 

#include "rubiksclocktimes.h"

#include <cassert>

#include "dial.h"
#include "rubiksclock.h"
#include "rubiksclockwidget.h"
#include "rubiksclockdial.h"
#include "rubiksclockdialwidget.h"

ribi::ruco::Times::Times(const bool is_front) noexcept
{
  for (int y=0; y!=3; ++y)
  {
    for (int x=0; x!=3; ++x)
    {
      times[x][y].reset(new ClockDialWidget(0,0,0,32,32,
        is_front ? 196 : 128,
        is_front ? 196 : 128,
        is_front ? 255 : 255));
    }
  }
}

bool ribi::ruco::operator==(const ribi::ruco::Times& lhs, const ribi::ruco::Times& rhs) noexcept
{
  for (int y=0; y!=3; ++y)
  {
    for (int x=0; x!=3; ++x)
    {
      if (lhs.times[x][y]->GetRubiksClockDial()->GetTime()
        != rhs.times[x][y]->GetRubiksClockDial()->GetTime()) return false;
    }
  }
  return true;
}

std::ostream& ribi::ruco::operator<<(std::ostream& os, const ribi::ruco::Times& t) noexcept
{
  os
    << "<rubiks_clock_times>";
  for (int x=0; x!=3; ++x)
  {
    for (int y=0; y!=3; ++y)
    {
      os
        << "<rubiks_clock_dial>"
        << "<x>"
        << x
        << "</x>"
        << "<y>"
        << y
        << "</y>"
        << t.times[x][y].get()
        << "</rubiks_clock_dial>";
    }
  }
  os
    << "</rubiks_clock_times>";
  return os;
}

 

 

 

 

 

Go back to Richel Bilderbeek's C++ page.

Go back to Richel Bilderbeek's homepage.

 

Valid XHTML 1.0 Strict

This page has been created by the tool CodeToHtml