diff --git a/AGENTS.md b/AGENTS.md index bdcd00c..48bd4a7 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -10,8 +10,22 @@ is added, document its layout under "Source Layout". ## Build System -No build system is set up yet. When one is added for the course examples, -document its configure, build, and test commands here. +CMake (3.21+) with Ninja. + +```sh +cmake -B build -G Ninja +cmake --build build +``` + +Course exercises in `cmat/` are excluded from the default build; build one by +target name, e.g.: + +```sh +cmake --build build --target Ex11 +``` + +Tests (optional): configure with `-DBUILD_TESTING=ON`, then run `ninja check` in +the build directory. ## Coding Conventions @@ -33,23 +47,23 @@ document its configure, build, and test commands here. - **Naming:** `SCREAMING_SNAKE_CASE` only for macros and constants - **Header extensions:** C++ headers use `.hpp`, C headers use `.h` - Include order: - 1. C++ standard library headers (``, ``, etc.) - 2. _(blank line)_ - 3. C standard library headers (``, ``, etc.) - 4. _(blank line)_ - 5. OS-specific headers (Windows API, POSIX, etc.) - 6. _(blank line)_ - 7. Third-party dependencies (`"fmt/core.h"`, etc.) - 8. _(blank line)_ - 9. Local/project headers + 1. C++ standard library headers (``, ``, etc.) + 2. _(blank line)_ + 3. C standard library headers (``, ``, etc.) + 4. _(blank line)_ + 5. OS-specific headers (Windows API, POSIX, etc.) + 6. _(blank line)_ + 7. Third-party dependencies (`"fmt/core.h"`, etc.) + 8. _(blank line)_ + 9. Local/project headers ## Shell Scripts - Always use `#!/bin/sh` shebang for shell scripts - Scripts must be POSIX compliant (no bashisms) - When providing commands to users: - - Windows/PowerShell: use `` ` `` for line continuation - - Unix/Linux/macOS: use `\` for line continuation + - Windows/PowerShell: use `` ` `` for line continuation + - Unix/Linux/macOS: use `\` for line continuation ## Commit Messages @@ -84,7 +98,7 @@ releases of the course material. - All markdown files are formatted with **oxfmt** - **Always run `npx oxfmt --write .` after editing any markdown file** - - This is mandatory. Do not skip it. Run it before finishing your response + - This is mandatory. Do not skip it. Run it before finishing your response - Use `npx oxfmt --check .` to verify formatting before committing - Config is in `.oxfmtrc.json` at the project root - Do not manually fight the formatter. Let oxfmt handle spacing, line breaks, @@ -98,10 +112,25 @@ cppcourse/ README.md # Project docs .oxfmtrc.json # oxfmt config .agents/ # Agent skills (git workflow) + CMakeLists.txt # Build system entry point + deps/ # CMake helper modules (platform, flags, Find* deps) + cmat/ # Course material: exercises and solutions + 397/ # Original copy of the course material (reference only) ``` -Course content (lectures, exercises, examples) will be added as the course is -developed. Document the layout here when it takes shape. +`cmat/` layout: + +- `Ex*/`: exercise starting points. Some intentionally contain bugs that + students fix during the course; their targets fail to compile (or misbehave at + runtime) until fixed. +- `SolutionEx*/`: working solutions of the exercises. +- `DOS_Unix/`: platform Keyboard/Screen implementations shared by the GUI + exercises. The DOS variants are Windows-specific; on Unix-like systems the + curses variants are built instead (linked as the `dos_unix` library). +- Each exercise directory holds a `CMakeLists.txt` that defines its target via + `cmat_add_exercise()` (see `cmat/CMakeLists.txt`). Exercises that need a + missing dependency (e.g. Boost) are reported as not available at configure + time and skipped. ## Behavioral Guidelines diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c0356e..f89e124 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,6 +22,9 @@ target_compile_options(hello PRIVATE ${BASE_OPTIONS}) target_compile_definitions(hello PRIVATE ${BASE_DEFINITIONS}) target_link_libraries(hello PRIVATE fmt::fmt) +# Course material (exercises and solutions) +add_subdirectory(cmat) + option(BUILD_TESTING OFF "Build Unity/CMock test suites") if (BUILD_TESTING AND NOT IS_EMSCRIPTEN) set(CMAKE_SKIP_TEST_ALL_DEPENDENCY FALSE) diff --git a/cmat/CMakeLists.txt b/cmat/CMakeLists.txt new file mode 100644 index 0000000..bc6e94f --- /dev/null +++ b/cmat/CMakeLists.txt @@ -0,0 +1,145 @@ +# ============================================================================== +# Course Material (cmat) +# ============================================================================== +# Exercises copied from 397. Each exercise directory holds its own +# CMakeLists.txt (included below) and defines one executable target with the +# directory's name via cmat_add_exercise(). +# +# Targets are excluded from the default build; build one by name: +# cmake --build build --target Ex11 +# +# Some exercises intentionally contain bugs that students fix during the +# course. Those targets fail to compile (or misbehave at runtime) until the +# bug is fixed, which is expected. + +# ------------------------------------------------------------------------------ +# Compile options +# ------------------------------------------------------------------------------ +# Legacy course material: keep the project's warning flags but drop -Werror; +# these old sources produce warnings that must not block the build. +set(CMAT_OPTIONS "") +foreach (opt IN LISTS BASE_OPTIONS) + if (NOT opt STREQUAL "-Werror" AND NOT opt STREQUAL "/WX") + list(APPEND CMAT_OPTIONS "${opt}") + endif() +endforeach() + +# ------------------------------------------------------------------------------ +# Keyboard/Screen support (DOS_Unix/) +# ------------------------------------------------------------------------------ +# GUI exercises use the Keyboard/Screen abstraction from DOS_Unix/. The DOS +# variants (Keyboard_DOS.cpp, Screen_DOS.cpp) are Windows-specific and are not +# compiled. On Unix-like systems the curses variants provide the same +# interface instead. + +set(CMAT_GUI_LIB "") +if (IS_LINUX OR IS_MACOS) + find_package(Curses QUIET) + if (Curses_FOUND) + add_library(dos_unix STATIC + DOS_Unix/CursesObj.cpp + DOS_Unix/Keyboard_Unix.cpp + DOS_Unix/Screen_Unix.cpp + ) + set_target_properties(dos_unix PROPERTIES EXCLUDE_FROM_ALL TRUE) + target_include_directories(dos_unix PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/DOS_Unix") + if (CURSES_INCLUDE_DIRS) + target_include_directories(dos_unix SYSTEM PUBLIC ${CURSES_INCLUDE_DIRS}) + endif() + target_link_libraries(dos_unix PUBLIC ${CURSES_LIBRARIES}) + set(CMAT_GUI_LIB dos_unix) + else() + message(STATUS "Curses not found; GUI exercises are unavailable") + endif() +else() + # Windows: only the DOS keyboard/screen implementations exist, which are + # Windows-specific; there is nothing portable to build with. +endif() + +# Exercises using Boost.Serialization (system install; not fetched). CONFIG +# mode uses Boost's own CMake package, since the FindBoost module was removed +# in CMake 4. +find_package(Boost CONFIG QUIET COMPONENTS serialization) + +# ------------------------------------------------------------------------------ +# Target helpers +# ------------------------------------------------------------------------------ +# cmat_add_exercise( [GUI] [BOOST] ...) +# +# Creates an executable target from the given sources. GUI links the +# Keyboard/Screen support library; BOOST links Boost.Serialization. If a +# required dependency is missing, the exercise is reported as not available +# and no target is created. +function(cmat_add_exercise name) + cmake_parse_arguments(ARG "GUI;BOOST" "" "SOURCES" ${ARGN}) + if (ARG_GUI AND NOT CMAT_GUI_LIB) + cmat_unavailable(${name} "requires the Keyboard/Screen abstraction, which is Windows-specific (DOS_Unix/)") + return() + endif() + if (ARG_BOOST AND NOT Boost_FOUND) + cmat_unavailable(${name} "requires Boost.Serialization") + return() + endif() + add_executable(${name} ${ARG_SOURCES}) + target_compile_features(${name} PRIVATE cxx_std_23) + target_compile_options(${name} PRIVATE ${CMAT_OPTIONS}) + set_target_properties(${name} PROPERTIES EXCLUDE_FROM_ALL TRUE) + if (ARG_GUI) + target_link_libraries(${name} PRIVATE ${CMAT_GUI_LIB}) + endif() + if (ARG_BOOST) + target_link_libraries(${name} PRIVATE Boost::serialization) + endif() +endfunction() + +# cmat_unavailable( ) +# +# Reports that an exercise cannot be built on this platform. A warning (not a +# hard error) is used so the configuration completes and all other exercises +# remain available. +function(cmat_unavailable name reason) + message(WARNING "Exercise ${name} is not available on this platform: ${reason}") +endfunction() + +# ------------------------------------------------------------------------------ +# Exercises +# ------------------------------------------------------------------------------ +add_subdirectory(Ex11) +add_subdirectory(Ex11bug) +add_subdirectory(Ex21) +add_subdirectory(Ex22) +add_subdirectory(Ex31) +add_subdirectory(Ex32) +add_subdirectory(Ex33) +add_subdirectory(Ex41) +add_subdirectory(Ex42) +add_subdirectory(Ex51) +add_subdirectory(Ex61) +add_subdirectory(Ex62) +add_subdirectory(Ex71) +add_subdirectory(Ex71A) +add_subdirectory(SolutionEx11bug) +add_subdirectory(SolutionEx21) +add_subdirectory(SolutionEx22) +add_subdirectory(SolutionEx22Bonus) +add_subdirectory(SolutionEx31) +add_subdirectory(SolutionEx31Bonus) +add_subdirectory(SolutionEx32) +add_subdirectory(SolutionEx33) +add_subdirectory(SolutionEx33Bonus) +add_subdirectory(SolutionEx41) +add_subdirectory(SolutionEx41Bonus) +add_subdirectory(SolutionEx42) +add_subdirectory(SolutionEx51) +add_subdirectory(SolutionEx51Bonus2) +add_subdirectory(SolutionEx61InterimSolution) +add_subdirectory(SolutionEx61Part1) +add_subdirectory(SolutionEx61Part2) +add_subdirectory(SolutionEx61Part2Bonus) +add_subdirectory(SolutionEx62) +add_subdirectory(SolutionEx62Bonus) +add_subdirectory(SolutionEx62Bonus2) +add_subdirectory(SolutionEx71) +add_subdirectory(SolutionEx71A) +add_subdirectory(SolutionEx71ABonus) +add_subdirectory(SolutionEx71Bonus) diff --git a/cmat/DOS_Unix/CursesObj.cpp b/cmat/DOS_Unix/CursesObj.cpp new file mode 100644 index 0000000..1a002c1 --- /dev/null +++ b/cmat/DOS_Unix/CursesObj.cpp @@ -0,0 +1,51 @@ +#include "CursesObj.h" +#include "curses.h" + +CursesObj::CursesObj() { + // Colours 0 to 7 are defined by curses. But we need grey as well + // Define a suitable constant here (and create the colour later) + const int COLOR_GREY = 8; + + initscr(); /* initialize the curses library */ + nonl(); /* tell curses not to do NL->CR/NL on output */ + cbreak(); /* take input chars one at a time, no wait for \n */ + nodelay(stdscr, FALSE); + noecho(); /* echo input - in color */ + curs_set(0); + intrflush(stdscr, FALSE); + + if (has_colors()) { + start_color(); + + /* + * Simple color assignment, often all we need. Color pair 0 cannot + * be redefined. This example uses the same value for the color + * pair as for the foreground color, though of course that is not + * necessary: + */ + init_pair(1, COLOR_RED, COLOR_BLACK); + init_pair(2, COLOR_GREEN, COLOR_BLACK); + init_pair(3, COLOR_YELLOW, COLOR_BLACK); + init_pair(4, COLOR_BLUE, COLOR_BLACK); + init_pair(5, COLOR_CYAN, COLOR_BLACK); + init_pair(6, COLOR_MAGENTA, COLOR_BLACK); + init_pair(7, COLOR_WHITE, COLOR_BLACK); + + // Create 'grey' and then use it as foreground colour + init_color(8, 1, 333, 333); + + init_pair(8, COLOR_GREY, COLOR_BLACK); + } +} + +CursesObj::~CursesObj() { + clear(); + refresh(); + endwin(); +} + +CursesObj &CursesObj::Instance() { + static CursesObj instance; + + return instance; +} diff --git a/cmat/DOS_Unix/CursesObj.h b/cmat/DOS_Unix/CursesObj.h new file mode 100644 index 0000000..21b64c8 --- /dev/null +++ b/cmat/DOS_Unix/CursesObj.h @@ -0,0 +1,13 @@ +#ifndef CURSESOBJ_H +#define CURSESOBJ_H + +class CursesObj { + private: + CursesObj(); + ~CursesObj(); + + public: + static CursesObj &Instance(); +}; + +#endif diff --git a/cmat/DOS_Unix/Keyboard.h b/cmat/DOS_Unix/Keyboard.h new file mode 100644 index 0000000..f2d3582 --- /dev/null +++ b/cmat/DOS_Unix/Keyboard.h @@ -0,0 +1,13 @@ +#ifndef KEYBOARD_H +#define KEYBOARD_H + +class Keyboard { + public: + Keyboard(); + bool isCharAvail(); + char getChar(); + + private: +}; + +#endif diff --git a/cmat/DOS_Unix/Keyboard_DOS.cpp b/cmat/DOS_Unix/Keyboard_DOS.cpp new file mode 100644 index 0000000..3513d30 --- /dev/null +++ b/cmat/DOS_Unix/Keyboard_DOS.cpp @@ -0,0 +1,13 @@ +#include "Keyboard.h" +#include + +Keyboard::Keyboard() {} + +bool Keyboard::isCharAvail() { + // 'return kbhit()' is sufficient, but Microsoft + // issues a warning 'coercing int to bool' and encourages + // the use of '!=0' to eliminate it + return _kbhit() != 0; +} + +char Keyboard::getChar() { return _getch(); } \ No newline at end of file diff --git a/cmat/DOS_Unix/Keyboard_Unix.cpp b/cmat/DOS_Unix/Keyboard_Unix.cpp new file mode 100644 index 0000000..ff6b8ee --- /dev/null +++ b/cmat/DOS_Unix/Keyboard_Unix.cpp @@ -0,0 +1,28 @@ +#include "Keyboard.h" +#include "CursesObj.h" +#include "curses.h" + +Keyboard::Keyboard() { + CursesObj::Instance(); // Force initialization + + nodelay(stdscr, FALSE); // Default to block on getch +} + +bool Keyboard::isCharAvail() { + nodelay(stdscr, TRUE); // getch must not block for this polling + + int c; // DON'T make this 'char'; 'ERR' may be an 'int' - on some systems, + // just like 'EOF' + + bool charWaiting = (c = getch()) != ERR; // If getch returns ERR, no char + // waiting, otherwise, next char is + // returned + + if (charWaiting) + ungetch(c); // We got a char; put it back! (We just want to know if there + // is one waiting.) + + return charWaiting; +} + +char Keyboard::getChar() { return getch(); } diff --git a/cmat/DOS_Unix/Screen.h b/cmat/DOS_Unix/Screen.h new file mode 100644 index 0000000..4b692a0 --- /dev/null +++ b/cmat/DOS_Unix/Screen.h @@ -0,0 +1,19 @@ +#ifndef SCREEN_H +#define SCREEN_H + +#include + +namespace Screen { +const int BLACK = 0; +const int GRAY = 8; // FOREGROUND_INTENSITY; +const int BLUE = 9; // FOREGROUND_RED|FOREGROUND_INTENSITY +const int GREEN = 10; // FOREGROUND_GREEN|FOREGROUND_INTENSITY; +const int RED = 12; // FOREGROUND_RED|FOREGROUND_INTENSITY +const int YELLOW = RED | GREEN; +const int WHITE = RED | GREEN | BLUE; +const int BACKGROUND = 128; // OR (|) with the color value for gray background + +void write(std::string s, int x, int y, int color); +}; + +#endif diff --git a/cmat/DOS_Unix/Screen_DOS.cpp b/cmat/DOS_Unix/Screen_DOS.cpp new file mode 100644 index 0000000..8cdfc13 --- /dev/null +++ b/cmat/DOS_Unix/Screen_DOS.cpp @@ -0,0 +1,32 @@ +#include +#include +#include +using std::string; + +#include "Screen.h" + +namespace { +HANDLE hStdout = 0; +} + +void Screen::write(string s, int x, int y, int color) { + if (hStdout == 0) { + hStdout = GetStdHandle(STD_OUTPUT_HANDLE); + } + + COORD screenPos; + screenPos.X = x; + screenPos.Y = y; + + unsigned long ln; + + static unsigned short attrib[80]; + + for (unsigned int i = 0; i < s.length(); ++i) { + attrib[i] = color; + } + + WriteConsoleOutputAttribute(hStdout, attrib, s.length(), screenPos, &ln); + + WriteConsoleOutputCharacter(hStdout, s.c_str(), s.length(), screenPos, &ln); +} diff --git a/cmat/DOS_Unix/Screen_Unix.cpp b/cmat/DOS_Unix/Screen_Unix.cpp new file mode 100644 index 0000000..b251516 --- /dev/null +++ b/cmat/DOS_Unix/Screen_Unix.cpp @@ -0,0 +1,66 @@ +#include "Screen.h" +#include "CursesObj.h" +#include "curses.h" +#include +#include + +// Forward declarations +int ConvertColour(int); + +void Screen::write(std::string s, int x, int y, int color) { + CursesObj::Instance(); // Force initialization + + if (color >= 128) + color -= 128; // Remove gray background - does not work on Linux + + std::string blank_str(s.length(), ' '); + + mvaddstr(y, x, blank_str.c_str()); // Always draw a black + refresh(); + + if (color != Screen::BLACK) // If colour is not black, also draw the color + { + printf("\e[%i;3%im", 0, ConvertColour(color)); + + fflush(stdout); + + mvaddstr(y, x, s.c_str()); + refresh(); + } +} + +typedef struct { + int pelio_colour; + int curses_color_pair; +} Entry; + +// Entry null pointer +const Entry *ENTRY_NP = (Entry *)0; + +typedef Entry Table[]; + +Table ColourTable = {{Screen::GRAY, 8}, // Display as white + {Screen::BLUE, 4}, {Screen::GREEN, 2}, {Screen::RED, 1}, {Screen::YELLOW, 3}, {Screen::WHITE, 7}}; + +const int LEN_TAB = sizeof ColourTable / sizeof ColourTable[0]; + +const Entry *TabSearch(Table t, int nEntries, int colour) { + Entry *p; + + for (p = t; p < t + nEntries && p->pelio_colour != colour; p++) + ; // EMPTY BODY + + return (p < t + nEntries) ? p : ENTRY_NP; +} + +int ConvertColour(int colour) { + int result = 0; + const Entry *p; + + p = TabSearch(ColourTable, LEN_TAB, colour); // Search the table for the colour specified + + if (p != ENTRY_NP) // If the colour is in the table ... + result = p->curses_color_pair; // ... return the 'int' for the associated + // curses colour pair + return result; +} diff --git a/cmat/Ex11/CMakeLists.txt b/cmat/Ex11/CMakeLists.txt new file mode 100644 index 0000000..a5ed154 --- /dev/null +++ b/cmat/Ex11/CMakeLists.txt @@ -0,0 +1,13 @@ +# Ex11 + +cmat_add_exercise(Ex11 + GUI + SOURCES + Light.cpp + main.cpp + Pelican.cpp + PelicanTimer.cpp + Pole.cpp + Timer.cpp + TimerSet.cpp +) diff --git a/cmat/Ex11/Debug/pelican.obj.enc b/cmat/Ex11/Debug/pelican.obj.enc new file mode 100644 index 0000000..c925196 Binary files /dev/null and b/cmat/Ex11/Debug/pelican.obj.enc differ diff --git a/cmat/Ex11/Ex11.sln b/cmat/Ex11/Ex11.sln new file mode 100644 index 0000000..50580c0 --- /dev/null +++ b/cmat/Ex11/Ex11.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.24720.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ex11", "Ex11.vcxproj", "{7195CF47-386C-4BF5-988B-B47FE9177122}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x86 = Debug|x86 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7195CF47-386C-4BF5-988B-B47FE9177122}.Debug|x86.ActiveCfg = Debug|Win32 + {7195CF47-386C-4BF5-988B-B47FE9177122}.Debug|x86.Build.0 = Debug|Win32 + {7195CF47-386C-4BF5-988B-B47FE9177122}.Release|x86.ActiveCfg = Release|Win32 + {7195CF47-386C-4BF5-988B-B47FE9177122}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/cmat/Ex11/Ex11.suo b/cmat/Ex11/Ex11.suo new file mode 100644 index 0000000..11c06f2 Binary files /dev/null and b/cmat/Ex11/Ex11.suo differ diff --git a/cmat/Ex11/Ex11.vcproj b/cmat/Ex11/Ex11.vcproj new file mode 100644 index 0000000..f350ab1 --- /dev/null +++ b/cmat/Ex11/Ex11.vcproj @@ -0,0 +1,185 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cmat/Ex11/Ex11.vcxproj b/cmat/Ex11/Ex11.vcxproj new file mode 100644 index 0000000..6f2f04b --- /dev/null +++ b/cmat/Ex11/Ex11.vcxproj @@ -0,0 +1,144 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + "$/Course/397/Ex11", DAAAAAAA + . + {7195CF47-386C-4BF5-988B-B47FE9177122} + + + + Application + v140 + false + MultiByte + + + Application + v140 + false + MultiByte + + + + + + + + + + + + + <_ProjectFileVersion>14.0.24730.2 + + + .\Release\ + .\Release\ + false + + + .\Debug\ + .\Debug\ + true + + + + OnlyExplicitInline + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + true + + .\Release/Ex11.pch + .\Release/ + .\Release/ + .\Release/ + Level3 + true + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Release/Ex11.exe + true + .\Release/Ex11.pdb + Console + + + .\Release/Ex11.tlb + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + true + + .\Debug/Ex11.pch + .\Debug/ + .\Debug/ + .\Debug/ + Level3 + true + EditAndContinue + C:\course\397\DOS_Unix;%(AdditionalIncludeDirectories) + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Debug/Ex11.exe + true + true + .\Debug/Ex11.pdb + Console + false + + + .\Debug/Ex11.tlb + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cmat/Ex11/Ex11.vcxproj.filters b/cmat/Ex11/Ex11.vcxproj.filters new file mode 100644 index 0000000..c323e5a --- /dev/null +++ b/cmat/Ex11/Ex11.vcxproj.filters @@ -0,0 +1,71 @@ + + + + + {94250b16-82d1-4f12-8890-9942de501588} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {3c44361f-9161-4807-9c8e-ca3dec754b19} + h;hpp;hxx;hm;inl + + + {33696874-76e6-4fed-9fae-20dbad38a143} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + DOS_Unix + + + Header Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + DOS_Unix + + + DOS_Unix + + + \ No newline at end of file diff --git a/cmat/Ex11/Ex11.vcxproj.user b/cmat/Ex11/Ex11.vcxproj.user new file mode 100644 index 0000000..695b5c7 --- /dev/null +++ b/cmat/Ex11/Ex11.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cmat/Ex11/Light.cpp b/cmat/Ex11/Light.cpp new file mode 100644 index 0000000..ef942c3 --- /dev/null +++ b/cmat/Ex11/Light.cpp @@ -0,0 +1,20 @@ +#include "Light.h" +#include "CursesObj.h" +#include "Pelican.h" +#include "Screen.h" +#include + +Light::Light(std::string name, int x, int y, int color) : x(x), y(y), c(color), name(name) {} + +Light::~Light() { + std::cout << "Deleting light (" << name << ", " << x << ", " << y << ", " << c << ")" << std::endl; + std::cout.flush(); +} + +void Light::set(LightState newState) { + state = newState; + Screen::write(name.c_str(), x, y, state == FLASH ? (128 + c) : (state == OFF ? 0 : c)); + // 128 + color was used to make a character flash (but not any more) +} + +Light::LightState Light::get(void) { return state; } diff --git a/cmat/Ex11/Light.h b/cmat/Ex11/Light.h new file mode 100644 index 0000000..03adf9a --- /dev/null +++ b/cmat/Ex11/Light.h @@ -0,0 +1,30 @@ +// ====================================================== +// +// Represents a light, implemented as a string written +// to a console window +// +// ====================================================== + +#ifndef LIGHT_H +#define LIGHT_H + +#include + +class Light { + public: + Light(std::string name, int x, int y, int color); + ~Light(); + + enum LightState { ON, OFF, FLASH }; + + void set(LightState new_state); + LightState get(void); + + private: + int c; // light colour + int x, y; + std::string name; + LightState state; +}; + +#endif diff --git a/cmat/Ex11/Pelican.cpp b/cmat/Ex11/Pelican.cpp new file mode 100644 index 0000000..1883ae4 --- /dev/null +++ b/cmat/Ex11/Pelican.cpp @@ -0,0 +1,64 @@ +#include "Pelican.h" +#include "PelicanTimer.h" +#include "Pole.h" + +Pelican::Pelican(int x, int y) + : pressed(false), RED_TIME(4), YELLOW_TIME(2), GREEN_TIME(3), FLASH_TIME(5), myPole(new Pole(x, y)), + state(GREEN_IDLE) { + myTimer = new PelicanTimer(*this, &Pelican::timerExpired); + + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed()); +} + +Pelican::~Pelican() { delete myPole; } + +void Pelican::press(void) { + if (state == GREEN_IDLE) { + state = YELLOW_STATE; + myTimer->timeoutRequest(YELLOW_TIME); + pressed = true; + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed()); + } else if (state != RED_STATE) { + pressed = true; + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed()); + } +} + +void Pelican::timerExpired(void) { + switch (state) { + case RED_STATE: + state = YELLOW_FLASHING; + myTimer->timeoutRequest(FLASH_TIME); + break; + + case YELLOW_FLASHING: + state = GREEN_TIMING; + myTimer->timeoutRequest(GREEN_TIME); + break; + + case GREEN_TIMING: + if (pressed) { + state = YELLOW_STATE; + myTimer->timeoutRequest(YELLOW_TIME); + } else { + state = GREEN_IDLE; + } + break; + + case GREEN_IDLE: + // should never happen + break; + + case YELLOW_STATE: + state = RED_STATE; + pressed = false; + myTimer->timeoutRequest(RED_TIME); + break; + } + + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed()); +} diff --git a/cmat/Ex11/Pelican.h b/cmat/Ex11/Pelican.h new file mode 100644 index 0000000..5cb813b --- /dev/null +++ b/cmat/Ex11/Pelican.h @@ -0,0 +1,54 @@ +// ====================================================== +// +// Represents a Pelican crossing +// +// ====================================================== + +#ifndef PELICAN_H +#define PELICAN_H + +class PelicanTimer; +class Pole; + +class Pelican { + public: + Pelican(int x, int y); + ~Pelican(); + + // call when the WAIT button has been pressed + void press(void); + + // states that a Pelican can be in + enum PelicanState { RED_STATE, YELLOW_FLASHING, GREEN_TIMING, GREEN_IDLE, YELLOW_STATE }; + + bool isPressed() const { return pressed; } + + PelicanState getState() const { return state; } + + private: + // state that this Pelican is in + PelicanState state; + + // called by PeleicanTimer when the lights need to change + void timerExpired(void); + + const unsigned int RED_TIME; + const unsigned int YELLOW_TIME; + const unsigned int GREEN_TIME; + const unsigned int FLASH_TIME; + + // indicates whether the WAIT light should be on + bool pressed; + + Pole *myPole; + + // Timer that indicates when the lights should change + PelicanTimer *myTimer; + + private: + // prevent general use of copy ctor and operator= + Pelican(const Pelican &); + Pelican &operator=(const Pelican &); +}; + +#endif diff --git a/cmat/Ex11/PelicanTimer.cpp b/cmat/Ex11/PelicanTimer.cpp new file mode 100644 index 0000000..bbb0b9b --- /dev/null +++ b/cmat/Ex11/PelicanTimer.cpp @@ -0,0 +1,10 @@ + +#include "PelicanTimer.h" + +PelicanTimer::PelicanTimer(Pelican &target, TargetFunc targetFunc) : myTarget(target), myTargetFunc(targetFunc) {} + +void PelicanTimer::tick() { + if (isExpired()) { + (myTarget.*myTargetFunc)(); + } +} diff --git a/cmat/Ex11/PelicanTimer.h b/cmat/Ex11/PelicanTimer.h new file mode 100644 index 0000000..3ce25b6 --- /dev/null +++ b/cmat/Ex11/PelicanTimer.h @@ -0,0 +1,27 @@ +// ====================================================== +// +// This class specializes the Timer to enable it to +// stimulate a Pelican +// +// ====================================================== + +#ifndef PELICANTIMER_H +#define PELICANTIMER_H + +#include "Pelican.h" +#include "Timer.h" + +class PelicanTimer : public Timer { + public: + typedef void (Pelican::*TargetFunc)(); + + PelicanTimer(Pelican &target, TargetFunc targetFunc); + + virtual void tick(); + + private: + Pelican &myTarget; + TargetFunc myTargetFunc; +}; + +#endif diff --git a/cmat/Ex11/Pole.cpp b/cmat/Ex11/Pole.cpp new file mode 100644 index 0000000..4055a89 --- /dev/null +++ b/cmat/Ex11/Pole.cpp @@ -0,0 +1,59 @@ +#include "Pole.h" +#include "Screen.h" + +Pole::Pole(int x, int y) : waitLight(new Light("WAIT", x + 6, y + 12, Screen::WHITE)) { + using namespace Screen; + + lights[RED_LIGHT] = new Light("*", x + 11, y + 3, RED); + lights[RED_MAN] = new Light("*<-=", x + 6, y + 4, RED); + lights[YELLOW_LIGHT] = new Light("*", x + 11, y + 5, YELLOW); + lights[GREEN_LIGHT] = new Light("*", x + 11, y + 7, GREEN); + lights[GREEN_MAN] = new Light("*|-<", x + 6, y + 7, GREEN); + + write(" _____ ", x, ++y, GRAY); + write(" /___ /| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" | |/| ", x, ++y, GRAY); + write(" |____| | ", x, ++y, GRAY); + write(" | |/| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" |____|/ ", x, ++y, GRAY); + write(" _||__ ", x, ++y, GRAY); + write(" /___ /| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" |____|/ ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write("========||===========", x, ++y, GRAY); + write(" / || / ", x, ++y, GRAY); + write("_ /_________ /_ ", x, ++y, GRAY); + write("/ / ", x, ++y, GRAY); +} + +Pole::~Pole() { + for (int i = 0; i < sizeof lights / sizeof(lights[0]); ++i) + delete lights[i]; + delete waitLight; +} + +void Pole::setTrafficLights(Pelican::PelicanState state) { + static const Light::LightState LightStates[Pelican::YELLOW_STATE + 1][RED_MAN + 1] = { + // red yellow green green man red man + {Light::ON, Light::OFF, Light::OFF, Light::ON, Light::OFF}, // red + {Light::OFF, Light::FLASH, Light::OFF, Light::FLASH, Light::OFF}, // y flash + {Light::OFF, Light::OFF, Light::ON, Light::OFF, Light::ON}, // g time + {Light::OFF, Light::OFF, Light::ON, Light::OFF, Light::ON}, // g idle + {Light::OFF, Light::ON, Light::OFF, Light::OFF, Light::ON} // yellow + }; + + for (int i = RED_LIGHT; i <= RED_MAN; i++) { + lights[i]->set(LightStates[state][i]); + } +} + +void Pole::setWaitLight(bool pressed) { waitLight->set(pressed ? Light::ON : Light::OFF); } diff --git a/cmat/Ex11/Pole.h b/cmat/Ex11/Pole.h new file mode 100644 index 0000000..6d2a7c2 --- /dev/null +++ b/cmat/Ex11/Pole.h @@ -0,0 +1,27 @@ +// ====================================================== +// The Pole presenting the Pelican +// ====================================================== + +#ifndef POLE_H +#define POLE_H + +#include "Light.h" +#include "Pelican.h" + +class Pole { + public: + Pole(int x, int y); + ~Pole(); + + void setTrafficLights(Pelican::PelicanState state); + void setWaitLight(bool pressed); + + private: + enum LightName { RED_LIGHT, YELLOW_LIGHT, GREEN_LIGHT, GREEN_MAN, RED_MAN }; + + Light *lights[RED_MAN + 1]; + + Light *waitLight; +}; + +#endif diff --git a/cmat/Ex11/Timer.cpp b/cmat/Ex11/Timer.cpp new file mode 100644 index 0000000..f4daa3f --- /dev/null +++ b/cmat/Ex11/Timer.cpp @@ -0,0 +1,17 @@ + + +#include "Timer.h" +#include "TimerSet.h" + +void Timer::timeoutRequest(int seconds) { timeToGo = seconds; } + +Timer::Timer() : timeToGo(-1) { theTimerSet.addATimer(this); } + +bool Timer::isExpired() { + if (timeToGo > 0) { + if (--timeToGo == 0) { + return true; + } + } + return false; +} diff --git a/cmat/Ex11/Timer.h b/cmat/Ex11/Timer.h new file mode 100644 index 0000000..2deb1e1 --- /dev/null +++ b/cmat/Ex11/Timer.h @@ -0,0 +1,27 @@ +// ====================================================== +// +// A general-purpose countdown timer +// To use this class, specialize it +// and override tick() +// +// ====================================================== + +#ifndef TIMER_H +#define TIMER_H + +class Timer { + public: + Timer(); + + void timeoutRequest(int seconds); + + virtual void tick() = 0; + + protected: + bool isExpired(); + + private: + int timeToGo; +}; + +#endif diff --git a/cmat/Ex11/TimerSet.cpp b/cmat/Ex11/TimerSet.cpp new file mode 100644 index 0000000..36b9d3c --- /dev/null +++ b/cmat/Ex11/TimerSet.cpp @@ -0,0 +1,20 @@ +#include "TimerSet.h" +#include "Timer.h" + +TimerSet theTimerSet; + +// Member functions + +TimerSet::TimerSet() : timersInUse(0), previousTime(time(&previousTime)) {} + +void TimerSet::addATimer(Timer *t) { timers[timersInUse++] = t; } + +void TimerSet::pollAllTimers() { + std::time_t timeNow; + if (time(&timeNow) > previousTime) { + previousTime = timeNow; + for (int i = 0; i < timersInUse; ++i) { + timers[i]->tick(); + } + } +} diff --git a/cmat/Ex11/TimerSet.h b/cmat/Ex11/TimerSet.h new file mode 100644 index 0000000..1ea4123 --- /dev/null +++ b/cmat/Ex11/TimerSet.h @@ -0,0 +1,23 @@ +#ifndef TIMERSET_H +#define TIMERSET_H + +#include + +class Timer; + +class TimerSet { + public: + TimerSet(); + + void pollAllTimers(); + void addATimer(Timer *); + + private: + Timer *timers[40]; + int timersInUse; + std::time_t previousTime; +}; + +extern TimerSet theTimerSet; + +#endif diff --git a/cmat/Ex11/UpgradeLog.htm b/cmat/Ex11/UpgradeLog.htm new file mode 100644 index 0000000..2afb726 Binary files /dev/null and b/cmat/Ex11/UpgradeLog.htm differ diff --git a/cmat/Ex11/main.cpp b/cmat/Ex11/main.cpp new file mode 100644 index 0000000..fff22a7 --- /dev/null +++ b/cmat/Ex11/main.cpp @@ -0,0 +1,29 @@ + + +#include "Keyboard.h" +#include "Pelican.h" +#include "TimerSet.h" + +#include // provides toupper() + +int main() { + Keyboard kbd; + Pelican thePelican(30, 0); + + char c = 0; + + while (std::toupper(c) != 'Q') { // loop until 'Q' is pressed + + while (!kbd.isCharAvail()) { + theTimerSet.pollAllTimers(); // no key press to process, poll the timers + } + + c = kbd.getChar(); // get the character + if (c == ' ') { + // it's a space, so press the WAIT button + thePelican.press(); + } + } + + return 0; +} diff --git a/cmat/Ex11/make.mk b/cmat/Ex11/make.mk new file mode 100644 index 0000000..9262097 --- /dev/null +++ b/cmat/Ex11/make.mk @@ -0,0 +1,2 @@ +BASEOBJS = \ + Light.o main.o Pelican.o PelicanTimer.o Pole.o Timer.o TimerSet.o diff --git a/cmat/Ex11/makefile b/cmat/Ex11/makefile new file mode 100644 index 0000000..13a67ac --- /dev/null +++ b/cmat/Ex11/makefile @@ -0,0 +1,17 @@ +COMPILER = gcc +FLAGS = +INCLUDES = -I/usr/local/include/c++/3.4.2 -I../DOS_Unix +ARCHIVES = -L/usr/local/lib/gcc/sparc-sun-solaris2.7/3.4.2 -L/usr/local/lib -L/usr/lib +UNIX_OBJS = ../DOS_Unix/CursesObj.o ../DOS_Unix/Keyboard_Unix.o ../DOS_Unix/Screen_Unix.o + +include make.mk + +.SUFFIXES: .cpp .o + +all: pelican + +.cpp.o: + $(COMPILER) $(INCLUDES) -frepo -c $(FLAGS) $*.cpp + +pelican : $(BASEOBJS) + $(COMPILER) $(ARCHIVES) -o pelican -lcurses $(BASEOBJS) $(UNIX_OBJS) -lcurses -lstdc++ -static diff --git a/cmat/Ex11bug/CMakeLists.txt b/cmat/Ex11bug/CMakeLists.txt new file mode 100644 index 0000000..af951ab --- /dev/null +++ b/cmat/Ex11bug/CMakeLists.txt @@ -0,0 +1,13 @@ +# Ex11bug + +cmat_add_exercise(Ex11bug + GUI + SOURCES + Light.cpp + main.cpp + Pelican.cpp + PelicanTimer.cpp + Pole.cpp + Timer.cpp + TimerSet.cpp +) diff --git a/cmat/Ex11bug/Ex11.sln b/cmat/Ex11bug/Ex11.sln new file mode 100644 index 0000000..2989bb0 --- /dev/null +++ b/cmat/Ex11bug/Ex11.sln @@ -0,0 +1,20 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ex11", "Ex11.vcxproj", "{E1F2BA40-B169-8D69-78E1-868C8A785A9C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E1F2BA40-B169-8D69-78E1-868C8A785A9C}.Debug|Win32.ActiveCfg = Debug|Win32 + {E1F2BA40-B169-8D69-78E1-868C8A785A9C}.Debug|Win32.Build.0 = Debug|Win32 + {E1F2BA40-B169-8D69-78E1-868C8A785A9C}.Release|Win32.ActiveCfg = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/cmat/Ex11bug/Ex11.suo b/cmat/Ex11bug/Ex11.suo new file mode 100644 index 0000000..11c06f2 Binary files /dev/null and b/cmat/Ex11bug/Ex11.suo differ diff --git a/cmat/Ex11bug/Ex11.vcproj b/cmat/Ex11bug/Ex11.vcproj new file mode 100644 index 0000000..f350ab1 --- /dev/null +++ b/cmat/Ex11bug/Ex11.vcproj @@ -0,0 +1,185 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cmat/Ex11bug/Ex11.vcxproj b/cmat/Ex11bug/Ex11.vcxproj new file mode 100644 index 0000000..4ef3de4 --- /dev/null +++ b/cmat/Ex11bug/Ex11.vcxproj @@ -0,0 +1,141 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + {E1F2BA40-B169-8D69-78E1-868C8A785A9C} + + + + Application + false + MultiByte + v140 + + + Application + false + MultiByte + v140 + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + .\Release\ + .\Release\ + false + .\Debug\ + .\Debug\ + true + + + + OnlyExplicitInline + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + true + + + .\Release/Ex11.pch + .\Release/ + .\Release/ + .\Release/ + Level3 + true + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Release/Ex11.exe + true + .\Release/Ex11.pdb + Console + + + .\Release/Ex11.tlb + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + true + NotUsing + .\Debug/Ex11.pch + .\Debug/ + .\Debug/ + .\Debug/ + Level3 + true + C:\course\397\DOS_Unix;%(AdditionalIncludeDirectories) + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Debug/Ex11.exe + true + true + .\Debug/Ex11.pdb + Console + + + .\Debug/Ex11.tlb + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cmat/Ex11bug/Ex11.vcxproj.filters b/cmat/Ex11bug/Ex11.vcxproj.filters new file mode 100644 index 0000000..44383de --- /dev/null +++ b/cmat/Ex11bug/Ex11.vcxproj.filters @@ -0,0 +1,71 @@ + + + + + {b96cbaea-8ae3-4716-865e-3aaf915fd0af} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {f948cebc-f590-4325-a5cc-fa8c85aa7733} + h;hpp;hxx;hm;inl + + + {c3395356-0a3a-4c18-8b27-851ff1f2369a} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + DOS_Unix + + + DOS_Unix + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + DOS_Unix + + + DOS_Unix + + + \ No newline at end of file diff --git a/cmat/Ex11bug/Ex11.vcxproj.user b/cmat/Ex11bug/Ex11.vcxproj.user new file mode 100644 index 0000000..695b5c7 --- /dev/null +++ b/cmat/Ex11bug/Ex11.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cmat/Ex11bug/Light.cpp b/cmat/Ex11bug/Light.cpp new file mode 100644 index 0000000..3a2878b --- /dev/null +++ b/cmat/Ex11bug/Light.cpp @@ -0,0 +1,22 @@ + + +#include "Light.h" +#include "CursesObj.h" +#include "Pelican.h" +#include "Screen.h" +#include + +Light::Light(std::string name, int x, int y, int color) : x(x), y(y), c(color), name(name) {} + +Light::~Light() { + std::cout << "Deleting light (" << name << ", " << x << ", " << y << ", " << c << ")" << std::endl; + std::cout.flush(); +} + +void Light::set(LightState newState) { + state = newState; + Screen::write(name.c_str(), x, y, state == FLASH ? (128 + c) : (state == OFF ? 0 : c)); + // 128 + color was used to make a character flash (but not any more) +} + +Light::LightState Light::get(void) { return state; } diff --git a/cmat/Ex11bug/Light.h b/cmat/Ex11bug/Light.h new file mode 100644 index 0000000..03adf9a --- /dev/null +++ b/cmat/Ex11bug/Light.h @@ -0,0 +1,30 @@ +// ====================================================== +// +// Represents a light, implemented as a string written +// to a console window +// +// ====================================================== + +#ifndef LIGHT_H +#define LIGHT_H + +#include + +class Light { + public: + Light(std::string name, int x, int y, int color); + ~Light(); + + enum LightState { ON, OFF, FLASH }; + + void set(LightState new_state); + LightState get(void); + + private: + int c; // light colour + int x, y; + std::string name; + LightState state; +}; + +#endif diff --git a/cmat/Ex11bug/Pelican.cpp b/cmat/Ex11bug/Pelican.cpp new file mode 100644 index 0000000..0eae8c2 --- /dev/null +++ b/cmat/Ex11bug/Pelican.cpp @@ -0,0 +1,66 @@ + + +#include "Pelican.h" +#include "PelicanTimer.h" +#include "Pole.h" + +Pelican::Pelican(int x, int y) + : pressed(false), RED_TIME(4), YELLOW_TIME(2), GREEN_TIME(3), FLASH_TIME(5), myPole(new Pole(x, y)), + state(GREEN_IDLE) { + myTimer = new PelicanTimer(*this, &Pelican::timerExpired); + + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed() ? Light::ON : Light::OFF); +} + +Pelican::~Pelican() { delete myPole; } + +void Pelican::press(void) { + if (state == GREEN_IDLE) { + state = YELLOW_STATE; + myTimer->timeoutRequest(YELLOW_TIME); + pressed = true; + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed() ? Light::ON : Light::OFF); + } else if (state != RED_STATE) { + pressed = true; + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed() ? Light::ON : Light::OFF); + } +} + +void Pelican::timerExpired(void) { + switch (state) { + case RED_STATE: + state = YELLOW_FLASHING; + myTimer->timeoutRequest(FLASH_TIME); + break; + + case YELLOW_FLASHING: + state = GREEN_TIMING; + myTimer->timeoutRequest(GREEN_TIME); + break; + + case GREEN_TIMING: + if (pressed) { + state = YELLOW_STATE; + myTimer->timeoutRequest(YELLOW_TIME); + } else { + state = GREEN_IDLE; + } + break; + + case GREEN_IDLE: + // should never happen + break; + + case YELLOW_STATE: + state = RED_STATE; + pressed = false; + myTimer->timeoutRequest(RED_TIME); + break; + } + + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed() ? Light::ON : Light::OFF); +} diff --git a/cmat/Ex11bug/Pelican.h b/cmat/Ex11bug/Pelican.h new file mode 100644 index 0000000..b7c8da0 --- /dev/null +++ b/cmat/Ex11bug/Pelican.h @@ -0,0 +1,53 @@ +// ====================================================== +// +// Represents a Pelican crossing +// +// ====================================================== + +#ifndef PELICAN_H +#define PELICAN_H + +class PelicanTimer; +class Pole; + +class Pelican { + public: + Pelican(int x, int y); + ~Pelican(); + + // call when the WAIT button has been pressed + void press(void); + + // states that a Pelican can be in + enum PelicanState { RED_STATE, YELLOW_FLASHING, GREEN_TIMING, GREEN_IDLE, YELLOW_STATE }; + + bool isPressed() const { return pressed; } + PelicanState getState() const { return state; } + + private: + // state that this Pelican is in + PelicanState state; + + // called by PeleicanTimer when the lights need to change + void timerExpired(void); + + const unsigned int RED_TIME; + const unsigned int YELLOW_TIME; + const unsigned int GREEN_TIME; + const unsigned int FLASH_TIME; + + // indicates whether the WAIT light should be on + bool pressed; + + Pole *myPole; + + // Timer that indicates when the lights should change + PelicanTimer *myTimer; + + private: + // prevent general use of copy ctor and operator= + Pelican(const Pelican &); + Pelican &operator=(const Pelican &); +}; + +#endif diff --git a/cmat/Ex11bug/PelicanTimer.cpp b/cmat/Ex11bug/PelicanTimer.cpp new file mode 100644 index 0000000..b1a8c97 --- /dev/null +++ b/cmat/Ex11bug/PelicanTimer.cpp @@ -0,0 +1,11 @@ + + +#include "PelicanTimer.h" + +PelicanTimer::PelicanTimer(Pelican &target, TargetFunc targetFunc) : myTarget(target), myTargetFunc(targetFunc) {} + +void PelicanTimer::tick() { + if (isExpired()) { + (myTarget.*myTargetFunc)(); + } +} diff --git a/cmat/Ex11bug/PelicanTimer.h b/cmat/Ex11bug/PelicanTimer.h new file mode 100644 index 0000000..3ce25b6 --- /dev/null +++ b/cmat/Ex11bug/PelicanTimer.h @@ -0,0 +1,27 @@ +// ====================================================== +// +// This class specializes the Timer to enable it to +// stimulate a Pelican +// +// ====================================================== + +#ifndef PELICANTIMER_H +#define PELICANTIMER_H + +#include "Pelican.h" +#include "Timer.h" + +class PelicanTimer : public Timer { + public: + typedef void (Pelican::*TargetFunc)(); + + PelicanTimer(Pelican &target, TargetFunc targetFunc); + + virtual void tick(); + + private: + Pelican &myTarget; + TargetFunc myTargetFunc; +}; + +#endif diff --git a/cmat/Ex11bug/Pole.cpp b/cmat/Ex11bug/Pole.cpp new file mode 100644 index 0000000..aeec308 --- /dev/null +++ b/cmat/Ex11bug/Pole.cpp @@ -0,0 +1,59 @@ +#include "Pole.h" +#include "Screen.h" + +Pole::Pole(int x, int y) : waitLight(new Light("WAIT", x + 6, y + 12, Screen::WHITE)) { + using namespace Screen; // we will discuss namespaces in the course + + lights[RED_LIGHT] = new Light("*", x + 11, y + 3, RED); + lights[RED_MAN] = new Light("*<-=", x + 6, y + 4, RED); + lights[YELLOW_LIGHT] = new Light("*", x + 11, y + 5, YELLOW); + lights[GREEN_LIGHT] = new Light("*", x + 11, y + 7, GREEN); + lights[GREEN_MAN] = new Light("*|-<", x + 6, y + 7, GREEN); + + write(" _____ ", x, ++y, GRAY); + write(" /___ /| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" | |/| ", x, ++y, GRAY); + write(" |____| | ", x, ++y, GRAY); + write(" | |/| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" |____|/ ", x, ++y, GRAY); + write(" _||__ ", x, ++y, GRAY); + write(" /___ /| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" |____|/ ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write("========||===========", x, ++y, GRAY); + write(" / || / ", x, ++y, GRAY); + write("_ /_________ /_ ", x, ++y, GRAY); + write("/ / ", x, ++y, GRAY); +} + +Pole::~Pole() { + for (int i = 0; i < sizeof lights / sizeof(lights[0]); ++i) + delete lights[i]; + delete waitLight; +} + +void Pole::setTrafficLights(Pelican::PelicanState state) { + static const Light::LightState LightStates[Pelican::YELLOW_STATE + 1][RED_MAN + 1] = { + // red yellow green green man red man + {Light::ON, Light::OFF, Light::OFF, Light::ON, Light::OFF}, // red + {Light::OFF, Light::FLASH, Light::OFF, Light::FLASH, Light::OFF}, // y flash + {Light::OFF, Light::OFF, Light::ON, Light::OFF, Light::ON}, // g time + {Light::OFF, Light::OFF, Light::ON, Light::OFF, Light::ON}, // g idle + {Light::OFF, Light::ON, Light::OFF, Light::OFF, Light::ON} // yellow + }; + + for (int i = RED_LIGHT; i <= RED_MAN; i++) { + lights[i]->set(LightStates[state][i]); + } +} + +void Pole::setWaitLight(bool pressed) { waitLight->set(pressed ? Light::ON : Light::OFF); } diff --git a/cmat/Ex11bug/Pole.h b/cmat/Ex11bug/Pole.h new file mode 100644 index 0000000..9013b95 --- /dev/null +++ b/cmat/Ex11bug/Pole.h @@ -0,0 +1,23 @@ +#ifndef POLE_H +#define POLE_H + +#include "Light.h" +#include "Pelican.h" + +class Pole { + public: + Pole(int x, int y); + ~Pole(); + + void setTrafficLights(Pelican::PelicanState state); + void setWaitLight(bool pressed); + + private: + enum LightName { RED_LIGHT, YELLOW_LIGHT, GREEN_LIGHT, GREEN_MAN, RED_MAN }; + + Light *lights[RED_MAN + 1]; + + Light *waitLight; +}; + +#endif diff --git a/cmat/Ex11bug/Timer.cpp b/cmat/Ex11bug/Timer.cpp new file mode 100644 index 0000000..f4daa3f --- /dev/null +++ b/cmat/Ex11bug/Timer.cpp @@ -0,0 +1,17 @@ + + +#include "Timer.h" +#include "TimerSet.h" + +void Timer::timeoutRequest(int seconds) { timeToGo = seconds; } + +Timer::Timer() : timeToGo(-1) { theTimerSet.addATimer(this); } + +bool Timer::isExpired() { + if (timeToGo > 0) { + if (--timeToGo == 0) { + return true; + } + } + return false; +} diff --git a/cmat/Ex11bug/Timer.h b/cmat/Ex11bug/Timer.h new file mode 100644 index 0000000..2deb1e1 --- /dev/null +++ b/cmat/Ex11bug/Timer.h @@ -0,0 +1,27 @@ +// ====================================================== +// +// A general-purpose countdown timer +// To use this class, specialize it +// and override tick() +// +// ====================================================== + +#ifndef TIMER_H +#define TIMER_H + +class Timer { + public: + Timer(); + + void timeoutRequest(int seconds); + + virtual void tick() = 0; + + protected: + bool isExpired(); + + private: + int timeToGo; +}; + +#endif diff --git a/cmat/Ex11bug/TimerSet.cpp b/cmat/Ex11bug/TimerSet.cpp new file mode 100644 index 0000000..7ff75c8 --- /dev/null +++ b/cmat/Ex11bug/TimerSet.cpp @@ -0,0 +1,24 @@ + + + + +#include "TimerSet.h" +#include "Timer.h" + +TimerSet theTimerSet; + + + +TimerSet::TimerSet() : timersInUse(0), previousTime(time(&previousTime)) {} + +void TimerSet::addATimer(Timer *t) { timers[timersInUse++] = t; } + +void TimerSet::pollAllTimers() { + std::time_t timeNow; + if (time(&timeNow) > previousTime) { + previousTime = timeNow; + for (int i = 0; i < timersInUse; ++i) { + timers[i]->tick(); + } + } +} diff --git a/cmat/Ex11bug/TimerSet.h b/cmat/Ex11bug/TimerSet.h new file mode 100644 index 0000000..1ea4123 --- /dev/null +++ b/cmat/Ex11bug/TimerSet.h @@ -0,0 +1,23 @@ +#ifndef TIMERSET_H +#define TIMERSET_H + +#include + +class Timer; + +class TimerSet { + public: + TimerSet(); + + void pollAllTimers(); + void addATimer(Timer *); + + private: + Timer *timers[40]; + int timersInUse; + std::time_t previousTime; +}; + +extern TimerSet theTimerSet; + +#endif diff --git a/cmat/Ex11bug/main.cpp b/cmat/Ex11bug/main.cpp new file mode 100644 index 0000000..fff22a7 --- /dev/null +++ b/cmat/Ex11bug/main.cpp @@ -0,0 +1,29 @@ + + +#include "Keyboard.h" +#include "Pelican.h" +#include "TimerSet.h" + +#include // provides toupper() + +int main() { + Keyboard kbd; + Pelican thePelican(30, 0); + + char c = 0; + + while (std::toupper(c) != 'Q') { // loop until 'Q' is pressed + + while (!kbd.isCharAvail()) { + theTimerSet.pollAllTimers(); // no key press to process, poll the timers + } + + c = kbd.getChar(); // get the character + if (c == ' ') { + // it's a space, so press the WAIT button + thePelican.press(); + } + } + + return 0; +} diff --git a/cmat/Ex11bug/make.mk b/cmat/Ex11bug/make.mk new file mode 100644 index 0000000..9262097 --- /dev/null +++ b/cmat/Ex11bug/make.mk @@ -0,0 +1,2 @@ +BASEOBJS = \ + Light.o main.o Pelican.o PelicanTimer.o Pole.o Timer.o TimerSet.o diff --git a/cmat/Ex11bug/makefile b/cmat/Ex11bug/makefile new file mode 100644 index 0000000..13a67ac --- /dev/null +++ b/cmat/Ex11bug/makefile @@ -0,0 +1,17 @@ +COMPILER = gcc +FLAGS = +INCLUDES = -I/usr/local/include/c++/3.4.2 -I../DOS_Unix +ARCHIVES = -L/usr/local/lib/gcc/sparc-sun-solaris2.7/3.4.2 -L/usr/local/lib -L/usr/lib +UNIX_OBJS = ../DOS_Unix/CursesObj.o ../DOS_Unix/Keyboard_Unix.o ../DOS_Unix/Screen_Unix.o + +include make.mk + +.SUFFIXES: .cpp .o + +all: pelican + +.cpp.o: + $(COMPILER) $(INCLUDES) -frepo -c $(FLAGS) $*.cpp + +pelican : $(BASEOBJS) + $(COMPILER) $(ARCHIVES) -o pelican -lcurses $(BASEOBJS) $(UNIX_OBJS) -lcurses -lstdc++ -static diff --git a/cmat/Ex21/CMakeLists.txt b/cmat/Ex21/CMakeLists.txt new file mode 100644 index 0000000..754134e --- /dev/null +++ b/cmat/Ex21/CMakeLists.txt @@ -0,0 +1,13 @@ +# Ex21 + +cmat_add_exercise(Ex21 + GUI + SOURCES + Light.cpp + Main.cpp + Pelican.cpp + PelicanTimer.cpp + Pole.cpp + Timer.cpp + TimerSet.cpp +) diff --git a/cmat/Ex21/Ex21.sln b/cmat/Ex21/Ex21.sln new file mode 100644 index 0000000..2e69fc6 --- /dev/null +++ b/cmat/Ex21/Ex21.sln @@ -0,0 +1,20 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ex21", "Ex21.vcxproj", "{AC7B29B3-9F42-7C36-686F-2F829309B86D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {AC7B29B3-9F42-7C36-686F-2F829309B86D}.Debug|Win32.ActiveCfg = Debug|Win32 + {AC7B29B3-9F42-7C36-686F-2F829309B86D}.Debug|Win32.Build.0 = Debug|Win32 + {AC7B29B3-9F42-7C36-686F-2F829309B86D}.Release|Win32.ActiveCfg = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/cmat/Ex21/Ex21.suo b/cmat/Ex21/Ex21.suo new file mode 100644 index 0000000..4177a2c Binary files /dev/null and b/cmat/Ex21/Ex21.suo differ diff --git a/cmat/Ex21/Ex21.vcproj b/cmat/Ex21/Ex21.vcproj new file mode 100644 index 0000000..dbda167 --- /dev/null +++ b/cmat/Ex21/Ex21.vcproj @@ -0,0 +1,185 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cmat/Ex21/Ex21.vcxproj b/cmat/Ex21/Ex21.vcxproj new file mode 100644 index 0000000..8505ca4 --- /dev/null +++ b/cmat/Ex21/Ex21.vcxproj @@ -0,0 +1,141 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + {AC7B29B3-9F42-7C36-686F-2F829309B86D} + + + + Application + false + MultiByte + v140 + + + Application + false + MultiByte + v140 + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + .\Release\ + .\Release\ + false + .\Debug\ + .\Debug\ + true + + + + OnlyExplicitInline + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + true + + + .\Release/Ex21.pch + .\Release/ + .\Release/ + .\Release/ + Level3 + true + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Release/Ex21.exe + true + .\Release/Ex21.pdb + Console + + + .\Release/Ex21.tlb + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + true + NotUsing + .\Debug/Ex21.pch + .\Debug/ + .\Debug/ + .\Debug/ + Level3 + true + C:\course\397\DOS_Unix;%(AdditionalIncludeDirectories) + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Debug/Ex21.exe + true + true + .\Debug/Ex21.pdb + Console + + + .\Debug/Ex21.tlb + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cmat/Ex21/Ex21.vcxproj.filters b/cmat/Ex21/Ex21.vcxproj.filters new file mode 100644 index 0000000..98467ba --- /dev/null +++ b/cmat/Ex21/Ex21.vcxproj.filters @@ -0,0 +1,71 @@ + + + + + {4b16368f-6693-40c4-8fcf-13a85f344069} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {2ec889ee-bec0-46c7-8125-b8c144b9328a} + h;hpp;hxx;hm;inl + + + {a57625e1-03b9-42e5-93c8-03d083fc7d09} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + DOS_Unix + + + DOS_Unix + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + DOS_Unix + + + DOS_Unix + + + \ No newline at end of file diff --git a/cmat/Ex21/Ex21.vcxproj.user b/cmat/Ex21/Ex21.vcxproj.user new file mode 100644 index 0000000..695b5c7 --- /dev/null +++ b/cmat/Ex21/Ex21.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cmat/Ex21/Light.cpp b/cmat/Ex21/Light.cpp new file mode 100644 index 0000000..4c06b21 --- /dev/null +++ b/cmat/Ex21/Light.cpp @@ -0,0 +1,19 @@ +#include "Light.h" +#include "Pelican.h" +#include "Screen.h" +#include + +Light::Light(std::string name, int x, int y, int color) : x(x), y(y), c(color), name(name) {} + +Light::~Light() { + std::cout << "Deleting light (" << name << ", " << x << ", " << y << ", " << c << ")" + << "\n"; +} + +void Light::set(LightState newState) { + state = newState; + Screen::write(name.c_str(), x, y, state == FLASH ? (128 + c) : (state == OFF ? 0 : c)); + // 128 + color was used to make a character flash (but not any more) +} + +Light::LightState Light::get(void) { return state; } diff --git a/cmat/Ex21/Light.h b/cmat/Ex21/Light.h new file mode 100644 index 0000000..03adf9a --- /dev/null +++ b/cmat/Ex21/Light.h @@ -0,0 +1,30 @@ +// ====================================================== +// +// Represents a light, implemented as a string written +// to a console window +// +// ====================================================== + +#ifndef LIGHT_H +#define LIGHT_H + +#include + +class Light { + public: + Light(std::string name, int x, int y, int color); + ~Light(); + + enum LightState { ON, OFF, FLASH }; + + void set(LightState new_state); + LightState get(void); + + private: + int c; // light colour + int x, y; + std::string name; + LightState state; +}; + +#endif diff --git a/cmat/Ex21/Main.cpp b/cmat/Ex21/Main.cpp new file mode 100644 index 0000000..71d922a --- /dev/null +++ b/cmat/Ex21/Main.cpp @@ -0,0 +1,31 @@ + + +#include "Keyboard.h" +#include "Pelican.h" +#include "TimerSet.h" + +#include // provides toupper() + +static TimerSet theTimerSet; + +int main() { + Keyboard kbd; + Pelican thePelican(30, 0); + + char c = 0; + + while (std::toupper(c) != 'Q') { // loop until 'Q' is pressed + + while (!kbd.isCharAvail()) { + theTimerSet.pollAllTimers(); // no key press to process, poll the timers + } + + c = kbd.getChar(); // get the character + if (c == ' ') { + // it's a space, so press the WAIT button + thePelican.press(); + } + } + + return 0; +} diff --git a/cmat/Ex21/Pelican.cpp b/cmat/Ex21/Pelican.cpp new file mode 100644 index 0000000..218611c --- /dev/null +++ b/cmat/Ex21/Pelican.cpp @@ -0,0 +1,65 @@ + +#include "Pelican.h" +#include "PelicanTimer.h" +#include "Pole.h" + +Pelican::Pelican(int x, int y) + : pressed(false), RED_TIME(4), YELLOW_TIME(2), GREEN_TIME(3), FLASH_TIME(5), myPole(new Pole(x, y)), + state(GREEN_IDLE) { + myTimer = new PelicanTimer(*this, &Pelican::timerExpired); + + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed()); +} + +Pelican::~Pelican() { delete myPole; } + +void Pelican::press(void) { + if (state == GREEN_IDLE) { + state = YELLOW_STATE; + myTimer->timeoutRequest(YELLOW_TIME); + pressed = true; + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed()); + } else if (state != RED_STATE) { + pressed = true; + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed()); + } +} + +void Pelican::timerExpired(void) { + switch (state) { + case RED_STATE: + state = YELLOW_FLASHING; + myTimer->timeoutRequest(FLASH_TIME); + break; + + case YELLOW_FLASHING: + state = GREEN_TIMING; + myTimer->timeoutRequest(GREEN_TIME); + break; + + case GREEN_TIMING: + if (pressed) { + state = YELLOW_STATE; + myTimer->timeoutRequest(YELLOW_TIME); + } else { + state = GREEN_IDLE; + } + break; + + case GREEN_IDLE: + // should never happen + break; + + case YELLOW_STATE: + state = RED_STATE; + pressed = false; + myTimer->timeoutRequest(RED_TIME); + break; + } + + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed()); +} diff --git a/cmat/Ex21/Pelican.h b/cmat/Ex21/Pelican.h new file mode 100644 index 0000000..b7c8da0 --- /dev/null +++ b/cmat/Ex21/Pelican.h @@ -0,0 +1,53 @@ +// ====================================================== +// +// Represents a Pelican crossing +// +// ====================================================== + +#ifndef PELICAN_H +#define PELICAN_H + +class PelicanTimer; +class Pole; + +class Pelican { + public: + Pelican(int x, int y); + ~Pelican(); + + // call when the WAIT button has been pressed + void press(void); + + // states that a Pelican can be in + enum PelicanState { RED_STATE, YELLOW_FLASHING, GREEN_TIMING, GREEN_IDLE, YELLOW_STATE }; + + bool isPressed() const { return pressed; } + PelicanState getState() const { return state; } + + private: + // state that this Pelican is in + PelicanState state; + + // called by PeleicanTimer when the lights need to change + void timerExpired(void); + + const unsigned int RED_TIME; + const unsigned int YELLOW_TIME; + const unsigned int GREEN_TIME; + const unsigned int FLASH_TIME; + + // indicates whether the WAIT light should be on + bool pressed; + + Pole *myPole; + + // Timer that indicates when the lights should change + PelicanTimer *myTimer; + + private: + // prevent general use of copy ctor and operator= + Pelican(const Pelican &); + Pelican &operator=(const Pelican &); +}; + +#endif diff --git a/cmat/Ex21/PelicanTimer.cpp b/cmat/Ex21/PelicanTimer.cpp new file mode 100644 index 0000000..bbb0b9b --- /dev/null +++ b/cmat/Ex21/PelicanTimer.cpp @@ -0,0 +1,10 @@ + +#include "PelicanTimer.h" + +PelicanTimer::PelicanTimer(Pelican &target, TargetFunc targetFunc) : myTarget(target), myTargetFunc(targetFunc) {} + +void PelicanTimer::tick() { + if (isExpired()) { + (myTarget.*myTargetFunc)(); + } +} diff --git a/cmat/Ex21/PelicanTimer.h b/cmat/Ex21/PelicanTimer.h new file mode 100644 index 0000000..6a8e936 --- /dev/null +++ b/cmat/Ex21/PelicanTimer.h @@ -0,0 +1,31 @@ +// ====================================================== +// +// This class specializes the Timer to enable it to +// stimulate a Pelican +// +// ====================================================== + +#ifndef PELICANTIMER_H +#define PELICANTIMER_H + +#include "Pelican.h" +#include "Timer.h" + +class PelicanTimer : public Timer { + public: + typedef void (Pelican::*TargetFunc)(); + + PelicanTimer(Pelican &target, TargetFunc targetFunc); + + // TODO: Remove this function + virtual void tick(); + + // TODO: Add override of virtual function Timer::doExpired + // (this is the "primitive step" of the template method pattern) + + private: + Pelican &myTarget; + TargetFunc myTargetFunc; +}; + +#endif diff --git a/cmat/Ex21/Pole.cpp b/cmat/Ex21/Pole.cpp new file mode 100644 index 0000000..8422fa7 --- /dev/null +++ b/cmat/Ex21/Pole.cpp @@ -0,0 +1,59 @@ +#include "Pole.h" +#include "Screen.h" + +Pole::Pole(int x, int y) : waitLight(new Light("WAIT", x + 6, y + 12, Screen::WHITE)) { + using namespace Screen; + + lights[RED_LIGHT] = new Light("*", x + 11, y + 3, RED); + lights[RED_MAN] = new Light("*<-=", x + 6, y + 4, RED); + lights[YELLOW_LIGHT] = new Light("*", x + 11, y + 5, YELLOW); + lights[GREEN_LIGHT] = new Light("*", x + 11, y + 7, GREEN); + lights[GREEN_MAN] = new Light("*|-<", x + 6, y + 7, GREEN); + + write(" _____ ", x, ++y, GRAY); + write(" /___ /| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" | |/| ", x, ++y, GRAY); + write(" |____| | ", x, ++y, GRAY); + write(" | |/| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" |____|/ ", x, ++y, GRAY); + write(" _||__ ", x, ++y, GRAY); + write(" /___ /| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" |____|/ ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write("========||===========", x, ++y, GRAY); + write(" / || / ", x, ++y, GRAY); + write("_ /_________ /_ ", x, ++y, GRAY); + write("/ / ", x, ++y, GRAY); +} + +Pole::~Pole() { + for (int i = 0; i < sizeof lights / sizeof(lights[0]); ++i) + delete lights[i]; + delete waitLight; +} + +void Pole::setTrafficLights(Pelican::PelicanState state) { + static const Light::LightState LightStates[Pelican::YELLOW_STATE + 1][RED_MAN + 1] = { + // red yellow green green man red man + {Light::ON, Light::OFF, Light::OFF, Light::ON, Light::OFF}, // red + {Light::OFF, Light::FLASH, Light::OFF, Light::FLASH, Light::OFF}, // y flash + {Light::OFF, Light::OFF, Light::ON, Light::OFF, Light::ON}, // g time + {Light::OFF, Light::OFF, Light::ON, Light::OFF, Light::ON}, // g idle + {Light::OFF, Light::ON, Light::OFF, Light::OFF, Light::ON} // yellow + }; + + for (int i = RED_LIGHT; i <= RED_MAN; i++) { + lights[i]->set(LightStates[state][i]); + } +} + +void Pole::setWaitLight(bool pressed) { waitLight->set(pressed ? Light::ON : Light::OFF); } diff --git a/cmat/Ex21/Pole.h b/cmat/Ex21/Pole.h new file mode 100644 index 0000000..9013b95 --- /dev/null +++ b/cmat/Ex21/Pole.h @@ -0,0 +1,23 @@ +#ifndef POLE_H +#define POLE_H + +#include "Light.h" +#include "Pelican.h" + +class Pole { + public: + Pole(int x, int y); + ~Pole(); + + void setTrafficLights(Pelican::PelicanState state); + void setWaitLight(bool pressed); + + private: + enum LightName { RED_LIGHT, YELLOW_LIGHT, GREEN_LIGHT, GREEN_MAN, RED_MAN }; + + Light *lights[RED_MAN + 1]; + + Light *waitLight; +}; + +#endif diff --git a/cmat/Ex21/Timer.cpp b/cmat/Ex21/Timer.cpp new file mode 100644 index 0000000..cdf31d4 --- /dev/null +++ b/cmat/Ex21/Timer.cpp @@ -0,0 +1,18 @@ + +#include "Timer.h" +#include "TimerSet.h" + +static TimerSet theTimerSet; + +void Timer::timeoutRequest(int seconds) { timeToGo = seconds; } + +Timer::Timer() : timeToGo(-1) { theTimerSet.addATimer(this); } + +bool Timer::isExpired() { + if (timeToGo > 0) { + if (--timeToGo == 0) { + return true; + } + } + return false; +} diff --git a/cmat/Ex21/Timer.h b/cmat/Ex21/Timer.h new file mode 100644 index 0000000..2deb1e1 --- /dev/null +++ b/cmat/Ex21/Timer.h @@ -0,0 +1,27 @@ +// ====================================================== +// +// A general-purpose countdown timer +// To use this class, specialize it +// and override tick() +// +// ====================================================== + +#ifndef TIMER_H +#define TIMER_H + +class Timer { + public: + Timer(); + + void timeoutRequest(int seconds); + + virtual void tick() = 0; + + protected: + bool isExpired(); + + private: + int timeToGo; +}; + +#endif diff --git a/cmat/Ex21/TimerSet.cpp b/cmat/Ex21/TimerSet.cpp new file mode 100644 index 0000000..62118b8 --- /dev/null +++ b/cmat/Ex21/TimerSet.cpp @@ -0,0 +1,22 @@ + + +// TODO: Add Singleton code + +#include "TimerSet.h" +#include "Timer.h" + + + +TimerSet::TimerSet() : timersInUse(0), previousTime(time(&previousTime)) {} + +void TimerSet::addATimer(Timer *t) { timers[timersInUse++] = t; } + +void TimerSet::pollAllTimers() { + std::time_t timeNow; + if (time(&timeNow) > previousTime) { + previousTime = timeNow; + for (int i = 0; i < timersInUse; ++i) { + timers[i]->tick(); + } + } +} diff --git a/cmat/Ex21/TimerSet.h b/cmat/Ex21/TimerSet.h new file mode 100644 index 0000000..1ea4123 --- /dev/null +++ b/cmat/Ex21/TimerSet.h @@ -0,0 +1,23 @@ +#ifndef TIMERSET_H +#define TIMERSET_H + +#include + +class Timer; + +class TimerSet { + public: + TimerSet(); + + void pollAllTimers(); + void addATimer(Timer *); + + private: + Timer *timers[40]; + int timersInUse; + std::time_t previousTime; +}; + +extern TimerSet theTimerSet; + +#endif diff --git a/cmat/Ex22/CMakeLists.txt b/cmat/Ex22/CMakeLists.txt new file mode 100644 index 0000000..8fd49c2 --- /dev/null +++ b/cmat/Ex22/CMakeLists.txt @@ -0,0 +1,13 @@ +# Ex22 + +cmat_add_exercise(Ex22 + GUI + SOURCES + Light.cpp + main.cpp + Pelican.cpp + PelicanTimer.cpp + Pole.cpp + Timer.cpp + TimerSet.cpp +) diff --git a/cmat/Ex22/Ex22.sln b/cmat/Ex22/Ex22.sln new file mode 100644 index 0000000..e1ea084 --- /dev/null +++ b/cmat/Ex22/Ex22.sln @@ -0,0 +1,20 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ex22", "Ex22.vcxproj", "{C2EDBD25-9006-0438-220A-8766E6F352A8}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C2EDBD25-9006-0438-220A-8766E6F352A8}.Debug|Win32.ActiveCfg = Debug|Win32 + {C2EDBD25-9006-0438-220A-8766E6F352A8}.Debug|Win32.Build.0 = Debug|Win32 + {C2EDBD25-9006-0438-220A-8766E6F352A8}.Release|Win32.ActiveCfg = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/cmat/Ex22/Ex22.suo b/cmat/Ex22/Ex22.suo new file mode 100644 index 0000000..5e8ec65 Binary files /dev/null and b/cmat/Ex22/Ex22.suo differ diff --git a/cmat/Ex22/Ex22.vcproj b/cmat/Ex22/Ex22.vcproj new file mode 100644 index 0000000..b96f6d2 --- /dev/null +++ b/cmat/Ex22/Ex22.vcproj @@ -0,0 +1,182 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cmat/Ex22/Ex22.vcxproj b/cmat/Ex22/Ex22.vcxproj new file mode 100644 index 0000000..0d9ef46 --- /dev/null +++ b/cmat/Ex22/Ex22.vcxproj @@ -0,0 +1,141 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + {C2EDBD25-9006-0438-220A-8766E6F352A8} + + + + Application + false + MultiByte + v140 + + + Application + false + MultiByte + v140 + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + .\Debug\ + .\Debug\ + true + .\Release\ + .\Release\ + false + + + + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + true + NotUsing + .\Debug/Ex22.pch + .\Debug/ + .\Debug/ + .\Debug/ + Level3 + true + C:\course\397\DOS_Unix;%(AdditionalIncludeDirectories) + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Debug/Ex22.exe + true + true + .\Debug/Ex22.pdb + Console + + + .\Debug/Ex22.tlb + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + OnlyExplicitInline + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + true + + + .\Release/Ex22.pch + .\Release/ + .\Release/ + .\Release/ + Level3 + true + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Release/Ex22.exe + true + .\Release/Ex22.pdb + Console + + + .\Release/Ex22.tlb + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cmat/Ex22/Ex22.vcxproj.filters b/cmat/Ex22/Ex22.vcxproj.filters new file mode 100644 index 0000000..6056df2 --- /dev/null +++ b/cmat/Ex22/Ex22.vcxproj.filters @@ -0,0 +1,71 @@ + + + + + {17deccef-8801-49d5-8ba1-c5db56fa73c0} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {eaf1391b-78b1-4db8-adb1-2585eaedd6e7} + h;hpp;hxx;hm;inl + + + {f8ec245a-126d-413b-8f31-4f57d4342719} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + DOS_Unix + + + DOS_Unix + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + DOS_Unix + + + DOS_Unix + + + Header Files + + + \ No newline at end of file diff --git a/cmat/Ex22/Ex22.vcxproj.user b/cmat/Ex22/Ex22.vcxproj.user new file mode 100644 index 0000000..695b5c7 --- /dev/null +++ b/cmat/Ex22/Ex22.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cmat/Ex22/Light.cpp b/cmat/Ex22/Light.cpp new file mode 100644 index 0000000..e111c52 --- /dev/null +++ b/cmat/Ex22/Light.cpp @@ -0,0 +1,21 @@ + + +#include "Light.h" +#include "Pelican.h" +#include "Screen.h" +#include + +Light::Light(std::string name, int x, int y, int color) : x(x), y(y), c(color), name(name) {} + +Light::~Light() { + std::cout << "Deleting light (" << name << ", " << x << ", " << y << ", " << c << ")" + << "\n"; +} + +void Light::set(LightState newState) { + state = newState; + Screen::write(name.c_str(), x, y, state == FLASH ? (128 + c) : (state == OFF ? 0 : c)); + // 128 + color was used to make a character flash (but not any more) +} + +Light::LightState Light::get(void) { return state; } diff --git a/cmat/Ex22/Light.h b/cmat/Ex22/Light.h new file mode 100644 index 0000000..03adf9a --- /dev/null +++ b/cmat/Ex22/Light.h @@ -0,0 +1,30 @@ +// ====================================================== +// +// Represents a light, implemented as a string written +// to a console window +// +// ====================================================== + +#ifndef LIGHT_H +#define LIGHT_H + +#include + +class Light { + public: + Light(std::string name, int x, int y, int color); + ~Light(); + + enum LightState { ON, OFF, FLASH }; + + void set(LightState new_state); + LightState get(void); + + private: + int c; // light colour + int x, y; + std::string name; + LightState state; +}; + +#endif diff --git a/cmat/Ex22/Pelican.cpp b/cmat/Ex22/Pelican.cpp new file mode 100644 index 0000000..29e1c07 --- /dev/null +++ b/cmat/Ex22/Pelican.cpp @@ -0,0 +1,66 @@ + + +#include "Pelican.h" +#include "PelicanTimer.h" +#include "Pole.h" + +Pelican::Pelican(int x, int y) + : pressed(false), RED_TIME(4), YELLOW_TIME(2), GREEN_TIME(3), FLASH_TIME(5), myPole(new Pole(x, y)), + state(GREEN_IDLE) { + myTimer = new PelicanTimer(*this, &Pelican::timerExpired); + + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed()); +} + +Pelican::~Pelican() { delete myPole; } + +void Pelican::press(void) { + if (state == GREEN_IDLE) { + state = YELLOW_STATE; + myTimer->timeoutRequest(YELLOW_TIME); + pressed = true; + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed()); + } else if (state != RED_STATE) { + pressed = true; + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed()); + } +} + +void Pelican::timerExpired(void) { + switch (state) { + case RED_STATE: + state = YELLOW_FLASHING; + myTimer->timeoutRequest(FLASH_TIME); + break; + + case YELLOW_FLASHING: + state = GREEN_TIMING; + myTimer->timeoutRequest(GREEN_TIME); + break; + + case GREEN_TIMING: + if (pressed) { + state = YELLOW_STATE; + myTimer->timeoutRequest(YELLOW_TIME); + } else { + state = GREEN_IDLE; + } + break; + + case GREEN_IDLE: + // should never happen + break; + + case YELLOW_STATE: + state = RED_STATE; + pressed = false; + myTimer->timeoutRequest(RED_TIME); + break; + } + + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed()); +} diff --git a/cmat/Ex22/Pelican.h b/cmat/Ex22/Pelican.h new file mode 100644 index 0000000..b7c8da0 --- /dev/null +++ b/cmat/Ex22/Pelican.h @@ -0,0 +1,53 @@ +// ====================================================== +// +// Represents a Pelican crossing +// +// ====================================================== + +#ifndef PELICAN_H +#define PELICAN_H + +class PelicanTimer; +class Pole; + +class Pelican { + public: + Pelican(int x, int y); + ~Pelican(); + + // call when the WAIT button has been pressed + void press(void); + + // states that a Pelican can be in + enum PelicanState { RED_STATE, YELLOW_FLASHING, GREEN_TIMING, GREEN_IDLE, YELLOW_STATE }; + + bool isPressed() const { return pressed; } + PelicanState getState() const { return state; } + + private: + // state that this Pelican is in + PelicanState state; + + // called by PeleicanTimer when the lights need to change + void timerExpired(void); + + const unsigned int RED_TIME; + const unsigned int YELLOW_TIME; + const unsigned int GREEN_TIME; + const unsigned int FLASH_TIME; + + // indicates whether the WAIT light should be on + bool pressed; + + Pole *myPole; + + // Timer that indicates when the lights should change + PelicanTimer *myTimer; + + private: + // prevent general use of copy ctor and operator= + Pelican(const Pelican &); + Pelican &operator=(const Pelican &); +}; + +#endif diff --git a/cmat/Ex22/PelicanTimer.cpp b/cmat/Ex22/PelicanTimer.cpp new file mode 100644 index 0000000..b1a8c97 --- /dev/null +++ b/cmat/Ex22/PelicanTimer.cpp @@ -0,0 +1,11 @@ + + +#include "PelicanTimer.h" + +PelicanTimer::PelicanTimer(Pelican &target, TargetFunc targetFunc) : myTarget(target), myTargetFunc(targetFunc) {} + +void PelicanTimer::tick() { + if (isExpired()) { + (myTarget.*myTargetFunc)(); + } +} diff --git a/cmat/Ex22/PelicanTimer.h b/cmat/Ex22/PelicanTimer.h new file mode 100644 index 0000000..9c17567 --- /dev/null +++ b/cmat/Ex22/PelicanTimer.h @@ -0,0 +1,28 @@ +// ====================================================== +// +// This class specializes the Timer to enable it to +// stimulate a Pelican +// +// ====================================================== + +#ifndef PELICANTIMER_H +#define PELICANTIMER_H + +#include "Pelican.h" +#include "Timer.h" + +class PelicanTimer : public Timer { + public: + typedef void (Pelican::*TargetFunc)(); + + PelicanTimer(Pelican &target, TargetFunc targetFunc); + + // TODO: Rename this function to doExpired. The parameters and return type are unchanged. + virtual void tick(); + + private: + Pelican &myTarget; + TargetFunc myTargetFunc; +}; + +#endif diff --git a/cmat/Ex22/Pole.cpp b/cmat/Ex22/Pole.cpp new file mode 100644 index 0000000..aeec308 --- /dev/null +++ b/cmat/Ex22/Pole.cpp @@ -0,0 +1,59 @@ +#include "Pole.h" +#include "Screen.h" + +Pole::Pole(int x, int y) : waitLight(new Light("WAIT", x + 6, y + 12, Screen::WHITE)) { + using namespace Screen; // we will discuss namespaces in the course + + lights[RED_LIGHT] = new Light("*", x + 11, y + 3, RED); + lights[RED_MAN] = new Light("*<-=", x + 6, y + 4, RED); + lights[YELLOW_LIGHT] = new Light("*", x + 11, y + 5, YELLOW); + lights[GREEN_LIGHT] = new Light("*", x + 11, y + 7, GREEN); + lights[GREEN_MAN] = new Light("*|-<", x + 6, y + 7, GREEN); + + write(" _____ ", x, ++y, GRAY); + write(" /___ /| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" | |/| ", x, ++y, GRAY); + write(" |____| | ", x, ++y, GRAY); + write(" | |/| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" |____|/ ", x, ++y, GRAY); + write(" _||__ ", x, ++y, GRAY); + write(" /___ /| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" |____|/ ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write("========||===========", x, ++y, GRAY); + write(" / || / ", x, ++y, GRAY); + write("_ /_________ /_ ", x, ++y, GRAY); + write("/ / ", x, ++y, GRAY); +} + +Pole::~Pole() { + for (int i = 0; i < sizeof lights / sizeof(lights[0]); ++i) + delete lights[i]; + delete waitLight; +} + +void Pole::setTrafficLights(Pelican::PelicanState state) { + static const Light::LightState LightStates[Pelican::YELLOW_STATE + 1][RED_MAN + 1] = { + // red yellow green green man red man + {Light::ON, Light::OFF, Light::OFF, Light::ON, Light::OFF}, // red + {Light::OFF, Light::FLASH, Light::OFF, Light::FLASH, Light::OFF}, // y flash + {Light::OFF, Light::OFF, Light::ON, Light::OFF, Light::ON}, // g time + {Light::OFF, Light::OFF, Light::ON, Light::OFF, Light::ON}, // g idle + {Light::OFF, Light::ON, Light::OFF, Light::OFF, Light::ON} // yellow + }; + + for (int i = RED_LIGHT; i <= RED_MAN; i++) { + lights[i]->set(LightStates[state][i]); + } +} + +void Pole::setWaitLight(bool pressed) { waitLight->set(pressed ? Light::ON : Light::OFF); } diff --git a/cmat/Ex22/Pole.h b/cmat/Ex22/Pole.h new file mode 100644 index 0000000..a62d29b --- /dev/null +++ b/cmat/Ex22/Pole.h @@ -0,0 +1,24 @@ + +#ifndef POLE_H +#define POLE_H + +#include "Light.h" +#include "Pelican.h" + +class Pole { + public: + Pole(int x, int y); + ~Pole(); + + void setTrafficLights(Pelican::PelicanState state); + void setWaitLight(bool pressed); + + private: + enum LightName { RED_LIGHT, YELLOW_LIGHT, GREEN_LIGHT, GREEN_MAN, RED_MAN }; + + Light *lights[RED_MAN + 1]; + + Light *waitLight; +}; + +#endif diff --git a/cmat/Ex22/Timer.cpp b/cmat/Ex22/Timer.cpp new file mode 100644 index 0000000..1384258 --- /dev/null +++ b/cmat/Ex22/Timer.cpp @@ -0,0 +1,17 @@ + + +#include "Timer.h" +#include "TimerSet.h" + +void Timer::timeoutRequest(int seconds) { timeToGo = seconds; } + +Timer::Timer() : timeToGo(-1) { TimerSet::Instance().addATimer(this); } + +bool Timer::isExpired() { + if (timeToGo > 0) { + if (--timeToGo == 0) { + return true; + } + } + return false; +} diff --git a/cmat/Ex22/Timer.h b/cmat/Ex22/Timer.h new file mode 100644 index 0000000..b52947b --- /dev/null +++ b/cmat/Ex22/Timer.h @@ -0,0 +1,27 @@ +// ====================================================== +// +// A general-purpose countdown timer +// To use this class, specialize it +// and override tick() +// +// ====================================================== + +#ifndef timer_H +#define timer_H + +class Timer { + public: + Timer(); + + void timeoutRequest(int seconds); + + virtual void tick() = 0; + + protected: + bool isExpired(); + + private: + int timeToGo; +}; + +#endif diff --git a/cmat/Ex22/TimerSet.cpp b/cmat/Ex22/TimerSet.cpp new file mode 100644 index 0000000..2a68d12 --- /dev/null +++ b/cmat/Ex22/TimerSet.cpp @@ -0,0 +1,23 @@ +#include "TimerSet.h" +#include "Timer.h" +#include + +TimerSet::TimerSet() : timersInUse(0), previousTime(time(NULL)) {} + +void TimerSet::addATimer(Timer *t) { timers[timersInUse++] = t; } + +void TimerSet::pollAllTimers() { + std::time_t timeNow; + if (time(&timeNow) > previousTime) { + previousTime = timeNow; + for (int i = 0; i < timersInUse; ++i) { + timers[i]->tick(); + } + } +} + +TimerSet &TimerSet::Instance() { + // Meyer's Singleton implementation + static TimerSet pInstance; + return pInstance; +} diff --git a/cmat/Ex22/TimerSet.h b/cmat/Ex22/TimerSet.h new file mode 100644 index 0000000..3dfe925 --- /dev/null +++ b/cmat/Ex22/TimerSet.h @@ -0,0 +1,29 @@ +#ifndef TIMERSET_H +#define TIMERSET_H + +#include + +class Timer; + +class TimerSet { + public: + void pollAllTimers(); + void addATimer(Timer *); + + private: + TimerSet(); + Timer *timers[40]; + int timersInUse; + std::time_t previousTime; + + // Meyer's singleton + public: + static TimerSet &Instance(); + + private: + // prevent copying and assignment of the singleton + TimerSet(const TimerSet &); + TimerSet &operator=(const TimerSet &); +}; + +#endif diff --git a/cmat/Ex22/main.cpp b/cmat/Ex22/main.cpp new file mode 100644 index 0000000..1cecd5c --- /dev/null +++ b/cmat/Ex22/main.cpp @@ -0,0 +1,29 @@ + + +#include "Keyboard.h" +#include "Pelican.h" +#include "TimerSet.h" + +#include // provides toupper() + +int main() { + Keyboard kbd; + Pelican thePelican(30, 0); + + char c = 0; + + while (std::toupper(c) != 'Q') { // loop until 'Q' is pressed + + while (!kbd.isCharAvail()) { + TimerSet::Instance().pollAllTimers(); // no key press to process, poll the timers + } + + c = kbd.getChar(); // get the character + if (c == ' ') { + // it's a space, so press the WAIT button + thePelican.press(); + } + } + + return 0; +} diff --git a/cmat/Ex31/.vs/Ex31/v14/.suo b/cmat/Ex31/.vs/Ex31/v14/.suo new file mode 100644 index 0000000..0517233 Binary files /dev/null and b/cmat/Ex31/.vs/Ex31/v14/.suo differ diff --git a/cmat/Ex31/CMakeLists.txt b/cmat/Ex31/CMakeLists.txt new file mode 100644 index 0000000..b805cfc --- /dev/null +++ b/cmat/Ex31/CMakeLists.txt @@ -0,0 +1,6 @@ +# Ex31 + +cmat_add_exercise(Ex31 + SOURCES + Main.cpp +) diff --git a/cmat/Ex31/Ex31.sln b/cmat/Ex31/Ex31.sln new file mode 100644 index 0000000..5a6bac2 --- /dev/null +++ b/cmat/Ex31/Ex31.sln @@ -0,0 +1,20 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ex31", "Ex31.vcxproj", "{8F266BE3-8B4C-8EDD-744B-50A12A4E07CF}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8F266BE3-8B4C-8EDD-744B-50A12A4E07CF}.Debug|Win32.ActiveCfg = Debug|Win32 + {8F266BE3-8B4C-8EDD-744B-50A12A4E07CF}.Debug|Win32.Build.0 = Debug|Win32 + {8F266BE3-8B4C-8EDD-744B-50A12A4E07CF}.Release|Win32.ActiveCfg = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/cmat/Ex31/Ex31.suo b/cmat/Ex31/Ex31.suo new file mode 100644 index 0000000..babac98 Binary files /dev/null and b/cmat/Ex31/Ex31.suo differ diff --git a/cmat/Ex31/Ex31.vcproj b/cmat/Ex31/Ex31.vcproj new file mode 100644 index 0000000..8a79692 --- /dev/null +++ b/cmat/Ex31/Ex31.vcproj @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cmat/Ex31/Ex31.vcxproj b/cmat/Ex31/Ex31.vcxproj new file mode 100644 index 0000000..cb1a015 --- /dev/null +++ b/cmat/Ex31/Ex31.vcxproj @@ -0,0 +1,126 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + {8F266BE3-8B4C-8EDD-744B-50A12A4E07CF} + + + + Application + false + MultiByte + v140 + + + Application + false + MultiByte + v140 + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + .\Release\ + .\Release\ + false + .\Debug\ + .\Debug\ + true + + + + OnlyExplicitInline + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + true + + + .\Release/Ex31.pch + .\Release/ + .\Release/ + .\Release/ + Level3 + true + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Release/Ex31.exe + true + .\Release/Ex31.pdb + Console + + + .\Release/Ex31.tlb + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + true + + + .\Debug/Ex31.pch + .\Debug/ + .\Debug/ + .\Debug/ + Level3 + true + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Debug/Ex31.exe + true + true + .\Debug/Ex31.pdb + Console + + + .\Debug/Ex31.tlb + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + + + + + + + + \ No newline at end of file diff --git a/cmat/Ex31/Ex31.vcxproj.filters b/cmat/Ex31/Ex31.vcxproj.filters new file mode 100644 index 0000000..415767d --- /dev/null +++ b/cmat/Ex31/Ex31.vcxproj.filters @@ -0,0 +1,23 @@ + + + + + {6203fd97-4a05-4e35-bd12-060da3c18bb3} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {567d7160-2695-45e1-ad9b-998cd1d33246} + h;hpp;hxx;hm;inl + + + + + Source Files + + + + + Header Files + + + \ No newline at end of file diff --git a/cmat/Ex31/Ex31.vcxproj.user b/cmat/Ex31/Ex31.vcxproj.user new file mode 100644 index 0000000..695b5c7 --- /dev/null +++ b/cmat/Ex31/Ex31.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cmat/Ex31/Main.cpp b/cmat/Ex31/Main.cpp new file mode 100644 index 0000000..8ea556d --- /dev/null +++ b/cmat/Ex31/Main.cpp @@ -0,0 +1,10 @@ + +#include "Pixel.h" + +#include + +int main() { + // insert code here *************************************** + + return 0; +} \ No newline at end of file diff --git a/cmat/Ex31/Pixel.h b/cmat/Ex31/Pixel.h new file mode 100644 index 0000000..bfc44c7 --- /dev/null +++ b/cmat/Ex31/Pixel.h @@ -0,0 +1,22 @@ + +#ifndef Pixel_h +#define Pixel_h + +#include + +class Pixel { + public: + Pixel(int x = 0, int y = 0) : x(x), y(y) {} + + void print() const { std::cout << '(' << x << "," << y << ") "; } + + bool operator<(const Pixel &rhs) const { return x < rhs.x; } + + bool operator==(const Pixel &rhs) const { return x == rhs.x; } + + private: + int x; + int y; +}; + +#endif diff --git a/cmat/Ex32/CMakeLists.txt b/cmat/Ex32/CMakeLists.txt new file mode 100644 index 0000000..d0061d7 --- /dev/null +++ b/cmat/Ex32/CMakeLists.txt @@ -0,0 +1,6 @@ +# Ex32 + +cmat_add_exercise(Ex32 + SOURCES + main.cpp +) diff --git a/cmat/Ex32/Ex32.sln b/cmat/Ex32/Ex32.sln new file mode 100644 index 0000000..b6d9072 --- /dev/null +++ b/cmat/Ex32/Ex32.sln @@ -0,0 +1,20 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ex32", "Ex32.vcxproj", "{F5DDDD69-0B34-7FD5-AEAF-1BA6CC4705A1}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F5DDDD69-0B34-7FD5-AEAF-1BA6CC4705A1}.Debug|Win32.ActiveCfg = Debug|Win32 + {F5DDDD69-0B34-7FD5-AEAF-1BA6CC4705A1}.Debug|Win32.Build.0 = Debug|Win32 + {F5DDDD69-0B34-7FD5-AEAF-1BA6CC4705A1}.Release|Win32.ActiveCfg = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/cmat/Ex32/Ex32.suo b/cmat/Ex32/Ex32.suo new file mode 100644 index 0000000..30336ac Binary files /dev/null and b/cmat/Ex32/Ex32.suo differ diff --git a/cmat/Ex32/Ex32.vcproj b/cmat/Ex32/Ex32.vcproj new file mode 100644 index 0000000..b746f98 --- /dev/null +++ b/cmat/Ex32/Ex32.vcproj @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cmat/Ex32/Ex32.vcxproj b/cmat/Ex32/Ex32.vcxproj new file mode 100644 index 0000000..636a9c2 --- /dev/null +++ b/cmat/Ex32/Ex32.vcxproj @@ -0,0 +1,127 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + {F5DDDD69-0B34-7FD5-AEAF-1BA6CC4705A1} + + + + Application + false + MultiByte + v140 + + + Application + false + MultiByte + v140 + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + .\Release\ + .\Release\ + false + .\Debug\ + .\Debug\ + true + + + + OnlyExplicitInline + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + true + + + .\Release/Ex32.pch + .\Release/ + .\Release/ + .\Release/ + Level3 + true + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Release/Ex32.exe + true + .\Release/Ex32.pdb + Console + + + .\Release/Ex32.tlb + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + true + + + .\Debug/Ex32.pch + .\Debug/ + .\Debug/ + .\Debug/ + Level3 + true + EditAndContinue + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Debug/Ex32.exe + true + true + .\Debug/Ex32.pdb + Console + + + .\Debug/Ex32.tlb + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + + + + + + + + \ No newline at end of file diff --git a/cmat/Ex32/Ex32.vcxproj.filters b/cmat/Ex32/Ex32.vcxproj.filters new file mode 100644 index 0000000..87c1488 --- /dev/null +++ b/cmat/Ex32/Ex32.vcxproj.filters @@ -0,0 +1,23 @@ + + + + + {d72b3ee0-72e7-4847-905d-3d8abcc3ab6b} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {a9a6650f-a77e-480b-aeb1-1b246b42abd0} + h;hpp;hxx;hm;inl + + + + + Source Files + + + + + Header Files + + + \ No newline at end of file diff --git a/cmat/Ex32/Ex32.vcxproj.user b/cmat/Ex32/Ex32.vcxproj.user new file mode 100644 index 0000000..695b5c7 --- /dev/null +++ b/cmat/Ex32/Ex32.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cmat/Ex32/Pixel.h b/cmat/Ex32/Pixel.h new file mode 100644 index 0000000..bfc44c7 --- /dev/null +++ b/cmat/Ex32/Pixel.h @@ -0,0 +1,22 @@ + +#ifndef Pixel_h +#define Pixel_h + +#include + +class Pixel { + public: + Pixel(int x = 0, int y = 0) : x(x), y(y) {} + + void print() const { std::cout << '(' << x << "," << y << ") "; } + + bool operator<(const Pixel &rhs) const { return x < rhs.x; } + + bool operator==(const Pixel &rhs) const { return x == rhs.x; } + + private: + int x; + int y; +}; + +#endif diff --git a/cmat/Ex32/main.cpp b/cmat/Ex32/main.cpp new file mode 100644 index 0000000..4a5c13b --- /dev/null +++ b/cmat/Ex32/main.cpp @@ -0,0 +1,63 @@ + +#include "Pixel.h" + +#include +#include +#include + +void pixelPrint(const Pixel &pixel) { pixel.print(); } + +int main() { + using namespace std; + + // From Ex 3.1 + + // preamble + Pixel pixel0; + cout << "Preamble:" << endl; + pixel0.print(); + cout << endl; + + Pixel pixel1(1, 2); + Pixel pixel2(3, 3); + Pixel pixel3(2, 4); + Pixel pixel4(5, 2); + Pixel pixel5(4, 2); + + // 3.1 part 1 + cout << "3.1 Part 1:" << endl; + vector pixelVec; + pixelVec.push_back(pixel1); + pixelVec.push_back(pixel2); + pixelVec.push_back(pixel3); + pixelVec.push_back(pixel4); + pixelVec.push_back(pixel5); + + for (unsigned int i = 0; i < pixelVec.size(); ++i) { + pixelVec[i].print(); + } + cout << endl; + + // 3.1 part 2 + cout << "3.1 Part 2:" << endl; + for (vector::iterator iter = pixelVec.begin(); iter != pixelVec.end(); ++iter) { + iter->print(); + } + cout << endl; + for (vector::reverse_iterator r_iter = pixelVec.rbegin(); r_iter != pixelVec.rend(); ++r_iter) { + r_iter->print(); + } + cout << endl; + + // 3.1 part 3 + cout << "3.1 Part 3:" << endl; + for_each(pixelVec.begin(), pixelVec.end(), pixelPrint); + cout << endl; + sort(pixelVec.begin(), pixelVec.end()); + for_each(pixelVec.begin(), pixelVec.end(), pixelPrint); + cout << endl; + + // insert code here *************************************** + + return 0; +} \ No newline at end of file diff --git a/cmat/Ex33/CMakeLists.txt b/cmat/Ex33/CMakeLists.txt new file mode 100644 index 0000000..14df64e --- /dev/null +++ b/cmat/Ex33/CMakeLists.txt @@ -0,0 +1,6 @@ +# Ex33 + +cmat_add_exercise(Ex33 + SOURCES + main.cpp +) diff --git a/cmat/Ex33/Ex33.sln b/cmat/Ex33/Ex33.sln new file mode 100644 index 0000000..4f98e7d --- /dev/null +++ b/cmat/Ex33/Ex33.sln @@ -0,0 +1,26 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.24720.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ex33", "Ex33.vcxproj", "{E3A48AF6-B757-7B89-D258-F569940E3991}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E3A48AF6-B757-7B89-D258-F569940E3991}.Debug|Win32.ActiveCfg = Debug|Win32 + {E3A48AF6-B757-7B89-D258-F569940E3991}.Debug|Win32.Build.0 = Debug|Win32 + {E3A48AF6-B757-7B89-D258-F569940E3991}.Debug|x64.ActiveCfg = Debug|Win32 + {E3A48AF6-B757-7B89-D258-F569940E3991}.Debug|x64.Build.0 = Debug|Win32 + {E3A48AF6-B757-7B89-D258-F569940E3991}.Release|Win32.ActiveCfg = Release|Win32 + {E3A48AF6-B757-7B89-D258-F569940E3991}.Release|x64.ActiveCfg = Release|x64 + {E3A48AF6-B757-7B89-D258-F569940E3991}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/cmat/Ex33/Ex33.suo b/cmat/Ex33/Ex33.suo new file mode 100644 index 0000000..1028312 Binary files /dev/null and b/cmat/Ex33/Ex33.suo differ diff --git a/cmat/Ex33/Ex33.vcproj b/cmat/Ex33/Ex33.vcproj new file mode 100644 index 0000000..a547b73 --- /dev/null +++ b/cmat/Ex33/Ex33.vcproj @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cmat/Ex33/Ex33.vcxproj b/cmat/Ex33/Ex33.vcxproj new file mode 100644 index 0000000..1f047ea --- /dev/null +++ b/cmat/Ex33/Ex33.vcxproj @@ -0,0 +1,223 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {E3A48AF6-B757-7B89-D258-F569940E3991} + + + + Application + false + MultiByte + v140 + + + Application + false + MultiByte + v140 + + + Application + false + MultiByte + v140 + + + Application + false + MultiByte + v140 + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + .\Release\ + .\Release\ + false + false + .\Debug\ + .\Debug\ + true + true + + + + OnlyExplicitInline + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + true + + + .\Release/Ex33.pch + .\Release/ + .\Release/ + .\Release/ + Level3 + true + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Release/Ex33.exe + true + .\Release/Ex33.pdb + Console + + + .\Release/Ex33.tlb + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + OnlyExplicitInline + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + true + + + .\Release/Ex33.pch + .\Release/ + .\Release/ + .\Release/ + Level3 + true + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Release/Ex33.exe + true + .\Release/Ex33.pdb + Console + + + .\Release/Ex33.tlb + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + true + + + .\Debug/Ex33.pch + .\Debug/ + .\Debug/ + .\Debug/ + Level3 + true + EditAndContinue + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Debug/Ex33.exe + true + true + .\Debug/Ex33.pdb + Console + false + + + .\Debug/Ex33.tlb + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + true + + + .\Debug/Ex33.pch + .\Debug/ + .\Debug/ + .\Debug/ + Level3 + true + ProgramDatabase + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Debug/Ex33.exe + true + true + .\Debug/Ex33.pdb + Console + false + + + .\Debug/Ex33.tlb + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + + + + + + + + \ No newline at end of file diff --git a/cmat/Ex33/Ex33.vcxproj.filters b/cmat/Ex33/Ex33.vcxproj.filters new file mode 100644 index 0000000..c058673 --- /dev/null +++ b/cmat/Ex33/Ex33.vcxproj.filters @@ -0,0 +1,23 @@ + + + + + {30d4d97f-a28a-416e-8f3b-51af12cbfddf} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {a39d7036-25c2-41d5-9406-9e596bc49b53} + h;hpp;hxx;hm;inl + + + + + Source Files + + + + + Header Files + + + \ No newline at end of file diff --git a/cmat/Ex33/Ex33.vcxproj.user b/cmat/Ex33/Ex33.vcxproj.user new file mode 100644 index 0000000..695b5c7 --- /dev/null +++ b/cmat/Ex33/Ex33.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cmat/Ex33/Pixel.h b/cmat/Ex33/Pixel.h new file mode 100644 index 0000000..fecff92 --- /dev/null +++ b/cmat/Ex33/Pixel.h @@ -0,0 +1,42 @@ + +#ifndef Pixel_h +#define Pixel_h + +#include +#include + +class Pixel { + public: + Pixel(int x = 0, int y = 0) : x(x), y(y) {} + + void print() const { std::cout << '(' << x << "," << y << ") "; } + + bool operator<(const Pixel &rhs) const { return x < rhs.x; } + + bool operator==(const Pixel &rhs) const { return x == rhs.x; } + + private: + int x; + int y; + + friend class PixelPtrCompare; +}; + +class PixelPtrCompare { + public: + PixelPtrCompare() : sortOnY(false) {} + + void setSortOnY(bool sortY) { this->sortOnY = sortY; } + + bool operator()(const Pixel *l, const Pixel *r) const { + if (sortOnY) + return l->y < r->y; + else + return l->x < r->x; + } + + private: + bool sortOnY; +}; + +#endif diff --git a/cmat/Ex33/main.cpp b/cmat/Ex33/main.cpp new file mode 100644 index 0000000..407fbfe --- /dev/null +++ b/cmat/Ex33/main.cpp @@ -0,0 +1,85 @@ + +#include "Pixel.h" + +#include +#include +#include + +void pixelPrint(const Pixel &pixel) { pixel.print(); } + +void pixelPtrPrint(const Pixel *pixel) { pixel->print(); } + +int main() { + using namespace std; + + // preamble + Pixel pixel0; + cout << "Preamble:" << endl; + pixel0.print(); + cout << endl; + + Pixel pixel1(1, 2); + Pixel pixel2(3, 3); + Pixel pixel3(2, 4); + Pixel pixel4(5, 2); + Pixel pixel5(4, 2); + + // 3.1 part 1 + cout << "3.1 Part 1:" << endl; + vector pixelVec; + pixelVec.push_back(pixel1); + pixelVec.push_back(pixel2); + pixelVec.push_back(pixel3); + pixelVec.push_back(pixel4); + pixelVec.push_back(pixel5); + + for (unsigned int i = 0; i < pixelVec.size(); ++i) { + pixelVec[i].print(); + } + cout << endl; + + // 3.1 part 2 + cout << "3.1 Part 2:" << endl; + for (vector::iterator iter = pixelVec.begin(); iter != pixelVec.end(); ++iter) { + iter->print(); + } + cout << endl; + for (vector::reverse_iterator r_iter = pixelVec.rbegin(); r_iter != pixelVec.rend(); ++r_iter) { + r_iter->print(); + } + cout << endl; + + // 3.1 part 3 + cout << "3.1 Part 3:" << endl; + for_each(pixelVec.begin(), pixelVec.end(), pixelPrint); + cout << endl; + sort(pixelVec.begin(), pixelVec.end()); + for_each(pixelVec.begin(), pixelVec.end(), pixelPrint); + cout << endl; + + // 3.2 + cout << "3.2, Part 1:" << endl; + vector pixelPtrVec; + pixelPtrVec.push_back(&pixel1); + pixelPtrVec.push_back(&pixel2); + pixelPtrVec.push_back(&pixel3); + pixelPtrVec.push_back(&pixel4); + pixelPtrVec.push_back(&pixel5); + + for_each(pixelPtrVec.begin(), pixelPtrVec.end(), pixelPtrPrint); + cout << endl; + PixelPtrCompare pixelPtrComp; + sort(pixelPtrVec.begin(), pixelPtrVec.end(), pixelPtrComp); + for_each(pixelPtrVec.begin(), pixelPtrVec.end(), pixelPtrPrint); + cout << endl; + pixelPtrComp.setSortOnY(true); + sort(pixelPtrVec.begin(), pixelPtrVec.end(), pixelPtrComp); + for_each(pixelPtrVec.begin(), pixelPtrVec.end(), pixelPtrPrint); + cout << endl; + + cout << endl; + + // insert code here... + + return 0; +} \ No newline at end of file diff --git a/cmat/Ex33/x64/Debug/Ex33.tlog/unsuccessfulbuild b/cmat/Ex33/x64/Debug/Ex33.tlog/unsuccessfulbuild new file mode 100644 index 0000000..e69de29 diff --git a/cmat/Ex33/x64/Release/Ex33.tlog/unsuccessfulbuild b/cmat/Ex33/x64/Release/Ex33.tlog/unsuccessfulbuild new file mode 100644 index 0000000..e69de29 diff --git a/cmat/Ex41/CMakeLists.txt b/cmat/Ex41/CMakeLists.txt new file mode 100644 index 0000000..40f4d39 --- /dev/null +++ b/cmat/Ex41/CMakeLists.txt @@ -0,0 +1,14 @@ +# Ex41 + +cmat_add_exercise(Ex41 + GUI + SOURCES + Light.cpp + main.cpp + Pelican.cpp + PelicanTimer.cpp + Pole.cpp + Subject.cpp + Timer.cpp + TimerSet.cpp +) diff --git a/cmat/Ex41/Ex41.sln b/cmat/Ex41/Ex41.sln new file mode 100644 index 0000000..419d6cc --- /dev/null +++ b/cmat/Ex41/Ex41.sln @@ -0,0 +1,20 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ex41", "Ex41.vcxproj", "{2B6BAD2C-A2F1-99CD-6A27-DD0BBF12E5A4}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2B6BAD2C-A2F1-99CD-6A27-DD0BBF12E5A4}.Debug|Win32.ActiveCfg = Debug|Win32 + {2B6BAD2C-A2F1-99CD-6A27-DD0BBF12E5A4}.Debug|Win32.Build.0 = Debug|Win32 + {2B6BAD2C-A2F1-99CD-6A27-DD0BBF12E5A4}.Release|Win32.ActiveCfg = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/cmat/Ex41/Ex41.suo b/cmat/Ex41/Ex41.suo new file mode 100644 index 0000000..eda747b Binary files /dev/null and b/cmat/Ex41/Ex41.suo differ diff --git a/cmat/Ex41/Ex41.vcproj b/cmat/Ex41/Ex41.vcproj new file mode 100644 index 0000000..f10d6ef --- /dev/null +++ b/cmat/Ex41/Ex41.vcproj @@ -0,0 +1,194 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cmat/Ex41/Ex41.vcxproj b/cmat/Ex41/Ex41.vcxproj new file mode 100644 index 0000000..13b07d4 --- /dev/null +++ b/cmat/Ex41/Ex41.vcxproj @@ -0,0 +1,144 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + {2B6BAD2C-A2F1-99CD-6A27-DD0BBF12E5A4} + + + + Application + false + MultiByte + v140 + + + Application + false + MultiByte + v140 + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + .\Debug\ + .\Debug\ + true + .\Release\ + .\Release\ + false + + + + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + true + NotUsing + .\Debug/Ex41.pch + .\Debug/ + .\Debug/ + .\Debug/ + Level3 + true + C:\course\397\DOS_Unix;%(AdditionalIncludeDirectories) + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Debug/Ex41.exe + true + true + .\Debug/Ex41.pdb + Console + + + .\Debug/Ex41.tlb + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + OnlyExplicitInline + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + true + + + .\Release/Ex41.pch + .\Release/ + .\Release/ + .\Release/ + Level3 + true + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Release/Ex41.exe + true + .\Release/Ex41.pdb + Console + + + .\Release/Ex41.tlb + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cmat/Ex41/Ex41.vcxproj.filters b/cmat/Ex41/Ex41.vcxproj.filters new file mode 100644 index 0000000..9d84e29 --- /dev/null +++ b/cmat/Ex41/Ex41.vcxproj.filters @@ -0,0 +1,80 @@ + + + + + {d342b4ff-da53-4cfa-9c78-ecc4af2f56cd} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {1e58a93c-2ba4-46f3-bde3-fdef6055c3a4} + h;hpp;hxx;hm;inl + + + {7d8dd5fa-5328-4693-8b68-b95e098fcdd6} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + DOS_Unix + + + DOS_Unix + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + DOS_Unix + + + DOS_Unix + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/cmat/Ex41/Ex41.vcxproj.user b/cmat/Ex41/Ex41.vcxproj.user new file mode 100644 index 0000000..695b5c7 --- /dev/null +++ b/cmat/Ex41/Ex41.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cmat/Ex41/Light.cpp b/cmat/Ex41/Light.cpp new file mode 100644 index 0000000..b59da2a --- /dev/null +++ b/cmat/Ex41/Light.cpp @@ -0,0 +1,20 @@ + +#include "Light.h" +#include "Pelican.h" +#include "Screen.h" +#include + +Light::Light(std::string name, int x, int y, int color) : x(x), y(y), c(color), name(name) {} + +Light::~Light() { + std::cout << "Deleting light (" << name << ", " << x << ", " << y << ", " << c << ")" + << "\n"; +} + +void Light::set(LightState newState) { + state = newState; + Screen::write(name.c_str(), x, y, state == FLASH ? (128 + c) : (state == OFF ? 0 : c)); + // 128 + color was used to make a character flash (but not any more) +} + +Light::LightState Light::get(void) { return state; } diff --git a/cmat/Ex41/Light.h b/cmat/Ex41/Light.h new file mode 100644 index 0000000..03adf9a --- /dev/null +++ b/cmat/Ex41/Light.h @@ -0,0 +1,30 @@ +// ====================================================== +// +// Represents a light, implemented as a string written +// to a console window +// +// ====================================================== + +#ifndef LIGHT_H +#define LIGHT_H + +#include + +class Light { + public: + Light(std::string name, int x, int y, int color); + ~Light(); + + enum LightState { ON, OFF, FLASH }; + + void set(LightState new_state); + LightState get(void); + + private: + int c; // light colour + int x, y; + std::string name; + LightState state; +}; + +#endif diff --git a/cmat/Ex41/Observer.h b/cmat/Ex41/Observer.h new file mode 100644 index 0000000..668fe8a --- /dev/null +++ b/cmat/Ex41/Observer.h @@ -0,0 +1,10 @@ + +#ifndef OBSERVER_H +#define OBSERVER_H + +class Observer { + public: + // TODO: declare the pure virtual function update() +}; + +#endif diff --git a/cmat/Ex41/Pelican.cpp b/cmat/Ex41/Pelican.cpp new file mode 100644 index 0000000..218611c --- /dev/null +++ b/cmat/Ex41/Pelican.cpp @@ -0,0 +1,65 @@ + +#include "Pelican.h" +#include "PelicanTimer.h" +#include "Pole.h" + +Pelican::Pelican(int x, int y) + : pressed(false), RED_TIME(4), YELLOW_TIME(2), GREEN_TIME(3), FLASH_TIME(5), myPole(new Pole(x, y)), + state(GREEN_IDLE) { + myTimer = new PelicanTimer(*this, &Pelican::timerExpired); + + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed()); +} + +Pelican::~Pelican() { delete myPole; } + +void Pelican::press(void) { + if (state == GREEN_IDLE) { + state = YELLOW_STATE; + myTimer->timeoutRequest(YELLOW_TIME); + pressed = true; + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed()); + } else if (state != RED_STATE) { + pressed = true; + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed()); + } +} + +void Pelican::timerExpired(void) { + switch (state) { + case RED_STATE: + state = YELLOW_FLASHING; + myTimer->timeoutRequest(FLASH_TIME); + break; + + case YELLOW_FLASHING: + state = GREEN_TIMING; + myTimer->timeoutRequest(GREEN_TIME); + break; + + case GREEN_TIMING: + if (pressed) { + state = YELLOW_STATE; + myTimer->timeoutRequest(YELLOW_TIME); + } else { + state = GREEN_IDLE; + } + break; + + case GREEN_IDLE: + // should never happen + break; + + case YELLOW_STATE: + state = RED_STATE; + pressed = false; + myTimer->timeoutRequest(RED_TIME); + break; + } + + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed()); +} diff --git a/cmat/Ex41/Pelican.h b/cmat/Ex41/Pelican.h new file mode 100644 index 0000000..b7c8da0 --- /dev/null +++ b/cmat/Ex41/Pelican.h @@ -0,0 +1,53 @@ +// ====================================================== +// +// Represents a Pelican crossing +// +// ====================================================== + +#ifndef PELICAN_H +#define PELICAN_H + +class PelicanTimer; +class Pole; + +class Pelican { + public: + Pelican(int x, int y); + ~Pelican(); + + // call when the WAIT button has been pressed + void press(void); + + // states that a Pelican can be in + enum PelicanState { RED_STATE, YELLOW_FLASHING, GREEN_TIMING, GREEN_IDLE, YELLOW_STATE }; + + bool isPressed() const { return pressed; } + PelicanState getState() const { return state; } + + private: + // state that this Pelican is in + PelicanState state; + + // called by PeleicanTimer when the lights need to change + void timerExpired(void); + + const unsigned int RED_TIME; + const unsigned int YELLOW_TIME; + const unsigned int GREEN_TIME; + const unsigned int FLASH_TIME; + + // indicates whether the WAIT light should be on + bool pressed; + + Pole *myPole; + + // Timer that indicates when the lights should change + PelicanTimer *myTimer; + + private: + // prevent general use of copy ctor and operator= + Pelican(const Pelican &); + Pelican &operator=(const Pelican &); +}; + +#endif diff --git a/cmat/Ex41/PelicanTimer.cpp b/cmat/Ex41/PelicanTimer.cpp new file mode 100644 index 0000000..b5af0ad --- /dev/null +++ b/cmat/Ex41/PelicanTimer.cpp @@ -0,0 +1,6 @@ + +#include "PelicanTimer.h" + +PelicanTimer::PelicanTimer(Pelican &target, TargetFunc targetFunc) : myTarget(target), myTargetFunc(targetFunc) {} + +void PelicanTimer::doExpired() { (myTarget.*myTargetFunc)(); } diff --git a/cmat/Ex41/PelicanTimer.h b/cmat/Ex41/PelicanTimer.h new file mode 100644 index 0000000..637290c --- /dev/null +++ b/cmat/Ex41/PelicanTimer.h @@ -0,0 +1,27 @@ +// ====================================================== +// +// This class specializes the Timer to enable it to +// stimulate a Pelican +// +// ====================================================== + +#ifndef PelicanTimer_H +#define PelicanTimer_H + +#include "Pelican.h" +#include "Timer.h" + +class PelicanTimer : public Timer { + public: + typedef void (Pelican::*TargetFunc)(); + + PelicanTimer(Pelican &target, TargetFunc targetFunc); + + private: + void doExpired(); + + Pelican &myTarget; + TargetFunc myTargetFunc; +}; + +#endif diff --git a/cmat/Ex41/Pole.cpp b/cmat/Ex41/Pole.cpp new file mode 100644 index 0000000..aeec308 --- /dev/null +++ b/cmat/Ex41/Pole.cpp @@ -0,0 +1,59 @@ +#include "Pole.h" +#include "Screen.h" + +Pole::Pole(int x, int y) : waitLight(new Light("WAIT", x + 6, y + 12, Screen::WHITE)) { + using namespace Screen; // we will discuss namespaces in the course + + lights[RED_LIGHT] = new Light("*", x + 11, y + 3, RED); + lights[RED_MAN] = new Light("*<-=", x + 6, y + 4, RED); + lights[YELLOW_LIGHT] = new Light("*", x + 11, y + 5, YELLOW); + lights[GREEN_LIGHT] = new Light("*", x + 11, y + 7, GREEN); + lights[GREEN_MAN] = new Light("*|-<", x + 6, y + 7, GREEN); + + write(" _____ ", x, ++y, GRAY); + write(" /___ /| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" | |/| ", x, ++y, GRAY); + write(" |____| | ", x, ++y, GRAY); + write(" | |/| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" |____|/ ", x, ++y, GRAY); + write(" _||__ ", x, ++y, GRAY); + write(" /___ /| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" |____|/ ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write("========||===========", x, ++y, GRAY); + write(" / || / ", x, ++y, GRAY); + write("_ /_________ /_ ", x, ++y, GRAY); + write("/ / ", x, ++y, GRAY); +} + +Pole::~Pole() { + for (int i = 0; i < sizeof lights / sizeof(lights[0]); ++i) + delete lights[i]; + delete waitLight; +} + +void Pole::setTrafficLights(Pelican::PelicanState state) { + static const Light::LightState LightStates[Pelican::YELLOW_STATE + 1][RED_MAN + 1] = { + // red yellow green green man red man + {Light::ON, Light::OFF, Light::OFF, Light::ON, Light::OFF}, // red + {Light::OFF, Light::FLASH, Light::OFF, Light::FLASH, Light::OFF}, // y flash + {Light::OFF, Light::OFF, Light::ON, Light::OFF, Light::ON}, // g time + {Light::OFF, Light::OFF, Light::ON, Light::OFF, Light::ON}, // g idle + {Light::OFF, Light::ON, Light::OFF, Light::OFF, Light::ON} // yellow + }; + + for (int i = RED_LIGHT; i <= RED_MAN; i++) { + lights[i]->set(LightStates[state][i]); + } +} + +void Pole::setWaitLight(bool pressed) { waitLight->set(pressed ? Light::ON : Light::OFF); } diff --git a/cmat/Ex41/Pole.h b/cmat/Ex41/Pole.h new file mode 100644 index 0000000..a62d29b --- /dev/null +++ b/cmat/Ex41/Pole.h @@ -0,0 +1,24 @@ + +#ifndef POLE_H +#define POLE_H + +#include "Light.h" +#include "Pelican.h" + +class Pole { + public: + Pole(int x, int y); + ~Pole(); + + void setTrafficLights(Pelican::PelicanState state); + void setWaitLight(bool pressed); + + private: + enum LightName { RED_LIGHT, YELLOW_LIGHT, GREEN_LIGHT, GREEN_MAN, RED_MAN }; + + Light *lights[RED_MAN + 1]; + + Light *waitLight; +}; + +#endif diff --git a/cmat/Ex41/Subject.cpp b/cmat/Ex41/Subject.cpp new file mode 100644 index 0000000..5d8e5ca --- /dev/null +++ b/cmat/Ex41/Subject.cpp @@ -0,0 +1,8 @@ + + +#include "Subject.h" +#include "Observer.h" + +// TODO: Implement the Subject::attach() member function that adds an Observer to the set + +// TODO: Implement the Subject::notify() member function that calls all the update functions diff --git a/cmat/Ex41/Subject.h b/cmat/Ex41/Subject.h new file mode 100644 index 0000000..f717d74 --- /dev/null +++ b/cmat/Ex41/Subject.h @@ -0,0 +1,18 @@ + +#ifndef SUBJECT_H +#define SUBJECT_H + +class Observer; + +#include + +class Subject { + public: + // TODO: Declare the attach() function that adds an Observer to the set + protected: + // TODO: Declare the notify() function that calls all the update functions + private: + // TODO: Define a set of Observer pointers +}; + +#endif diff --git a/cmat/Ex41/Timer.cpp b/cmat/Ex41/Timer.cpp new file mode 100644 index 0000000..e62ee48 --- /dev/null +++ b/cmat/Ex41/Timer.cpp @@ -0,0 +1,22 @@ + +#include "Timer.h" +#include "TimerSet.h" + +void Timer::timeoutRequest(int seconds) { timeToGo = seconds; } + +Timer::Timer() : timeToGo(-1) { TimerSet::Instance().addATimer(this); } + +void Timer::tick() { + if (isExpired()) { + doExpired(); + } +} + +bool Timer::isExpired() { + if (timeToGo > 0) { + if (--timeToGo == 0) { + return true; + } + } + return false; +} diff --git a/cmat/Ex41/Timer.h b/cmat/Ex41/Timer.h new file mode 100644 index 0000000..37d1ce9 --- /dev/null +++ b/cmat/Ex41/Timer.h @@ -0,0 +1,32 @@ +// ====================================================== +// +// A general-purpose countdown timer +// To use this class, specialize it +// and override tick() +// +// ====================================================== + +#ifndef timer_H +#define timer_H + +#include + +class Timer { + public: + Timer(); + + void timeoutRequest(int seconds); + + // template method + void tick(); + + protected: + bool isExpired(); + + private: + virtual void doExpired() = 0; + + int timeToGo; +}; + +#endif diff --git a/cmat/Ex41/TimerSet.cpp b/cmat/Ex41/TimerSet.cpp new file mode 100644 index 0000000..5606f75 --- /dev/null +++ b/cmat/Ex41/TimerSet.cpp @@ -0,0 +1,24 @@ +#include "TimerSet.h" +#include "Timer.h" +#include + +TimerSet::TimerSet() : previousTime(time(NULL)) {} + +void TimerSet::addATimer(Timer *t) { timers.push_back(t); } + +void TimerSet::pollAllTimers() { + std::time_t timeNow; + if (time(&timeNow) > previousTime) { + previousTime = timeNow; + + for (auto it = timers.begin(); it != timers.end(); it++) { + (*it)->tick(); + } + } +} + +TimerSet &TimerSet::Instance() { + // Meyer's Singleton implementation + static TimerSet pInstance; + return pInstance; +} diff --git a/cmat/Ex41/TimerSet.h b/cmat/Ex41/TimerSet.h new file mode 100644 index 0000000..35c2baf --- /dev/null +++ b/cmat/Ex41/TimerSet.h @@ -0,0 +1,29 @@ +#ifndef TIMERSET_H +#define TIMERSET_H + +#include +#include + +class Timer; + +class TimerSet { + public: + void pollAllTimers(); + void addATimer(Timer *); + + private: + TimerSet(); + std::vector timers; + std::time_t previousTime; + + // Meyer's singleton + public: + static TimerSet &Instance(); + + private: + // prevent copying and assignment of the singleton + TimerSet(const TimerSet &); + TimerSet &operator=(const TimerSet &); +}; + +#endif diff --git a/cmat/Ex41/main.cpp b/cmat/Ex41/main.cpp new file mode 100644 index 0000000..a28f2ab --- /dev/null +++ b/cmat/Ex41/main.cpp @@ -0,0 +1,28 @@ + +#include "Keyboard.h" +#include "Pelican.h" +#include "TimerSet.h" + +#include // provides toupper() + +int main() { + Keyboard kbd; + Pelican thePelican(30, 0); + + char c = 0; + + while (std::toupper(c) != 'Q') { // loop until 'Q' is pressed + + while (!kbd.isCharAvail()) { + TimerSet::Instance().pollAllTimers(); // no key press to process, poll the timers + } + + c = kbd.getChar(); // get the character + if (c == ' ') { + // it's a space, so press the WAIT button + thePelican.press(); + } + } + + return 0; +} diff --git a/cmat/Ex42/CMakeLists.txt b/cmat/Ex42/CMakeLists.txt new file mode 100644 index 0000000..a0418a4 --- /dev/null +++ b/cmat/Ex42/CMakeLists.txt @@ -0,0 +1,14 @@ +# Ex42 + +cmat_add_exercise(Ex42 + GUI + SOURCES + Light.cpp + main.cpp + Pelican.cpp + PelicanTimer.cpp + Pole.cpp + Subject.cpp + Timer.cpp + TimerSet.cpp +) diff --git a/cmat/Ex42/Ex42.sln b/cmat/Ex42/Ex42.sln new file mode 100644 index 0000000..bc7c20b --- /dev/null +++ b/cmat/Ex42/Ex42.sln @@ -0,0 +1,20 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ex42", "Ex42.vcxproj", "{F39C16B5-32B7-322D-F5D9-367B7F9EEEB8}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F39C16B5-32B7-322D-F5D9-367B7F9EEEB8}.Debug|Win32.ActiveCfg = Debug|Win32 + {F39C16B5-32B7-322D-F5D9-367B7F9EEEB8}.Debug|Win32.Build.0 = Debug|Win32 + {F39C16B5-32B7-322D-F5D9-367B7F9EEEB8}.Release|Win32.ActiveCfg = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/cmat/Ex42/Ex42.suo b/cmat/Ex42/Ex42.suo new file mode 100644 index 0000000..58216ee Binary files /dev/null and b/cmat/Ex42/Ex42.suo differ diff --git a/cmat/Ex42/Ex42.vcproj b/cmat/Ex42/Ex42.vcproj new file mode 100644 index 0000000..7c9d9a9 --- /dev/null +++ b/cmat/Ex42/Ex42.vcproj @@ -0,0 +1,194 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cmat/Ex42/Ex42.vcxproj b/cmat/Ex42/Ex42.vcxproj new file mode 100644 index 0000000..9001afd --- /dev/null +++ b/cmat/Ex42/Ex42.vcxproj @@ -0,0 +1,145 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + {F39C16B5-32B7-322D-F5D9-367B7F9EEEB8} + + + + Application + false + MultiByte + v140 + + + Application + false + MultiByte + v140 + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + .\Release\ + .\Release\ + false + .\Debug\ + .\Debug\ + true + + + + OnlyExplicitInline + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + true + + + .\Release/Ex42.pch + .\Release/ + .\Release/ + .\Release/ + Level3 + true + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Release/Ex42.exe + true + .\Release/Ex42.pdb + Console + + + .\Release/Ex42.tlb + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + true + NotUsing + .\Debug/Ex42.pch + .\Debug/ + .\Debug/ + .\Debug/ + Level3 + true + C:\course\397\DOS_Unix;%(AdditionalIncludeDirectories) + false + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Debug/Ex42.exe + true + true + .\Debug/Ex42.pdb + Console + + + .\Debug/Ex42.tlb + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cmat/Ex42/Ex42.vcxproj.filters b/cmat/Ex42/Ex42.vcxproj.filters new file mode 100644 index 0000000..91a19d0 --- /dev/null +++ b/cmat/Ex42/Ex42.vcxproj.filters @@ -0,0 +1,80 @@ + + + + + {71ef5090-ad5d-4a5a-ad8f-650d82bf21bb} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {c9b4ef1f-e7e6-42d9-913c-27e559907ee1} + h;hpp;hxx;hm;inl + + + {417d066f-541c-4c89-9db1-cbd5934a72c4} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + DOS_Unix + + + DOS_Unix + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + DOS_Unix + + + DOS_Unix + + + \ No newline at end of file diff --git a/cmat/Ex42/Ex42.vcxproj.user b/cmat/Ex42/Ex42.vcxproj.user new file mode 100644 index 0000000..695b5c7 --- /dev/null +++ b/cmat/Ex42/Ex42.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cmat/Ex42/Light.cpp b/cmat/Ex42/Light.cpp new file mode 100644 index 0000000..e111c52 --- /dev/null +++ b/cmat/Ex42/Light.cpp @@ -0,0 +1,21 @@ + + +#include "Light.h" +#include "Pelican.h" +#include "Screen.h" +#include + +Light::Light(std::string name, int x, int y, int color) : x(x), y(y), c(color), name(name) {} + +Light::~Light() { + std::cout << "Deleting light (" << name << ", " << x << ", " << y << ", " << c << ")" + << "\n"; +} + +void Light::set(LightState newState) { + state = newState; + Screen::write(name.c_str(), x, y, state == FLASH ? (128 + c) : (state == OFF ? 0 : c)); + // 128 + color was used to make a character flash (but not any more) +} + +Light::LightState Light::get(void) { return state; } diff --git a/cmat/Ex42/Light.h b/cmat/Ex42/Light.h new file mode 100644 index 0000000..03adf9a --- /dev/null +++ b/cmat/Ex42/Light.h @@ -0,0 +1,30 @@ +// ====================================================== +// +// Represents a light, implemented as a string written +// to a console window +// +// ====================================================== + +#ifndef LIGHT_H +#define LIGHT_H + +#include + +class Light { + public: + Light(std::string name, int x, int y, int color); + ~Light(); + + enum LightState { ON, OFF, FLASH }; + + void set(LightState new_state); + LightState get(void); + + private: + int c; // light colour + int x, y; + std::string name; + LightState state; +}; + +#endif diff --git a/cmat/Ex42/Observer.h b/cmat/Ex42/Observer.h new file mode 100644 index 0000000..b55a19e --- /dev/null +++ b/cmat/Ex42/Observer.h @@ -0,0 +1,10 @@ + +#ifndef OBSERVER_H +#define OBSERVER_H + +class Observer { + public: + virtual void update() = 0; +}; + +#endif diff --git a/cmat/Ex42/Pelican.cpp b/cmat/Ex42/Pelican.cpp new file mode 100644 index 0000000..8cde63a --- /dev/null +++ b/cmat/Ex42/Pelican.cpp @@ -0,0 +1,55 @@ + + +#include "Pelican.h" +#include "PelicanTimer.h" + +Pelican::Pelican() : pressed(false), RED_TIME(4), YELLOW_TIME(2), GREEN_TIME(3), FLASH_TIME(5), state(GREEN_IDLE) { + myTimer = new PelicanTimer(*this, &Pelican::timerExpired); +} + +void Pelican::press(void) { + if (state == GREEN_IDLE) { + state = YELLOW_STATE; + myTimer->timeoutRequest(YELLOW_TIME); + pressed = true; + notify(); + } else if (state != RED_STATE) { + pressed = true; + notify(); + } +} + +void Pelican::timerExpired(void) { + switch (state) { + case RED_STATE: + state = YELLOW_FLASHING; + myTimer->timeoutRequest(FLASH_TIME); + break; + + case YELLOW_FLASHING: + state = GREEN_TIMING; + myTimer->timeoutRequest(GREEN_TIME); + break; + + case GREEN_TIMING: + if (pressed) { + state = YELLOW_STATE; + myTimer->timeoutRequest(YELLOW_TIME); + } else { + state = GREEN_IDLE; + } + break; + + case GREEN_IDLE: + // should never happen + break; + + case YELLOW_STATE: + state = RED_STATE; + pressed = false; + myTimer->timeoutRequest(RED_TIME); + break; + } + + notify(); +} diff --git a/cmat/Ex42/Pelican.h b/cmat/Ex42/Pelican.h new file mode 100644 index 0000000..6527cd5 --- /dev/null +++ b/cmat/Ex42/Pelican.h @@ -0,0 +1,51 @@ +// ====================================================== +// +// Represents a Pelican crossing +// +// ====================================================== + +#ifndef PELICAN_H +#define PELICAN_H + +#include "Subject.h" + +class PelicanTimer; + +class Pelican : public Subject { + public: + Pelican(); + + // call when the WAIT button has been pressed + void press(void); + + // states that a Pelican can be in + enum PelicanState { RED_STATE, YELLOW_FLASHING, GREEN_TIMING, GREEN_IDLE, YELLOW_STATE }; + + bool isPressed() const { return pressed; } + PelicanState getState() const { return state; } + + private: + // state that this Pelican is in + PelicanState state; + + // called by PelicanTimer when the lights need to change + void timerExpired(void); + + const unsigned int RED_TIME; + const unsigned int YELLOW_TIME; + const unsigned int GREEN_TIME; + const unsigned int FLASH_TIME; + + // indicates whether the WAIT light should be on + bool pressed; + + // Timer that indicates when the lights should change + PelicanTimer *myTimer; + + private: + // prevent general use of copy ctor and operator= + Pelican(const Pelican &); + Pelican &operator=(const Pelican &); +}; + +#endif diff --git a/cmat/Ex42/PelicanTimer.cpp b/cmat/Ex42/PelicanTimer.cpp new file mode 100644 index 0000000..f9c107a --- /dev/null +++ b/cmat/Ex42/PelicanTimer.cpp @@ -0,0 +1,7 @@ + + +#include "PelicanTimer.h" + +PelicanTimer::PelicanTimer(Pelican &target, TargetFunc targetFunc) : myTarget(target), myTargetFunc(targetFunc) {} + +void PelicanTimer::doExpired() { (myTarget.*myTargetFunc)(); } diff --git a/cmat/Ex42/PelicanTimer.h b/cmat/Ex42/PelicanTimer.h new file mode 100644 index 0000000..637290c --- /dev/null +++ b/cmat/Ex42/PelicanTimer.h @@ -0,0 +1,27 @@ +// ====================================================== +// +// This class specializes the Timer to enable it to +// stimulate a Pelican +// +// ====================================================== + +#ifndef PelicanTimer_H +#define PelicanTimer_H + +#include "Pelican.h" +#include "Timer.h" + +class PelicanTimer : public Timer { + public: + typedef void (Pelican::*TargetFunc)(); + + PelicanTimer(Pelican &target, TargetFunc targetFunc); + + private: + void doExpired(); + + Pelican &myTarget; + TargetFunc myTargetFunc; +}; + +#endif diff --git a/cmat/Ex42/Pole.cpp b/cmat/Ex42/Pole.cpp new file mode 100644 index 0000000..fdf9826 --- /dev/null +++ b/cmat/Ex42/Pole.cpp @@ -0,0 +1,68 @@ +#include "Pole.h" +#include "Screen.h" + +Pole::Pole(int x, int y, Pelican &p) : waitLight(new Light("WAIT", x + 6, y + 12, Screen::WHITE)), myPelican(p) { + myPelican.attach(*this); + + using namespace Screen; // we will discuss namespaces in the course + + lights[RED_LIGHT] = new Light("*", x + 11, y + 3, RED); + lights[RED_MAN] = new Light("*<-=", x + 6, y + 4, RED); + lights[YELLOW_LIGHT] = new Light("*", x + 11, y + 5, YELLOW); + lights[GREEN_LIGHT] = new Light("*", x + 11, y + 7, GREEN); + lights[GREEN_MAN] = new Light("*|-<", x + 6, y + 7, GREEN); + + write(" _____ ", x, ++y, GRAY); + write(" /___ /| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" | |/| ", x, ++y, GRAY); + write(" |____| | ", x, ++y, GRAY); + write(" | |/| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" |____|/ ", x, ++y, GRAY); + write(" _||__ ", x, ++y, GRAY); + write(" /___ /| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" |____|/ ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write("========||===========", x, ++y, GRAY); + write(" / || / ", x, ++y, GRAY); + write("_ /_________ /_ ", x, ++y, GRAY); + write("/ / ", x, ++y, GRAY); + + update(); +} + +Pole::~Pole() { + for (int i = 0; i < sizeof lights / sizeof(lights[0]); ++i) + delete lights[i]; + delete waitLight; +} + +void Pole::setTrafficLights(Pelican::PelicanState state) { + static const Light::LightState LightStates[Pelican::YELLOW_STATE + 1][RED_MAN + 1] = { + // red yellow green green man red man + {Light::ON, Light::OFF, Light::OFF, Light::ON, Light::OFF}, // red + {Light::OFF, Light::FLASH, Light::OFF, Light::FLASH, Light::OFF}, // y flash + {Light::OFF, Light::OFF, Light::ON, Light::OFF, Light::ON}, // g time + {Light::OFF, Light::OFF, Light::ON, Light::OFF, Light::ON}, // g idle + {Light::OFF, Light::ON, Light::OFF, Light::OFF, Light::ON} // yellow + }; + + for (int i = RED_LIGHT; i <= RED_MAN; i++) { + lights[i]->set(LightStates[state][i]); + } +} + +void Pole::setWaitLight(bool pressed) { waitLight->set(pressed ? Light::ON : Light::OFF); } + +void Pole::update() { + setTrafficLights(myPelican.getState()); + setWaitLight(myPelican.isPressed()); +} diff --git a/cmat/Ex42/Pole.h b/cmat/Ex42/Pole.h new file mode 100644 index 0000000..674fbfe --- /dev/null +++ b/cmat/Ex42/Pole.h @@ -0,0 +1,28 @@ + +#ifndef POLE_H +#define POLE_H + +#include "Light.h" +#include "Observer.h" +#include "Pelican.h" + +class Pole : public Observer { + public: + Pole(int x, int y, Pelican &p); + ~Pole(); + + void setTrafficLights(Pelican::PelicanState state); + void setWaitLight(bool pressed); + + void update(); + + private: + Pelican &myPelican; + + enum LightName { RED_LIGHT, YELLOW_LIGHT, GREEN_LIGHT, GREEN_MAN, RED_MAN }; + + Light *lights[RED_MAN + 1]; + Light *waitLight; +}; + +#endif diff --git a/cmat/Ex42/Subject.cpp b/cmat/Ex42/Subject.cpp new file mode 100644 index 0000000..c31e2b6 --- /dev/null +++ b/cmat/Ex42/Subject.cpp @@ -0,0 +1,12 @@ + + +#include "Subject.h" +#include "Observer.h" + +void Subject::attach(Observer &obs) { myObservers.insert(&obs); } + +void Subject::notify() const { + for (ObsList::const_iterator iter = myObservers.begin(); iter != myObservers.end(); ++iter) { + (*iter)->update(); + } +} diff --git a/cmat/Ex42/Subject.h b/cmat/Ex42/Subject.h new file mode 100644 index 0000000..245ff61 --- /dev/null +++ b/cmat/Ex42/Subject.h @@ -0,0 +1,20 @@ + + +#ifndef SUBJECT_H +#define SUBJECT_H + +class Observer; + +#include + +class Subject { + public: + typedef std::set ObsList; + void attach(Observer &obs); + void notify() const; + + private: + ObsList myObservers; +}; + +#endif diff --git a/cmat/Ex42/Timer.cpp b/cmat/Ex42/Timer.cpp new file mode 100644 index 0000000..9240bda --- /dev/null +++ b/cmat/Ex42/Timer.cpp @@ -0,0 +1,23 @@ + + +#include "Timer.h" +#include "TimerSet.h" + +void Timer::timeoutRequest(int seconds) { timeToGo = seconds; } + +Timer::Timer() : timeToGo(-1) { TimerSet::Instance().addATimer(this); } + +void Timer::tick() { + if (isExpired()) { + doExpired(); + } +} + +bool Timer::isExpired() { + if (timeToGo > 0) { + if (--timeToGo == 0) { + return true; + } + } + return false; +} diff --git a/cmat/Ex42/Timer.h b/cmat/Ex42/Timer.h new file mode 100644 index 0000000..37d1ce9 --- /dev/null +++ b/cmat/Ex42/Timer.h @@ -0,0 +1,32 @@ +// ====================================================== +// +// A general-purpose countdown timer +// To use this class, specialize it +// and override tick() +// +// ====================================================== + +#ifndef timer_H +#define timer_H + +#include + +class Timer { + public: + Timer(); + + void timeoutRequest(int seconds); + + // template method + void tick(); + + protected: + bool isExpired(); + + private: + virtual void doExpired() = 0; + + int timeToGo; +}; + +#endif diff --git a/cmat/Ex42/TimerSet.cpp b/cmat/Ex42/TimerSet.cpp new file mode 100644 index 0000000..5606f75 --- /dev/null +++ b/cmat/Ex42/TimerSet.cpp @@ -0,0 +1,24 @@ +#include "TimerSet.h" +#include "Timer.h" +#include + +TimerSet::TimerSet() : previousTime(time(NULL)) {} + +void TimerSet::addATimer(Timer *t) { timers.push_back(t); } + +void TimerSet::pollAllTimers() { + std::time_t timeNow; + if (time(&timeNow) > previousTime) { + previousTime = timeNow; + + for (auto it = timers.begin(); it != timers.end(); it++) { + (*it)->tick(); + } + } +} + +TimerSet &TimerSet::Instance() { + // Meyer's Singleton implementation + static TimerSet pInstance; + return pInstance; +} diff --git a/cmat/Ex42/TimerSet.h b/cmat/Ex42/TimerSet.h new file mode 100644 index 0000000..35c2baf --- /dev/null +++ b/cmat/Ex42/TimerSet.h @@ -0,0 +1,29 @@ +#ifndef TIMERSET_H +#define TIMERSET_H + +#include +#include + +class Timer; + +class TimerSet { + public: + void pollAllTimers(); + void addATimer(Timer *); + + private: + TimerSet(); + std::vector timers; + std::time_t previousTime; + + // Meyer's singleton + public: + static TimerSet &Instance(); + + private: + // prevent copying and assignment of the singleton + TimerSet(const TimerSet &); + TimerSet &operator=(const TimerSet &); +}; + +#endif diff --git a/cmat/Ex42/main.cpp b/cmat/Ex42/main.cpp new file mode 100644 index 0000000..3624dd0 --- /dev/null +++ b/cmat/Ex42/main.cpp @@ -0,0 +1,32 @@ + + +#include "Keyboard.h" +#include "Pelican.h" +#include "Pole.h" +#include "TimerSet.h" + +#include // provides toupper() + +int main() { + Keyboard kbd; + Pelican thePelican; + Pole pole1(20, 0, thePelican); + Pole pole2(40, 0, thePelican); + + char c = 0; + + while (std::toupper(c) != 'Q') { // loop until 'Q' is pressed + + while (!kbd.isCharAvail()) { + TimerSet::Instance().pollAllTimers(); // no key press to process, poll the timers + } + + c = kbd.getChar(); // get the character + if (c == ' ') { + // it's a space, so press the WAIT button + thePelican.press(); + } + } + + return 0; +} diff --git a/cmat/Ex51/CMakeLists.txt b/cmat/Ex51/CMakeLists.txt new file mode 100644 index 0000000..ac5a363 --- /dev/null +++ b/cmat/Ex51/CMakeLists.txt @@ -0,0 +1,14 @@ +# Ex51 + +cmat_add_exercise(Ex51 + GUI + SOURCES + Light.cpp + main.cpp + Pelican.cpp + PelicanTimer.cpp + Pole.cpp + Subject.cpp + Timer.cpp + TimerSet.cpp +) diff --git a/cmat/Ex51/Ex51.sln b/cmat/Ex51/Ex51.sln new file mode 100644 index 0000000..8f27b85 --- /dev/null +++ b/cmat/Ex51/Ex51.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ex51", "Ex51.vcxproj", "{AFB7826A-449B-436C-A7FC-4401601F082B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {AFB7826A-449B-436C-A7FC-4401601F082B}.Debug|Win32.ActiveCfg = Debug|Win32 + {AFB7826A-449B-436C-A7FC-4401601F082B}.Debug|Win32.Build.0 = Debug|Win32 + {AFB7826A-449B-436C-A7FC-4401601F082B}.Release|Win32.ActiveCfg = Release|Win32 + {AFB7826A-449B-436C-A7FC-4401601F082B}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/cmat/Ex51/Ex51.vcxproj b/cmat/Ex51/Ex51.vcxproj new file mode 100644 index 0000000..aef1c40 --- /dev/null +++ b/cmat/Ex51/Ex51.vcxproj @@ -0,0 +1,95 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {AFB7826A-449B-436C-A7FC-4401601F082B} + Ex51 + + + + Application + true + v140 + MultiByte + + + Application + false + v140 + true + MultiByte + + + + + + + + + + + + + + + Level3 + Disabled + true + C:\course\397\DOS_Unix; + + + true + Console + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cmat/Ex51/Ex51.vcxproj.filters b/cmat/Ex51/Ex51.vcxproj.filters new file mode 100644 index 0000000..db0c66c --- /dev/null +++ b/cmat/Ex51/Ex51.vcxproj.filters @@ -0,0 +1,80 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {075c2eca-b76b-43df-8022-827ab031c5e2} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + DOS_Unix + + + DOS_Unix + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + DOS_Unix + + + DOS_Unix + + + \ No newline at end of file diff --git a/cmat/Ex51/Ex51.vcxproj.user b/cmat/Ex51/Ex51.vcxproj.user new file mode 100644 index 0000000..2a22e69 --- /dev/null +++ b/cmat/Ex51/Ex51.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/cmat/Ex51/Light.cpp b/cmat/Ex51/Light.cpp new file mode 100644 index 0000000..e111c52 --- /dev/null +++ b/cmat/Ex51/Light.cpp @@ -0,0 +1,21 @@ + + +#include "Light.h" +#include "Pelican.h" +#include "Screen.h" +#include + +Light::Light(std::string name, int x, int y, int color) : x(x), y(y), c(color), name(name) {} + +Light::~Light() { + std::cout << "Deleting light (" << name << ", " << x << ", " << y << ", " << c << ")" + << "\n"; +} + +void Light::set(LightState newState) { + state = newState; + Screen::write(name.c_str(), x, y, state == FLASH ? (128 + c) : (state == OFF ? 0 : c)); + // 128 + color was used to make a character flash (but not any more) +} + +Light::LightState Light::get(void) { return state; } diff --git a/cmat/Ex51/Light.h b/cmat/Ex51/Light.h new file mode 100644 index 0000000..03adf9a --- /dev/null +++ b/cmat/Ex51/Light.h @@ -0,0 +1,30 @@ +// ====================================================== +// +// Represents a light, implemented as a string written +// to a console window +// +// ====================================================== + +#ifndef LIGHT_H +#define LIGHT_H + +#include + +class Light { + public: + Light(std::string name, int x, int y, int color); + ~Light(); + + enum LightState { ON, OFF, FLASH }; + + void set(LightState new_state); + LightState get(void); + + private: + int c; // light colour + int x, y; + std::string name; + LightState state; +}; + +#endif diff --git a/cmat/Ex51/Observer.h b/cmat/Ex51/Observer.h new file mode 100644 index 0000000..8304c48 --- /dev/null +++ b/cmat/Ex51/Observer.h @@ -0,0 +1,12 @@ + +#ifndef OBSERVER_H +#define OBSERVER_H + +#include "Subject.h" + +class Observer { + public: + virtual void update(const Hint &) = 0; +}; + +#endif diff --git a/cmat/Ex51/Pelican.cpp b/cmat/Ex51/Pelican.cpp new file mode 100644 index 0000000..fba7d3f --- /dev/null +++ b/cmat/Ex51/Pelican.cpp @@ -0,0 +1,58 @@ + +#include "Pelican.h" +#include "PelicanTimer.h" +#include "Pole.h" + +Pelican::Pelican() : pressed(false), RED_TIME(4), YELLOW_TIME(2), GREEN_TIME(3), FLASH_TIME(5), state(GREEN_IDLE) { + myTimer = new PelicanTimer(*this, &Pelican::timerExpired); +} + +void Pelican::press(void) { + if (state == GREEN_IDLE) { + state = YELLOW_STATE; + myTimer->timeoutRequest(YELLOW_TIME); + pressed = true; + + notify(WaitHint(pressed)); + notify(LightHint(state)); + } else if (state != RED_STATE) { + pressed = true; + notify(WaitHint(pressed)); + } +} + +void Pelican::timerExpired(void) { + switch (state) { + case RED_STATE: + state = YELLOW_FLASHING; + myTimer->timeoutRequest(FLASH_TIME); + break; + + case YELLOW_FLASHING: + state = GREEN_TIMING; + myTimer->timeoutRequest(GREEN_TIME); + break; + + case GREEN_TIMING: + if (pressed) { + state = YELLOW_STATE; + myTimer->timeoutRequest(YELLOW_TIME); + } else { + state = GREEN_IDLE; + } + break; + + case GREEN_IDLE: + // should never happen + break; + + case YELLOW_STATE: + state = RED_STATE; + pressed = false; + notify(WaitHint(pressed)); + myTimer->timeoutRequest(RED_TIME); + break; + } + + notify(LightHint(state)); +} diff --git a/cmat/Ex51/Pelican.h b/cmat/Ex51/Pelican.h new file mode 100644 index 0000000..7aa37f9 --- /dev/null +++ b/cmat/Ex51/Pelican.h @@ -0,0 +1,65 @@ +// ====================================================== +// +// Represents a Pelican crossing +// +// ====================================================== + +#ifndef PELICAN_H +#define PELICAN_H + +#include "Subject.h" + +class PelicanTimer; + +class Pelican : public Subject { + public: + Pelican(); + + // call when the WAIT button has been pressed + void press(void); + + // states that a Pelican can be in + enum PelicanState { RED_STATE, YELLOW_FLASHING, GREEN_TIMING, GREEN_IDLE, YELLOW_STATE }; + + bool isPressed() const { return pressed; } + PelicanState getState() const { return state; } + + private: + // state that this Pelican is in + PelicanState state; + + // called by PeleicanTimer when the lights need to change + void timerExpired(void); + + const unsigned int RED_TIME; + const unsigned int YELLOW_TIME; + const unsigned int GREEN_TIME; + const unsigned int FLASH_TIME; + + // indicates whether the WAIT light should be on + bool pressed; + + // Timer that indicates when the lights should change + PelicanTimer *myTimer; + + private: + // prevent general use of copy ctor and operator= + Pelican(const Pelican &); + Pelican &operator=(const Pelican &); +}; + +class LightHint : public Hint { + public: + LightHint(Pelican::PelicanState s) : state(s) {} + + Pelican::PelicanState state; +}; + +class WaitHint : public Hint { + public: + WaitHint(bool p) : pressed(p) {} + + bool pressed; +}; + +#endif diff --git a/cmat/Ex51/PelicanTimer.cpp b/cmat/Ex51/PelicanTimer.cpp new file mode 100644 index 0000000..f9c107a --- /dev/null +++ b/cmat/Ex51/PelicanTimer.cpp @@ -0,0 +1,7 @@ + + +#include "PelicanTimer.h" + +PelicanTimer::PelicanTimer(Pelican &target, TargetFunc targetFunc) : myTarget(target), myTargetFunc(targetFunc) {} + +void PelicanTimer::doExpired() { (myTarget.*myTargetFunc)(); } diff --git a/cmat/Ex51/PelicanTimer.h b/cmat/Ex51/PelicanTimer.h new file mode 100644 index 0000000..637290c --- /dev/null +++ b/cmat/Ex51/PelicanTimer.h @@ -0,0 +1,27 @@ +// ====================================================== +// +// This class specializes the Timer to enable it to +// stimulate a Pelican +// +// ====================================================== + +#ifndef PelicanTimer_H +#define PelicanTimer_H + +#include "Pelican.h" +#include "Timer.h" + +class PelicanTimer : public Timer { + public: + typedef void (Pelican::*TargetFunc)(); + + PelicanTimer(Pelican &target, TargetFunc targetFunc); + + private: + void doExpired(); + + Pelican &myTarget; + TargetFunc myTargetFunc; +}; + +#endif diff --git a/cmat/Ex51/Pole.cpp b/cmat/Ex51/Pole.cpp new file mode 100644 index 0000000..9da08c0 --- /dev/null +++ b/cmat/Ex51/Pole.cpp @@ -0,0 +1,78 @@ +#include "Pole.h" +#include "Screen.h" + +Pole::Pole(int x, int y, Pelican &p) : waitLight(new Light("WAIT", x + 6, y + 12, Screen::WHITE)), myPelican(p) { + myPelican.attach(*this); + + using namespace Screen; // we will discuss namespaces in the course + + lights[RED_LIGHT] = new Light("*", x + 11, y + 3, RED); + lights[RED_MAN] = new Light("*<-=", x + 6, y + 4, RED); + lights[YELLOW_LIGHT] = new Light("*", x + 11, y + 5, YELLOW); + lights[GREEN_LIGHT] = new Light("*", x + 11, y + 7, GREEN); + lights[GREEN_MAN] = new Light("*|-<", x + 6, y + 7, GREEN); + + write(" _____ ", x, ++y, GRAY); + write(" /___ /| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" | |/| ", x, ++y, GRAY); + write(" |____| | ", x, ++y, GRAY); + write(" | |/| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" |____|/ ", x, ++y, GRAY); + write(" _||__ ", x, ++y, GRAY); + write(" /___ /| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" |____|/ ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write("========||===========", x, ++y, GRAY); + write(" / || / ", x, ++y, GRAY); + write("_ /_________ /_ ", x, ++y, GRAY); + write("/ / ", x, ++y, GRAY); + + update(Hint()); +} + +Pole::~Pole() { + for (int i = 0; i < sizeof lights / sizeof(lights[0]); ++i) + delete lights[i]; + delete waitLight; +} + +void Pole::setTrafficLights(Pelican::PelicanState state) { + static const Light::LightState LightStates[Pelican::YELLOW_STATE + 1][RED_MAN + 1] = { + // red yellow green green man red man + {Light::ON, Light::OFF, Light::OFF, Light::ON, Light::OFF}, // red + {Light::OFF, Light::FLASH, Light::OFF, Light::FLASH, Light::OFF}, // y flash + {Light::OFF, Light::OFF, Light::ON, Light::OFF, Light::ON}, // g time + {Light::OFF, Light::OFF, Light::ON, Light::OFF, Light::ON}, // g idle + {Light::OFF, Light::ON, Light::OFF, Light::OFF, Light::ON} // yellow + }; + + for (int i = RED_LIGHT; i <= RED_MAN; i++) { + lights[i]->set(LightStates[state][i]); + } +} + +void Pole::setWaitLight(bool pressed) { waitLight->set(pressed ? Light::ON : Light::OFF); } + +void Pole::update(const Hint &h) { + const WaitHint *waitHintPtr; + const LightHint *lightHintPtr; + + if ((waitHintPtr = dynamic_cast(&h)) != 0) { + setWaitLight(waitHintPtr->pressed); + } else if ((lightHintPtr = dynamic_cast(&h)) != 0) { + setTrafficLights(lightHintPtr->state); + } else { + // don't know what's changed, so update everything + setTrafficLights(myPelican.getState()); + setWaitLight(myPelican.isPressed()); + } +} diff --git a/cmat/Ex51/Pole.h b/cmat/Ex51/Pole.h new file mode 100644 index 0000000..3154771 --- /dev/null +++ b/cmat/Ex51/Pole.h @@ -0,0 +1,28 @@ + +#ifndef POLE_H +#define POLE_H + +#include "Light.h" +#include "Observer.h" +#include "Pelican.h" + +class Pole : public Observer { + public: + Pole(int x, int y, Pelican &p); + ~Pole(); + + void setTrafficLights(Pelican::PelicanState state); + void setWaitLight(bool pressed); + + void update(const Hint &); + + private: + Pelican &myPelican; + + enum LightName { RED_LIGHT, YELLOW_LIGHT, GREEN_LIGHT, GREEN_MAN, RED_MAN }; + + Light *lights[RED_MAN + 1]; + Light *waitLight; +}; + +#endif diff --git a/cmat/Ex51/Subject.cpp b/cmat/Ex51/Subject.cpp new file mode 100644 index 0000000..bb73802 --- /dev/null +++ b/cmat/Ex51/Subject.cpp @@ -0,0 +1,12 @@ + + +#include "Subject.h" +#include "Observer.h" + +void Subject::attach(Observer &obs) { myObservers.insert(&obs); } + +void Subject::notify(const Hint &h) const { + for (ObsList::const_iterator iter = myObservers.begin(); iter != myObservers.end(); ++iter) { + (*iter)->update(h); + } +} diff --git a/cmat/Ex51/Subject.h b/cmat/Ex51/Subject.h new file mode 100644 index 0000000..4e51407 --- /dev/null +++ b/cmat/Ex51/Subject.h @@ -0,0 +1,26 @@ + +#ifndef SUBJECT_H +#define SUBJECT_H + +class Observer; + +#include + +class Hint { + public: + virtual ~Hint() {} +}; + +class Subject { + public: + typedef std::set ObsList; + void attach(Observer &obs); + + protected: + void notify(const Hint &) const; + + private: + ObsList myObservers; +}; + +#endif diff --git a/cmat/Ex51/Timer.cpp b/cmat/Ex51/Timer.cpp new file mode 100644 index 0000000..9240bda --- /dev/null +++ b/cmat/Ex51/Timer.cpp @@ -0,0 +1,23 @@ + + +#include "Timer.h" +#include "TimerSet.h" + +void Timer::timeoutRequest(int seconds) { timeToGo = seconds; } + +Timer::Timer() : timeToGo(-1) { TimerSet::Instance().addATimer(this); } + +void Timer::tick() { + if (isExpired()) { + doExpired(); + } +} + +bool Timer::isExpired() { + if (timeToGo > 0) { + if (--timeToGo == 0) { + return true; + } + } + return false; +} diff --git a/cmat/Ex51/Timer.h b/cmat/Ex51/Timer.h new file mode 100644 index 0000000..37d1ce9 --- /dev/null +++ b/cmat/Ex51/Timer.h @@ -0,0 +1,32 @@ +// ====================================================== +// +// A general-purpose countdown timer +// To use this class, specialize it +// and override tick() +// +// ====================================================== + +#ifndef timer_H +#define timer_H + +#include + +class Timer { + public: + Timer(); + + void timeoutRequest(int seconds); + + // template method + void tick(); + + protected: + bool isExpired(); + + private: + virtual void doExpired() = 0; + + int timeToGo; +}; + +#endif diff --git a/cmat/Ex51/TimerSet.cpp b/cmat/Ex51/TimerSet.cpp new file mode 100644 index 0000000..5606f75 --- /dev/null +++ b/cmat/Ex51/TimerSet.cpp @@ -0,0 +1,24 @@ +#include "TimerSet.h" +#include "Timer.h" +#include + +TimerSet::TimerSet() : previousTime(time(NULL)) {} + +void TimerSet::addATimer(Timer *t) { timers.push_back(t); } + +void TimerSet::pollAllTimers() { + std::time_t timeNow; + if (time(&timeNow) > previousTime) { + previousTime = timeNow; + + for (auto it = timers.begin(); it != timers.end(); it++) { + (*it)->tick(); + } + } +} + +TimerSet &TimerSet::Instance() { + // Meyer's Singleton implementation + static TimerSet pInstance; + return pInstance; +} diff --git a/cmat/Ex51/TimerSet.h b/cmat/Ex51/TimerSet.h new file mode 100644 index 0000000..35c2baf --- /dev/null +++ b/cmat/Ex51/TimerSet.h @@ -0,0 +1,29 @@ +#ifndef TIMERSET_H +#define TIMERSET_H + +#include +#include + +class Timer; + +class TimerSet { + public: + void pollAllTimers(); + void addATimer(Timer *); + + private: + TimerSet(); + std::vector timers; + std::time_t previousTime; + + // Meyer's singleton + public: + static TimerSet &Instance(); + + private: + // prevent copying and assignment of the singleton + TimerSet(const TimerSet &); + TimerSet &operator=(const TimerSet &); +}; + +#endif diff --git a/cmat/Ex51/main.cpp b/cmat/Ex51/main.cpp new file mode 100644 index 0000000..3624dd0 --- /dev/null +++ b/cmat/Ex51/main.cpp @@ -0,0 +1,32 @@ + + +#include "Keyboard.h" +#include "Pelican.h" +#include "Pole.h" +#include "TimerSet.h" + +#include // provides toupper() + +int main() { + Keyboard kbd; + Pelican thePelican; + Pole pole1(20, 0, thePelican); + Pole pole2(40, 0, thePelican); + + char c = 0; + + while (std::toupper(c) != 'Q') { // loop until 'Q' is pressed + + while (!kbd.isCharAvail()) { + TimerSet::Instance().pollAllTimers(); // no key press to process, poll the timers + } + + c = kbd.getChar(); // get the character + if (c == ' ') { + // it's a space, so press the WAIT button + thePelican.press(); + } + } + + return 0; +} diff --git a/cmat/Ex61/CMakeLists.txt b/cmat/Ex61/CMakeLists.txt new file mode 100644 index 0000000..20e1599 --- /dev/null +++ b/cmat/Ex61/CMakeLists.txt @@ -0,0 +1,9 @@ +# Ex61 + +cmat_add_exercise(Ex61 + SOURCES + main.cpp + Person.cpp + PersonException.cpp + YoungPerson.cpp +) diff --git a/cmat/Ex61/Ex61.sln b/cmat/Ex61/Ex61.sln new file mode 100644 index 0000000..b9d83cb --- /dev/null +++ b/cmat/Ex61/Ex61.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ex61", "Ex61.vcxproj", "{71B1E667-58E2-4C71-A6A3-73F9502928D7}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {71B1E667-58E2-4C71-A6A3-73F9502928D7}.Debug|Win32.ActiveCfg = Debug|Win32 + {71B1E667-58E2-4C71-A6A3-73F9502928D7}.Debug|Win32.Build.0 = Debug|Win32 + {71B1E667-58E2-4C71-A6A3-73F9502928D7}.Release|Win32.ActiveCfg = Release|Win32 + {71B1E667-58E2-4C71-A6A3-73F9502928D7}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/cmat/Ex61/Ex61.suo b/cmat/Ex61/Ex61.suo new file mode 100644 index 0000000..364c892 Binary files /dev/null and b/cmat/Ex61/Ex61.suo differ diff --git a/cmat/Ex61/Ex61.vcproj b/cmat/Ex61/Ex61.vcproj new file mode 100644 index 0000000..b3ad81a --- /dev/null +++ b/cmat/Ex61/Ex61.vcproj @@ -0,0 +1,121 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cmat/Ex61/Ex61.vcxproj b/cmat/Ex61/Ex61.vcxproj new file mode 100644 index 0000000..f87347e --- /dev/null +++ b/cmat/Ex61/Ex61.vcxproj @@ -0,0 +1,92 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {71B1E667-58E2-4C71-A6A3-73F9502928D7} + ManagedCProj + + + + Application + MultiByte + OldSyntax + v140 + + + Application + MultiByte + false + v140 + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + Debug\ + Debug\ + true + Release\ + Release\ + false + + + + Disabled + WIN32;_DEBUG;%(PreprocessorDefinitions) + false + Default + MultiThreadedDebugDLL + Level3 + ProgramDatabase + + + $(OutDir)Ex61.exe + true + Console + + + + + MaxSpeed + OnlyExplicitInline + WIN32;NDEBUG;%(PreprocessorDefinitions) + false + Level3 + + + $(OutDir)Ex61.exe + true + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cmat/Ex61/Ex61.vcxproj.filters b/cmat/Ex61/Ex61.vcxproj.filters new file mode 100644 index 0000000..a9ce652 --- /dev/null +++ b/cmat/Ex61/Ex61.vcxproj.filters @@ -0,0 +1,38 @@ + + + + + {216ad10e-da13-4e74-bd7b-3d1fd4babd53} + cpp;c;cxx;def;odl;idl;hpj;bat;asm + + + {57ab839f-9334-4b02-aa8e-af153d217a12} + h;hpp;hxx;hm;inl;inc + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/cmat/Ex61/Ex61.vcxproj.user b/cmat/Ex61/Ex61.vcxproj.user new file mode 100644 index 0000000..695b5c7 --- /dev/null +++ b/cmat/Ex61/Ex61.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cmat/Ex61/Person.cpp b/cmat/Ex61/Person.cpp new file mode 100644 index 0000000..5b6d36c --- /dev/null +++ b/cmat/Ex61/Person.cpp @@ -0,0 +1,37 @@ +#include "Person.h" +#include "PersonException.h" +#include "YoungPerson.h" +#include + +using std::cout; + +Person::Person(std::string name, int age) : name(name), age(age) { + if (age < 0) { + throw PersonException("negative age"); + } + + cout << "Person ctor\n"; + Count++; +} + +Person::Person(const Person &) { + cout << "Copy ctor\n"; + Count++; +} + +Person::~Person() { + cout << "Dtor\n"; + Count--; +} + +void Person::setSalary(int sal) { + if (sal < 0) { + throw PersonException("negative salary"); + } + + salary = sal; +} + +int Person::GetCount() { return Count; } + +int Person::Count = 0; diff --git a/cmat/Ex61/Person.h b/cmat/Ex61/Person.h new file mode 100644 index 0000000..e043203 --- /dev/null +++ b/cmat/Ex61/Person.h @@ -0,0 +1,28 @@ + + +#ifndef Person_h +#define Person_h + +#include + +class Person { + public: + virtual ~Person(); + + static int GetCount(); + + Person(std::string name, int age); + + void setSalary(int sal); + + private: + Person(const Person &); + + std::string name; + int age; + int salary; + + static int Count; +}; + +#endif \ No newline at end of file diff --git a/cmat/Ex61/PersonException.cpp b/cmat/Ex61/PersonException.cpp new file mode 100644 index 0000000..bef2a5e --- /dev/null +++ b/cmat/Ex61/PersonException.cpp @@ -0,0 +1,5 @@ +#include "PersonException.h" + +PersonException::PersonException(std::string m) : msg(m) {} + +const char *PersonException::what() const throw() { return msg.c_str(); } \ No newline at end of file diff --git a/cmat/Ex61/PersonException.h b/cmat/Ex61/PersonException.h new file mode 100644 index 0000000..d9e6b06 --- /dev/null +++ b/cmat/Ex61/PersonException.h @@ -0,0 +1,16 @@ +#ifndef Person_Exception_h +#define Person_Exception_h + +#include +#include + +class PersonException : public std::exception { + public: + PersonException(std::string m); + const char *what() const throw(); + + private: + std::string msg; +}; + +#endif diff --git a/cmat/Ex61/YoungPerson.cpp b/cmat/Ex61/YoungPerson.cpp new file mode 100644 index 0000000..fbd4280 --- /dev/null +++ b/cmat/Ex61/YoungPerson.cpp @@ -0,0 +1,5 @@ +#include "YoungPerson.h" + +#include + +YoungPerson::YoungPerson(std::string name, int age) : Person(name, age) { std::cout << "YoungPerson ctor\n"; } diff --git a/cmat/Ex61/YoungPerson.h b/cmat/Ex61/YoungPerson.h new file mode 100644 index 0000000..4f59191 --- /dev/null +++ b/cmat/Ex61/YoungPerson.h @@ -0,0 +1,13 @@ + + +#ifndef YoungPerson_h +#define YoungPerson_h + +#include "Person.h" + +class YoungPerson : public Person { + public: + YoungPerson(std::string name, int age); +}; + +#endif \ No newline at end of file diff --git a/cmat/Ex61/main.cpp b/cmat/Ex61/main.cpp new file mode 100644 index 0000000..5ec24ff --- /dev/null +++ b/cmat/Ex61/main.cpp @@ -0,0 +1,75 @@ + +#include +#include +#include + +#include "Person.h" + +#include "PersonException.h" +#include + +using std::cin; +using std::cout; +using std::string; +using std::exception; + +int main() { + std::vector people; + + string namePrompt = "Enter name: "; + string name; + string agePrompt = "Enter age: "; + int age; + string salaryPrompt = "Enter salary: "; + int salary; + + cout << namePrompt; + cin >> name; + + while (name != "q") { + try { + cout << agePrompt; + cin >> age; + + if (!cin) { + cin.clear(); + string dummy; + cin >> dummy; + throw PersonException("invalid age"); + } + + Person *personPtr = new Person(name, age); + + cout << salaryPrompt; + cin >> salary; + if (!cin) { + cin.clear(); + string dummy; + cin >> dummy; + throw PersonException("invalid salary"); + } + + personPtr->setSalary(salary); + + people.push_back(personPtr); + } + + catch (exception &e) { + cout << "PersonException thrown: " << e.what() << '\n'; + } + + cout << "There are " << Person::GetCount() << " Person(s), " << people.size() << " in vector\n"; + + cout << namePrompt; + cin >> name; + } + + // delete all the person(s) in the vector + for (std::vector::iterator iter = people.begin(); iter != people.end(); ++iter) { + delete *iter; + } + + cout << "There are " << Person::GetCount() << " Person(s) left dangling\n"; + + return 0; +} diff --git a/cmat/Ex62/CMakeLists.txt b/cmat/Ex62/CMakeLists.txt new file mode 100644 index 0000000..1c71795 --- /dev/null +++ b/cmat/Ex62/CMakeLists.txt @@ -0,0 +1,7 @@ +# Ex62 + +cmat_add_exercise(Ex62 + SOURCES + Main.cpp + Person.cpp +) diff --git a/cmat/Ex62/Ex62.sln b/cmat/Ex62/Ex62.sln new file mode 100644 index 0000000..c1b76bf --- /dev/null +++ b/cmat/Ex62/Ex62.sln @@ -0,0 +1,20 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ex62", "Ex62.vcxproj", "{252EC352-EE7F-66EF-0B79-229BBB7504A7}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {252EC352-EE7F-66EF-0B79-229BBB7504A7}.Debug|Win32.ActiveCfg = Debug|Win32 + {252EC352-EE7F-66EF-0B79-229BBB7504A7}.Debug|Win32.Build.0 = Debug|Win32 + {252EC352-EE7F-66EF-0B79-229BBB7504A7}.Release|Win32.ActiveCfg = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/cmat/Ex62/Ex62.suo b/cmat/Ex62/Ex62.suo new file mode 100644 index 0000000..e8bc8cf Binary files /dev/null and b/cmat/Ex62/Ex62.suo differ diff --git a/cmat/Ex62/Ex62.vcproj b/cmat/Ex62/Ex62.vcproj new file mode 100644 index 0000000..1c3f5b3 --- /dev/null +++ b/cmat/Ex62/Ex62.vcproj @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cmat/Ex62/Ex62.vcxproj b/cmat/Ex62/Ex62.vcxproj new file mode 100644 index 0000000..4666408 --- /dev/null +++ b/cmat/Ex62/Ex62.vcxproj @@ -0,0 +1,130 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + {252EC352-EE7F-66EF-0B79-229BBB7504A7} + + + + Application + false + MultiByte + v140 + + + Application + false + MultiByte + v140 + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + .\Debug\ + .\Debug\ + true + .\Release\ + .\Release\ + false + + + + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebugDLL + true + NotUsing + .\Debug/Ex62.pch + .\Debug/ + .\Debug/ + .\Debug/ + Level3 + true + C:\boost_1_60_0;%(AdditionalIncludeDirectories) + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Debug/Ex62.exe + true + true + .\Debug/Ex62.pdb + Console + C:\boost_1_60_0\stage\lib;%(AdditionalLibraryDirectories) + + + .\Debug/Ex62.tlb + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + OnlyExplicitInline + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + true + + + .\Release/Ex62.pch + .\Release/ + .\Release/ + .\Release/ + Level3 + true + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Release/Ex62.exe + true + .\Release/Ex62.pdb + Console + + + .\Release/Ex62.tlb + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + 4308 + + + + + + + + + + \ No newline at end of file diff --git a/cmat/Ex62/Ex62.vcxproj.filters b/cmat/Ex62/Ex62.vcxproj.filters new file mode 100644 index 0000000..e427d6f --- /dev/null +++ b/cmat/Ex62/Ex62.vcxproj.filters @@ -0,0 +1,26 @@ + + + + + {ee8cac86-35f3-4b27-880c-c2776398baea} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {4ce1c82c-752c-4f94-a6c3-fc2858d4d4c2} + h;hpp;hxx;hm;inl + + + + + Source Files + + + Source Files + + + + + Header Files + + + \ No newline at end of file diff --git a/cmat/Ex62/Ex62.vcxproj.user b/cmat/Ex62/Ex62.vcxproj.user new file mode 100644 index 0000000..695b5c7 --- /dev/null +++ b/cmat/Ex62/Ex62.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cmat/Ex62/Main.cpp b/cmat/Ex62/Main.cpp new file mode 100644 index 0000000..90f93f0 --- /dev/null +++ b/cmat/Ex62/Main.cpp @@ -0,0 +1,53 @@ + +#include "Person.h" +#include +#include +#include +#include + +//#include +// include headers that implement an archive in simple text format +//#include +//#include +// include header that allows serialization of STL list +//#include + +// STL collection of Person* +std::list people; + +void add() { + // creates a person, collects the information, adds person to list + Person *newP = new Person; + newP->askForInfo(); + people.push_back(newP); +} + +void showPerson(Person *p) { + // displays a person + p->display(); +} + +void display() { + // displays all the people + std::for_each(people.begin(), people.end(), &showPerson); +} + +int main() { + char choice = 0; + + while (choice != 'X') { + switch (choice) { + case 'A': + add(); + break; + case 'D': + display(); + break; + } + std::cout << "Enter choice: [A]dd, [D]isplay, e[X]it: "; + std::cin >> choice; + choice = std::toupper(choice); + } + + return 0; +} diff --git a/cmat/Ex62/Person.cpp b/cmat/Ex62/Person.cpp new file mode 100644 index 0000000..f3283ac --- /dev/null +++ b/cmat/Ex62/Person.cpp @@ -0,0 +1,13 @@ +#include "Person.h" +#include + +void Person::askForInfo() { + std::cout << "First name: "; + std::cin >> firstName; + std::cout << "Last name: "; + std::cin >> lastName; + std::cout << "Age: "; + std::cin >> age; +} + +void Person::display() { std::cout << firstName << " " << lastName << ", " << age << std::endl; } diff --git a/cmat/Ex62/Person.h b/cmat/Ex62/Person.h new file mode 100644 index 0000000..e7d4d2b --- /dev/null +++ b/cmat/Ex62/Person.h @@ -0,0 +1,20 @@ + +#ifndef person_H +#define person_H + +//#include + +#include + +class Person { + public: + void askForInfo(); + void display(); + + private: + std::string firstName; + std::string lastName; + int age; +}; + +#endif diff --git a/cmat/Ex71/CMakeLists.txt b/cmat/Ex71/CMakeLists.txt new file mode 100644 index 0000000..2d4ec46 --- /dev/null +++ b/cmat/Ex71/CMakeLists.txt @@ -0,0 +1,11 @@ +# Ex71 + +cmat_add_exercise(Ex71 + SOURCES + CompanyEntry.cpp + CountVisitor.cpp + FindVisitor.cpp + GroupEntry.cpp + main.cpp + PersonEntry.cpp +) diff --git a/cmat/Ex71/CompanyEntry.cpp b/cmat/Ex71/CompanyEntry.cpp new file mode 100644 index 0000000..898dcc6 --- /dev/null +++ b/cmat/Ex71/CompanyEntry.cpp @@ -0,0 +1,19 @@ +#include +#include + +#include "CompanyEntry.h" +#include "EntryVisitor.h" + +CompanyEntry::CompanyEntry(std::string name, std::string category, std::string phone) + : Entry(name), _category(category), _phone(phone) {} + +void CompanyEntry::print(std::string indent) const { + + std::cout << indent << "Company: " << getName() << " <" << _category << "> " << _phone << '\n'; +} + +std::string CompanyEntry::getPhone() const { return _phone; } + +std::string CompanyEntry::getCategory() const { return _category; } + +void CompanyEntry::accept(EntryVisitor &v) const { v.visit(*this); } \ No newline at end of file diff --git a/cmat/Ex71/CompanyEntry.h b/cmat/Ex71/CompanyEntry.h new file mode 100644 index 0000000..819ca0d --- /dev/null +++ b/cmat/Ex71/CompanyEntry.h @@ -0,0 +1,22 @@ + +#ifndef COMPANYENTRY_H +#define COMPANYENTRY_H + +#include "Entry.h" + +class CompanyEntry : public Entry { + public: + CompanyEntry(std::string name, std::string category, std::string phone); + + void print(std::string indent = "") const; + std::string getPhone() const; + std::string getCategory() const; + + void accept(EntryVisitor &) const; + + private: + std::string _category; + std::string _phone; +}; + +#endif \ No newline at end of file diff --git a/cmat/Ex71/CountVisitor.cpp b/cmat/Ex71/CountVisitor.cpp new file mode 100644 index 0000000..5fb051a --- /dev/null +++ b/cmat/Ex71/CountVisitor.cpp @@ -0,0 +1,2 @@ +#include "CountVisitor.h" +#include diff --git a/cmat/Ex71/CountVisitor.h b/cmat/Ex71/CountVisitor.h new file mode 100644 index 0000000..f1fb989 --- /dev/null +++ b/cmat/Ex71/CountVisitor.h @@ -0,0 +1,7 @@ +#ifndef COUNTVISITOR_H +#define COUNTVISITOR_H + +#include "EntryVisitor.h" +class CountVisitor {}; + +#endif \ No newline at end of file diff --git a/cmat/Ex71/Entry.cpp b/cmat/Ex71/Entry.cpp new file mode 100644 index 0000000..a1a6fa7 --- /dev/null +++ b/cmat/Ex71/Entry.cpp @@ -0,0 +1,5 @@ +// Entry.cpp + +#include "Entry.h" + +Entry::Entry(std::string name) : _name(name), _phone(phone) {} diff --git a/cmat/Ex71/Entry.h b/cmat/Ex71/Entry.h new file mode 100644 index 0000000..f38a2bd --- /dev/null +++ b/cmat/Ex71/Entry.h @@ -0,0 +1,23 @@ + +#ifndef ENTRY_H +#define ENTRY_H + +#include + +class EntryVisitor; + +class Entry { + public: + Entry(std::string name) : _name(name) {} + + std::string getName() const { return _name; } + + virtual void print(std::string indent = "") const = 0; + + virtual void accept(EntryVisitor &) const = 0; + + private: + std::string _name; +}; + +#endif diff --git a/cmat/Ex71/EntryVisitor.h b/cmat/Ex71/EntryVisitor.h new file mode 100644 index 0000000..70e2308 --- /dev/null +++ b/cmat/Ex71/EntryVisitor.h @@ -0,0 +1,17 @@ + + +#ifndef ENTRYVISITOR_H +#define ENTRYVISITOR_H + +class PersonEntry; +class CompanyEntry; +class GroupEntry; + +class EntryVisitor { + public: + virtual void visit(const PersonEntry &) = 0; + virtual void visit(const CompanyEntry &) = 0; + virtual void visit(const GroupEntry &) = 0; +}; + +#endif diff --git a/cmat/Ex71/Ex71.sln b/cmat/Ex71/Ex71.sln new file mode 100644 index 0000000..a1c4809 --- /dev/null +++ b/cmat/Ex71/Ex71.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ex71", "Ex71.vcxproj", "{3BE8ED56-4FC0-F86D-B9E1-1EE211AF78DB}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3BE8ED56-4FC0-F86D-B9E1-1EE211AF78DB}.Debug|Win32.ActiveCfg = Debug|Win32 + {3BE8ED56-4FC0-F86D-B9E1-1EE211AF78DB}.Debug|Win32.Build.0 = Debug|Win32 + {3BE8ED56-4FC0-F86D-B9E1-1EE211AF78DB}.Release|Win32.ActiveCfg = Release|Win32 + {3BE8ED56-4FC0-F86D-B9E1-1EE211AF78DB}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/cmat/Ex71/Ex71.suo b/cmat/Ex71/Ex71.suo new file mode 100644 index 0000000..d13baa0 Binary files /dev/null and b/cmat/Ex71/Ex71.suo differ diff --git a/cmat/Ex71/Ex71.vcxproj b/cmat/Ex71/Ex71.vcxproj new file mode 100644 index 0000000..c8a25d1 --- /dev/null +++ b/cmat/Ex71/Ex71.vcxproj @@ -0,0 +1,136 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + {3BE8ED56-4FC0-F86D-B9E1-1EE211AF78DB} + + + + Application + false + MultiByte + v140 + + + Application + false + MultiByte + v140 + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + .\Release\ + .\Release\ + false + .\Debug\ + .\Debug\ + true + + + + OnlyExplicitInline + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + true + + + .\Release/Ex71A.pch + .\Release/ + .\Release/ + .\Release/ + Level3 + true + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Release/Ex71A.exe + true + .\Release/Ex71A.pdb + Console + + + .\Release/Ex71A.tlb + + + NDEBUG;%(PreprocessorDefinitions) + 0x0809 + + + + + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + NotUsing + .\Debug/Ex71A.pch + .\Debug/ + .\Debug/ + .\Debug/ + Level3 + true + C:\course\397\DOS_Unix;%(AdditionalIncludeDirectories) + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Debug/Ex71.exe + true + true + .\Debug/Ex71A.pdb + Console + + + .\Debug/Ex71A.tlb + + + _DEBUG;%(PreprocessorDefinitions) + 0x0809 + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cmat/Ex71/Ex71.vcxproj.filters b/cmat/Ex71/Ex71.vcxproj.filters new file mode 100644 index 0000000..090c40d --- /dev/null +++ b/cmat/Ex71/Ex71.vcxproj.filters @@ -0,0 +1,56 @@ + + + + + {a373d85d-0daa-4771-a2af-24735700f4b5} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {28280df5-d09d-4335-a70c-dd81eee4485f} + h;hpp;hxx;hm;inl + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/cmat/Ex71/Ex71.vcxproj.user b/cmat/Ex71/Ex71.vcxproj.user new file mode 100644 index 0000000..695b5c7 --- /dev/null +++ b/cmat/Ex71/Ex71.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cmat/Ex71/FindVisitor.cpp b/cmat/Ex71/FindVisitor.cpp new file mode 100644 index 0000000..c90965a --- /dev/null +++ b/cmat/Ex71/FindVisitor.cpp @@ -0,0 +1,31 @@ + + +#include + +#include "CompanyEntry.h" +#include "FindVisitor.h" +#include "GroupEntry.h" +#include "PersonEntry.h" + +FindVisitor::FindVisitor(std::string query) : _query(query) {} + +const std::vector &FindVisitor::getFindings() { return findings; } + +void FindVisitor::visit(const PersonEntry &s) { + if (s.getName().find(_query) != std::string::npos) { + findings.push_back(&s); + } +} + +void FindVisitor::visit(const GroupEntry &g) { + if (g.getName().find(_query) != std::string::npos) { + findings.push_back(&g); + } +} + +void FindVisitor::visit(const CompanyEntry &c) { + + if (c.getName().find(_query) != std::string::npos || c.getCategory().find(_query) != std::string::npos) { + findings.push_back(&c); + } +} diff --git a/cmat/Ex71/FindVisitor.h b/cmat/Ex71/FindVisitor.h new file mode 100644 index 0000000..c185a52 --- /dev/null +++ b/cmat/Ex71/FindVisitor.h @@ -0,0 +1,22 @@ + + +#ifndef FINDVISITOR_H +#define FINDVISITOR_H + +#include "Entry.h" +#include "EntryVisitor.h" +#include + +class FindVisitor : public EntryVisitor { + std::string _query; // looking for this + std::vector findings; // finding these entries + public: + FindVisitor(std::string query); + const std::vector &getFindings(); + + void visit(const PersonEntry &); + void visit(const CompanyEntry &); + void visit(const GroupEntry &); +}; + +#endif diff --git a/cmat/Ex71/GroupEntry.cpp b/cmat/Ex71/GroupEntry.cpp new file mode 100644 index 0000000..d28a52f --- /dev/null +++ b/cmat/Ex71/GroupEntry.cpp @@ -0,0 +1,31 @@ + + +#include + +#include "EntryVisitor.h" +#include "GroupEntry.h" +#include "PersonEntry.h" + +GroupEntry::GroupEntry(std::string name) : Entry(name) {} + +void GroupEntry::print(std::string indent) const { + // PART 1 implement print here + // When you call print for the child objects, extend the indent string argument + // with a couple of more space characters. +} + +void GroupEntry::addEntry(const Entry &entry) { + // Part 1: Add the entry to this group + + _entries.push_back(&entry); +} + +void GroupEntry::accept(EntryVisitor &v) const { + + v.visit(*this); + + // pass visitor to my children + for (auto p : _entries) { + p->accept(v); + } +} diff --git a/cmat/Ex71/GroupEntry.h b/cmat/Ex71/GroupEntry.h new file mode 100644 index 0000000..4dec0a9 --- /dev/null +++ b/cmat/Ex71/GroupEntry.h @@ -0,0 +1,29 @@ + +#ifndef GROUPENTRY_H +#define GROUPENTRY_H + +#include +#include +#include + +#include "Entry.h" +#include "PersonEntry.h" + +class GroupEntry : public Entry { + public: + GroupEntry(std::string name); + + // print the entire group, including its members + // precede the name with the "indent" string + void print(std::string indent = "") const; + + // child management + void addEntry(const Entry &); + + void accept(EntryVisitor &) const; + + private: + std::vector _entries; +}; + +#endif diff --git a/cmat/Ex71/PersonEntry.cpp b/cmat/Ex71/PersonEntry.cpp new file mode 100644 index 0000000..fc5721c --- /dev/null +++ b/cmat/Ex71/PersonEntry.cpp @@ -0,0 +1,18 @@ + + +#include +#include + +#include "EntryVisitor.h" +#include "PersonEntry.h" + +PersonEntry::PersonEntry(std::string name, std::string phone) : Entry(name), _phone(phone) {} + +void PersonEntry::print(std::string indent) const { + + std::cout << indent << "Person: " << getName() << ' ' << _phone << '\n'; +} + +std::string PersonEntry::getPhone() const { return _phone; } + +void PersonEntry::accept(EntryVisitor &v) const { v.visit(*this); } diff --git a/cmat/Ex71/PersonEntry.h b/cmat/Ex71/PersonEntry.h new file mode 100644 index 0000000..61b3326 --- /dev/null +++ b/cmat/Ex71/PersonEntry.h @@ -0,0 +1,22 @@ + + +#ifndef PERSONENTRY_H +#define PERSONENTRY_H + +#include "Entry.h" + +class PersonEntry : public Entry { + public: + PersonEntry(std::string name, std::string phone); + + void print(std::string indent = "") const; + + std::string getPhone() const; + + void accept(EntryVisitor &) const; + + private: + std::string _phone; +}; + +#endif diff --git a/cmat/Ex71/main.cpp b/cmat/Ex71/main.cpp new file mode 100644 index 0000000..f17b902 --- /dev/null +++ b/cmat/Ex71/main.cpp @@ -0,0 +1,68 @@ + + +#include "CompanyEntry.h" +#include "CountVisitor.h" +#include "FindVisitor.h" +#include "GroupEntry.h" +#include "PersonEntry.h" +#include + +using namespace std; + +int main() { + + // declare an address book + GroupEntry addressbook("My addressbook"); + + // create some entries + PersonEntry Fred("Fred", "555 1234"); + PersonEntry Gert("Gert", "555 1235"); + PersonEntry Jim("Jim", "999 2445"); + PersonEntry Sue("Sue", "456 2951"); + PersonEntry Ingar("Ingar", "999 2345"); + PersonEntry Lisa("Lisa", "443 4532"); + CompanyEntry ShoeWorld("ShoeWorld", "Shoes", "234 4314"); + CompanyEntry BestBurgers("BestBurgers", "Food", "456 4651"); + CompanyEntry DreamPizza("DreamPizza", "Food", "935 2345"); + CompanyEntry BestBooks("BestBooks", "Books", "345 3232"); + + // add some simple entries + addressbook.addEntry(Fred); + addressbook.addEntry(Gert); + addressbook.addEntry(ShoeWorld); + + // make some groups + GroupEntry group1("My Best Food"); + group1.addEntry(BestBurgers); + group1.addEntry(DreamPizza); + + GroupEntry group2("Coworkers"); + group2.addEntry(Jim); + group2.addEntry(Sue); + + // make a nested group + GroupEntry group3("Favorites"); + group3.addEntry(Ingar); + group3.addEntry(Lisa); + group3.addEntry(BestBooks); + group3.addEntry(group1); + + addressbook.addEntry(group2); + addressbook.addEntry(group3); + + cout << "*** Print using Composite print operation\n"; + addressbook.print(); + + cout << "*** Find using Visitor\n"; + FindVisitor pv("Fred"); + addressbook.accept(pv); + for (const Entry *p : pv.getFindings()) { + p->print(); + } + + // PART 2 Create a CountVisitor and let it visit the address book + // cout << "*** Count objects using Visitor\n"; + + cout << "*** Test complete\n"; + return 0; +} diff --git a/cmat/Ex71A/CMakeLists.txt b/cmat/Ex71A/CMakeLists.txt new file mode 100644 index 0000000..b7cbc85 --- /dev/null +++ b/cmat/Ex71A/CMakeLists.txt @@ -0,0 +1,13 @@ +# Ex71A + +cmat_add_exercise(Ex71A + GUI + SOURCES + Light.cpp + main.cpp + Pelican.cpp + Pole.cpp + Subject.cpp + Timer.cpp + TimerSet.cpp +) diff --git a/cmat/Ex71A/Ex71.sln b/cmat/Ex71A/Ex71.sln new file mode 100644 index 0000000..7611fff --- /dev/null +++ b/cmat/Ex71A/Ex71.sln @@ -0,0 +1,20 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ex71", "Ex71.vcxproj", "{3D7880AE-E251-9B65-4D9A-70B4E2BCB93C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3D7880AE-E251-9B65-4D9A-70B4E2BCB93C}.Debug|Win32.ActiveCfg = Debug|Win32 + {3D7880AE-E251-9B65-4D9A-70B4E2BCB93C}.Debug|Win32.Build.0 = Debug|Win32 + {3D7880AE-E251-9B65-4D9A-70B4E2BCB93C}.Release|Win32.ActiveCfg = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/cmat/Ex71A/Ex71.suo b/cmat/Ex71A/Ex71.suo new file mode 100644 index 0000000..d388461 Binary files /dev/null and b/cmat/Ex71A/Ex71.suo differ diff --git a/cmat/Ex71A/Ex71.vcproj b/cmat/Ex71A/Ex71.vcproj new file mode 100644 index 0000000..7a82d29 --- /dev/null +++ b/cmat/Ex71A/Ex71.vcproj @@ -0,0 +1,218 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cmat/Ex71A/Ex71.vcxproj b/cmat/Ex71A/Ex71.vcxproj new file mode 100644 index 0000000..76683e9 --- /dev/null +++ b/cmat/Ex71A/Ex71.vcxproj @@ -0,0 +1,149 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + {3D7880AE-E251-9B65-4D9A-70B4E2BCB93C} + + + + Application + false + MultiByte + v140 + + + Application + false + MultiByte + v140 + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + .\Release\ + .\Release\ + false + .\Debug\ + .\Debug\ + true + + + + OnlyExplicitInline + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + true + + + .\Release/Ex71.pch + .\Release/ + .\Release/ + .\Release/ + Level3 + true + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Release/Ex71.exe + true + .\Release/Ex71.pdb + Console + + + .\Release/Ex71.tlb + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + true + NotUsing + .\Debug/Ex71.pch + .\Debug/ + .\Debug/ + .\Debug/ + Level3 + true + ProgramDatabase + C:\course\397\DOS_Unix;%(AdditionalIncludeDirectories) + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Debug/Ex71.exe + true + true + .\Debug/Ex71.pdb + Console + + + .\Debug/Ex71.tlb + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + + + + + + + + $(IntDir)%(Filename)1.obj + $(IntDir)%(Filename)1.obj + + + $(IntDir)%(Filename)1.obj + $(IntDir)%(Filename)1.obj + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cmat/Ex71A/Ex71.vcxproj.filters b/cmat/Ex71A/Ex71.vcxproj.filters new file mode 100644 index 0000000..5b8e659 --- /dev/null +++ b/cmat/Ex71A/Ex71.vcxproj.filters @@ -0,0 +1,74 @@ + + + + + {0b227cf9-5391-4e90-8d9f-fc451731aeee} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {da5f2d9c-de70-4bec-afc6-e895bd2dad8c} + h;hpp;hxx;hm;inl + + + {a539e3af-b783-430f-b157-9886e19d62cc} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + DOS_Unix + + + DOS_Unix + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + DOS_Unix + + + DOS_Unix + + + \ No newline at end of file diff --git a/cmat/Ex71A/Ex71.vcxproj.user b/cmat/Ex71A/Ex71.vcxproj.user new file mode 100644 index 0000000..695b5c7 --- /dev/null +++ b/cmat/Ex71A/Ex71.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cmat/Ex71A/Light.cpp b/cmat/Ex71A/Light.cpp new file mode 100644 index 0000000..b59da2a --- /dev/null +++ b/cmat/Ex71A/Light.cpp @@ -0,0 +1,20 @@ + +#include "Light.h" +#include "Pelican.h" +#include "Screen.h" +#include + +Light::Light(std::string name, int x, int y, int color) : x(x), y(y), c(color), name(name) {} + +Light::~Light() { + std::cout << "Deleting light (" << name << ", " << x << ", " << y << ", " << c << ")" + << "\n"; +} + +void Light::set(LightState newState) { + state = newState; + Screen::write(name.c_str(), x, y, state == FLASH ? (128 + c) : (state == OFF ? 0 : c)); + // 128 + color was used to make a character flash (but not any more) +} + +Light::LightState Light::get(void) { return state; } diff --git a/cmat/Ex71A/Light.h b/cmat/Ex71A/Light.h new file mode 100644 index 0000000..03adf9a --- /dev/null +++ b/cmat/Ex71A/Light.h @@ -0,0 +1,30 @@ +// ====================================================== +// +// Represents a light, implemented as a string written +// to a console window +// +// ====================================================== + +#ifndef LIGHT_H +#define LIGHT_H + +#include + +class Light { + public: + Light(std::string name, int x, int y, int color); + ~Light(); + + enum LightState { ON, OFF, FLASH }; + + void set(LightState new_state); + LightState get(void); + + private: + int c; // light colour + int x, y; + std::string name; + LightState state; +}; + +#endif diff --git a/cmat/Ex71A/Observer.h b/cmat/Ex71A/Observer.h new file mode 100644 index 0000000..4c5dbf0 --- /dev/null +++ b/cmat/Ex71A/Observer.h @@ -0,0 +1,13 @@ + + +#ifndef OBSERVER_H +#define OBSERVER_H + +#include "Subject.h" + +class Observer { + public: + virtual void update(const Hint &) = 0; +}; + +#endif diff --git a/cmat/Ex71A/Pelican.cpp b/cmat/Ex71A/Pelican.cpp new file mode 100644 index 0000000..a712e9f --- /dev/null +++ b/cmat/Ex71A/Pelican.cpp @@ -0,0 +1,59 @@ + + +#include "Pelican.h" +#include "Pole.h" +#include "Timer.h" + +Pelican::Pelican() : pressed(false), RED_TIME(4), YELLOW_TIME(2), GREEN_TIME(3), FLASH_TIME(5), state(GREEN_IDLE) { + myTimer = new Timer([this] { timerExpired(); }); +} + +void Pelican::press(void) { + if (state == GREEN_IDLE) { + state = YELLOW_STATE; + myTimer->timeoutRequest(YELLOW_TIME); + pressed = true; + + notify(WaitHint(pressed)); + notify(LightHint(state)); + } else if (state != RED_STATE) { + pressed = true; + notify(WaitHint(pressed)); + } +} + +void Pelican::timerExpired(void) { + switch (state) { + case RED_STATE: + state = YELLOW_FLASHING; + myTimer->timeoutRequest(FLASH_TIME); + break; + + case YELLOW_FLASHING: + state = GREEN_TIMING; + myTimer->timeoutRequest(GREEN_TIME); + break; + + case GREEN_TIMING: + if (pressed) { + state = YELLOW_STATE; + myTimer->timeoutRequest(YELLOW_TIME); + } else { + state = GREEN_IDLE; + } + break; + + case GREEN_IDLE: + // should never happen + break; + + case YELLOW_STATE: + state = RED_STATE; + pressed = false; + notify(WaitHint(pressed)); + myTimer->timeoutRequest(RED_TIME); + break; + } + + notify(LightHint(state)); +} diff --git a/cmat/Ex71A/Pelican.h b/cmat/Ex71A/Pelican.h new file mode 100644 index 0000000..ab3ad46 --- /dev/null +++ b/cmat/Ex71A/Pelican.h @@ -0,0 +1,64 @@ +// ====================================================== +// +// Represents a Pelican crossing +// +// ====================================================== + +#ifndef PELICAN_H +#define PELICAN_H + +#include "Subject.h" +#include "Timer.h" + +class Pelican : public Subject { + public: + Pelican(); + + // call when the WAIT button has been pressed + void press(void); + + // states that a Pelican can be in + enum PelicanState { RED_STATE, YELLOW_FLASHING, GREEN_TIMING, GREEN_IDLE, YELLOW_STATE }; + + bool isPressed() const { return pressed; } + PelicanState getState() const { return state; } + + private: + // state that this Pelican is in + PelicanState state; + + // called by PeleicanTimer when the lights need to change + void timerExpired(void); + + const unsigned int RED_TIME; + const unsigned int YELLOW_TIME; + const unsigned int GREEN_TIME; + const unsigned int FLASH_TIME; + + // indicates whether the WAIT light should be on + bool pressed; + + // Timer that indicates when the lights should change + Timer *myTimer; + + private: + // prevent general use of copy ctor and operator= + Pelican(const Pelican &); + Pelican &operator=(const Pelican &); +}; + +class LightHint : public Hint { + public: + LightHint(Pelican::PelicanState s) : state(s) {} + + Pelican::PelicanState state; +}; + +class WaitHint : public Hint { + public: + WaitHint(bool p) : pressed(p) {} + + bool pressed; +}; + +#endif diff --git a/cmat/Ex71A/Pole.cpp b/cmat/Ex71A/Pole.cpp new file mode 100644 index 0000000..9da08c0 --- /dev/null +++ b/cmat/Ex71A/Pole.cpp @@ -0,0 +1,78 @@ +#include "Pole.h" +#include "Screen.h" + +Pole::Pole(int x, int y, Pelican &p) : waitLight(new Light("WAIT", x + 6, y + 12, Screen::WHITE)), myPelican(p) { + myPelican.attach(*this); + + using namespace Screen; // we will discuss namespaces in the course + + lights[RED_LIGHT] = new Light("*", x + 11, y + 3, RED); + lights[RED_MAN] = new Light("*<-=", x + 6, y + 4, RED); + lights[YELLOW_LIGHT] = new Light("*", x + 11, y + 5, YELLOW); + lights[GREEN_LIGHT] = new Light("*", x + 11, y + 7, GREEN); + lights[GREEN_MAN] = new Light("*|-<", x + 6, y + 7, GREEN); + + write(" _____ ", x, ++y, GRAY); + write(" /___ /| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" | |/| ", x, ++y, GRAY); + write(" |____| | ", x, ++y, GRAY); + write(" | |/| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" |____|/ ", x, ++y, GRAY); + write(" _||__ ", x, ++y, GRAY); + write(" /___ /| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" |____|/ ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write("========||===========", x, ++y, GRAY); + write(" / || / ", x, ++y, GRAY); + write("_ /_________ /_ ", x, ++y, GRAY); + write("/ / ", x, ++y, GRAY); + + update(Hint()); +} + +Pole::~Pole() { + for (int i = 0; i < sizeof lights / sizeof(lights[0]); ++i) + delete lights[i]; + delete waitLight; +} + +void Pole::setTrafficLights(Pelican::PelicanState state) { + static const Light::LightState LightStates[Pelican::YELLOW_STATE + 1][RED_MAN + 1] = { + // red yellow green green man red man + {Light::ON, Light::OFF, Light::OFF, Light::ON, Light::OFF}, // red + {Light::OFF, Light::FLASH, Light::OFF, Light::FLASH, Light::OFF}, // y flash + {Light::OFF, Light::OFF, Light::ON, Light::OFF, Light::ON}, // g time + {Light::OFF, Light::OFF, Light::ON, Light::OFF, Light::ON}, // g idle + {Light::OFF, Light::ON, Light::OFF, Light::OFF, Light::ON} // yellow + }; + + for (int i = RED_LIGHT; i <= RED_MAN; i++) { + lights[i]->set(LightStates[state][i]); + } +} + +void Pole::setWaitLight(bool pressed) { waitLight->set(pressed ? Light::ON : Light::OFF); } + +void Pole::update(const Hint &h) { + const WaitHint *waitHintPtr; + const LightHint *lightHintPtr; + + if ((waitHintPtr = dynamic_cast(&h)) != 0) { + setWaitLight(waitHintPtr->pressed); + } else if ((lightHintPtr = dynamic_cast(&h)) != 0) { + setTrafficLights(lightHintPtr->state); + } else { + // don't know what's changed, so update everything + setTrafficLights(myPelican.getState()); + setWaitLight(myPelican.isPressed()); + } +} diff --git a/cmat/Ex71A/Pole.h b/cmat/Ex71A/Pole.h new file mode 100644 index 0000000..3154771 --- /dev/null +++ b/cmat/Ex71A/Pole.h @@ -0,0 +1,28 @@ + +#ifndef POLE_H +#define POLE_H + +#include "Light.h" +#include "Observer.h" +#include "Pelican.h" + +class Pole : public Observer { + public: + Pole(int x, int y, Pelican &p); + ~Pole(); + + void setTrafficLights(Pelican::PelicanState state); + void setWaitLight(bool pressed); + + void update(const Hint &); + + private: + Pelican &myPelican; + + enum LightName { RED_LIGHT, YELLOW_LIGHT, GREEN_LIGHT, GREEN_MAN, RED_MAN }; + + Light *lights[RED_MAN + 1]; + Light *waitLight; +}; + +#endif diff --git a/cmat/Ex71A/Subject.cpp b/cmat/Ex71A/Subject.cpp new file mode 100644 index 0000000..1ab7de0 --- /dev/null +++ b/cmat/Ex71A/Subject.cpp @@ -0,0 +1,11 @@ + +#include "Subject.h" +#include "Observer.h" + +void Subject::attach(Observer &obs) { myObservers.insert(&obs); } + +void Subject::notify(const Hint &h) const { + for (ObsList::const_iterator iter = myObservers.begin(); iter != myObservers.end(); ++iter) { + (*iter)->update(h); + } +} diff --git a/cmat/Ex71A/Subject.h b/cmat/Ex71A/Subject.h new file mode 100644 index 0000000..46c2de8 --- /dev/null +++ b/cmat/Ex71A/Subject.h @@ -0,0 +1,27 @@ + + +#ifndef SUBJECT_H +#define SUBJECT_H + +class Observer; + +#include + +class Hint { + public: + virtual ~Hint() {} +}; + +class Subject { + public: + typedef std::set ObsList; + void attach(Observer &obs); + + protected: + void notify(const Hint &) const; + + private: + ObsList myObservers; +}; + +#endif diff --git a/cmat/Ex71A/Timer.cpp b/cmat/Ex71A/Timer.cpp new file mode 100644 index 0000000..36d0627 --- /dev/null +++ b/cmat/Ex71A/Timer.cpp @@ -0,0 +1,25 @@ + + +#include "Timer.h" +#include "TimerSet.h" + +void Timer::timeoutRequest(int seconds) { timeToGo = seconds; } + +Timer::Timer(std::function action) : timeToGo(-1), doExpired(action) { + TimerSet::Instance().addATimer(this); +} + +void Timer::tick() { + if (isExpired()) { + doExpired(); + } +} + +bool Timer::isExpired() { + if (timeToGo > 0) { + if (--timeToGo == 0) { + return true; + } + } + return false; +} diff --git a/cmat/Ex71A/Timer.h b/cmat/Ex71A/Timer.h new file mode 100644 index 0000000..8d5e8a4 --- /dev/null +++ b/cmat/Ex71A/Timer.h @@ -0,0 +1,33 @@ +// ====================================================== +// +// A general-purpose countdown timer +// To use this class, specialize it +// and override tick() +// +// ====================================================== + +#ifndef timer_H +#define timer_H + +#include +#include + +class Timer { + public: + Timer(std::function action); + + void timeoutRequest(int seconds); + + // template method + void tick(); + + protected: + bool isExpired(); + + private: + std::function doExpired; + + int timeToGo; +}; + +#endif diff --git a/cmat/Ex71A/TimerSet.cpp b/cmat/Ex71A/TimerSet.cpp new file mode 100644 index 0000000..3595eb6 --- /dev/null +++ b/cmat/Ex71A/TimerSet.cpp @@ -0,0 +1,37 @@ +#include "TimerSet.h" +#include "Timer.h" +#include + + + +TimerSet::TimerSet() + : previousTime(time(&previousTime)), pollingThread([this]() { poll10Hz(); }) // Exercise 5.1 start thread +{ + pollingThread.detach(); // let it die on its own, without join +} + +// Exercise 5.1 new function +void TimerSet::poll10Hz() { + std::chrono::duration pause(100); + while (true) { + std::this_thread::sleep_for(pause); + pollAllTimers(); + } +} + +void TimerSet::addATimer(Timer *t) { timers.push_back(t); } + +void TimerSet::pollAllTimers() { + std::time_t timeNow; + if (time(&timeNow) > previousTime) { + previousTime = timeNow; + for (auto it = timers.begin(); it != timers.end(); it++) { + (*it)->tick(); + } + } +} + +TimerSet &TimerSet::Instance() { + static TimerSet pInstance; + return pInstance; +} diff --git a/cmat/Ex71A/TimerSet.h b/cmat/Ex71A/TimerSet.h new file mode 100644 index 0000000..1a027f3 --- /dev/null +++ b/cmat/Ex71A/TimerSet.h @@ -0,0 +1,33 @@ +#ifndef TIMERSET_H +#define TIMERSET_H + +#include +#include +#include + +class Timer; + +class TimerSet { + public: + void pollAllTimers(); + void addATimer(Timer *); + + private: + TimerSet(); + std::vector timers; + std::time_t previousTime; + + // Exercise 5.1 Threading two new members + std::thread pollingThread; + void poll10Hz(); + + // Meyer's Singleton + public: + static TimerSet &Instance(); + + private: + TimerSet(const TimerSet &); + TimerSet &operator=(const TimerSet &); +}; + +#endif diff --git a/cmat/Ex71A/main.cpp b/cmat/Ex71A/main.cpp new file mode 100644 index 0000000..60fc5f4 --- /dev/null +++ b/cmat/Ex71A/main.cpp @@ -0,0 +1,28 @@ + + +#include "Keyboard.h" +#include "Pelican.h" +#include "Pole.h" +#include "TimerSet.h" + +#include // provides toupper() + +int main() { + Keyboard kbd; + + Pelican thePelican; + Pole pole1(20, 0, thePelican); + Pole pole2(40, 0, thePelican); + + char c = 0; + + while (std::toupper(c) != 'Q') { // loop until 'Q' is pressed + c = kbd.getChar(); // get the character + if (c == ' ') { + // it's a space, so press the WAIT button + thePelican.press(); + } + } + + return 0; +} diff --git a/cmat/SolutionEx11bug/CMakeLists.txt b/cmat/SolutionEx11bug/CMakeLists.txt new file mode 100644 index 0000000..3c16ef6 --- /dev/null +++ b/cmat/SolutionEx11bug/CMakeLists.txt @@ -0,0 +1,13 @@ +# SolutionEx11bug + +cmat_add_exercise(SolutionEx11bug + GUI + SOURCES + Light.cpp + main.cpp + Pelican.cpp + PelicanTimer.cpp + pole.cpp + Timer.cpp + TimerSet.cpp +) diff --git a/cmat/SolutionEx11bug/Ex11.sln b/cmat/SolutionEx11bug/Ex11.sln new file mode 100644 index 0000000..2989bb0 --- /dev/null +++ b/cmat/SolutionEx11bug/Ex11.sln @@ -0,0 +1,20 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ex11", "Ex11.vcxproj", "{E1F2BA40-B169-8D69-78E1-868C8A785A9C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E1F2BA40-B169-8D69-78E1-868C8A785A9C}.Debug|Win32.ActiveCfg = Debug|Win32 + {E1F2BA40-B169-8D69-78E1-868C8A785A9C}.Debug|Win32.Build.0 = Debug|Win32 + {E1F2BA40-B169-8D69-78E1-868C8A785A9C}.Release|Win32.ActiveCfg = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/cmat/SolutionEx11bug/Ex11.suo b/cmat/SolutionEx11bug/Ex11.suo new file mode 100644 index 0000000..11c06f2 Binary files /dev/null and b/cmat/SolutionEx11bug/Ex11.suo differ diff --git a/cmat/SolutionEx11bug/Ex11.vcproj b/cmat/SolutionEx11bug/Ex11.vcproj new file mode 100644 index 0000000..f350ab1 --- /dev/null +++ b/cmat/SolutionEx11bug/Ex11.vcproj @@ -0,0 +1,185 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cmat/SolutionEx11bug/Ex11.vcxproj b/cmat/SolutionEx11bug/Ex11.vcxproj new file mode 100644 index 0000000..4ef3de4 --- /dev/null +++ b/cmat/SolutionEx11bug/Ex11.vcxproj @@ -0,0 +1,141 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + {E1F2BA40-B169-8D69-78E1-868C8A785A9C} + + + + Application + false + MultiByte + v140 + + + Application + false + MultiByte + v140 + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + .\Release\ + .\Release\ + false + .\Debug\ + .\Debug\ + true + + + + OnlyExplicitInline + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + true + + + .\Release/Ex11.pch + .\Release/ + .\Release/ + .\Release/ + Level3 + true + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Release/Ex11.exe + true + .\Release/Ex11.pdb + Console + + + .\Release/Ex11.tlb + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + true + NotUsing + .\Debug/Ex11.pch + .\Debug/ + .\Debug/ + .\Debug/ + Level3 + true + C:\course\397\DOS_Unix;%(AdditionalIncludeDirectories) + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Debug/Ex11.exe + true + true + .\Debug/Ex11.pdb + Console + + + .\Debug/Ex11.tlb + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cmat/SolutionEx11bug/Ex11.vcxproj.filters b/cmat/SolutionEx11bug/Ex11.vcxproj.filters new file mode 100644 index 0000000..44383de --- /dev/null +++ b/cmat/SolutionEx11bug/Ex11.vcxproj.filters @@ -0,0 +1,71 @@ + + + + + {b96cbaea-8ae3-4716-865e-3aaf915fd0af} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {f948cebc-f590-4325-a5cc-fa8c85aa7733} + h;hpp;hxx;hm;inl + + + {c3395356-0a3a-4c18-8b27-851ff1f2369a} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + DOS_Unix + + + DOS_Unix + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + DOS_Unix + + + DOS_Unix + + + \ No newline at end of file diff --git a/cmat/SolutionEx11bug/Ex11.vcxproj.user b/cmat/SolutionEx11bug/Ex11.vcxproj.user new file mode 100644 index 0000000..695b5c7 --- /dev/null +++ b/cmat/SolutionEx11bug/Ex11.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cmat/SolutionEx11bug/Light.cpp b/cmat/SolutionEx11bug/Light.cpp new file mode 100644 index 0000000..e1e9e8e --- /dev/null +++ b/cmat/SolutionEx11bug/Light.cpp @@ -0,0 +1,22 @@ + + +#include "Light.h" +#include "CursesObj.h" +#include "Pelican.h" +#include "Screen.h" +#include + +Light::Light(std::string name, int x, int y, int color) : x(x), y(y), c(color), name(name) {} + +Light::~Light() { + std::cout << "Deleting light (" << name << ", " << x << ", " << y << ", " << c << ")" << std::endl; + std::cout.flush(); +} + +void Light::set(LightState newState) { + state = newState; + Screen::write(name.c_str(), x, y, state == LightState::FLASH ? (128 + c) : (state == LightState::OFF ? 0 : c)); + // 128 + color was used to make a character flash (but not any more) +} + +Light::LightState Light::get(void) { return state; } diff --git a/cmat/SolutionEx11bug/Light.h b/cmat/SolutionEx11bug/Light.h new file mode 100644 index 0000000..279695e --- /dev/null +++ b/cmat/SolutionEx11bug/Light.h @@ -0,0 +1,30 @@ +// ====================================================== +// +// Represents a light, implemented as a string written +// to a console window +// +// ====================================================== + +#ifndef LIGHT_H +#define LIGHT_H + +#include + +class Light { + public: + Light(std::string name, int x, int y, int color); + ~Light(); + + enum class LightState { ON, OFF, FLASH }; + + void set(LightState new_state); + LightState get(void); + + private: + int c; // light colour + int x, y; + std::string name; + LightState state; +}; + +#endif diff --git a/cmat/SolutionEx11bug/Pelican.cpp b/cmat/SolutionEx11bug/Pelican.cpp new file mode 100644 index 0000000..29e1c07 --- /dev/null +++ b/cmat/SolutionEx11bug/Pelican.cpp @@ -0,0 +1,66 @@ + + +#include "Pelican.h" +#include "PelicanTimer.h" +#include "Pole.h" + +Pelican::Pelican(int x, int y) + : pressed(false), RED_TIME(4), YELLOW_TIME(2), GREEN_TIME(3), FLASH_TIME(5), myPole(new Pole(x, y)), + state(GREEN_IDLE) { + myTimer = new PelicanTimer(*this, &Pelican::timerExpired); + + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed()); +} + +Pelican::~Pelican() { delete myPole; } + +void Pelican::press(void) { + if (state == GREEN_IDLE) { + state = YELLOW_STATE; + myTimer->timeoutRequest(YELLOW_TIME); + pressed = true; + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed()); + } else if (state != RED_STATE) { + pressed = true; + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed()); + } +} + +void Pelican::timerExpired(void) { + switch (state) { + case RED_STATE: + state = YELLOW_FLASHING; + myTimer->timeoutRequest(FLASH_TIME); + break; + + case YELLOW_FLASHING: + state = GREEN_TIMING; + myTimer->timeoutRequest(GREEN_TIME); + break; + + case GREEN_TIMING: + if (pressed) { + state = YELLOW_STATE; + myTimer->timeoutRequest(YELLOW_TIME); + } else { + state = GREEN_IDLE; + } + break; + + case GREEN_IDLE: + // should never happen + break; + + case YELLOW_STATE: + state = RED_STATE; + pressed = false; + myTimer->timeoutRequest(RED_TIME); + break; + } + + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed()); +} diff --git a/cmat/SolutionEx11bug/Pelican.h b/cmat/SolutionEx11bug/Pelican.h new file mode 100644 index 0000000..b7c8da0 --- /dev/null +++ b/cmat/SolutionEx11bug/Pelican.h @@ -0,0 +1,53 @@ +// ====================================================== +// +// Represents a Pelican crossing +// +// ====================================================== + +#ifndef PELICAN_H +#define PELICAN_H + +class PelicanTimer; +class Pole; + +class Pelican { + public: + Pelican(int x, int y); + ~Pelican(); + + // call when the WAIT button has been pressed + void press(void); + + // states that a Pelican can be in + enum PelicanState { RED_STATE, YELLOW_FLASHING, GREEN_TIMING, GREEN_IDLE, YELLOW_STATE }; + + bool isPressed() const { return pressed; } + PelicanState getState() const { return state; } + + private: + // state that this Pelican is in + PelicanState state; + + // called by PeleicanTimer when the lights need to change + void timerExpired(void); + + const unsigned int RED_TIME; + const unsigned int YELLOW_TIME; + const unsigned int GREEN_TIME; + const unsigned int FLASH_TIME; + + // indicates whether the WAIT light should be on + bool pressed; + + Pole *myPole; + + // Timer that indicates when the lights should change + PelicanTimer *myTimer; + + private: + // prevent general use of copy ctor and operator= + Pelican(const Pelican &); + Pelican &operator=(const Pelican &); +}; + +#endif diff --git a/cmat/SolutionEx11bug/PelicanTimer.cpp b/cmat/SolutionEx11bug/PelicanTimer.cpp new file mode 100644 index 0000000..b1a8c97 --- /dev/null +++ b/cmat/SolutionEx11bug/PelicanTimer.cpp @@ -0,0 +1,11 @@ + + +#include "PelicanTimer.h" + +PelicanTimer::PelicanTimer(Pelican &target, TargetFunc targetFunc) : myTarget(target), myTargetFunc(targetFunc) {} + +void PelicanTimer::tick() { + if (isExpired()) { + (myTarget.*myTargetFunc)(); + } +} diff --git a/cmat/SolutionEx11bug/PelicanTimer.h b/cmat/SolutionEx11bug/PelicanTimer.h new file mode 100644 index 0000000..3ce25b6 --- /dev/null +++ b/cmat/SolutionEx11bug/PelicanTimer.h @@ -0,0 +1,27 @@ +// ====================================================== +// +// This class specializes the Timer to enable it to +// stimulate a Pelican +// +// ====================================================== + +#ifndef PELICANTIMER_H +#define PELICANTIMER_H + +#include "Pelican.h" +#include "Timer.h" + +class PelicanTimer : public Timer { + public: + typedef void (Pelican::*TargetFunc)(); + + PelicanTimer(Pelican &target, TargetFunc targetFunc); + + virtual void tick(); + + private: + Pelican &myTarget; + TargetFunc myTargetFunc; +}; + +#endif diff --git a/cmat/SolutionEx11bug/Pole.h b/cmat/SolutionEx11bug/Pole.h new file mode 100644 index 0000000..a62d29b --- /dev/null +++ b/cmat/SolutionEx11bug/Pole.h @@ -0,0 +1,24 @@ + +#ifndef POLE_H +#define POLE_H + +#include "Light.h" +#include "Pelican.h" + +class Pole { + public: + Pole(int x, int y); + ~Pole(); + + void setTrafficLights(Pelican::PelicanState state); + void setWaitLight(bool pressed); + + private: + enum LightName { RED_LIGHT, YELLOW_LIGHT, GREEN_LIGHT, GREEN_MAN, RED_MAN }; + + Light *lights[RED_MAN + 1]; + + Light *waitLight; +}; + +#endif diff --git a/cmat/SolutionEx11bug/Timer.cpp b/cmat/SolutionEx11bug/Timer.cpp new file mode 100644 index 0000000..f4daa3f --- /dev/null +++ b/cmat/SolutionEx11bug/Timer.cpp @@ -0,0 +1,17 @@ + + +#include "Timer.h" +#include "TimerSet.h" + +void Timer::timeoutRequest(int seconds) { timeToGo = seconds; } + +Timer::Timer() : timeToGo(-1) { theTimerSet.addATimer(this); } + +bool Timer::isExpired() { + if (timeToGo > 0) { + if (--timeToGo == 0) { + return true; + } + } + return false; +} diff --git a/cmat/SolutionEx11bug/Timer.h b/cmat/SolutionEx11bug/Timer.h new file mode 100644 index 0000000..2deb1e1 --- /dev/null +++ b/cmat/SolutionEx11bug/Timer.h @@ -0,0 +1,27 @@ +// ====================================================== +// +// A general-purpose countdown timer +// To use this class, specialize it +// and override tick() +// +// ====================================================== + +#ifndef TIMER_H +#define TIMER_H + +class Timer { + public: + Timer(); + + void timeoutRequest(int seconds); + + virtual void tick() = 0; + + protected: + bool isExpired(); + + private: + int timeToGo; +}; + +#endif diff --git a/cmat/SolutionEx11bug/TimerSet.cpp b/cmat/SolutionEx11bug/TimerSet.cpp new file mode 100644 index 0000000..d33a408 --- /dev/null +++ b/cmat/SolutionEx11bug/TimerSet.cpp @@ -0,0 +1,22 @@ + + +#include "TimerSet.h" +#include "Timer.h" + +TimerSet theTimerSet; + + + +TimerSet::TimerSet() : timersInUse(0), previousTime(time(&previousTime)) {} + +void TimerSet::addATimer(Timer *t) { timers[timersInUse++] = t; } + +void TimerSet::pollAllTimers() { + std::time_t timeNow; + if (time(&timeNow) > previousTime) { + previousTime = timeNow; + for (int i = 0; i < timersInUse; ++i) { + timers[i]->tick(); + } + } +} diff --git a/cmat/SolutionEx11bug/TimerSet.h b/cmat/SolutionEx11bug/TimerSet.h new file mode 100644 index 0000000..1ea4123 --- /dev/null +++ b/cmat/SolutionEx11bug/TimerSet.h @@ -0,0 +1,23 @@ +#ifndef TIMERSET_H +#define TIMERSET_H + +#include + +class Timer; + +class TimerSet { + public: + TimerSet(); + + void pollAllTimers(); + void addATimer(Timer *); + + private: + Timer *timers[40]; + int timersInUse; + std::time_t previousTime; +}; + +extern TimerSet theTimerSet; + +#endif diff --git a/cmat/SolutionEx11bug/main.cpp b/cmat/SolutionEx11bug/main.cpp new file mode 100644 index 0000000..fff22a7 --- /dev/null +++ b/cmat/SolutionEx11bug/main.cpp @@ -0,0 +1,29 @@ + + +#include "Keyboard.h" +#include "Pelican.h" +#include "TimerSet.h" + +#include // provides toupper() + +int main() { + Keyboard kbd; + Pelican thePelican(30, 0); + + char c = 0; + + while (std::toupper(c) != 'Q') { // loop until 'Q' is pressed + + while (!kbd.isCharAvail()) { + theTimerSet.pollAllTimers(); // no key press to process, poll the timers + } + + c = kbd.getChar(); // get the character + if (c == ' ') { + // it's a space, so press the WAIT button + thePelican.press(); + } + } + + return 0; +} diff --git a/cmat/SolutionEx11bug/make.mk b/cmat/SolutionEx11bug/make.mk new file mode 100644 index 0000000..9262097 --- /dev/null +++ b/cmat/SolutionEx11bug/make.mk @@ -0,0 +1,2 @@ +BASEOBJS = \ + Light.o main.o Pelican.o PelicanTimer.o Pole.o Timer.o TimerSet.o diff --git a/cmat/SolutionEx11bug/makefile b/cmat/SolutionEx11bug/makefile new file mode 100644 index 0000000..13a67ac --- /dev/null +++ b/cmat/SolutionEx11bug/makefile @@ -0,0 +1,17 @@ +COMPILER = gcc +FLAGS = +INCLUDES = -I/usr/local/include/c++/3.4.2 -I../DOS_Unix +ARCHIVES = -L/usr/local/lib/gcc/sparc-sun-solaris2.7/3.4.2 -L/usr/local/lib -L/usr/lib +UNIX_OBJS = ../DOS_Unix/CursesObj.o ../DOS_Unix/Keyboard_Unix.o ../DOS_Unix/Screen_Unix.o + +include make.mk + +.SUFFIXES: .cpp .o + +all: pelican + +.cpp.o: + $(COMPILER) $(INCLUDES) -frepo -c $(FLAGS) $*.cpp + +pelican : $(BASEOBJS) + $(COMPILER) $(ARCHIVES) -o pelican -lcurses $(BASEOBJS) $(UNIX_OBJS) -lcurses -lstdc++ -static diff --git a/cmat/SolutionEx11bug/pole.cpp b/cmat/SolutionEx11bug/pole.cpp new file mode 100644 index 0000000..ae22c5b --- /dev/null +++ b/cmat/SolutionEx11bug/pole.cpp @@ -0,0 +1,60 @@ +#include "Pole.h" +#include "Screen.h" + +Pole::Pole(int x, int y) : waitLight(new Light("WAIT", x + 6, y + 12, Screen::WHITE)) { + using namespace Screen; // we will discuss namespaces in the course + + lights[RED_LIGHT] = new Light("*", x + 11, y + 3, RED); + lights[RED_MAN] = new Light("*<-=", x + 6, y + 4, RED); + lights[YELLOW_LIGHT] = new Light("*", x + 11, y + 5, YELLOW); + lights[GREEN_LIGHT] = new Light("*", x + 11, y + 7, GREEN); + lights[GREEN_MAN] = new Light("*|-<", x + 6, y + 7, GREEN); + + write(" _____ ", x, ++y, GRAY); + write(" /___ /| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" | |/| ", x, ++y, GRAY); + write(" |____| | ", x, ++y, GRAY); + write(" | |/| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" |____|/ ", x, ++y, GRAY); + write(" _||__ ", x, ++y, GRAY); + write(" /___ /| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" |____|/ ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write("========||===========", x, ++y, GRAY); + write(" / || / ", x, ++y, GRAY); + write("_ /_________ /_ ", x, ++y, GRAY); + write("/ / ", x, ++y, GRAY); +} + +Pole::~Pole() { + for (int i = 0; i < sizeof lights / sizeof(lights[0]); ++i) + delete lights[i]; + delete waitLight; +} + +void Pole::setTrafficLights(Pelican::PelicanState state) { + + static const Light::LightState LightStates[Pelican::YELLOW_STATE + 1][RED_MAN + 1] = { + // red yellow green green man red man + {Light::LightState::ON, Light::LightState::OFF, Light::LightState::OFF, Light::LightState::ON, Light::LightState::OFF}, // red + {Light::LightState::OFF, Light::LightState::FLASH, Light::LightState::OFF, Light::LightState::FLASH, Light::LightState::OFF}, // y flash + {Light::LightState::OFF, Light::LightState::OFF, Light::LightState::ON, Light::LightState::OFF, Light::LightState::ON}, // g time + {Light::LightState::OFF, Light::LightState::OFF, Light::LightState::ON, Light::LightState::OFF, Light::LightState::ON}, // g idle + {Light::LightState::OFF, Light::LightState::ON, Light::LightState::OFF, Light::LightState::OFF, Light::LightState::ON} // yellow + }; + + for (int i = RED_LIGHT; i <= RED_MAN; i++) { + lights[i]->set(LightStates[state][i]); + } +} + +void Pole::setWaitLight(bool pressed) { waitLight->set(pressed ? Light::LightState::ON : Light::LightState::OFF); } diff --git a/cmat/SolutionEx21/CMakeLists.txt b/cmat/SolutionEx21/CMakeLists.txt new file mode 100644 index 0000000..2762ada --- /dev/null +++ b/cmat/SolutionEx21/CMakeLists.txt @@ -0,0 +1,13 @@ +# SolutionEx21 + +cmat_add_exercise(SolutionEx21 + GUI + SOURCES + Light.cpp + Main.cpp + Pelican.cpp + PelicanTimer.cpp + Pole.cpp + Timer.cpp + TimerSet.cpp +) diff --git a/cmat/SolutionEx21/Ex21.sln b/cmat/SolutionEx21/Ex21.sln new file mode 100644 index 0000000..2e69fc6 --- /dev/null +++ b/cmat/SolutionEx21/Ex21.sln @@ -0,0 +1,20 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ex21", "Ex21.vcxproj", "{AC7B29B3-9F42-7C36-686F-2F829309B86D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {AC7B29B3-9F42-7C36-686F-2F829309B86D}.Debug|Win32.ActiveCfg = Debug|Win32 + {AC7B29B3-9F42-7C36-686F-2F829309B86D}.Debug|Win32.Build.0 = Debug|Win32 + {AC7B29B3-9F42-7C36-686F-2F829309B86D}.Release|Win32.ActiveCfg = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/cmat/SolutionEx21/Ex21.suo b/cmat/SolutionEx21/Ex21.suo new file mode 100644 index 0000000..4177a2c Binary files /dev/null and b/cmat/SolutionEx21/Ex21.suo differ diff --git a/cmat/SolutionEx21/Ex21.vcproj b/cmat/SolutionEx21/Ex21.vcproj new file mode 100644 index 0000000..dbda167 --- /dev/null +++ b/cmat/SolutionEx21/Ex21.vcproj @@ -0,0 +1,185 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cmat/SolutionEx21/Ex21.vcxproj b/cmat/SolutionEx21/Ex21.vcxproj new file mode 100644 index 0000000..8505ca4 --- /dev/null +++ b/cmat/SolutionEx21/Ex21.vcxproj @@ -0,0 +1,141 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + {AC7B29B3-9F42-7C36-686F-2F829309B86D} + + + + Application + false + MultiByte + v140 + + + Application + false + MultiByte + v140 + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + .\Release\ + .\Release\ + false + .\Debug\ + .\Debug\ + true + + + + OnlyExplicitInline + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + true + + + .\Release/Ex21.pch + .\Release/ + .\Release/ + .\Release/ + Level3 + true + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Release/Ex21.exe + true + .\Release/Ex21.pdb + Console + + + .\Release/Ex21.tlb + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + true + NotUsing + .\Debug/Ex21.pch + .\Debug/ + .\Debug/ + .\Debug/ + Level3 + true + C:\course\397\DOS_Unix;%(AdditionalIncludeDirectories) + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Debug/Ex21.exe + true + true + .\Debug/Ex21.pdb + Console + + + .\Debug/Ex21.tlb + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cmat/SolutionEx21/Ex21.vcxproj.filters b/cmat/SolutionEx21/Ex21.vcxproj.filters new file mode 100644 index 0000000..98467ba --- /dev/null +++ b/cmat/SolutionEx21/Ex21.vcxproj.filters @@ -0,0 +1,71 @@ + + + + + {4b16368f-6693-40c4-8fcf-13a85f344069} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {2ec889ee-bec0-46c7-8125-b8c144b9328a} + h;hpp;hxx;hm;inl + + + {a57625e1-03b9-42e5-93c8-03d083fc7d09} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + DOS_Unix + + + DOS_Unix + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + DOS_Unix + + + DOS_Unix + + + \ No newline at end of file diff --git a/cmat/SolutionEx21/Ex21.vcxproj.user b/cmat/SolutionEx21/Ex21.vcxproj.user new file mode 100644 index 0000000..695b5c7 --- /dev/null +++ b/cmat/SolutionEx21/Ex21.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cmat/SolutionEx21/Light.cpp b/cmat/SolutionEx21/Light.cpp new file mode 100644 index 0000000..e111c52 --- /dev/null +++ b/cmat/SolutionEx21/Light.cpp @@ -0,0 +1,21 @@ + + +#include "Light.h" +#include "Pelican.h" +#include "Screen.h" +#include + +Light::Light(std::string name, int x, int y, int color) : x(x), y(y), c(color), name(name) {} + +Light::~Light() { + std::cout << "Deleting light (" << name << ", " << x << ", " << y << ", " << c << ")" + << "\n"; +} + +void Light::set(LightState newState) { + state = newState; + Screen::write(name.c_str(), x, y, state == FLASH ? (128 + c) : (state == OFF ? 0 : c)); + // 128 + color was used to make a character flash (but not any more) +} + +Light::LightState Light::get(void) { return state; } diff --git a/cmat/SolutionEx21/Light.h b/cmat/SolutionEx21/Light.h new file mode 100644 index 0000000..03adf9a --- /dev/null +++ b/cmat/SolutionEx21/Light.h @@ -0,0 +1,30 @@ +// ====================================================== +// +// Represents a light, implemented as a string written +// to a console window +// +// ====================================================== + +#ifndef LIGHT_H +#define LIGHT_H + +#include + +class Light { + public: + Light(std::string name, int x, int y, int color); + ~Light(); + + enum LightState { ON, OFF, FLASH }; + + void set(LightState new_state); + LightState get(void); + + private: + int c; // light colour + int x, y; + std::string name; + LightState state; +}; + +#endif diff --git a/cmat/SolutionEx21/Main.cpp b/cmat/SolutionEx21/Main.cpp new file mode 100644 index 0000000..1cecd5c --- /dev/null +++ b/cmat/SolutionEx21/Main.cpp @@ -0,0 +1,29 @@ + + +#include "Keyboard.h" +#include "Pelican.h" +#include "TimerSet.h" + +#include // provides toupper() + +int main() { + Keyboard kbd; + Pelican thePelican(30, 0); + + char c = 0; + + while (std::toupper(c) != 'Q') { // loop until 'Q' is pressed + + while (!kbd.isCharAvail()) { + TimerSet::Instance().pollAllTimers(); // no key press to process, poll the timers + } + + c = kbd.getChar(); // get the character + if (c == ' ') { + // it's a space, so press the WAIT button + thePelican.press(); + } + } + + return 0; +} diff --git a/cmat/SolutionEx21/Pelican.cpp b/cmat/SolutionEx21/Pelican.cpp new file mode 100644 index 0000000..29e1c07 --- /dev/null +++ b/cmat/SolutionEx21/Pelican.cpp @@ -0,0 +1,66 @@ + + +#include "Pelican.h" +#include "PelicanTimer.h" +#include "Pole.h" + +Pelican::Pelican(int x, int y) + : pressed(false), RED_TIME(4), YELLOW_TIME(2), GREEN_TIME(3), FLASH_TIME(5), myPole(new Pole(x, y)), + state(GREEN_IDLE) { + myTimer = new PelicanTimer(*this, &Pelican::timerExpired); + + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed()); +} + +Pelican::~Pelican() { delete myPole; } + +void Pelican::press(void) { + if (state == GREEN_IDLE) { + state = YELLOW_STATE; + myTimer->timeoutRequest(YELLOW_TIME); + pressed = true; + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed()); + } else if (state != RED_STATE) { + pressed = true; + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed()); + } +} + +void Pelican::timerExpired(void) { + switch (state) { + case RED_STATE: + state = YELLOW_FLASHING; + myTimer->timeoutRequest(FLASH_TIME); + break; + + case YELLOW_FLASHING: + state = GREEN_TIMING; + myTimer->timeoutRequest(GREEN_TIME); + break; + + case GREEN_TIMING: + if (pressed) { + state = YELLOW_STATE; + myTimer->timeoutRequest(YELLOW_TIME); + } else { + state = GREEN_IDLE; + } + break; + + case GREEN_IDLE: + // should never happen + break; + + case YELLOW_STATE: + state = RED_STATE; + pressed = false; + myTimer->timeoutRequest(RED_TIME); + break; + } + + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed()); +} diff --git a/cmat/SolutionEx21/Pelican.h b/cmat/SolutionEx21/Pelican.h new file mode 100644 index 0000000..b7c8da0 --- /dev/null +++ b/cmat/SolutionEx21/Pelican.h @@ -0,0 +1,53 @@ +// ====================================================== +// +// Represents a Pelican crossing +// +// ====================================================== + +#ifndef PELICAN_H +#define PELICAN_H + +class PelicanTimer; +class Pole; + +class Pelican { + public: + Pelican(int x, int y); + ~Pelican(); + + // call when the WAIT button has been pressed + void press(void); + + // states that a Pelican can be in + enum PelicanState { RED_STATE, YELLOW_FLASHING, GREEN_TIMING, GREEN_IDLE, YELLOW_STATE }; + + bool isPressed() const { return pressed; } + PelicanState getState() const { return state; } + + private: + // state that this Pelican is in + PelicanState state; + + // called by PeleicanTimer when the lights need to change + void timerExpired(void); + + const unsigned int RED_TIME; + const unsigned int YELLOW_TIME; + const unsigned int GREEN_TIME; + const unsigned int FLASH_TIME; + + // indicates whether the WAIT light should be on + bool pressed; + + Pole *myPole; + + // Timer that indicates when the lights should change + PelicanTimer *myTimer; + + private: + // prevent general use of copy ctor and operator= + Pelican(const Pelican &); + Pelican &operator=(const Pelican &); +}; + +#endif diff --git a/cmat/SolutionEx21/PelicanTimer.cpp b/cmat/SolutionEx21/PelicanTimer.cpp new file mode 100644 index 0000000..bbb0b9b --- /dev/null +++ b/cmat/SolutionEx21/PelicanTimer.cpp @@ -0,0 +1,10 @@ + +#include "PelicanTimer.h" + +PelicanTimer::PelicanTimer(Pelican &target, TargetFunc targetFunc) : myTarget(target), myTargetFunc(targetFunc) {} + +void PelicanTimer::tick() { + if (isExpired()) { + (myTarget.*myTargetFunc)(); + } +} diff --git a/cmat/SolutionEx21/PelicanTimer.h b/cmat/SolutionEx21/PelicanTimer.h new file mode 100644 index 0000000..6a8e936 --- /dev/null +++ b/cmat/SolutionEx21/PelicanTimer.h @@ -0,0 +1,31 @@ +// ====================================================== +// +// This class specializes the Timer to enable it to +// stimulate a Pelican +// +// ====================================================== + +#ifndef PELICANTIMER_H +#define PELICANTIMER_H + +#include "Pelican.h" +#include "Timer.h" + +class PelicanTimer : public Timer { + public: + typedef void (Pelican::*TargetFunc)(); + + PelicanTimer(Pelican &target, TargetFunc targetFunc); + + // TODO: Remove this function + virtual void tick(); + + // TODO: Add override of virtual function Timer::doExpired + // (this is the "primitive step" of the template method pattern) + + private: + Pelican &myTarget; + TargetFunc myTargetFunc; +}; + +#endif diff --git a/cmat/SolutionEx21/Pole.cpp b/cmat/SolutionEx21/Pole.cpp new file mode 100644 index 0000000..aeec308 --- /dev/null +++ b/cmat/SolutionEx21/Pole.cpp @@ -0,0 +1,59 @@ +#include "Pole.h" +#include "Screen.h" + +Pole::Pole(int x, int y) : waitLight(new Light("WAIT", x + 6, y + 12, Screen::WHITE)) { + using namespace Screen; // we will discuss namespaces in the course + + lights[RED_LIGHT] = new Light("*", x + 11, y + 3, RED); + lights[RED_MAN] = new Light("*<-=", x + 6, y + 4, RED); + lights[YELLOW_LIGHT] = new Light("*", x + 11, y + 5, YELLOW); + lights[GREEN_LIGHT] = new Light("*", x + 11, y + 7, GREEN); + lights[GREEN_MAN] = new Light("*|-<", x + 6, y + 7, GREEN); + + write(" _____ ", x, ++y, GRAY); + write(" /___ /| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" | |/| ", x, ++y, GRAY); + write(" |____| | ", x, ++y, GRAY); + write(" | |/| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" |____|/ ", x, ++y, GRAY); + write(" _||__ ", x, ++y, GRAY); + write(" /___ /| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" |____|/ ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write("========||===========", x, ++y, GRAY); + write(" / || / ", x, ++y, GRAY); + write("_ /_________ /_ ", x, ++y, GRAY); + write("/ / ", x, ++y, GRAY); +} + +Pole::~Pole() { + for (int i = 0; i < sizeof lights / sizeof(lights[0]); ++i) + delete lights[i]; + delete waitLight; +} + +void Pole::setTrafficLights(Pelican::PelicanState state) { + static const Light::LightState LightStates[Pelican::YELLOW_STATE + 1][RED_MAN + 1] = { + // red yellow green green man red man + {Light::ON, Light::OFF, Light::OFF, Light::ON, Light::OFF}, // red + {Light::OFF, Light::FLASH, Light::OFF, Light::FLASH, Light::OFF}, // y flash + {Light::OFF, Light::OFF, Light::ON, Light::OFF, Light::ON}, // g time + {Light::OFF, Light::OFF, Light::ON, Light::OFF, Light::ON}, // g idle + {Light::OFF, Light::ON, Light::OFF, Light::OFF, Light::ON} // yellow + }; + + for (int i = RED_LIGHT; i <= RED_MAN; i++) { + lights[i]->set(LightStates[state][i]); + } +} + +void Pole::setWaitLight(bool pressed) { waitLight->set(pressed ? Light::ON : Light::OFF); } diff --git a/cmat/SolutionEx21/Pole.h b/cmat/SolutionEx21/Pole.h new file mode 100644 index 0000000..cc271ec --- /dev/null +++ b/cmat/SolutionEx21/Pole.h @@ -0,0 +1,25 @@ + + +#ifndef POLE_H +#define POLE_H + +#include "Light.h" +#include "Pelican.h" + +class Pole { + public: + Pole(int x, int y); + ~Pole(); + + void setTrafficLights(Pelican::PelicanState state); + void setWaitLight(bool pressed); + + private: + enum LightName { RED_LIGHT, YELLOW_LIGHT, GREEN_LIGHT, GREEN_MAN, RED_MAN }; + + Light *lights[RED_MAN + 1]; + + Light *waitLight; +}; + +#endif diff --git a/cmat/SolutionEx21/Timer.cpp b/cmat/SolutionEx21/Timer.cpp new file mode 100644 index 0000000..1384258 --- /dev/null +++ b/cmat/SolutionEx21/Timer.cpp @@ -0,0 +1,17 @@ + + +#include "Timer.h" +#include "TimerSet.h" + +void Timer::timeoutRequest(int seconds) { timeToGo = seconds; } + +Timer::Timer() : timeToGo(-1) { TimerSet::Instance().addATimer(this); } + +bool Timer::isExpired() { + if (timeToGo > 0) { + if (--timeToGo == 0) { + return true; + } + } + return false; +} diff --git a/cmat/SolutionEx21/Timer.h b/cmat/SolutionEx21/Timer.h new file mode 100644 index 0000000..b52947b --- /dev/null +++ b/cmat/SolutionEx21/Timer.h @@ -0,0 +1,27 @@ +// ====================================================== +// +// A general-purpose countdown timer +// To use this class, specialize it +// and override tick() +// +// ====================================================== + +#ifndef timer_H +#define timer_H + +class Timer { + public: + Timer(); + + void timeoutRequest(int seconds); + + virtual void tick() = 0; + + protected: + bool isExpired(); + + private: + int timeToGo; +}; + +#endif diff --git a/cmat/SolutionEx21/TimerSet.cpp b/cmat/SolutionEx21/TimerSet.cpp new file mode 100644 index 0000000..2a68d12 --- /dev/null +++ b/cmat/SolutionEx21/TimerSet.cpp @@ -0,0 +1,23 @@ +#include "TimerSet.h" +#include "Timer.h" +#include + +TimerSet::TimerSet() : timersInUse(0), previousTime(time(NULL)) {} + +void TimerSet::addATimer(Timer *t) { timers[timersInUse++] = t; } + +void TimerSet::pollAllTimers() { + std::time_t timeNow; + if (time(&timeNow) > previousTime) { + previousTime = timeNow; + for (int i = 0; i < timersInUse; ++i) { + timers[i]->tick(); + } + } +} + +TimerSet &TimerSet::Instance() { + // Meyer's Singleton implementation + static TimerSet pInstance; + return pInstance; +} diff --git a/cmat/SolutionEx21/TimerSet.h b/cmat/SolutionEx21/TimerSet.h new file mode 100644 index 0000000..3dfe925 --- /dev/null +++ b/cmat/SolutionEx21/TimerSet.h @@ -0,0 +1,29 @@ +#ifndef TIMERSET_H +#define TIMERSET_H + +#include + +class Timer; + +class TimerSet { + public: + void pollAllTimers(); + void addATimer(Timer *); + + private: + TimerSet(); + Timer *timers[40]; + int timersInUse; + std::time_t previousTime; + + // Meyer's singleton + public: + static TimerSet &Instance(); + + private: + // prevent copying and assignment of the singleton + TimerSet(const TimerSet &); + TimerSet &operator=(const TimerSet &); +}; + +#endif diff --git a/cmat/SolutionEx22/CMakeLists.txt b/cmat/SolutionEx22/CMakeLists.txt new file mode 100644 index 0000000..a91ba3b --- /dev/null +++ b/cmat/SolutionEx22/CMakeLists.txt @@ -0,0 +1,13 @@ +# SolutionEx22 + +cmat_add_exercise(SolutionEx22 + GUI + SOURCES + Light.cpp + main.cpp + Pelican.cpp + PelicanTimer.cpp + Pole.cpp + Timer.cpp + TimerSet.cpp +) diff --git a/cmat/SolutionEx22/Ex22.sln b/cmat/SolutionEx22/Ex22.sln new file mode 100644 index 0000000..e1ea084 --- /dev/null +++ b/cmat/SolutionEx22/Ex22.sln @@ -0,0 +1,20 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ex22", "Ex22.vcxproj", "{C2EDBD25-9006-0438-220A-8766E6F352A8}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C2EDBD25-9006-0438-220A-8766E6F352A8}.Debug|Win32.ActiveCfg = Debug|Win32 + {C2EDBD25-9006-0438-220A-8766E6F352A8}.Debug|Win32.Build.0 = Debug|Win32 + {C2EDBD25-9006-0438-220A-8766E6F352A8}.Release|Win32.ActiveCfg = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/cmat/SolutionEx22/Ex22.suo b/cmat/SolutionEx22/Ex22.suo new file mode 100644 index 0000000..5e8ec65 Binary files /dev/null and b/cmat/SolutionEx22/Ex22.suo differ diff --git a/cmat/SolutionEx22/Ex22.vcproj b/cmat/SolutionEx22/Ex22.vcproj new file mode 100644 index 0000000..b96f6d2 --- /dev/null +++ b/cmat/SolutionEx22/Ex22.vcproj @@ -0,0 +1,182 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cmat/SolutionEx22/Ex22.vcxproj b/cmat/SolutionEx22/Ex22.vcxproj new file mode 100644 index 0000000..252027e --- /dev/null +++ b/cmat/SolutionEx22/Ex22.vcxproj @@ -0,0 +1,140 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + {C2EDBD25-9006-0438-220A-8766E6F352A8} + + + + Application + false + MultiByte + v140 + + + Application + false + MultiByte + v140 + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + .\Debug\ + .\Debug\ + true + .\Release\ + .\Release\ + false + + + + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + true + NotUsing + .\Debug/Ex22.pch + .\Debug/ + .\Debug/ + .\Debug/ + Level3 + true + C:\course\397\DOS_Unix;%(AdditionalIncludeDirectories) + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Debug/Ex22.exe + true + true + .\Debug/Ex22.pdb + Console + + + .\Debug/Ex22.tlb + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + OnlyExplicitInline + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + true + + + .\Release/Ex22.pch + .\Release/ + .\Release/ + .\Release/ + Level3 + true + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Release/Ex22.exe + true + .\Release/Ex22.pdb + Console + + + .\Release/Ex22.tlb + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cmat/SolutionEx22/Ex22.vcxproj.filters b/cmat/SolutionEx22/Ex22.vcxproj.filters new file mode 100644 index 0000000..a30671e --- /dev/null +++ b/cmat/SolutionEx22/Ex22.vcxproj.filters @@ -0,0 +1,68 @@ + + + + + {17deccef-8801-49d5-8ba1-c5db56fa73c0} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {eaf1391b-78b1-4db8-adb1-2585eaedd6e7} + h;hpp;hxx;hm;inl + + + {f8ec245a-126d-413b-8f31-4f57d4342719} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + DOS_Unix + + + DOS_Unix + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + DOS_Unix + + + DOS_Unix + + + \ No newline at end of file diff --git a/cmat/SolutionEx22/Ex22.vcxproj.user b/cmat/SolutionEx22/Ex22.vcxproj.user new file mode 100644 index 0000000..695b5c7 --- /dev/null +++ b/cmat/SolutionEx22/Ex22.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cmat/SolutionEx22/Light.cpp b/cmat/SolutionEx22/Light.cpp new file mode 100644 index 0000000..e111c52 --- /dev/null +++ b/cmat/SolutionEx22/Light.cpp @@ -0,0 +1,21 @@ + + +#include "Light.h" +#include "Pelican.h" +#include "Screen.h" +#include + +Light::Light(std::string name, int x, int y, int color) : x(x), y(y), c(color), name(name) {} + +Light::~Light() { + std::cout << "Deleting light (" << name << ", " << x << ", " << y << ", " << c << ")" + << "\n"; +} + +void Light::set(LightState newState) { + state = newState; + Screen::write(name.c_str(), x, y, state == FLASH ? (128 + c) : (state == OFF ? 0 : c)); + // 128 + color was used to make a character flash (but not any more) +} + +Light::LightState Light::get(void) { return state; } diff --git a/cmat/SolutionEx22/Light.h b/cmat/SolutionEx22/Light.h new file mode 100644 index 0000000..035c0f0 --- /dev/null +++ b/cmat/SolutionEx22/Light.h @@ -0,0 +1,31 @@ +// ====================================================== +// Light.h +// +// Represents a light, implemented as a string written +// to a console window +// +// ====================================================== + +#ifndef LIGHT_H +#define LIGHT_H + +#include + +class Light { + public: + Light(std::string name, int x, int y, int color); + ~Light(); + + enum LightState { ON, OFF, FLASH }; + + void set(LightState new_state); + LightState get(void); + + private: + int c; // light colour + int x, y; + std::string name; + LightState state; +}; + +#endif diff --git a/cmat/SolutionEx22/Pelican.cpp b/cmat/SolutionEx22/Pelican.cpp new file mode 100644 index 0000000..29e1c07 --- /dev/null +++ b/cmat/SolutionEx22/Pelican.cpp @@ -0,0 +1,66 @@ + + +#include "Pelican.h" +#include "PelicanTimer.h" +#include "Pole.h" + +Pelican::Pelican(int x, int y) + : pressed(false), RED_TIME(4), YELLOW_TIME(2), GREEN_TIME(3), FLASH_TIME(5), myPole(new Pole(x, y)), + state(GREEN_IDLE) { + myTimer = new PelicanTimer(*this, &Pelican::timerExpired); + + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed()); +} + +Pelican::~Pelican() { delete myPole; } + +void Pelican::press(void) { + if (state == GREEN_IDLE) { + state = YELLOW_STATE; + myTimer->timeoutRequest(YELLOW_TIME); + pressed = true; + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed()); + } else if (state != RED_STATE) { + pressed = true; + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed()); + } +} + +void Pelican::timerExpired(void) { + switch (state) { + case RED_STATE: + state = YELLOW_FLASHING; + myTimer->timeoutRequest(FLASH_TIME); + break; + + case YELLOW_FLASHING: + state = GREEN_TIMING; + myTimer->timeoutRequest(GREEN_TIME); + break; + + case GREEN_TIMING: + if (pressed) { + state = YELLOW_STATE; + myTimer->timeoutRequest(YELLOW_TIME); + } else { + state = GREEN_IDLE; + } + break; + + case GREEN_IDLE: + // should never happen + break; + + case YELLOW_STATE: + state = RED_STATE; + pressed = false; + myTimer->timeoutRequest(RED_TIME); + break; + } + + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed()); +} diff --git a/cmat/SolutionEx22/Pelican.h b/cmat/SolutionEx22/Pelican.h new file mode 100644 index 0000000..b7c8da0 --- /dev/null +++ b/cmat/SolutionEx22/Pelican.h @@ -0,0 +1,53 @@ +// ====================================================== +// +// Represents a Pelican crossing +// +// ====================================================== + +#ifndef PELICAN_H +#define PELICAN_H + +class PelicanTimer; +class Pole; + +class Pelican { + public: + Pelican(int x, int y); + ~Pelican(); + + // call when the WAIT button has been pressed + void press(void); + + // states that a Pelican can be in + enum PelicanState { RED_STATE, YELLOW_FLASHING, GREEN_TIMING, GREEN_IDLE, YELLOW_STATE }; + + bool isPressed() const { return pressed; } + PelicanState getState() const { return state; } + + private: + // state that this Pelican is in + PelicanState state; + + // called by PeleicanTimer when the lights need to change + void timerExpired(void); + + const unsigned int RED_TIME; + const unsigned int YELLOW_TIME; + const unsigned int GREEN_TIME; + const unsigned int FLASH_TIME; + + // indicates whether the WAIT light should be on + bool pressed; + + Pole *myPole; + + // Timer that indicates when the lights should change + PelicanTimer *myTimer; + + private: + // prevent general use of copy ctor and operator= + Pelican(const Pelican &); + Pelican &operator=(const Pelican &); +}; + +#endif diff --git a/cmat/SolutionEx22/PelicanTimer.cpp b/cmat/SolutionEx22/PelicanTimer.cpp new file mode 100644 index 0000000..f9c107a --- /dev/null +++ b/cmat/SolutionEx22/PelicanTimer.cpp @@ -0,0 +1,7 @@ + + +#include "PelicanTimer.h" + +PelicanTimer::PelicanTimer(Pelican &target, TargetFunc targetFunc) : myTarget(target), myTargetFunc(targetFunc) {} + +void PelicanTimer::doExpired() { (myTarget.*myTargetFunc)(); } diff --git a/cmat/SolutionEx22/PelicanTimer.h b/cmat/SolutionEx22/PelicanTimer.h new file mode 100644 index 0000000..637290c --- /dev/null +++ b/cmat/SolutionEx22/PelicanTimer.h @@ -0,0 +1,27 @@ +// ====================================================== +// +// This class specializes the Timer to enable it to +// stimulate a Pelican +// +// ====================================================== + +#ifndef PelicanTimer_H +#define PelicanTimer_H + +#include "Pelican.h" +#include "Timer.h" + +class PelicanTimer : public Timer { + public: + typedef void (Pelican::*TargetFunc)(); + + PelicanTimer(Pelican &target, TargetFunc targetFunc); + + private: + void doExpired(); + + Pelican &myTarget; + TargetFunc myTargetFunc; +}; + +#endif diff --git a/cmat/SolutionEx22/Pole.cpp b/cmat/SolutionEx22/Pole.cpp new file mode 100644 index 0000000..aeec308 --- /dev/null +++ b/cmat/SolutionEx22/Pole.cpp @@ -0,0 +1,59 @@ +#include "Pole.h" +#include "Screen.h" + +Pole::Pole(int x, int y) : waitLight(new Light("WAIT", x + 6, y + 12, Screen::WHITE)) { + using namespace Screen; // we will discuss namespaces in the course + + lights[RED_LIGHT] = new Light("*", x + 11, y + 3, RED); + lights[RED_MAN] = new Light("*<-=", x + 6, y + 4, RED); + lights[YELLOW_LIGHT] = new Light("*", x + 11, y + 5, YELLOW); + lights[GREEN_LIGHT] = new Light("*", x + 11, y + 7, GREEN); + lights[GREEN_MAN] = new Light("*|-<", x + 6, y + 7, GREEN); + + write(" _____ ", x, ++y, GRAY); + write(" /___ /| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" | |/| ", x, ++y, GRAY); + write(" |____| | ", x, ++y, GRAY); + write(" | |/| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" |____|/ ", x, ++y, GRAY); + write(" _||__ ", x, ++y, GRAY); + write(" /___ /| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" |____|/ ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write("========||===========", x, ++y, GRAY); + write(" / || / ", x, ++y, GRAY); + write("_ /_________ /_ ", x, ++y, GRAY); + write("/ / ", x, ++y, GRAY); +} + +Pole::~Pole() { + for (int i = 0; i < sizeof lights / sizeof(lights[0]); ++i) + delete lights[i]; + delete waitLight; +} + +void Pole::setTrafficLights(Pelican::PelicanState state) { + static const Light::LightState LightStates[Pelican::YELLOW_STATE + 1][RED_MAN + 1] = { + // red yellow green green man red man + {Light::ON, Light::OFF, Light::OFF, Light::ON, Light::OFF}, // red + {Light::OFF, Light::FLASH, Light::OFF, Light::FLASH, Light::OFF}, // y flash + {Light::OFF, Light::OFF, Light::ON, Light::OFF, Light::ON}, // g time + {Light::OFF, Light::OFF, Light::ON, Light::OFF, Light::ON}, // g idle + {Light::OFF, Light::ON, Light::OFF, Light::OFF, Light::ON} // yellow + }; + + for (int i = RED_LIGHT; i <= RED_MAN; i++) { + lights[i]->set(LightStates[state][i]); + } +} + +void Pole::setWaitLight(bool pressed) { waitLight->set(pressed ? Light::ON : Light::OFF); } diff --git a/cmat/SolutionEx22/Pole.h b/cmat/SolutionEx22/Pole.h new file mode 100644 index 0000000..a62d29b --- /dev/null +++ b/cmat/SolutionEx22/Pole.h @@ -0,0 +1,24 @@ + +#ifndef POLE_H +#define POLE_H + +#include "Light.h" +#include "Pelican.h" + +class Pole { + public: + Pole(int x, int y); + ~Pole(); + + void setTrafficLights(Pelican::PelicanState state); + void setWaitLight(bool pressed); + + private: + enum LightName { RED_LIGHT, YELLOW_LIGHT, GREEN_LIGHT, GREEN_MAN, RED_MAN }; + + Light *lights[RED_MAN + 1]; + + Light *waitLight; +}; + +#endif diff --git a/cmat/SolutionEx22/Timer.cpp b/cmat/SolutionEx22/Timer.cpp new file mode 100644 index 0000000..9240bda --- /dev/null +++ b/cmat/SolutionEx22/Timer.cpp @@ -0,0 +1,23 @@ + + +#include "Timer.h" +#include "TimerSet.h" + +void Timer::timeoutRequest(int seconds) { timeToGo = seconds; } + +Timer::Timer() : timeToGo(-1) { TimerSet::Instance().addATimer(this); } + +void Timer::tick() { + if (isExpired()) { + doExpired(); + } +} + +bool Timer::isExpired() { + if (timeToGo > 0) { + if (--timeToGo == 0) { + return true; + } + } + return false; +} diff --git a/cmat/SolutionEx22/Timer.h b/cmat/SolutionEx22/Timer.h new file mode 100644 index 0000000..37d1ce9 --- /dev/null +++ b/cmat/SolutionEx22/Timer.h @@ -0,0 +1,32 @@ +// ====================================================== +// +// A general-purpose countdown timer +// To use this class, specialize it +// and override tick() +// +// ====================================================== + +#ifndef timer_H +#define timer_H + +#include + +class Timer { + public: + Timer(); + + void timeoutRequest(int seconds); + + // template method + void tick(); + + protected: + bool isExpired(); + + private: + virtual void doExpired() = 0; + + int timeToGo; +}; + +#endif diff --git a/cmat/SolutionEx22/TimerSet.cpp b/cmat/SolutionEx22/TimerSet.cpp new file mode 100644 index 0000000..2a68d12 --- /dev/null +++ b/cmat/SolutionEx22/TimerSet.cpp @@ -0,0 +1,23 @@ +#include "TimerSet.h" +#include "Timer.h" +#include + +TimerSet::TimerSet() : timersInUse(0), previousTime(time(NULL)) {} + +void TimerSet::addATimer(Timer *t) { timers[timersInUse++] = t; } + +void TimerSet::pollAllTimers() { + std::time_t timeNow; + if (time(&timeNow) > previousTime) { + previousTime = timeNow; + for (int i = 0; i < timersInUse; ++i) { + timers[i]->tick(); + } + } +} + +TimerSet &TimerSet::Instance() { + // Meyer's Singleton implementation + static TimerSet pInstance; + return pInstance; +} diff --git a/cmat/SolutionEx22/TimerSet.h b/cmat/SolutionEx22/TimerSet.h new file mode 100644 index 0000000..3dfe925 --- /dev/null +++ b/cmat/SolutionEx22/TimerSet.h @@ -0,0 +1,29 @@ +#ifndef TIMERSET_H +#define TIMERSET_H + +#include + +class Timer; + +class TimerSet { + public: + void pollAllTimers(); + void addATimer(Timer *); + + private: + TimerSet(); + Timer *timers[40]; + int timersInUse; + std::time_t previousTime; + + // Meyer's singleton + public: + static TimerSet &Instance(); + + private: + // prevent copying and assignment of the singleton + TimerSet(const TimerSet &); + TimerSet &operator=(const TimerSet &); +}; + +#endif diff --git a/cmat/SolutionEx22/main.cpp b/cmat/SolutionEx22/main.cpp new file mode 100644 index 0000000..1cecd5c --- /dev/null +++ b/cmat/SolutionEx22/main.cpp @@ -0,0 +1,29 @@ + + +#include "Keyboard.h" +#include "Pelican.h" +#include "TimerSet.h" + +#include // provides toupper() + +int main() { + Keyboard kbd; + Pelican thePelican(30, 0); + + char c = 0; + + while (std::toupper(c) != 'Q') { // loop until 'Q' is pressed + + while (!kbd.isCharAvail()) { + TimerSet::Instance().pollAllTimers(); // no key press to process, poll the timers + } + + c = kbd.getChar(); // get the character + if (c == ' ') { + // it's a space, so press the WAIT button + thePelican.press(); + } + } + + return 0; +} diff --git a/cmat/SolutionEx22Bonus/CMakeLists.txt b/cmat/SolutionEx22Bonus/CMakeLists.txt new file mode 100644 index 0000000..2903e54 --- /dev/null +++ b/cmat/SolutionEx22Bonus/CMakeLists.txt @@ -0,0 +1,14 @@ +# SolutionEx22Bonus + +cmat_add_exercise(SolutionEx22Bonus + GUI + SOURCES + Light.cpp + LightTimer.cpp + main.cpp + Pelican.cpp + PelicanTimer.cpp + Pole.cpp + Timer.cpp + TimerSet.cpp +) diff --git a/cmat/SolutionEx22Bonus/Ex22.sln b/cmat/SolutionEx22Bonus/Ex22.sln new file mode 100644 index 0000000..e1ea084 --- /dev/null +++ b/cmat/SolutionEx22Bonus/Ex22.sln @@ -0,0 +1,20 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ex22", "Ex22.vcxproj", "{C2EDBD25-9006-0438-220A-8766E6F352A8}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C2EDBD25-9006-0438-220A-8766E6F352A8}.Debug|Win32.ActiveCfg = Debug|Win32 + {C2EDBD25-9006-0438-220A-8766E6F352A8}.Debug|Win32.Build.0 = Debug|Win32 + {C2EDBD25-9006-0438-220A-8766E6F352A8}.Release|Win32.ActiveCfg = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/cmat/SolutionEx22Bonus/Ex22.suo b/cmat/SolutionEx22Bonus/Ex22.suo new file mode 100644 index 0000000..5e8ec65 Binary files /dev/null and b/cmat/SolutionEx22Bonus/Ex22.suo differ diff --git a/cmat/SolutionEx22Bonus/Ex22.vcproj b/cmat/SolutionEx22Bonus/Ex22.vcproj new file mode 100644 index 0000000..b96f6d2 --- /dev/null +++ b/cmat/SolutionEx22Bonus/Ex22.vcproj @@ -0,0 +1,182 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cmat/SolutionEx22Bonus/Ex22.vcxproj b/cmat/SolutionEx22Bonus/Ex22.vcxproj new file mode 100644 index 0000000..31631c2 --- /dev/null +++ b/cmat/SolutionEx22Bonus/Ex22.vcxproj @@ -0,0 +1,143 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + {C2EDBD25-9006-0438-220A-8766E6F352A8} + + + + Application + false + MultiByte + v140 + + + Application + false + MultiByte + v140 + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + .\Debug\ + .\Debug\ + true + .\Release\ + .\Release\ + false + + + + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + true + NotUsing + .\Debug/Ex22.pch + .\Debug/ + .\Debug/ + .\Debug/ + Level3 + true + C:\course\397\DOS_Unix;%(AdditionalIncludeDirectories) + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Debug/Ex22.exe + true + true + .\Debug/Ex22.pdb + Console + + + .\Debug/Ex22.tlb + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + OnlyExplicitInline + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + true + + + .\Release/Ex22.pch + .\Release/ + .\Release/ + .\Release/ + Level3 + true + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Release/Ex22.exe + true + .\Release/Ex22.pdb + Console + + + .\Release/Ex22.tlb + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cmat/SolutionEx22Bonus/Ex22.vcxproj.filters b/cmat/SolutionEx22Bonus/Ex22.vcxproj.filters new file mode 100644 index 0000000..3da8fa1 --- /dev/null +++ b/cmat/SolutionEx22Bonus/Ex22.vcxproj.filters @@ -0,0 +1,77 @@ + + + + + {17deccef-8801-49d5-8ba1-c5db56fa73c0} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {eaf1391b-78b1-4db8-adb1-2585eaedd6e7} + h;hpp;hxx;hm;inl + + + {f8ec245a-126d-413b-8f31-4f57d4342719} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + DOS_Unix + + + DOS_Unix + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + DOS_Unix + + + DOS_Unix + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/cmat/SolutionEx22Bonus/Ex22.vcxproj.user b/cmat/SolutionEx22Bonus/Ex22.vcxproj.user new file mode 100644 index 0000000..695b5c7 --- /dev/null +++ b/cmat/SolutionEx22Bonus/Ex22.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cmat/SolutionEx22Bonus/Light.cpp b/cmat/SolutionEx22Bonus/Light.cpp new file mode 100644 index 0000000..1cdcb0a --- /dev/null +++ b/cmat/SolutionEx22Bonus/Light.cpp @@ -0,0 +1,40 @@ + + +#include "Light.h" +#include "LightTimer.h" +#include "Pelican.h" +#include "Screen.h" +#include + +Light::Light(std::string name, int x, int y, int color) : x(x), y(y), c(color), name(name), flashOn(false) { + myTimer = new LightTimer(*this, &Light::flashLight); +} + +Light::~Light() { + std::cout << "Deleting light (" << name << ", " << x << ", " << y << ", " << c << ")" + << "\n"; +} + +void Light::set(LightState newState) { + state = newState; + + if (state == FLASH) { + flashOn = true; + + flashLight(); + } else + Screen::write(name.c_str(), x, y, state == OFF ? 0 : c); // No need to worry about flashing here +} + +Light::LightState Light::get(void) { return state; } + +void Light::flashLight() { + if (state == FLASH) // If we haven't left the FLASH state + { + Screen::write(name.c_str(), x, y, flashOn ? c : 0); // Display + + flashOn = !flashOn; // Toggle + + myTimer->timeoutRequest(FLASH_PERIOD); // Have another go + } +} diff --git a/cmat/SolutionEx22Bonus/Light.h b/cmat/SolutionEx22Bonus/Light.h new file mode 100644 index 0000000..1ae3352 --- /dev/null +++ b/cmat/SolutionEx22Bonus/Light.h @@ -0,0 +1,40 @@ +// ====================================================== +// +// Represents a light, implemented as a string written +// to a console window +// +// ====================================================== + +#ifndef LIGHT_H +#define LIGHT_H + +#include + +class LightTimer; + +class Light { + public: + Light(std::string name, int x, int y, int color); + ~Light(); + + enum LightState { ON, OFF, FLASH }; + + void set(LightState new_state); + LightState get(void); + + private: + int c; // light colour + int x, y; + std::string name; + LightState state; + + bool flashOn; + + LightTimer *myTimer; + + void flashLight(); + + const int FLASH_PERIOD = 1; +}; + +#endif diff --git a/cmat/SolutionEx22Bonus/LightTimer.cpp b/cmat/SolutionEx22Bonus/LightTimer.cpp new file mode 100644 index 0000000..83048e5 --- /dev/null +++ b/cmat/SolutionEx22Bonus/LightTimer.cpp @@ -0,0 +1,5 @@ +#include "LightTimer.h" + +LightTimer::LightTimer(Light &target, TargetFunc targetFunc) : myTarget(target), myTargetFunc(targetFunc) {} + +void LightTimer::doExpired() { (myTarget.*myTargetFunc)(); } diff --git a/cmat/SolutionEx22Bonus/LightTimer.h b/cmat/SolutionEx22Bonus/LightTimer.h new file mode 100644 index 0000000..f18aa27 --- /dev/null +++ b/cmat/SolutionEx22Bonus/LightTimer.h @@ -0,0 +1,27 @@ +// ====================================================== +// +// This class specializes the Timer to enable it to +// stimulate a Light +// +// ====================================================== + +#ifndef LightTimer_H +#define LightTimer_H + +#include "Light.h" +#include "Timer.h" + +class LightTimer : public Timer { + public: + typedef void (Light::*TargetFunc)(); + + LightTimer(Light &target, TargetFunc targetFunc); + + private: + void doExpired(); + + Light &myTarget; + TargetFunc myTargetFunc; +}; + +#endif diff --git a/cmat/SolutionEx22Bonus/Pelican.cpp b/cmat/SolutionEx22Bonus/Pelican.cpp new file mode 100644 index 0000000..29e1c07 --- /dev/null +++ b/cmat/SolutionEx22Bonus/Pelican.cpp @@ -0,0 +1,66 @@ + + +#include "Pelican.h" +#include "PelicanTimer.h" +#include "Pole.h" + +Pelican::Pelican(int x, int y) + : pressed(false), RED_TIME(4), YELLOW_TIME(2), GREEN_TIME(3), FLASH_TIME(5), myPole(new Pole(x, y)), + state(GREEN_IDLE) { + myTimer = new PelicanTimer(*this, &Pelican::timerExpired); + + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed()); +} + +Pelican::~Pelican() { delete myPole; } + +void Pelican::press(void) { + if (state == GREEN_IDLE) { + state = YELLOW_STATE; + myTimer->timeoutRequest(YELLOW_TIME); + pressed = true; + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed()); + } else if (state != RED_STATE) { + pressed = true; + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed()); + } +} + +void Pelican::timerExpired(void) { + switch (state) { + case RED_STATE: + state = YELLOW_FLASHING; + myTimer->timeoutRequest(FLASH_TIME); + break; + + case YELLOW_FLASHING: + state = GREEN_TIMING; + myTimer->timeoutRequest(GREEN_TIME); + break; + + case GREEN_TIMING: + if (pressed) { + state = YELLOW_STATE; + myTimer->timeoutRequest(YELLOW_TIME); + } else { + state = GREEN_IDLE; + } + break; + + case GREEN_IDLE: + // should never happen + break; + + case YELLOW_STATE: + state = RED_STATE; + pressed = false; + myTimer->timeoutRequest(RED_TIME); + break; + } + + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed()); +} diff --git a/cmat/SolutionEx22Bonus/Pelican.h b/cmat/SolutionEx22Bonus/Pelican.h new file mode 100644 index 0000000..b7c8da0 --- /dev/null +++ b/cmat/SolutionEx22Bonus/Pelican.h @@ -0,0 +1,53 @@ +// ====================================================== +// +// Represents a Pelican crossing +// +// ====================================================== + +#ifndef PELICAN_H +#define PELICAN_H + +class PelicanTimer; +class Pole; + +class Pelican { + public: + Pelican(int x, int y); + ~Pelican(); + + // call when the WAIT button has been pressed + void press(void); + + // states that a Pelican can be in + enum PelicanState { RED_STATE, YELLOW_FLASHING, GREEN_TIMING, GREEN_IDLE, YELLOW_STATE }; + + bool isPressed() const { return pressed; } + PelicanState getState() const { return state; } + + private: + // state that this Pelican is in + PelicanState state; + + // called by PeleicanTimer when the lights need to change + void timerExpired(void); + + const unsigned int RED_TIME; + const unsigned int YELLOW_TIME; + const unsigned int GREEN_TIME; + const unsigned int FLASH_TIME; + + // indicates whether the WAIT light should be on + bool pressed; + + Pole *myPole; + + // Timer that indicates when the lights should change + PelicanTimer *myTimer; + + private: + // prevent general use of copy ctor and operator= + Pelican(const Pelican &); + Pelican &operator=(const Pelican &); +}; + +#endif diff --git a/cmat/SolutionEx22Bonus/PelicanTimer.cpp b/cmat/SolutionEx22Bonus/PelicanTimer.cpp new file mode 100644 index 0000000..f9c107a --- /dev/null +++ b/cmat/SolutionEx22Bonus/PelicanTimer.cpp @@ -0,0 +1,7 @@ + + +#include "PelicanTimer.h" + +PelicanTimer::PelicanTimer(Pelican &target, TargetFunc targetFunc) : myTarget(target), myTargetFunc(targetFunc) {} + +void PelicanTimer::doExpired() { (myTarget.*myTargetFunc)(); } diff --git a/cmat/SolutionEx22Bonus/PelicanTimer.h b/cmat/SolutionEx22Bonus/PelicanTimer.h new file mode 100644 index 0000000..637290c --- /dev/null +++ b/cmat/SolutionEx22Bonus/PelicanTimer.h @@ -0,0 +1,27 @@ +// ====================================================== +// +// This class specializes the Timer to enable it to +// stimulate a Pelican +// +// ====================================================== + +#ifndef PelicanTimer_H +#define PelicanTimer_H + +#include "Pelican.h" +#include "Timer.h" + +class PelicanTimer : public Timer { + public: + typedef void (Pelican::*TargetFunc)(); + + PelicanTimer(Pelican &target, TargetFunc targetFunc); + + private: + void doExpired(); + + Pelican &myTarget; + TargetFunc myTargetFunc; +}; + +#endif diff --git a/cmat/SolutionEx22Bonus/Pole.cpp b/cmat/SolutionEx22Bonus/Pole.cpp new file mode 100644 index 0000000..aeec308 --- /dev/null +++ b/cmat/SolutionEx22Bonus/Pole.cpp @@ -0,0 +1,59 @@ +#include "Pole.h" +#include "Screen.h" + +Pole::Pole(int x, int y) : waitLight(new Light("WAIT", x + 6, y + 12, Screen::WHITE)) { + using namespace Screen; // we will discuss namespaces in the course + + lights[RED_LIGHT] = new Light("*", x + 11, y + 3, RED); + lights[RED_MAN] = new Light("*<-=", x + 6, y + 4, RED); + lights[YELLOW_LIGHT] = new Light("*", x + 11, y + 5, YELLOW); + lights[GREEN_LIGHT] = new Light("*", x + 11, y + 7, GREEN); + lights[GREEN_MAN] = new Light("*|-<", x + 6, y + 7, GREEN); + + write(" _____ ", x, ++y, GRAY); + write(" /___ /| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" | |/| ", x, ++y, GRAY); + write(" |____| | ", x, ++y, GRAY); + write(" | |/| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" |____|/ ", x, ++y, GRAY); + write(" _||__ ", x, ++y, GRAY); + write(" /___ /| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" |____|/ ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write("========||===========", x, ++y, GRAY); + write(" / || / ", x, ++y, GRAY); + write("_ /_________ /_ ", x, ++y, GRAY); + write("/ / ", x, ++y, GRAY); +} + +Pole::~Pole() { + for (int i = 0; i < sizeof lights / sizeof(lights[0]); ++i) + delete lights[i]; + delete waitLight; +} + +void Pole::setTrafficLights(Pelican::PelicanState state) { + static const Light::LightState LightStates[Pelican::YELLOW_STATE + 1][RED_MAN + 1] = { + // red yellow green green man red man + {Light::ON, Light::OFF, Light::OFF, Light::ON, Light::OFF}, // red + {Light::OFF, Light::FLASH, Light::OFF, Light::FLASH, Light::OFF}, // y flash + {Light::OFF, Light::OFF, Light::ON, Light::OFF, Light::ON}, // g time + {Light::OFF, Light::OFF, Light::ON, Light::OFF, Light::ON}, // g idle + {Light::OFF, Light::ON, Light::OFF, Light::OFF, Light::ON} // yellow + }; + + for (int i = RED_LIGHT; i <= RED_MAN; i++) { + lights[i]->set(LightStates[state][i]); + } +} + +void Pole::setWaitLight(bool pressed) { waitLight->set(pressed ? Light::ON : Light::OFF); } diff --git a/cmat/SolutionEx22Bonus/Pole.h b/cmat/SolutionEx22Bonus/Pole.h new file mode 100644 index 0000000..cc271ec --- /dev/null +++ b/cmat/SolutionEx22Bonus/Pole.h @@ -0,0 +1,25 @@ + + +#ifndef POLE_H +#define POLE_H + +#include "Light.h" +#include "Pelican.h" + +class Pole { + public: + Pole(int x, int y); + ~Pole(); + + void setTrafficLights(Pelican::PelicanState state); + void setWaitLight(bool pressed); + + private: + enum LightName { RED_LIGHT, YELLOW_LIGHT, GREEN_LIGHT, GREEN_MAN, RED_MAN }; + + Light *lights[RED_MAN + 1]; + + Light *waitLight; +}; + +#endif diff --git a/cmat/SolutionEx22Bonus/Timer.cpp b/cmat/SolutionEx22Bonus/Timer.cpp new file mode 100644 index 0000000..e62ee48 --- /dev/null +++ b/cmat/SolutionEx22Bonus/Timer.cpp @@ -0,0 +1,22 @@ + +#include "Timer.h" +#include "TimerSet.h" + +void Timer::timeoutRequest(int seconds) { timeToGo = seconds; } + +Timer::Timer() : timeToGo(-1) { TimerSet::Instance().addATimer(this); } + +void Timer::tick() { + if (isExpired()) { + doExpired(); + } +} + +bool Timer::isExpired() { + if (timeToGo > 0) { + if (--timeToGo == 0) { + return true; + } + } + return false; +} diff --git a/cmat/SolutionEx22Bonus/Timer.h b/cmat/SolutionEx22Bonus/Timer.h new file mode 100644 index 0000000..37d1ce9 --- /dev/null +++ b/cmat/SolutionEx22Bonus/Timer.h @@ -0,0 +1,32 @@ +// ====================================================== +// +// A general-purpose countdown timer +// To use this class, specialize it +// and override tick() +// +// ====================================================== + +#ifndef timer_H +#define timer_H + +#include + +class Timer { + public: + Timer(); + + void timeoutRequest(int seconds); + + // template method + void tick(); + + protected: + bool isExpired(); + + private: + virtual void doExpired() = 0; + + int timeToGo; +}; + +#endif diff --git a/cmat/SolutionEx22Bonus/TimerSet.cpp b/cmat/SolutionEx22Bonus/TimerSet.cpp new file mode 100644 index 0000000..2a68d12 --- /dev/null +++ b/cmat/SolutionEx22Bonus/TimerSet.cpp @@ -0,0 +1,23 @@ +#include "TimerSet.h" +#include "Timer.h" +#include + +TimerSet::TimerSet() : timersInUse(0), previousTime(time(NULL)) {} + +void TimerSet::addATimer(Timer *t) { timers[timersInUse++] = t; } + +void TimerSet::pollAllTimers() { + std::time_t timeNow; + if (time(&timeNow) > previousTime) { + previousTime = timeNow; + for (int i = 0; i < timersInUse; ++i) { + timers[i]->tick(); + } + } +} + +TimerSet &TimerSet::Instance() { + // Meyer's Singleton implementation + static TimerSet pInstance; + return pInstance; +} diff --git a/cmat/SolutionEx22Bonus/TimerSet.h b/cmat/SolutionEx22Bonus/TimerSet.h new file mode 100644 index 0000000..3dfe925 --- /dev/null +++ b/cmat/SolutionEx22Bonus/TimerSet.h @@ -0,0 +1,29 @@ +#ifndef TIMERSET_H +#define TIMERSET_H + +#include + +class Timer; + +class TimerSet { + public: + void pollAllTimers(); + void addATimer(Timer *); + + private: + TimerSet(); + Timer *timers[40]; + int timersInUse; + std::time_t previousTime; + + // Meyer's singleton + public: + static TimerSet &Instance(); + + private: + // prevent copying and assignment of the singleton + TimerSet(const TimerSet &); + TimerSet &operator=(const TimerSet &); +}; + +#endif diff --git a/cmat/SolutionEx22Bonus/main.cpp b/cmat/SolutionEx22Bonus/main.cpp new file mode 100644 index 0000000..1cecd5c --- /dev/null +++ b/cmat/SolutionEx22Bonus/main.cpp @@ -0,0 +1,29 @@ + + +#include "Keyboard.h" +#include "Pelican.h" +#include "TimerSet.h" + +#include // provides toupper() + +int main() { + Keyboard kbd; + Pelican thePelican(30, 0); + + char c = 0; + + while (std::toupper(c) != 'Q') { // loop until 'Q' is pressed + + while (!kbd.isCharAvail()) { + TimerSet::Instance().pollAllTimers(); // no key press to process, poll the timers + } + + c = kbd.getChar(); // get the character + if (c == ' ') { + // it's a space, so press the WAIT button + thePelican.press(); + } + } + + return 0; +} diff --git a/cmat/SolutionEx31/CMakeLists.txt b/cmat/SolutionEx31/CMakeLists.txt new file mode 100644 index 0000000..b9d6686 --- /dev/null +++ b/cmat/SolutionEx31/CMakeLists.txt @@ -0,0 +1,6 @@ +# SolutionEx31 + +cmat_add_exercise(SolutionEx31 + SOURCES + Main.cpp +) diff --git a/cmat/SolutionEx31/Ex31.sln b/cmat/SolutionEx31/Ex31.sln new file mode 100644 index 0000000..5a6bac2 --- /dev/null +++ b/cmat/SolutionEx31/Ex31.sln @@ -0,0 +1,20 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ex31", "Ex31.vcxproj", "{8F266BE3-8B4C-8EDD-744B-50A12A4E07CF}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8F266BE3-8B4C-8EDD-744B-50A12A4E07CF}.Debug|Win32.ActiveCfg = Debug|Win32 + {8F266BE3-8B4C-8EDD-744B-50A12A4E07CF}.Debug|Win32.Build.0 = Debug|Win32 + {8F266BE3-8B4C-8EDD-744B-50A12A4E07CF}.Release|Win32.ActiveCfg = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/cmat/SolutionEx31/Ex31.suo b/cmat/SolutionEx31/Ex31.suo new file mode 100644 index 0000000..babac98 Binary files /dev/null and b/cmat/SolutionEx31/Ex31.suo differ diff --git a/cmat/SolutionEx31/Ex31.vcproj b/cmat/SolutionEx31/Ex31.vcproj new file mode 100644 index 0000000..8a79692 --- /dev/null +++ b/cmat/SolutionEx31/Ex31.vcproj @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cmat/SolutionEx31/Ex31.vcxproj b/cmat/SolutionEx31/Ex31.vcxproj new file mode 100644 index 0000000..cb1a015 --- /dev/null +++ b/cmat/SolutionEx31/Ex31.vcxproj @@ -0,0 +1,126 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + {8F266BE3-8B4C-8EDD-744B-50A12A4E07CF} + + + + Application + false + MultiByte + v140 + + + Application + false + MultiByte + v140 + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + .\Release\ + .\Release\ + false + .\Debug\ + .\Debug\ + true + + + + OnlyExplicitInline + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + true + + + .\Release/Ex31.pch + .\Release/ + .\Release/ + .\Release/ + Level3 + true + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Release/Ex31.exe + true + .\Release/Ex31.pdb + Console + + + .\Release/Ex31.tlb + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + true + + + .\Debug/Ex31.pch + .\Debug/ + .\Debug/ + .\Debug/ + Level3 + true + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Debug/Ex31.exe + true + true + .\Debug/Ex31.pdb + Console + + + .\Debug/Ex31.tlb + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + + + + + + + + \ No newline at end of file diff --git a/cmat/SolutionEx31/Ex31.vcxproj.filters b/cmat/SolutionEx31/Ex31.vcxproj.filters new file mode 100644 index 0000000..415767d --- /dev/null +++ b/cmat/SolutionEx31/Ex31.vcxproj.filters @@ -0,0 +1,23 @@ + + + + + {6203fd97-4a05-4e35-bd12-060da3c18bb3} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {567d7160-2695-45e1-ad9b-998cd1d33246} + h;hpp;hxx;hm;inl + + + + + Source Files + + + + + Header Files + + + \ No newline at end of file diff --git a/cmat/SolutionEx31/Ex31.vcxproj.user b/cmat/SolutionEx31/Ex31.vcxproj.user new file mode 100644 index 0000000..695b5c7 --- /dev/null +++ b/cmat/SolutionEx31/Ex31.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cmat/SolutionEx31/Main.cpp b/cmat/SolutionEx31/Main.cpp new file mode 100644 index 0000000..466b5d9 --- /dev/null +++ b/cmat/SolutionEx31/Main.cpp @@ -0,0 +1,69 @@ + +#include "Pixel.h" + +#include +#include +#include +using namespace std; + +void pixelPrint(const Pixel &pixel) { pixel.print(); } + +int main() { + + // From Ex 3.1 + + // preamble + Pixel pixel0; + cout << "Preamble:" << endl; + pixel0.print(); + cout << endl; + + Pixel pixel1(1, 2); + Pixel pixel2(3, 3); + Pixel pixel3(2, 4); + Pixel pixel4(5, 2); + Pixel pixel5(4, 2); + + // 3.1 part 1 + cout << "3.1 Part 1:" << endl; + vector pixelVec; + pixelVec.push_back(pixel1); + pixelVec.push_back(pixel2); + pixelVec.push_back(pixel3); + pixelVec.push_back(pixel4); + pixelVec.push_back(pixel5); + + for (unsigned int i = 0; i < pixelVec.size(); ++i) { + pixelVec[i].print(); + } + cout << endl; + + // 3.1 part 2 + cout << "3.1 Part 2:" << endl; + for (vector::iterator iter = pixelVec.begin(); iter != pixelVec.end(); ++iter) { + iter->print(); + } + cout << endl; + for (vector::reverse_iterator r_iter = pixelVec.rbegin(); r_iter != pixelVec.rend(); ++r_iter) { + r_iter->print(); + } + cout << endl; + + vector pixelVec2{pixel1, pixel2, pixel3, pixel4, pixel5}; + for (const Pixel &p : pixelVec2) { + p.print(); + } + cout << endl; + + // 3.1 part 3 + cout << "3.1 Part 3:" << endl; + for_each(pixelVec.begin(), pixelVec.end(), pixelPrint); + cout << endl; + sort(pixelVec.begin(), pixelVec.end()); + for_each(pixelVec.begin(), pixelVec.end(), pixelPrint); + cout << endl; + + // insert code here *************************************** + + return 0; +} \ No newline at end of file diff --git a/cmat/SolutionEx31/Pixel.h b/cmat/SolutionEx31/Pixel.h new file mode 100644 index 0000000..bfc44c7 --- /dev/null +++ b/cmat/SolutionEx31/Pixel.h @@ -0,0 +1,22 @@ + +#ifndef Pixel_h +#define Pixel_h + +#include + +class Pixel { + public: + Pixel(int x = 0, int y = 0) : x(x), y(y) {} + + void print() const { std::cout << '(' << x << "," << y << ") "; } + + bool operator<(const Pixel &rhs) const { return x < rhs.x; } + + bool operator==(const Pixel &rhs) const { return x == rhs.x; } + + private: + int x; + int y; +}; + +#endif diff --git a/cmat/SolutionEx31Bonus/CMakeLists.txt b/cmat/SolutionEx31Bonus/CMakeLists.txt new file mode 100644 index 0000000..625ba38 --- /dev/null +++ b/cmat/SolutionEx31Bonus/CMakeLists.txt @@ -0,0 +1,13 @@ +# SolutionEx31Bonus + +cmat_add_exercise(SolutionEx31Bonus + GUI + SOURCES + Light.cpp + main.cpp + Pelican.cpp + PelicanTimer.cpp + Pole.cpp + Timer.cpp + TimerSet.cpp +) diff --git a/cmat/SolutionEx31Bonus/Ex31.sln b/cmat/SolutionEx31Bonus/Ex31.sln new file mode 100644 index 0000000..9c0ccd3 --- /dev/null +++ b/cmat/SolutionEx31Bonus/Ex31.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ex31", "Ex31.vcxproj", "{C2EDBD25-9006-0438-220A-8766E6F352A8}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C2EDBD25-9006-0438-220A-8766E6F352A8}.Debug|Win32.ActiveCfg = Debug|Win32 + {C2EDBD25-9006-0438-220A-8766E6F352A8}.Debug|Win32.Build.0 = Debug|Win32 + {C2EDBD25-9006-0438-220A-8766E6F352A8}.Release|Win32.ActiveCfg = Release|Win32 + {C2EDBD25-9006-0438-220A-8766E6F352A8}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/cmat/SolutionEx31Bonus/Ex31.suo b/cmat/SolutionEx31Bonus/Ex31.suo new file mode 100644 index 0000000..5e8ec65 Binary files /dev/null and b/cmat/SolutionEx31Bonus/Ex31.suo differ diff --git a/cmat/SolutionEx31Bonus/Ex31.vcproj b/cmat/SolutionEx31Bonus/Ex31.vcproj new file mode 100644 index 0000000..b96f6d2 --- /dev/null +++ b/cmat/SolutionEx31Bonus/Ex31.vcproj @@ -0,0 +1,182 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cmat/SolutionEx31Bonus/Ex31.vcxproj b/cmat/SolutionEx31Bonus/Ex31.vcxproj new file mode 100644 index 0000000..d00af4b --- /dev/null +++ b/cmat/SolutionEx31Bonus/Ex31.vcxproj @@ -0,0 +1,141 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + {C2EDBD25-9006-0438-220A-8766E6F352A8} + Ex31 + + + + Application + false + MultiByte + v140 + + + Application + false + MultiByte + v140 + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + .\Debug\ + .\Debug\ + true + .\Release\ + .\Release\ + false + + + + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + true + NotUsing + .\Debug/Ex22.pch + .\Debug/ + .\Debug/ + .\Debug/ + Level3 + true + C:\course\397\DOS_Unix;%(AdditionalIncludeDirectories) + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Debug/Ex31.exe + true + true + .\Debug/Ex22.pdb + Console + + + .\Debug/Ex22.tlb + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + OnlyExplicitInline + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + true + + + .\Release/Ex22.pch + .\Release/ + .\Release/ + .\Release/ + Level3 + true + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Release/Ex22.exe + true + .\Release/Ex22.pdb + Console + + + .\Release/Ex22.tlb + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cmat/SolutionEx31Bonus/Ex31.vcxproj.filters b/cmat/SolutionEx31Bonus/Ex31.vcxproj.filters new file mode 100644 index 0000000..a30671e --- /dev/null +++ b/cmat/SolutionEx31Bonus/Ex31.vcxproj.filters @@ -0,0 +1,68 @@ + + + + + {17deccef-8801-49d5-8ba1-c5db56fa73c0} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {eaf1391b-78b1-4db8-adb1-2585eaedd6e7} + h;hpp;hxx;hm;inl + + + {f8ec245a-126d-413b-8f31-4f57d4342719} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + DOS_Unix + + + DOS_Unix + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + DOS_Unix + + + DOS_Unix + + + \ No newline at end of file diff --git a/cmat/SolutionEx31Bonus/Ex31.vcxproj.user b/cmat/SolutionEx31Bonus/Ex31.vcxproj.user new file mode 100644 index 0000000..695b5c7 --- /dev/null +++ b/cmat/SolutionEx31Bonus/Ex31.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cmat/SolutionEx31Bonus/Light.cpp b/cmat/SolutionEx31Bonus/Light.cpp new file mode 100644 index 0000000..e111c52 --- /dev/null +++ b/cmat/SolutionEx31Bonus/Light.cpp @@ -0,0 +1,21 @@ + + +#include "Light.h" +#include "Pelican.h" +#include "Screen.h" +#include + +Light::Light(std::string name, int x, int y, int color) : x(x), y(y), c(color), name(name) {} + +Light::~Light() { + std::cout << "Deleting light (" << name << ", " << x << ", " << y << ", " << c << ")" + << "\n"; +} + +void Light::set(LightState newState) { + state = newState; + Screen::write(name.c_str(), x, y, state == FLASH ? (128 + c) : (state == OFF ? 0 : c)); + // 128 + color was used to make a character flash (but not any more) +} + +Light::LightState Light::get(void) { return state; } diff --git a/cmat/SolutionEx31Bonus/Light.h b/cmat/SolutionEx31Bonus/Light.h new file mode 100644 index 0000000..035c0f0 --- /dev/null +++ b/cmat/SolutionEx31Bonus/Light.h @@ -0,0 +1,31 @@ +// ====================================================== +// Light.h +// +// Represents a light, implemented as a string written +// to a console window +// +// ====================================================== + +#ifndef LIGHT_H +#define LIGHT_H + +#include + +class Light { + public: + Light(std::string name, int x, int y, int color); + ~Light(); + + enum LightState { ON, OFF, FLASH }; + + void set(LightState new_state); + LightState get(void); + + private: + int c; // light colour + int x, y; + std::string name; + LightState state; +}; + +#endif diff --git a/cmat/SolutionEx31Bonus/Pelican.cpp b/cmat/SolutionEx31Bonus/Pelican.cpp new file mode 100644 index 0000000..29e1c07 --- /dev/null +++ b/cmat/SolutionEx31Bonus/Pelican.cpp @@ -0,0 +1,66 @@ + + +#include "Pelican.h" +#include "PelicanTimer.h" +#include "Pole.h" + +Pelican::Pelican(int x, int y) + : pressed(false), RED_TIME(4), YELLOW_TIME(2), GREEN_TIME(3), FLASH_TIME(5), myPole(new Pole(x, y)), + state(GREEN_IDLE) { + myTimer = new PelicanTimer(*this, &Pelican::timerExpired); + + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed()); +} + +Pelican::~Pelican() { delete myPole; } + +void Pelican::press(void) { + if (state == GREEN_IDLE) { + state = YELLOW_STATE; + myTimer->timeoutRequest(YELLOW_TIME); + pressed = true; + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed()); + } else if (state != RED_STATE) { + pressed = true; + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed()); + } +} + +void Pelican::timerExpired(void) { + switch (state) { + case RED_STATE: + state = YELLOW_FLASHING; + myTimer->timeoutRequest(FLASH_TIME); + break; + + case YELLOW_FLASHING: + state = GREEN_TIMING; + myTimer->timeoutRequest(GREEN_TIME); + break; + + case GREEN_TIMING: + if (pressed) { + state = YELLOW_STATE; + myTimer->timeoutRequest(YELLOW_TIME); + } else { + state = GREEN_IDLE; + } + break; + + case GREEN_IDLE: + // should never happen + break; + + case YELLOW_STATE: + state = RED_STATE; + pressed = false; + myTimer->timeoutRequest(RED_TIME); + break; + } + + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed()); +} diff --git a/cmat/SolutionEx31Bonus/Pelican.h b/cmat/SolutionEx31Bonus/Pelican.h new file mode 100644 index 0000000..f26b845 --- /dev/null +++ b/cmat/SolutionEx31Bonus/Pelican.h @@ -0,0 +1,52 @@ +// ===================================================== +// Represents a Pelican crossing +// +// ====================================================== + +#ifndef PELICAN_H +#define PELICAN_H + +class PelicanTimer; +class Pole; + +class Pelican { + public: + Pelican(int x, int y); + ~Pelican(); + + // call when the WAIT button has been pressed + void press(void); + + // states that a Pelican can be in + enum PelicanState { RED_STATE, YELLOW_FLASHING, GREEN_TIMING, GREEN_IDLE, YELLOW_STATE }; + + bool isPressed() const { return pressed; } + PelicanState getState() const { return state; } + + private: + // state that this Pelican is in + PelicanState state; + + // called by PeleicanTimer when the lights need to change + void timerExpired(void); + + const unsigned int RED_TIME; + const unsigned int YELLOW_TIME; + const unsigned int GREEN_TIME; + const unsigned int FLASH_TIME; + + // indicates whether the WAIT light should be on + bool pressed; + + Pole *myPole; + + // Timer that indicates when the lights should change + PelicanTimer *myTimer; + + private: + // prevent general use of copy ctor and operator= + Pelican(const Pelican &); + Pelican &operator=(const Pelican &); +}; + +#endif diff --git a/cmat/SolutionEx31Bonus/PelicanTimer.cpp b/cmat/SolutionEx31Bonus/PelicanTimer.cpp new file mode 100644 index 0000000..f9c107a --- /dev/null +++ b/cmat/SolutionEx31Bonus/PelicanTimer.cpp @@ -0,0 +1,7 @@ + + +#include "PelicanTimer.h" + +PelicanTimer::PelicanTimer(Pelican &target, TargetFunc targetFunc) : myTarget(target), myTargetFunc(targetFunc) {} + +void PelicanTimer::doExpired() { (myTarget.*myTargetFunc)(); } diff --git a/cmat/SolutionEx31Bonus/PelicanTimer.h b/cmat/SolutionEx31Bonus/PelicanTimer.h new file mode 100644 index 0000000..637290c --- /dev/null +++ b/cmat/SolutionEx31Bonus/PelicanTimer.h @@ -0,0 +1,27 @@ +// ====================================================== +// +// This class specializes the Timer to enable it to +// stimulate a Pelican +// +// ====================================================== + +#ifndef PelicanTimer_H +#define PelicanTimer_H + +#include "Pelican.h" +#include "Timer.h" + +class PelicanTimer : public Timer { + public: + typedef void (Pelican::*TargetFunc)(); + + PelicanTimer(Pelican &target, TargetFunc targetFunc); + + private: + void doExpired(); + + Pelican &myTarget; + TargetFunc myTargetFunc; +}; + +#endif diff --git a/cmat/SolutionEx31Bonus/Pole.cpp b/cmat/SolutionEx31Bonus/Pole.cpp new file mode 100644 index 0000000..aeec308 --- /dev/null +++ b/cmat/SolutionEx31Bonus/Pole.cpp @@ -0,0 +1,59 @@ +#include "Pole.h" +#include "Screen.h" + +Pole::Pole(int x, int y) : waitLight(new Light("WAIT", x + 6, y + 12, Screen::WHITE)) { + using namespace Screen; // we will discuss namespaces in the course + + lights[RED_LIGHT] = new Light("*", x + 11, y + 3, RED); + lights[RED_MAN] = new Light("*<-=", x + 6, y + 4, RED); + lights[YELLOW_LIGHT] = new Light("*", x + 11, y + 5, YELLOW); + lights[GREEN_LIGHT] = new Light("*", x + 11, y + 7, GREEN); + lights[GREEN_MAN] = new Light("*|-<", x + 6, y + 7, GREEN); + + write(" _____ ", x, ++y, GRAY); + write(" /___ /| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" | |/| ", x, ++y, GRAY); + write(" |____| | ", x, ++y, GRAY); + write(" | |/| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" |____|/ ", x, ++y, GRAY); + write(" _||__ ", x, ++y, GRAY); + write(" /___ /| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" |____|/ ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write("========||===========", x, ++y, GRAY); + write(" / || / ", x, ++y, GRAY); + write("_ /_________ /_ ", x, ++y, GRAY); + write("/ / ", x, ++y, GRAY); +} + +Pole::~Pole() { + for (int i = 0; i < sizeof lights / sizeof(lights[0]); ++i) + delete lights[i]; + delete waitLight; +} + +void Pole::setTrafficLights(Pelican::PelicanState state) { + static const Light::LightState LightStates[Pelican::YELLOW_STATE + 1][RED_MAN + 1] = { + // red yellow green green man red man + {Light::ON, Light::OFF, Light::OFF, Light::ON, Light::OFF}, // red + {Light::OFF, Light::FLASH, Light::OFF, Light::FLASH, Light::OFF}, // y flash + {Light::OFF, Light::OFF, Light::ON, Light::OFF, Light::ON}, // g time + {Light::OFF, Light::OFF, Light::ON, Light::OFF, Light::ON}, // g idle + {Light::OFF, Light::ON, Light::OFF, Light::OFF, Light::ON} // yellow + }; + + for (int i = RED_LIGHT; i <= RED_MAN; i++) { + lights[i]->set(LightStates[state][i]); + } +} + +void Pole::setWaitLight(bool pressed) { waitLight->set(pressed ? Light::ON : Light::OFF); } diff --git a/cmat/SolutionEx31Bonus/Pole.h b/cmat/SolutionEx31Bonus/Pole.h new file mode 100644 index 0000000..cc271ec --- /dev/null +++ b/cmat/SolutionEx31Bonus/Pole.h @@ -0,0 +1,25 @@ + + +#ifndef POLE_H +#define POLE_H + +#include "Light.h" +#include "Pelican.h" + +class Pole { + public: + Pole(int x, int y); + ~Pole(); + + void setTrafficLights(Pelican::PelicanState state); + void setWaitLight(bool pressed); + + private: + enum LightName { RED_LIGHT, YELLOW_LIGHT, GREEN_LIGHT, GREEN_MAN, RED_MAN }; + + Light *lights[RED_MAN + 1]; + + Light *waitLight; +}; + +#endif diff --git a/cmat/SolutionEx31Bonus/Timer.cpp b/cmat/SolutionEx31Bonus/Timer.cpp new file mode 100644 index 0000000..e62ee48 --- /dev/null +++ b/cmat/SolutionEx31Bonus/Timer.cpp @@ -0,0 +1,22 @@ + +#include "Timer.h" +#include "TimerSet.h" + +void Timer::timeoutRequest(int seconds) { timeToGo = seconds; } + +Timer::Timer() : timeToGo(-1) { TimerSet::Instance().addATimer(this); } + +void Timer::tick() { + if (isExpired()) { + doExpired(); + } +} + +bool Timer::isExpired() { + if (timeToGo > 0) { + if (--timeToGo == 0) { + return true; + } + } + return false; +} diff --git a/cmat/SolutionEx31Bonus/Timer.h b/cmat/SolutionEx31Bonus/Timer.h new file mode 100644 index 0000000..37d1ce9 --- /dev/null +++ b/cmat/SolutionEx31Bonus/Timer.h @@ -0,0 +1,32 @@ +// ====================================================== +// +// A general-purpose countdown timer +// To use this class, specialize it +// and override tick() +// +// ====================================================== + +#ifndef timer_H +#define timer_H + +#include + +class Timer { + public: + Timer(); + + void timeoutRequest(int seconds); + + // template method + void tick(); + + protected: + bool isExpired(); + + private: + virtual void doExpired() = 0; + + int timeToGo; +}; + +#endif diff --git a/cmat/SolutionEx31Bonus/TimerSet.cpp b/cmat/SolutionEx31Bonus/TimerSet.cpp new file mode 100644 index 0000000..58cdc2b --- /dev/null +++ b/cmat/SolutionEx31Bonus/TimerSet.cpp @@ -0,0 +1,33 @@ +#include "TimerSet.h" +#include "Timer.h" +#include + +TimerSet::TimerSet() + : /* timersInUse(), */ previousTime(time(NULL)) +// 3.1 bonus: removed init +{} + +void TimerSet::addATimer(Timer *t) { + // timers[timersInUse++] = t; 3.1 bonus: uses vector + timers.push_back(t); +} + +void TimerSet::pollAllTimers() { + std::time_t timeNow; + if (time(&timeNow) > previousTime) { + previousTime = timeNow; + // for(int i=0; i < timersInUse; ++i) + //{ + // timers[i]->tick(); + //} Bonus 3.1: use iterator for the vector + for (auto it = timers.begin(); it != timers.end(); it++) { + (*it)->tick(); + } + } +} + +TimerSet &TimerSet::Instance() { + // Meyer's Singleton implementation + static TimerSet pInstance; + return pInstance; +} diff --git a/cmat/SolutionEx31Bonus/TimerSet.h b/cmat/SolutionEx31Bonus/TimerSet.h new file mode 100644 index 0000000..359ab6a --- /dev/null +++ b/cmat/SolutionEx31Bonus/TimerSet.h @@ -0,0 +1,30 @@ +#ifndef TIMERSET_H +#define TIMERSET_H + +#include +#include + +class Timer; + +class TimerSet { + public: + void pollAllTimers(); + void addATimer(Timer *); + + private: + TimerSet(); + std::vector timers; // 3.1 bonus: change from array to vector + // int timersInUse; // 3.1 bonus: Not needed + std::time_t previousTime; + + // Meyer's singleton + public: + static TimerSet &Instance(); + + private: + // prevent copying and assignment of the singleton + TimerSet(const TimerSet &); + TimerSet &operator=(const TimerSet &); +}; + +#endif diff --git a/cmat/SolutionEx31Bonus/main.cpp b/cmat/SolutionEx31Bonus/main.cpp new file mode 100644 index 0000000..1cecd5c --- /dev/null +++ b/cmat/SolutionEx31Bonus/main.cpp @@ -0,0 +1,29 @@ + + +#include "Keyboard.h" +#include "Pelican.h" +#include "TimerSet.h" + +#include // provides toupper() + +int main() { + Keyboard kbd; + Pelican thePelican(30, 0); + + char c = 0; + + while (std::toupper(c) != 'Q') { // loop until 'Q' is pressed + + while (!kbd.isCharAvail()) { + TimerSet::Instance().pollAllTimers(); // no key press to process, poll the timers + } + + c = kbd.getChar(); // get the character + if (c == ' ') { + // it's a space, so press the WAIT button + thePelican.press(); + } + } + + return 0; +} diff --git a/cmat/SolutionEx32/CMakeLists.txt b/cmat/SolutionEx32/CMakeLists.txt new file mode 100644 index 0000000..1f95b03 --- /dev/null +++ b/cmat/SolutionEx32/CMakeLists.txt @@ -0,0 +1,6 @@ +# SolutionEx32 + +cmat_add_exercise(SolutionEx32 + SOURCES + main.cpp +) diff --git a/cmat/SolutionEx32/Ex32.sln b/cmat/SolutionEx32/Ex32.sln new file mode 100644 index 0000000..b6d9072 --- /dev/null +++ b/cmat/SolutionEx32/Ex32.sln @@ -0,0 +1,20 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ex32", "Ex32.vcxproj", "{F5DDDD69-0B34-7FD5-AEAF-1BA6CC4705A1}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F5DDDD69-0B34-7FD5-AEAF-1BA6CC4705A1}.Debug|Win32.ActiveCfg = Debug|Win32 + {F5DDDD69-0B34-7FD5-AEAF-1BA6CC4705A1}.Debug|Win32.Build.0 = Debug|Win32 + {F5DDDD69-0B34-7FD5-AEAF-1BA6CC4705A1}.Release|Win32.ActiveCfg = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/cmat/SolutionEx32/Ex32.suo b/cmat/SolutionEx32/Ex32.suo new file mode 100644 index 0000000..30336ac Binary files /dev/null and b/cmat/SolutionEx32/Ex32.suo differ diff --git a/cmat/SolutionEx32/Ex32.vcproj b/cmat/SolutionEx32/Ex32.vcproj new file mode 100644 index 0000000..b746f98 --- /dev/null +++ b/cmat/SolutionEx32/Ex32.vcproj @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cmat/SolutionEx32/Ex32.vcxproj b/cmat/SolutionEx32/Ex32.vcxproj new file mode 100644 index 0000000..636a9c2 --- /dev/null +++ b/cmat/SolutionEx32/Ex32.vcxproj @@ -0,0 +1,127 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + {F5DDDD69-0B34-7FD5-AEAF-1BA6CC4705A1} + + + + Application + false + MultiByte + v140 + + + Application + false + MultiByte + v140 + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + .\Release\ + .\Release\ + false + .\Debug\ + .\Debug\ + true + + + + OnlyExplicitInline + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + true + + + .\Release/Ex32.pch + .\Release/ + .\Release/ + .\Release/ + Level3 + true + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Release/Ex32.exe + true + .\Release/Ex32.pdb + Console + + + .\Release/Ex32.tlb + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + true + + + .\Debug/Ex32.pch + .\Debug/ + .\Debug/ + .\Debug/ + Level3 + true + EditAndContinue + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Debug/Ex32.exe + true + true + .\Debug/Ex32.pdb + Console + + + .\Debug/Ex32.tlb + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + + + + + + + + \ No newline at end of file diff --git a/cmat/SolutionEx32/Ex32.vcxproj.filters b/cmat/SolutionEx32/Ex32.vcxproj.filters new file mode 100644 index 0000000..87c1488 --- /dev/null +++ b/cmat/SolutionEx32/Ex32.vcxproj.filters @@ -0,0 +1,23 @@ + + + + + {d72b3ee0-72e7-4847-905d-3d8abcc3ab6b} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {a9a6650f-a77e-480b-aeb1-1b246b42abd0} + h;hpp;hxx;hm;inl + + + + + Source Files + + + + + Header Files + + + \ No newline at end of file diff --git a/cmat/SolutionEx32/Ex32.vcxproj.user b/cmat/SolutionEx32/Ex32.vcxproj.user new file mode 100644 index 0000000..695b5c7 --- /dev/null +++ b/cmat/SolutionEx32/Ex32.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cmat/SolutionEx32/Pixel.h b/cmat/SolutionEx32/Pixel.h new file mode 100644 index 0000000..4c98ede --- /dev/null +++ b/cmat/SolutionEx32/Pixel.h @@ -0,0 +1,43 @@ + +#ifndef Pixel_h +#define Pixel_h + +#include +#include + +class Pixel { + public: + Pixel(int x = 0, int y = 0) : x(x), y(y) {} + + void print() const { std::cout << '(' << x << "," << y << ") "; } + + bool operator<(const Pixel &rhs) const { return x < rhs.x; } + + bool operator==(const Pixel &rhs) const { return x == rhs.x; } + + private: + int x; + int y; + + friend class PixelPtrCompare; +}; + +class PixelPtrCompare { + public: + PixelPtrCompare() : sortOnY(false) {} + + void setSortOnY(bool sortY) { this->sortOnY = sortY; } + + bool operator()(const Pixel *l, const Pixel *r) const { + if (sortOnY) { + return l->y < r->y; + } else { + return l->x < r->x; + } + } + + private: + bool sortOnY; +}; + +#endif diff --git a/cmat/SolutionEx32/main.cpp b/cmat/SolutionEx32/main.cpp new file mode 100644 index 0000000..745efba --- /dev/null +++ b/cmat/SolutionEx32/main.cpp @@ -0,0 +1,85 @@ + +#include "Pixel.h" + +#include +#include +#include + +void pixelPrint(const Pixel &pixel) { pixel.print(); } + +void pixelPtrPrint(const Pixel *pixel) { pixel->print(); } + +int main() { + using namespace std; + + + Pixel pixel0; + cout << "Preamble:" << endl; + pixel0.print(); + cout << endl; + + Pixel pixel1(1, 2); + Pixel pixel2(3, 3); + Pixel pixel3(2, 4); + Pixel pixel4(5, 2); + Pixel pixel5(4, 2); + + // 3.1 part 1 + cout << "3.1 Part 1:" << endl; + vector pixelVec; + pixelVec.push_back(pixel1); + pixelVec.push_back(pixel2); + pixelVec.push_back(pixel3); + pixelVec.push_back(pixel4); + pixelVec.push_back(pixel5); + + for (unsigned int i = 0; i < pixelVec.size(); ++i) { + pixelVec[i].print(); + } + cout << endl; + + // 3.1 part 2 + cout << "3.1 Part 2:" << endl; + for (vector::iterator iter = pixelVec.begin(); iter != pixelVec.end(); ++iter) { + iter->print(); + } + cout << endl; + for (vector::reverse_iterator r_iter = pixelVec.rbegin(); r_iter != pixelVec.rend(); ++r_iter) { + r_iter->print(); + } + cout << endl; + + // 3.1 part 3 + cout << "3.1 Part 3:" << endl; + for_each(pixelVec.begin(), pixelVec.end(), pixelPrint); + cout << endl; + sort(pixelVec.begin(), pixelVec.end()); + for_each(pixelVec.begin(), pixelVec.end(), pixelPrint); + cout << endl; + + // 3.2 part 1 + cout << "3.2, Part 1:" << endl; + vector pixelPtrVec; + pixelPtrVec.push_back(&pixel1); + pixelPtrVec.push_back(&pixel2); + pixelPtrVec.push_back(&pixel3); + pixelPtrVec.push_back(&pixel4); + pixelPtrVec.push_back(&pixel5); + + for_each(pixelPtrVec.begin(), pixelPtrVec.end(), pixelPtrPrint); + cout << endl; + PixelPtrCompare pixelPtrComp; + sort(pixelPtrVec.begin(), pixelPtrVec.end(), pixelPtrComp); + for_each(pixelPtrVec.begin(), pixelPtrVec.end(), pixelPtrPrint); + cout << endl; + pixelPtrComp.setSortOnY(true); + sort(pixelPtrVec.begin(), pixelPtrVec.end(), pixelPtrComp); + for_each(pixelPtrVec.begin(), pixelPtrVec.end(), pixelPtrPrint); + cout << endl; + + vector pixelPtrVec2{&pixel1, &pixel2, &pixel3, &pixel4, &pixel5}; + sort(pixelPtrVec2.begin(), pixelPtrVec2.end(), [](const Pixel *l, const Pixel *r) { return (*r < *l); }); + for_each(pixelPtrVec2.begin(), pixelPtrVec2.end(), [](const Pixel *p) { p->print(); }); + + return 0; +} \ No newline at end of file diff --git a/cmat/SolutionEx33/CMakeLists.txt b/cmat/SolutionEx33/CMakeLists.txt new file mode 100644 index 0000000..7349476 --- /dev/null +++ b/cmat/SolutionEx33/CMakeLists.txt @@ -0,0 +1,6 @@ +# SolutionEx33 + +cmat_add_exercise(SolutionEx33 + SOURCES + main.cpp +) diff --git a/cmat/SolutionEx33/Ex33.sln b/cmat/SolutionEx33/Ex33.sln new file mode 100644 index 0000000..0d0fd91 --- /dev/null +++ b/cmat/SolutionEx33/Ex33.sln @@ -0,0 +1,20 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ex33", "Ex33.vcxproj", "{E3A48AF6-B757-7B89-D258-F569940E3991}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E3A48AF6-B757-7B89-D258-F569940E3991}.Debug|Win32.ActiveCfg = Debug|Win32 + {E3A48AF6-B757-7B89-D258-F569940E3991}.Debug|Win32.Build.0 = Debug|Win32 + {E3A48AF6-B757-7B89-D258-F569940E3991}.Release|Win32.ActiveCfg = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/cmat/SolutionEx33/Ex33.suo b/cmat/SolutionEx33/Ex33.suo new file mode 100644 index 0000000..1028312 Binary files /dev/null and b/cmat/SolutionEx33/Ex33.suo differ diff --git a/cmat/SolutionEx33/Ex33.vcproj b/cmat/SolutionEx33/Ex33.vcproj new file mode 100644 index 0000000..a547b73 --- /dev/null +++ b/cmat/SolutionEx33/Ex33.vcproj @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cmat/SolutionEx33/Ex33.vcxproj b/cmat/SolutionEx33/Ex33.vcxproj new file mode 100644 index 0000000..27964cf --- /dev/null +++ b/cmat/SolutionEx33/Ex33.vcxproj @@ -0,0 +1,127 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + {E3A48AF6-B757-7B89-D258-F569940E3991} + + + + Application + false + MultiByte + v140 + + + Application + false + MultiByte + v140 + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + .\Release\ + .\Release\ + false + .\Debug\ + .\Debug\ + true + + + + OnlyExplicitInline + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + true + + + .\Release/Ex33.pch + .\Release/ + .\Release/ + .\Release/ + Level3 + true + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Release/Ex33.exe + true + .\Release/Ex33.pdb + Console + + + .\Release/Ex33.tlb + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + true + + + .\Debug/Ex33.pch + .\Debug/ + .\Debug/ + .\Debug/ + Level3 + true + EditAndContinue + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Debug/Ex33.exe + true + true + .\Debug/Ex33.pdb + Console + + + .\Debug/Ex33.tlb + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + + + + + + + + \ No newline at end of file diff --git a/cmat/SolutionEx33/Ex33.vcxproj.filters b/cmat/SolutionEx33/Ex33.vcxproj.filters new file mode 100644 index 0000000..c058673 --- /dev/null +++ b/cmat/SolutionEx33/Ex33.vcxproj.filters @@ -0,0 +1,23 @@ + + + + + {30d4d97f-a28a-416e-8f3b-51af12cbfddf} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {a39d7036-25c2-41d5-9406-9e596bc49b53} + h;hpp;hxx;hm;inl + + + + + Source Files + + + + + Header Files + + + \ No newline at end of file diff --git a/cmat/SolutionEx33/Ex33.vcxproj.user b/cmat/SolutionEx33/Ex33.vcxproj.user new file mode 100644 index 0000000..695b5c7 --- /dev/null +++ b/cmat/SolutionEx33/Ex33.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cmat/SolutionEx33/Pixel.h b/cmat/SolutionEx33/Pixel.h new file mode 100644 index 0000000..fecff92 --- /dev/null +++ b/cmat/SolutionEx33/Pixel.h @@ -0,0 +1,42 @@ + +#ifndef Pixel_h +#define Pixel_h + +#include +#include + +class Pixel { + public: + Pixel(int x = 0, int y = 0) : x(x), y(y) {} + + void print() const { std::cout << '(' << x << "," << y << ") "; } + + bool operator<(const Pixel &rhs) const { return x < rhs.x; } + + bool operator==(const Pixel &rhs) const { return x == rhs.x; } + + private: + int x; + int y; + + friend class PixelPtrCompare; +}; + +class PixelPtrCompare { + public: + PixelPtrCompare() : sortOnY(false) {} + + void setSortOnY(bool sortY) { this->sortOnY = sortY; } + + bool operator()(const Pixel *l, const Pixel *r) const { + if (sortOnY) + return l->y < r->y; + else + return l->x < r->x; + } + + private: + bool sortOnY; +}; + +#endif diff --git a/cmat/SolutionEx33/main.cpp b/cmat/SolutionEx33/main.cpp new file mode 100644 index 0000000..03c024c --- /dev/null +++ b/cmat/SolutionEx33/main.cpp @@ -0,0 +1,146 @@ + +#include "Pixel.h" + +#include +#include +#include +#include +#include + +void pixelPrint(const Pixel &pixel) { pixel.print(); } + +void pixelPtrPrint(const Pixel *pixel) { pixel->print(); } + +int main() { + using namespace std; + + // from Exercise 3.1 + Pixel pixel0; + cout << "Ex 3.1:" << endl; + pixel0.print(); + cout << endl; + Pixel pixel1(1, 2); + Pixel pixel2(3, 3); + Pixel pixel3(2, 4); + Pixel pixel4(5, 2); + Pixel pixel5(4, 2); + vector pixelVec; + pixelVec.push_back(pixel1); + pixelVec.push_back(pixel2); + pixelVec.push_back(pixel3); + pixelVec.push_back(pixel4); + pixelVec.push_back(pixel5); + for (unsigned int i = 0; i < pixelVec.size(); ++i) { + pixelVec[i].print(); + } + cout << endl; + for (vector::iterator iter = pixelVec.begin(); iter != pixelVec.end(); ++iter) { + iter->print(); + } + cout << endl; + for (vector::reverse_iterator r_iter = pixelVec.rbegin(); r_iter != pixelVec.rend(); ++r_iter) { + r_iter->print(); + } + cout << endl; + for_each(pixelVec.begin(), pixelVec.end(), pixelPrint); + cout << endl; + sort(pixelVec.begin(), pixelVec.end()); + for_each(pixelVec.begin(), pixelVec.end(), pixelPrint); + cout << endl; + + // from Exercise 3.2 + cout << "Ex 3.2:" << endl; + + vector pixelPtrVec; + pixelPtrVec.push_back(&pixel1); + pixelPtrVec.push_back(&pixel2); + pixelPtrVec.push_back(&pixel3); + pixelPtrVec.push_back(&pixel4); + pixelPtrVec.push_back(&pixel5); + + for_each(pixelPtrVec.begin(), pixelPtrVec.end(), pixelPtrPrint); + cout << endl; + PixelPtrCompare pixelPtrComp; + sort(pixelPtrVec.begin(), pixelPtrVec.end(), pixelPtrComp); + for_each(pixelPtrVec.begin(), pixelPtrVec.end(), pixelPtrPrint); + cout << endl; + pixelPtrComp.setSortOnY(true); + sort(pixelPtrVec.begin(), pixelPtrVec.end(), pixelPtrComp); + for_each(pixelPtrVec.begin(), pixelPtrVec.end(), pixelPtrPrint); + cout << endl; + + cout << endl; + + // Ex 3.3 + cout << "3.3 Part 1:" << endl; + + set pixelSet; + + pixelSet.insert(Pixel(1, 7)); + pixelSet.insert(Pixel(3, 7)); + pixelSet.insert(Pixel(2, 7)); + cout << "There are " << pixelSet.size() << " elements in pixelSet" << endl; + for_each(pixelSet.begin(), pixelSet.end(), &pixelPrint); + cout << endl; + + pixelSet.insert(Pixel(1, 7)); + cout << "There are " << pixelSet.size() << " elements in pixelSet" << endl; + + multiset pixelMultiset; + pixelMultiset.insert(Pixel(1)); + pixelMultiset.insert(Pixel(3)); + pixelMultiset.insert(Pixel(2)); + cout << "There are " << pixelMultiset.size() << " elements in pixelMultiset" << endl; + for_each(pixelMultiset.begin(), pixelMultiset.end(), &pixelPrint); + cout << endl; + + pixelMultiset.insert(Pixel(1)); + cout << "There are " << pixelMultiset.size() << " elements in pixelMultiset" << endl; + + cout << "3.3 Part 2:" << endl; + typedef map IPixelMap; + IPixelMap pixelMap; + pixelMap.insert(std::make_pair(1, Pixel(1))); + pixelMap.insert(std::make_pair(2, Pixel(2))); + pixelMap.insert(std::make_pair(2, Pixel(3))); + + cout << "There are " << pixelMap.size() << " elements in pixelMap" << endl; + + IPixelMap::iterator found_it = pixelMap.find(1); + if (found_it != pixelMap.end()) { + cout << "found "; + found_it->second.print(); + cout << endl; + } else { + cout << "not found" << endl; + } + + found_it = pixelMap.find(4); + if (found_it != pixelMap.end()) { + cout << "found "; + found_it->second.print(); + cout << endl; + } else { + cout << "not found" << endl; + } + + cout << "pixelMap[1] "; + pixelMap[1].print(); + cout << endl; + cout << "pixelMap[4] "; + pixelMap[4].print(); + cout << endl << endl; + + typedef multimap IPixelMultiMap; + IPixelMultiMap pixelMultimap; + + pixelMultimap.insert(std::make_pair(1, Pixel(1))); + pixelMultimap.insert(std::make_pair(2, Pixel(2))); + pixelMultimap.insert(std::make_pair(2, Pixel(3))); + + cout << "There are " << pixelMultimap.size() << " elements in pixelMultimap" << endl; + + cout << endl; + + return 0; +} \ No newline at end of file diff --git a/cmat/SolutionEx33Bonus/CMakeLists.txt b/cmat/SolutionEx33Bonus/CMakeLists.txt new file mode 100644 index 0000000..4e5315f --- /dev/null +++ b/cmat/SolutionEx33Bonus/CMakeLists.txt @@ -0,0 +1,12 @@ +# SolutionEx33Bonus + +cmat_add_exercise(SolutionEx33Bonus + GUI + SOURCES + Light.cpp + main.cpp + Pelican.cpp + Pole.cpp + Timer.cpp + TimerSet.cpp +) diff --git a/cmat/SolutionEx33Bonus/Ex33.sln b/cmat/SolutionEx33Bonus/Ex33.sln new file mode 100644 index 0000000..842cba9 --- /dev/null +++ b/cmat/SolutionEx33Bonus/Ex33.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.31101.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ex33", "Ex33.vcxproj", "{C2EDBD25-9006-0438-220A-8766E6F352A8}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C2EDBD25-9006-0438-220A-8766E6F352A8}.Debug|Win32.ActiveCfg = Debug|Win32 + {C2EDBD25-9006-0438-220A-8766E6F352A8}.Debug|Win32.Build.0 = Debug|Win32 + {C2EDBD25-9006-0438-220A-8766E6F352A8}.Release|Win32.ActiveCfg = Release|Win32 + {C2EDBD25-9006-0438-220A-8766E6F352A8}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/cmat/SolutionEx33Bonus/Ex33.vcxproj b/cmat/SolutionEx33Bonus/Ex33.vcxproj new file mode 100644 index 0000000..3e9b0dd --- /dev/null +++ b/cmat/SolutionEx33Bonus/Ex33.vcxproj @@ -0,0 +1,141 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + {C2EDBD25-9006-0438-220A-8766E6F352A8} + Ex33 + + + + Application + false + MultiByte + v140 + + + Application + false + MultiByte + v140 + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + .\Debug\ + .\Debug\ + true + .\Release\ + .\Release\ + false + + + + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + true + NotUsing + .\Debug/Ex22.pch + .\Debug/ + .\Debug/ + .\Debug/ + Level3 + true + C:\course\397\DOS_Unix;%(AdditionalIncludeDirectories) + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Debug/Ex33.exe + true + true + .\Debug/Ex22.pdb + Console + + + .\Debug/Ex22.tlb + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + OnlyExplicitInline + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + true + + + .\Release/Ex22.pch + .\Release/ + .\Release/ + .\Release/ + Level3 + true + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Release/Ex33.exe + true + .\Release/Ex22.pdb + Console + + + .\Release/Ex22.tlb + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cmat/SolutionEx33Bonus/Ex33.vcxproj.filters b/cmat/SolutionEx33Bonus/Ex33.vcxproj.filters new file mode 100644 index 0000000..b32e027 --- /dev/null +++ b/cmat/SolutionEx33Bonus/Ex33.vcxproj.filters @@ -0,0 +1,68 @@ + + + + + {17deccef-8801-49d5-8ba1-c5db56fa73c0} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {eaf1391b-78b1-4db8-adb1-2585eaedd6e7} + h;hpp;hxx;hm;inl + + + {f8ec245a-126d-413b-8f31-4f57d4342719} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + DOS_Unix + + + DOS_Unix + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + DOS_Unix + + + DOS_Unix + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/cmat/SolutionEx33Bonus/Ex33.vcxproj.user b/cmat/SolutionEx33Bonus/Ex33.vcxproj.user new file mode 100644 index 0000000..695b5c7 --- /dev/null +++ b/cmat/SolutionEx33Bonus/Ex33.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cmat/SolutionEx33Bonus/Light.cpp b/cmat/SolutionEx33Bonus/Light.cpp new file mode 100644 index 0000000..e111c52 --- /dev/null +++ b/cmat/SolutionEx33Bonus/Light.cpp @@ -0,0 +1,21 @@ + + +#include "Light.h" +#include "Pelican.h" +#include "Screen.h" +#include + +Light::Light(std::string name, int x, int y, int color) : x(x), y(y), c(color), name(name) {} + +Light::~Light() { + std::cout << "Deleting light (" << name << ", " << x << ", " << y << ", " << c << ")" + << "\n"; +} + +void Light::set(LightState newState) { + state = newState; + Screen::write(name.c_str(), x, y, state == FLASH ? (128 + c) : (state == OFF ? 0 : c)); + // 128 + color was used to make a character flash (but not any more) +} + +Light::LightState Light::get(void) { return state; } diff --git a/cmat/SolutionEx33Bonus/Light.h b/cmat/SolutionEx33Bonus/Light.h new file mode 100644 index 0000000..03adf9a --- /dev/null +++ b/cmat/SolutionEx33Bonus/Light.h @@ -0,0 +1,30 @@ +// ====================================================== +// +// Represents a light, implemented as a string written +// to a console window +// +// ====================================================== + +#ifndef LIGHT_H +#define LIGHT_H + +#include + +class Light { + public: + Light(std::string name, int x, int y, int color); + ~Light(); + + enum LightState { ON, OFF, FLASH }; + + void set(LightState new_state); + LightState get(void); + + private: + int c; // light colour + int x, y; + std::string name; + LightState state; +}; + +#endif diff --git a/cmat/SolutionEx33Bonus/Pelican.cpp b/cmat/SolutionEx33Bonus/Pelican.cpp new file mode 100644 index 0000000..8a8c3e1 --- /dev/null +++ b/cmat/SolutionEx33Bonus/Pelican.cpp @@ -0,0 +1,65 @@ + + +#include "Pelican.h" +#include "Pole.h" + +Pelican::Pelican(int x, int y) + : pressed(false), RED_TIME(4), YELLOW_TIME(2), GREEN_TIME(3), FLASH_TIME(5), myPole(new Pole(x, y)), + state(GREEN_IDLE) { + myTimer = new TimerT(*this, &Pelican::timerExpired); + + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed()); +} + +Pelican::~Pelican() { delete myPole; } + +void Pelican::press(void) { + if (state == GREEN_IDLE) { + state = YELLOW_STATE; + myTimer->timeoutRequest(YELLOW_TIME); + pressed = true; + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed()); + } else if (state != RED_STATE) { + pressed = true; + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed()); + } +} + +void Pelican::timerExpired(void) { + switch (state) { + case RED_STATE: + state = YELLOW_FLASHING; + myTimer->timeoutRequest(FLASH_TIME); + break; + + case YELLOW_FLASHING: + state = GREEN_TIMING; + myTimer->timeoutRequest(GREEN_TIME); + break; + + case GREEN_TIMING: + if (pressed) { + state = YELLOW_STATE; + myTimer->timeoutRequest(YELLOW_TIME); + } else { + state = GREEN_IDLE; + } + break; + + case GREEN_IDLE: + // should never happen + break; + + case YELLOW_STATE: + state = RED_STATE; + pressed = false; + myTimer->timeoutRequest(RED_TIME); + break; + } + + myPole->setTrafficLights(getState()); + myPole->setWaitLight(isPressed()); +} diff --git a/cmat/SolutionEx33Bonus/Pelican.h b/cmat/SolutionEx33Bonus/Pelican.h new file mode 100644 index 0000000..e7c3256 --- /dev/null +++ b/cmat/SolutionEx33Bonus/Pelican.h @@ -0,0 +1,54 @@ +// ====================================================== +// +// Represents a Pelican crossing +// +// ====================================================== + +#ifndef PELICAN_H +#define PELICAN_H + +#include "TimerT.h" + +class Pole; + +class Pelican { + public: + Pelican(int x, int y); + ~Pelican(); + + // call when the WAIT button has been pressed + void press(void); + + // states that a Pelican can be in + enum PelicanState { RED_STATE, YELLOW_FLASHING, GREEN_TIMING, GREEN_IDLE, YELLOW_STATE }; + + bool isPressed() const { return pressed; } + PelicanState getState() const { return state; } + + private: + // state that this Pelican is in + PelicanState state; + + // called by PeleicanTimer when the lights need to change + void timerExpired(void); + + const unsigned int RED_TIME; + const unsigned int YELLOW_TIME; + const unsigned int GREEN_TIME; + const unsigned int FLASH_TIME; + + // indicates whether the WAIT light should be on + bool pressed; + + Pole *myPole; + + // Timer that indicates when the lights should change + TimerT *myTimer; + + private: + // prevent general use of copy ctor and operator= + Pelican(const Pelican &); + Pelican &operator=(const Pelican &); +}; + +#endif diff --git a/cmat/SolutionEx33Bonus/Pole.cpp b/cmat/SolutionEx33Bonus/Pole.cpp new file mode 100644 index 0000000..aeec308 --- /dev/null +++ b/cmat/SolutionEx33Bonus/Pole.cpp @@ -0,0 +1,59 @@ +#include "Pole.h" +#include "Screen.h" + +Pole::Pole(int x, int y) : waitLight(new Light("WAIT", x + 6, y + 12, Screen::WHITE)) { + using namespace Screen; // we will discuss namespaces in the course + + lights[RED_LIGHT] = new Light("*", x + 11, y + 3, RED); + lights[RED_MAN] = new Light("*<-=", x + 6, y + 4, RED); + lights[YELLOW_LIGHT] = new Light("*", x + 11, y + 5, YELLOW); + lights[GREEN_LIGHT] = new Light("*", x + 11, y + 7, GREEN); + lights[GREEN_MAN] = new Light("*|-<", x + 6, y + 7, GREEN); + + write(" _____ ", x, ++y, GRAY); + write(" /___ /| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" | |/| ", x, ++y, GRAY); + write(" |____| | ", x, ++y, GRAY); + write(" | |/| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" |____|/ ", x, ++y, GRAY); + write(" _||__ ", x, ++y, GRAY); + write(" /___ /| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" |____|/ ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write("========||===========", x, ++y, GRAY); + write(" / || / ", x, ++y, GRAY); + write("_ /_________ /_ ", x, ++y, GRAY); + write("/ / ", x, ++y, GRAY); +} + +Pole::~Pole() { + for (int i = 0; i < sizeof lights / sizeof(lights[0]); ++i) + delete lights[i]; + delete waitLight; +} + +void Pole::setTrafficLights(Pelican::PelicanState state) { + static const Light::LightState LightStates[Pelican::YELLOW_STATE + 1][RED_MAN + 1] = { + // red yellow green green man red man + {Light::ON, Light::OFF, Light::OFF, Light::ON, Light::OFF}, // red + {Light::OFF, Light::FLASH, Light::OFF, Light::FLASH, Light::OFF}, // y flash + {Light::OFF, Light::OFF, Light::ON, Light::OFF, Light::ON}, // g time + {Light::OFF, Light::OFF, Light::ON, Light::OFF, Light::ON}, // g idle + {Light::OFF, Light::ON, Light::OFF, Light::OFF, Light::ON} // yellow + }; + + for (int i = RED_LIGHT; i <= RED_MAN; i++) { + lights[i]->set(LightStates[state][i]); + } +} + +void Pole::setWaitLight(bool pressed) { waitLight->set(pressed ? Light::ON : Light::OFF); } diff --git a/cmat/SolutionEx33Bonus/Pole.h b/cmat/SolutionEx33Bonus/Pole.h new file mode 100644 index 0000000..a62d29b --- /dev/null +++ b/cmat/SolutionEx33Bonus/Pole.h @@ -0,0 +1,24 @@ + +#ifndef POLE_H +#define POLE_H + +#include "Light.h" +#include "Pelican.h" + +class Pole { + public: + Pole(int x, int y); + ~Pole(); + + void setTrafficLights(Pelican::PelicanState state); + void setWaitLight(bool pressed); + + private: + enum LightName { RED_LIGHT, YELLOW_LIGHT, GREEN_LIGHT, GREEN_MAN, RED_MAN }; + + Light *lights[RED_MAN + 1]; + + Light *waitLight; +}; + +#endif diff --git a/cmat/SolutionEx33Bonus/Timer.cpp b/cmat/SolutionEx33Bonus/Timer.cpp new file mode 100644 index 0000000..9240bda --- /dev/null +++ b/cmat/SolutionEx33Bonus/Timer.cpp @@ -0,0 +1,23 @@ + + +#include "Timer.h" +#include "TimerSet.h" + +void Timer::timeoutRequest(int seconds) { timeToGo = seconds; } + +Timer::Timer() : timeToGo(-1) { TimerSet::Instance().addATimer(this); } + +void Timer::tick() { + if (isExpired()) { + doExpired(); + } +} + +bool Timer::isExpired() { + if (timeToGo > 0) { + if (--timeToGo == 0) { + return true; + } + } + return false; +} diff --git a/cmat/SolutionEx33Bonus/Timer.h b/cmat/SolutionEx33Bonus/Timer.h new file mode 100644 index 0000000..37d1ce9 --- /dev/null +++ b/cmat/SolutionEx33Bonus/Timer.h @@ -0,0 +1,32 @@ +// ====================================================== +// +// A general-purpose countdown timer +// To use this class, specialize it +// and override tick() +// +// ====================================================== + +#ifndef timer_H +#define timer_H + +#include + +class Timer { + public: + Timer(); + + void timeoutRequest(int seconds); + + // template method + void tick(); + + protected: + bool isExpired(); + + private: + virtual void doExpired() = 0; + + int timeToGo; +}; + +#endif diff --git a/cmat/SolutionEx33Bonus/TimerSet.cpp b/cmat/SolutionEx33Bonus/TimerSet.cpp new file mode 100644 index 0000000..9138370 --- /dev/null +++ b/cmat/SolutionEx33Bonus/TimerSet.cpp @@ -0,0 +1,24 @@ +#include "TimerSet.h" +#include "Timer.h" +#include + +TimerSet::TimerSet() : previousTime(time(nullptr)) {} + +void TimerSet::addATimer(Timer *t) { timers.push_back(t); } + +void TimerSet::pollAllTimers() { + std::time_t timeNow; + if (time(&timeNow) > previousTime) { + previousTime = timeNow; + + for (auto it = timers.begin(); it != timers.end(); it++) { + (*it)->tick(); + } + } +} + +TimerSet &TimerSet::Instance() { + // Meyer's Singleton implementation + static TimerSet pInstance; + return pInstance; +} diff --git a/cmat/SolutionEx33Bonus/TimerSet.h b/cmat/SolutionEx33Bonus/TimerSet.h new file mode 100644 index 0000000..35c2baf --- /dev/null +++ b/cmat/SolutionEx33Bonus/TimerSet.h @@ -0,0 +1,29 @@ +#ifndef TIMERSET_H +#define TIMERSET_H + +#include +#include + +class Timer; + +class TimerSet { + public: + void pollAllTimers(); + void addATimer(Timer *); + + private: + TimerSet(); + std::vector timers; + std::time_t previousTime; + + // Meyer's singleton + public: + static TimerSet &Instance(); + + private: + // prevent copying and assignment of the singleton + TimerSet(const TimerSet &); + TimerSet &operator=(const TimerSet &); +}; + +#endif diff --git a/cmat/SolutionEx33Bonus/TimerT.h b/cmat/SolutionEx33Bonus/TimerT.h new file mode 100644 index 0000000..f7902b3 --- /dev/null +++ b/cmat/SolutionEx33Bonus/TimerT.h @@ -0,0 +1,23 @@ +// ====================================================== +// +// Template for derievd Timers +// +// ====================================================== + +#ifndef TIMERT_H +#define TIMERT_H + +#include "Timer.h" + +template class TimerT : public Timer { + public: + typedef void (Target::*TargetFunc)(); + TimerT(Target &target, TargetFunc targetFunc) : myTarget(target), myTargetFunc(targetFunc) {} + + private: + void doExpired() { (myTarget.*myTargetFunc)(); } + Target &myTarget; + TargetFunc myTargetFunc; +}; + +#endif \ No newline at end of file diff --git a/cmat/SolutionEx33Bonus/main.cpp b/cmat/SolutionEx33Bonus/main.cpp new file mode 100644 index 0000000..1cecd5c --- /dev/null +++ b/cmat/SolutionEx33Bonus/main.cpp @@ -0,0 +1,29 @@ + + +#include "Keyboard.h" +#include "Pelican.h" +#include "TimerSet.h" + +#include // provides toupper() + +int main() { + Keyboard kbd; + Pelican thePelican(30, 0); + + char c = 0; + + while (std::toupper(c) != 'Q') { // loop until 'Q' is pressed + + while (!kbd.isCharAvail()) { + TimerSet::Instance().pollAllTimers(); // no key press to process, poll the timers + } + + c = kbd.getChar(); // get the character + if (c == ' ') { + // it's a space, so press the WAIT button + thePelican.press(); + } + } + + return 0; +} diff --git a/cmat/SolutionEx41/CMakeLists.txt b/cmat/SolutionEx41/CMakeLists.txt new file mode 100644 index 0000000..a04e0d0 --- /dev/null +++ b/cmat/SolutionEx41/CMakeLists.txt @@ -0,0 +1,14 @@ +# SolutionEx41 + +cmat_add_exercise(SolutionEx41 + GUI + SOURCES + Light.cpp + main.cpp + Pelican.cpp + PelicanTimer.cpp + Pole.cpp + Subject.cpp + Timer.cpp + TimerSet.cpp +) diff --git a/cmat/SolutionEx41/Ex41.sln b/cmat/SolutionEx41/Ex41.sln new file mode 100644 index 0000000..419d6cc --- /dev/null +++ b/cmat/SolutionEx41/Ex41.sln @@ -0,0 +1,20 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ex41", "Ex41.vcxproj", "{2B6BAD2C-A2F1-99CD-6A27-DD0BBF12E5A4}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2B6BAD2C-A2F1-99CD-6A27-DD0BBF12E5A4}.Debug|Win32.ActiveCfg = Debug|Win32 + {2B6BAD2C-A2F1-99CD-6A27-DD0BBF12E5A4}.Debug|Win32.Build.0 = Debug|Win32 + {2B6BAD2C-A2F1-99CD-6A27-DD0BBF12E5A4}.Release|Win32.ActiveCfg = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/cmat/SolutionEx41/Ex41.suo b/cmat/SolutionEx41/Ex41.suo new file mode 100644 index 0000000..eda747b Binary files /dev/null and b/cmat/SolutionEx41/Ex41.suo differ diff --git a/cmat/SolutionEx41/Ex41.vcproj b/cmat/SolutionEx41/Ex41.vcproj new file mode 100644 index 0000000..f10d6ef --- /dev/null +++ b/cmat/SolutionEx41/Ex41.vcproj @@ -0,0 +1,194 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cmat/SolutionEx41/Ex41.vcxproj b/cmat/SolutionEx41/Ex41.vcxproj new file mode 100644 index 0000000..13b07d4 --- /dev/null +++ b/cmat/SolutionEx41/Ex41.vcxproj @@ -0,0 +1,144 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + {2B6BAD2C-A2F1-99CD-6A27-DD0BBF12E5A4} + + + + Application + false + MultiByte + v140 + + + Application + false + MultiByte + v140 + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + .\Debug\ + .\Debug\ + true + .\Release\ + .\Release\ + false + + + + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + true + NotUsing + .\Debug/Ex41.pch + .\Debug/ + .\Debug/ + .\Debug/ + Level3 + true + C:\course\397\DOS_Unix;%(AdditionalIncludeDirectories) + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Debug/Ex41.exe + true + true + .\Debug/Ex41.pdb + Console + + + .\Debug/Ex41.tlb + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + OnlyExplicitInline + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + true + + + .\Release/Ex41.pch + .\Release/ + .\Release/ + .\Release/ + Level3 + true + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Release/Ex41.exe + true + .\Release/Ex41.pdb + Console + + + .\Release/Ex41.tlb + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cmat/SolutionEx41/Ex41.vcxproj.filters b/cmat/SolutionEx41/Ex41.vcxproj.filters new file mode 100644 index 0000000..0e9eddc --- /dev/null +++ b/cmat/SolutionEx41/Ex41.vcxproj.filters @@ -0,0 +1,80 @@ + + + + + {d342b4ff-da53-4cfa-9c78-ecc4af2f56cd} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {1e58a93c-2ba4-46f3-bde3-fdef6055c3a4} + h;hpp;hxx;hm;inl + + + {7d8dd5fa-5328-4693-8b68-b95e098fcdd6} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + DOS_Unix + + + DOS_Unix + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + DOS_Unix + + + DOS_Unix + + + \ No newline at end of file diff --git a/cmat/SolutionEx41/Ex41.vcxproj.user b/cmat/SolutionEx41/Ex41.vcxproj.user new file mode 100644 index 0000000..695b5c7 --- /dev/null +++ b/cmat/SolutionEx41/Ex41.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cmat/SolutionEx41/Light.cpp b/cmat/SolutionEx41/Light.cpp new file mode 100644 index 0000000..e111c52 --- /dev/null +++ b/cmat/SolutionEx41/Light.cpp @@ -0,0 +1,21 @@ + + +#include "Light.h" +#include "Pelican.h" +#include "Screen.h" +#include + +Light::Light(std::string name, int x, int y, int color) : x(x), y(y), c(color), name(name) {} + +Light::~Light() { + std::cout << "Deleting light (" << name << ", " << x << ", " << y << ", " << c << ")" + << "\n"; +} + +void Light::set(LightState newState) { + state = newState; + Screen::write(name.c_str(), x, y, state == FLASH ? (128 + c) : (state == OFF ? 0 : c)); + // 128 + color was used to make a character flash (but not any more) +} + +Light::LightState Light::get(void) { return state; } diff --git a/cmat/SolutionEx41/Light.h b/cmat/SolutionEx41/Light.h new file mode 100644 index 0000000..03adf9a --- /dev/null +++ b/cmat/SolutionEx41/Light.h @@ -0,0 +1,30 @@ +// ====================================================== +// +// Represents a light, implemented as a string written +// to a console window +// +// ====================================================== + +#ifndef LIGHT_H +#define LIGHT_H + +#include + +class Light { + public: + Light(std::string name, int x, int y, int color); + ~Light(); + + enum LightState { ON, OFF, FLASH }; + + void set(LightState new_state); + LightState get(void); + + private: + int c; // light colour + int x, y; + std::string name; + LightState state; +}; + +#endif diff --git a/cmat/SolutionEx41/Observer.h b/cmat/SolutionEx41/Observer.h new file mode 100644 index 0000000..368bd0f --- /dev/null +++ b/cmat/SolutionEx41/Observer.h @@ -0,0 +1,11 @@ + + +#ifndef OBSERVER_H +#define OBSERVER_H + +class Observer { + public: + virtual void update() = 0; +}; + +#endif diff --git a/cmat/SolutionEx41/Pelican.cpp b/cmat/SolutionEx41/Pelican.cpp new file mode 100644 index 0000000..8cde63a --- /dev/null +++ b/cmat/SolutionEx41/Pelican.cpp @@ -0,0 +1,55 @@ + + +#include "Pelican.h" +#include "PelicanTimer.h" + +Pelican::Pelican() : pressed(false), RED_TIME(4), YELLOW_TIME(2), GREEN_TIME(3), FLASH_TIME(5), state(GREEN_IDLE) { + myTimer = new PelicanTimer(*this, &Pelican::timerExpired); +} + +void Pelican::press(void) { + if (state == GREEN_IDLE) { + state = YELLOW_STATE; + myTimer->timeoutRequest(YELLOW_TIME); + pressed = true; + notify(); + } else if (state != RED_STATE) { + pressed = true; + notify(); + } +} + +void Pelican::timerExpired(void) { + switch (state) { + case RED_STATE: + state = YELLOW_FLASHING; + myTimer->timeoutRequest(FLASH_TIME); + break; + + case YELLOW_FLASHING: + state = GREEN_TIMING; + myTimer->timeoutRequest(GREEN_TIME); + break; + + case GREEN_TIMING: + if (pressed) { + state = YELLOW_STATE; + myTimer->timeoutRequest(YELLOW_TIME); + } else { + state = GREEN_IDLE; + } + break; + + case GREEN_IDLE: + // should never happen + break; + + case YELLOW_STATE: + state = RED_STATE; + pressed = false; + myTimer->timeoutRequest(RED_TIME); + break; + } + + notify(); +} diff --git a/cmat/SolutionEx41/Pelican.h b/cmat/SolutionEx41/Pelican.h new file mode 100644 index 0000000..e8825a2 --- /dev/null +++ b/cmat/SolutionEx41/Pelican.h @@ -0,0 +1,51 @@ +// ====================================================== +// +// Represents a Pelican crossing +// +// ====================================================== + +#ifndef PELICAN_H +#define PELICAN_H + +#include "Subject.h" + +class PelicanTimer; + +class Pelican : public Subject { + public: + Pelican(); + + // call when the WAIT button has been pressed + void press(void); + + // states that a Pelican can be in + enum PelicanState { RED_STATE, YELLOW_FLASHING, GREEN_TIMING, GREEN_IDLE, YELLOW_STATE }; + + bool isPressed() const { return pressed; } + PelicanState getState() const { return state; } + + private: + // state that this Pelican is in + PelicanState state; + + // called by PeleicanTimer when the lights need to change + void timerExpired(void); + + const unsigned int RED_TIME; + const unsigned int YELLOW_TIME; + const unsigned int GREEN_TIME; + const unsigned int FLASH_TIME; + + // indicates whether the WAIT light should be on + bool pressed; + + // Timer that indicates when the lights should change + PelicanTimer *myTimer; + + private: + // prevent general use of copy ctor and operator= + Pelican(const Pelican &); + Pelican &operator=(const Pelican &); +}; + +#endif diff --git a/cmat/SolutionEx41/PelicanTimer.cpp b/cmat/SolutionEx41/PelicanTimer.cpp new file mode 100644 index 0000000..f9c107a --- /dev/null +++ b/cmat/SolutionEx41/PelicanTimer.cpp @@ -0,0 +1,7 @@ + + +#include "PelicanTimer.h" + +PelicanTimer::PelicanTimer(Pelican &target, TargetFunc targetFunc) : myTarget(target), myTargetFunc(targetFunc) {} + +void PelicanTimer::doExpired() { (myTarget.*myTargetFunc)(); } diff --git a/cmat/SolutionEx41/PelicanTimer.h b/cmat/SolutionEx41/PelicanTimer.h new file mode 100644 index 0000000..637290c --- /dev/null +++ b/cmat/SolutionEx41/PelicanTimer.h @@ -0,0 +1,27 @@ +// ====================================================== +// +// This class specializes the Timer to enable it to +// stimulate a Pelican +// +// ====================================================== + +#ifndef PelicanTimer_H +#define PelicanTimer_H + +#include "Pelican.h" +#include "Timer.h" + +class PelicanTimer : public Timer { + public: + typedef void (Pelican::*TargetFunc)(); + + PelicanTimer(Pelican &target, TargetFunc targetFunc); + + private: + void doExpired(); + + Pelican &myTarget; + TargetFunc myTargetFunc; +}; + +#endif diff --git a/cmat/SolutionEx41/Pole.cpp b/cmat/SolutionEx41/Pole.cpp new file mode 100644 index 0000000..b14eb14 --- /dev/null +++ b/cmat/SolutionEx41/Pole.cpp @@ -0,0 +1,69 @@ +#include "Pole.h" +#include "Screen.h" + +Pole::Pole(int x, int y, Pelican &p) : waitLight(new Light("WAIT", x + 6, y + 12, Screen::WHITE)), myPelican(p) { + myPelican.attach(*this); + + using namespace Screen; // we will discuss namespaces in the course + + lights[RED_LIGHT] = new Light("*", x + 11, y + 3, RED); + lights[RED_MAN] = new Light("*<-=", x + 6, y + 4, RED); + lights[YELLOW_LIGHT] = new Light("*", x + 11, y + 5, YELLOW); + lights[GREEN_LIGHT] = new Light("*", x + 11, y + 7, GREEN); + lights[GREEN_MAN] = new Light("*|-<", x + 6, y + 7, GREEN); + + write(" _____ ", x, ++y, GRAY); + write(" /___ /| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" | |/| ", x, ++y, GRAY); + write(" |____| | ", x, ++y, GRAY); + write(" | |/| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" |____|/ ", x, ++y, GRAY); + write(" _||__ ", x, ++y, GRAY); + write(" /___ /| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" |____|/ ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write("========||===========", x, ++y, GRAY); + write(" / || / ", x, ++y, GRAY); + write("_ /_________ /_ ", x, ++y, GRAY); + write("/ / ", x, ++y, GRAY); + + // Force initial display + update(); +} + +Pole::~Pole() { + for (int i = 0; i < sizeof lights / sizeof(lights[0]); ++i) + delete lights[i]; + delete waitLight; +} + +void Pole::setTrafficLights(Pelican::PelicanState state) { + static const Light::LightState LightStates[Pelican::YELLOW_STATE + 1][RED_MAN + 1] = { + // red yellow green green man red man + {Light::ON, Light::OFF, Light::OFF, Light::ON, Light::OFF}, // red + {Light::OFF, Light::FLASH, Light::OFF, Light::FLASH, Light::OFF}, // y flash + {Light::OFF, Light::OFF, Light::ON, Light::OFF, Light::ON}, // g time + {Light::OFF, Light::OFF, Light::ON, Light::OFF, Light::ON}, // g idle + {Light::OFF, Light::ON, Light::OFF, Light::OFF, Light::ON} // yellow + }; + + for (int i = RED_LIGHT; i <= RED_MAN; i++) { + lights[i]->set(LightStates[state][i]); + } +} + +void Pole::setWaitLight(bool pressed) { waitLight->set(pressed ? Light::ON : Light::OFF); } + +void Pole::update() { + setTrafficLights(myPelican.getState()); + setWaitLight(myPelican.isPressed()); +} diff --git a/cmat/SolutionEx41/Pole.h b/cmat/SolutionEx41/Pole.h new file mode 100644 index 0000000..674fbfe --- /dev/null +++ b/cmat/SolutionEx41/Pole.h @@ -0,0 +1,28 @@ + +#ifndef POLE_H +#define POLE_H + +#include "Light.h" +#include "Observer.h" +#include "Pelican.h" + +class Pole : public Observer { + public: + Pole(int x, int y, Pelican &p); + ~Pole(); + + void setTrafficLights(Pelican::PelicanState state); + void setWaitLight(bool pressed); + + void update(); + + private: + Pelican &myPelican; + + enum LightName { RED_LIGHT, YELLOW_LIGHT, GREEN_LIGHT, GREEN_MAN, RED_MAN }; + + Light *lights[RED_MAN + 1]; + Light *waitLight; +}; + +#endif diff --git a/cmat/SolutionEx41/Subject.cpp b/cmat/SolutionEx41/Subject.cpp new file mode 100644 index 0000000..c31e2b6 --- /dev/null +++ b/cmat/SolutionEx41/Subject.cpp @@ -0,0 +1,12 @@ + + +#include "Subject.h" +#include "Observer.h" + +void Subject::attach(Observer &obs) { myObservers.insert(&obs); } + +void Subject::notify() const { + for (ObsList::const_iterator iter = myObservers.begin(); iter != myObservers.end(); ++iter) { + (*iter)->update(); + } +} diff --git a/cmat/SolutionEx41/Subject.h b/cmat/SolutionEx41/Subject.h new file mode 100644 index 0000000..321c5e0 --- /dev/null +++ b/cmat/SolutionEx41/Subject.h @@ -0,0 +1,21 @@ + +#ifndef SUBJECT_H +#define SUBJECT_H + +class Observer; + +#include + +class Subject { + public: + typedef std::set ObsList; + void attach(Observer &obs); + + protected: + void notify() const; + + private: + ObsList myObservers; +}; + +#endif diff --git a/cmat/SolutionEx41/Timer.cpp b/cmat/SolutionEx41/Timer.cpp new file mode 100644 index 0000000..e62ee48 --- /dev/null +++ b/cmat/SolutionEx41/Timer.cpp @@ -0,0 +1,22 @@ + +#include "Timer.h" +#include "TimerSet.h" + +void Timer::timeoutRequest(int seconds) { timeToGo = seconds; } + +Timer::Timer() : timeToGo(-1) { TimerSet::Instance().addATimer(this); } + +void Timer::tick() { + if (isExpired()) { + doExpired(); + } +} + +bool Timer::isExpired() { + if (timeToGo > 0) { + if (--timeToGo == 0) { + return true; + } + } + return false; +} diff --git a/cmat/SolutionEx41/Timer.h b/cmat/SolutionEx41/Timer.h new file mode 100644 index 0000000..37d1ce9 --- /dev/null +++ b/cmat/SolutionEx41/Timer.h @@ -0,0 +1,32 @@ +// ====================================================== +// +// A general-purpose countdown timer +// To use this class, specialize it +// and override tick() +// +// ====================================================== + +#ifndef timer_H +#define timer_H + +#include + +class Timer { + public: + Timer(); + + void timeoutRequest(int seconds); + + // template method + void tick(); + + protected: + bool isExpired(); + + private: + virtual void doExpired() = 0; + + int timeToGo; +}; + +#endif diff --git a/cmat/SolutionEx41/TimerSet.cpp b/cmat/SolutionEx41/TimerSet.cpp new file mode 100644 index 0000000..5606f75 --- /dev/null +++ b/cmat/SolutionEx41/TimerSet.cpp @@ -0,0 +1,24 @@ +#include "TimerSet.h" +#include "Timer.h" +#include + +TimerSet::TimerSet() : previousTime(time(NULL)) {} + +void TimerSet::addATimer(Timer *t) { timers.push_back(t); } + +void TimerSet::pollAllTimers() { + std::time_t timeNow; + if (time(&timeNow) > previousTime) { + previousTime = timeNow; + + for (auto it = timers.begin(); it != timers.end(); it++) { + (*it)->tick(); + } + } +} + +TimerSet &TimerSet::Instance() { + // Meyer's Singleton implementation + static TimerSet pInstance; + return pInstance; +} diff --git a/cmat/SolutionEx41/TimerSet.h b/cmat/SolutionEx41/TimerSet.h new file mode 100644 index 0000000..35c2baf --- /dev/null +++ b/cmat/SolutionEx41/TimerSet.h @@ -0,0 +1,29 @@ +#ifndef TIMERSET_H +#define TIMERSET_H + +#include +#include + +class Timer; + +class TimerSet { + public: + void pollAllTimers(); + void addATimer(Timer *); + + private: + TimerSet(); + std::vector timers; + std::time_t previousTime; + + // Meyer's singleton + public: + static TimerSet &Instance(); + + private: + // prevent copying and assignment of the singleton + TimerSet(const TimerSet &); + TimerSet &operator=(const TimerSet &); +}; + +#endif diff --git a/cmat/SolutionEx41/main.cpp b/cmat/SolutionEx41/main.cpp new file mode 100644 index 0000000..3624dd0 --- /dev/null +++ b/cmat/SolutionEx41/main.cpp @@ -0,0 +1,32 @@ + + +#include "Keyboard.h" +#include "Pelican.h" +#include "Pole.h" +#include "TimerSet.h" + +#include // provides toupper() + +int main() { + Keyboard kbd; + Pelican thePelican; + Pole pole1(20, 0, thePelican); + Pole pole2(40, 0, thePelican); + + char c = 0; + + while (std::toupper(c) != 'Q') { // loop until 'Q' is pressed + + while (!kbd.isCharAvail()) { + TimerSet::Instance().pollAllTimers(); // no key press to process, poll the timers + } + + c = kbd.getChar(); // get the character + if (c == ' ') { + // it's a space, so press the WAIT button + thePelican.press(); + } + } + + return 0; +} diff --git a/cmat/SolutionEx41Bonus/Beeper.cpp b/cmat/SolutionEx41Bonus/Beeper.cpp new file mode 100644 index 0000000..7d97c13 --- /dev/null +++ b/cmat/SolutionEx41Bonus/Beeper.cpp @@ -0,0 +1,11 @@ +#include "Beeper.h" +#include "Pelican.h" +#include + +Beeper::Beeper(Pelican &pel) : myPelican(pel) { myPelican.attach(*this); } + +void Beeper::update() { + if (myPelican.getState() == Pelican::RED_STATE) { + std::cout << "BEEP!\n"; + } +} diff --git a/cmat/SolutionEx41Bonus/Beeper.h b/cmat/SolutionEx41Bonus/Beeper.h new file mode 100644 index 0000000..caa502d --- /dev/null +++ b/cmat/SolutionEx41Bonus/Beeper.h @@ -0,0 +1,25 @@ +// ====================================================== +// +// Observer to make the crossing beep when traffic +// lights are red +// +// ====================================================== + +#ifndef BEEPER_H +#define BEEPER_H + +#include "Observer.h" + +class Pelican; + +class Beeper : public Observer { + public: + Beeper(Pelican &pel); + + void update(); + + private: + Pelican &myPelican; +}; + +#endif diff --git a/cmat/SolutionEx41Bonus/CMakeLists.txt b/cmat/SolutionEx41Bonus/CMakeLists.txt new file mode 100644 index 0000000..5487764 --- /dev/null +++ b/cmat/SolutionEx41Bonus/CMakeLists.txt @@ -0,0 +1,15 @@ +# SolutionEx41Bonus + +cmat_add_exercise(SolutionEx41Bonus + GUI + SOURCES + Beeper.cpp + Light.cpp + main.cpp + Pelican.cpp + PelicanTimer.cpp + Pole.cpp + Subject.cpp + Timer.cpp + TimerSet.cpp +) diff --git a/cmat/SolutionEx41Bonus/Ex41.sln b/cmat/SolutionEx41Bonus/Ex41.sln new file mode 100644 index 0000000..419d6cc --- /dev/null +++ b/cmat/SolutionEx41Bonus/Ex41.sln @@ -0,0 +1,20 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ex41", "Ex41.vcxproj", "{2B6BAD2C-A2F1-99CD-6A27-DD0BBF12E5A4}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2B6BAD2C-A2F1-99CD-6A27-DD0BBF12E5A4}.Debug|Win32.ActiveCfg = Debug|Win32 + {2B6BAD2C-A2F1-99CD-6A27-DD0BBF12E5A4}.Debug|Win32.Build.0 = Debug|Win32 + {2B6BAD2C-A2F1-99CD-6A27-DD0BBF12E5A4}.Release|Win32.ActiveCfg = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/cmat/SolutionEx41Bonus/Ex41.suo b/cmat/SolutionEx41Bonus/Ex41.suo new file mode 100644 index 0000000..eda747b Binary files /dev/null and b/cmat/SolutionEx41Bonus/Ex41.suo differ diff --git a/cmat/SolutionEx41Bonus/Ex41.vcproj b/cmat/SolutionEx41Bonus/Ex41.vcproj new file mode 100644 index 0000000..f10d6ef --- /dev/null +++ b/cmat/SolutionEx41Bonus/Ex41.vcproj @@ -0,0 +1,194 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cmat/SolutionEx41Bonus/Ex41.vcxproj b/cmat/SolutionEx41Bonus/Ex41.vcxproj new file mode 100644 index 0000000..0bf27c6 --- /dev/null +++ b/cmat/SolutionEx41Bonus/Ex41.vcxproj @@ -0,0 +1,146 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + {2B6BAD2C-A2F1-99CD-6A27-DD0BBF12E5A4} + + + + Application + false + MultiByte + v140 + + + Application + false + MultiByte + v140 + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + .\Debug\ + .\Debug\ + true + .\Release\ + .\Release\ + false + + + + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + true + NotUsing + .\Debug/Ex41.pch + .\Debug/ + .\Debug/ + .\Debug/ + Level3 + true + C:\course\397\DOS_Unix;%(AdditionalIncludeDirectories) + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Debug/Ex41.exe + true + true + .\Debug/Ex41.pdb + Console + + + .\Debug/Ex41.tlb + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + OnlyExplicitInline + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + true + + + .\Release/Ex41.pch + .\Release/ + .\Release/ + .\Release/ + Level3 + true + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Release/Ex41.exe + true + .\Release/Ex41.pdb + Console + + + .\Release/Ex41.tlb + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cmat/SolutionEx41Bonus/Ex41.vcxproj.filters b/cmat/SolutionEx41Bonus/Ex41.vcxproj.filters new file mode 100644 index 0000000..8babae3 --- /dev/null +++ b/cmat/SolutionEx41Bonus/Ex41.vcxproj.filters @@ -0,0 +1,86 @@ + + + + + {d342b4ff-da53-4cfa-9c78-ecc4af2f56cd} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {1e58a93c-2ba4-46f3-bde3-fdef6055c3a4} + h;hpp;hxx;hm;inl + + + {7d8dd5fa-5328-4693-8b68-b95e098fcdd6} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + DOS_Unix + + + DOS_Unix + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + DOS_Unix + + + DOS_Unix + + + Header Files + + + \ No newline at end of file diff --git a/cmat/SolutionEx41Bonus/Ex41.vcxproj.user b/cmat/SolutionEx41Bonus/Ex41.vcxproj.user new file mode 100644 index 0000000..695b5c7 --- /dev/null +++ b/cmat/SolutionEx41Bonus/Ex41.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cmat/SolutionEx41Bonus/Light.cpp b/cmat/SolutionEx41Bonus/Light.cpp new file mode 100644 index 0000000..e111c52 --- /dev/null +++ b/cmat/SolutionEx41Bonus/Light.cpp @@ -0,0 +1,21 @@ + + +#include "Light.h" +#include "Pelican.h" +#include "Screen.h" +#include + +Light::Light(std::string name, int x, int y, int color) : x(x), y(y), c(color), name(name) {} + +Light::~Light() { + std::cout << "Deleting light (" << name << ", " << x << ", " << y << ", " << c << ")" + << "\n"; +} + +void Light::set(LightState newState) { + state = newState; + Screen::write(name.c_str(), x, y, state == FLASH ? (128 + c) : (state == OFF ? 0 : c)); + // 128 + color was used to make a character flash (but not any more) +} + +Light::LightState Light::get(void) { return state; } diff --git a/cmat/SolutionEx41Bonus/Light.h b/cmat/SolutionEx41Bonus/Light.h new file mode 100644 index 0000000..03adf9a --- /dev/null +++ b/cmat/SolutionEx41Bonus/Light.h @@ -0,0 +1,30 @@ +// ====================================================== +// +// Represents a light, implemented as a string written +// to a console window +// +// ====================================================== + +#ifndef LIGHT_H +#define LIGHT_H + +#include + +class Light { + public: + Light(std::string name, int x, int y, int color); + ~Light(); + + enum LightState { ON, OFF, FLASH }; + + void set(LightState new_state); + LightState get(void); + + private: + int c; // light colour + int x, y; + std::string name; + LightState state; +}; + +#endif diff --git a/cmat/SolutionEx41Bonus/Observer.h b/cmat/SolutionEx41Bonus/Observer.h new file mode 100644 index 0000000..368bd0f --- /dev/null +++ b/cmat/SolutionEx41Bonus/Observer.h @@ -0,0 +1,11 @@ + + +#ifndef OBSERVER_H +#define OBSERVER_H + +class Observer { + public: + virtual void update() = 0; +}; + +#endif diff --git a/cmat/SolutionEx41Bonus/Pelican.cpp b/cmat/SolutionEx41Bonus/Pelican.cpp new file mode 100644 index 0000000..af641ad --- /dev/null +++ b/cmat/SolutionEx41Bonus/Pelican.cpp @@ -0,0 +1,54 @@ + +#include "Pelican.h" +#include "PelicanTimer.h" + +Pelican::Pelican() : pressed(false), RED_TIME(4), YELLOW_TIME(2), GREEN_TIME(3), FLASH_TIME(5), state(GREEN_IDLE) { + myTimer = new PelicanTimer(*this, &Pelican::timerExpired); +} + +void Pelican::press(void) { + if (state == GREEN_IDLE) { + state = YELLOW_STATE; + myTimer->timeoutRequest(YELLOW_TIME); + pressed = true; + notify(); + } else if (state != RED_STATE) { + pressed = true; + notify(); + } +} + +void Pelican::timerExpired(void) { + switch (state) { + case RED_STATE: + state = YELLOW_FLASHING; + myTimer->timeoutRequest(FLASH_TIME); + break; + + case YELLOW_FLASHING: + state = GREEN_TIMING; + myTimer->timeoutRequest(GREEN_TIME); + break; + + case GREEN_TIMING: + if (pressed) { + state = YELLOW_STATE; + myTimer->timeoutRequest(YELLOW_TIME); + } else { + state = GREEN_IDLE; + } + break; + + case GREEN_IDLE: + // should never happen + break; + + case YELLOW_STATE: + state = RED_STATE; + pressed = false; + myTimer->timeoutRequest(RED_TIME); + break; + } + + notify(); +} diff --git a/cmat/SolutionEx41Bonus/Pelican.h b/cmat/SolutionEx41Bonus/Pelican.h new file mode 100644 index 0000000..e8825a2 --- /dev/null +++ b/cmat/SolutionEx41Bonus/Pelican.h @@ -0,0 +1,51 @@ +// ====================================================== +// +// Represents a Pelican crossing +// +// ====================================================== + +#ifndef PELICAN_H +#define PELICAN_H + +#include "Subject.h" + +class PelicanTimer; + +class Pelican : public Subject { + public: + Pelican(); + + // call when the WAIT button has been pressed + void press(void); + + // states that a Pelican can be in + enum PelicanState { RED_STATE, YELLOW_FLASHING, GREEN_TIMING, GREEN_IDLE, YELLOW_STATE }; + + bool isPressed() const { return pressed; } + PelicanState getState() const { return state; } + + private: + // state that this Pelican is in + PelicanState state; + + // called by PeleicanTimer when the lights need to change + void timerExpired(void); + + const unsigned int RED_TIME; + const unsigned int YELLOW_TIME; + const unsigned int GREEN_TIME; + const unsigned int FLASH_TIME; + + // indicates whether the WAIT light should be on + bool pressed; + + // Timer that indicates when the lights should change + PelicanTimer *myTimer; + + private: + // prevent general use of copy ctor and operator= + Pelican(const Pelican &); + Pelican &operator=(const Pelican &); +}; + +#endif diff --git a/cmat/SolutionEx41Bonus/PelicanTimer.cpp b/cmat/SolutionEx41Bonus/PelicanTimer.cpp new file mode 100644 index 0000000..f9c107a --- /dev/null +++ b/cmat/SolutionEx41Bonus/PelicanTimer.cpp @@ -0,0 +1,7 @@ + + +#include "PelicanTimer.h" + +PelicanTimer::PelicanTimer(Pelican &target, TargetFunc targetFunc) : myTarget(target), myTargetFunc(targetFunc) {} + +void PelicanTimer::doExpired() { (myTarget.*myTargetFunc)(); } diff --git a/cmat/SolutionEx41Bonus/PelicanTimer.h b/cmat/SolutionEx41Bonus/PelicanTimer.h new file mode 100644 index 0000000..637290c --- /dev/null +++ b/cmat/SolutionEx41Bonus/PelicanTimer.h @@ -0,0 +1,27 @@ +// ====================================================== +// +// This class specializes the Timer to enable it to +// stimulate a Pelican +// +// ====================================================== + +#ifndef PelicanTimer_H +#define PelicanTimer_H + +#include "Pelican.h" +#include "Timer.h" + +class PelicanTimer : public Timer { + public: + typedef void (Pelican::*TargetFunc)(); + + PelicanTimer(Pelican &target, TargetFunc targetFunc); + + private: + void doExpired(); + + Pelican &myTarget; + TargetFunc myTargetFunc; +}; + +#endif diff --git a/cmat/SolutionEx41Bonus/Pole.cpp b/cmat/SolutionEx41Bonus/Pole.cpp new file mode 100644 index 0000000..b14eb14 --- /dev/null +++ b/cmat/SolutionEx41Bonus/Pole.cpp @@ -0,0 +1,69 @@ +#include "Pole.h" +#include "Screen.h" + +Pole::Pole(int x, int y, Pelican &p) : waitLight(new Light("WAIT", x + 6, y + 12, Screen::WHITE)), myPelican(p) { + myPelican.attach(*this); + + using namespace Screen; // we will discuss namespaces in the course + + lights[RED_LIGHT] = new Light("*", x + 11, y + 3, RED); + lights[RED_MAN] = new Light("*<-=", x + 6, y + 4, RED); + lights[YELLOW_LIGHT] = new Light("*", x + 11, y + 5, YELLOW); + lights[GREEN_LIGHT] = new Light("*", x + 11, y + 7, GREEN); + lights[GREEN_MAN] = new Light("*|-<", x + 6, y + 7, GREEN); + + write(" _____ ", x, ++y, GRAY); + write(" /___ /| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" | |/| ", x, ++y, GRAY); + write(" |____| | ", x, ++y, GRAY); + write(" | |/| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" |____|/ ", x, ++y, GRAY); + write(" _||__ ", x, ++y, GRAY); + write(" /___ /| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" |____|/ ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write("========||===========", x, ++y, GRAY); + write(" / || / ", x, ++y, GRAY); + write("_ /_________ /_ ", x, ++y, GRAY); + write("/ / ", x, ++y, GRAY); + + // Force initial display + update(); +} + +Pole::~Pole() { + for (int i = 0; i < sizeof lights / sizeof(lights[0]); ++i) + delete lights[i]; + delete waitLight; +} + +void Pole::setTrafficLights(Pelican::PelicanState state) { + static const Light::LightState LightStates[Pelican::YELLOW_STATE + 1][RED_MAN + 1] = { + // red yellow green green man red man + {Light::ON, Light::OFF, Light::OFF, Light::ON, Light::OFF}, // red + {Light::OFF, Light::FLASH, Light::OFF, Light::FLASH, Light::OFF}, // y flash + {Light::OFF, Light::OFF, Light::ON, Light::OFF, Light::ON}, // g time + {Light::OFF, Light::OFF, Light::ON, Light::OFF, Light::ON}, // g idle + {Light::OFF, Light::ON, Light::OFF, Light::OFF, Light::ON} // yellow + }; + + for (int i = RED_LIGHT; i <= RED_MAN; i++) { + lights[i]->set(LightStates[state][i]); + } +} + +void Pole::setWaitLight(bool pressed) { waitLight->set(pressed ? Light::ON : Light::OFF); } + +void Pole::update() { + setTrafficLights(myPelican.getState()); + setWaitLight(myPelican.isPressed()); +} diff --git a/cmat/SolutionEx41Bonus/Pole.h b/cmat/SolutionEx41Bonus/Pole.h new file mode 100644 index 0000000..674fbfe --- /dev/null +++ b/cmat/SolutionEx41Bonus/Pole.h @@ -0,0 +1,28 @@ + +#ifndef POLE_H +#define POLE_H + +#include "Light.h" +#include "Observer.h" +#include "Pelican.h" + +class Pole : public Observer { + public: + Pole(int x, int y, Pelican &p); + ~Pole(); + + void setTrafficLights(Pelican::PelicanState state); + void setWaitLight(bool pressed); + + void update(); + + private: + Pelican &myPelican; + + enum LightName { RED_LIGHT, YELLOW_LIGHT, GREEN_LIGHT, GREEN_MAN, RED_MAN }; + + Light *lights[RED_MAN + 1]; + Light *waitLight; +}; + +#endif diff --git a/cmat/SolutionEx41Bonus/Subject.cpp b/cmat/SolutionEx41Bonus/Subject.cpp new file mode 100644 index 0000000..c31e2b6 --- /dev/null +++ b/cmat/SolutionEx41Bonus/Subject.cpp @@ -0,0 +1,12 @@ + + +#include "Subject.h" +#include "Observer.h" + +void Subject::attach(Observer &obs) { myObservers.insert(&obs); } + +void Subject::notify() const { + for (ObsList::const_iterator iter = myObservers.begin(); iter != myObservers.end(); ++iter) { + (*iter)->update(); + } +} diff --git a/cmat/SolutionEx41Bonus/Subject.h b/cmat/SolutionEx41Bonus/Subject.h new file mode 100644 index 0000000..9737df9 --- /dev/null +++ b/cmat/SolutionEx41Bonus/Subject.h @@ -0,0 +1,22 @@ + + +#ifndef SUBJECT_H +#define SUBJECT_H + +class Observer; + +#include + +class Subject { + public: + typedef std::set ObsList; + void attach(Observer &obs); + + protected: + void notify() const; + + private: + ObsList myObservers; +}; + +#endif diff --git a/cmat/SolutionEx41Bonus/Timer.cpp b/cmat/SolutionEx41Bonus/Timer.cpp new file mode 100644 index 0000000..e62ee48 --- /dev/null +++ b/cmat/SolutionEx41Bonus/Timer.cpp @@ -0,0 +1,22 @@ + +#include "Timer.h" +#include "TimerSet.h" + +void Timer::timeoutRequest(int seconds) { timeToGo = seconds; } + +Timer::Timer() : timeToGo(-1) { TimerSet::Instance().addATimer(this); } + +void Timer::tick() { + if (isExpired()) { + doExpired(); + } +} + +bool Timer::isExpired() { + if (timeToGo > 0) { + if (--timeToGo == 0) { + return true; + } + } + return false; +} diff --git a/cmat/SolutionEx41Bonus/Timer.h b/cmat/SolutionEx41Bonus/Timer.h new file mode 100644 index 0000000..38bbced --- /dev/null +++ b/cmat/SolutionEx41Bonus/Timer.h @@ -0,0 +1,31 @@ +// ====================================================== +// A general-purpose countdown timer +// To use this class, specialize it +// and override tick() +// +// ====================================================== + +#ifndef timer_H +#define timer_H + +#include + +class Timer { + public: + Timer(); + + void timeoutRequest(int seconds); + + // template method + void tick(); + + protected: + bool isExpired(); + + private: + virtual void doExpired() = 0; + + int timeToGo; +}; + +#endif diff --git a/cmat/SolutionEx41Bonus/TimerSet.cpp b/cmat/SolutionEx41Bonus/TimerSet.cpp new file mode 100644 index 0000000..2a68d12 --- /dev/null +++ b/cmat/SolutionEx41Bonus/TimerSet.cpp @@ -0,0 +1,23 @@ +#include "TimerSet.h" +#include "Timer.h" +#include + +TimerSet::TimerSet() : timersInUse(0), previousTime(time(NULL)) {} + +void TimerSet::addATimer(Timer *t) { timers[timersInUse++] = t; } + +void TimerSet::pollAllTimers() { + std::time_t timeNow; + if (time(&timeNow) > previousTime) { + previousTime = timeNow; + for (int i = 0; i < timersInUse; ++i) { + timers[i]->tick(); + } + } +} + +TimerSet &TimerSet::Instance() { + // Meyer's Singleton implementation + static TimerSet pInstance; + return pInstance; +} diff --git a/cmat/SolutionEx41Bonus/TimerSet.h b/cmat/SolutionEx41Bonus/TimerSet.h new file mode 100644 index 0000000..3dfe925 --- /dev/null +++ b/cmat/SolutionEx41Bonus/TimerSet.h @@ -0,0 +1,29 @@ +#ifndef TIMERSET_H +#define TIMERSET_H + +#include + +class Timer; + +class TimerSet { + public: + void pollAllTimers(); + void addATimer(Timer *); + + private: + TimerSet(); + Timer *timers[40]; + int timersInUse; + std::time_t previousTime; + + // Meyer's singleton + public: + static TimerSet &Instance(); + + private: + // prevent copying and assignment of the singleton + TimerSet(const TimerSet &); + TimerSet &operator=(const TimerSet &); +}; + +#endif diff --git a/cmat/SolutionEx41Bonus/main.cpp b/cmat/SolutionEx41Bonus/main.cpp new file mode 100644 index 0000000..9a63ab3 --- /dev/null +++ b/cmat/SolutionEx41Bonus/main.cpp @@ -0,0 +1,34 @@ + + +#include "Beeper.h" +#include "Keyboard.h" +#include "Pelican.h" +#include "Pole.h" +#include "TimerSet.h" + +#include // provides toupper() + +int main() { + Keyboard kbd; + Pelican thePelican; + Pole pole1(20, 0, thePelican); + Pole pole2(40, 0, thePelican); + Beeper beeper(thePelican); + + char c = 0; + + while (std::toupper(c) != 'Q') { // loop until 'Q' is pressed + + while (!kbd.isCharAvail()) { + TimerSet::Instance().pollAllTimers(); // no key press to process, poll the timers + } + + c = kbd.getChar(); // get the character + if (c == ' ') { + // it's a space, so press the WAIT button + thePelican.press(); + } + } + + return 0; +} diff --git a/cmat/SolutionEx42/CMakeLists.txt b/cmat/SolutionEx42/CMakeLists.txt new file mode 100644 index 0000000..645e292 --- /dev/null +++ b/cmat/SolutionEx42/CMakeLists.txt @@ -0,0 +1,14 @@ +# SolutionEx42 + +cmat_add_exercise(SolutionEx42 + GUI + SOURCES + Light.cpp + main.cpp + Pelican.cpp + PelicanTimer.cpp + Pole.cpp + Subject.cpp + Timer.cpp + TimerSet.cpp +) diff --git a/cmat/SolutionEx42/Ex42.sln b/cmat/SolutionEx42/Ex42.sln new file mode 100644 index 0000000..bc7c20b --- /dev/null +++ b/cmat/SolutionEx42/Ex42.sln @@ -0,0 +1,20 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ex42", "Ex42.vcxproj", "{F39C16B5-32B7-322D-F5D9-367B7F9EEEB8}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F39C16B5-32B7-322D-F5D9-367B7F9EEEB8}.Debug|Win32.ActiveCfg = Debug|Win32 + {F39C16B5-32B7-322D-F5D9-367B7F9EEEB8}.Debug|Win32.Build.0 = Debug|Win32 + {F39C16B5-32B7-322D-F5D9-367B7F9EEEB8}.Release|Win32.ActiveCfg = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/cmat/SolutionEx42/Ex42.suo b/cmat/SolutionEx42/Ex42.suo new file mode 100644 index 0000000..58216ee Binary files /dev/null and b/cmat/SolutionEx42/Ex42.suo differ diff --git a/cmat/SolutionEx42/Ex42.vcproj b/cmat/SolutionEx42/Ex42.vcproj new file mode 100644 index 0000000..7c9d9a9 --- /dev/null +++ b/cmat/SolutionEx42/Ex42.vcproj @@ -0,0 +1,194 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cmat/SolutionEx42/Ex42.vcxproj b/cmat/SolutionEx42/Ex42.vcxproj new file mode 100644 index 0000000..9001afd --- /dev/null +++ b/cmat/SolutionEx42/Ex42.vcxproj @@ -0,0 +1,145 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + {F39C16B5-32B7-322D-F5D9-367B7F9EEEB8} + + + + Application + false + MultiByte + v140 + + + Application + false + MultiByte + v140 + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + .\Release\ + .\Release\ + false + .\Debug\ + .\Debug\ + true + + + + OnlyExplicitInline + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + true + + + .\Release/Ex42.pch + .\Release/ + .\Release/ + .\Release/ + Level3 + true + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Release/Ex42.exe + true + .\Release/Ex42.pdb + Console + + + .\Release/Ex42.tlb + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + true + NotUsing + .\Debug/Ex42.pch + .\Debug/ + .\Debug/ + .\Debug/ + Level3 + true + C:\course\397\DOS_Unix;%(AdditionalIncludeDirectories) + false + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Debug/Ex42.exe + true + true + .\Debug/Ex42.pdb + Console + + + .\Debug/Ex42.tlb + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cmat/SolutionEx42/Ex42.vcxproj.filters b/cmat/SolutionEx42/Ex42.vcxproj.filters new file mode 100644 index 0000000..91a19d0 --- /dev/null +++ b/cmat/SolutionEx42/Ex42.vcxproj.filters @@ -0,0 +1,80 @@ + + + + + {71ef5090-ad5d-4a5a-ad8f-650d82bf21bb} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {c9b4ef1f-e7e6-42d9-913c-27e559907ee1} + h;hpp;hxx;hm;inl + + + {417d066f-541c-4c89-9db1-cbd5934a72c4} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + DOS_Unix + + + DOS_Unix + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + DOS_Unix + + + DOS_Unix + + + \ No newline at end of file diff --git a/cmat/SolutionEx42/Ex42.vcxproj.user b/cmat/SolutionEx42/Ex42.vcxproj.user new file mode 100644 index 0000000..695b5c7 --- /dev/null +++ b/cmat/SolutionEx42/Ex42.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cmat/SolutionEx42/Light.cpp b/cmat/SolutionEx42/Light.cpp new file mode 100644 index 0000000..e111c52 --- /dev/null +++ b/cmat/SolutionEx42/Light.cpp @@ -0,0 +1,21 @@ + + +#include "Light.h" +#include "Pelican.h" +#include "Screen.h" +#include + +Light::Light(std::string name, int x, int y, int color) : x(x), y(y), c(color), name(name) {} + +Light::~Light() { + std::cout << "Deleting light (" << name << ", " << x << ", " << y << ", " << c << ")" + << "\n"; +} + +void Light::set(LightState newState) { + state = newState; + Screen::write(name.c_str(), x, y, state == FLASH ? (128 + c) : (state == OFF ? 0 : c)); + // 128 + color was used to make a character flash (but not any more) +} + +Light::LightState Light::get(void) { return state; } diff --git a/cmat/SolutionEx42/Light.h b/cmat/SolutionEx42/Light.h new file mode 100644 index 0000000..03adf9a --- /dev/null +++ b/cmat/SolutionEx42/Light.h @@ -0,0 +1,30 @@ +// ====================================================== +// +// Represents a light, implemented as a string written +// to a console window +// +// ====================================================== + +#ifndef LIGHT_H +#define LIGHT_H + +#include + +class Light { + public: + Light(std::string name, int x, int y, int color); + ~Light(); + + enum LightState { ON, OFF, FLASH }; + + void set(LightState new_state); + LightState get(void); + + private: + int c; // light colour + int x, y; + std::string name; + LightState state; +}; + +#endif diff --git a/cmat/SolutionEx42/Observer.h b/cmat/SolutionEx42/Observer.h new file mode 100644 index 0000000..4c5dbf0 --- /dev/null +++ b/cmat/SolutionEx42/Observer.h @@ -0,0 +1,13 @@ + + +#ifndef OBSERVER_H +#define OBSERVER_H + +#include "Subject.h" + +class Observer { + public: + virtual void update(const Hint &) = 0; +}; + +#endif diff --git a/cmat/SolutionEx42/Pelican.cpp b/cmat/SolutionEx42/Pelican.cpp new file mode 100644 index 0000000..cee9f57 --- /dev/null +++ b/cmat/SolutionEx42/Pelican.cpp @@ -0,0 +1,59 @@ + + +#include "Pelican.h" +#include "PelicanTimer.h" +#include "Pole.h" + +Pelican::Pelican() : pressed(false), RED_TIME(4), YELLOW_TIME(2), GREEN_TIME(3), FLASH_TIME(5), state(GREEN_IDLE) { + myTimer = new PelicanTimer(*this, &Pelican::timerExpired); +} + +void Pelican::press(void) { + if (state == GREEN_IDLE) { + state = YELLOW_STATE; + myTimer->timeoutRequest(YELLOW_TIME); + pressed = true; + + notify(WaitHint(pressed)); + notify(LightHint(state)); + } else if (state != RED_STATE) { + pressed = true; + notify(WaitHint(pressed)); + } +} + +void Pelican::timerExpired(void) { + switch (state) { + case RED_STATE: + state = YELLOW_FLASHING; + myTimer->timeoutRequest(FLASH_TIME); + break; + + case YELLOW_FLASHING: + state = GREEN_TIMING; + myTimer->timeoutRequest(GREEN_TIME); + break; + + case GREEN_TIMING: + if (pressed) { + state = YELLOW_STATE; + myTimer->timeoutRequest(YELLOW_TIME); + } else { + state = GREEN_IDLE; + } + break; + + case GREEN_IDLE: + // should never happen + break; + + case YELLOW_STATE: + state = RED_STATE; + pressed = false; + notify(WaitHint(pressed)); + myTimer->timeoutRequest(RED_TIME); + break; + } + + notify(LightHint(state)); +} diff --git a/cmat/SolutionEx42/Pelican.h b/cmat/SolutionEx42/Pelican.h new file mode 100644 index 0000000..7aa37f9 --- /dev/null +++ b/cmat/SolutionEx42/Pelican.h @@ -0,0 +1,65 @@ +// ====================================================== +// +// Represents a Pelican crossing +// +// ====================================================== + +#ifndef PELICAN_H +#define PELICAN_H + +#include "Subject.h" + +class PelicanTimer; + +class Pelican : public Subject { + public: + Pelican(); + + // call when the WAIT button has been pressed + void press(void); + + // states that a Pelican can be in + enum PelicanState { RED_STATE, YELLOW_FLASHING, GREEN_TIMING, GREEN_IDLE, YELLOW_STATE }; + + bool isPressed() const { return pressed; } + PelicanState getState() const { return state; } + + private: + // state that this Pelican is in + PelicanState state; + + // called by PeleicanTimer when the lights need to change + void timerExpired(void); + + const unsigned int RED_TIME; + const unsigned int YELLOW_TIME; + const unsigned int GREEN_TIME; + const unsigned int FLASH_TIME; + + // indicates whether the WAIT light should be on + bool pressed; + + // Timer that indicates when the lights should change + PelicanTimer *myTimer; + + private: + // prevent general use of copy ctor and operator= + Pelican(const Pelican &); + Pelican &operator=(const Pelican &); +}; + +class LightHint : public Hint { + public: + LightHint(Pelican::PelicanState s) : state(s) {} + + Pelican::PelicanState state; +}; + +class WaitHint : public Hint { + public: + WaitHint(bool p) : pressed(p) {} + + bool pressed; +}; + +#endif diff --git a/cmat/SolutionEx42/PelicanTimer.cpp b/cmat/SolutionEx42/PelicanTimer.cpp new file mode 100644 index 0000000..f9c107a --- /dev/null +++ b/cmat/SolutionEx42/PelicanTimer.cpp @@ -0,0 +1,7 @@ + + +#include "PelicanTimer.h" + +PelicanTimer::PelicanTimer(Pelican &target, TargetFunc targetFunc) : myTarget(target), myTargetFunc(targetFunc) {} + +void PelicanTimer::doExpired() { (myTarget.*myTargetFunc)(); } diff --git a/cmat/SolutionEx42/PelicanTimer.h b/cmat/SolutionEx42/PelicanTimer.h new file mode 100644 index 0000000..637290c --- /dev/null +++ b/cmat/SolutionEx42/PelicanTimer.h @@ -0,0 +1,27 @@ +// ====================================================== +// +// This class specializes the Timer to enable it to +// stimulate a Pelican +// +// ====================================================== + +#ifndef PelicanTimer_H +#define PelicanTimer_H + +#include "Pelican.h" +#include "Timer.h" + +class PelicanTimer : public Timer { + public: + typedef void (Pelican::*TargetFunc)(); + + PelicanTimer(Pelican &target, TargetFunc targetFunc); + + private: + void doExpired(); + + Pelican &myTarget; + TargetFunc myTargetFunc; +}; + +#endif diff --git a/cmat/SolutionEx42/Pole.cpp b/cmat/SolutionEx42/Pole.cpp new file mode 100644 index 0000000..9048cf4 --- /dev/null +++ b/cmat/SolutionEx42/Pole.cpp @@ -0,0 +1,79 @@ +#include "Pole.h" +#include "Screen.h" + +Pole::Pole(int x, int y, Pelican &p) : waitLight(new Light("WAIT", x + 6, y + 12, Screen::WHITE)), myPelican(p) { + myPelican.attach(*this); + + using namespace Screen; // we will discuss namespaces in the course + + lights[RED_LIGHT] = new Light("*", x + 11, y + 3, RED); + lights[RED_MAN] = new Light("*<-=", x + 6, y + 4, RED); + lights[YELLOW_LIGHT] = new Light("*", x + 11, y + 5, YELLOW); + lights[GREEN_LIGHT] = new Light("*", x + 11, y + 7, GREEN); + lights[GREEN_MAN] = new Light("*|-<", x + 6, y + 7, GREEN); + + write(" _____ ", x, ++y, GRAY); + write(" /___ /| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" | |/| ", x, ++y, GRAY); + write(" |____| | ", x, ++y, GRAY); + write(" | |/| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" |____|/ ", x, ++y, GRAY); + write(" _||__ ", x, ++y, GRAY); + write(" /___ /| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" |____|/ ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write("========||===========", x, ++y, GRAY); + write(" / || / ", x, ++y, GRAY); + write("_ /_________ /_ ", x, ++y, GRAY); + write("/ / ", x, ++y, GRAY); + + // Force initial display + update(Hint()); +} + +Pole::~Pole() { + for (int i = 0; i < sizeof lights / sizeof(lights[0]); ++i) + delete lights[i]; + delete waitLight; +} + +void Pole::setTrafficLights(Pelican::PelicanState state) { + static const Light::LightState LightStates[Pelican::YELLOW_STATE + 1][RED_MAN + 1] = { + // red yellow green green man red man + {Light::ON, Light::OFF, Light::OFF, Light::ON, Light::OFF}, // red + {Light::OFF, Light::FLASH, Light::OFF, Light::FLASH, Light::OFF}, // y flash + {Light::OFF, Light::OFF, Light::ON, Light::OFF, Light::ON}, // g time + {Light::OFF, Light::OFF, Light::ON, Light::OFF, Light::ON}, // g idle + {Light::OFF, Light::ON, Light::OFF, Light::OFF, Light::ON} // yellow + }; + + for (int i = RED_LIGHT; i <= RED_MAN; i++) { + lights[i]->set(LightStates[state][i]); + } +} + +void Pole::setWaitLight(bool pressed) { waitLight->set(pressed ? Light::ON : Light::OFF); } + +void Pole::update(const Hint &h) { + const WaitHint *waitHintPtr; + const LightHint *lightHintPtr; + + if ((waitHintPtr = dynamic_cast(&h)) != 0) { + setWaitLight(waitHintPtr->pressed); + } else if ((lightHintPtr = dynamic_cast(&h)) != 0) { + setTrafficLights(lightHintPtr->state); + } else { + // don't know what's changed, so update everything + setTrafficLights(myPelican.getState()); + setWaitLight(myPelican.isPressed()); + } +} diff --git a/cmat/SolutionEx42/Pole.h b/cmat/SolutionEx42/Pole.h new file mode 100644 index 0000000..06e79e0 --- /dev/null +++ b/cmat/SolutionEx42/Pole.h @@ -0,0 +1,29 @@ + + +#ifndef POLE_H +#define POLE_H + +#include "Light.h" +#include "Observer.h" +#include "Pelican.h" + +class Pole : public Observer { + public: + Pole(int x, int y, Pelican &p); + ~Pole(); + + void setTrafficLights(Pelican::PelicanState state); + void setWaitLight(bool pressed); + + void update(const Hint &); + + private: + Pelican &myPelican; + + enum LightName { RED_LIGHT, YELLOW_LIGHT, GREEN_LIGHT, GREEN_MAN, RED_MAN }; + + Light *lights[RED_MAN + 1]; + Light *waitLight; +}; + +#endif diff --git a/cmat/SolutionEx42/Subject.cpp b/cmat/SolutionEx42/Subject.cpp new file mode 100644 index 0000000..bb73802 --- /dev/null +++ b/cmat/SolutionEx42/Subject.cpp @@ -0,0 +1,12 @@ + + +#include "Subject.h" +#include "Observer.h" + +void Subject::attach(Observer &obs) { myObservers.insert(&obs); } + +void Subject::notify(const Hint &h) const { + for (ObsList::const_iterator iter = myObservers.begin(); iter != myObservers.end(); ++iter) { + (*iter)->update(h); + } +} diff --git a/cmat/SolutionEx42/Subject.h b/cmat/SolutionEx42/Subject.h new file mode 100644 index 0000000..46c2de8 --- /dev/null +++ b/cmat/SolutionEx42/Subject.h @@ -0,0 +1,27 @@ + + +#ifndef SUBJECT_H +#define SUBJECT_H + +class Observer; + +#include + +class Hint { + public: + virtual ~Hint() {} +}; + +class Subject { + public: + typedef std::set ObsList; + void attach(Observer &obs); + + protected: + void notify(const Hint &) const; + + private: + ObsList myObservers; +}; + +#endif diff --git a/cmat/SolutionEx42/Timer.cpp b/cmat/SolutionEx42/Timer.cpp new file mode 100644 index 0000000..9240bda --- /dev/null +++ b/cmat/SolutionEx42/Timer.cpp @@ -0,0 +1,23 @@ + + +#include "Timer.h" +#include "TimerSet.h" + +void Timer::timeoutRequest(int seconds) { timeToGo = seconds; } + +Timer::Timer() : timeToGo(-1) { TimerSet::Instance().addATimer(this); } + +void Timer::tick() { + if (isExpired()) { + doExpired(); + } +} + +bool Timer::isExpired() { + if (timeToGo > 0) { + if (--timeToGo == 0) { + return true; + } + } + return false; +} diff --git a/cmat/SolutionEx42/Timer.h b/cmat/SolutionEx42/Timer.h new file mode 100644 index 0000000..38bbced --- /dev/null +++ b/cmat/SolutionEx42/Timer.h @@ -0,0 +1,31 @@ +// ====================================================== +// A general-purpose countdown timer +// To use this class, specialize it +// and override tick() +// +// ====================================================== + +#ifndef timer_H +#define timer_H + +#include + +class Timer { + public: + Timer(); + + void timeoutRequest(int seconds); + + // template method + void tick(); + + protected: + bool isExpired(); + + private: + virtual void doExpired() = 0; + + int timeToGo; +}; + +#endif diff --git a/cmat/SolutionEx42/TimerSet.cpp b/cmat/SolutionEx42/TimerSet.cpp new file mode 100644 index 0000000..5606f75 --- /dev/null +++ b/cmat/SolutionEx42/TimerSet.cpp @@ -0,0 +1,24 @@ +#include "TimerSet.h" +#include "Timer.h" +#include + +TimerSet::TimerSet() : previousTime(time(NULL)) {} + +void TimerSet::addATimer(Timer *t) { timers.push_back(t); } + +void TimerSet::pollAllTimers() { + std::time_t timeNow; + if (time(&timeNow) > previousTime) { + previousTime = timeNow; + + for (auto it = timers.begin(); it != timers.end(); it++) { + (*it)->tick(); + } + } +} + +TimerSet &TimerSet::Instance() { + // Meyer's Singleton implementation + static TimerSet pInstance; + return pInstance; +} diff --git a/cmat/SolutionEx42/TimerSet.h b/cmat/SolutionEx42/TimerSet.h new file mode 100644 index 0000000..35c2baf --- /dev/null +++ b/cmat/SolutionEx42/TimerSet.h @@ -0,0 +1,29 @@ +#ifndef TIMERSET_H +#define TIMERSET_H + +#include +#include + +class Timer; + +class TimerSet { + public: + void pollAllTimers(); + void addATimer(Timer *); + + private: + TimerSet(); + std::vector timers; + std::time_t previousTime; + + // Meyer's singleton + public: + static TimerSet &Instance(); + + private: + // prevent copying and assignment of the singleton + TimerSet(const TimerSet &); + TimerSet &operator=(const TimerSet &); +}; + +#endif diff --git a/cmat/SolutionEx42/main.cpp b/cmat/SolutionEx42/main.cpp new file mode 100644 index 0000000..b7c6d29 --- /dev/null +++ b/cmat/SolutionEx42/main.cpp @@ -0,0 +1,33 @@ + + +#include "Keyboard.h" +#include "Pelican.h" +#include "Pole.h" +#include "TimerSet.h" + +#include // provides toupper() + +int main() { + Keyboard kbd; + + Pelican thePelican; + Pole pole1(20, 0, thePelican); + Pole pole2(40, 0, thePelican); + + char c = 0; + + while (std::toupper(c) != 'Q') { // loop until 'Q' is pressed + + while (!kbd.isCharAvail()) { + TimerSet::Instance().pollAllTimers(); // no key press to process, poll the timers + } + + c = kbd.getChar(); // get the character + if (c == ' ') { + // it's a space, so press the WAIT button + thePelican.press(); + } + } + + return 0; +} diff --git a/cmat/SolutionEx51/CMakeLists.txt b/cmat/SolutionEx51/CMakeLists.txt new file mode 100644 index 0000000..cf54338 --- /dev/null +++ b/cmat/SolutionEx51/CMakeLists.txt @@ -0,0 +1,14 @@ +# SolutionEx51 + +cmat_add_exercise(SolutionEx51 + GUI + SOURCES + Light.cpp + main.cpp + Pelican.cpp + PelicanTimer.cpp + Pole.cpp + Subject.cpp + Timer.cpp + TimerSet.cpp +) diff --git a/cmat/SolutionEx51/Ex51.sln b/cmat/SolutionEx51/Ex51.sln new file mode 100644 index 0000000..8f27b85 --- /dev/null +++ b/cmat/SolutionEx51/Ex51.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ex51", "Ex51.vcxproj", "{AFB7826A-449B-436C-A7FC-4401601F082B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {AFB7826A-449B-436C-A7FC-4401601F082B}.Debug|Win32.ActiveCfg = Debug|Win32 + {AFB7826A-449B-436C-A7FC-4401601F082B}.Debug|Win32.Build.0 = Debug|Win32 + {AFB7826A-449B-436C-A7FC-4401601F082B}.Release|Win32.ActiveCfg = Release|Win32 + {AFB7826A-449B-436C-A7FC-4401601F082B}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/cmat/SolutionEx51/Ex51.vcxproj b/cmat/SolutionEx51/Ex51.vcxproj new file mode 100644 index 0000000..aef1c40 --- /dev/null +++ b/cmat/SolutionEx51/Ex51.vcxproj @@ -0,0 +1,95 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {AFB7826A-449B-436C-A7FC-4401601F082B} + Ex51 + + + + Application + true + v140 + MultiByte + + + Application + false + v140 + true + MultiByte + + + + + + + + + + + + + + + Level3 + Disabled + true + C:\course\397\DOS_Unix; + + + true + Console + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cmat/SolutionEx51/Ex51.vcxproj.filters b/cmat/SolutionEx51/Ex51.vcxproj.filters new file mode 100644 index 0000000..db0c66c --- /dev/null +++ b/cmat/SolutionEx51/Ex51.vcxproj.filters @@ -0,0 +1,80 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {075c2eca-b76b-43df-8022-827ab031c5e2} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + DOS_Unix + + + DOS_Unix + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + DOS_Unix + + + DOS_Unix + + + \ No newline at end of file diff --git a/cmat/SolutionEx51/Ex51.vcxproj.user b/cmat/SolutionEx51/Ex51.vcxproj.user new file mode 100644 index 0000000..2a22e69 --- /dev/null +++ b/cmat/SolutionEx51/Ex51.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/cmat/SolutionEx51/Light.cpp b/cmat/SolutionEx51/Light.cpp new file mode 100644 index 0000000..e111c52 --- /dev/null +++ b/cmat/SolutionEx51/Light.cpp @@ -0,0 +1,21 @@ + + +#include "Light.h" +#include "Pelican.h" +#include "Screen.h" +#include + +Light::Light(std::string name, int x, int y, int color) : x(x), y(y), c(color), name(name) {} + +Light::~Light() { + std::cout << "Deleting light (" << name << ", " << x << ", " << y << ", " << c << ")" + << "\n"; +} + +void Light::set(LightState newState) { + state = newState; + Screen::write(name.c_str(), x, y, state == FLASH ? (128 + c) : (state == OFF ? 0 : c)); + // 128 + color was used to make a character flash (but not any more) +} + +Light::LightState Light::get(void) { return state; } diff --git a/cmat/SolutionEx51/Light.h b/cmat/SolutionEx51/Light.h new file mode 100644 index 0000000..37c9935 --- /dev/null +++ b/cmat/SolutionEx51/Light.h @@ -0,0 +1,30 @@ +// ==================================================== +// +// Represents a light, implemented as a string written +// to a console window +// +// ====================================================== + +#ifndef LIGHT_H +#define LIGHT_H + +#include + +class Light { + public: + Light(std::string name, int x, int y, int color); + ~Light(); + + enum LightState { ON, OFF, FLASH }; + + void set(LightState new_state); + LightState get(void); + + private: + int c; // light colour + int x, y; + std::string name; + LightState state; +}; + +#endif diff --git a/cmat/SolutionEx51/Observer.h b/cmat/SolutionEx51/Observer.h new file mode 100644 index 0000000..8304c48 --- /dev/null +++ b/cmat/SolutionEx51/Observer.h @@ -0,0 +1,12 @@ + +#ifndef OBSERVER_H +#define OBSERVER_H + +#include "Subject.h" + +class Observer { + public: + virtual void update(const Hint &) = 0; +}; + +#endif diff --git a/cmat/SolutionEx51/Pelican.cpp b/cmat/SolutionEx51/Pelican.cpp new file mode 100644 index 0000000..cee9f57 --- /dev/null +++ b/cmat/SolutionEx51/Pelican.cpp @@ -0,0 +1,59 @@ + + +#include "Pelican.h" +#include "PelicanTimer.h" +#include "Pole.h" + +Pelican::Pelican() : pressed(false), RED_TIME(4), YELLOW_TIME(2), GREEN_TIME(3), FLASH_TIME(5), state(GREEN_IDLE) { + myTimer = new PelicanTimer(*this, &Pelican::timerExpired); +} + +void Pelican::press(void) { + if (state == GREEN_IDLE) { + state = YELLOW_STATE; + myTimer->timeoutRequest(YELLOW_TIME); + pressed = true; + + notify(WaitHint(pressed)); + notify(LightHint(state)); + } else if (state != RED_STATE) { + pressed = true; + notify(WaitHint(pressed)); + } +} + +void Pelican::timerExpired(void) { + switch (state) { + case RED_STATE: + state = YELLOW_FLASHING; + myTimer->timeoutRequest(FLASH_TIME); + break; + + case YELLOW_FLASHING: + state = GREEN_TIMING; + myTimer->timeoutRequest(GREEN_TIME); + break; + + case GREEN_TIMING: + if (pressed) { + state = YELLOW_STATE; + myTimer->timeoutRequest(YELLOW_TIME); + } else { + state = GREEN_IDLE; + } + break; + + case GREEN_IDLE: + // should never happen + break; + + case YELLOW_STATE: + state = RED_STATE; + pressed = false; + notify(WaitHint(pressed)); + myTimer->timeoutRequest(RED_TIME); + break; + } + + notify(LightHint(state)); +} diff --git a/cmat/SolutionEx51/Pelican.h b/cmat/SolutionEx51/Pelican.h new file mode 100644 index 0000000..7aa37f9 --- /dev/null +++ b/cmat/SolutionEx51/Pelican.h @@ -0,0 +1,65 @@ +// ====================================================== +// +// Represents a Pelican crossing +// +// ====================================================== + +#ifndef PELICAN_H +#define PELICAN_H + +#include "Subject.h" + +class PelicanTimer; + +class Pelican : public Subject { + public: + Pelican(); + + // call when the WAIT button has been pressed + void press(void); + + // states that a Pelican can be in + enum PelicanState { RED_STATE, YELLOW_FLASHING, GREEN_TIMING, GREEN_IDLE, YELLOW_STATE }; + + bool isPressed() const { return pressed; } + PelicanState getState() const { return state; } + + private: + // state that this Pelican is in + PelicanState state; + + // called by PeleicanTimer when the lights need to change + void timerExpired(void); + + const unsigned int RED_TIME; + const unsigned int YELLOW_TIME; + const unsigned int GREEN_TIME; + const unsigned int FLASH_TIME; + + // indicates whether the WAIT light should be on + bool pressed; + + // Timer that indicates when the lights should change + PelicanTimer *myTimer; + + private: + // prevent general use of copy ctor and operator= + Pelican(const Pelican &); + Pelican &operator=(const Pelican &); +}; + +class LightHint : public Hint { + public: + LightHint(Pelican::PelicanState s) : state(s) {} + + Pelican::PelicanState state; +}; + +class WaitHint : public Hint { + public: + WaitHint(bool p) : pressed(p) {} + + bool pressed; +}; + +#endif diff --git a/cmat/SolutionEx51/PelicanTimer.cpp b/cmat/SolutionEx51/PelicanTimer.cpp new file mode 100644 index 0000000..f9c107a --- /dev/null +++ b/cmat/SolutionEx51/PelicanTimer.cpp @@ -0,0 +1,7 @@ + + +#include "PelicanTimer.h" + +PelicanTimer::PelicanTimer(Pelican &target, TargetFunc targetFunc) : myTarget(target), myTargetFunc(targetFunc) {} + +void PelicanTimer::doExpired() { (myTarget.*myTargetFunc)(); } diff --git a/cmat/SolutionEx51/PelicanTimer.h b/cmat/SolutionEx51/PelicanTimer.h new file mode 100644 index 0000000..637290c --- /dev/null +++ b/cmat/SolutionEx51/PelicanTimer.h @@ -0,0 +1,27 @@ +// ====================================================== +// +// This class specializes the Timer to enable it to +// stimulate a Pelican +// +// ====================================================== + +#ifndef PelicanTimer_H +#define PelicanTimer_H + +#include "Pelican.h" +#include "Timer.h" + +class PelicanTimer : public Timer { + public: + typedef void (Pelican::*TargetFunc)(); + + PelicanTimer(Pelican &target, TargetFunc targetFunc); + + private: + void doExpired(); + + Pelican &myTarget; + TargetFunc myTargetFunc; +}; + +#endif diff --git a/cmat/SolutionEx51/Pole.cpp b/cmat/SolutionEx51/Pole.cpp new file mode 100644 index 0000000..cce8abf --- /dev/null +++ b/cmat/SolutionEx51/Pole.cpp @@ -0,0 +1,79 @@ +#include "Pole.h" +#include "Screen.h" + +Pole::Pole(int x, int y, Pelican &p) : waitLight(new Light("WAIT", x + 6, y + 12, Screen::WHITE)), myPelican(p) { + myPelican.attach(*this); + + using namespace Screen; // we will discuss namespaces in the course + + lights[RED_LIGHT] = new Light("*", x + 11, y + 3, RED); + lights[RED_MAN] = new Light("*<-=", x + 6, y + 4, RED); + lights[YELLOW_LIGHT] = new Light("*", x + 11, y + 5, YELLOW); + lights[GREEN_LIGHT] = new Light("*", x + 11, y + 7, GREEN); + lights[GREEN_MAN] = new Light("*|-<", x + 6, y + 7, GREEN); + + write(" _____ ", x, ++y, GRAY); + write(" /___ /| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" | |/| ", x, ++y, GRAY); + write(" |____| | ", x, ++y, GRAY); + write(" | |/| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" |____|/ ", x, ++y, GRAY); + write(" _||__ ", x, ++y, GRAY); + write(" /___ /| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" |____|/ ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write("========||===========", x, ++y, GRAY); + write(" / || / ", x, ++y, GRAY); + write("_ /_________ /_ ", x, ++y, GRAY); + write("/ / ", x, ++y, GRAY); + + // the only time we need to ask the Pelican its state is at start up + update(Hint()); +} + +Pole::~Pole() { + for (int i = 0; i < sizeof lights / sizeof(lights[0]); ++i) + delete lights[i]; + delete waitLight; +} + +void Pole::setTrafficLights(Pelican::PelicanState state) { + static const Light::LightState LightStates[Pelican::YELLOW_STATE + 1][RED_MAN + 1] = { + // red yellow green green man red man + {Light::ON, Light::OFF, Light::OFF, Light::ON, Light::OFF}, // red + {Light::OFF, Light::FLASH, Light::OFF, Light::FLASH, Light::OFF}, // y flash + {Light::OFF, Light::OFF, Light::ON, Light::OFF, Light::ON}, // g time + {Light::OFF, Light::OFF, Light::ON, Light::OFF, Light::ON}, // g idle + {Light::OFF, Light::ON, Light::OFF, Light::OFF, Light::ON} // yellow + }; + + for (int i = RED_LIGHT; i <= RED_MAN; i++) { + lights[i]->set(LightStates[state][i]); + } +} + +void Pole::setWaitLight(bool pressed) { waitLight->set(pressed ? Light::ON : Light::OFF); } + +void Pole::update(const Hint &h) { + const WaitHint *waitHintPtr; + const LightHint *lightHintPtr; + + if ((waitHintPtr = dynamic_cast(&h)) != 0) { + setWaitLight(waitHintPtr->pressed); + } else if ((lightHintPtr = dynamic_cast(&h)) != 0) { + setTrafficLights(lightHintPtr->state); + } else { + // don't know what's changed, so update everything + setTrafficLights(myPelican.getState()); + setWaitLight(myPelican.isPressed()); + } +} diff --git a/cmat/SolutionEx51/Pole.h b/cmat/SolutionEx51/Pole.h new file mode 100644 index 0000000..06e79e0 --- /dev/null +++ b/cmat/SolutionEx51/Pole.h @@ -0,0 +1,29 @@ + + +#ifndef POLE_H +#define POLE_H + +#include "Light.h" +#include "Observer.h" +#include "Pelican.h" + +class Pole : public Observer { + public: + Pole(int x, int y, Pelican &p); + ~Pole(); + + void setTrafficLights(Pelican::PelicanState state); + void setWaitLight(bool pressed); + + void update(const Hint &); + + private: + Pelican &myPelican; + + enum LightName { RED_LIGHT, YELLOW_LIGHT, GREEN_LIGHT, GREEN_MAN, RED_MAN }; + + Light *lights[RED_MAN + 1]; + Light *waitLight; +}; + +#endif diff --git a/cmat/SolutionEx51/Subject.cpp b/cmat/SolutionEx51/Subject.cpp new file mode 100644 index 0000000..bb73802 --- /dev/null +++ b/cmat/SolutionEx51/Subject.cpp @@ -0,0 +1,12 @@ + + +#include "Subject.h" +#include "Observer.h" + +void Subject::attach(Observer &obs) { myObservers.insert(&obs); } + +void Subject::notify(const Hint &h) const { + for (ObsList::const_iterator iter = myObservers.begin(); iter != myObservers.end(); ++iter) { + (*iter)->update(h); + } +} diff --git a/cmat/SolutionEx51/Subject.h b/cmat/SolutionEx51/Subject.h new file mode 100644 index 0000000..46c2de8 --- /dev/null +++ b/cmat/SolutionEx51/Subject.h @@ -0,0 +1,27 @@ + + +#ifndef SUBJECT_H +#define SUBJECT_H + +class Observer; + +#include + +class Hint { + public: + virtual ~Hint() {} +}; + +class Subject { + public: + typedef std::set ObsList; + void attach(Observer &obs); + + protected: + void notify(const Hint &) const; + + private: + ObsList myObservers; +}; + +#endif diff --git a/cmat/SolutionEx51/Timer.cpp b/cmat/SolutionEx51/Timer.cpp new file mode 100644 index 0000000..9240bda --- /dev/null +++ b/cmat/SolutionEx51/Timer.cpp @@ -0,0 +1,23 @@ + + +#include "Timer.h" +#include "TimerSet.h" + +void Timer::timeoutRequest(int seconds) { timeToGo = seconds; } + +Timer::Timer() : timeToGo(-1) { TimerSet::Instance().addATimer(this); } + +void Timer::tick() { + if (isExpired()) { + doExpired(); + } +} + +bool Timer::isExpired() { + if (timeToGo > 0) { + if (--timeToGo == 0) { + return true; + } + } + return false; +} diff --git a/cmat/SolutionEx51/Timer.h b/cmat/SolutionEx51/Timer.h new file mode 100644 index 0000000..37d1ce9 --- /dev/null +++ b/cmat/SolutionEx51/Timer.h @@ -0,0 +1,32 @@ +// ====================================================== +// +// A general-purpose countdown timer +// To use this class, specialize it +// and override tick() +// +// ====================================================== + +#ifndef timer_H +#define timer_H + +#include + +class Timer { + public: + Timer(); + + void timeoutRequest(int seconds); + + // template method + void tick(); + + protected: + bool isExpired(); + + private: + virtual void doExpired() = 0; + + int timeToGo; +}; + +#endif diff --git a/cmat/SolutionEx51/TimerSet.cpp b/cmat/SolutionEx51/TimerSet.cpp new file mode 100644 index 0000000..0a06bd1 --- /dev/null +++ b/cmat/SolutionEx51/TimerSet.cpp @@ -0,0 +1,37 @@ +#include "TimerSet.h" +#include "Timer.h" +#include + +// Member functions + +TimerSet::TimerSet() + : previousTime(time(&previousTime)), pollingThread([this]() { poll10Hz(); }) // Exercise 5.1 start thread +{ + pollingThread.detach(); // let it die on its own, without join +} + +// Exercise 5.1 new function +void TimerSet::poll10Hz() { + std::chrono::milliseconds pause(100); + while (true) { + std::this_thread::sleep_for(pause); + pollAllTimers(); + } +} + +void TimerSet::addATimer(Timer *t) { timers.push_back(t); } + +void TimerSet::pollAllTimers() { + std::time_t timeNow; + if (time(&timeNow) > previousTime) { + previousTime = timeNow; + for (auto it = timers.begin(); it != timers.end(); it++) { + (*it)->tick(); + } + } +} + +TimerSet &TimerSet::Instance() { + static TimerSet pInstance; + return pInstance; +} diff --git a/cmat/SolutionEx51/TimerSet.h b/cmat/SolutionEx51/TimerSet.h new file mode 100644 index 0000000..1a027f3 --- /dev/null +++ b/cmat/SolutionEx51/TimerSet.h @@ -0,0 +1,33 @@ +#ifndef TIMERSET_H +#define TIMERSET_H + +#include +#include +#include + +class Timer; + +class TimerSet { + public: + void pollAllTimers(); + void addATimer(Timer *); + + private: + TimerSet(); + std::vector timers; + std::time_t previousTime; + + // Exercise 5.1 Threading two new members + std::thread pollingThread; + void poll10Hz(); + + // Meyer's Singleton + public: + static TimerSet &Instance(); + + private: + TimerSet(const TimerSet &); + TimerSet &operator=(const TimerSet &); +}; + +#endif diff --git a/cmat/SolutionEx51/main.cpp b/cmat/SolutionEx51/main.cpp new file mode 100644 index 0000000..08abe33 --- /dev/null +++ b/cmat/SolutionEx51/main.cpp @@ -0,0 +1,35 @@ + + +#include "Keyboard.h" +#include "Pelican.h" +#include "Pole.h" +#include "TimerSet.h" + +#include // provides toupper() + +int main() { + Keyboard kbd; + + Pelican thePelican; + Pole pole1(20, 0, thePelican); + Pole pole2(40, 0, thePelican); + + char c = 0; + + while (std::toupper(c) != 'Q') { // loop until 'Q' is pressed + + // Exercise 5.1 no longer needed to poll TimerSet from + // while (!kbd.isCharAvail()) + //{ + // TimerSet::Instance().pollAllTimers(); // no key press to process, poll the timers + //} + + c = kbd.getChar(); // get the character + if (c == ' ') { + // it's a space, so press the WAIT button + thePelican.press(); + } + } + + return 0; +} diff --git a/cmat/SolutionEx51Bonus2/CMakeLists.txt b/cmat/SolutionEx51Bonus2/CMakeLists.txt new file mode 100644 index 0000000..3d0ecb2 --- /dev/null +++ b/cmat/SolutionEx51Bonus2/CMakeLists.txt @@ -0,0 +1,13 @@ +# SolutionEx51Bonus2 + +cmat_add_exercise(SolutionEx51Bonus2 + GUI + SOURCES + Light.cpp + main.cpp + Pelican.cpp + Pole.cpp + Subject.cpp + Timer.cpp + TimerSet.cpp +) diff --git a/cmat/SolutionEx51Bonus2/Ex51.sln b/cmat/SolutionEx51Bonus2/Ex51.sln new file mode 100644 index 0000000..8f27b85 --- /dev/null +++ b/cmat/SolutionEx51Bonus2/Ex51.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ex51", "Ex51.vcxproj", "{AFB7826A-449B-436C-A7FC-4401601F082B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {AFB7826A-449B-436C-A7FC-4401601F082B}.Debug|Win32.ActiveCfg = Debug|Win32 + {AFB7826A-449B-436C-A7FC-4401601F082B}.Debug|Win32.Build.0 = Debug|Win32 + {AFB7826A-449B-436C-A7FC-4401601F082B}.Release|Win32.ActiveCfg = Release|Win32 + {AFB7826A-449B-436C-A7FC-4401601F082B}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/cmat/SolutionEx51Bonus2/Ex51.vcxproj b/cmat/SolutionEx51Bonus2/Ex51.vcxproj new file mode 100644 index 0000000..1c205d1 --- /dev/null +++ b/cmat/SolutionEx51Bonus2/Ex51.vcxproj @@ -0,0 +1,93 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {AFB7826A-449B-436C-A7FC-4401601F082B} + Ex51 + + + + Application + true + v140 + MultiByte + + + Application + false + v140 + true + MultiByte + + + + + + + + + + + + + + + Level3 + Disabled + true + C:\course\397\DOS_Unix; + + + true + Console + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cmat/SolutionEx51Bonus2/Ex51.vcxproj.filters b/cmat/SolutionEx51Bonus2/Ex51.vcxproj.filters new file mode 100644 index 0000000..a659e26 --- /dev/null +++ b/cmat/SolutionEx51Bonus2/Ex51.vcxproj.filters @@ -0,0 +1,74 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {075c2eca-b76b-43df-8022-827ab031c5e2} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + DOS_Unix + + + DOS_Unix + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + DOS_Unix + + + DOS_Unix + + + \ No newline at end of file diff --git a/cmat/SolutionEx51Bonus2/Ex51.vcxproj.user b/cmat/SolutionEx51Bonus2/Ex51.vcxproj.user new file mode 100644 index 0000000..2a22e69 --- /dev/null +++ b/cmat/SolutionEx51Bonus2/Ex51.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/cmat/SolutionEx51Bonus2/Light.cpp b/cmat/SolutionEx51Bonus2/Light.cpp new file mode 100644 index 0000000..e111c52 --- /dev/null +++ b/cmat/SolutionEx51Bonus2/Light.cpp @@ -0,0 +1,21 @@ + + +#include "Light.h" +#include "Pelican.h" +#include "Screen.h" +#include + +Light::Light(std::string name, int x, int y, int color) : x(x), y(y), c(color), name(name) {} + +Light::~Light() { + std::cout << "Deleting light (" << name << ", " << x << ", " << y << ", " << c << ")" + << "\n"; +} + +void Light::set(LightState newState) { + state = newState; + Screen::write(name.c_str(), x, y, state == FLASH ? (128 + c) : (state == OFF ? 0 : c)); + // 128 + color was used to make a character flash (but not any more) +} + +Light::LightState Light::get(void) { return state; } diff --git a/cmat/SolutionEx51Bonus2/Light.h b/cmat/SolutionEx51Bonus2/Light.h new file mode 100644 index 0000000..03adf9a --- /dev/null +++ b/cmat/SolutionEx51Bonus2/Light.h @@ -0,0 +1,30 @@ +// ====================================================== +// +// Represents a light, implemented as a string written +// to a console window +// +// ====================================================== + +#ifndef LIGHT_H +#define LIGHT_H + +#include + +class Light { + public: + Light(std::string name, int x, int y, int color); + ~Light(); + + enum LightState { ON, OFF, FLASH }; + + void set(LightState new_state); + LightState get(void); + + private: + int c; // light colour + int x, y; + std::string name; + LightState state; +}; + +#endif diff --git a/cmat/SolutionEx51Bonus2/Observer.h b/cmat/SolutionEx51Bonus2/Observer.h new file mode 100644 index 0000000..4c5dbf0 --- /dev/null +++ b/cmat/SolutionEx51Bonus2/Observer.h @@ -0,0 +1,13 @@ + + +#ifndef OBSERVER_H +#define OBSERVER_H + +#include "Subject.h" + +class Observer { + public: + virtual void update(const Hint &) = 0; +}; + +#endif diff --git a/cmat/SolutionEx51Bonus2/Pelican.cpp b/cmat/SolutionEx51Bonus2/Pelican.cpp new file mode 100644 index 0000000..a712e9f --- /dev/null +++ b/cmat/SolutionEx51Bonus2/Pelican.cpp @@ -0,0 +1,59 @@ + + +#include "Pelican.h" +#include "Pole.h" +#include "Timer.h" + +Pelican::Pelican() : pressed(false), RED_TIME(4), YELLOW_TIME(2), GREEN_TIME(3), FLASH_TIME(5), state(GREEN_IDLE) { + myTimer = new Timer([this] { timerExpired(); }); +} + +void Pelican::press(void) { + if (state == GREEN_IDLE) { + state = YELLOW_STATE; + myTimer->timeoutRequest(YELLOW_TIME); + pressed = true; + + notify(WaitHint(pressed)); + notify(LightHint(state)); + } else if (state != RED_STATE) { + pressed = true; + notify(WaitHint(pressed)); + } +} + +void Pelican::timerExpired(void) { + switch (state) { + case RED_STATE: + state = YELLOW_FLASHING; + myTimer->timeoutRequest(FLASH_TIME); + break; + + case YELLOW_FLASHING: + state = GREEN_TIMING; + myTimer->timeoutRequest(GREEN_TIME); + break; + + case GREEN_TIMING: + if (pressed) { + state = YELLOW_STATE; + myTimer->timeoutRequest(YELLOW_TIME); + } else { + state = GREEN_IDLE; + } + break; + + case GREEN_IDLE: + // should never happen + break; + + case YELLOW_STATE: + state = RED_STATE; + pressed = false; + notify(WaitHint(pressed)); + myTimer->timeoutRequest(RED_TIME); + break; + } + + notify(LightHint(state)); +} diff --git a/cmat/SolutionEx51Bonus2/Pelican.h b/cmat/SolutionEx51Bonus2/Pelican.h new file mode 100644 index 0000000..ab3ad46 --- /dev/null +++ b/cmat/SolutionEx51Bonus2/Pelican.h @@ -0,0 +1,64 @@ +// ====================================================== +// +// Represents a Pelican crossing +// +// ====================================================== + +#ifndef PELICAN_H +#define PELICAN_H + +#include "Subject.h" +#include "Timer.h" + +class Pelican : public Subject { + public: + Pelican(); + + // call when the WAIT button has been pressed + void press(void); + + // states that a Pelican can be in + enum PelicanState { RED_STATE, YELLOW_FLASHING, GREEN_TIMING, GREEN_IDLE, YELLOW_STATE }; + + bool isPressed() const { return pressed; } + PelicanState getState() const { return state; } + + private: + // state that this Pelican is in + PelicanState state; + + // called by PeleicanTimer when the lights need to change + void timerExpired(void); + + const unsigned int RED_TIME; + const unsigned int YELLOW_TIME; + const unsigned int GREEN_TIME; + const unsigned int FLASH_TIME; + + // indicates whether the WAIT light should be on + bool pressed; + + // Timer that indicates when the lights should change + Timer *myTimer; + + private: + // prevent general use of copy ctor and operator= + Pelican(const Pelican &); + Pelican &operator=(const Pelican &); +}; + +class LightHint : public Hint { + public: + LightHint(Pelican::PelicanState s) : state(s) {} + + Pelican::PelicanState state; +}; + +class WaitHint : public Hint { + public: + WaitHint(bool p) : pressed(p) {} + + bool pressed; +}; + +#endif diff --git a/cmat/SolutionEx51Bonus2/Pole.cpp b/cmat/SolutionEx51Bonus2/Pole.cpp new file mode 100644 index 0000000..9da08c0 --- /dev/null +++ b/cmat/SolutionEx51Bonus2/Pole.cpp @@ -0,0 +1,78 @@ +#include "Pole.h" +#include "Screen.h" + +Pole::Pole(int x, int y, Pelican &p) : waitLight(new Light("WAIT", x + 6, y + 12, Screen::WHITE)), myPelican(p) { + myPelican.attach(*this); + + using namespace Screen; // we will discuss namespaces in the course + + lights[RED_LIGHT] = new Light("*", x + 11, y + 3, RED); + lights[RED_MAN] = new Light("*<-=", x + 6, y + 4, RED); + lights[YELLOW_LIGHT] = new Light("*", x + 11, y + 5, YELLOW); + lights[GREEN_LIGHT] = new Light("*", x + 11, y + 7, GREEN); + lights[GREEN_MAN] = new Light("*|-<", x + 6, y + 7, GREEN); + + write(" _____ ", x, ++y, GRAY); + write(" /___ /| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" | |/| ", x, ++y, GRAY); + write(" |____| | ", x, ++y, GRAY); + write(" | |/| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" |____|/ ", x, ++y, GRAY); + write(" _||__ ", x, ++y, GRAY); + write(" /___ /| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" |____|/ ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write("========||===========", x, ++y, GRAY); + write(" / || / ", x, ++y, GRAY); + write("_ /_________ /_ ", x, ++y, GRAY); + write("/ / ", x, ++y, GRAY); + + update(Hint()); +} + +Pole::~Pole() { + for (int i = 0; i < sizeof lights / sizeof(lights[0]); ++i) + delete lights[i]; + delete waitLight; +} + +void Pole::setTrafficLights(Pelican::PelicanState state) { + static const Light::LightState LightStates[Pelican::YELLOW_STATE + 1][RED_MAN + 1] = { + // red yellow green green man red man + {Light::ON, Light::OFF, Light::OFF, Light::ON, Light::OFF}, // red + {Light::OFF, Light::FLASH, Light::OFF, Light::FLASH, Light::OFF}, // y flash + {Light::OFF, Light::OFF, Light::ON, Light::OFF, Light::ON}, // g time + {Light::OFF, Light::OFF, Light::ON, Light::OFF, Light::ON}, // g idle + {Light::OFF, Light::ON, Light::OFF, Light::OFF, Light::ON} // yellow + }; + + for (int i = RED_LIGHT; i <= RED_MAN; i++) { + lights[i]->set(LightStates[state][i]); + } +} + +void Pole::setWaitLight(bool pressed) { waitLight->set(pressed ? Light::ON : Light::OFF); } + +void Pole::update(const Hint &h) { + const WaitHint *waitHintPtr; + const LightHint *lightHintPtr; + + if ((waitHintPtr = dynamic_cast(&h)) != 0) { + setWaitLight(waitHintPtr->pressed); + } else if ((lightHintPtr = dynamic_cast(&h)) != 0) { + setTrafficLights(lightHintPtr->state); + } else { + // don't know what's changed, so update everything + setTrafficLights(myPelican.getState()); + setWaitLight(myPelican.isPressed()); + } +} diff --git a/cmat/SolutionEx51Bonus2/Pole.h b/cmat/SolutionEx51Bonus2/Pole.h new file mode 100644 index 0000000..3154771 --- /dev/null +++ b/cmat/SolutionEx51Bonus2/Pole.h @@ -0,0 +1,28 @@ + +#ifndef POLE_H +#define POLE_H + +#include "Light.h" +#include "Observer.h" +#include "Pelican.h" + +class Pole : public Observer { + public: + Pole(int x, int y, Pelican &p); + ~Pole(); + + void setTrafficLights(Pelican::PelicanState state); + void setWaitLight(bool pressed); + + void update(const Hint &); + + private: + Pelican &myPelican; + + enum LightName { RED_LIGHT, YELLOW_LIGHT, GREEN_LIGHT, GREEN_MAN, RED_MAN }; + + Light *lights[RED_MAN + 1]; + Light *waitLight; +}; + +#endif diff --git a/cmat/SolutionEx51Bonus2/Subject.cpp b/cmat/SolutionEx51Bonus2/Subject.cpp new file mode 100644 index 0000000..1ab7de0 --- /dev/null +++ b/cmat/SolutionEx51Bonus2/Subject.cpp @@ -0,0 +1,11 @@ + +#include "Subject.h" +#include "Observer.h" + +void Subject::attach(Observer &obs) { myObservers.insert(&obs); } + +void Subject::notify(const Hint &h) const { + for (ObsList::const_iterator iter = myObservers.begin(); iter != myObservers.end(); ++iter) { + (*iter)->update(h); + } +} diff --git a/cmat/SolutionEx51Bonus2/Subject.h b/cmat/SolutionEx51Bonus2/Subject.h new file mode 100644 index 0000000..46c2de8 --- /dev/null +++ b/cmat/SolutionEx51Bonus2/Subject.h @@ -0,0 +1,27 @@ + + +#ifndef SUBJECT_H +#define SUBJECT_H + +class Observer; + +#include + +class Hint { + public: + virtual ~Hint() {} +}; + +class Subject { + public: + typedef std::set ObsList; + void attach(Observer &obs); + + protected: + void notify(const Hint &) const; + + private: + ObsList myObservers; +}; + +#endif diff --git a/cmat/SolutionEx51Bonus2/Timer.cpp b/cmat/SolutionEx51Bonus2/Timer.cpp new file mode 100644 index 0000000..36d0627 --- /dev/null +++ b/cmat/SolutionEx51Bonus2/Timer.cpp @@ -0,0 +1,25 @@ + + +#include "Timer.h" +#include "TimerSet.h" + +void Timer::timeoutRequest(int seconds) { timeToGo = seconds; } + +Timer::Timer(std::function action) : timeToGo(-1), doExpired(action) { + TimerSet::Instance().addATimer(this); +} + +void Timer::tick() { + if (isExpired()) { + doExpired(); + } +} + +bool Timer::isExpired() { + if (timeToGo > 0) { + if (--timeToGo == 0) { + return true; + } + } + return false; +} diff --git a/cmat/SolutionEx51Bonus2/Timer.h b/cmat/SolutionEx51Bonus2/Timer.h new file mode 100644 index 0000000..8d5e8a4 --- /dev/null +++ b/cmat/SolutionEx51Bonus2/Timer.h @@ -0,0 +1,33 @@ +// ====================================================== +// +// A general-purpose countdown timer +// To use this class, specialize it +// and override tick() +// +// ====================================================== + +#ifndef timer_H +#define timer_H + +#include +#include + +class Timer { + public: + Timer(std::function action); + + void timeoutRequest(int seconds); + + // template method + void tick(); + + protected: + bool isExpired(); + + private: + std::function doExpired; + + int timeToGo; +}; + +#endif diff --git a/cmat/SolutionEx51Bonus2/TimerSet.cpp b/cmat/SolutionEx51Bonus2/TimerSet.cpp new file mode 100644 index 0000000..44d6f04 --- /dev/null +++ b/cmat/SolutionEx51Bonus2/TimerSet.cpp @@ -0,0 +1,36 @@ +#include "TimerSet.h" +#include "Timer.h" +#include + + +TimerSet::TimerSet() + : previousTime(time(&previousTime)), pollingThread([this]() { poll10Hz(); }) // Exercise 5.1 start thread +{ + pollingThread.detach(); // let it die on its own, without join +} + +// Exercise 5.1 new function +void TimerSet::poll10Hz() { + std::chrono::duration pause(100); + while (true) { + std::this_thread::sleep_for(pause); + pollAllTimers(); + } +} + +void TimerSet::addATimer(Timer *t) { timers.push_back(t); } + +void TimerSet::pollAllTimers() { + std::time_t timeNow; + if (time(&timeNow) > previousTime) { + previousTime = timeNow; + for (auto it = timers.begin(); it != timers.end(); it++) { + (*it)->tick(); + } + } +} + +TimerSet &TimerSet::Instance() { + static TimerSet pInstance; + return pInstance; +} diff --git a/cmat/SolutionEx51Bonus2/TimerSet.h b/cmat/SolutionEx51Bonus2/TimerSet.h new file mode 100644 index 0000000..1a027f3 --- /dev/null +++ b/cmat/SolutionEx51Bonus2/TimerSet.h @@ -0,0 +1,33 @@ +#ifndef TIMERSET_H +#define TIMERSET_H + +#include +#include +#include + +class Timer; + +class TimerSet { + public: + void pollAllTimers(); + void addATimer(Timer *); + + private: + TimerSet(); + std::vector timers; + std::time_t previousTime; + + // Exercise 5.1 Threading two new members + std::thread pollingThread; + void poll10Hz(); + + // Meyer's Singleton + public: + static TimerSet &Instance(); + + private: + TimerSet(const TimerSet &); + TimerSet &operator=(const TimerSet &); +}; + +#endif diff --git a/cmat/SolutionEx51Bonus2/main.cpp b/cmat/SolutionEx51Bonus2/main.cpp new file mode 100644 index 0000000..141a04e --- /dev/null +++ b/cmat/SolutionEx51Bonus2/main.cpp @@ -0,0 +1,35 @@ + + +#include "Keyboard.h" +#include "Pelican.h" +#include "Pole.h" +#include "TimerSet.h" + +#include // provides toupper() + +int main() { + Keyboard kbd; + + Pelican thePelican; + Pole pole1(20, 0, thePelican); + Pole pole2(40, 0, thePelican); + + char c = 0; + + while (std::toupper(c) != 'Q') { // loop until 'Q' is pressed + + // Exercise 5.1 no longer needed to poll TimerSet from + // while (!kbd.isCharAvail()) + //{ + // TimerSet::Instance()->pollAllTimers(); // no key press to process, poll the timers + //} + + c = kbd.getChar(); // get the character + if (c == ' ') { + // it's a space, so press the WAIT button + thePelican.press(); + } + } + + return 0; +} diff --git a/cmat/SolutionEx61InterimSolution/CMakeLists.txt b/cmat/SolutionEx61InterimSolution/CMakeLists.txt new file mode 100644 index 0000000..c47cf9f --- /dev/null +++ b/cmat/SolutionEx61InterimSolution/CMakeLists.txt @@ -0,0 +1,9 @@ +# SolutionEx61InterimSolution + +cmat_add_exercise(SolutionEx61InterimSolution + SOURCES + main.cpp + Person.cpp + PersonException.cpp + YoungPerson.cpp +) diff --git a/cmat/SolutionEx61InterimSolution/Ex61.sln b/cmat/SolutionEx61InterimSolution/Ex61.sln new file mode 100644 index 0000000..b9d83cb --- /dev/null +++ b/cmat/SolutionEx61InterimSolution/Ex61.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ex61", "Ex61.vcxproj", "{71B1E667-58E2-4C71-A6A3-73F9502928D7}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {71B1E667-58E2-4C71-A6A3-73F9502928D7}.Debug|Win32.ActiveCfg = Debug|Win32 + {71B1E667-58E2-4C71-A6A3-73F9502928D7}.Debug|Win32.Build.0 = Debug|Win32 + {71B1E667-58E2-4C71-A6A3-73F9502928D7}.Release|Win32.ActiveCfg = Release|Win32 + {71B1E667-58E2-4C71-A6A3-73F9502928D7}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/cmat/SolutionEx61InterimSolution/Ex61.suo b/cmat/SolutionEx61InterimSolution/Ex61.suo new file mode 100644 index 0000000..364c892 Binary files /dev/null and b/cmat/SolutionEx61InterimSolution/Ex61.suo differ diff --git a/cmat/SolutionEx61InterimSolution/Ex61.vcproj b/cmat/SolutionEx61InterimSolution/Ex61.vcproj new file mode 100644 index 0000000..b3ad81a --- /dev/null +++ b/cmat/SolutionEx61InterimSolution/Ex61.vcproj @@ -0,0 +1,121 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cmat/SolutionEx61InterimSolution/Ex61.vcxproj b/cmat/SolutionEx61InterimSolution/Ex61.vcxproj new file mode 100644 index 0000000..f87347e --- /dev/null +++ b/cmat/SolutionEx61InterimSolution/Ex61.vcxproj @@ -0,0 +1,92 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {71B1E667-58E2-4C71-A6A3-73F9502928D7} + ManagedCProj + + + + Application + MultiByte + OldSyntax + v140 + + + Application + MultiByte + false + v140 + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + Debug\ + Debug\ + true + Release\ + Release\ + false + + + + Disabled + WIN32;_DEBUG;%(PreprocessorDefinitions) + false + Default + MultiThreadedDebugDLL + Level3 + ProgramDatabase + + + $(OutDir)Ex61.exe + true + Console + + + + + MaxSpeed + OnlyExplicitInline + WIN32;NDEBUG;%(PreprocessorDefinitions) + false + Level3 + + + $(OutDir)Ex61.exe + true + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cmat/SolutionEx61InterimSolution/Ex61.vcxproj.filters b/cmat/SolutionEx61InterimSolution/Ex61.vcxproj.filters new file mode 100644 index 0000000..a9ce652 --- /dev/null +++ b/cmat/SolutionEx61InterimSolution/Ex61.vcxproj.filters @@ -0,0 +1,38 @@ + + + + + {216ad10e-da13-4e74-bd7b-3d1fd4babd53} + cpp;c;cxx;def;odl;idl;hpj;bat;asm + + + {57ab839f-9334-4b02-aa8e-af153d217a12} + h;hpp;hxx;hm;inl;inc + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/cmat/SolutionEx61InterimSolution/Ex61.vcxproj.user b/cmat/SolutionEx61InterimSolution/Ex61.vcxproj.user new file mode 100644 index 0000000..695b5c7 --- /dev/null +++ b/cmat/SolutionEx61InterimSolution/Ex61.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cmat/SolutionEx61InterimSolution/Person.cpp b/cmat/SolutionEx61InterimSolution/Person.cpp new file mode 100644 index 0000000..5b6d36c --- /dev/null +++ b/cmat/SolutionEx61InterimSolution/Person.cpp @@ -0,0 +1,37 @@ +#include "Person.h" +#include "PersonException.h" +#include "YoungPerson.h" +#include + +using std::cout; + +Person::Person(std::string name, int age) : name(name), age(age) { + if (age < 0) { + throw PersonException("negative age"); + } + + cout << "Person ctor\n"; + Count++; +} + +Person::Person(const Person &) { + cout << "Copy ctor\n"; + Count++; +} + +Person::~Person() { + cout << "Dtor\n"; + Count--; +} + +void Person::setSalary(int sal) { + if (sal < 0) { + throw PersonException("negative salary"); + } + + salary = sal; +} + +int Person::GetCount() { return Count; } + +int Person::Count = 0; diff --git a/cmat/SolutionEx61InterimSolution/Person.h b/cmat/SolutionEx61InterimSolution/Person.h new file mode 100644 index 0000000..e043203 --- /dev/null +++ b/cmat/SolutionEx61InterimSolution/Person.h @@ -0,0 +1,28 @@ + + +#ifndef Person_h +#define Person_h + +#include + +class Person { + public: + virtual ~Person(); + + static int GetCount(); + + Person(std::string name, int age); + + void setSalary(int sal); + + private: + Person(const Person &); + + std::string name; + int age; + int salary; + + static int Count; +}; + +#endif \ No newline at end of file diff --git a/cmat/SolutionEx61InterimSolution/PersonException.cpp b/cmat/SolutionEx61InterimSolution/PersonException.cpp new file mode 100644 index 0000000..bef2a5e --- /dev/null +++ b/cmat/SolutionEx61InterimSolution/PersonException.cpp @@ -0,0 +1,5 @@ +#include "PersonException.h" + +PersonException::PersonException(std::string m) : msg(m) {} + +const char *PersonException::what() const throw() { return msg.c_str(); } \ No newline at end of file diff --git a/cmat/SolutionEx61InterimSolution/PersonException.h b/cmat/SolutionEx61InterimSolution/PersonException.h new file mode 100644 index 0000000..d9e6b06 --- /dev/null +++ b/cmat/SolutionEx61InterimSolution/PersonException.h @@ -0,0 +1,16 @@ +#ifndef Person_Exception_h +#define Person_Exception_h + +#include +#include + +class PersonException : public std::exception { + public: + PersonException(std::string m); + const char *what() const throw(); + + private: + std::string msg; +}; + +#endif diff --git a/cmat/SolutionEx61InterimSolution/YoungPerson.cpp b/cmat/SolutionEx61InterimSolution/YoungPerson.cpp new file mode 100644 index 0000000..fbd4280 --- /dev/null +++ b/cmat/SolutionEx61InterimSolution/YoungPerson.cpp @@ -0,0 +1,5 @@ +#include "YoungPerson.h" + +#include + +YoungPerson::YoungPerson(std::string name, int age) : Person(name, age) { std::cout << "YoungPerson ctor\n"; } diff --git a/cmat/SolutionEx61InterimSolution/YoungPerson.h b/cmat/SolutionEx61InterimSolution/YoungPerson.h new file mode 100644 index 0000000..4f59191 --- /dev/null +++ b/cmat/SolutionEx61InterimSolution/YoungPerson.h @@ -0,0 +1,13 @@ + + +#ifndef YoungPerson_h +#define YoungPerson_h + +#include "Person.h" + +class YoungPerson : public Person { + public: + YoungPerson(std::string name, int age); +}; + +#endif \ No newline at end of file diff --git a/cmat/SolutionEx61InterimSolution/main.cpp b/cmat/SolutionEx61InterimSolution/main.cpp new file mode 100644 index 0000000..78c0c43 --- /dev/null +++ b/cmat/SolutionEx61InterimSolution/main.cpp @@ -0,0 +1,94 @@ + +#include +#include +#include + +#include "Person.h" + +#include "PersonException.h" +#include + +using std::cin; +using std::cout; +using std::string; +using std::exception; + +int main() { + std::vector people; + Person *personPtr; + + string namePrompt = "Enter name: "; + string name; + string agePrompt = "Enter age: "; + int age; + string salaryPrompt = "Enter salary: "; + int salary; + + cout << namePrompt; + cin >> name; + + while (name != "q") { + // Set 'personPtr' to nullptr at the beginning + // of the loop to tell us whether a Person + // object has been created during this pass + // through the loop + personPtr = nullptr; + + try { + cout << agePrompt; + cin >> age; + + if (!cin) { + cin.clear(); + string dummy; + cin >> dummy; + throw PersonException("invalid age"); + } + + personPtr = new Person(name, age); + + cout << salaryPrompt; + cin >> salary; + if (!cin) { + cin.clear(); + string dummy; + cin >> dummy; + throw PersonException("invalid salary"); + } + + personPtr->setSalary(salary); + + // We only get here if no exception has been + // raised, that is, both 'age' and 'salary' + // are valid and non-negative. + people.push_back(personPtr); + } + + catch (exception &e) { + cout << "PersonException thrown: " << e.what() << '\n'; + + // If an exception was raised, then the current object + // is invalid and should be deleted. Recall that: + // 1. delete on a null pointer is harmless (does nothing) + // 2. delete on a non-null pointer causes that pointer + // to be set to an undefined value + delete personPtr; + // Since 'personPtr' may now be undefined, set it to null. + personPtr = nullptr; + } + + cout << "There are " << Person::GetCount() << " Person(s), " << people.size() << " in vector\n"; + + cout << namePrompt; + cin >> name; + } + + // delete all the person(s) in the vector + for (std::vector::iterator iter = people.begin(); iter != people.end(); ++iter) { + delete *iter; + } + + cout << "There are " << Person::GetCount() << " Person(s) left dangling\n"; + + return 0; +} diff --git a/cmat/SolutionEx61Part1/CMakeLists.txt b/cmat/SolutionEx61Part1/CMakeLists.txt new file mode 100644 index 0000000..4c08d40 --- /dev/null +++ b/cmat/SolutionEx61Part1/CMakeLists.txt @@ -0,0 +1,9 @@ +# SolutionEx61Part1 + +cmat_add_exercise(SolutionEx61Part1 + SOURCES + main.cpp + Person.cpp + PersonException.cpp + YoungPerson.cpp +) diff --git a/cmat/SolutionEx61Part1/Ex61.sln b/cmat/SolutionEx61Part1/Ex61.sln new file mode 100644 index 0000000..b9d83cb --- /dev/null +++ b/cmat/SolutionEx61Part1/Ex61.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ex61", "Ex61.vcxproj", "{71B1E667-58E2-4C71-A6A3-73F9502928D7}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {71B1E667-58E2-4C71-A6A3-73F9502928D7}.Debug|Win32.ActiveCfg = Debug|Win32 + {71B1E667-58E2-4C71-A6A3-73F9502928D7}.Debug|Win32.Build.0 = Debug|Win32 + {71B1E667-58E2-4C71-A6A3-73F9502928D7}.Release|Win32.ActiveCfg = Release|Win32 + {71B1E667-58E2-4C71-A6A3-73F9502928D7}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/cmat/SolutionEx61Part1/Ex61.suo b/cmat/SolutionEx61Part1/Ex61.suo new file mode 100644 index 0000000..364c892 Binary files /dev/null and b/cmat/SolutionEx61Part1/Ex61.suo differ diff --git a/cmat/SolutionEx61Part1/Ex61.vcproj b/cmat/SolutionEx61Part1/Ex61.vcproj new file mode 100644 index 0000000..b3ad81a --- /dev/null +++ b/cmat/SolutionEx61Part1/Ex61.vcproj @@ -0,0 +1,121 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cmat/SolutionEx61Part1/Ex61.vcxproj b/cmat/SolutionEx61Part1/Ex61.vcxproj new file mode 100644 index 0000000..f87347e --- /dev/null +++ b/cmat/SolutionEx61Part1/Ex61.vcxproj @@ -0,0 +1,92 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {71B1E667-58E2-4C71-A6A3-73F9502928D7} + ManagedCProj + + + + Application + MultiByte + OldSyntax + v140 + + + Application + MultiByte + false + v140 + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + Debug\ + Debug\ + true + Release\ + Release\ + false + + + + Disabled + WIN32;_DEBUG;%(PreprocessorDefinitions) + false + Default + MultiThreadedDebugDLL + Level3 + ProgramDatabase + + + $(OutDir)Ex61.exe + true + Console + + + + + MaxSpeed + OnlyExplicitInline + WIN32;NDEBUG;%(PreprocessorDefinitions) + false + Level3 + + + $(OutDir)Ex61.exe + true + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cmat/SolutionEx61Part1/Ex61.vcxproj.filters b/cmat/SolutionEx61Part1/Ex61.vcxproj.filters new file mode 100644 index 0000000..a9ce652 --- /dev/null +++ b/cmat/SolutionEx61Part1/Ex61.vcxproj.filters @@ -0,0 +1,38 @@ + + + + + {216ad10e-da13-4e74-bd7b-3d1fd4babd53} + cpp;c;cxx;def;odl;idl;hpj;bat;asm + + + {57ab839f-9334-4b02-aa8e-af153d217a12} + h;hpp;hxx;hm;inl;inc + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/cmat/SolutionEx61Part1/Ex61.vcxproj.user b/cmat/SolutionEx61Part1/Ex61.vcxproj.user new file mode 100644 index 0000000..695b5c7 --- /dev/null +++ b/cmat/SolutionEx61Part1/Ex61.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cmat/SolutionEx61Part1/Person.cpp b/cmat/SolutionEx61Part1/Person.cpp new file mode 100644 index 0000000..5b6d36c --- /dev/null +++ b/cmat/SolutionEx61Part1/Person.cpp @@ -0,0 +1,37 @@ +#include "Person.h" +#include "PersonException.h" +#include "YoungPerson.h" +#include + +using std::cout; + +Person::Person(std::string name, int age) : name(name), age(age) { + if (age < 0) { + throw PersonException("negative age"); + } + + cout << "Person ctor\n"; + Count++; +} + +Person::Person(const Person &) { + cout << "Copy ctor\n"; + Count++; +} + +Person::~Person() { + cout << "Dtor\n"; + Count--; +} + +void Person::setSalary(int sal) { + if (sal < 0) { + throw PersonException("negative salary"); + } + + salary = sal; +} + +int Person::GetCount() { return Count; } + +int Person::Count = 0; diff --git a/cmat/SolutionEx61Part1/Person.h b/cmat/SolutionEx61Part1/Person.h new file mode 100644 index 0000000..e043203 --- /dev/null +++ b/cmat/SolutionEx61Part1/Person.h @@ -0,0 +1,28 @@ + + +#ifndef Person_h +#define Person_h + +#include + +class Person { + public: + virtual ~Person(); + + static int GetCount(); + + Person(std::string name, int age); + + void setSalary(int sal); + + private: + Person(const Person &); + + std::string name; + int age; + int salary; + + static int Count; +}; + +#endif \ No newline at end of file diff --git a/cmat/SolutionEx61Part1/PersonException.cpp b/cmat/SolutionEx61Part1/PersonException.cpp new file mode 100644 index 0000000..bef2a5e --- /dev/null +++ b/cmat/SolutionEx61Part1/PersonException.cpp @@ -0,0 +1,5 @@ +#include "PersonException.h" + +PersonException::PersonException(std::string m) : msg(m) {} + +const char *PersonException::what() const throw() { return msg.c_str(); } \ No newline at end of file diff --git a/cmat/SolutionEx61Part1/PersonException.h b/cmat/SolutionEx61Part1/PersonException.h new file mode 100644 index 0000000..d9e6b06 --- /dev/null +++ b/cmat/SolutionEx61Part1/PersonException.h @@ -0,0 +1,16 @@ +#ifndef Person_Exception_h +#define Person_Exception_h + +#include +#include + +class PersonException : public std::exception { + public: + PersonException(std::string m); + const char *what() const throw(); + + private: + std::string msg; +}; + +#endif diff --git a/cmat/SolutionEx61Part1/YoungPerson.cpp b/cmat/SolutionEx61Part1/YoungPerson.cpp new file mode 100644 index 0000000..fbd4280 --- /dev/null +++ b/cmat/SolutionEx61Part1/YoungPerson.cpp @@ -0,0 +1,5 @@ +#include "YoungPerson.h" + +#include + +YoungPerson::YoungPerson(std::string name, int age) : Person(name, age) { std::cout << "YoungPerson ctor\n"; } diff --git a/cmat/SolutionEx61Part1/YoungPerson.h b/cmat/SolutionEx61Part1/YoungPerson.h new file mode 100644 index 0000000..4f59191 --- /dev/null +++ b/cmat/SolutionEx61Part1/YoungPerson.h @@ -0,0 +1,13 @@ + + +#ifndef YoungPerson_h +#define YoungPerson_h + +#include "Person.h" + +class YoungPerson : public Person { + public: + YoungPerson(std::string name, int age); +}; + +#endif \ No newline at end of file diff --git a/cmat/SolutionEx61Part1/main.cpp b/cmat/SolutionEx61Part1/main.cpp new file mode 100644 index 0000000..fe3b7be --- /dev/null +++ b/cmat/SolutionEx61Part1/main.cpp @@ -0,0 +1,86 @@ + +#include +#include +#include + +#include "Person.h" + +#include "PersonException.h" +#include + +#include "memory" + +using std::cin; +using std::cout; +using std::string; +using std::exception; + +int main() { + { // start of extra scope to show destuctor of the vector being called at end-of-scope + + // std::vector people; + std::vector> people; + + string namePrompt = "Enter name: "; + string name; + string agePrompt = "Enter age: "; + int age; + string salaryPrompt = "Enter salary: "; + int salary; + + cout << namePrompt; + cin >> name; + + while (name != "q") { + try { + cout << agePrompt; + cin >> age; + + if (!cin) { + cin.clear(); + string dummy; + cin >> dummy; + throw PersonException("invalid age"); + } + + // Person* personPtr = new Person(name, age); + std::shared_ptr personPtr(new Person(name, age)); + + cout << salaryPrompt; + cin >> salary; + if (!cin) { + cin.clear(); + string dummy; + cin >> dummy; + throw PersonException("invalid salary"); + } + + personPtr->setSalary(salary); + + people.push_back(personPtr); + } + + catch (exception &e) { + cout << "PersonException thrown: " << e.what() << '\n'; + } + + cout << "There are " << Person::GetCount() << " Person(s), " << people.size() << " in vector\n"; + + cout << namePrompt; + cin >> name; + } + + // delete all the person(s) in the vector + // for(std::vector::iterator iter=people.begin(); iter != people.end(); ++iter) + // { + // delete *iter; + // } + + // people.clear(); + + } // end-of-scope: destructor of vector called here + + cout << "There are " << Person::GetCount() << " Person(s) left dangling\n"; + + return 0; +} diff --git a/cmat/SolutionEx61Part2/CMakeLists.txt b/cmat/SolutionEx61Part2/CMakeLists.txt new file mode 100644 index 0000000..6cae3f0 --- /dev/null +++ b/cmat/SolutionEx61Part2/CMakeLists.txt @@ -0,0 +1,9 @@ +# SolutionEx61Part2 + +cmat_add_exercise(SolutionEx61Part2 + SOURCES + main.cpp + Person.cpp + PersonException.cpp + YoungPerson.cpp +) diff --git a/cmat/SolutionEx61Part2/Ex61.sln b/cmat/SolutionEx61Part2/Ex61.sln new file mode 100644 index 0000000..b9d83cb --- /dev/null +++ b/cmat/SolutionEx61Part2/Ex61.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ex61", "Ex61.vcxproj", "{71B1E667-58E2-4C71-A6A3-73F9502928D7}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {71B1E667-58E2-4C71-A6A3-73F9502928D7}.Debug|Win32.ActiveCfg = Debug|Win32 + {71B1E667-58E2-4C71-A6A3-73F9502928D7}.Debug|Win32.Build.0 = Debug|Win32 + {71B1E667-58E2-4C71-A6A3-73F9502928D7}.Release|Win32.ActiveCfg = Release|Win32 + {71B1E667-58E2-4C71-A6A3-73F9502928D7}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/cmat/SolutionEx61Part2/Ex61.suo b/cmat/SolutionEx61Part2/Ex61.suo new file mode 100644 index 0000000..364c892 Binary files /dev/null and b/cmat/SolutionEx61Part2/Ex61.suo differ diff --git a/cmat/SolutionEx61Part2/Ex61.vcproj b/cmat/SolutionEx61Part2/Ex61.vcproj new file mode 100644 index 0000000..b3ad81a --- /dev/null +++ b/cmat/SolutionEx61Part2/Ex61.vcproj @@ -0,0 +1,121 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cmat/SolutionEx61Part2/Ex61.vcxproj b/cmat/SolutionEx61Part2/Ex61.vcxproj new file mode 100644 index 0000000..f87347e --- /dev/null +++ b/cmat/SolutionEx61Part2/Ex61.vcxproj @@ -0,0 +1,92 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {71B1E667-58E2-4C71-A6A3-73F9502928D7} + ManagedCProj + + + + Application + MultiByte + OldSyntax + v140 + + + Application + MultiByte + false + v140 + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + Debug\ + Debug\ + true + Release\ + Release\ + false + + + + Disabled + WIN32;_DEBUG;%(PreprocessorDefinitions) + false + Default + MultiThreadedDebugDLL + Level3 + ProgramDatabase + + + $(OutDir)Ex61.exe + true + Console + + + + + MaxSpeed + OnlyExplicitInline + WIN32;NDEBUG;%(PreprocessorDefinitions) + false + Level3 + + + $(OutDir)Ex61.exe + true + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cmat/SolutionEx61Part2/Ex61.vcxproj.filters b/cmat/SolutionEx61Part2/Ex61.vcxproj.filters new file mode 100644 index 0000000..a9ce652 --- /dev/null +++ b/cmat/SolutionEx61Part2/Ex61.vcxproj.filters @@ -0,0 +1,38 @@ + + + + + {216ad10e-da13-4e74-bd7b-3d1fd4babd53} + cpp;c;cxx;def;odl;idl;hpj;bat;asm + + + {57ab839f-9334-4b02-aa8e-af153d217a12} + h;hpp;hxx;hm;inl;inc + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/cmat/SolutionEx61Part2/Ex61.vcxproj.user b/cmat/SolutionEx61Part2/Ex61.vcxproj.user new file mode 100644 index 0000000..695b5c7 --- /dev/null +++ b/cmat/SolutionEx61Part2/Ex61.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cmat/SolutionEx61Part2/Person.cpp b/cmat/SolutionEx61Part2/Person.cpp new file mode 100644 index 0000000..d01e3a9 --- /dev/null +++ b/cmat/SolutionEx61Part2/Person.cpp @@ -0,0 +1,41 @@ +#include "Person.h" +#include "PersonException.h" +#include "YoungPerson.h" +#include + +using std::cout; + +Person::Person(std::string name, int age) : name(name), age(age) { + if (age < 0) { + throw PersonException("negative age"); + } + + cout << "Person ctor\n"; + Count++; +} + +Person::Person(const Person &) { + cout << "Copy ctor\n"; + Count++; +} + +Person::~Person() { + cout << "Person dtor\n"; + Count--; +} + +void Person::setSalary(int sal) { + if (sal < 0) { + throw PersonException("negative salary"); + } + + salary = sal; +} + +int Person::GetCount() { return Count; } + +std::shared_ptr Person::GetPerson(std::string name, int age) { + return age < 18 ? std::make_shared(name, age) : std::make_shared(name, age); +} + +int Person::Count = 0; diff --git a/cmat/SolutionEx61Part2/Person.h b/cmat/SolutionEx61Part2/Person.h new file mode 100644 index 0000000..63712c1 --- /dev/null +++ b/cmat/SolutionEx61Part2/Person.h @@ -0,0 +1,30 @@ + +#ifndef Person_h +#define Person_h + +#include +#include + +class Person { + public: + virtual ~Person(); + + static int GetCount(); + + Person(std::string name, int age); + + static std::shared_ptr GetPerson(std::string name, int age); + + void setSalary(int sal); + + private: + Person(const Person &); + + std::string name; + int age; + int salary; + + static int Count; +}; + +#endif \ No newline at end of file diff --git a/cmat/SolutionEx61Part2/PersonException.cpp b/cmat/SolutionEx61Part2/PersonException.cpp new file mode 100644 index 0000000..bef2a5e --- /dev/null +++ b/cmat/SolutionEx61Part2/PersonException.cpp @@ -0,0 +1,5 @@ +#include "PersonException.h" + +PersonException::PersonException(std::string m) : msg(m) {} + +const char *PersonException::what() const throw() { return msg.c_str(); } \ No newline at end of file diff --git a/cmat/SolutionEx61Part2/PersonException.h b/cmat/SolutionEx61Part2/PersonException.h new file mode 100644 index 0000000..d9e6b06 --- /dev/null +++ b/cmat/SolutionEx61Part2/PersonException.h @@ -0,0 +1,16 @@ +#ifndef Person_Exception_h +#define Person_Exception_h + +#include +#include + +class PersonException : public std::exception { + public: + PersonException(std::string m); + const char *what() const throw(); + + private: + std::string msg; +}; + +#endif diff --git a/cmat/SolutionEx61Part2/YoungPerson.cpp b/cmat/SolutionEx61Part2/YoungPerson.cpp new file mode 100644 index 0000000..04d4518 --- /dev/null +++ b/cmat/SolutionEx61Part2/YoungPerson.cpp @@ -0,0 +1,12 @@ +#include "YoungPerson.h" + +#include + +YoungPerson::YoungPerson(std::string name, int age) : Person(name, age) { std::cout << "YoungPerson ctor\n"; } + +YoungPerson::~YoungPerson() { + // Implemented purely to show that + // the derived-class destructor was + // being called where appropriate + std::cout << "YoungPerson dtor\n"; +} diff --git a/cmat/SolutionEx61Part2/YoungPerson.h b/cmat/SolutionEx61Part2/YoungPerson.h new file mode 100644 index 0000000..dd7efcf --- /dev/null +++ b/cmat/SolutionEx61Part2/YoungPerson.h @@ -0,0 +1,14 @@ + + +#ifndef YoungPerson_h +#define YoungPerson_h + +#include "Person.h" + +class YoungPerson : public Person { + public: + YoungPerson(std::string name, int age); + ~YoungPerson(); +}; + +#endif \ No newline at end of file diff --git a/cmat/SolutionEx61Part2/main.cpp b/cmat/SolutionEx61Part2/main.cpp new file mode 100644 index 0000000..ea3b335 --- /dev/null +++ b/cmat/SolutionEx61Part2/main.cpp @@ -0,0 +1,76 @@ + +#include +#include +#include + +#include "Person.h" + +#include "PersonException.h" +#include + +#include "memory" + +using std::cin; +using std::cout; +using std::string; +using std::exception; + +int main() { + { // start of extra scope + std::vector> people; + + string namePrompt = "Enter name: "; + string name; + string agePrompt = "Enter age: "; + int age; + string salaryPrompt = "Enter salary: "; + int salary; + + cout << namePrompt; + cin >> name; + + while (name != "q") { + try { + cout << agePrompt; + cin >> age; + + if (!cin) { + cin.clear(); + string dummy; + cin >> dummy; + throw PersonException("invalid age"); + } + + // Person* personPtr = new Person(name, age); + std::shared_ptr personPtr(Person::GetPerson(name, age)); + + cout << salaryPrompt; + cin >> salary; + if (!cin) { + cin.clear(); + string dummy; + cin >> dummy; + throw PersonException("invalid salary"); + } + + personPtr->setSalary(salary); + + people.push_back(personPtr); + } + + catch (exception &e) { + cout << "PersonException thrown: " << e.what() << '\n'; + } + + cout << "There are " << Person::GetCount() << " Person(s), " << people.size() << " in vector\n"; + + cout << namePrompt; + cin >> name; + } + + } // end of extra scope, destructor of vector called here + + cout << "There are " << Person::GetCount() << " Person(s) left dangling\n"; + + return 0; +} diff --git a/cmat/SolutionEx61Part2Bonus/CMakeLists.txt b/cmat/SolutionEx61Part2Bonus/CMakeLists.txt new file mode 100644 index 0000000..65f5aa6 --- /dev/null +++ b/cmat/SolutionEx61Part2Bonus/CMakeLists.txt @@ -0,0 +1,9 @@ +# SolutionEx61Part2Bonus + +cmat_add_exercise(SolutionEx61Part2Bonus + SOURCES + main.cpp + Person.cpp + PersonException.cpp + YoungPerson.cpp +) diff --git a/cmat/SolutionEx61Part2Bonus/Ex61.sln b/cmat/SolutionEx61Part2Bonus/Ex61.sln new file mode 100644 index 0000000..b9d83cb --- /dev/null +++ b/cmat/SolutionEx61Part2Bonus/Ex61.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ex61", "Ex61.vcxproj", "{71B1E667-58E2-4C71-A6A3-73F9502928D7}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {71B1E667-58E2-4C71-A6A3-73F9502928D7}.Debug|Win32.ActiveCfg = Debug|Win32 + {71B1E667-58E2-4C71-A6A3-73F9502928D7}.Debug|Win32.Build.0 = Debug|Win32 + {71B1E667-58E2-4C71-A6A3-73F9502928D7}.Release|Win32.ActiveCfg = Release|Win32 + {71B1E667-58E2-4C71-A6A3-73F9502928D7}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/cmat/SolutionEx61Part2Bonus/Ex61.suo b/cmat/SolutionEx61Part2Bonus/Ex61.suo new file mode 100644 index 0000000..364c892 Binary files /dev/null and b/cmat/SolutionEx61Part2Bonus/Ex61.suo differ diff --git a/cmat/SolutionEx61Part2Bonus/Ex61.vcproj b/cmat/SolutionEx61Part2Bonus/Ex61.vcproj new file mode 100644 index 0000000..b3ad81a --- /dev/null +++ b/cmat/SolutionEx61Part2Bonus/Ex61.vcproj @@ -0,0 +1,121 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cmat/SolutionEx61Part2Bonus/Ex61.vcxproj b/cmat/SolutionEx61Part2Bonus/Ex61.vcxproj new file mode 100644 index 0000000..f87347e --- /dev/null +++ b/cmat/SolutionEx61Part2Bonus/Ex61.vcxproj @@ -0,0 +1,92 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {71B1E667-58E2-4C71-A6A3-73F9502928D7} + ManagedCProj + + + + Application + MultiByte + OldSyntax + v140 + + + Application + MultiByte + false + v140 + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + Debug\ + Debug\ + true + Release\ + Release\ + false + + + + Disabled + WIN32;_DEBUG;%(PreprocessorDefinitions) + false + Default + MultiThreadedDebugDLL + Level3 + ProgramDatabase + + + $(OutDir)Ex61.exe + true + Console + + + + + MaxSpeed + OnlyExplicitInline + WIN32;NDEBUG;%(PreprocessorDefinitions) + false + Level3 + + + $(OutDir)Ex61.exe + true + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cmat/SolutionEx61Part2Bonus/Ex61.vcxproj.filters b/cmat/SolutionEx61Part2Bonus/Ex61.vcxproj.filters new file mode 100644 index 0000000..a9ce652 --- /dev/null +++ b/cmat/SolutionEx61Part2Bonus/Ex61.vcxproj.filters @@ -0,0 +1,38 @@ + + + + + {216ad10e-da13-4e74-bd7b-3d1fd4babd53} + cpp;c;cxx;def;odl;idl;hpj;bat;asm + + + {57ab839f-9334-4b02-aa8e-af153d217a12} + h;hpp;hxx;hm;inl;inc + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/cmat/SolutionEx61Part2Bonus/Ex61.vcxproj.user b/cmat/SolutionEx61Part2Bonus/Ex61.vcxproj.user new file mode 100644 index 0000000..695b5c7 --- /dev/null +++ b/cmat/SolutionEx61Part2Bonus/Ex61.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cmat/SolutionEx61Part2Bonus/Person.cpp b/cmat/SolutionEx61Part2Bonus/Person.cpp new file mode 100644 index 0000000..f511907 --- /dev/null +++ b/cmat/SolutionEx61Part2Bonus/Person.cpp @@ -0,0 +1,41 @@ +#include "Person.h" +#include "PersonException.h" +#include "YoungPerson.h" +#include + +using std::cout; + +Person::Person(std::string name, int age) : name(name), age(age) { + if (age < 0) { + throw PersonException("negative age"); + } + + cout << "Person ctor\n"; + Count++; +} + +Person::Person(const Person &) { + cout << "Copy ctor\n"; + Count++; +} + +Person::~Person() { + cout << "Person dtor\n"; + Count--; +} + +void Person::setSalary(int sal) { + if (sal < 0) { + throw PersonException("negative salary"); + } + + salary = sal; +} + +int Person::GetCount() { return Count; } + +std::unique_ptr Person::GetPerson(std::string name, int age) { + return age < 18 ? std::make_unique(name, age) : std::make_unique(name, age); +} + +int Person::Count = 0; diff --git a/cmat/SolutionEx61Part2Bonus/Person.h b/cmat/SolutionEx61Part2Bonus/Person.h new file mode 100644 index 0000000..e0273a3 --- /dev/null +++ b/cmat/SolutionEx61Part2Bonus/Person.h @@ -0,0 +1,31 @@ + + +#ifndef Person_h +#define Person_h + +#include +#include + +class Person { + public: + virtual ~Person(); + + static int GetCount(); + + Person(std::string name, int age); + + static std::unique_ptr GetPerson(std::string name, int age); + + void setSalary(int sal); + + private: + Person(const Person &); + + std::string name; + int age; + int salary; + + static int Count; +}; + +#endif \ No newline at end of file diff --git a/cmat/SolutionEx61Part2Bonus/PersonException.cpp b/cmat/SolutionEx61Part2Bonus/PersonException.cpp new file mode 100644 index 0000000..bef2a5e --- /dev/null +++ b/cmat/SolutionEx61Part2Bonus/PersonException.cpp @@ -0,0 +1,5 @@ +#include "PersonException.h" + +PersonException::PersonException(std::string m) : msg(m) {} + +const char *PersonException::what() const throw() { return msg.c_str(); } \ No newline at end of file diff --git a/cmat/SolutionEx61Part2Bonus/PersonException.h b/cmat/SolutionEx61Part2Bonus/PersonException.h new file mode 100644 index 0000000..d9e6b06 --- /dev/null +++ b/cmat/SolutionEx61Part2Bonus/PersonException.h @@ -0,0 +1,16 @@ +#ifndef Person_Exception_h +#define Person_Exception_h + +#include +#include + +class PersonException : public std::exception { + public: + PersonException(std::string m); + const char *what() const throw(); + + private: + std::string msg; +}; + +#endif diff --git a/cmat/SolutionEx61Part2Bonus/YoungPerson.cpp b/cmat/SolutionEx61Part2Bonus/YoungPerson.cpp new file mode 100644 index 0000000..04d4518 --- /dev/null +++ b/cmat/SolutionEx61Part2Bonus/YoungPerson.cpp @@ -0,0 +1,12 @@ +#include "YoungPerson.h" + +#include + +YoungPerson::YoungPerson(std::string name, int age) : Person(name, age) { std::cout << "YoungPerson ctor\n"; } + +YoungPerson::~YoungPerson() { + // Implemented purely to show that + // the derived-class destructor was + // being called where appropriate + std::cout << "YoungPerson dtor\n"; +} diff --git a/cmat/SolutionEx61Part2Bonus/YoungPerson.h b/cmat/SolutionEx61Part2Bonus/YoungPerson.h new file mode 100644 index 0000000..dd7efcf --- /dev/null +++ b/cmat/SolutionEx61Part2Bonus/YoungPerson.h @@ -0,0 +1,14 @@ + + +#ifndef YoungPerson_h +#define YoungPerson_h + +#include "Person.h" + +class YoungPerson : public Person { + public: + YoungPerson(std::string name, int age); + ~YoungPerson(); +}; + +#endif \ No newline at end of file diff --git a/cmat/SolutionEx61Part2Bonus/main.cpp b/cmat/SolutionEx61Part2Bonus/main.cpp new file mode 100644 index 0000000..381a41e --- /dev/null +++ b/cmat/SolutionEx61Part2Bonus/main.cpp @@ -0,0 +1,76 @@ + +#include +#include +#include + +#include "Person.h" + +#include "PersonException.h" +#include + +#include "memory" + +using std::cin; +using std::cout; +using std::string; +using std::exception; + +int main() { + { // extra scope starts here to cause destructor of the vector being called at end-of-scope + std::vector> people; + + string namePrompt = "Enter name: "; + string name; + string agePrompt = "Enter age: "; + int age; + string salaryPrompt = "Enter salary: "; + int salary; + + cout << namePrompt; + cin >> name; + + while (name != "q") { + try { + cout << agePrompt; + cin >> age; + + if (!cin) { + cin.clear(); + string dummy; + cin >> dummy; + throw PersonException("invalid age"); + } + + std::unique_ptr personPtr(Person::GetPerson(name, age)); + + cout << salaryPrompt; + cin >> salary; + if (!cin) { + cin.clear(); + string dummy; + cin >> dummy; + throw PersonException("invalid salary"); + } + + personPtr->setSalary(salary); + + people.push_back(move(personPtr)); + } + + catch (exception &e) { + cout << "PersonException thrown: " << e.what() << '\n'; + } + + cout << "There are " << Person::GetCount() << " Person(s), " << people.size() << " in vector\n"; + + cout << namePrompt; + cin >> name; + } + + // people.clear(); + } // end-of-scope, the vector will be automatically cleared here in its destructor + + cout << "There are " << Person::GetCount() << " Person(s) left dangling\n"; + + return 0; +} diff --git a/cmat/SolutionEx62/CMakeLists.txt b/cmat/SolutionEx62/CMakeLists.txt new file mode 100644 index 0000000..a94a214 --- /dev/null +++ b/cmat/SolutionEx62/CMakeLists.txt @@ -0,0 +1,8 @@ +# SolutionEx62 + +cmat_add_exercise(SolutionEx62 + BOOST + SOURCES + Main.cpp + Person.cpp +) diff --git a/cmat/SolutionEx62/Ex62.sln b/cmat/SolutionEx62/Ex62.sln new file mode 100644 index 0000000..c1b76bf --- /dev/null +++ b/cmat/SolutionEx62/Ex62.sln @@ -0,0 +1,20 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ex62", "Ex62.vcxproj", "{252EC352-EE7F-66EF-0B79-229BBB7504A7}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {252EC352-EE7F-66EF-0B79-229BBB7504A7}.Debug|Win32.ActiveCfg = Debug|Win32 + {252EC352-EE7F-66EF-0B79-229BBB7504A7}.Debug|Win32.Build.0 = Debug|Win32 + {252EC352-EE7F-66EF-0B79-229BBB7504A7}.Release|Win32.ActiveCfg = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/cmat/SolutionEx62/Ex62.suo b/cmat/SolutionEx62/Ex62.suo new file mode 100644 index 0000000..e8bc8cf Binary files /dev/null and b/cmat/SolutionEx62/Ex62.suo differ diff --git a/cmat/SolutionEx62/Ex62.vcproj b/cmat/SolutionEx62/Ex62.vcproj new file mode 100644 index 0000000..1c3f5b3 --- /dev/null +++ b/cmat/SolutionEx62/Ex62.vcproj @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cmat/SolutionEx62/Ex62.vcxproj b/cmat/SolutionEx62/Ex62.vcxproj new file mode 100644 index 0000000..4666408 --- /dev/null +++ b/cmat/SolutionEx62/Ex62.vcxproj @@ -0,0 +1,130 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + {252EC352-EE7F-66EF-0B79-229BBB7504A7} + + + + Application + false + MultiByte + v140 + + + Application + false + MultiByte + v140 + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + .\Debug\ + .\Debug\ + true + .\Release\ + .\Release\ + false + + + + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebugDLL + true + NotUsing + .\Debug/Ex62.pch + .\Debug/ + .\Debug/ + .\Debug/ + Level3 + true + C:\boost_1_60_0;%(AdditionalIncludeDirectories) + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Debug/Ex62.exe + true + true + .\Debug/Ex62.pdb + Console + C:\boost_1_60_0\stage\lib;%(AdditionalLibraryDirectories) + + + .\Debug/Ex62.tlb + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + OnlyExplicitInline + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + true + + + .\Release/Ex62.pch + .\Release/ + .\Release/ + .\Release/ + Level3 + true + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Release/Ex62.exe + true + .\Release/Ex62.pdb + Console + + + .\Release/Ex62.tlb + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + 4308 + + + + + + + + + + \ No newline at end of file diff --git a/cmat/SolutionEx62/Ex62.vcxproj.filters b/cmat/SolutionEx62/Ex62.vcxproj.filters new file mode 100644 index 0000000..e427d6f --- /dev/null +++ b/cmat/SolutionEx62/Ex62.vcxproj.filters @@ -0,0 +1,26 @@ + + + + + {ee8cac86-35f3-4b27-880c-c2776398baea} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {4ce1c82c-752c-4f94-a6c3-fc2858d4d4c2} + h;hpp;hxx;hm;inl + + + + + Source Files + + + Source Files + + + + + Header Files + + + \ No newline at end of file diff --git a/cmat/SolutionEx62/Ex62.vcxproj.user b/cmat/SolutionEx62/Ex62.vcxproj.user new file mode 100644 index 0000000..695b5c7 --- /dev/null +++ b/cmat/SolutionEx62/Ex62.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cmat/SolutionEx62/Main.cpp b/cmat/SolutionEx62/Main.cpp new file mode 100644 index 0000000..a1e5a3d --- /dev/null +++ b/cmat/SolutionEx62/Main.cpp @@ -0,0 +1,72 @@ + + +#include "Person.h" +#include +#include +#include +#include + +// header for file streams +#include +// include headers that implement a archive in simple text format +#include +#include +// include header that allows serialization of STL list +#include + +// STL collection of Person* +std::list people; + +void add() { + // creates a person, collects the information, adds person to list + Person *newP = new Person; + newP->askForInfo(); + people.push_back(newP); +} + +void showPerson(Person *p) { + // displays a person + p->display(); +} + +void display() { + // displays all the people + std::for_each(people.begin(), people.end(), &showPerson); +} + +int main() { + // deserialize existing file (if there is one) + try { + // create and open an archive for input + std::ifstream ifs("file.dat"); + boost::archive::text_iarchive ia(ifs); + // read class state from archive + ia >> people; + // archive and stream closed when destructors are called + } catch (...) { + } + + char choice = 0; + + while (choice != 'X') { + switch (choice) { + case 'A': + add(); + break; + case 'D': + display(); + break; + } + std::cout << "Enter choice: [A]dd, [D]isplay, e[X]it: "; + std::cin >> choice; + choice = std::toupper(choice); + } + + // save data to archive + std::ofstream ofs("file.dat"); + boost::archive::text_oarchive oa(ofs); + oa << people; + // archive and stream closed when destructors are called + + return 0; +} diff --git a/cmat/SolutionEx62/Person.cpp b/cmat/SolutionEx62/Person.cpp new file mode 100644 index 0000000..f3283ac --- /dev/null +++ b/cmat/SolutionEx62/Person.cpp @@ -0,0 +1,13 @@ +#include "Person.h" +#include + +void Person::askForInfo() { + std::cout << "First name: "; + std::cin >> firstName; + std::cout << "Last name: "; + std::cin >> lastName; + std::cout << "Age: "; + std::cin >> age; +} + +void Person::display() { std::cout << firstName << " " << lastName << ", " << age << std::endl; } diff --git a/cmat/SolutionEx62/Person.h b/cmat/SolutionEx62/Person.h new file mode 100644 index 0000000..f1275f0 --- /dev/null +++ b/cmat/SolutionEx62/Person.h @@ -0,0 +1,28 @@ + + +#ifndef person_H +#define person_H + +#include + +#include + +class Person { + public: + void askForInfo(); + void display(); + + private: + std::string firstName; + std::string lastName; + int age; + + template void serialize(Archive &ar, const unsigned int version) { + ar &firstName; + ar &lastName; + ar &age; + } + friend class boost::serialization::access; +}; + +#endif diff --git a/cmat/SolutionEx62Bonus/CMakeLists.txt b/cmat/SolutionEx62Bonus/CMakeLists.txt new file mode 100644 index 0000000..c0b9fd3 --- /dev/null +++ b/cmat/SolutionEx62Bonus/CMakeLists.txt @@ -0,0 +1,9 @@ +# SolutionEx62Bonus + +cmat_add_exercise(SolutionEx62Bonus + BOOST + SOURCES + Employee.cpp + Main.cpp + Person.cpp +) diff --git a/cmat/SolutionEx62Bonus/Employee.cpp b/cmat/SolutionEx62Bonus/Employee.cpp new file mode 100644 index 0000000..e0f3822 --- /dev/null +++ b/cmat/SolutionEx62Bonus/Employee.cpp @@ -0,0 +1,11 @@ +#include "Employee.h" +#include + +void Employee::doDisplay() { std::cout << ", $" << salary; } + +void Employee::askForInfo() { + Person::askForInfo(); + + std::cout << "Salary: "; + std::cin >> salary; +} diff --git a/cmat/SolutionEx62Bonus/Employee.h b/cmat/SolutionEx62Bonus/Employee.h new file mode 100644 index 0000000..f39c0a0 --- /dev/null +++ b/cmat/SolutionEx62Bonus/Employee.h @@ -0,0 +1,21 @@ +#ifndef EMPLYOEE_H +#define EMPLYOEE_H +#include "Person.h" + +class Employee : public Person { + public: + void askForInfo(); + + private: + int salary; + + void doDisplay(); + + template void serialize(Archive &ar, const unsigned int version) { + ar &boost::serialization::base_object(*this); + ar &salary; + } + friend class boost::serialization::access; +}; + +#endif \ No newline at end of file diff --git a/cmat/SolutionEx62Bonus/Ex62.sln b/cmat/SolutionEx62Bonus/Ex62.sln new file mode 100644 index 0000000..c1b76bf --- /dev/null +++ b/cmat/SolutionEx62Bonus/Ex62.sln @@ -0,0 +1,20 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ex62", "Ex62.vcxproj", "{252EC352-EE7F-66EF-0B79-229BBB7504A7}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {252EC352-EE7F-66EF-0B79-229BBB7504A7}.Debug|Win32.ActiveCfg = Debug|Win32 + {252EC352-EE7F-66EF-0B79-229BBB7504A7}.Debug|Win32.Build.0 = Debug|Win32 + {252EC352-EE7F-66EF-0B79-229BBB7504A7}.Release|Win32.ActiveCfg = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/cmat/SolutionEx62Bonus/Ex62.suo b/cmat/SolutionEx62Bonus/Ex62.suo new file mode 100644 index 0000000..e8bc8cf Binary files /dev/null and b/cmat/SolutionEx62Bonus/Ex62.suo differ diff --git a/cmat/SolutionEx62Bonus/Ex62.vcproj b/cmat/SolutionEx62Bonus/Ex62.vcproj new file mode 100644 index 0000000..1c3f5b3 --- /dev/null +++ b/cmat/SolutionEx62Bonus/Ex62.vcproj @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cmat/SolutionEx62Bonus/Ex62.vcxproj b/cmat/SolutionEx62Bonus/Ex62.vcxproj new file mode 100644 index 0000000..880a43d --- /dev/null +++ b/cmat/SolutionEx62Bonus/Ex62.vcxproj @@ -0,0 +1,132 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + {252EC352-EE7F-66EF-0B79-229BBB7504A7} + + + + Application + false + MultiByte + v140 + + + Application + false + MultiByte + v140 + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + .\Debug\ + .\Debug\ + true + .\Release\ + .\Release\ + false + + + + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebugDLL + true + NotUsing + .\Debug/Ex62.pch + .\Debug/ + .\Debug/ + .\Debug/ + Level3 + true + C:\boost_1_60_0;%(AdditionalIncludeDirectories) + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Debug/Ex62.exe + true + true + .\Debug/Ex62.pdb + Console + C:\boost_1_60_0\stage\lib;%(AdditionalLibraryDirectories) + + + .\Debug/Ex62.tlb + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + OnlyExplicitInline + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + true + + + .\Release/Ex62.pch + .\Release/ + .\Release/ + .\Release/ + Level3 + true + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Release/Ex62.exe + true + .\Release/Ex62.pdb + Console + + + .\Release/Ex62.tlb + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + + 4308 + + + + + + + + + + + \ No newline at end of file diff --git a/cmat/SolutionEx62Bonus/Ex62.vcxproj.filters b/cmat/SolutionEx62Bonus/Ex62.vcxproj.filters new file mode 100644 index 0000000..1b7388f --- /dev/null +++ b/cmat/SolutionEx62Bonus/Ex62.vcxproj.filters @@ -0,0 +1,32 @@ + + + + + {ee8cac86-35f3-4b27-880c-c2776398baea} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {4ce1c82c-752c-4f94-a6c3-fc2858d4d4c2} + h;hpp;hxx;hm;inl + + + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/cmat/SolutionEx62Bonus/Ex62.vcxproj.user b/cmat/SolutionEx62Bonus/Ex62.vcxproj.user new file mode 100644 index 0000000..695b5c7 --- /dev/null +++ b/cmat/SolutionEx62Bonus/Ex62.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cmat/SolutionEx62Bonus/Main.cpp b/cmat/SolutionEx62Bonus/Main.cpp new file mode 100644 index 0000000..9906069 --- /dev/null +++ b/cmat/SolutionEx62Bonus/Main.cpp @@ -0,0 +1,77 @@ + + +#include "Employee.h" +#include "Person.h" +#include +#include +#include +#include + +// header for file streams +#include +// include headers that implement a archive in simple text format +#include +#include +// include header that allows serialization of STL list +#include +#include +BOOST_CLASS_EXPORT_GUID(Employee, "Employee") + +// STL collection of Person* +std::list people; + +void add(Person *newP) { + // creates a person, collects the information, adds person to list + newP->askForInfo(); + people.push_back(newP); +} + +void showPerson(Person *p) { + // displays a person + p->display(); +} + +void display() { + // displays all the people + std::for_each(people.begin(), people.end(), &showPerson); +} + +int main() { + // deserialize existing file (if there is one) + try { + // create and open an archive for input + std::ifstream ifs("file.dat"); + boost::archive::text_iarchive ia(ifs); + // read class state from archive + ia >> people; + // archive and stream closed when destructors are called + } catch (...) { + } + + char choice = 0; + + while (choice != 'X') { + switch (choice) { + case 'P': + add(new Person()); + break; + case 'E': + add(new Employee()); + break; + case 'D': + display(); + break; + } + std::cout << "Enter choice: Add [P]erson, add [E]mployee, [D]isplay, e[X]it: "; + std::cin >> choice; + choice = std::toupper(choice); + } + + // save data to archive + std::ofstream ofs("file.dat"); + boost::archive::text_oarchive oa(ofs); + oa << people; + // archive and stream closed when destructors are called + + return 0; +} diff --git a/cmat/SolutionEx62Bonus/Person.cpp b/cmat/SolutionEx62Bonus/Person.cpp new file mode 100644 index 0000000..006ad16 --- /dev/null +++ b/cmat/SolutionEx62Bonus/Person.cpp @@ -0,0 +1,23 @@ +#include "Person.h" +#include + +void Person::askForInfo() { + std::cout << "First name: "; + std::cin >> firstName; + std::cout << "Last name: "; + std::cin >> lastName; + std::cout << "Age: "; + std::cin >> age; +} + +void Person::display() { + std::cout << firstName << " " << lastName << ", " << age; + + doDisplay(); // Call primitive step + + std::cout << std::endl; +} + +void Person::doDisplay() { + // Nothing to do in base class +} diff --git a/cmat/SolutionEx62Bonus/Person.h b/cmat/SolutionEx62Bonus/Person.h new file mode 100644 index 0000000..1f3eabb --- /dev/null +++ b/cmat/SolutionEx62Bonus/Person.h @@ -0,0 +1,30 @@ + + +#ifndef person_H +#define person_H + +#include + +#include + +class Person { + public: + virtual void askForInfo(); + void display(); + + private: + virtual void doDisplay(); + + std::string firstName; + std::string lastName; + int age; + + template void serialize(Archive &ar, const unsigned int version) { + ar &firstName; + ar &lastName; + ar &age; + } + friend class boost::serialization::access; +}; + +#endif diff --git a/cmat/SolutionEx62Bonus2/CMakeLists.txt b/cmat/SolutionEx62Bonus2/CMakeLists.txt new file mode 100644 index 0000000..46c36dd --- /dev/null +++ b/cmat/SolutionEx62Bonus2/CMakeLists.txt @@ -0,0 +1,9 @@ +# SolutionEx62Bonus2 + +cmat_add_exercise(SolutionEx62Bonus2 + BOOST + SOURCES + Employee.cpp + Main.cpp + Person.cpp +) diff --git a/cmat/SolutionEx62Bonus2/Employee.cpp b/cmat/SolutionEx62Bonus2/Employee.cpp new file mode 100644 index 0000000..e0f3822 --- /dev/null +++ b/cmat/SolutionEx62Bonus2/Employee.cpp @@ -0,0 +1,11 @@ +#include "Employee.h" +#include + +void Employee::doDisplay() { std::cout << ", $" << salary; } + +void Employee::askForInfo() { + Person::askForInfo(); + + std::cout << "Salary: "; + std::cin >> salary; +} diff --git a/cmat/SolutionEx62Bonus2/Employee.h b/cmat/SolutionEx62Bonus2/Employee.h new file mode 100644 index 0000000..c7095b7 --- /dev/null +++ b/cmat/SolutionEx62Bonus2/Employee.h @@ -0,0 +1,21 @@ +#ifndef EMPLOYEE_H +#define EMPLOYEE_H + +#include "Person.h" + +class Employee : public Person { + public: + void askForInfo(); + + private: + int salary; + + void doDisplay(); + + template void serialize(Archive &ar, const unsigned int version) { + ar &BOOST_SERIALIZATION_BASE_OBJECT_NVP(Person); + ar &BOOST_SERIALIZATION_NVP(salary); + } + friend class boost::serialization::access; +}; +#endif \ No newline at end of file diff --git a/cmat/SolutionEx62Bonus2/Ex62.sln b/cmat/SolutionEx62Bonus2/Ex62.sln new file mode 100644 index 0000000..c1b76bf --- /dev/null +++ b/cmat/SolutionEx62Bonus2/Ex62.sln @@ -0,0 +1,20 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ex62", "Ex62.vcxproj", "{252EC352-EE7F-66EF-0B79-229BBB7504A7}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {252EC352-EE7F-66EF-0B79-229BBB7504A7}.Debug|Win32.ActiveCfg = Debug|Win32 + {252EC352-EE7F-66EF-0B79-229BBB7504A7}.Debug|Win32.Build.0 = Debug|Win32 + {252EC352-EE7F-66EF-0B79-229BBB7504A7}.Release|Win32.ActiveCfg = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/cmat/SolutionEx62Bonus2/Ex62.suo b/cmat/SolutionEx62Bonus2/Ex62.suo new file mode 100644 index 0000000..e8bc8cf Binary files /dev/null and b/cmat/SolutionEx62Bonus2/Ex62.suo differ diff --git a/cmat/SolutionEx62Bonus2/Ex62.vcproj b/cmat/SolutionEx62Bonus2/Ex62.vcproj new file mode 100644 index 0000000..1c3f5b3 --- /dev/null +++ b/cmat/SolutionEx62Bonus2/Ex62.vcproj @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cmat/SolutionEx62Bonus2/Ex62.vcxproj b/cmat/SolutionEx62Bonus2/Ex62.vcxproj new file mode 100644 index 0000000..880a43d --- /dev/null +++ b/cmat/SolutionEx62Bonus2/Ex62.vcxproj @@ -0,0 +1,132 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + {252EC352-EE7F-66EF-0B79-229BBB7504A7} + + + + Application + false + MultiByte + v140 + + + Application + false + MultiByte + v140 + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + .\Debug\ + .\Debug\ + true + .\Release\ + .\Release\ + false + + + + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebugDLL + true + NotUsing + .\Debug/Ex62.pch + .\Debug/ + .\Debug/ + .\Debug/ + Level3 + true + C:\boost_1_60_0;%(AdditionalIncludeDirectories) + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Debug/Ex62.exe + true + true + .\Debug/Ex62.pdb + Console + C:\boost_1_60_0\stage\lib;%(AdditionalLibraryDirectories) + + + .\Debug/Ex62.tlb + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + OnlyExplicitInline + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + true + + + .\Release/Ex62.pch + .\Release/ + .\Release/ + .\Release/ + Level3 + true + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Release/Ex62.exe + true + .\Release/Ex62.pdb + Console + + + .\Release/Ex62.tlb + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + + 4308 + + + + + + + + + + + \ No newline at end of file diff --git a/cmat/SolutionEx62Bonus2/Ex62.vcxproj.filters b/cmat/SolutionEx62Bonus2/Ex62.vcxproj.filters new file mode 100644 index 0000000..1b7388f --- /dev/null +++ b/cmat/SolutionEx62Bonus2/Ex62.vcxproj.filters @@ -0,0 +1,32 @@ + + + + + {ee8cac86-35f3-4b27-880c-c2776398baea} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {4ce1c82c-752c-4f94-a6c3-fc2858d4d4c2} + h;hpp;hxx;hm;inl + + + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/cmat/SolutionEx62Bonus2/Ex62.vcxproj.user b/cmat/SolutionEx62Bonus2/Ex62.vcxproj.user new file mode 100644 index 0000000..695b5c7 --- /dev/null +++ b/cmat/SolutionEx62Bonus2/Ex62.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cmat/SolutionEx62Bonus2/Main.cpp b/cmat/SolutionEx62Bonus2/Main.cpp new file mode 100644 index 0000000..b3669e4 --- /dev/null +++ b/cmat/SolutionEx62Bonus2/Main.cpp @@ -0,0 +1,81 @@ + + +#include "Employee.h" +#include "Person.h" +#include +#include +#include +#include + +// header for file streams +#include +// include headers that implement a archive in simple text format and XML format +#include +#include +#include +#include +// include header that allows serialization of STL list +#include +#include +#include + +BOOST_CLASS_EXPORT_GUID(Employee, "Employee") + +// STL collection of Person* +std::list people; + +void add(Person *newP) { + // creates a person, collects the information, adds person to list + newP->askForInfo(); + people.push_back(newP); +} + +void showPerson(Person *p) { + // displays a person + p->display(); +} + +void display() { + // displays all the people + std::for_each(people.begin(), people.end(), &showPerson); +} + +int main() { + // deserialize existing file (if there is one) + try { + // create and open an archive for input + std::ifstream ifs("file.xml"); + boost::archive::xml_iarchive ia(ifs); + // read class state from archive + ia >> BOOST_SERIALIZATION_NVP(people); + // archive and stream closed when destructors are called + } catch (...) { + } + + char choice = 0; + + while (choice != 'X') { + switch (choice) { + case 'P': + add(new Person()); + break; + case 'E': + add(new Employee()); + break; + case 'D': + display(); + break; + } + std::cout << "Enter choice: Add [P]erson, add [E]mployee, [D]isplay, e[X]it: "; + std::cin >> choice; + choice = std::toupper(choice); + } + + // save data to archive + std::ofstream ofs("file.xml"); + boost::archive::xml_oarchive oa(ofs); + oa << BOOST_SERIALIZATION_NVP(people); + // archive and stream closed when destructors are called + + return 0; +} diff --git a/cmat/SolutionEx62Bonus2/Person.cpp b/cmat/SolutionEx62Bonus2/Person.cpp new file mode 100644 index 0000000..006ad16 --- /dev/null +++ b/cmat/SolutionEx62Bonus2/Person.cpp @@ -0,0 +1,23 @@ +#include "Person.h" +#include + +void Person::askForInfo() { + std::cout << "First name: "; + std::cin >> firstName; + std::cout << "Last name: "; + std::cin >> lastName; + std::cout << "Age: "; + std::cin >> age; +} + +void Person::display() { + std::cout << firstName << " " << lastName << ", " << age; + + doDisplay(); // Call primitive step + + std::cout << std::endl; +} + +void Person::doDisplay() { + // Nothing to do in base class +} diff --git a/cmat/SolutionEx62Bonus2/Person.h b/cmat/SolutionEx62Bonus2/Person.h new file mode 100644 index 0000000..4ae4b78 --- /dev/null +++ b/cmat/SolutionEx62Bonus2/Person.h @@ -0,0 +1,31 @@ + + +#ifndef person_H +#define person_H + +#include + +#include +#include + +class Person { + public: + virtual void askForInfo(); + void display(); + + private: + virtual void doDisplay(); + + std::string firstName; + std::string lastName; + int age; + + template void serialize(Archive &ar, const unsigned int version) { + ar &BOOST_SERIALIZATION_NVP(firstName); + ar &BOOST_SERIALIZATION_NVP(lastName); + ar &BOOST_SERIALIZATION_NVP(age); + } + friend class boost::serialization::access; +}; + +#endif diff --git a/cmat/SolutionEx71/CMakeLists.txt b/cmat/SolutionEx71/CMakeLists.txt new file mode 100644 index 0000000..a244e52 --- /dev/null +++ b/cmat/SolutionEx71/CMakeLists.txt @@ -0,0 +1,11 @@ +# SolutionEx71 + +cmat_add_exercise(SolutionEx71 + SOURCES + CompanyEntry.cpp + CountVisitor.cpp + FindVisitor.cpp + GroupEntry.cpp + main.cpp + PersonEntry.cpp +) diff --git a/cmat/SolutionEx71/CompanyEntry.cpp b/cmat/SolutionEx71/CompanyEntry.cpp new file mode 100644 index 0000000..898dcc6 --- /dev/null +++ b/cmat/SolutionEx71/CompanyEntry.cpp @@ -0,0 +1,19 @@ +#include +#include + +#include "CompanyEntry.h" +#include "EntryVisitor.h" + +CompanyEntry::CompanyEntry(std::string name, std::string category, std::string phone) + : Entry(name), _category(category), _phone(phone) {} + +void CompanyEntry::print(std::string indent) const { + + std::cout << indent << "Company: " << getName() << " <" << _category << "> " << _phone << '\n'; +} + +std::string CompanyEntry::getPhone() const { return _phone; } + +std::string CompanyEntry::getCategory() const { return _category; } + +void CompanyEntry::accept(EntryVisitor &v) const { v.visit(*this); } \ No newline at end of file diff --git a/cmat/SolutionEx71/CompanyEntry.h b/cmat/SolutionEx71/CompanyEntry.h new file mode 100644 index 0000000..819ca0d --- /dev/null +++ b/cmat/SolutionEx71/CompanyEntry.h @@ -0,0 +1,22 @@ + +#ifndef COMPANYENTRY_H +#define COMPANYENTRY_H + +#include "Entry.h" + +class CompanyEntry : public Entry { + public: + CompanyEntry(std::string name, std::string category, std::string phone); + + void print(std::string indent = "") const; + std::string getPhone() const; + std::string getCategory() const; + + void accept(EntryVisitor &) const; + + private: + std::string _category; + std::string _phone; +}; + +#endif \ No newline at end of file diff --git a/cmat/SolutionEx71/CountVisitor.cpp b/cmat/SolutionEx71/CountVisitor.cpp new file mode 100644 index 0000000..db8cbc5 --- /dev/null +++ b/cmat/SolutionEx71/CountVisitor.cpp @@ -0,0 +1,14 @@ +#include "CountVisitor.h" +#include + +CountVisitor::CountVisitor() : nPerson(0), nCompany(0), nGroup(0) {} + +void CountVisitor::printCounts() { + std::cout << "Persons: " << nPerson << " Companies: " << nCompany << " Groups: " << nGroup << "\n"; +} + +void CountVisitor::visit(const PersonEntry &p) { nPerson++; } + +void CountVisitor::visit(const CompanyEntry &c) { nCompany++; } + +void CountVisitor::visit(const GroupEntry &g) { nGroup++; } \ No newline at end of file diff --git a/cmat/SolutionEx71/CountVisitor.h b/cmat/SolutionEx71/CountVisitor.h new file mode 100644 index 0000000..5277ae7 --- /dev/null +++ b/cmat/SolutionEx71/CountVisitor.h @@ -0,0 +1,17 @@ +#ifndef COUNTVISITOR_H +#define COUNTVISITOR_H + +#include "EntryVisitor.h" +class CountVisitor : public EntryVisitor { + int nPerson, nCompany, nGroup; + + public: + CountVisitor(); + + void printCounts(); + + void visit(const PersonEntry &); + void visit(const CompanyEntry &); + void visit(const GroupEntry &); +}; +#endif \ No newline at end of file diff --git a/cmat/SolutionEx71/Entry.cpp b/cmat/SolutionEx71/Entry.cpp new file mode 100644 index 0000000..a1a6fa7 --- /dev/null +++ b/cmat/SolutionEx71/Entry.cpp @@ -0,0 +1,5 @@ +// Entry.cpp + +#include "Entry.h" + +Entry::Entry(std::string name) : _name(name), _phone(phone) {} diff --git a/cmat/SolutionEx71/Entry.h b/cmat/SolutionEx71/Entry.h new file mode 100644 index 0000000..f38a2bd --- /dev/null +++ b/cmat/SolutionEx71/Entry.h @@ -0,0 +1,23 @@ + +#ifndef ENTRY_H +#define ENTRY_H + +#include + +class EntryVisitor; + +class Entry { + public: + Entry(std::string name) : _name(name) {} + + std::string getName() const { return _name; } + + virtual void print(std::string indent = "") const = 0; + + virtual void accept(EntryVisitor &) const = 0; + + private: + std::string _name; +}; + +#endif diff --git a/cmat/SolutionEx71/EntryVisitor.h b/cmat/SolutionEx71/EntryVisitor.h new file mode 100644 index 0000000..70e2308 --- /dev/null +++ b/cmat/SolutionEx71/EntryVisitor.h @@ -0,0 +1,17 @@ + + +#ifndef ENTRYVISITOR_H +#define ENTRYVISITOR_H + +class PersonEntry; +class CompanyEntry; +class GroupEntry; + +class EntryVisitor { + public: + virtual void visit(const PersonEntry &) = 0; + virtual void visit(const CompanyEntry &) = 0; + virtual void visit(const GroupEntry &) = 0; +}; + +#endif diff --git a/cmat/SolutionEx71/Ex71.sln b/cmat/SolutionEx71/Ex71.sln new file mode 100644 index 0000000..a1c4809 --- /dev/null +++ b/cmat/SolutionEx71/Ex71.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ex71", "Ex71.vcxproj", "{3BE8ED56-4FC0-F86D-B9E1-1EE211AF78DB}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3BE8ED56-4FC0-F86D-B9E1-1EE211AF78DB}.Debug|Win32.ActiveCfg = Debug|Win32 + {3BE8ED56-4FC0-F86D-B9E1-1EE211AF78DB}.Debug|Win32.Build.0 = Debug|Win32 + {3BE8ED56-4FC0-F86D-B9E1-1EE211AF78DB}.Release|Win32.ActiveCfg = Release|Win32 + {3BE8ED56-4FC0-F86D-B9E1-1EE211AF78DB}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/cmat/SolutionEx71/Ex71.suo b/cmat/SolutionEx71/Ex71.suo new file mode 100644 index 0000000..d13baa0 Binary files /dev/null and b/cmat/SolutionEx71/Ex71.suo differ diff --git a/cmat/SolutionEx71/Ex71.v11.suo b/cmat/SolutionEx71/Ex71.v11.suo new file mode 100644 index 0000000..f22610a Binary files /dev/null and b/cmat/SolutionEx71/Ex71.v11.suo differ diff --git a/cmat/SolutionEx71/Ex71.vcxproj b/cmat/SolutionEx71/Ex71.vcxproj new file mode 100644 index 0000000..c8a25d1 --- /dev/null +++ b/cmat/SolutionEx71/Ex71.vcxproj @@ -0,0 +1,136 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + {3BE8ED56-4FC0-F86D-B9E1-1EE211AF78DB} + + + + Application + false + MultiByte + v140 + + + Application + false + MultiByte + v140 + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + .\Release\ + .\Release\ + false + .\Debug\ + .\Debug\ + true + + + + OnlyExplicitInline + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + true + + + .\Release/Ex71A.pch + .\Release/ + .\Release/ + .\Release/ + Level3 + true + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Release/Ex71A.exe + true + .\Release/Ex71A.pdb + Console + + + .\Release/Ex71A.tlb + + + NDEBUG;%(PreprocessorDefinitions) + 0x0809 + + + + + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + NotUsing + .\Debug/Ex71A.pch + .\Debug/ + .\Debug/ + .\Debug/ + Level3 + true + C:\course\397\DOS_Unix;%(AdditionalIncludeDirectories) + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Debug/Ex71.exe + true + true + .\Debug/Ex71A.pdb + Console + + + .\Debug/Ex71A.tlb + + + _DEBUG;%(PreprocessorDefinitions) + 0x0809 + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cmat/SolutionEx71/Ex71.vcxproj.filters b/cmat/SolutionEx71/Ex71.vcxproj.filters new file mode 100644 index 0000000..090c40d --- /dev/null +++ b/cmat/SolutionEx71/Ex71.vcxproj.filters @@ -0,0 +1,56 @@ + + + + + {a373d85d-0daa-4771-a2af-24735700f4b5} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {28280df5-d09d-4335-a70c-dd81eee4485f} + h;hpp;hxx;hm;inl + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/cmat/SolutionEx71/Ex71.vcxproj.user b/cmat/SolutionEx71/Ex71.vcxproj.user new file mode 100644 index 0000000..695b5c7 --- /dev/null +++ b/cmat/SolutionEx71/Ex71.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cmat/SolutionEx71/FindVisitor.cpp b/cmat/SolutionEx71/FindVisitor.cpp new file mode 100644 index 0000000..5e4c123 --- /dev/null +++ b/cmat/SolutionEx71/FindVisitor.cpp @@ -0,0 +1,30 @@ + +#include + +#include "CompanyEntry.h" +#include "FindVisitor.h" +#include "GroupEntry.h" +#include "PersonEntry.h" + +FindVisitor::FindVisitor(std::string query) : _query(query) {} + +const std::vector &FindVisitor::getFindings() { return findings; } + +void FindVisitor::visit(const PersonEntry &s) { + if (s.getName().find(_query) != std::string::npos) { + findings.push_back(&s); + } +} + +void FindVisitor::visit(const GroupEntry &g) { + if (g.getName().find(_query) != std::string::npos) { + findings.push_back(&g); + } +} + +void FindVisitor::visit(const CompanyEntry &c) { + + if (c.getName().find(_query) != std::string::npos || c.getCategory().find(_query) != std::string::npos) { + findings.push_back(&c); + } +} diff --git a/cmat/SolutionEx71/FindVisitor.h b/cmat/SolutionEx71/FindVisitor.h new file mode 100644 index 0000000..c185a52 --- /dev/null +++ b/cmat/SolutionEx71/FindVisitor.h @@ -0,0 +1,22 @@ + + +#ifndef FINDVISITOR_H +#define FINDVISITOR_H + +#include "Entry.h" +#include "EntryVisitor.h" +#include + +class FindVisitor : public EntryVisitor { + std::string _query; // looking for this + std::vector findings; // finding these entries + public: + FindVisitor(std::string query); + const std::vector &getFindings(); + + void visit(const PersonEntry &); + void visit(const CompanyEntry &); + void visit(const GroupEntry &); +}; + +#endif diff --git a/cmat/SolutionEx71/GroupEntry.cpp b/cmat/SolutionEx71/GroupEntry.cpp new file mode 100644 index 0000000..0c8b90a --- /dev/null +++ b/cmat/SolutionEx71/GroupEntry.cpp @@ -0,0 +1,35 @@ + +#include + +#include "EntryVisitor.h" +#include "GroupEntry.h" +#include "PersonEntry.h" + +GroupEntry::GroupEntry(std::string name) : Entry(name) {} + +void GroupEntry::print(std::string indent) const { + // print group name + std::cout << indent << "Group: " << getName() << '\n'; + + // Part 1: call print() on each group member (with increased indent level) + + for (auto p : _entries) { + p->print(indent + " "); + } +} + +void GroupEntry::addEntry(const Entry &entry) { + // Part 1: Add the entry to this group + + _entries.push_back(&entry); +} + +void GroupEntry::accept(EntryVisitor &v) const { + + v.visit(*this); + + // pass visitor to my children + for (auto p : _entries) { + p->accept(v); + } +} diff --git a/cmat/SolutionEx71/GroupEntry.h b/cmat/SolutionEx71/GroupEntry.h new file mode 100644 index 0000000..fdde291 --- /dev/null +++ b/cmat/SolutionEx71/GroupEntry.h @@ -0,0 +1,30 @@ + + +#ifndef GROUPENTRY_H +#define GROUPENTRY_H + +#include +#include +#include + +#include "Entry.h" +#include "PersonEntry.h" + +class GroupEntry : public Entry { + public: + GroupEntry(std::string name); + + // print the entire group, including its members + // precede the name with the "indent" string + void print(std::string indent = "") const; + + // child management + void addEntry(const Entry &); + + void accept(EntryVisitor &) const; + + private: + std::vector _entries; +}; + +#endif diff --git a/cmat/SolutionEx71/PersonEntry.cpp b/cmat/SolutionEx71/PersonEntry.cpp new file mode 100644 index 0000000..fc5721c --- /dev/null +++ b/cmat/SolutionEx71/PersonEntry.cpp @@ -0,0 +1,18 @@ + + +#include +#include + +#include "EntryVisitor.h" +#include "PersonEntry.h" + +PersonEntry::PersonEntry(std::string name, std::string phone) : Entry(name), _phone(phone) {} + +void PersonEntry::print(std::string indent) const { + + std::cout << indent << "Person: " << getName() << ' ' << _phone << '\n'; +} + +std::string PersonEntry::getPhone() const { return _phone; } + +void PersonEntry::accept(EntryVisitor &v) const { v.visit(*this); } diff --git a/cmat/SolutionEx71/PersonEntry.h b/cmat/SolutionEx71/PersonEntry.h new file mode 100644 index 0000000..61b3326 --- /dev/null +++ b/cmat/SolutionEx71/PersonEntry.h @@ -0,0 +1,22 @@ + + +#ifndef PERSONENTRY_H +#define PERSONENTRY_H + +#include "Entry.h" + +class PersonEntry : public Entry { + public: + PersonEntry(std::string name, std::string phone); + + void print(std::string indent = "") const; + + std::string getPhone() const; + + void accept(EntryVisitor &) const; + + private: + std::string _phone; +}; + +#endif diff --git a/cmat/SolutionEx71/main.cpp b/cmat/SolutionEx71/main.cpp new file mode 100644 index 0000000..9b3f6a8 --- /dev/null +++ b/cmat/SolutionEx71/main.cpp @@ -0,0 +1,70 @@ + + +#include "CompanyEntry.h" +#include "CountVisitor.h" +#include "FindVisitor.h" +#include "GroupEntry.h" +#include "PersonEntry.h" +#include + +using namespace std; + +int main() { + + // declare an address book + GroupEntry addressbook("My addressbook"); + + // create some entries + PersonEntry Fred("Fred", "555 1234"); + PersonEntry Gert("Gert", "555 1235"); + PersonEntry Jim("Jim", "999 2445"); + PersonEntry Sue("Sue", "456 2951"); + PersonEntry Ingar("Ingar", "999 2345"); + PersonEntry Lisa("Lisa", "443 4532"); + CompanyEntry ShoeWorld("ShoeWorld", "Shoes", "234 4314"); + CompanyEntry BestBurgers("BestBurgers", "Food", "456 4651"); + CompanyEntry DreamPizza("DreamPizza", "Food", "935 2345"); + CompanyEntry BestBooks("BestBooks", "Books", "345 3232"); + + // add some simple entries + addressbook.addEntry(Fred); + addressbook.addEntry(Gert); + addressbook.addEntry(ShoeWorld); + + // make some groups + GroupEntry group1("My Best Food"); + group1.addEntry(BestBurgers); + group1.addEntry(DreamPizza); + + GroupEntry group2("Coworkers"); + group2.addEntry(Jim); + group2.addEntry(Sue); + + // make a nested group + GroupEntry group3("Favorites"); + group3.addEntry(Ingar); + group3.addEntry(Lisa); + group3.addEntry(BestBooks); + group3.addEntry(group1); + + addressbook.addEntry(group2); + addressbook.addEntry(group3); + + cout << "*** Print using Composite print operation\n"; + addressbook.print(); + + cout << "*** Find using Visitor\n"; + FindVisitor pv("Fred"); + addressbook.accept(pv); + for (const Entry *p : pv.getFindings()) { + p->print(); + } + + cout << "*** Print Entry counts using Visitor\n"; + CountVisitor cv; + addressbook.accept(cv); + cv.printCounts(); + + cout << "*** Test complete\n"; + return 0; +} diff --git a/cmat/SolutionEx71A/CMakeLists.txt b/cmat/SolutionEx71A/CMakeLists.txt new file mode 100644 index 0000000..0772148 --- /dev/null +++ b/cmat/SolutionEx71A/CMakeLists.txt @@ -0,0 +1,14 @@ +# SolutionEx71A + +cmat_add_exercise(SolutionEx71A + GUI + SOURCES + ConsolePoleVisitor.cpp + Light.cpp + main.cpp + Pelican.cpp + Pole.cpp + Subject.cpp + Timer.cpp + TimerSet.cpp +) diff --git a/cmat/SolutionEx71A/ConsolePoleVisitor.cpp b/cmat/SolutionEx71A/ConsolePoleVisitor.cpp new file mode 100644 index 0000000..976e156 --- /dev/null +++ b/cmat/SolutionEx71A/ConsolePoleVisitor.cpp @@ -0,0 +1,12 @@ + + +#include "ConsolePoleVisitor.h" +#include "Light.h" +#include "Pole.h" +#include "Screen.h" + +void ConsolePoleVisitor::update(const Hint &h) { MyPole.accept(*this); } + +ConsolePoleVisitor::ConsolePoleVisitor(Pole &p) : MyPole(p) { MyPole.accept(*this); } + +void ConsolePoleVisitor::visit(Light &l) { Screen::write(l.getString(), l.getX(), l.getY(), l.getColor()); } diff --git a/cmat/SolutionEx71A/ConsolePoleVisitor.h b/cmat/SolutionEx71A/ConsolePoleVisitor.h new file mode 100644 index 0000000..0a6de9b --- /dev/null +++ b/cmat/SolutionEx71A/ConsolePoleVisitor.h @@ -0,0 +1,21 @@ + + +#ifndef CONSOLEPOLEVISITOR_H +#define CONSOLEPOLEVISITOR_H + +#include "Observer.h" + +class Pole; +#include "PoleVisitor.h" + +class ConsolePoleVisitor : public Observer, public PoleVisitor { + public: + ConsolePoleVisitor(Pole &); + virtual void update(const Hint &); + virtual void visit(Light &); + + private: + Pole &MyPole; +}; + +#endif diff --git a/cmat/SolutionEx71A/Ex71.sln b/cmat/SolutionEx71A/Ex71.sln new file mode 100644 index 0000000..7611fff --- /dev/null +++ b/cmat/SolutionEx71A/Ex71.sln @@ -0,0 +1,20 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ex71", "Ex71.vcxproj", "{3D7880AE-E251-9B65-4D9A-70B4E2BCB93C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3D7880AE-E251-9B65-4D9A-70B4E2BCB93C}.Debug|Win32.ActiveCfg = Debug|Win32 + {3D7880AE-E251-9B65-4D9A-70B4E2BCB93C}.Debug|Win32.Build.0 = Debug|Win32 + {3D7880AE-E251-9B65-4D9A-70B4E2BCB93C}.Release|Win32.ActiveCfg = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/cmat/SolutionEx71A/Ex71.suo b/cmat/SolutionEx71A/Ex71.suo new file mode 100644 index 0000000..d388461 Binary files /dev/null and b/cmat/SolutionEx71A/Ex71.suo differ diff --git a/cmat/SolutionEx71A/Ex71.vcproj b/cmat/SolutionEx71A/Ex71.vcproj new file mode 100644 index 0000000..7a82d29 --- /dev/null +++ b/cmat/SolutionEx71A/Ex71.vcproj @@ -0,0 +1,218 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cmat/SolutionEx71A/Ex71.vcxproj b/cmat/SolutionEx71A/Ex71.vcxproj new file mode 100644 index 0000000..09d74b1 --- /dev/null +++ b/cmat/SolutionEx71A/Ex71.vcxproj @@ -0,0 +1,151 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + {3D7880AE-E251-9B65-4D9A-70B4E2BCB93C} + + + + Application + false + MultiByte + v140 + + + Application + false + MultiByte + v140 + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + .\Release\ + .\Release\ + false + .\Debug\ + .\Debug\ + true + + + + OnlyExplicitInline + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + true + + + .\Release/Ex71.pch + .\Release/ + .\Release/ + .\Release/ + Level3 + true + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Release/Ex71.exe + true + .\Release/Ex71.pdb + Console + + + .\Release/Ex71.tlb + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + true + NotUsing + .\Debug/Ex71.pch + .\Debug/ + .\Debug/ + .\Debug/ + Level3 + true + ProgramDatabase + C:\course\397\DOS_Unix;%(AdditionalIncludeDirectories) + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Debug/Ex71.exe + true + true + .\Debug/Ex71.pdb + Console + + + .\Debug/Ex71.tlb + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + + + + + + + + + $(IntDir)%(Filename)1.obj + $(IntDir)%(Filename)1.obj + + + $(IntDir)%(Filename)1.obj + $(IntDir)%(Filename)1.obj + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cmat/SolutionEx71A/Ex71.vcxproj.filters b/cmat/SolutionEx71A/Ex71.vcxproj.filters new file mode 100644 index 0000000..8f7449c --- /dev/null +++ b/cmat/SolutionEx71A/Ex71.vcxproj.filters @@ -0,0 +1,80 @@ + + + + + {0b227cf9-5391-4e90-8d9f-fc451731aeee} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {da5f2d9c-de70-4bec-afc6-e895bd2dad8c} + h;hpp;hxx;hm;inl + + + {a539e3af-b783-430f-b157-9886e19d62cc} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + DOS_Unix + + + DOS_Unix + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + DOS_Unix + + + DOS_Unix + + + Header Files + + + \ No newline at end of file diff --git a/cmat/SolutionEx71A/Ex71.vcxproj.user b/cmat/SolutionEx71A/Ex71.vcxproj.user new file mode 100644 index 0000000..695b5c7 --- /dev/null +++ b/cmat/SolutionEx71A/Ex71.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cmat/SolutionEx71A/Light.cpp b/cmat/SolutionEx71A/Light.cpp new file mode 100644 index 0000000..d253045 --- /dev/null +++ b/cmat/SolutionEx71A/Light.cpp @@ -0,0 +1,25 @@ + +#include "Light.h" +#include "PoleVisitor.h" +#include + +Light::Light(std::string name, int x, int y, int color) : x(x), y(y), c(color), name(name) {} + +Light::~Light() { + std::cout << "Deleting light (" << name << ", " << x << ", " << y << ", " << c << ")" + << "\n"; +} + +void Light::accept(PoleVisitor &pv) { pv.visit(*this); } + +void Light::set(LightState new_state) { state = new_state; } + +Light::LightState Light::get(void) { return state; } + +int Light::getColor(void) { return state == OFF ? 0 : (state == FLASH ? 128 + c : c); } + +std::string Light::getString() { return name; } + +int Light::getX() { return x; } + +int Light::getY() { return y; } diff --git a/cmat/SolutionEx71A/Light.h b/cmat/SolutionEx71A/Light.h new file mode 100644 index 0000000..235b4c8 --- /dev/null +++ b/cmat/SolutionEx71A/Light.h @@ -0,0 +1,34 @@ + + +#ifndef LIGHT_H +#define LIGHT_H + +#include + +class PoleVisitor; + +class Light { + public: + Light(std::string name, int x, int y, int color); + ~Light(); + + enum LightState { ON, OFF, FLASH }; + + int getColor(); + std::string getString(); + int getX(); + int getY(); + + void set(LightState newState); // now just sets the state + LightState get(void); + + void accept(PoleVisitor &); + + private: + int c; // light color + int x, y; + std::string name; + LightState state; +}; + +#endif diff --git a/cmat/SolutionEx71A/Observer.h b/cmat/SolutionEx71A/Observer.h new file mode 100644 index 0000000..8304c48 --- /dev/null +++ b/cmat/SolutionEx71A/Observer.h @@ -0,0 +1,12 @@ + +#ifndef OBSERVER_H +#define OBSERVER_H + +#include "Subject.h" + +class Observer { + public: + virtual void update(const Hint &) = 0; +}; + +#endif diff --git a/cmat/SolutionEx71A/Pelican.cpp b/cmat/SolutionEx71A/Pelican.cpp new file mode 100644 index 0000000..a712e9f --- /dev/null +++ b/cmat/SolutionEx71A/Pelican.cpp @@ -0,0 +1,59 @@ + + +#include "Pelican.h" +#include "Pole.h" +#include "Timer.h" + +Pelican::Pelican() : pressed(false), RED_TIME(4), YELLOW_TIME(2), GREEN_TIME(3), FLASH_TIME(5), state(GREEN_IDLE) { + myTimer = new Timer([this] { timerExpired(); }); +} + +void Pelican::press(void) { + if (state == GREEN_IDLE) { + state = YELLOW_STATE; + myTimer->timeoutRequest(YELLOW_TIME); + pressed = true; + + notify(WaitHint(pressed)); + notify(LightHint(state)); + } else if (state != RED_STATE) { + pressed = true; + notify(WaitHint(pressed)); + } +} + +void Pelican::timerExpired(void) { + switch (state) { + case RED_STATE: + state = YELLOW_FLASHING; + myTimer->timeoutRequest(FLASH_TIME); + break; + + case YELLOW_FLASHING: + state = GREEN_TIMING; + myTimer->timeoutRequest(GREEN_TIME); + break; + + case GREEN_TIMING: + if (pressed) { + state = YELLOW_STATE; + myTimer->timeoutRequest(YELLOW_TIME); + } else { + state = GREEN_IDLE; + } + break; + + case GREEN_IDLE: + // should never happen + break; + + case YELLOW_STATE: + state = RED_STATE; + pressed = false; + notify(WaitHint(pressed)); + myTimer->timeoutRequest(RED_TIME); + break; + } + + notify(LightHint(state)); +} diff --git a/cmat/SolutionEx71A/Pelican.h b/cmat/SolutionEx71A/Pelican.h new file mode 100644 index 0000000..ab3ad46 --- /dev/null +++ b/cmat/SolutionEx71A/Pelican.h @@ -0,0 +1,64 @@ +// ====================================================== +// +// Represents a Pelican crossing +// +// ====================================================== + +#ifndef PELICAN_H +#define PELICAN_H + +#include "Subject.h" +#include "Timer.h" + +class Pelican : public Subject { + public: + Pelican(); + + // call when the WAIT button has been pressed + void press(void); + + // states that a Pelican can be in + enum PelicanState { RED_STATE, YELLOW_FLASHING, GREEN_TIMING, GREEN_IDLE, YELLOW_STATE }; + + bool isPressed() const { return pressed; } + PelicanState getState() const { return state; } + + private: + // state that this Pelican is in + PelicanState state; + + // called by PeleicanTimer when the lights need to change + void timerExpired(void); + + const unsigned int RED_TIME; + const unsigned int YELLOW_TIME; + const unsigned int GREEN_TIME; + const unsigned int FLASH_TIME; + + // indicates whether the WAIT light should be on + bool pressed; + + // Timer that indicates when the lights should change + Timer *myTimer; + + private: + // prevent general use of copy ctor and operator= + Pelican(const Pelican &); + Pelican &operator=(const Pelican &); +}; + +class LightHint : public Hint { + public: + LightHint(Pelican::PelicanState s) : state(s) {} + + Pelican::PelicanState state; +}; + +class WaitHint : public Hint { + public: + WaitHint(bool p) : pressed(p) {} + + bool pressed; +}; + +#endif diff --git a/cmat/SolutionEx71A/Pole.cpp b/cmat/SolutionEx71A/Pole.cpp new file mode 100644 index 0000000..8d81d79 --- /dev/null +++ b/cmat/SolutionEx71A/Pole.cpp @@ -0,0 +1,93 @@ + + +#include + +#include "Pelican.h" +#include "Pole.h" +#include "PoleVisitor.h" +#include "Screen.h" + +void Pole::accept(PoleVisitor &pv) { + for (int i = RED_LIGHT; i <= RED_MAN; i++) { + lights[i]->accept(pv); + } + waitLight->accept(pv); +} + +Pole::Pole(int x, int y, Pelican &pelican) + : waitLight(new Light("WAIT", x + 6, y + 12, Screen::WHITE)), myPelican(pelican) { + using namespace Screen; + + lights[RED_LIGHT] = new Light("*", x + 11, y + 3, RED); + lights[RED_MAN] = new Light("*<-=", x + 6, y + 4, RED); + lights[YELLOW_LIGHT] = new Light("*", x + 11, y + 5, YELLOW); + lights[GREEN_LIGHT] = new Light("*", x + 11, y + 7, GREEN); + lights[GREEN_MAN] = new Light("*|-<", x + 6, y + 7, GREEN); + + write(" _____ ", x, ++y, GRAY); + write(" /___ /| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" | |/| ", x, ++y, GRAY); + write(" |____| | ", x, ++y, GRAY); + write(" | |/| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" |____|/ ", x, ++y, GRAY); + write(" _||__ ", x, ++y, GRAY); + write(" /___ /| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" |____|/ ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write("========||===========", x, ++y, GRAY); + write(" / || / ", x, ++y, GRAY); + write("_ /_________ /_ ", x, ++y, GRAY); + write("/ / ", x, ++y, GRAY); + + // the only time we need to ask the Pelican its state is at start up + update(Hint()); +} + +Pole::~Pole() { + for (int i = 0; i < sizeof lights / sizeof(lights[0]); ++i) + delete lights[i]; + delete waitLight; +} + +void Pole::update(const Hint &h) { + if (typeid(h) == typeid(WaitHint)) { + const WaitHint *whPtr = dynamic_cast(&h); + setWaitLight(whPtr->pressed); + } else if (typeid(h) == typeid(LightHint)) { + const LightHint &lh = dynamic_cast(h); + setTrafficLights(lh.state); + } else { + // get the state and update everything + setWaitLight(myPelican.isPressed()); + setTrafficLights(myPelican.getState()); + notify(Hint()); + } + + notify(h); +} + +void Pole::setTrafficLights(Pelican::PelicanState state) { + static const Light::LightState LightStates[Pelican::YELLOW_STATE + 1][RED_MAN + 1] = { + // red yellow green green man red man + {Light::ON, Light::OFF, Light::OFF, Light::ON, Light::OFF}, // red + {Light::OFF, Light::FLASH, Light::OFF, Light::FLASH, Light::OFF}, // y flash + {Light::OFF, Light::OFF, Light::ON, Light::OFF, Light::ON}, // g time + {Light::OFF, Light::OFF, Light::ON, Light::OFF, Light::ON}, // g idle + {Light::OFF, Light::ON, Light::OFF, Light::OFF, Light::ON} // yellow + }; + + for (int i = RED_LIGHT; i <= RED_MAN; i++) { + lights[i]->set(LightStates[state][i]); + } +} + +void Pole::setWaitLight(bool state) { waitLight->set(state ? Light::ON : Light::OFF); } diff --git a/cmat/SolutionEx71A/Pole.h b/cmat/SolutionEx71A/Pole.h new file mode 100644 index 0000000..37e11dd --- /dev/null +++ b/cmat/SolutionEx71A/Pole.h @@ -0,0 +1,35 @@ + + +#ifndef POLE_H +#define POLE_H + +#include "Light.h" +#include "Observer.h" +#include "Pelican.h" +#include "Subject.h" + +class Hint; +class PoleVisitor; + +class Pole : public Observer, public Subject { + public: + void update(const Hint &); + + void accept(PoleVisitor &); + + Pole(int x, int y, Pelican &p); + ~Pole(); + + private: + Pelican &myPelican; + + void setTrafficLights(Pelican::PelicanState); + void setWaitLight(bool); + + enum LightName { RED_LIGHT, YELLOW_LIGHT, GREEN_LIGHT, GREEN_MAN, RED_MAN }; + + Light *lights[RED_MAN + 1]; + Light *waitLight; +}; + +#endif diff --git a/cmat/SolutionEx71A/PoleVisitor.h b/cmat/SolutionEx71A/PoleVisitor.h new file mode 100644 index 0000000..c8d2cc6 --- /dev/null +++ b/cmat/SolutionEx71A/PoleVisitor.h @@ -0,0 +1,15 @@ +// ====================================================== +// PoleVisitor.h +// ====================================================== + +#ifndef POLEVISITOR_H +#define POLEVISITOR_H + +class Light; + +class PoleVisitor { + public: + virtual void visit(Light &) = 0; +}; + +#endif diff --git a/cmat/SolutionEx71A/Subject.cpp b/cmat/SolutionEx71A/Subject.cpp new file mode 100644 index 0000000..bb73802 --- /dev/null +++ b/cmat/SolutionEx71A/Subject.cpp @@ -0,0 +1,12 @@ + + +#include "Subject.h" +#include "Observer.h" + +void Subject::attach(Observer &obs) { myObservers.insert(&obs); } + +void Subject::notify(const Hint &h) const { + for (ObsList::const_iterator iter = myObservers.begin(); iter != myObservers.end(); ++iter) { + (*iter)->update(h); + } +} diff --git a/cmat/SolutionEx71A/Subject.h b/cmat/SolutionEx71A/Subject.h new file mode 100644 index 0000000..46c2de8 --- /dev/null +++ b/cmat/SolutionEx71A/Subject.h @@ -0,0 +1,27 @@ + + +#ifndef SUBJECT_H +#define SUBJECT_H + +class Observer; + +#include + +class Hint { + public: + virtual ~Hint() {} +}; + +class Subject { + public: + typedef std::set ObsList; + void attach(Observer &obs); + + protected: + void notify(const Hint &) const; + + private: + ObsList myObservers; +}; + +#endif diff --git a/cmat/SolutionEx71A/Timer.cpp b/cmat/SolutionEx71A/Timer.cpp new file mode 100644 index 0000000..36d0627 --- /dev/null +++ b/cmat/SolutionEx71A/Timer.cpp @@ -0,0 +1,25 @@ + + +#include "Timer.h" +#include "TimerSet.h" + +void Timer::timeoutRequest(int seconds) { timeToGo = seconds; } + +Timer::Timer(std::function action) : timeToGo(-1), doExpired(action) { + TimerSet::Instance().addATimer(this); +} + +void Timer::tick() { + if (isExpired()) { + doExpired(); + } +} + +bool Timer::isExpired() { + if (timeToGo > 0) { + if (--timeToGo == 0) { + return true; + } + } + return false; +} diff --git a/cmat/SolutionEx71A/Timer.h b/cmat/SolutionEx71A/Timer.h new file mode 100644 index 0000000..8d5e8a4 --- /dev/null +++ b/cmat/SolutionEx71A/Timer.h @@ -0,0 +1,33 @@ +// ====================================================== +// +// A general-purpose countdown timer +// To use this class, specialize it +// and override tick() +// +// ====================================================== + +#ifndef timer_H +#define timer_H + +#include +#include + +class Timer { + public: + Timer(std::function action); + + void timeoutRequest(int seconds); + + // template method + void tick(); + + protected: + bool isExpired(); + + private: + std::function doExpired; + + int timeToGo; +}; + +#endif diff --git a/cmat/SolutionEx71A/TimerSet.cpp b/cmat/SolutionEx71A/TimerSet.cpp new file mode 100644 index 0000000..fdfabd4 --- /dev/null +++ b/cmat/SolutionEx71A/TimerSet.cpp @@ -0,0 +1,37 @@ +#include "TimerSet.h" +#include "Timer.h" +#include + +// Member functions + +TimerSet::TimerSet() + : previousTime(time(&previousTime)), pollingThread([this]() { poll10Hz(); }) // Exercise 5.1 start thread +{ + pollingThread.detach(); // let it die on its own, without join +} + +// Exercise 5.1 new function +void TimerSet::poll10Hz() { + std::chrono::duration pause(100); + while (true) { + std::this_thread::sleep_for(pause); + pollAllTimers(); + } +} + +void TimerSet::addATimer(Timer *t) { timers.push_back(t); } + +void TimerSet::pollAllTimers() { + std::time_t timeNow; + if (time(&timeNow) > previousTime) { + previousTime = timeNow; + for (auto it = timers.begin(); it != timers.end(); it++) { + (*it)->tick(); + } + } +} + +TimerSet &TimerSet::Instance() { + static TimerSet pInstance; + return pInstance; +} diff --git a/cmat/SolutionEx71A/TimerSet.h b/cmat/SolutionEx71A/TimerSet.h new file mode 100644 index 0000000..1a027f3 --- /dev/null +++ b/cmat/SolutionEx71A/TimerSet.h @@ -0,0 +1,33 @@ +#ifndef TIMERSET_H +#define TIMERSET_H + +#include +#include +#include + +class Timer; + +class TimerSet { + public: + void pollAllTimers(); + void addATimer(Timer *); + + private: + TimerSet(); + std::vector timers; + std::time_t previousTime; + + // Exercise 5.1 Threading two new members + std::thread pollingThread; + void poll10Hz(); + + // Meyer's Singleton + public: + static TimerSet &Instance(); + + private: + TimerSet(const TimerSet &); + TimerSet &operator=(const TimerSet &); +}; + +#endif diff --git a/cmat/SolutionEx71A/main.cpp b/cmat/SolutionEx71A/main.cpp new file mode 100644 index 0000000..a571f0b --- /dev/null +++ b/cmat/SolutionEx71A/main.cpp @@ -0,0 +1,36 @@ + + +#include "ConsolePoleVisitor.h" +#include "Keyboard.h" +#include "Pelican.h" +#include "Pole.h" +#include "TimerSet.h" + +#include // provides toupper() + +int main() { + Keyboard kbd; + Pelican thePelican; + + Pole pole1(20, 0, thePelican); + thePelican.attach(pole1); + ConsolePoleVisitor cp1(pole1); + pole1.attach(cp1); + + Pole pole2(40, 0, thePelican); + thePelican.attach(pole2); + ConsolePoleVisitor cp2(pole2); + pole2.attach(cp2); + + char c = 0; + + while (std::toupper(c) != 'Q') { // loop until 'Q' is pressed + c = kbd.getChar(); // get the character + if (c == ' ') { + // it's a space, so press the WAIT button + thePelican.press(); + } + } + + return 0; +} diff --git a/cmat/SolutionEx71ABonus/CMakeLists.txt b/cmat/SolutionEx71ABonus/CMakeLists.txt new file mode 100644 index 0000000..c81bf67 --- /dev/null +++ b/cmat/SolutionEx71ABonus/CMakeLists.txt @@ -0,0 +1,15 @@ +# SolutionEx71ABonus + +cmat_add_exercise(SolutionEx71ABonus + GUI + SOURCES + ConsolePoleVisitor.cpp + Light.cpp + main.cpp + Pelican.cpp + Pole.cpp + PowerVisitor.cpp + Subject.cpp + Timer.cpp + TimerSet.cpp +) diff --git a/cmat/SolutionEx71ABonus/ConsolePoleVisitor.cpp b/cmat/SolutionEx71ABonus/ConsolePoleVisitor.cpp new file mode 100644 index 0000000..8642fff --- /dev/null +++ b/cmat/SolutionEx71ABonus/ConsolePoleVisitor.cpp @@ -0,0 +1,14 @@ +// ====================================================== +// ConsolePole.cpp +// ====================================================== + +#include "ConsolePoleVisitor.h" +#include "Light.h" +#include "Pole.h" +#include "Screen.h" + +void ConsolePoleVisitor::update(const Hint &h) { MyPole.accept(*this); } + +ConsolePoleVisitor::ConsolePoleVisitor(Pole &p) : MyPole(p) { MyPole.accept(*this); } + +void ConsolePoleVisitor::visit(Light &l) { Screen::write(l.getString(), l.getX(), l.getY(), l.getColor()); } diff --git a/cmat/SolutionEx71ABonus/ConsolePoleVisitor.h b/cmat/SolutionEx71ABonus/ConsolePoleVisitor.h new file mode 100644 index 0000000..418a622 --- /dev/null +++ b/cmat/SolutionEx71ABonus/ConsolePoleVisitor.h @@ -0,0 +1,23 @@ +// ====================================================== +// ConsolePole.h +// ====================================================== + +#ifndef CONSOLEPOLEVISITOR_H +#define CONSOLEPOLEVISITOR_H + +#include "Observer.h" + +class Pole; +#include "PoleVisitor.h" + +class ConsolePoleVisitor : public Observer, public PoleVisitor { + public: + ConsolePoleVisitor(Pole &); + virtual void update(const Hint &); + virtual void visit(Light &); + + private: + Pole &MyPole; +}; + +#endif diff --git a/cmat/SolutionEx71ABonus/Ex71.sln b/cmat/SolutionEx71ABonus/Ex71.sln new file mode 100644 index 0000000..340c124 --- /dev/null +++ b/cmat/SolutionEx71ABonus/Ex71.sln @@ -0,0 +1,20 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.31101.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ex71", "Ex71.vcxproj", "{3D7880AE-E251-9B65-4D9A-70B4E2BCB93C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3D7880AE-E251-9B65-4D9A-70B4E2BCB93C}.Debug|Win32.ActiveCfg = Debug|Win32 + {3D7880AE-E251-9B65-4D9A-70B4E2BCB93C}.Debug|Win32.Build.0 = Debug|Win32 + {3D7880AE-E251-9B65-4D9A-70B4E2BCB93C}.Release|Win32.ActiveCfg = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/cmat/SolutionEx71ABonus/Ex71.vcxproj b/cmat/SolutionEx71ABonus/Ex71.vcxproj new file mode 100644 index 0000000..428cd65 --- /dev/null +++ b/cmat/SolutionEx71ABonus/Ex71.vcxproj @@ -0,0 +1,154 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + {3D7880AE-E251-9B65-4D9A-70B4E2BCB93C} + + + + Application + false + MultiByte + v140 + + + Application + false + MultiByte + v140 + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + .\Release\ + .\Release\ + false + .\Debug\ + .\Debug\ + true + + + + OnlyExplicitInline + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + true + + + .\Release/Ex71.pch + .\Release/ + .\Release/ + .\Release/ + Level3 + true + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Release/Ex71.exe + true + .\Release/Ex71.pdb + Console + + + .\Release/Ex71.tlb + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + true + NotUsing + .\Debug/Ex71.pch + .\Debug/ + .\Debug/ + .\Debug/ + Level3 + true + ProgramDatabase + C:\course\397\DOS_Unix;%(AdditionalIncludeDirectories) + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Debug/Ex71.exe + true + true + .\Debug/Ex71.pdb + Console + + + .\Debug/Ex71.tlb + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + + + + + + + + + + $(IntDir)%(Filename)1.obj + $(IntDir)%(Filename)1.obj + + + $(IntDir)%(Filename)1.obj + $(IntDir)%(Filename)1.obj + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cmat/SolutionEx71ABonus/Ex71.vcxproj.filters b/cmat/SolutionEx71ABonus/Ex71.vcxproj.filters new file mode 100644 index 0000000..62b686b --- /dev/null +++ b/cmat/SolutionEx71ABonus/Ex71.vcxproj.filters @@ -0,0 +1,89 @@ + + + + + {0b227cf9-5391-4e90-8d9f-fc451731aeee} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {da5f2d9c-de70-4bec-afc6-e895bd2dad8c} + h;hpp;hxx;hm;inl + + + {a539e3af-b783-430f-b157-9886e19d62cc} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + DOS_Unix + + + DOS_Unix + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + DOS_Unix + + + DOS_Unix + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/cmat/SolutionEx71ABonus/Ex71.vcxproj.user b/cmat/SolutionEx71ABonus/Ex71.vcxproj.user new file mode 100644 index 0000000..695b5c7 --- /dev/null +++ b/cmat/SolutionEx71ABonus/Ex71.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cmat/SolutionEx71ABonus/Light.cpp b/cmat/SolutionEx71ABonus/Light.cpp new file mode 100644 index 0000000..88877ea --- /dev/null +++ b/cmat/SolutionEx71ABonus/Light.cpp @@ -0,0 +1,28 @@ +// ====================================================== +// Light.cpp +// ====================================================== + +#include "Light.h" +#include "PoleVisitor.h" +#include + +Light::Light(std::string name, int x, int y, int color) : x(x), y(y), c(color), name(name) {} + +Light::~Light() { + std::cout << "Deleting light (" << name << ", " << x << ", " << y << ", " << c << ")" + << "\n"; +} + +void Light::accept(PoleVisitor &pv) { pv.visit(*this); } + +void Light::set(LightState new_state) { state = new_state; } + +Light::LightState Light::get(void) { return state; } + +int Light::getColor(void) { return state == OFF ? 0 : (state == FLASH ? 128 + c : c); } + +std::string Light::getString() { return name; } + +int Light::getX() { return x; } + +int Light::getY() { return y; } diff --git a/cmat/SolutionEx71ABonus/Light.h b/cmat/SolutionEx71ABonus/Light.h new file mode 100644 index 0000000..5ed1913 --- /dev/null +++ b/cmat/SolutionEx71ABonus/Light.h @@ -0,0 +1,36 @@ +// ====================================================== +// Light.h +// ====================================================== + +#ifndef LIGHT_H +#define LIGHT_H + +#include + +class PoleVisitor; + +class Light { + public: + Light(std::string name, int x, int y, int color); + ~Light(); + + enum LightState { ON, OFF, FLASH }; + + int getColor(); + std::string getString(); + int getX(); + int getY(); + + void set(LightState newState); // now just sets the state + LightState get(void); + + void accept(PoleVisitor &); + + private: + int c; // light color + int x, y; + std::string name; + LightState state; +}; + +#endif diff --git a/cmat/SolutionEx71ABonus/Observer.h b/cmat/SolutionEx71ABonus/Observer.h new file mode 100644 index 0000000..82cec78 --- /dev/null +++ b/cmat/SolutionEx71ABonus/Observer.h @@ -0,0 +1,15 @@ +// ====================================================== +// Observer.h +// ====================================================== + +#ifndef OBSERVER_H +#define OBSERVER_H + +#include "Subject.h" + +class Observer { + public: + virtual void update(const Hint &) = 0; +}; + +#endif diff --git a/cmat/SolutionEx71ABonus/Pelican.cpp b/cmat/SolutionEx71ABonus/Pelican.cpp new file mode 100644 index 0000000..d78b35c --- /dev/null +++ b/cmat/SolutionEx71ABonus/Pelican.cpp @@ -0,0 +1,61 @@ +// ====================================================== +// Pelican.cpp +// ====================================================== + +#include "Pelican.h" +#include "Pole.h" +#include "Timer.h" + +Pelican::Pelican() : pressed(false), RED_TIME(4), YELLOW_TIME(2), GREEN_TIME(3), FLASH_TIME(5), state(GREEN_IDLE) { + myTimer = new Timer([this] { timerExpired(); }); +} + +void Pelican::press(void) { + if (state == GREEN_IDLE) { + state = YELLOW_STATE; + myTimer->timeoutRequest(YELLOW_TIME); + pressed = true; + + notify(WaitHint(pressed)); + notify(LightHint(state)); + } else if (state != RED_STATE) { + pressed = true; + notify(WaitHint(pressed)); + } +} + +void Pelican::timerExpired(void) { + switch (state) { + case RED_STATE: + state = YELLOW_FLASHING; + myTimer->timeoutRequest(FLASH_TIME); + break; + + case YELLOW_FLASHING: + state = GREEN_TIMING; + myTimer->timeoutRequest(GREEN_TIME); + break; + + case GREEN_TIMING: + if (pressed) { + state = YELLOW_STATE; + myTimer->timeoutRequest(YELLOW_TIME); + } else { + state = GREEN_IDLE; + } + break; + + case GREEN_IDLE: + // should never happen + break; + + case YELLOW_STATE: + state = RED_STATE; + pressed = false; + notify(WaitHint(pressed)); + myTimer->timeoutRequest(RED_TIME); + break; + } + + notify(LightHint(state)); +} diff --git a/cmat/SolutionEx71ABonus/Pelican.h b/cmat/SolutionEx71ABonus/Pelican.h new file mode 100644 index 0000000..c08d91b --- /dev/null +++ b/cmat/SolutionEx71ABonus/Pelican.h @@ -0,0 +1,65 @@ +// ====================================================== +// Pelican.h +// +// Represents a Pelican crossing +// +// ====================================================== + +#ifndef PELICAN_H +#define PELICAN_H + +#include "Subject.h" +#include "Timer.h" + +class Pelican : public Subject { + public: + Pelican(); + + // call when the WAIT button has been pressed + void press(void); + + // states that a Pelican can be in + enum PelicanState { RED_STATE, YELLOW_FLASHING, GREEN_TIMING, GREEN_IDLE, YELLOW_STATE }; + + bool isPressed() const { return pressed; } + PelicanState getState() const { return state; } + + private: + // state that this Pelican is in + PelicanState state; + + // called by PeleicanTimer when the lights need to change + void timerExpired(void); + + const unsigned int RED_TIME; + const unsigned int YELLOW_TIME; + const unsigned int GREEN_TIME; + const unsigned int FLASH_TIME; + + // indicates whether the WAIT light should be on + bool pressed; + + // Timer that indicates when the lights should change + Timer *myTimer; + + private: + // prevent general use of copy ctor and operator= + Pelican(const Pelican &); + Pelican &operator=(const Pelican &); +}; + +class LightHint : public Hint { + public: + LightHint(Pelican::PelicanState s) : state(s) {} + + Pelican::PelicanState state; +}; + +class WaitHint : public Hint { + public: + WaitHint(bool p) : pressed(p) {} + + bool pressed; +}; + +#endif diff --git a/cmat/SolutionEx71ABonus/Pole.cpp b/cmat/SolutionEx71ABonus/Pole.cpp new file mode 100644 index 0000000..29274ef --- /dev/null +++ b/cmat/SolutionEx71ABonus/Pole.cpp @@ -0,0 +1,95 @@ +// ====================================================== +// Pole.cpp +// ====================================================== + +#include + +#include "Pelican.h" +#include "Pole.h" +#include "PoleVisitor.h" +#include "Screen.h" + +void Pole::accept(PoleVisitor &pv) { + for (int i = RED_LIGHT; i <= RED_MAN; i++) { + lights[i]->accept(pv); + } + waitLight->accept(pv); +} + +Pole::Pole(int x, int y, Pelican &pelican) + : waitLight(new Light("WAIT", x + 6, y + 12, Screen::WHITE)), myPelican(pelican) { + using namespace Screen; + + lights[RED_LIGHT] = new Light("*", x + 11, y + 3, RED); + lights[RED_MAN] = new Light("*<-=", x + 6, y + 4, RED); + lights[YELLOW_LIGHT] = new Light("*", x + 11, y + 5, YELLOW); + lights[GREEN_LIGHT] = new Light("*", x + 11, y + 7, GREEN); + lights[GREEN_MAN] = new Light("*|-<", x + 6, y + 7, GREEN); + + write(" _____ ", x, ++y, GRAY); + write(" /___ /| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" | |/| ", x, ++y, GRAY); + write(" |____| | ", x, ++y, GRAY); + write(" | |/| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" |____|/ ", x, ++y, GRAY); + write(" _||__ ", x, ++y, GRAY); + write(" /___ /| ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" | | | ", x, ++y, GRAY); + write(" |____|/ ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write(" || ", x, ++y, GRAY); + write("========||===========", x, ++y, GRAY); + write(" / || / ", x, ++y, GRAY); + write("_ /_________ /_ ", x, ++y, GRAY); + write("/ / ", x, ++y, GRAY); + + // the only time we need to ask the Pelican its state is at start up + update(Hint()); +} + +Pole::~Pole() { + for (int i = 0; i < sizeof lights / sizeof(lights[0]); ++i) + delete lights[i]; + delete waitLight; +} + +void Pole::update(const Hint &h) { + if (typeid(h) == typeid(WaitHint)) { + const WaitHint *whPtr = dynamic_cast(&h); + setWaitLight(whPtr->pressed); + } else if (typeid(h) == typeid(LightHint)) { + const LightHint &lh = dynamic_cast(h); + setTrafficLights(lh.state); + } else { + // get the state and update everything + setWaitLight(myPelican.isPressed()); + setTrafficLights(myPelican.getState()); + notify(Hint()); + } + + notify(h); +} + +void Pole::setTrafficLights(Pelican::PelicanState state) { + static const Light::LightState LightStates[Pelican::YELLOW_STATE + 1][RED_MAN + 1] = { + // red yellow green green man red man + {Light::ON, Light::OFF, Light::OFF, Light::ON, Light::OFF}, // red + {Light::OFF, Light::FLASH, Light::OFF, Light::FLASH, Light::OFF}, // y flash + {Light::OFF, Light::OFF, Light::ON, Light::OFF, Light::ON}, // g time + {Light::OFF, Light::OFF, Light::ON, Light::OFF, Light::ON}, // g idle + {Light::OFF, Light::ON, Light::OFF, Light::OFF, Light::ON} // yellow + }; + + for (int i = RED_LIGHT; i <= RED_MAN; i++) { + lights[i]->set(LightStates[state][i]); + } +} + +void Pole::setWaitLight(bool state) { waitLight->set(state ? Light::ON : Light::OFF); } diff --git a/cmat/SolutionEx71ABonus/Pole.h b/cmat/SolutionEx71ABonus/Pole.h new file mode 100644 index 0000000..e2032ea --- /dev/null +++ b/cmat/SolutionEx71ABonus/Pole.h @@ -0,0 +1,37 @@ +// ====================================================== +// Pole.h +// ====================================================== + +#ifndef POLE_H +#define POLE_H + +#include "Light.h" +#include "Observer.h" +#include "Pelican.h" +#include "Subject.h" + +class Hint; +class PoleVisitor; + +class Pole : public Observer, public Subject { + public: + void update(const Hint &); + + void accept(PoleVisitor &); + + Pole(int x, int y, Pelican &p); + ~Pole(); + + private: + Pelican &myPelican; + + void setTrafficLights(Pelican::PelicanState); + void setWaitLight(bool); + + enum LightName { RED_LIGHT, YELLOW_LIGHT, GREEN_LIGHT, GREEN_MAN, RED_MAN }; + + Light *lights[RED_MAN + 1]; + Light *waitLight; +}; + +#endif diff --git a/cmat/SolutionEx71ABonus/PoleVisitor.h b/cmat/SolutionEx71ABonus/PoleVisitor.h new file mode 100644 index 0000000..c8d2cc6 --- /dev/null +++ b/cmat/SolutionEx71ABonus/PoleVisitor.h @@ -0,0 +1,15 @@ +// ====================================================== +// PoleVisitor.h +// ====================================================== + +#ifndef POLEVISITOR_H +#define POLEVISITOR_H + +class Light; + +class PoleVisitor { + public: + virtual void visit(Light &) = 0; +}; + +#endif diff --git a/cmat/SolutionEx71ABonus/PowerVisitor.cpp b/cmat/SolutionEx71ABonus/PowerVisitor.cpp new file mode 100644 index 0000000..09c0149 --- /dev/null +++ b/cmat/SolutionEx71ABonus/PowerVisitor.cpp @@ -0,0 +1,23 @@ +#include "PowerVisitor.h" +#include "Light.h" +#include "Pole.h" +#include + +void PowerVisitor::visit(Light &l) { + switch (l.get()) { + case Light::ON: + runningTotal += 60; + break; + case Light::FLASH: + runningTotal += 30; + break; + } +} + +void PowerVisitor::calculatePower(Pole &p) { + runningTotal = 0; + + p.accept(*this); + + std::cout << "Power usage is " << runningTotal << " watts.\n"; +} \ No newline at end of file diff --git a/cmat/SolutionEx71ABonus/PowerVisitor.h b/cmat/SolutionEx71ABonus/PowerVisitor.h new file mode 100644 index 0000000..a941522 --- /dev/null +++ b/cmat/SolutionEx71ABonus/PowerVisitor.h @@ -0,0 +1,15 @@ +#pragma once + +#include "PoleVisitor.h" + +class Pole; + +class PowerVisitor : public PoleVisitor { + private: + int runningTotal; + + public: + void visit(Light &l); + + void calculatePower(Pole &p); +}; diff --git a/cmat/SolutionEx71ABonus/Subject.cpp b/cmat/SolutionEx71ABonus/Subject.cpp new file mode 100644 index 0000000..ae5b35b --- /dev/null +++ b/cmat/SolutionEx71ABonus/Subject.cpp @@ -0,0 +1,14 @@ +// ====================================================== +// Subject.cpp +// ====================================================== + +#include "Subject.h" +#include "Observer.h" + +void Subject::attach(Observer &obs) { myObservers.insert(&obs); } + +void Subject::notify(const Hint &h) const { + for (ObsList::const_iterator iter = myObservers.begin(); iter != myObservers.end(); ++iter) { + (*iter)->update(h); + } +} diff --git a/cmat/SolutionEx71ABonus/Subject.h b/cmat/SolutionEx71ABonus/Subject.h new file mode 100644 index 0000000..b9c4f40 --- /dev/null +++ b/cmat/SolutionEx71ABonus/Subject.h @@ -0,0 +1,29 @@ +// ====================================================== +// Subject.h +// ====================================================== + +#ifndef SUBJECT_H +#define SUBJECT_H + +class Observer; + +#include + +class Hint { + public: + virtual ~Hint() {} +}; + +class Subject { + public: + typedef std::set ObsList; + void attach(Observer &obs); + + protected: + void notify(const Hint &) const; + + private: + ObsList myObservers; +}; + +#endif diff --git a/cmat/SolutionEx71ABonus/Timer.cpp b/cmat/SolutionEx71ABonus/Timer.cpp new file mode 100644 index 0000000..b508069 --- /dev/null +++ b/cmat/SolutionEx71ABonus/Timer.cpp @@ -0,0 +1,27 @@ +// ====================================================== +// timer.cpp +// ====================================================== + +#include "Timer.h" +#include "TimerSet.h" + +void Timer::timeoutRequest(int seconds) { timeToGo = seconds; } + +Timer::Timer(std::function action) : timeToGo(-1), doExpired(action) { + TimerSet::Instance().addATimer(this); +} + +void Timer::tick() { + if (isExpired()) { + doExpired(); + } +} + +bool Timer::isExpired() { + if (timeToGo > 0) { + if (--timeToGo == 0) { + return true; + } + } + return false; +} diff --git a/cmat/SolutionEx71ABonus/Timer.h b/cmat/SolutionEx71ABonus/Timer.h new file mode 100644 index 0000000..61cac90 --- /dev/null +++ b/cmat/SolutionEx71ABonus/Timer.h @@ -0,0 +1,34 @@ +// ====================================================== +// Timer.h +// +// A general-purpose countdown timer +// To use this class, specialize it +// and override tick() +// +// ====================================================== + +#ifndef timer_H +#define timer_H + +#include +#include + +class Timer { + public: + Timer(std::function action); + + void timeoutRequest(int seconds); + + // template method + void tick(); + + protected: + bool isExpired(); + + private: + std::function doExpired; + + int timeToGo; +}; + +#endif diff --git a/cmat/SolutionEx71ABonus/TimerSet.cpp b/cmat/SolutionEx71ABonus/TimerSet.cpp new file mode 100644 index 0000000..fdfabd4 --- /dev/null +++ b/cmat/SolutionEx71ABonus/TimerSet.cpp @@ -0,0 +1,37 @@ +#include "TimerSet.h" +#include "Timer.h" +#include + +// Member functions + +TimerSet::TimerSet() + : previousTime(time(&previousTime)), pollingThread([this]() { poll10Hz(); }) // Exercise 5.1 start thread +{ + pollingThread.detach(); // let it die on its own, without join +} + +// Exercise 5.1 new function +void TimerSet::poll10Hz() { + std::chrono::duration pause(100); + while (true) { + std::this_thread::sleep_for(pause); + pollAllTimers(); + } +} + +void TimerSet::addATimer(Timer *t) { timers.push_back(t); } + +void TimerSet::pollAllTimers() { + std::time_t timeNow; + if (time(&timeNow) > previousTime) { + previousTime = timeNow; + for (auto it = timers.begin(); it != timers.end(); it++) { + (*it)->tick(); + } + } +} + +TimerSet &TimerSet::Instance() { + static TimerSet pInstance; + return pInstance; +} diff --git a/cmat/SolutionEx71ABonus/TimerSet.h b/cmat/SolutionEx71ABonus/TimerSet.h new file mode 100644 index 0000000..1a027f3 --- /dev/null +++ b/cmat/SolutionEx71ABonus/TimerSet.h @@ -0,0 +1,33 @@ +#ifndef TIMERSET_H +#define TIMERSET_H + +#include +#include +#include + +class Timer; + +class TimerSet { + public: + void pollAllTimers(); + void addATimer(Timer *); + + private: + TimerSet(); + std::vector timers; + std::time_t previousTime; + + // Exercise 5.1 Threading two new members + std::thread pollingThread; + void poll10Hz(); + + // Meyer's Singleton + public: + static TimerSet &Instance(); + + private: + TimerSet(const TimerSet &); + TimerSet &operator=(const TimerSet &); +}; + +#endif diff --git a/cmat/SolutionEx71ABonus/main.cpp b/cmat/SolutionEx71ABonus/main.cpp new file mode 100644 index 0000000..c517ead --- /dev/null +++ b/cmat/SolutionEx71ABonus/main.cpp @@ -0,0 +1,43 @@ +// ================================================================= +// main.cpp (for pelican crossing program) +// ================================================================= + +#include "ConsolePoleVisitor.h" +#include "Keyboard.h" +#include "Pelican.h" +#include "Pole.h" +#include "PowerVisitor.h" +#include "TimerSet.h" + +#include // provides toupper() + +int main() { + Keyboard kbd; + Pelican thePelican; + + Pole pole1(20, 0, thePelican); + thePelican.attach(pole1); + ConsolePoleVisitor cp1(pole1); + pole1.attach(cp1); + + Pole pole2(40, 0, thePelican); + thePelican.attach(pole2); + ConsolePoleVisitor cp2(pole2); + pole2.attach(cp2); + + char c = 0; + + while (std::toupper(c) != 'Q') { // loop until 'Q' is pressed + c = kbd.getChar(); // get the character + if (c == ' ') { + // it's a space, so press the WAIT button + thePelican.press(); + } else if (c == 'p') { + PowerVisitor pv; + + pv.calculatePower(pole1); + } + } + + return 0; +} diff --git a/cmat/SolutionEx71Bonus/CMakeLists.txt b/cmat/SolutionEx71Bonus/CMakeLists.txt new file mode 100644 index 0000000..6fd7d7d --- /dev/null +++ b/cmat/SolutionEx71Bonus/CMakeLists.txt @@ -0,0 +1,12 @@ +# SolutionEx71Bonus + +cmat_add_exercise(SolutionEx71Bonus + SOURCES + CompanyEntry.cpp + CountVisitor.cpp + FindVisitor.cpp + GroupEntry.cpp + main.cpp + PersonEntry.cpp + PrintVisitor.cpp +) diff --git a/cmat/SolutionEx71Bonus/CompanyEntry.cpp b/cmat/SolutionEx71Bonus/CompanyEntry.cpp new file mode 100644 index 0000000..898dcc6 --- /dev/null +++ b/cmat/SolutionEx71Bonus/CompanyEntry.cpp @@ -0,0 +1,19 @@ +#include +#include + +#include "CompanyEntry.h" +#include "EntryVisitor.h" + +CompanyEntry::CompanyEntry(std::string name, std::string category, std::string phone) + : Entry(name), _category(category), _phone(phone) {} + +void CompanyEntry::print(std::string indent) const { + + std::cout << indent << "Company: " << getName() << " <" << _category << "> " << _phone << '\n'; +} + +std::string CompanyEntry::getPhone() const { return _phone; } + +std::string CompanyEntry::getCategory() const { return _category; } + +void CompanyEntry::accept(EntryVisitor &v) const { v.visit(*this); } \ No newline at end of file diff --git a/cmat/SolutionEx71Bonus/CompanyEntry.h b/cmat/SolutionEx71Bonus/CompanyEntry.h new file mode 100644 index 0000000..819ca0d --- /dev/null +++ b/cmat/SolutionEx71Bonus/CompanyEntry.h @@ -0,0 +1,22 @@ + +#ifndef COMPANYENTRY_H +#define COMPANYENTRY_H + +#include "Entry.h" + +class CompanyEntry : public Entry { + public: + CompanyEntry(std::string name, std::string category, std::string phone); + + void print(std::string indent = "") const; + std::string getPhone() const; + std::string getCategory() const; + + void accept(EntryVisitor &) const; + + private: + std::string _category; + std::string _phone; +}; + +#endif \ No newline at end of file diff --git a/cmat/SolutionEx71Bonus/CountVisitor.cpp b/cmat/SolutionEx71Bonus/CountVisitor.cpp new file mode 100644 index 0000000..db8cbc5 --- /dev/null +++ b/cmat/SolutionEx71Bonus/CountVisitor.cpp @@ -0,0 +1,14 @@ +#include "CountVisitor.h" +#include + +CountVisitor::CountVisitor() : nPerson(0), nCompany(0), nGroup(0) {} + +void CountVisitor::printCounts() { + std::cout << "Persons: " << nPerson << " Companies: " << nCompany << " Groups: " << nGroup << "\n"; +} + +void CountVisitor::visit(const PersonEntry &p) { nPerson++; } + +void CountVisitor::visit(const CompanyEntry &c) { nCompany++; } + +void CountVisitor::visit(const GroupEntry &g) { nGroup++; } \ No newline at end of file diff --git a/cmat/SolutionEx71Bonus/CountVisitor.h b/cmat/SolutionEx71Bonus/CountVisitor.h new file mode 100644 index 0000000..855fecf --- /dev/null +++ b/cmat/SolutionEx71Bonus/CountVisitor.h @@ -0,0 +1,15 @@ +#pragma once + +#include "EntryVisitor.h" +class CountVisitor : public EntryVisitor { + int nPerson, nCompany, nGroup; + + public: + CountVisitor(); + + void printCounts(); + + void visit(const PersonEntry &); + void visit(const CompanyEntry &); + void visit(const GroupEntry &); +}; diff --git a/cmat/SolutionEx71Bonus/Entry.cpp b/cmat/SolutionEx71Bonus/Entry.cpp new file mode 100644 index 0000000..a1a6fa7 --- /dev/null +++ b/cmat/SolutionEx71Bonus/Entry.cpp @@ -0,0 +1,5 @@ +// Entry.cpp + +#include "Entry.h" + +Entry::Entry(std::string name) : _name(name), _phone(phone) {} diff --git a/cmat/SolutionEx71Bonus/Entry.h b/cmat/SolutionEx71Bonus/Entry.h new file mode 100644 index 0000000..f38a2bd --- /dev/null +++ b/cmat/SolutionEx71Bonus/Entry.h @@ -0,0 +1,23 @@ + +#ifndef ENTRY_H +#define ENTRY_H + +#include + +class EntryVisitor; + +class Entry { + public: + Entry(std::string name) : _name(name) {} + + std::string getName() const { return _name; } + + virtual void print(std::string indent = "") const = 0; + + virtual void accept(EntryVisitor &) const = 0; + + private: + std::string _name; +}; + +#endif diff --git a/cmat/SolutionEx71Bonus/EntryVisitor.h b/cmat/SolutionEx71Bonus/EntryVisitor.h new file mode 100644 index 0000000..66b4d78 --- /dev/null +++ b/cmat/SolutionEx71Bonus/EntryVisitor.h @@ -0,0 +1,20 @@ +// EntryVisitor.h + +#ifndef ENTRYVISITOR_H +#define ENTRYVISITOR_H + +class PersonEntry; +class CompanyEntry; +class GroupEntry; + +class EntryVisitor { + public: + virtual void visit(const PersonEntry &) = 0; + virtual void visit(const CompanyEntry &) = 0; + virtual void visit(const GroupEntry &) = 0; + + virtual void unVisit(const GroupEntry &) { + } // In some cases, the composite node may need special processing after delegation to children +}; + +#endif diff --git a/cmat/SolutionEx71Bonus/Ex71.sln b/cmat/SolutionEx71Bonus/Ex71.sln new file mode 100644 index 0000000..a1c4809 --- /dev/null +++ b/cmat/SolutionEx71Bonus/Ex71.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ex71", "Ex71.vcxproj", "{3BE8ED56-4FC0-F86D-B9E1-1EE211AF78DB}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3BE8ED56-4FC0-F86D-B9E1-1EE211AF78DB}.Debug|Win32.ActiveCfg = Debug|Win32 + {3BE8ED56-4FC0-F86D-B9E1-1EE211AF78DB}.Debug|Win32.Build.0 = Debug|Win32 + {3BE8ED56-4FC0-F86D-B9E1-1EE211AF78DB}.Release|Win32.ActiveCfg = Release|Win32 + {3BE8ED56-4FC0-F86D-B9E1-1EE211AF78DB}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/cmat/SolutionEx71Bonus/Ex71.suo b/cmat/SolutionEx71Bonus/Ex71.suo new file mode 100644 index 0000000..d13baa0 Binary files /dev/null and b/cmat/SolutionEx71Bonus/Ex71.suo differ diff --git a/cmat/SolutionEx71Bonus/Ex71.v11.suo b/cmat/SolutionEx71Bonus/Ex71.v11.suo new file mode 100644 index 0000000..f22610a Binary files /dev/null and b/cmat/SolutionEx71Bonus/Ex71.v11.suo differ diff --git a/cmat/SolutionEx71Bonus/Ex71.vcxproj b/cmat/SolutionEx71Bonus/Ex71.vcxproj new file mode 100644 index 0000000..bf9ac8f --- /dev/null +++ b/cmat/SolutionEx71Bonus/Ex71.vcxproj @@ -0,0 +1,138 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + {3BE8ED56-4FC0-F86D-B9E1-1EE211AF78DB} + + + + Application + false + MultiByte + v140 + + + Application + false + MultiByte + v140 + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + .\Release\ + .\Release\ + false + .\Debug\ + .\Debug\ + true + + + + OnlyExplicitInline + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + true + + + .\Release/Ex71A.pch + .\Release/ + .\Release/ + .\Release/ + Level3 + true + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Release/Ex71A.exe + true + .\Release/Ex71A.pdb + Console + + + .\Release/Ex71A.tlb + + + NDEBUG;%(PreprocessorDefinitions) + 0x0809 + + + + + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + NotUsing + .\Debug/Ex71A.pch + .\Debug/ + .\Debug/ + .\Debug/ + Level3 + true + C:\course\397\DOS_Unix;%(AdditionalIncludeDirectories) + + + /MACHINE:I386 %(AdditionalOptions) + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + .\Debug/Ex71.exe + true + true + .\Debug/Ex71A.pdb + Console + + + .\Debug/Ex71A.tlb + + + _DEBUG;%(PreprocessorDefinitions) + 0x0809 + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cmat/SolutionEx71Bonus/Ex71.vcxproj.filters b/cmat/SolutionEx71Bonus/Ex71.vcxproj.filters new file mode 100644 index 0000000..3334c5b --- /dev/null +++ b/cmat/SolutionEx71Bonus/Ex71.vcxproj.filters @@ -0,0 +1,62 @@ + + + + + {a373d85d-0daa-4771-a2af-24735700f4b5} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {28280df5-d09d-4335-a70c-dd81eee4485f} + h;hpp;hxx;hm;inl + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/cmat/SolutionEx71Bonus/Ex71.vcxproj.user b/cmat/SolutionEx71Bonus/Ex71.vcxproj.user new file mode 100644 index 0000000..695b5c7 --- /dev/null +++ b/cmat/SolutionEx71Bonus/Ex71.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cmat/SolutionEx71Bonus/FindVisitor.cpp b/cmat/SolutionEx71Bonus/FindVisitor.cpp new file mode 100644 index 0000000..3bd42f1 --- /dev/null +++ b/cmat/SolutionEx71Bonus/FindVisitor.cpp @@ -0,0 +1,32 @@ +#pragma warning(disable : 4786) +// PrintVisitor.cpp + +#include + +#include "CompanyEntry.h" +#include "FindVisitor.h" +#include "GroupEntry.h" +#include "PersonEntry.h" + +FindVisitor::FindVisitor(std::string query) : _query(query) {} + +const std::vector &FindVisitor::getFindings() { return findings; } + +void FindVisitor::visit(const PersonEntry &s) { + if (s.getName().find(_query) != std::string::npos) { + findings.push_back(&s); + } +} + +void FindVisitor::visit(const GroupEntry &g) { + if (g.getName().find(_query) != std::string::npos) { + findings.push_back(&g); + } +} + +void FindVisitor::visit(const CompanyEntry &c) { + + if (c.getName().find(_query) != std::string::npos || c.getCategory().find(_query) != std::string::npos) { + findings.push_back(&c); + } +} diff --git a/cmat/SolutionEx71Bonus/FindVisitor.h b/cmat/SolutionEx71Bonus/FindVisitor.h new file mode 100644 index 0000000..c185a52 --- /dev/null +++ b/cmat/SolutionEx71Bonus/FindVisitor.h @@ -0,0 +1,22 @@ + + +#ifndef FINDVISITOR_H +#define FINDVISITOR_H + +#include "Entry.h" +#include "EntryVisitor.h" +#include + +class FindVisitor : public EntryVisitor { + std::string _query; // looking for this + std::vector findings; // finding these entries + public: + FindVisitor(std::string query); + const std::vector &getFindings(); + + void visit(const PersonEntry &); + void visit(const CompanyEntry &); + void visit(const GroupEntry &); +}; + +#endif diff --git a/cmat/SolutionEx71Bonus/GroupEntry.cpp b/cmat/SolutionEx71Bonus/GroupEntry.cpp new file mode 100644 index 0000000..eda90e6 --- /dev/null +++ b/cmat/SolutionEx71Bonus/GroupEntry.cpp @@ -0,0 +1,38 @@ +#pragma warning(disable : 4786) +// GroupEntry.cpp + +#include + +#include "EntryVisitor.h" +#include "GroupEntry.h" +#include "PersonEntry.h" + +GroupEntry::GroupEntry(std::string name) : Entry(name) {} + +void GroupEntry::print(std::string indent) const { + // print group name + std::cout << indent << "Group: " << getName() << '\n'; + + // Part 1: call print() on each group member (with increased indent level) + + for (auto p : _entries) { + p->print(indent + " "); + } +} + +void GroupEntry::addEntry(const Entry &entry) { + // Part 1: Add the entry to this group + + _entries.push_back(&entry); +} + +void GroupEntry::accept(EntryVisitor &v) const { + v.visit(*this); + + // pass visitor to my children + for (auto p : _entries) { + p->accept(v); + } + + v.unVisit(*this); +} diff --git a/cmat/SolutionEx71Bonus/GroupEntry.h b/cmat/SolutionEx71Bonus/GroupEntry.h new file mode 100644 index 0000000..dcb506a --- /dev/null +++ b/cmat/SolutionEx71Bonus/GroupEntry.h @@ -0,0 +1,30 @@ +// GroupEntry.h + +#ifndef GROUPENTRY_H +#define GROUPENTRY_H + +#include +#include +#include + +#include "Entry.h" +#include "PersonEntry.h" + +class GroupEntry : public Entry { + public: + GroupEntry(std::string name); + + // print the entire group, including its members + // precede the name with the "indent" string + void print(std::string indent = "") const; + + // child management + void addEntry(const Entry &); + + void accept(EntryVisitor &) const; + + private: + std::vector _entries; +}; + +#endif diff --git a/cmat/SolutionEx71Bonus/PersonEntry.cpp b/cmat/SolutionEx71Bonus/PersonEntry.cpp new file mode 100644 index 0000000..fc5721c --- /dev/null +++ b/cmat/SolutionEx71Bonus/PersonEntry.cpp @@ -0,0 +1,18 @@ + + +#include +#include + +#include "EntryVisitor.h" +#include "PersonEntry.h" + +PersonEntry::PersonEntry(std::string name, std::string phone) : Entry(name), _phone(phone) {} + +void PersonEntry::print(std::string indent) const { + + std::cout << indent << "Person: " << getName() << ' ' << _phone << '\n'; +} + +std::string PersonEntry::getPhone() const { return _phone; } + +void PersonEntry::accept(EntryVisitor &v) const { v.visit(*this); } diff --git a/cmat/SolutionEx71Bonus/PersonEntry.h b/cmat/SolutionEx71Bonus/PersonEntry.h new file mode 100644 index 0000000..61b3326 --- /dev/null +++ b/cmat/SolutionEx71Bonus/PersonEntry.h @@ -0,0 +1,22 @@ + + +#ifndef PERSONENTRY_H +#define PERSONENTRY_H + +#include "Entry.h" + +class PersonEntry : public Entry { + public: + PersonEntry(std::string name, std::string phone); + + void print(std::string indent = "") const; + + std::string getPhone() const; + + void accept(EntryVisitor &) const; + + private: + std::string _phone; +}; + +#endif diff --git a/cmat/SolutionEx71Bonus/PrintVisitor.cpp b/cmat/SolutionEx71Bonus/PrintVisitor.cpp new file mode 100644 index 0000000..4047f9f --- /dev/null +++ b/cmat/SolutionEx71Bonus/PrintVisitor.cpp @@ -0,0 +1,24 @@ +#include "PrintVisitor.h" +#include "CompanyEntry.h" +#include "GroupEntry.h" +#include "PersonEntry.h" +#include + +void PrintVisitor::visit(const PersonEntry &pe) { + std::cout << indent << "Person: " << pe.getName() << ' ' << pe.getPhone() << '\n'; +} + +void PrintVisitor::visit(const CompanyEntry &ce) { + std::cout << indent << "Company: " << ce.getName() << " <" << ce.getCategory() << "> " << ce.getPhone() << '\n'; +} + +void PrintVisitor::visit(const GroupEntry &ge) { + std::cout << indent << "Group: " << ge.getName() << '\n'; + + indent += " "; +} + +void PrintVisitor::unVisit(const GroupEntry &) { + // Get rid of the extra indent we added + indent = indent.substr(indent.length() - 2, 2); +} diff --git a/cmat/SolutionEx71Bonus/PrintVisitor.h b/cmat/SolutionEx71Bonus/PrintVisitor.h new file mode 100644 index 0000000..fcadcc8 --- /dev/null +++ b/cmat/SolutionEx71Bonus/PrintVisitor.h @@ -0,0 +1,19 @@ +#ifndef PRINTVISITOR_H +#define PRINTVISITOR_H + +#include "EntryVisitor.h" +#include + +class PrintVisitor : public EntryVisitor { + private: + std::string indent; + + public: + void visit(const PersonEntry &); + void visit(const CompanyEntry &); + void visit(const GroupEntry &); + + void unVisit(const GroupEntry &); +}; + +#endif diff --git a/cmat/SolutionEx71Bonus/main.cpp b/cmat/SolutionEx71Bonus/main.cpp new file mode 100644 index 0000000..fb52997 --- /dev/null +++ b/cmat/SolutionEx71Bonus/main.cpp @@ -0,0 +1,81 @@ +#pragma warning(disable : 4786) + +#include "CompanyEntry.h" +#include "CountVisitor.h" +#include "FindVisitor.h" +#include "GroupEntry.h" +#include "PersonEntry.h" +#include "PrintVisitor.h" +#include + +using namespace std; + +int main() { + + // declare an address book + GroupEntry addressbook("My addressbook"); + + // create some entries + PersonEntry Fred("Fred", "555 1234"); + PersonEntry Gert("Gert", "555 1235"); + PersonEntry Jim("Jim", "999 2445"); + PersonEntry Sue("Sue", "456 2951"); + PersonEntry Ingar("Ingar", "999 2345"); + PersonEntry Lisa("Lisa", "443 4532"); + CompanyEntry ShoeWorld("ShoeWorld", "Shoes", "234 4314"); + CompanyEntry BestBurgers("BestBurgers", "Food", "456 4651"); + CompanyEntry DreamPizza("DreamPizza", "Food", "935 2345"); + CompanyEntry BestBooks("BestBooks", "Books", "345 3232"); + + // add some simple entries + addressbook.addEntry(Fred); + addressbook.addEntry(Gert); + addressbook.addEntry(ShoeWorld); + + // make some groups + GroupEntry group1("My Best Food"); + group1.addEntry(BestBurgers); + group1.addEntry(DreamPizza); + + GroupEntry group2("Coworkers"); + group2.addEntry(Jim); + group2.addEntry(Sue); + + // make a nested group + GroupEntry group3("Favorites"); + group3.addEntry(Ingar); + group3.addEntry(Lisa); + group3.addEntry(BestBooks); + group3.addEntry(group1); + + addressbook.addEntry(group2); + addressbook.addEntry(group3); + + cout << "\n\n"; + + cout << "*** Print using Composite print operation\n"; + addressbook.print(); + + cout << "\n\n"; + + cout << "*** Print using PrintVisitor\n"; + PrintVisitor printVisitor; + addressbook.accept(printVisitor); + + cout << "\n\n"; + + cout << "*** Find using Visitor\n"; + FindVisitor pv("Fred"); + addressbook.accept(pv); + for (const Entry *p : pv.getFindings()) { + p->print(); + } + + cout << "*** Print Entry counts using Visitor\n"; + CountVisitor cv; + addressbook.accept(cv); + cv.printCounts(); + + cout << "*** Test complete\n"; + return 0; +} diff --git a/cmat/cleanall.bat b/cmat/cleanall.bat new file mode 100644 index 0000000..e1ded27 --- /dev/null +++ b/cmat/cleanall.bat @@ -0,0 +1,2 @@ +del /S *.ilk *.sdf *.obj *.pdb *.exe *.tlog *.log *.lastbuildstate *.lib *.idb *.exp file.dat file.xml +del /S /a:h *.suo \ No newline at end of file