Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
be9c07a
TASK1: .gitignore added
militant-daos Nov 21, 2021
79a2506
TASK1: Makefile and game sources added.
militant-daos Nov 21, 2021
10d014d
TASK1: Minor style fixes
militant-daos Nov 21, 2021
9ce3e0d
TASK1: MD5 output added, minor Makefile fixes.
militant-daos Nov 21, 2021
0500e43
TASK2: Add hwdetect device nodes monitoring script
militant-daos Nov 22, 2021
7eb27c2
TASK2: Fix a typo in the header comment
militant-daos Nov 22, 2021
93d1363
TASK2: Fix more typos
militant-daos Nov 22, 2021
9386c25
Bash HW: create hot plugged hardware detector
artemkomyshan Nov 21, 2021
7cef59c
Merge pull request #11 from artemkomyshan/bash_hw
artemkomyshan Nov 23, 2021
c0da3e3
Revert "Task2: Bash HW create hot plugged hardware detector"
artemkomyshan Nov 23, 2021
d89f0c0
Merge pull request #34 from Kernel-GL-HRK/revert-11-bash_hw
artemkomyshan Nov 23, 2021
4a9e2f5
TASK1: Project structure refactoring
militant-daos Nov 23, 2021
3099c4e
Merge pull request #10 from militant-daos/Victor.Krasnoshchok
militant-daos Nov 24, 2021
2eb9991
Merge pull request #21 from militant-daos/task02
militant-daos Nov 24, 2021
d907e98
Merge branch 'Kernel-GL-HRK:main' into main
militant-daos Nov 24, 2021
4f320db
TASK3: Implement a basic module with params.
militant-daos Nov 28, 2021
e974d1f
TASK3: Fix typos.
militant-daos Nov 28, 2021
c476298
TASK3: Add module test logs.
militant-daos Nov 28, 2021
9bdcb28
GENERAL: Update working branch from origin/main.
militant-daos Nov 28, 2021
70372f3
Merge pull request #70 from militant-daos/Victor.Krasnoshchok
militant-daos Nov 28, 2021
e4746bb
TASK3: Fix second_arg param desc.
militant-daos Nov 30, 2021
32e7f39
Merge pull request #71 from militant-daos/task03
ziod Dec 6, 2021
10134b4
Merge pull request #12 from Kernel-GL-HRK/Victor.Krasnoshchok
ValentinSidorov Dec 10, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions 01_git/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*.out
*.json
game
20 changes: 20 additions & 0 deletions 01_git/scissors/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
CXX=g++
CXX_FLAGS=-std=c++11 -O3 -Wall -Werror -Wpedantic
INC=-I.
LDFLAGS=-lcrypto

CXX_SOURCES=choice.cpp game.cpp
OUT_NAME=game

RM=rm -rf

# The project is tiny so do clean build at all times
# to suppress $TARGET is up to date" in case we're
# updating the module.
game: clean
$(CXX) $(CXX_FLAGS) $(INC) $(CXX_SOURCES) -o$@ $(LDFLAGS)

all: game

clean:
$(RM) $(OUT_NAME)
150 changes: 150 additions & 0 deletions 01_git/scissors/choice.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
#include "choice.h"

#include <iostream>
#include <cassert>
#include <cstring>

#include <openssl/md5.h>

namespace
{

const char* const gaItemsStrRepr[]
{
"scissors", // SCISSORS
"paper", // PAPER
"rock" // ROCK
};

} //namespace

namespace game
{
// Auxiliary stuff.

CVal decodeChoiceStdin(char rdRawChoice)
{
switch (std::tolower(rdRawChoice))
{
// In-game items.
case 's':
return CVal::SCISSORS;
case 'p':
return CVal::PAPER;
case 'r':
return CVal::ROCK;

// Control codes.
case 'q':
// FALLTHROUGH
case EOF:
// FALLTHROUGH
case 0: // ^D - a corner-case for std::cin! In case ^D is pressed
// we get into an infinite loop.
return CVal::QUIT;
case '\n':
// FALLTHROUGH
case '\r':
return CVal::IGNORE;

default:
return CVal::CHOICE_LAST;
}
}

CVal decodeChoiceInt(int rdRawChoice)
{
for (auto i = Choice::ToInt(CVal::SCISSORS);
i < Choice::ToInt(CVal::CHOICE_LAST); ++i)
{
if (i == rdRawChoice)
{
return static_cast<CVal>(i);
}
}

return CVal::CHOICE_LAST;
}

// Choice class impl.

const char* const Choice::ToString(CVal reValue)
{
assert(reValue < CVal::CHOICE_LAST);
return gaItemsStrRepr[ToInt(reValue)];
}

void Choice::PrintMd5FromChoice(CVal reValue)
{
assert(reValue < CVal::CHOICE_LAST);
const auto pChoiceString = ToString(reValue);
const auto dChoiceLength = std::strlen(pChoiceString);

unsigned char aDigest[MD5_DIGEST_LENGTH] {};
const auto pDigest = MD5(reinterpret_cast<const unsigned char*>(pChoiceString),
dChoiceLength, aDigest);
std::cout << "MD5(choice): 0x";
for (size_t i = 0; i < sizeof(aDigest); ++i)
{
std::cout << std::hex << short(pDigest[i]);
}

std::cout << std::endl;
}

// ChoiceStdin class impl.

CVal ChoiceStdin::Get()
{
bool bSkipHeading = false;

while (true)
{
if (not bSkipHeading)
{
std::cout << "Please choose: rock (r) - paper (p) - scissors (s)" << std::endl;
}
else
{
bSkipHeading = false;
}

auto dInput = '\0';
std::cin >> dInput;
const auto eChoice {decodeChoiceStdin(dInput)};

if (eChoice == CVal::IGNORE)
{
// Eat up LFs and CRs, do not repeat the prompt above.
bSkipHeading = true;
continue;
}

if (eChoice == CVal::CHOICE_LAST)
{
std::cout << "Wrong input";
if (std::isalnum(dInput))
{
// Check letters & numbers only, do not overcomplicate things.
std::cout << ": " << char(dInput);
}

std::cout << "!" << std::endl << "Press 'q' or '^C'/'^D' to exit" << std::endl;
continue;
}

return eChoice;
}
}

// ChoiceRandom class impl.

CVal ChoiceRandom::Get()
{
const auto eChoice = decodeChoiceInt(mtUniDistr(mtRandSrc));
assert(eChoice != CVal::CHOICE_LAST); // Double-checking UniDistr range.
PrintMd5FromChoice(eChoice);
return eChoice;
}

} // namespace game
69 changes: 69 additions & 0 deletions 01_git/scissors/choice.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#pragma once

#include <random>

namespace game
{

class Choice
{
public:

enum class Value : int
{
// Game-related values.
SCISSORS = 0,
PAPER,
ROCK,

// Enum size & invalid input marker.
CHOICE_LAST,
// Crutch to skip some control chars, like CR & LF
IGNORE,
// "game quit" choice.
QUIT
};

virtual Value Get() = 0;

static constexpr int ToInt(Value reValue)
{
return static_cast<int>(reValue);
}

static const char* const ToString(Value reValue);
static void PrintMd5FromChoice(Value reValue);

};

using CVal = Choice::Value;

class ChoiceStdin : public Choice
{
public:

Value Get() override;
};

class ChoiceRandom : public Choice
{
using UniDistr = std::uniform_int_distribution<>;

public:

ChoiceRandom() :
mtUniDistr(ToInt(CVal::SCISSORS), ToInt(CVal::ROCK))
{
std::random_device tDrbg;
mtRandSrc.seed(tDrbg());
}

Value Get() override;

private:

std::mt19937 mtRandSrc;
UniDistr mtUniDistr;
};

} // namespace game
79 changes: 79 additions & 0 deletions 01_git/scissors/game.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#include "choice.h"

#include <iostream>

enum class Result : int
{
PLAYER_WINS = 0,
CPU_WINS,
DRAW
};

using namespace game;

namespace
{

const char* const gaGameResStrRepr[]
{
"You win", // PLAYER_WINS
"I win", // CPU_WINS
"Draw!" // DRAW
};

const Result gaResolveTbl[][Choice::ToInt(CVal::CHOICE_LAST)]
{
// SCISSORS | PAPER | ROCK <- Player's choice
//
// CPU's choice
// |
// V
{ Result::DRAW, Result::PLAYER_WINS, Result::CPU_WINS }, // SCISSORS
{ Result::CPU_WINS, Result::DRAW, Result::PLAYER_WINS }, // PAPER
{ Result::PLAYER_WINS, Result::CPU_WINS, Result::DRAW } // ROCK
};

void resolveGame(CVal rePlayerChoice, CVal reCpuChoice)
{
const auto eResult = gaResolveTbl
[Choice::ToInt(rePlayerChoice)]
[Choice::ToInt(reCpuChoice)];

std::cout << gaGameResStrRepr[static_cast<int>(eResult)];

if (eResult != Result::DRAW)
{
const auto eFirstNoun = (eResult == Result::CPU_WINS) ? reCpuChoice : rePlayerChoice;
const auto eSecondNoun = (eFirstNoun == reCpuChoice) ? rePlayerChoice : reCpuChoice;
std::cout << ": " << Choice::ToString(eFirstNoun);
std::cout << " beat" << (eFirstNoun != CVal::SCISSORS ? "s" : "");
std::cout << " " << Choice::ToString(eSecondNoun);
}

std::cout << std::endl;
}
} // namespace

int main()
{
ChoiceStdin tPlayerInput;
ChoiceRandom tCpuInput;

while (true)
{

// Make CPU's move first, we need to play fair.
const auto eCpuChoice = tCpuInput.Get();
const auto ePlayerChoice = tPlayerInput.Get();
if (ePlayerChoice == CVal::QUIT)
{
break;
}

std::cout << "You chose " << Choice::ToString(ePlayerChoice);
std::cout << ", I chose " << Choice::ToString(eCpuChoice) << std::endl;
resolveGame(ePlayerChoice, eCpuChoice);
}

std::cout << "Bye!" << std::endl;
}
Loading