/
RedResistance
/
wonders
Обзор
Документация
Войти
/
RedResistance
/
wonders
Код
Запросы
2
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
card_factory.cpp
364 строки
11 KB
Domovoi-Kuzma
T-10 new parser
09 мар 2026, 13:09
09 мар 2026, 13:09
0cea529
Код
Авторство
О чём код?
#include <iostream> #include <fstream> #include <sstream> #include "card_factory.h" #include "cards_classes.h" using namespace std; const unordered_map<string, Color> COLOR_MAP = { {"green", Color::Green}, {"red", Color::Red}, {"yellow",Color::Yellow}, {"blue", Color::Blue}, {"brown", Color::Brown}, {"grey", Color::Grey}, {"purple",Color::Purple} }; const unordered_map<string, ResourceType> RESOURCE_TYPE_MAP = { {"null", ResourceType::LastResourceTypeId}, {"plain",ResourceType::Plain}, {"rare", ResourceType::Rare}, }; const unordered_map<string, Direction> DIRECTION_MAP = { {"null", Direction::LastDirectionId}, {"left", Direction::Left}, {"right",Direction::Right}, {"both", Direction::Both}, }; const unordered_map<string, Science> SCIENCE_MAP = { {"mason", Science::Mason}, {"script", Science::Script}, {"gear", Science::Gear} }; const unordered_map<string, Resource> RESOURCE_MAP = { {"wood", Resource::Wood}, {"stone", Resource::Stone}, {"ore", Resource::Ore}, {"clay", Resource::Clay}, {"glass", Resource::Glass}, {"paper", Resource::Paper}, {"clothes", Resource::Clothes} }; const unordered_map<string, ReferringPlayers> REFERRING_MAP = { {"<>", ReferringPlayers::Neighbors}, {"V", ReferringPlayers::Self}, {"<V>", ReferringPlayers::Both}, }; std::vector<std::unique_ptr<Card> > CardFactory::load_game_box(string filename) { ifstream file(filename); if (!file.is_open()) { cerr << "������ �������� �����: " << filename << std::endl; throw invalid_argument("������ �������� ����� \"" + filename + "\""); } vector<unique_ptr<Card> > game_box; std::string line; while (getline(file, line)) { if (line.empty() || line[0] == '#') continue; game_box.emplace_back(CardFactory::create_card(line)); } return game_box; } std::string CardFactory::readToken(std::istream& in) { in >> std::ws; char ch = in.peek(); if (ch == '[' || ch == '(') { char open = in.get(); char close = (open == '[') ? ']' : ')'; std::string result; int depth = 1; while (depth && in.get(ch)) { if (ch == open) depth++; else if (ch == close) depth--; if (depth) result += ch; } if (depth != 0) throw std::runtime_error("Unclosed bracket group"); return std::string(1, open) + result + close; } std::string token; while (in.peek() != EOF && !isspace(in.peek())) token += in.get(); return token; } // ������� ��� �������� ������ � ���������� ������� �� ��������� // ���������� ������ �� ������ � ����������� ���. // ����������� - ������� // ���������� ������� - std::vector<std::string> CardFactory::splitIntoSubGroups(const std::string& input) { std::vector<std::string> result; std::stringstream ss(input); std::string item; while (getline(ss, item, ',')) result.push_back(item); return result; } // ������� ��� �������� ������ �� ������ ��������� �������� //���������� ������ ������ ������ ��������� � �� ����������� �������� //���������� ������ �� ������ � ������ ��������� std::vector<std::string> CardFactory::splitIntoGroups(const std::string& input) { std::vector<std::string> result; std::string current; int depth = 0; for (char ch : input) { if (ch == '[') depth++; if (ch == ']') depth--; if (ch == ',' && depth == 0) { result.push_back(current); current.clear(); } else { current += ch; } } if (!current.empty()) result.push_back(current); return result; } // ������ ������ ������� // [SCALAR_RES,SCALAR_RES,SCALAR_RES] // ���� // SCALAR_RES // � ������ ����� ��� ���������� ����� SCALAR_RES // ������ SCALAR_RES ��� ������ ���� "1wood" std::vector<std::string> CardFactory::readStrings1d(std::istream& in) { std::string token = readToken(in); if (token == "[]") return {}; if (token.front() == '[') { token = token.substr(1, token.size() - 2); return splitIntoSubGroups(token); } if (token.find(',') != std::string::npos) return splitIntoSubGroups(token); return { token }; } /* * // ������ ������ ������� SCALAR_RES ��� �� 1wood � ������� */ void CardFactory::parseSingleResourceAndAdd(const std::string& s, Cost& cost) { int i = 0; int amount = 0; while (i < s.size() && isdigit(s[i])) { amount = amount * 10 + (s[i] - '0'); i++; } if (amount == 0) amount = 1; std::string resource = s.substr(i); Resource r = findInMap( RESOURCE_MAP, resource, "Unknown resource: " + s ); cost.add(r, amount); } void CardFactory::readCostOrMoney(std::istream& in, Cost& cost, Money& dollars) { std::string token = readToken(in); if (token.empty()) return; if (token[0] == '$') { dollars = Money(std::stoi(token.substr(1))); return; } if (token == "[]") return; std::vector<std::string> items; if (token.front() == '[') items = splitIntoSubGroups(token.substr(1, token.size() - 2)); else if (token.find(',') != std::string::npos) items = splitIntoSubGroups(token); else items = { token }; for (auto& s : items) parseSingleResourceAndAdd(s, cost); } //������ ������ ���� ([1wood,1wood,1wood],[,,],[,,]) // ���� [1wood,1wood,1wood] // ���� 1wood // � ������ ��������� ��� CostVariants CardFactory::readCostVariants(std::istream& in) { std::string token = readToken(in); CostVariants result; if (token.front() == '(') { token = token.substr(1, token.size() - 2); for (auto& group : splitIntoGroups(token)) { if (group.front() == '[' && group.back() == ']') group = group.substr(1, group.size() - 2); Cost next; for (auto& element : splitIntoSubGroups(group)) parseSingleResourceAndAdd(element, next); result.add(next); } } else { Cost next; std::vector<std::string> elements; if (token.front() == '[') { std::string inner = token.substr(1, token.size() - 2); elements = splitIntoSubGroups(inner); } else if (token.find(',') != std::string::npos) { elements = splitIntoSubGroups(token); } else { elements = { token }; } for (auto& element : elements) parseSingleResourceAndAdd(element, next); result.add(next); } return result; } int CardFactory::checkOrReadDollar(std::istream& iss) { int amount = 0; char ch; iss.get(ch); if (ch == '$') { while (iss.get(ch) && ch >= '0' && ch <= '9') { amount *= 10; amount += ch - '0'; } } else { iss.unget(); } return amount; } void processEscapedSymbols(string& str) { string newStr; bool inEscapeSequence = false; for (char ch : str) { if (inEscapeSequence) { switch (ch) { case 's': newStr += ' '; break; // ������ case 't': newStr += '\t'; break; // ��������� case 'n': newStr += '\n'; break; // ������� ������ default: newStr += '\\' + ch; break; // ��������� �������������� ������� } inEscapeSequence = false; } else if (ch == '\\') { inEscapeSequence = true; } else { newStr += ch; } } if (inEscapeSequence) { newStr += "\\"; // ������� ������������� escape-������������������ } str.swap(newStr); // ������ ������������ ������ ������������ ��������� } std::unique_ptr<Card> CardFactory::create_card(const std::string& raw_line) { istringstream iss(raw_line); string type, name, str_color, bonus_building_required_; int min_players_required, deck_id; iss >> type >> name >> str_color >> min_players_required >> deck_id >> bonus_building_required_; if (bonus_building_required_ == "null") bonus_building_required_.clear(); processEscapedSymbols(name); Color color = findInMap(COLOR_MAP, str_color, "������� ����� ����� " + name); iss >> std::ws; Money dollars{ 0 }; Cost cost; int raw_dollars = checkOrReadDollar(iss); if (raw_dollars > 0) { dollars = Money(raw_dollars); } else { for (std::string str_resource : readStrings1d(iss)) parseSingleResourceAndAdd(str_resource, cost); } if (type == "wp") { int WP_value; iss >> WP_value; return make_unique<CardWP>(name, color, bonus_building_required_, cost, dollars, min_players_required, deck_id, WP_value); } else if (type == "military") { int MP_value; iss >> MP_value; return make_unique<CardMilitary>(name, color, bonus_building_required_, cost, dollars, min_players_required, deck_id, MP_value); } else if (type == "science") { string str_science_points; iss >> str_science_points; Science SP_value = findInMap(SCIENCE_MAP, str_science_points, "������� ����� ����� " + name); return make_unique<CardScience>(name, color, bonus_building_required_, cost, dollars, min_players_required, deck_id, SP_value); } else if (type == "production") { CostVariants production_appended = readCostVariants(iss); return make_unique<CardProduction>(name, color, bonus_building_required_, cost, dollars, min_players_required, deck_id, production_appended); } else if (type == "discount&pay") { int money; string resources_type_str, direction_str; iss >> money >> direction_str >> resources_type_str; ResourceType resource_type_ = findInMap(RESOURCE_TYPE_MAP, resources_type_str, "������� ������ ������ ����� " + name); Direction direction_ = findInMap(DIRECTION_MAP, direction_str, "������� ����������� ������ ����� " + name); return make_unique<CardDiscountAndPay>(name, color, bonus_building_required_, cost, dollars, min_players_required, deck_id, money, direction_, resource_type_); } else if (type == "untradables") { string resources_type_str; iss >> resources_type_str; ResourceType resource_type_ = findInMap(RESOURCE_TYPE_MAP, resources_type_str, "������� ������ ����� ����� " + name); return make_unique<CardUntradables>(name, color, bonus_building_required_, cost, dollars, min_players_required, deck_id, resource_type_); } else if (type == "count_colors") { int money_per_color_referring, wp_per_color_referring; string str_referring, str_color_referring; iss >> str_referring >> str_color_referring >> money_per_color_referring >> wp_per_color_referring; Color color_referring = findInMap(COLOR_MAP, str_color_referring, "������� ������������ ����� ������� " + name); ReferringPlayers referring = findInMap(REFERRING_MAP, str_referring, "������� ����������� ������� ������� " + name); return make_unique<CardWPandPayForColors>(name, color, bonus_building_required_, cost, dollars, min_players_required, deck_id, referring, color_referring, money_per_color_referring, wp_per_color_referring); } else { return make_unique<Card>(name, color, bonus_building_required_, cost, dollars, min_players_required, deck_id); } throw invalid_argument("Wrong type " + type ); }