(C++) MysteryMachine
January 25, 2018 · View on GitHub
(C++) MysteryMachine



MysteryMachine is a class to simulate my mystery machine.
MysteryMachine is used in the tool SimMysteryMachine.
Technical facts
./CppMysteryMachine/CppMysteryMachine.pri
INCLUDEPATH += \ ../../Classes/CppMysteryMachine SOURCES += \ ../../Classes/CppMysteryMachine/mysterymachine.cpp HEADERS += \ ../../Classes/CppMysteryMachine/mysterymachine.h OTHER_FILES += \ ../../Classes/CppMysteryMachine/Licence.txt
./CppMysteryMachine/mysterymachine.h
//--------------------------------------------------------------------------- /* MysteryMachine, my mystery machine class Copyright 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/CppMysteryMachine.htm //--------------------------------------------------------------------------- #ifndef MYSTERYMACHINE_H #define MYSTERYMACHINE_H #include <string> #include <vector> #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Weffc++" #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #include <boost/checked_delete.hpp> #include <boost/shared_ptr.hpp> #include <boost/signals2.hpp> #pragma GCC diagnostic pop namespace ribi { struct DialWidget; struct LedWidget; struct TextCanvas; struct ToggleButtonWidget; ///MysteryMachine contains the logic behind my Mystery Machine struct MysteryMachine { MysteryMachine() noexcept; MysteryMachine(const MysteryMachine&) = delete; MysteryMachine& operator=(const MysteryMachine&) = delete; const boost::shared_ptr<DialWidget> GetDialBack() noexcept { return m_dial_back; } const boost::shared_ptr<DialWidget> GetDialFront() noexcept { return m_dial_front; } const boost::shared_ptr<LedWidget> GetLedBack1() noexcept { return m_led_back_1; } const boost::shared_ptr<LedWidget> GetLedBack2() noexcept { return m_led_back_2; } const boost::shared_ptr<LedWidget> GetLedBack3() noexcept { return m_led_back_3; } const boost::shared_ptr<LedWidget> GetLedFront1() noexcept { return m_led_front_1; } const boost::shared_ptr<LedWidget> GetLedFront2() noexcept { return m_led_front_2; } const boost::shared_ptr<LedWidget> GetLedFront3() noexcept { return m_led_front_3; } const boost::shared_ptr<LedWidget> GetLedTopFront() noexcept { return m_led_top_front; } const boost::shared_ptr<LedWidget> GetLedTopMiddle() noexcept { return m_led_top_middle; } const boost::shared_ptr<LedWidget> GetLedTopBack() noexcept { return m_led_top_back; } const boost::shared_ptr<ToggleButtonWidget> GetToggleButton() noexcept { return m_toggle_button; } const boost::shared_ptr<const DialWidget> GetDialBack() const noexcept { return m_dial_back; } const boost::shared_ptr<const DialWidget> GetDialFront() const noexcept { return m_dial_front; } const boost::shared_ptr<const LedWidget> GetLedBack1() const noexcept { return m_led_back_1; } const boost::shared_ptr<const LedWidget> GetLedBack2() const noexcept { return m_led_back_2; } const boost::shared_ptr<const LedWidget> GetLedBack3() const noexcept { return m_led_back_3; } const boost::shared_ptr<const LedWidget> GetLedFront1() const noexcept { return m_led_front_1; } const boost::shared_ptr<const LedWidget> GetLedFront2() const noexcept { return m_led_front_2; } const boost::shared_ptr<const LedWidget> GetLedFront3() const noexcept { return m_led_front_3; } const boost::shared_ptr<const LedWidget> GetLedTopFront() const noexcept { return m_led_top_front; } const boost::shared_ptr<const LedWidget> GetLedTopMiddle() const noexcept { return m_led_top_middle; } const boost::shared_ptr<const LedWidget> GetLedTopBack() const noexcept { return m_led_top_back; } const boost::shared_ptr<const ToggleButtonWidget> GetToggleButton() const noexcept { return m_toggle_button; } static std::string GetVersion() noexcept; static std::vector<std::string> GetVersionHistory() noexcept; ///Convert the MysteryMachine to a TextCanvas /* +--------------------------------------------------------+ | *** *** *** ____ | |** | ** **hhh** **MMM** | | *** | |* | * *hhhhh* *MMMMM* |____| **MMM** | |* | * *hhhhh* *MMMMM* |____| *MMMMM* | |* * *hhhhh* *MMMMM* *MMMMM* | | * * *** *MMM* *** *MMMMM* | | *** **MMM** *** **MMM** *** | | *MMMMM* *MMMMM* **MMM** | | *MMMMM* *MMMMM* *MMMMM* | | *MMMMM* *MMMMM* *MMMMM* | | *** *MMM* *** *MMMMM* | | **MMM** *** **MMM** *** *** | | *MMMMM* *MMMMM* **hhh** ** | ** | | *MMMMM* *MMMMM* *hhhhh* * | * | | *MMMMM* *MMMMM* *hhhhh* * | * | | *MMM* *MMM* *hhhhh* * * | | *** *** *hhh* * * | | *** *** | +--------------------------------------------------------+ */ const boost::shared_ptr<TextCanvas> ToTextCanvas() const noexcept; private: virtual ~MysteryMachine() noexcept {} friend void boost::checked_delete<>(MysteryMachine*); boost::shared_ptr<DialWidget> m_dial_back; boost::shared_ptr<DialWidget> m_dial_front; boost::shared_ptr<LedWidget> m_led_front_1; boost::shared_ptr<LedWidget> m_led_front_2; boost::shared_ptr<LedWidget> m_led_front_3; boost::shared_ptr<LedWidget> m_led_back_1; boost::shared_ptr<LedWidget> m_led_back_2; boost::shared_ptr<LedWidget> m_led_back_3; boost::shared_ptr<LedWidget> m_led_top_front; boost::shared_ptr<LedWidget> m_led_top_middle; boost::shared_ptr<LedWidget> m_led_top_back; boost::shared_ptr<ToggleButtonWidget> m_toggle_button; #ifndef NDEBUG static void Test() noexcept; #endif void Update() noexcept; friend std::ostream& operator<<(std::ostream& os, const MysteryMachine& machine) noexcept; }; std::ostream& operator<<(std::ostream& os, const MysteryMachine& machine) noexcept; } //~namespace ribi #endif // MYSTERYMACHINE_H
./CppMysteryMachine/mysterymachine.cpp
//--------------------------------------------------------------------------- /* MysteryMachine, my mystery machine class Copyright 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/CppMysteryMachine.htm //--------------------------------------------------------------------------- #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Weffc++" #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #include "mysterymachine.h" #include <boost/lexical_cast.hpp> #include "dial.h" #include "dialwidget.h" #include "led.h" #include "ledwidget.h" #include "textcanvas.h" #include "testtimer.h" #include "togglebutton.h" #include "togglebuttonwidget.h" #include "trace.h" #pragma GCC diagnostic pop ribi::MysteryMachine::MysteryMachine() noexcept : m_dial_back(new DialWidget), m_dial_front(new DialWidget), m_led_front_1(new LedWidget(0,0,32,32,1.0,255, 0, 0)), m_led_front_2(new LedWidget(0,0,32,32,0.0, 0,255, 0)), m_led_front_3(new LedWidget(0,0,32,32,0.0, 0, 0,255)), m_led_back_1(new LedWidget(0,0,32,32,1.0,255, 0, 0)), m_led_back_2(new LedWidget(0,0,32,32,0.0, 0,255, 0)), m_led_back_3(new LedWidget(0,0,32,32,0.0, 0, 0,255)), m_led_top_front( new LedWidget(0,0,32,32,0.0,255,0,0)), m_led_top_middle(new LedWidget(0,0,32,32,0.0,255,0,0)), m_led_top_back( new LedWidget(0,0,32,32,0.0,255,0,0)), m_toggle_button(new ToggleButtonWidget) { #ifndef NDEBUG Test(); #endif m_dial_back->GetDial()->m_signal_position_changed.connect(boost::bind( &ribi::MysteryMachine::Update,this)); m_dial_front->GetDial()->m_signal_position_changed.connect(boost::bind( &ribi::MysteryMachine::Update,this)); m_toggle_button->GetToggleButton()->m_signal_toggled.connect(boost::bind( &ribi::MysteryMachine::Update,this)); Update(); } std::string ribi::MysteryMachine::GetVersion() noexcept { return "1.2"; } std::vector<std::string> ribi::MysteryMachine::GetVersionHistory() noexcept { return { "2011-04-10: Version 1.0: initial version", "2011-08-20: Version 1.1: added operator<<", "2014-02-28: Version 1.2: added ToTextCanvas", }; } #ifndef NDEBUG void ribi::MysteryMachine::Test() noexcept { { static bool is_tested{false}; if (is_tested) return; is_tested = true; } const TestTimer test_timer(__func__,__FILE__,1.0); MysteryMachine m; assert(!m.GetVersion().empty()); } #endif const boost::shared_ptr<ribi::TextCanvas> ribi::MysteryMachine::ToTextCanvas() const noexcept { const int w = 58; const int h = 20; boost::shared_ptr<TextCanvas> canvas { new TextCanvas(w,h) }; //Create the edges { canvas->PutText(0,0,std::string(w,'-')); canvas->PutText(0,h - 1,std::string(w,'-')); for (int y=0; y!=h; ++y) { canvas->PutChar(0,y,'|'); canvas->PutChar(w-1,y,'|'); } canvas->PutChar( 0,0 ,'+'); canvas->PutChar( 0,h-1,'+'); canvas->PutChar(w-1,0 ,'+'); canvas->PutChar(w-1,h-1,'+'); } //Put front at left canvas->PutCanvas(1,1,m_dial_front->ToTextCanvas(3)); canvas->PutCanvas(49,12,m_dial_back->ToTextCanvas(3)); canvas->PutCanvas(9,1,m_led_front_1->ToCanvas(3)); canvas->PutCanvas(9,6,m_led_front_2->ToCanvas(3)); canvas->PutCanvas(9,11,m_led_front_3->ToCanvas(3)); canvas->PutCanvas(17,1,m_led_top_front->ToCanvas(3)); canvas->PutCanvas(25,6,m_led_top_middle->ToCanvas(3)); canvas->PutCanvas(33,11,m_led_top_back->ToCanvas(3)); canvas->PutCanvas(41,2,m_led_back_3->ToCanvas(3)); canvas->PutCanvas(41,7,m_led_back_2->ToCanvas(3)); canvas->PutCanvas(41,12,m_led_back_1->ToCanvas(3)); canvas->PutCanvas(26,1,m_toggle_button->ToTextCanvas(6,4)); return canvas; } void ribi::MysteryMachine::Update() noexcept { const int back = static_cast<int>(GetDialBack()->GetDial()->GetPosition() * 12.0) % 3; const int front = static_cast<int>(GetDialFront()->GetDial()->GetPosition() * 12.0) % 3; int top = (GetToggleButton()->GetToggleButton()->IsPressed() ? (1 + front - back + 3) % 3 : -1); assert(front >= 0); assert(front < 3); assert(back >= 0); assert(back < 3); assert(top >= -1); //-1 denotes off assert(top < 3); m_led_front_1->GetLed()->SetIntensity(front == 0 ? 1.0 : 0.0); m_led_front_2->GetLed()->SetIntensity(front == 1 ? 1.0 : 0.0); m_led_front_3->GetLed()->SetIntensity(front == 2 ? 1.0 : 0.0); m_led_back_1->GetLed()->SetIntensity(back == 0 ? 1.0 : 0.0); m_led_back_2->GetLed()->SetIntensity(back == 1 ? 1.0 : 0.0); m_led_back_3->GetLed()->SetIntensity(back == 2 ? 1.0 : 0.0); m_led_top_front->GetLed()->SetIntensity( top == 0 ? 1.0 : 0.0); m_led_top_middle->GetLed()->SetIntensity(top == 1 ? 1.0 : 0.0); m_led_top_back->GetLed()->SetIntensity( top == 2 ? 1.0 : 0.0); } std::ostream& ribi::operator<<(std::ostream& os, const MysteryMachine& machine) noexcept { os << "<MysteryMachine>" << "<dial_back>" << *machine.m_dial_back << "</dial_back>" << "<dial_front>" << *machine.m_dial_front << "</dial_front>" << "<led_back_1>" << *machine.m_led_back_1 << "</led_back_1>" << "<led_back_2>" << *machine.m_led_back_2 << "</led_back_2>" << "<led_back_3>" << *machine.m_led_back_3 << "</led_back_3>" << "<led_front_1>" << *machine.m_led_front_1 << "</led_front_1>" << "<led_front_2>" << *machine.m_led_front_2 << "</led_front_2>" << "<led_front_3>" << *machine.m_led_front_3 << "<led_front_3>" << "<led_top_back>" << *machine.m_led_top_back << "</led_top_back>" << "<led_top_front>" << *machine.m_led_top_front << "</led_top_front>" << "<led_top_middle>" << *machine.m_led_top_middle << "</led_top_middle>" << "<toggle_button>" << *machine.m_toggle_button << "</toggle_button>" << "</MysteryMachine>"; return os; }