Move as much as possible to menicka.cz

This commit is contained in:
zv0n 2022-03-03 08:49:58 +01:00
parent c73199e6d6
commit 2a5d6d3fce
17 changed files with 110 additions and 424 deletions

View File

@ -15,28 +15,22 @@ find_library(Curl curl
project(LunchRest)
list(APPEND Restaurants
restaurants/udrevaka.cpp
restaurants/padagali.cpp
restaurants/lightofindia.cpp
restaurants/ukarla.cpp
restaurants/alcapone.cpp
restaurants/plac.cpp
restaurants/zo.cpp
restaurants/suzies.cpp
restaurants/tao.cpp
restaurants/mahostina.cpp
restaurants/menicka.cpp
)
add_executable(lunchrest)
target_sources(lunchrest
PRIVATE ${Restaurants}
PRIVATE ${Restaurants}
PRIVATE main.cpp
PRIVATE meal.cpp
PRIVATE menu.cpp
PRIVATE network/network.cpp
PRIVATE restaurants/restaurants.cpp
PRIVATE environment.cpp
PRIVATE restaurants/functions.cpp
)
target_link_libraries(lunchrest ${LIBXML_LIBRARIES} ${LIBXMLPP_LIBRARIES} ${Restbed} ${Curl})

View File

@ -2,6 +2,7 @@
#include "meal.hpp"
#include "menu.hpp"
#include "restaurant.hpp"
#include "restaurants/menicka.hpp"
#include "restaurants/restaurants.hpp"
#include <fstream>
@ -100,17 +101,15 @@ void get(const std::shared_ptr<restbed::Session> session) {
int main(int /*UNUSED*/, char ** /*UNUSED*/, char **env) {
setupEnv(env);
restaurants["udrevaka"] = std::make_unique<LunchRest::UDrevakaRestaurant>();
restaurants["padagali"] = std::make_unique<LunchRest::PadagaliRestaurant>();
restaurants["lightofindia"] =
std::make_unique<LunchRest::LightOfIndiaRestaurant>();
restaurants["udrevaka"] = std::make_unique<LunchRest::MenickaRestaurant>("https://www.menicka.cz/2752-u-drevaka-beergrill.html", "U Dřeváka");
restaurants["padagali"] = std::make_unique<LunchRest::MenickaRestaurant>("https://www.menicka.cz/4116-padagali.html", "Padagali");
restaurants["lightofindia"] = std::make_unique<LunchRest::MenickaRestaurant>("https://www.menicka.cz/5448-light-of-india.html", "Light of India");
restaurants["ukarla"] = std::make_unique<LunchRest::UKarlaRestaurant>();
restaurants["alcapone"] = std::make_unique<LunchRest::AlCaponeRestaurant>();
restaurants["plac"] = std::make_unique<LunchRest::PlacRestaurant>();
restaurants["zo"] = std::make_unique<LunchRest::ZoRestaurant>();
restaurants["suzies"] = std::make_unique<LunchRest::SuziesRestaurant>();
restaurants["alcapone"] = std::make_unique<LunchRest::MenickaRestaurant>("https://www.menicka.cz/2609-pizzeria-al-capone.html", "Al Capone");
restaurants["suzies"] = std::make_unique<LunchRest::MenickaRestaurant>("https://www.menicka.cz/3830-suzies-steak-pub.html", "Suzies");
restaurants["tao"] = std::make_unique<LunchRest::TaoRestaurant>();
restaurants["mahostina"] = std::make_unique<LunchRest::MahostinaRestaurant>();
restaurants["divabara"] = std::make_unique<LunchRest::MenickaRestaurant>("https://www.menicka.cz/325-restaurace-diva-bara.html", "Divá Bára");
std::cout << "Initial parsing" << std::endl;
for (auto &restaurant : restaurants)
restaurant.second->parse();

View File

@ -1,55 +0,0 @@
#include "restaurants.hpp"
#include "../network/network.hpp"
#include "../htmlparser.hpp"
std::string removeAlergens(const std::string &name) {
int pos = name.length() - 1;
while(name[pos] == ',' || std::isdigit(name[pos]))
pos--;
return name.substr(0,pos);
}
void LunchRest::AlCaponeRestaurant::parse() {
Request r;
auto html = r.get(_url);
if(html == "")
return;
clearMenus();
HtmlParser hparse(html);
auto &root = hparse.getRoot();
auto rows = root.find("//table[@class='table table-responsive']/tbody/tr");
int cur_day = -1;
for(auto &row : rows) {
if(row->find("./td[@class='bg1']").size() != 0) {
std::string day = nodeToText(row->find("./td[@class='bg1']/text()")[0]);
if(day.find("pondělí") != std::string::npos)
cur_day = 0;
else if(day.find("úterý") != std::string::npos)
cur_day = 1;
else if(day.find("středa") != std::string::npos)
cur_day = 2;
else if(day.find("čtvrtek") != std::string::npos)
cur_day = 3;
else if(day.find("pátek") != std::string::npos)
cur_day = 4;
else if(day.find("sobota") != std::string::npos)
cur_day = 5;
else if(day.find("neděle") != std::string::npos)
cur_day = 6;
menus[cur_day].setInvalidMenu(false);
continue;
}
if(cur_day < 0)
continue;
auto menu_info = row->find("./td/text()");
auto meal_data = row->find("./td/h3/text()");
std::string menu = nodeToText(menu_info[0]);
std::string name = nodeToText(meal_data[0]);
name = removeAlergens(name);
if(menu == "Polévka") {
menus[cur_day].addMeal(true, name, "", 0);
} else {
menus[cur_day].addMeal(false, name, "", std::stoi(nodeToText(meal_data[1])));
}
}
}

View File

@ -1,4 +1,4 @@
#include "restaurants.hpp"
#include "functions.hpp"
std::string LunchRest::nodeToText(xmlpp::Node *node) {
return dynamic_cast<const xmlpp::ContentNode *>(node)->get_content();

10
restaurants/functions.hpp Normal file
View File

@ -0,0 +1,10 @@
#ifndef LUNCH_REST_FUNCTIONS
#define LUNCH_REST_FUNCTIONS
#include <string>
#include <libxml++/libxml++.h>
namespace LunchRest {
std::string nodeToText(xmlpp::Node *node);
std::string trim(const std::string &input);
}
#endif

View File

@ -1,44 +0,0 @@
#include "restaurants.hpp"
#include "../network/network.hpp"
#include "../htmlparser.hpp"
bool isWhiteSpaceOnly(const std::string &text) {
if(text == "")
return true;
for(auto &x : text) {
if(!std::isspace(x))
return false;
}
return true;
}
void LunchRest::LightOfIndiaRestaurant::parse() {
Request r;
auto html = r.get(_url);
if(html == "")
return;
clearMenus();
HtmlParser hparse(html);
auto &root = hparse.getRoot();
auto container = root.find("//div[@id='content_container']")[0];
auto texts = container->find(".//td/text()");
int index = -1;
for(auto text : texts) {
std::string text_text = nodeToText(text);
if(isWhiteSpaceOnly(text_text) || text_text.find("Week") != std::string::npos)
continue;
if(text_text[0] == '1')
index++;
auto end = text_text.find(')');
if(end == std::string::npos)
continue;
auto possible_end = text_text.find('g', end);
if(possible_end != std::string::npos)
end = possible_end;
std::string name = text_text.substr(4, end - 3);
int price = std::stoi(text_text.substr(end+1));
bool soup = name.find("soup") == std::string::npos ? false : true;
menus[index].addMeal(soup, name, "", price);
menus[index].setInvalidMenu(false);
}
}

View File

@ -1,3 +1,4 @@
#include "functions.hpp"
#include "restaurants.hpp"
#include "../network/network.hpp"
#include "../htmlparser.hpp"

73
restaurants/menicka.cpp Normal file
View File

@ -0,0 +1,73 @@
#include "menicka.hpp"
#include "../network/network.hpp"
#include "../htmlparser.hpp"
#include "functions.hpp"
std::pair<std::string, int> getNameAndPrice(xmlpp::Node *meal) {
auto souptext = meal->find("./div[@class='polozka']/text()");
auto soupprice = meal->find("./div[@class='cena']/text()");
std::string name = "";
int price = -1;
if(souptext.size() != 0) {
name = LunchRest::nodeToText(souptext[0]);
}
if(soupprice.size() != 0) {
price = std::stoi(LunchRest::nodeToText(soupprice[0]));
}
return {name, price};
}
void LunchRest::MenickaRestaurant::parse() {
Request r;
auto html = r.get(_url);
if(html == "")
return;
clearMenus();
HtmlParser hparse(html);
auto &root = hparse.getRoot();
auto days = root.find("//div[@class='menicka']");
for(auto &day : days) {
auto daytext = day->find("./div[@class='nadpis']/text()");
auto soup = day->find("./ul/li[@class='polevka']");
auto meals = day->find("./ul/li[@class='jidlo']");
if(daytext.size() == 0) {
continue;
}
auto daystr = nodeToText(daytext[0]);
int cur_day = 0;
switch (daystr[0]) {
case 'P':
if (daystr[1] != 'o') {
cur_day = 4;
}
break;
case "Ú"[0]:
cur_day = 1;
break;
case 'S':
cur_day = 2;
break;
case "Č"[0]:
cur_day = 3;
default:
break;
}
if(soup.size() != 0) {
auto soupData = getNameAndPrice(soup[0]);
if(!soupData.first.empty()) {
menus[cur_day].addMeal(Meal(true, soupData.first, "", soupData.second));
}
}
for(auto &meal : meals) {
auto mealData = getNameAndPrice(meal);
if(!mealData.first.empty()) {
menus[cur_day].addMeal(Meal(false, mealData.first, "", mealData.second));
}
}
if(!menus[cur_day].getMeals().empty()) {
menus[cur_day].setInvalidMenu(false);
}
}
}

13
restaurants/menicka.hpp Normal file
View File

@ -0,0 +1,13 @@
#ifndef LUNCH_REST_MENICKA
#define LUNCH_REST_MENICKA
#include "../restaurant.hpp"
namespace LunchRest {
class MenickaRestaurant : public Restaurant {
public:
MenickaRestaurant(const std::string &url, const std::string &name) : Restaurant(url, name) {}
virtual ~MenickaRestaurant() = default;
virtual void parse() override;
};
}
#endif

View File

@ -1,53 +0,0 @@
#include "restaurants.hpp"
#include "../network/network.hpp"
#include "../htmlparser.hpp"
int dayToNum(const std::string &day) {
if(day.find("POND") != std::string::npos) {
return 0;
}
if (day.find("ÚTER") != std::string::npos) {
return 1;
}
if (day.find("STŘE") != std::string::npos) {
return 2;
}
if (day.find("ČTVR") != std::string::npos) {
return 3;
}
if (day.find("PÁTE") != std::string::npos) {
return 4;
}
return -1;
}
void LunchRest::PadagaliRestaurant::parse() {
Request r;
auto html = r.get(_url);
if(html.empty()) {
return;
}
clearMenus();
HtmlParser hparse(html);
auto &root = hparse.getRoot();
auto days = root.find("//div[@class='glf-mor-restaurant-menu-category']");
auto menu_index = dayToNum(nodeToText(days[0]->find("./h3/text()")[0]));
if(menu_index == -1) {
return;
}
auto max_div = 5 - menu_index;
for(int i = 0; i < max_div; i++) {
auto *day = days[i];
auto meals = day->find("./div");
for(auto &meal : meals) {
auto info = meal->find("./div/div/div");
std::string desc = nodeToText(info[1]->find("./text()")[0]);
std::string name = nodeToText(info[0]->find("./h5/text()")[0]);
int price = std::stoi(nodeToText(info[0]->find("./div/span/text()")[0]));
bool soup = name.find("Soup") != std::string::npos;
menus[menu_index].addMeal(soup, name, desc, price);
menus[menu_index].setInvalidMenu(false);
}
menu_index++;
}
}

View File

@ -1,50 +0,0 @@
#include "restaurants.hpp"
#include "../network/network.hpp"
#include "../htmlparser.hpp"
void LunchRest::PlacRestaurant::parse() {
Request r;
auto html = r.get(_url);
if(html == "")
return;
clearMenus();
HtmlParser hparse(html);
auto &root = hparse.getRoot();
auto pizzas = root.find("//div[@class='mt-c cf']//div[@class='mt-i cf']");
if(pizzas.size() == 0)
return;
auto soups = pizzas[0]->find(".//div[@class='b b-text cf']");
int soup_price = std::stoi(nodeToText(soups[1]->find(".//strong/text()")[0]));
int cur_day = -1;
for(auto &soup : soups[0]->find(".//p/text()")) {
std::string soup_text = nodeToText(soup);
auto soup_day = soup_text.substr(0,2);
if(soup_day == "Po")
cur_day = 0;
if(cur_day < 0)
continue;
menus[cur_day].setInvalidMenu(false);
auto soupname = soup_text.substr(5);
while(std::isspace(soupname[0]))
soupname = soupname.substr(1);
menus[cur_day].addMeal(true, soupname, "", soup_price);
cur_day++;
if(cur_day > 4)
break;
}
for(unsigned long int i = 2; i < pizzas.size(); i++) {
auto content = pizzas[i]->find(".//div[@class='b b-text cf']");
auto name_candidates = content[0]->find(".//h3/text()");
std::string name = nodeToText(name_candidates[0]);
auto desc_candidates = content[0]->find(".//p//text()");
std::string desc = nodeToText(desc_candidates[0]);
auto price_candidates = content[1]->find(".//p/strong/text()");
int price = std::stoi(nodeToText(price_candidates[0]));
name = trim(name);
desc = trim(desc);
addPermanent(false, name, desc, price);
}
}

View File

@ -2,56 +2,12 @@
#include <libxml++/libxml++.h>
namespace LunchRest {
std::string nodeToText(xmlpp::Node *node);
std::string trim(const std::string &input);
class UDrevakaRestaurant : public Restaurant {
public:
UDrevakaRestaurant() : Restaurant("https://udrevaka.cz/denni-menu/", "U Dřeváka") {}
virtual ~UDrevakaRestaurant() = default;
virtual void parse() override;
};
class PadagaliRestaurant : public Restaurant {
public:
PadagaliRestaurant() : Restaurant("https://padagali.cz/denni-menu/", "Padagali") {}
virtual ~PadagaliRestaurant() = default;
virtual void parse() override;
};
class LightOfIndiaRestaurant : public Restaurant {
public:
LightOfIndiaRestaurant() : Restaurant("http://lightofindia.cz/lang-en/denni-menu", "Light of India") {}
virtual ~LightOfIndiaRestaurant() = default;
virtual void parse() override;
};
class UKarlaRestaurant : public Restaurant {
public:
UKarlaRestaurant() : Restaurant("https://ukarlabrno.cz/denni-menu/", "U Karla") {}
virtual ~UKarlaRestaurant() = default;
virtual void parse() override;
};
class AlCaponeRestaurant : public Restaurant {
public:
AlCaponeRestaurant() : Restaurant("https://www.pizzaalcapone.cz/cz/poledni-menu", "Al Capone") {}
virtual ~AlCaponeRestaurant() = default;
virtual void parse() override;
};
class PlacRestaurant : public Restaurant {
public:
PlacRestaurant() : Restaurant("https://www.bistroplac.cz/poledni-nabidka/", "Bistro Plac") {}
virtual ~PlacRestaurant() = default;
virtual void parse() override;
};
class ZoRestaurant : public Restaurant {
public:
ZoRestaurant();
virtual ~ZoRestaurant() = default;
virtual void parse() override {};
};
class SuziesRestaurant : public Restaurant {
public:
SuziesRestaurant() : Restaurant("https://www.suzies.cz/poledni-menu", "Suzie's") {}
virtual ~SuziesRestaurant() = default;
virtual void parse() override;
};
class TaoRestaurant : public Restaurant {
public:
TaoRestaurant() : Restaurant("https://www.taorestaurant.cz/tydenni_menu/nabidka/", "Táo Viet Nam") {}

View File

@ -1,93 +0,0 @@
#include "restaurants.hpp"
#include "../network/network.hpp"
#include "../htmlparser.hpp"
#include <iostream>
void LunchRest::SuziesRestaurant::parse() {
Request r;
auto html = r.get(_url);
if (html == "")
return;
clearMenus();
HtmlParser hparse(html);
auto &root = hparse.getRoot();
auto days = root.find("//div[@class='uk-card-body item']");
for (auto &day : days) {
auto daytext = nodeToText(day->find("./h2/text()")[0]);
int cur_day = 0;
switch (daytext[0]) {
case 'P':
if (daytext[1] != 'o') {
cur_day = 4;
}
break;
case "Ú"[0]:
cur_day = 1;
break;
case 'S':
cur_day = 2;
break;
case "Č"[0]:
cur_day = 3;
default:
break;
}
bool working_on_meal = false;
bool working_on_soup = false;
Meal meal{};
for (auto &child : day->get_children()) {
if (child->get_name() == "h3" &&
child->find("./text()").size() != 0) {
auto meal_type = trim(nodeToText(child->find("./text()")[0]));
meal = Meal();
working_on_meal = true;
if (meal_type == "Polévka") {
working_on_soup = true;
meal.setSoup();
} else {
meal.setDesc(meal_type);
}
}
if (working_on_meal && child->get_name() == "div") {
if (!working_on_soup) {
auto price_elements =
child->find("./div[contains(@class, 'price')]/text()");
if (price_elements.size() == 0) {
goto end;
}
auto price = nodeToText(price_elements[0]);
meal.setPrice(std::stoi(price));
auto namelen = child
->find("./div[contains(@class, "
"'uk-width-expand')]/text()")
.size();
std::string name = "";
if (namelen == 1) {
name = trim(nodeToText(child->find(
"./div[contains(@class, 'uk-width-expand')]/text()")
[0]));
} else {
name = trim(nodeToText(child->find(
"./div[contains(@class, "
"'uk-width-expand')]/span/text()")[0])) +
" " +
trim(nodeToText(child->find(
"./div[contains(@class, "
"'uk-width-expand')]/text()")[1]));
}
meal.setName(name);
} else {
auto name = trim(nodeToText(child->find(
"./div[contains(@class, 'uk-width-expand')]/text()")
[0]));
meal.setName(name);
}
menus[cur_day].addMeal(meal);
end:
working_on_meal = false;
working_on_soup = false;
}
}
menus[cur_day].setInvalidMenu(false);
}
}

View File

@ -1,3 +1,4 @@
#include "functions.hpp"
#include "restaurants.hpp"
#include "../network/network.hpp"
#include "../htmlparser.hpp"

View File

@ -1,36 +0,0 @@
#include "restaurants.hpp"
#include "../network/network.hpp"
#include "../htmlparser.hpp"
void LunchRest::UDrevakaRestaurant::parse() {
int menu_index = 0;
Request r;
auto html = r.get(_url);
if(html == "")
return;
clearMenus();
HtmlParser hparse(html);
auto &root = hparse.getRoot();
auto days = root.find("//li[@class='item-day']");
for(auto &day : days) {
auto meals = day->find("./div[@class='row']");
for(auto &meal : meals) {
auto divs = meal->find(".//div/text()");
Meal meal_obj{};
std::string name = trim(nodeToText(divs[0]));
auto soup_pos = name.find("Polévka");
if(soup_pos != std::string::npos) {
meal_obj.setSoup();
meal_obj.setName(name.substr(10, name.find('(') - 11));
} else {
meal_obj.setName(name.substr(3, name.find('(') - 4));
}
if(divs.size() > 1) {
meal_obj.setPrice(std::stoi(trim(nodeToText(divs[1]))));
}
menus[menu_index].addMeal(meal_obj);
menus[menu_index].setInvalidMenu(false);
}
menu_index++;
}
}

View File

@ -1,3 +1,4 @@
#include "functions.hpp"
#include "restaurants.hpp"
#include "../network/network.hpp"
#include "../htmlparser.hpp"

View File

@ -1,31 +0,0 @@
#include "restaurants.hpp"
LunchRest::ZoRestaurant::ZoRestaurant() : Restaurant("", "Zo!") {
clearMenus();
addPermanent(true, "Pho Bo", "Rýžové nudle pho v hovězím vývaru, hovězí maso, vietnamské bylinky", 120);
addPermanent(true, "Pho Bo Tai Lan", "Rýžové nudle pho v hovězím vývaru, RESTOVANÉ hovězí maso, vietnamské bylinky", 120);
addPermanent(true, "Bun Bo Hue", "Rýžové nudle bun v hovězím vývaru po Hue, masové kuličky, krevetová pasta", 120);
addPermanent(true, "Bun Tom", "Rýžové nudle bun s krevety", 120);
addPermanent(true, "Bun Dau", "Rýžové nudle bun v zeleninovém vývaru, tofu", 120);
addPermanent(true, "Pho Bo Bam", "Rýžové nudle pho, syrové nasekané hovězí maso zalité hovězím vývarem, vietnamské bylinky", 135);
addPermanent(true, "Bun Moc", "Rýžové nudle bun, kuřecí vývar s masovými kuličky, houbami a bylinkami", 125);
addPermanent(false, "Bun Bo Nam Bo", "Rýžové nudle bun, hovězí maso, vietnamské bylinky, sladkokyselá zálivka", 135);
addPermanent(false, "Bun Ga Tron", "Rýžové nudle bun s restovaným kuřecím masem, vietnamské bylinky, omáčka ZO!", 135);
addPermanent(false, "Bun Dau Zo", "Podobné jako Bun Bo Nam Bo, ale s tofu", 120);
addPermanent(false, "Bun Tom Tron", "Rýžové nudle bun s krevety, vietnamské bylinky, omáčka ZO!", 135);
addPermanent(false, "Zo Bowl", "Miska plná rýžových nudlí a zeleniny, hrášek, houby shitake, brokolice, mungo, arašídová omáčka", 135);
addPermanent(false, "Mi Orizo", "Orestované nudle z naší kuchyně, Vyberte si: kuřecí (120), hovězí (130)", 120);
addPermanent(false, "Ban Da Xao", "Orestované jižanské placaté rýžové nudle, Vyberte si: kuřecí (120), hovězí (135)", 120);
addPermanent(false, "Mi Udozo", "Orestované udon nudle po našem stylu, Vyberte si: kuřecí, hovězí", 135);
addPermanent(false, "Bun Ngan Nuong", "Grilované kachní maso, rýžové nudle bun, vietnamské bylinky, sojová omáčka", 155);
addPermanent(false, "Bun Cha", "Grilované vepřové maso, rýžové nudle bun, vietnamské bylinky, sladkokyselá zálivka", 135);
addPermanent(false, "Salát Bo Zo", "Smažené obalené kousky avokáda, zelenina, ředkev", 135);
addPermanent(false, "Com Xuat dle šéfkuchaře", "Vyberte si základ (kuřecí, vepřové, hovězí, krevetové, tofu), my domyslíme zbytek, rýže, zelenina", 135);
addPermanent(false, "Rýže s kari omáčkou", "Vyberte si: kuřecí, hovězí, krevety, tofu", 120);
addPermanent(false, "Vitský", "Smažená kachna podávaná s bambusovými výhonky a rýží", 155);
addPermanent(false, "Nem Ran 2ks", "Smažené rolky", 50);
addPermanent(false, "Nem Cuon Tom 2ks", "Smažené rolky plněné krevetami", 50);
addPermanent(false, "Nem Cuon Bo 2ks", "Nesmažené rolky plněné avokádem podle Zo", 70);
addPermanent(false, "Nem Cuon Vege 2ks", "Nesmažené rolky plněné tofu", 50);
addPermanent(false, "Nem Ran Vege 2ks", "Smažené rolky plněné zeleninou (bez masa)", 50);
}