diff --git a/CMakeLists.txt b/CMakeLists.txt index 550e6ae..f5a4aa5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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}) diff --git a/main.cpp b/main.cpp index 79429d3..99658d0 100644 --- a/main.cpp +++ b/main.cpp @@ -2,6 +2,7 @@ #include "meal.hpp" #include "menu.hpp" #include "restaurant.hpp" +#include "restaurants/menicka.hpp" #include "restaurants/restaurants.hpp" #include @@ -100,17 +101,15 @@ void get(const std::shared_ptr session) { int main(int /*UNUSED*/, char ** /*UNUSED*/, char **env) { setupEnv(env); - restaurants["udrevaka"] = std::make_unique(); - restaurants["padagali"] = std::make_unique(); - restaurants["lightofindia"] = - std::make_unique(); + restaurants["udrevaka"] = std::make_unique("https://www.menicka.cz/2752-u-drevaka-beergrill.html", "U Dřeváka"); + restaurants["padagali"] = std::make_unique("https://www.menicka.cz/4116-padagali.html", "Padagali"); + restaurants["lightofindia"] = std::make_unique("https://www.menicka.cz/5448-light-of-india.html", "Light of India"); restaurants["ukarla"] = std::make_unique(); - restaurants["alcapone"] = std::make_unique(); - restaurants["plac"] = std::make_unique(); - restaurants["zo"] = std::make_unique(); - restaurants["suzies"] = std::make_unique(); + restaurants["alcapone"] = std::make_unique("https://www.menicka.cz/2609-pizzeria-al-capone.html", "Al Capone"); + restaurants["suzies"] = std::make_unique("https://www.menicka.cz/3830-suzies-steak-pub.html", "Suzies"); restaurants["tao"] = std::make_unique(); restaurants["mahostina"] = std::make_unique(); + restaurants["divabara"] = std::make_unique("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(); diff --git a/restaurants/alcapone.cpp b/restaurants/alcapone.cpp deleted file mode 100644 index 1e8f348..0000000 --- a/restaurants/alcapone.cpp +++ /dev/null @@ -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]))); - } - } -} diff --git a/restaurants/restaurants.cpp b/restaurants/functions.cpp similarity index 94% rename from restaurants/restaurants.cpp rename to restaurants/functions.cpp index c72f28d..557043b 100644 --- a/restaurants/restaurants.cpp +++ b/restaurants/functions.cpp @@ -1,4 +1,4 @@ -#include "restaurants.hpp" +#include "functions.hpp" std::string LunchRest::nodeToText(xmlpp::Node *node) { return dynamic_cast(node)->get_content(); diff --git a/restaurants/functions.hpp b/restaurants/functions.hpp new file mode 100644 index 0000000..4c45fd1 --- /dev/null +++ b/restaurants/functions.hpp @@ -0,0 +1,10 @@ +#ifndef LUNCH_REST_FUNCTIONS +#define LUNCH_REST_FUNCTIONS +#include +#include + +namespace LunchRest { +std::string nodeToText(xmlpp::Node *node); +std::string trim(const std::string &input); +} +#endif diff --git a/restaurants/lightofindia.cpp b/restaurants/lightofindia.cpp deleted file mode 100644 index 65f72a3..0000000 --- a/restaurants/lightofindia.cpp +++ /dev/null @@ -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); - } -} diff --git a/restaurants/mahostina.cpp b/restaurants/mahostina.cpp index 10f5b5a..4d51c23 100644 --- a/restaurants/mahostina.cpp +++ b/restaurants/mahostina.cpp @@ -1,3 +1,4 @@ +#include "functions.hpp" #include "restaurants.hpp" #include "../network/network.hpp" #include "../htmlparser.hpp" diff --git a/restaurants/menicka.cpp b/restaurants/menicka.cpp new file mode 100644 index 0000000..6700760 --- /dev/null +++ b/restaurants/menicka.cpp @@ -0,0 +1,73 @@ +#include "menicka.hpp" +#include "../network/network.hpp" +#include "../htmlparser.hpp" +#include "functions.hpp" + +std::pair 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); + } + } +} diff --git a/restaurants/menicka.hpp b/restaurants/menicka.hpp new file mode 100644 index 0000000..10fec3c --- /dev/null +++ b/restaurants/menicka.hpp @@ -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 diff --git a/restaurants/padagali.cpp b/restaurants/padagali.cpp deleted file mode 100644 index afd915c..0000000 --- a/restaurants/padagali.cpp +++ /dev/null @@ -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++; - } -} diff --git a/restaurants/plac.cpp b/restaurants/plac.cpp deleted file mode 100644 index 7da9387..0000000 --- a/restaurants/plac.cpp +++ /dev/null @@ -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); - } -} diff --git a/restaurants/restaurants.hpp b/restaurants/restaurants.hpp index e4b74e2..2e09dee 100644 --- a/restaurants/restaurants.hpp +++ b/restaurants/restaurants.hpp @@ -2,56 +2,12 @@ #include 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") {} diff --git a/restaurants/suzies.cpp b/restaurants/suzies.cpp deleted file mode 100644 index 5541e20..0000000 --- a/restaurants/suzies.cpp +++ /dev/null @@ -1,93 +0,0 @@ -#include "restaurants.hpp" -#include "../network/network.hpp" -#include "../htmlparser.hpp" -#include - -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); - } -} diff --git a/restaurants/tao.cpp b/restaurants/tao.cpp index d096a28..642d854 100644 --- a/restaurants/tao.cpp +++ b/restaurants/tao.cpp @@ -1,3 +1,4 @@ +#include "functions.hpp" #include "restaurants.hpp" #include "../network/network.hpp" #include "../htmlparser.hpp" diff --git a/restaurants/udrevaka.cpp b/restaurants/udrevaka.cpp deleted file mode 100644 index 91ac086..0000000 --- a/restaurants/udrevaka.cpp +++ /dev/null @@ -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++; - } -} diff --git a/restaurants/ukarla.cpp b/restaurants/ukarla.cpp index d2ae6f4..d22513b 100644 --- a/restaurants/ukarla.cpp +++ b/restaurants/ukarla.cpp @@ -1,3 +1,4 @@ +#include "functions.hpp" #include "restaurants.hpp" #include "../network/network.hpp" #include "../htmlparser.hpp" diff --git a/restaurants/zo.cpp b/restaurants/zo.cpp deleted file mode 100644 index 04dc1ed..0000000 --- a/restaurants/zo.cpp +++ /dev/null @@ -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); -}