net weights implementation WIP
This commit is contained in:
parent
d83f106a91
commit
59315f9445
|
@ -216,15 +216,9 @@ endif()
|
|||
|
||||
target_link_libraries(checks-parser PRIVATE -lcurl)
|
||||
|
||||
find_package(Boost 1.45.0 COMPONENTS boost_regex)
|
||||
|
||||
if(Boost_FOUND)
|
||||
include_directories(${Boost_INCLUDE_DIRS})
|
||||
target_link_libraries(checks-parser PUBLIC ${Boost_LIBRARIES})
|
||||
else()
|
||||
message(FATAL_ERROR "No BOOST library found. Please, install one. If you beleive this is an error, please, contact the developer.")
|
||||
return()
|
||||
endif()
|
||||
find_package(Boost 1.45.0 CONFIG REQUIRED COMPONENTS regex)
|
||||
include_directories(${Boost_INCLUDE_DIRS})
|
||||
target_link_libraries(checks-parser PUBLIC ${Boost_LIBRARIES})
|
||||
|
||||
if (BUILD_OCR_MODE OR BUILD_OFD_LOCAL_QR_SCAN OR BUILD_OFD_BINARYEYE_SCAN)
|
||||
find_package(OpenCV REQUIRED COMPONENTS core imgproc imgcodecs)
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
#include "goods.h"
|
||||
#include <string>
|
||||
|
||||
Goods::Goods(std::string name, double price_per_unit, double quantity) {
|
||||
this->name = name;
|
||||
this->price_per_unit = price_per_unit;
|
||||
this->quantity = quantity;
|
||||
}
|
||||
Goods::Goods(std::string name, double price_per_unit, std::string net_weight, double quantity) :
|
||||
name(name), price_per_unit(price_per_unit),
|
||||
net_weight(net_weight), quantity(quantity) {}
|
||||
|
||||
double Goods::calculate_total_price() {
|
||||
return this->price_per_unit * this->quantity;
|
||||
|
@ -15,12 +13,16 @@ std::string Goods::get_name() { return this->name; }
|
|||
|
||||
double Goods::get_quantity() { return this->quantity; }
|
||||
|
||||
std::string Goods::get_net_weight() { return this->net_weight; }
|
||||
|
||||
double Goods::get_price_per_unit() { return this->price_per_unit; }
|
||||
|
||||
void Goods::set_name(std::string name) { this->name = name; }
|
||||
|
||||
void Goods::set_quantity(double quantity) { this->quantity = quantity; }
|
||||
|
||||
void Goods::set_net_weight(std::string net_weight) { this->net_weight = net_weight; }
|
||||
|
||||
void Goods::set_price_per_unit(double price_per_unit) {
|
||||
this->price_per_unit = price_per_unit;
|
||||
}
|
||||
|
|
|
@ -7,17 +7,20 @@ class Goods
|
|||
{
|
||||
std::string name;
|
||||
double quantity; // by weight or by the piece
|
||||
std::string net_weight; // will contain values like "5мл" or "10г"
|
||||
double price_per_unit;
|
||||
public:
|
||||
Goods(std::string, double, double);
|
||||
Goods(std::string name, double quantity, std::string net_weight, double price_per_unit);
|
||||
double calculate_total_price();
|
||||
|
||||
std::string get_name();
|
||||
double get_quantity();
|
||||
std::string get_net_weight();
|
||||
double get_price_per_unit();
|
||||
|
||||
void set_name(std::string);
|
||||
void set_quantity(double);
|
||||
void set_net_weight(std::string);
|
||||
void set_price_per_unit(double);
|
||||
};
|
||||
|
||||
|
|
|
@ -83,8 +83,7 @@ void OutputDialog::on_buttonBox_accepted() {
|
|||
output_file << std::fixed << std::setprecision(2) << goods.get_quantity();
|
||||
break;
|
||||
case ColumnType::goods_net_weight:
|
||||
output_file << "TODO";
|
||||
// TODO
|
||||
output_file << goods.get_net_weight();
|
||||
break;
|
||||
case ColumnType::goods_total:
|
||||
output_file << std::fixed << std::setprecision(2) << goods.calculate_total_price();
|
||||
|
|
|
@ -1,11 +1,25 @@
|
|||
#include "module.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <string>
|
||||
#include "../utils/utils.h"
|
||||
#include <utils/utils.h>
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
StoreModule::StoreModule() {}
|
||||
|
||||
std::vector<std::string> StoreModule::parse(std::wstring str, std::wstring regexp, boost::regex_constants::flag_type_ flag) {
|
||||
std::vector<std::string> result;
|
||||
boost::wregex r(regexp, flag);
|
||||
|
||||
for (boost::wsregex_iterator it{str.begin(), str.end(), r}, end{}; it != end;
|
||||
it++) {
|
||||
result.push_back(to_utf8(it->str()));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
StoreModule::StoreModule(std::string path) {
|
||||
std::ifstream settings_file(path);
|
||||
nlohmann::json settings = nlohmann::json::parse(settings_file);
|
||||
|
@ -13,54 +27,35 @@ StoreModule::StoreModule(std::string path) {
|
|||
this->name = from_utf8(settings["name"]);
|
||||
this->goods_name_regex = from_utf8(settings["goods_name_regex"]);
|
||||
this->goods_price_regex = from_utf8(settings["goods_price_regex"]);
|
||||
this->goods_net_weight_regex = from_utf8(settings["goods_net_weight_regex"]);
|
||||
this->goods_quantity_regex = from_utf8(settings["goods_quantity_regex"]);
|
||||
this->check_start_regex = from_utf8(settings["check_start_regex"]);
|
||||
this->check_end_regex = from_utf8(settings["check_end_regex"]);
|
||||
|
||||
#ifdef DEBUG
|
||||
std::wcout << "Name: " << this->name << std::endl;
|
||||
std::wcout << "Goods name regex: " << this->goods_name_regex << std::endl;
|
||||
std::wcout << "Goods price regex: " << this->goods_price_regex << std::endl;
|
||||
std::wcout << "Goods quantity regex: " << this->goods_quantity_regex
|
||||
<< std::endl;
|
||||
std::wcout << "Check start regex: " << this->check_start_regex << std::endl;
|
||||
std::wcout << "Check end regex: " << this->check_end_regex << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
std::vector<std::string> StoreModule::parse_name(std::wstring str) {
|
||||
std::vector<std::string> result;
|
||||
boost::wregex r(this->goods_name_regex, boost::regex_constants::extended);
|
||||
|
||||
for (boost::wsregex_iterator it{str.begin(), str.end(), r}, end{}; it != end;
|
||||
it++) {
|
||||
result.push_back(to_utf8(it->str()));
|
||||
}
|
||||
|
||||
return result;
|
||||
return parse(str, this->goods_name_regex, boost::regex_constants::extended);
|
||||
}
|
||||
|
||||
std::vector<std::string> StoreModule::parse_price(std::wstring str) {
|
||||
return parse(str, this->goods_price_regex, boost::regex_constants::collate);
|
||||
}
|
||||
|
||||
std::vector<std::string> StoreModule::parse_net_weight(std::vector<std::string> &names) {
|
||||
std::vector<std::string> result;
|
||||
boost::wregex r(this->goods_price_regex, boost::regex::collate);
|
||||
|
||||
for (boost::wsregex_iterator it{str.begin(), str.end(), r}, end{}; it != end;
|
||||
it++) {
|
||||
result.push_back(to_utf8(it->str()));
|
||||
for (std::string &name : names) {
|
||||
std::vector<std::string> parsed = parse(from_utf8(name), this->goods_net_weight_regex, boost::regex_constants::collate);
|
||||
if (parsed.size() == 0) {
|
||||
result.push_back("?");
|
||||
} else {
|
||||
result.push_back(parsed[0]);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<std::string> StoreModule::parse_quantity(std::wstring str) {
|
||||
std::vector<std::string> result;
|
||||
boost::wregex r(this->goods_quantity_regex, boost::regex::collate);
|
||||
|
||||
for (boost::wsregex_iterator it{str.begin(), str.end(), r}, end{}; it != end;
|
||||
it++) {
|
||||
result.push_back(to_utf8(it->str()));
|
||||
}
|
||||
return result;
|
||||
return parse(str, this->goods_quantity_regex, boost::regex_constants::collate);
|
||||
}
|
||||
|
||||
std::wstring StoreModule::trim_check(std::wstring& check) {
|
||||
|
|
|
@ -3,22 +3,28 @@
|
|||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
class StoreModule {
|
||||
std::string path;
|
||||
std::wstring name;
|
||||
std::wstring goods_name_regex;
|
||||
std::wstring goods_price_regex;
|
||||
std::wstring goods_net_weight_regex;
|
||||
std::wstring goods_quantity_regex;
|
||||
std::wstring check_start_regex;
|
||||
std::wstring check_end_regex;
|
||||
|
||||
std::vector<std::string> parse(std::wstring, std::wstring, boost::regex_constants::flag_type_);
|
||||
public:
|
||||
StoreModule(std::string);
|
||||
StoreModule();
|
||||
|
||||
std::vector<std::string> parse_name(std::wstring);
|
||||
std::vector<std::string> parse_price(std::wstring);
|
||||
std::vector<std::string> parse_net_weight(std::vector<std::string> &names);
|
||||
std::vector<std::string> parse_quantity(std::wstring);
|
||||
|
||||
std::wstring trim_check(std::wstring&);
|
||||
|
||||
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
#include "parser.h"
|
||||
#include "../goods/goods.h"
|
||||
#include "../net/net.h"
|
||||
#include "../settings/settings.h"
|
||||
#include "../utils/utils.h"
|
||||
|
||||
#include <goods/goods.h>
|
||||
#include <net/net.h>
|
||||
#include <settings/settings.h>
|
||||
#include <utils/utils.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
|
@ -15,27 +16,6 @@
|
|||
using namespace std::filesystem;
|
||||
#endif
|
||||
|
||||
static void dumpVectorsToStdErr(std::vector<std::string> &goods_names, std::vector<std::string> &goods_prices, std::vector<std::string>& goods_quantities) {
|
||||
std::cerr << goods_names.size() << " " << goods_prices.size() << " " << goods_quantities.size() << std::endl;
|
||||
std::cerr << "Found goods names: ";
|
||||
for (auto &goods_name : goods_names) {
|
||||
std::cerr << goods_name << " ";
|
||||
}
|
||||
std::cerr << std::endl;
|
||||
|
||||
std::cerr << "Found goods prices: ";
|
||||
for (auto &goods_price : goods_prices) {
|
||||
std::cerr << goods_price << " ";
|
||||
}
|
||||
std::cerr << std::endl;
|
||||
|
||||
std::cerr << "Found goods names: ";
|
||||
for (auto &goods_quantity : goods_quantities) {
|
||||
std::cerr << goods_quantity << " ";
|
||||
}
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
|
||||
Parser::Parser() {}
|
||||
|
||||
std::vector<std::string> Parser::search_modules() {
|
||||
|
@ -84,22 +64,21 @@ std::vector<Goods> Parser::parse(std::wstring check_plaintext) {
|
|||
|
||||
std::vector<std::string> goods_names = module.parse_name(check_plaintext);
|
||||
std::vector<std::string> goods_prices = module.parse_price(check_plaintext);
|
||||
std::vector<std::string> goods_quantities =
|
||||
module.parse_quantity(check_plaintext);
|
||||
std::vector<std::string> goods_net_weights = module.parse_net_weight(goods_names);
|
||||
std::vector<std::string> goods_quantities = module.parse_quantity(check_plaintext);
|
||||
|
||||
if (goods_names.size() != goods_prices.size() ||
|
||||
goods_names.size() != goods_quantities.size() ||
|
||||
goods_prices.size() != goods_quantities.size()) {
|
||||
|
||||
// dumpVectorsToStdErr(goods_names, goods_prices, goods_quantities);
|
||||
if (areAllSizesEqual(goods_names, goods_prices, goods_net_weights, goods_quantities)) {
|
||||
|
||||
//Error. Amount of names, prices or quantities are not equal. That means, that some regex(es) has mismatched.
|
||||
// dumpVectorsToStderr(goods_names, goods_prices, goods_net_weights, goods_quantities);
|
||||
|
||||
//Error. Amount of names, prices, net weights or quantities are not equal. That means, that some regex(es) has mismatched.
|
||||
return {};
|
||||
}
|
||||
short goods_amount = goods_names.size();
|
||||
|
||||
for (short i = 0; i < goods_amount; i++) {
|
||||
Goods goods(goods_names[i], std::stof(goods_prices[i]), std::stof(goods_quantities[i]));
|
||||
Goods goods(goods_names[i], std::stod(goods_prices[i]), goods_net_weights[i], std::stod(goods_quantities[i]));
|
||||
|
||||
result.push_back(goods);
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ SolveCaptchaDialog::SolveCaptchaDialog(QWidget *parent, std::string* solved_capt
|
|||
ui->setupUi(this);
|
||||
|
||||
QString captcha_path = QString::fromStdString(get_path_relative_to_home(".local/share/checks_parser/captcha.jpg"));
|
||||
std::cout << captcha_path.toStdString() << std::endl;
|
||||
ui->captcha_picture->setPixmap(captcha_path);
|
||||
ui->captcha_picture->setScaledContents(true);
|
||||
}
|
||||
|
|
|
@ -573,12 +573,12 @@
|
|||
<translation>Dialog</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../solvecaptchadialog.cpp" line="23"/>
|
||||
<location filename="../solvecaptchadialog.cpp" line="22"/>
|
||||
<source>Please, enter a valid captcha</source>
|
||||
<translation>Please, enter a valid captcha</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../solvecaptchadialog.cpp" line="25"/>
|
||||
<location filename="../solvecaptchadialog.cpp" line="24"/>
|
||||
<source>No captcha</source>
|
||||
<translation>No captcha</translation>
|
||||
</message>
|
||||
|
|
|
@ -573,12 +573,12 @@
|
|||
<translation>Диалог</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../solvecaptchadialog.cpp" line="23"/>
|
||||
<location filename="../solvecaptchadialog.cpp" line="22"/>
|
||||
<source>Please, enter a valid captcha</source>
|
||||
<translation>Пожалуйста, введите верную капчу</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../solvecaptchadialog.cpp" line="25"/>
|
||||
<location filename="../solvecaptchadialog.cpp" line="24"/>
|
||||
<source>No captcha</source>
|
||||
<translation>Нет капчи</translation>
|
||||
</message>
|
||||
|
|
|
@ -73,10 +73,17 @@ bool vector_contains_element(const std::vector<T>& vector, const T& to_find) {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
template<class T>
|
||||
bool areAllSizesEqual(const std::vector<T>& v1, const std::vector<T>& v2,
|
||||
const std::vector<T>& v3, const std::vector<T>& v4) {
|
||||
return (v1.size() == v2.size() && v2.size() == v3.size() && v3.size() == v4.size());
|
||||
}
|
||||
|
||||
|
||||
//ужас
|
||||
template bool vector_contains_element<std::string>(const std::vector<std::string>& vector, const std::string& to_find);
|
||||
|
||||
template bool areAllSizesEqual(const std::vector<std::string>& v1, const std::vector<std::string>& v2,
|
||||
const std::vector<std::string>& v3, const std::vector<std::string>& v4);
|
||||
std::vector<std::string> split(std::string s, std::string delimiter) {
|
||||
std::vector<std::string> result;
|
||||
size_t pos = 0;
|
||||
|
@ -147,7 +154,7 @@ std::vector<std::wstring> find_in_html(std::string& html, std::string regex, std
|
|||
}
|
||||
|
||||
std::vector<std::wstring> find_products_in_html(std::string html) {
|
||||
return find_in_html(html, "<div class=\"ifw-col ifw-col-1 text-left\"><b>.*<\\/b><\\/div>", "<div class=\"ifw-col ifw-col-1 text-left\"><b>", "<\\/b><\\/div>");
|
||||
return find_in_html(html, "<div class=\"ifw-col ifw-col-1 text-left\"><b>.{10,100}<\\/b><\\/div>", "<div class=\"ifw-col ifw-col-1 text-left\"><b>", "<\\/b><\\/div>");
|
||||
}
|
||||
|
||||
std::vector<std::wstring> find_amounts_in_html(std::string html) {
|
||||
|
@ -159,6 +166,19 @@ std::vector<std::wstring> find_amounts_in_html(std::string html) {
|
|||
return founds;
|
||||
}
|
||||
|
||||
std::vector<std::wstring> find_net_weights_in_names(std::vector<std::wstring> &names) {
|
||||
std::vector<std::wstring> result;
|
||||
for (std::wstring &name : names ) {
|
||||
boost::wregex regexp(from_utf8("((\\d+(.|,)?\\d?((м|)л|(к|м|)г|т|ц|шт|(pc|)s|(m|k|)g|(m|)l|t)).?)+"), boost::regex_constants::collate);
|
||||
for (boost::wsregex_iterator it{name.begin(), name.end(), regexp}, end{}; it != end;
|
||||
it++) {
|
||||
result.push_back(it->str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<std::wstring> find_prices_in_html(std::string html) {
|
||||
std::vector<std::wstring> founds = find_in_html(html, "X <\\/span><span>\\d+(\\.|,)\\d{2}<\\/span>", "X <\\/span><span>", "<\\/span>");
|
||||
for (auto &found : founds) {
|
||||
|
@ -168,7 +188,7 @@ std::vector<std::wstring> find_prices_in_html(std::string html) {
|
|||
return founds;
|
||||
}
|
||||
|
||||
void dumpVectorsToStderr(std::vector<std::wstring> &products, std::vector<std::wstring> &amounts, std::vector<std::wstring> &prices) {
|
||||
void dumpVectorsToStderr(std::vector<std::wstring> &products, std::vector<std::wstring> &amounts, std::vector<std::wstring> &net_weights, std::vector<std::wstring> &prices) {
|
||||
std::cerr << "Products: ";
|
||||
for (auto &product : products) {
|
||||
std::cerr << to_utf8(product) << "|[]|";
|
||||
|
@ -181,6 +201,12 @@ void dumpVectorsToStderr(std::vector<std::wstring> &products, std::vector<std::w
|
|||
}
|
||||
std::cerr << std::endl;
|
||||
|
||||
std::cerr << "Net weights: ";
|
||||
for (auto &net_weight : net_weights) {
|
||||
std::wcerr << net_weight << " ";
|
||||
}
|
||||
std::cerr << std::endl;
|
||||
|
||||
std::cerr << "Prices: ";
|
||||
for (auto &price : prices) {
|
||||
std::wcerr << price << " ";
|
||||
|
@ -195,6 +221,7 @@ Check parseOfdRuAnswer(std::string html) {
|
|||
|
||||
std::vector<std::wstring> products = find_products_in_html(trimmed);
|
||||
std::vector<std::wstring> amounts = find_amounts_in_html(trimmed);
|
||||
std::vector<std::wstring> net_weights = find_net_weights_in_names(products);
|
||||
std::vector<std::wstring> prices = find_prices_in_html(trimmed);
|
||||
|
||||
if ((products.size() + amounts.size() + prices.size()) == 0) {
|
||||
|
@ -209,7 +236,7 @@ Check parseOfdRuAnswer(std::string html) {
|
|||
}
|
||||
|
||||
if ((products.size() + amounts.size() + prices.size())/products.size() != 3) {
|
||||
dumpVectorsToStderr(products, amounts, prices);
|
||||
dumpVectorsToStderr(products, amounts, net_weights, prices);
|
||||
//TOOD: make new setting "app_home" and get all path using it.
|
||||
std::ofstream error_log(get_path_relative_to_home(".local/share/checks_parser/error_log.txt"), std::ios_base::app);
|
||||
error_log << trimmed << std::endl;
|
||||
|
@ -220,7 +247,7 @@ Check parseOfdRuAnswer(std::string html) {
|
|||
Check c;
|
||||
|
||||
for (int i = 0; i < products.size(); i ++) {
|
||||
Goods goods(to_utf8(products[i]), std::stod(prices[i]), std::stod(amounts[i]));
|
||||
Goods goods(to_utf8(products[i]), std::stod(prices[i]), to_utf8(net_weights[i]), std::stod(amounts[i]));
|
||||
c.add_goods(goods);
|
||||
}
|
||||
|
||||
|
@ -254,3 +281,4 @@ void generate_qr_code(std::string data) {
|
|||
QRcode_free(qrCode);
|
||||
}
|
||||
#endif // ifdef BUILD_OFD_BINARYEYE_SCAN
|
||||
|
||||
|
|
|
@ -12,6 +12,9 @@ std::string get_path_relative_to_home(std::string path);
|
|||
|
||||
template <typename T>
|
||||
bool vector_contains_element(const std::vector<T> &vector, const T &to_find);
|
||||
template <class T>
|
||||
bool areAllSizesEqual(const std::vector<T>& v1, const std::vector<T>& v2,
|
||||
const std::vector<T>& v3, const std::vector<T>& v4);
|
||||
|
||||
std::vector<std::string> split(std::string, std::string);
|
||||
|
||||
|
@ -26,4 +29,6 @@ void generate_qr_code(std::string data);
|
|||
std::string get_local_ip_address();
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif // UTILS_H
|
||||
|
|
Loading…
Reference in New Issue