332 lines
10 KiB
C++
332 lines
10 KiB
C++
|
#include <iostream>
|
|||
|
#include <vector>
|
|||
|
#include <string>
|
|||
|
#include <algorithm>
|
|||
|
#include <map>
|
|||
|
#include <iomanip>
|
|||
|
#include <fstream>
|
|||
|
#include <cctype>
|
|||
|
#include "json.hpp"
|
|||
|
|
|||
|
using namespace std;
|
|||
|
using json = nlohmann::json;
|
|||
|
|
|||
|
struct Transaction {
|
|||
|
string from;
|
|||
|
string to;
|
|||
|
double value;
|
|||
|
};
|
|||
|
|
|||
|
struct Block {
|
|||
|
int index;
|
|||
|
string hash;
|
|||
|
int64_t timestamp;
|
|||
|
string miner;
|
|||
|
double reward;
|
|||
|
vector<Transaction> transactions;
|
|||
|
string secret_info;
|
|||
|
int nonce;
|
|||
|
};
|
|||
|
|
|||
|
vector<Block> blocks;
|
|||
|
|
|||
|
|
|||
|
bool loadBlocksFromFile(const string& filename) {
|
|||
|
ifstream input_file(filename);
|
|||
|
if (!input_file.is_open()) {
|
|||
|
cerr << "Error: Cannot open file " << filename << endl; //Ошибка: не удалось открыть файл
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
try {
|
|||
|
json j;
|
|||
|
input_file >> j;
|
|||
|
blocks.clear();
|
|||
|
|
|||
|
for (const auto& item : j) {
|
|||
|
Block block;
|
|||
|
block.index = item["index"];
|
|||
|
block.hash = item["hash"];
|
|||
|
block.timestamp = item["timestamp"];
|
|||
|
block.miner = item["miner"];
|
|||
|
block.reward = item["reward"];
|
|||
|
block.secret_info = item.value("secret_info", "");
|
|||
|
block.nonce = item["nonce"];
|
|||
|
|
|||
|
for (const auto& tx_item : item["transactions"]) {
|
|||
|
Transaction tx;
|
|||
|
tx.from = tx_item["from"];
|
|||
|
tx.to = tx_item["to"];
|
|||
|
tx.value = tx_item["value"];
|
|||
|
block.transactions.push_back(tx);
|
|||
|
}
|
|||
|
|
|||
|
blocks.push_back(block);
|
|||
|
}
|
|||
|
|
|||
|
//Успешно загружено //блоков из файла
|
|||
|
cout << "Successfully loaded " << blocks.size() << " blocks from " << filename << endl;
|
|||
|
return true;
|
|||
|
}
|
|||
|
catch (const exception& e) {
|
|||
|
cerr << "JSON parsing error: " << e.what() << endl; //Ошибка при чтении JSON:
|
|||
|
return false;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
bool saveBlocksToFile(const string& filename) {
|
|||
|
json j;
|
|||
|
|
|||
|
for (const auto& block : blocks) {
|
|||
|
json block_json;
|
|||
|
block_json["index"] = block.index;
|
|||
|
block_json["hash"] = block.hash;
|
|||
|
block_json["timestamp"] = block.timestamp;
|
|||
|
block_json["miner"] = block.miner;
|
|||
|
block_json["reward"] = block.reward;
|
|||
|
block_json["secret_info"] = block.secret_info;
|
|||
|
block_json["nonce"] = block.nonce;
|
|||
|
|
|||
|
for (const auto& tx : block.transactions) {
|
|||
|
json tx_json;
|
|||
|
tx_json["from"] = tx.from;
|
|||
|
tx_json["to"] = tx.to;
|
|||
|
tx_json["value"] = tx.value;
|
|||
|
block_json["transactions"].push_back(tx_json);
|
|||
|
}
|
|||
|
|
|||
|
j.push_back(block_json);
|
|||
|
}
|
|||
|
|
|||
|
ofstream output_file(filename);
|
|||
|
if (!output_file.is_open()) {
|
|||
|
cerr << "Error: Cannot create file " << filename << endl; //Ошибка: не удалось создать файл
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
output_file << setw(4) << j << endl;
|
|||
|
cout << "Successfully saved " << blocks.size() << " blocks to " << filename << endl; //Успешно сохранено //блоков в файл
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
void printBlock(const Block& block) {
|
|||
|
cout << "index: " << block.index << "\n"
|
|||
|
<< "hash: " << block.hash << "\n"
|
|||
|
<< "timestamp: " << block.timestamp << "\n"
|
|||
|
<< "miner: " << block.miner << "\n"
|
|||
|
<< "reward: " << fixed << setprecision(2) << block.reward << "\n"
|
|||
|
<< "secret_info: " << block.secret_info << "\n"
|
|||
|
<< "nonce: " << block.nonce << "\n"
|
|||
|
<< "Transactions (" << block.transactions.size() << "):\n";
|
|||
|
|
|||
|
for (const auto& tx : block.transactions) {
|
|||
|
cout << " " << tx.from << " -> " << tx.to << ": " << tx.value << "\n";
|
|||
|
}
|
|||
|
cout << "----------------------------\n";
|
|||
|
}
|
|||
|
|
|||
|
void printAllBlocks() {
|
|||
|
if (blocks.empty()) {
|
|||
|
cout << "There is no data about the blocks.Download them first." << endl; //Нет данных о блоках. Загрузите их сначала.
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
for (const auto& block : blocks) {
|
|||
|
printBlock(block);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void filterByMiner() {
|
|||
|
if (blocks.empty()) {
|
|||
|
cout << "There is no data about the blocks. Download them first." << endl; //Нет данных о блоках. Загрузите их сначала.
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
string minerName;
|
|||
|
cout << "Enter the miner's name: "; //Введите имя майнера:
|
|||
|
cin >> minerName;
|
|||
|
|
|||
|
bool found = false;
|
|||
|
for (const auto& block : blocks) {
|
|||
|
if (block.miner == minerName) {
|
|||
|
printBlock(block);
|
|||
|
found = true;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (!found) {
|
|||
|
cout << "Blocks with a miner " << minerName << " not found." << endl; //Блоки с майнером ... не найдены
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void printTransactionsCount() {
|
|||
|
if (blocks.empty()) {
|
|||
|
cout << "There is no data about the blocks. Download them first." << endl; //Нет данных о блоках. Загрузите их сначала.
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
cout << "Number of transactions in blocks: " << endl; //Количество транзакций в блоках:
|
|||
|
for (const auto& block : blocks) {
|
|||
|
cout << "block " << block.index << ": "
|
|||
|
<< block.transactions.size() << " transactions" << endl;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void calculateBalances() {
|
|||
|
if (blocks.empty()) {
|
|||
|
cout << "There is no data about the blocks. Download them first." << endl; //Нет данных о блоках. Загрузите их сначала.
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
map<string, double> balances;
|
|||
|
|
|||
|
for (const auto& block : blocks) {
|
|||
|
for (const auto& tx : block.transactions) {
|
|||
|
if (tx.from != "SYSTEM") {
|
|||
|
balances[tx.from] -= tx.value;
|
|||
|
}
|
|||
|
balances[tx.to] += tx.value;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
cout << "User balances:" << endl; //Балансы пользователей:
|
|||
|
for (const auto& entry : balances) {
|
|||
|
cout << entry.first << ": " << fixed << setprecision(2) << entry.second << endl;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void sortBlocksByIndex() {
|
|||
|
if (blocks.empty()) {
|
|||
|
cout << "There is no data about the blocks. Download them first." << endl;
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
for (size_t i = 0; i < blocks.size(); ++i) {
|
|||
|
for (size_t j = 0; j < blocks.size() - i - 1; ++j) {
|
|||
|
if (blocks[j].index > blocks[j + 1].index) {
|
|||
|
swap(blocks[j], blocks[j + 1]);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
cout << "The blocks are sorted by index." << endl; //Блоки отсортированы по индексу.
|
|||
|
}
|
|||
|
|
|||
|
void printEvenIndexBlocks() {
|
|||
|
if (blocks.empty()) {
|
|||
|
cout << "There is no data about the blocks. Download them first." << endl;
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
cout << "Blocks with an even index:" << endl; //Блоки с четным индексом:
|
|||
|
for (const auto& block : blocks) {
|
|||
|
if (block.index % 2 == 0) {
|
|||
|
printBlock(block);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void printVowelMinerBlocks() {
|
|||
|
if (blocks.empty()) {
|
|||
|
cout << "There is no data about the blocks. Download them first." << endl;
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
const string vowels = "AEIOUaeiou";
|
|||
|
cout << "Blocks where the miner starts with a vowel:" << endl; //Блоки, где майнер начинается с гласной:
|
|||
|
|
|||
|
for (const auto& block : blocks) {
|
|||
|
if (!block.miner.empty() && vowels.find(block.miner[0]) != string::npos) {
|
|||
|
printBlock(block);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void printFourDigitNonceBlocks() {
|
|||
|
if (blocks.empty()) {
|
|||
|
cout << "There is no data about the blocks. Download them first." << endl;
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
cout << "Blocks with a 4-digit nonce (1000-9999):" << endl; //Блоки с 4-значным nonce (1000-9999):
|
|||
|
for (const auto& block : blocks) {
|
|||
|
if (block.nonce >= 1000 && block.nonce <= 9999) {
|
|||
|
printBlock(block);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void showMenu() {
|
|||
|
cout << "\n=== Menu ===" << endl //Загрузить блоки из файла
|
|||
|
<< "1. Load blocks from file" << endl //Загрузить блоки из файла
|
|||
|
<< "2. Save blocks to file" << endl //Сохранить блоки в файл
|
|||
|
<< "3. Print all blocks" << endl //Вывести все блоки
|
|||
|
<< "4. Filter by miner" << endl //Фильтр по майнеру
|
|||
|
<< "5. Transaction count" << endl //Количество транзакций
|
|||
|
<< "6. User balances" << endl //Балансы пользователей
|
|||
|
<< "7. Sort by index" << endl //Сортировать по индексу
|
|||
|
<< "8. Blocks with even index" << endl //Блоки с четным индексом
|
|||
|
<< "9. Blocks where miner starts with a vowel" << endl //Блоки, где майнер начинается с гласной
|
|||
|
<< "10. Blocks with 4-digit nonce" << endl //Блоки с 4-значным nonce
|
|||
|
<< "0. Exit" << endl //Выход
|
|||
|
<< "Enter choice: "; //Введите номер
|
|||
|
}
|
|||
|
|
|||
|
int main() {
|
|||
|
int choice;
|
|||
|
do {
|
|||
|
showMenu();
|
|||
|
cin >> choice;
|
|||
|
|
|||
|
switch (choice) {
|
|||
|
case 1: {
|
|||
|
string filename;
|
|||
|
cout << "Enter the file name to download: "; //Введите имя файла для загрузки:
|
|||
|
cin >> filename;
|
|||
|
if (!loadBlocksFromFile(filename)) {
|
|||
|
cout << "File upload error!" << endl; //Ошибка загрузки файла!
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
case 2: {
|
|||
|
string filename;
|
|||
|
cout << "Enter the file name to save: "; //Введите имя файла для сохранения:
|
|||
|
cin >> filename;
|
|||
|
if (!saveBlocksToFile(filename)) {
|
|||
|
cout << "File upload error!" << endl;
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
case 3:
|
|||
|
printAllBlocks();
|
|||
|
break;
|
|||
|
case 4:
|
|||
|
filterByMiner();
|
|||
|
break;
|
|||
|
case 5:
|
|||
|
printTransactionsCount();
|
|||
|
break;
|
|||
|
case 6:
|
|||
|
calculateBalances();
|
|||
|
break;
|
|||
|
case 7:
|
|||
|
sortBlocksByIndex();
|
|||
|
break;
|
|||
|
case 8:
|
|||
|
printEvenIndexBlocks();
|
|||
|
break;
|
|||
|
case 9:
|
|||
|
printVowelMinerBlocks();
|
|||
|
break;
|
|||
|
case 10:
|
|||
|
printFourDigitNonceBlocks();
|
|||
|
break;
|
|||
|
case 0:
|
|||
|
cout << "Exit the program..." << endl;
|
|||
|
break;
|
|||
|
default:
|
|||
|
cout << "Wrong choice! Try again." << endl; //Неверный выбор! Попробуйте снова.
|
|||
|
}
|
|||
|
} while (choice != 0);
|
|||
|
|
|||
|
return 0;
|
|||
|
}
|