Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 4 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,17 @@ addons:
before_install:
- sudo apt-get update -qq

install:
- sudo apt-get install doxygen graphviz -y

script:
- bash scripts/deploy.sh

before_deploy:
- sed -i "s/__VERSION__/$TRAVIS_BUILD_NUMBER/g" bintray-spec.json

deploy:
- provider: pages
- provider: pages
skip_cleanup: true
github_token: $GITHUB_TOKEN
keep-history: true
Expand Down
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ option(ENABLE_DOXYGEN "Build documentation" OFF)

# ================ Project ========================
# Project name and a few useful settings
project(struct
project(bulk
VERSION 0.0.$ENV{TRAVIS_BUILD_NUMBER}
DESCRIPTION "OTUS c++ homeworks: struct"
DESCRIPTION "OTUS c++ homeworks: bulk"
LANGUAGES CXX
)

Expand Down
4 changes: 4 additions & 0 deletions apps/Bulk/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
add_and_install_project_app(bulk
DEPEND
lib_Bulk
)
22 changes: 22 additions & 0 deletions apps/Bulk/src/main_Bulk.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* \brief Main application
*/
#include <iostream>
#include <Bulk/Bulk.h>
#include <Bulk/Reporter.h>


int main(int arg, char**args) {
if (arg !=2) {
std::cerr << "Wrong number of params. It should be exactly 1, but " << arg - 1 << " provided\n";
return -1;
}

auto bulk = std::make_shared<bulk::Bulk>(std::atoi(args[1]));
bulk::PrintReportDefault a(bulk);
bulk::PrintReportToFile b(bulk);

std::cin >> bulk;

return 0;
}
2 changes: 1 addition & 1 deletion apps/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
add_subdirectory(Struct)
add_subdirectory(Bulk)
4 changes: 0 additions & 4 deletions apps/Struct/CMakeLists.txt

This file was deleted.

8 changes: 0 additions & 8 deletions apps/Struct/src/main_Struct.cpp

This file was deleted.

File renamed without changes.
68 changes: 68 additions & 0 deletions library/Bulk/README.MD
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# OTUS course: "C++ Developer. Professional"

## Домашнее Задание 5

Разработать программу для пакетной обработки команд.

Команды считываются построчно из стандартного ввода и обрабатываются блоками по N команд. Одна команда - одна строка, конкретное значение роли не играет. Если данные закончились - блок завершается принудительно. Параметр N передается как единственный параметр командной строки в виде целого числа.
Логика работы для статических блоков (в примере N == 3):

```bash
./bulk 3
```

| Ввод | Вывод | Комментарий |
|------|--------------------|-------------------------------------------|
| cmd1 |
| cmd2 |
| cmd3 |
| |bulk: cmd1, cmd2, cmd3| Блок завершён – выводим блок. |
| cmd4 |
| cmd5 |
| EOF |
| |bulk: cmd4, cmd5 |Конец ввода – принудительно завершаем блок.|

Размер блока можно изменить динамически, если перед началом блока и сразу после дать команды `{` и `}` соответственно. Предыдущий пакет при этом принудительно завершается. Такие блоки могут быть включены друг в друга при этом вложенные команды `{` и `}` игнорируются (но не сами блоки). Если данные закончились внутри динамического блока, весь динамический блок игнорируется.

Логика работы для динамического размера блоков (в примере N == 3):

```bash
./bulk 3
```

| Ввод | Вывод | Комментарий |
|------|--------------------|-------------------------------------------|
| cmd1 |
| cmd2 |
| { |
| | bulk: cmd1, cmd2 | Начало динамического блока – выводим предыдущий статический досрочно. |
| cmd3 |
| cmd4 |
| } |
| |bulk: cmd3, cmd4 |Конец динамического блока – выводим.|
| { |
| cmd5 |
| cmd6 |
| { | | Игнорируем вложенные команды. |
| cmd7 |
| cmd8 |
| } | | Игнорируем вложенные команды. |
| cmd9 |
| } |
| |bulk: cmd5, cmd6, cmd7, cmd8, cmd9| Конец динамического блока – выводим. |
| { |
| cmd10|
| cmd11|
| EOF |
|||Конец ввода – динамический блок игнорируется, не выводим.|


Вместе с выводом в консоль блоки должны сохранятся в отдельные файлы с именами
`bulk1517223860.log` , где 1517223860 - это время получения первой команды из блока. По одному файлу на блок.

## Требования к реализации
Бинарный файл должен называться bulk.

## Проверка
Задание считается выполненным успешно, если после установки пакета и запуска с тестовыми данными вывод соответствует описанию. Данные подаются на стандартный вход построчно с паузой в 1 секунду для визуального контроля.
Будет отмечена низкая связанность обработки данных, накопления пачек команд, вывода в консоль и сохранения в файлы.
60 changes: 60 additions & 0 deletions library/Bulk/include/Bulk/Bulk.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/**
* \brief Class Bulk Declaration
*/

#pragma once

#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <ctime>
#include <memory>


namespace bulk {

//------------------------------------
#pragma mark Forward Declaration
//------------------------------------

class PrintReport;


//------------------------------------
#pragma mark Main Bulk class declaration
//------------------------------------

/// \brief Main class to work with input commands
class Bulk {
public:
Bulk();
explicit Bulk (const size_t chunk);

friend std::istream& operator>>(std::istream& input, std::shared_ptr<Bulk> bulk);

void AddReporter(std::shared_ptr<PrintReport>);

void Process(std::string cmd);
void ChopInput(std::string cmd);
void AgregateInput(std::string cmd);

std::time_t GetTimestamp() const;

void DoReport();

private:
enum class BehaviourStatus {
Separate,
AllinOne
};

BehaviourStatus status_ = BehaviourStatus::Separate;
const size_t chunk_size_ = 1;
std::vector<std::string> command_package_;
std::queue<char> braces_balancer_;
std::vector<std::shared_ptr<PrintReport>> reporters_;
std::time_t timestamp_;
};

} // namespace bulk
11 changes: 11 additions & 0 deletions library/Bulk/include/Bulk/FormatUtil.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#pragma once

#include <vector>
#include <string>

namespace bulk::FormatUtil {

auto Format(const std::vector<std::string>&, const std::string& delimiter) -> std::string;
auto StripString(std::string&) -> void;

} // namespace bulk::FormatUtil
58 changes: 58 additions & 0 deletions library/Bulk/include/Bulk/Reporter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#pragma once

#include <Bulk/Bulk.h>

#include <string>
#include <vector>
#include <iostream>

namespace bulk {

//------------------------------------
#pragma mark Forward declararions
//------------------------------------

// class Bulk;

//------------------------------------
#pragma mark Reporters declaration
//------------------------------------

/// \brief Interface for reporters
class PrintReport {
public:
PrintReport() = default;

explicit PrintReport(const std::string& delimiter);
virtual void Print(const std::vector<std::string>&) const = 0;
virtual ~PrintReport() = default;
protected:
std::string delimiter_;
};

/// \brief Report to std::cout
class PrintReportDefault : public PrintReport {
public:
PrintReportDefault() = default;

PrintReportDefault(std::shared_ptr<Bulk> bulk, std::ostream& source = std::cout);
~PrintReportDefault() = default;
void Print(const std::vector<std::string>&) const override;
private:
std::ostream& source_ = std::cout;
};


/// \brief Report to file
class PrintReportToFile : public PrintReport {
public:
PrintReportToFile() = default;

PrintReportToFile(std::shared_ptr<Bulk> bulk);
~PrintReportToFile() = default;
void Print(const std::vector<std::string>&) const override;
private:
std::shared_ptr<Bulk> bulk_ = nullptr;
};

} // namespace bulk
100 changes: 100 additions & 0 deletions library/Bulk/src/Bulk.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/**
* \brief main library
*
*/

#include <Bulk/Bulk.h>
#include <Bulk/Reporter.h>
#include <Bulk/FormatUtil.h>

#include <iostream>
#include <string>
#include <algorithm>

namespace bulk {

//---------------------------------
#pragma mark Bulk Implementation
//---------------------------------

Bulk::Bulk() = default;

Bulk::Bulk(const size_t chunk_size):
chunk_size_(chunk_size) {
}

void Bulk::Process(std::string cmd) {
FormatUtil::StripString(cmd);
if (cmd == "{") {
if (braces_balancer_.empty()){
DoReport();
}
braces_balancer_.push('{');
status_ = BehaviourStatus::AllinOne;
}
else if (cmd == "}"){
if (!braces_balancer_.empty())
braces_balancer_.pop();

if (braces_balancer_.empty()) {
DoReport();
status_ = BehaviourStatus::Separate;
}
}
else {
if (command_package_.empty()) {
timestamp_ = std::time(0);
}
switch (status_) {
case BehaviourStatus::Separate:
ChopInput(std::move(cmd));
break;
case BehaviourStatus::AllinOne:
AgregateInput(std::move(cmd));
break;
}
}
}

void Bulk::ChopInput(std::string cmd) {
if (chunk_size_ == command_package_.size()) {
DoReport();
timestamp_ = std::time(0);
}
command_package_.push_back(cmd);
}

void Bulk::AgregateInput(std::string cmd) {
command_package_.push_back(cmd);
}

void Bulk::DoReport() {
if (braces_balancer_.empty()) {
for (const auto& reporter: reporters_)
reporter->Print(command_package_);
}
command_package_.clear();
}

std::time_t Bulk::GetTimestamp() const {
return timestamp_;
}

void Bulk::AddReporter(std::shared_ptr<PrintReport> new_reporter) {
if (new_reporter) {
reporters_.push_back(new_reporter);
}
}

std::istream& operator>>(std::istream& input, std::shared_ptr<Bulk> bulk) {
std::string cmd;
while (std::getline(input, cmd)) {
FormatUtil::StripString(cmd);
bulk->Process(cmd);
}
// for the last input
bulk->DoReport();
return input;
}

} // namespace bulk
Loading