Obiectivul temei îl reprezintă exercițiul cu mai multe concepte de bază ale Programării Orientate pe Obiecte, presupunând că totul se întâmplă în contextul unui proiect pe care trebuie să îl implementați la locul de muncă si o parte din implementare a fost deja facuta de alti colegi.
Tema 2 utilizează următoarele concepte:
Responsabili: BARAC Ilie-Constantin, CRAIOVEANU Sergiu-Ionuț, IONIȚĂ Alexandru, PARASCHIVA Mihai-Florian
Link Github: click aici
Arhiva: click aici
git clone <repo_link>
sugeram folosirea WSL. Git Bash introduce probleme in formatarea fisierelor intre Windows/Linux (CRLF vs LF). Cei care au Linux/VM cu Linux nu vor intampina probleme. De asemenea, puteti downlada arhiva fara probleme.
Link Github: https://github.com/poo-is-aa/tema2_schelet
Arhiva: tema2_schelet-master.zip
- 24-12-20: Modificare enunt Cerinta 3, Query 3c: Se vor cauta doar produse resigilate (in loc de produse returnate si resigilate). Se mentioneaza ca sortarea va fi crescatoare, in functie de pret. Am adaugat si informatii suplimentare legate de dynamic cast.
- 04-01-21: Am adaugat o sectiune de “Debugging”, care explica cum puteti rula executabilul fara ajutorul checker-ului.
- 05-01-21: Adăugat în descrierea temei cele două scheme ce prezintă structura unui ID pentru obiectele de tip produs si user. Adăugat informații suplimentare în cadrul cerinței LRU Cache (nu fixați dimensiunea la 4, precum cea din exemplu. Aceasta poate fi oricât).
- 07-01-21: Adăugat clarificare suplimentară Query 3f: este nevoie de sortare doar dacă nu iterați lista cu utilizatori în ordinea begin() → end().
- 08-01-21: Adăugat clarificare suplimentară Query 3e: este nevoie de sortare dupa ID-ul utilizatorilor inainte de a returna lista.
- 11-01-21: Adăugat clarificare suplimentară Query 3f: orice produs poate avea cupon (nu doar cele deja reduse). Map-ul unui utilizator premium poate conține cupoane pentru produse care nu mai sunt disponibile. Căutați doar produsele ce se găsesc și în magazin (deci în lista de produse de pe server).
- 20-01-21: BUG Query 3d. Există două perechi de produse alimentare cu același preț si cu acelasi nume (Offtopic: nu stiu care erau sansele. Am generat preturile folosind rand() din MATLAB). Acestea au ID-urile 1238-12112 si 11110-11130. In cazul in care output-ul pare similar cu fisierul de referinta pentru testul 8, verificati ordinea acestor perechi de produse. O modificare a capatului listei prin care adaugati elemente ar trebui sa rezolve problema (push_back in loc de push_front). Multumiri lui Dennis-Andrei Bicu si Bogdan-Andrei Enache pentru descoperirea bug-ului.
- 23-12-20: Varianta de arhiva continea executabilul si output-ul ce putea genera nota maxima. Era inconsistenta intre varianta git si cea din arhiva, acum ambele sunt in varianta fara executabil/output. Au aparut nedumeriri in legatura cu 'ce mai trebuie facut'. Corectarea se va face cu rerularea codului sursa si regenerarea tuturor output-urilor. Acel executabil era mai degraba ca sa vedeti ca tema functioneaza corect.
- 04-01-21: Cerinta 3f (Query f) avea in fisierul de .ref obiecte cu UserID duplicate. Acestea au fost eliminate. Dupa sine, asta a atras regenerarea fisierului de referinta, care difera de versiunea anterioara. Concret, doar fisierul ref10.out din folderul .ref a fost modificat. Kudos Petronel-Valeriu MARIN.
Prin această temă, dorim să implementam un sistem pentru o platforma online dedicata vanzarii de produse diverse. Entitatile principale sunt Produsele, Utilizatorii si Serverul care stocheaza detalii despre produse si utilizatori si unde se pot efectua diverse operatii asupra entitatilor, precum căutări de produse, de utilizatori sau modificări de diferite cantități (adăugare sau scoatere de produse din coș).
Mai jos detaliem clasele, cu scopul de a oferi o intelegere mai buna asupra proiectului.
Sageata alba inspre o clasa: 'derivare din'
Aceasta este cea mai complicata ierarhie de clase a intregului proiect - din motive evidente - cand intrati pe un site de retail, tipurile de produse pot fi deseori coplesitoare prin pura lor varietate. Numele Claselor (si implicit al tipurilor) sunt in engleza pentru consecventa (ca sa minimizam utilizarea romglezei in acest proiect).
Asadar, clasa Product (Produs) este abstracta din dorinta de a ramifica tipurile de produse de pe site. Niciodata nu o sa avem un produs (simplu), intotdeauna o sa apartina de o 'categorie' anume. Ea reprezinta o schita pentru restul tipurilor de produse ce se vor deriva din aceasta.
Mai departe, distingem 2 tipuri de produse: FoodProduct (Produs Alimentar) si NonFoodProduct (Produs Nealimentar) - ca in viata reala. Fiecare din aceste clase aduce dupa sine campuri/metode noi.
Pentru ca viata reala e deseori mai complicata decat am spera, in sectiunea produselor nealimentare avem de rezolvat o problema de tip 'Death Diamond', conform diagramei de mai sus. NonFood Product (Produsele Nealimentare) pot fi de 2 tipuri: Returned Products (Produse Returnate, care probabil aveau defecte) si Discounted Products (Produse Reduse, care au un pret scazut fata de cel normal).
Din cele 2 ia nastere Resealed Product (Produs Resigilat), care indeplineste atat proprietatea de a fi un produs returnat, cat si unul redus.
Romb alb inspre o clasa: 'agregare'
Urmatoarea ierarhie de clase are ca scop implementarea urmatoarei paradigme: “Dai un ban, dar stai in fata”.
Clasa User este una abstracta, care reprezinta schita celor 2 tipuri de Useri: Basic User si Premium User. Astfel, reusim sa distingem tipurile de Useri prin diferite campuri/metode, oferind posibilitatea particularizarilor (planuri de plata diferite, in functie de User).
Trebuie precizat că Userii Premium au un map de reduceri de tipul <int ProductID, int discount>, în care sunt stocate reduceri pentru diferite produse. Atenție: Map-ul poate conține și ID-uri ale produselor ce nu se mai află în acest moment în magazin (nu se află în lista cu produse de pe server)
Ca in ierarhia de clase Product, clasa User este abstracta, neputand sa avem un User simplu, ci doar Basic sau Premium.
Are loc, de asemenea, procesul de agregare printr-o clasa Address al carui scop este de a introduce campuri complexe de adresa Userilor.
Nevoia unei clase de Shopping Cart (Cos Produse) este evidenta pentru toata lumea, mai ales pentru cei care aleg sa nu ia un cos la intrarea in magazin si tin toate produsele in mana pana la casa.
Cel mai important aspect al acestei clase este reprezentat de campul “shoppingCart”, un map ce contine 2 numere intregi per intrare.
map <int, int> shoppingCart
Cheia (primul numar intreg) reprezinta Product ID, adica ID-ul unui produs din 'Baza de Date' a produselor. Valoarea (al doilea numar intreg) reprezinta Quantity, adica cantitatea unui produs din cos. Practic, per intrare in cosul nostru de produse, vom avea o pereche (ProdusID, Quantity).
e.g. (225200, 420) -> Produsul cu ID-ul 225200 are cantitatea de 420 in cosul nostru.
Cosul joaca un rol esential mai departe in integrarea lui pe Server, in concordanta cu UserID.
Clasa Server este piesa ce leaga tot. Aici stocam toate datele legate de Useri si Produse (in liste neomogene). Astfel, ne-ar placea sa avem 'acces' la aceste date de 'oriunde'.
Analogia de mai sus se traduce prin implementarea unui Design Pattern numit Singleton. Concret, Singleton ne permite instantierea unui singur obiect de un anume tip (un singur obiect de tip Server, numit server), care poate fi accesat din multiple clase.
Pentru a construi o mai buna intuitie asupra Design Pattern-ului Singleton, click aici. Pentru un exemplu de cod, click aici.
Avem o instanta a clasei Server, pe care o numim server. Pentru a obtine lista de Produse prin instanta server, putem scrie ceva de genul:
server->getProductsList()
Concret, exista un singur Bucuresti, la care se poate ajunge din orice oras al Romaniei.
Un camp important din clasa Server este reprezentat de map-ul:
map<int, ShoppingCart*> __UserID__ProductsCart__
Cheia este un UserID (id-ul unui User/Utilizator). Valoarea este un pointer catre un obiect de tip ShoppingCart (Cos Produse). Practic, acest map reprezinta legatura dintre un User si cosul sau de produse, o functionalitate prevalenta in toate site-ul de retail.
Aceasta clasa este pusa la dispozitia voastra pentru a implementa cerintele ce tin de Queries/Interogari. Fiecare subcerinta are o metoda aferenta.
Ea nu se afla in propriul folder fiindca nu reprezinta un 'tip' utilizat in proiectul nostru. Este doar o clasa ajutatoare, care speram ca va facilita abordarea cerintelor de Query (Cerinta 3).
In general, cand vorbim despre resurse computationale si servicii oferite, mereu apare cuvantul “optimizare”. Motivul e simplu: Daca operatiile se efectueaza suficient de repede, avem clienti multumiti. De asemenea, reducand spatiul ocupat pe servere, ajungem sa platim mai putin pentru serviciile Cloud. Astfel, atunci cand rulam milioane de operatii zilnic, optimizarea unei operatii ce are loc des (de exemplu accesul la o resursa populara), poate avea un impact masiv asupra intregului serviciu oferit.
Intuitiv, produsele populare vor fi destul de des accesate, deci ne-ar placea sa oferim acces “privilegiat” acestora. Acesta paradigma se traduce intr-o modificare hardware.
Asadar, pentru implementarea paradigmei de mai sus, vom simula comportamentul unui 'Least Recently Used Cache', care va retine id-ul produselor ce reprezinta ultimele accesari ale utilizatorilor. Pentru o scurta explicatie asupra LRU Cache, click aici.
La deschiderea folderului principal al Proiectului (temei), veti fi intampinati de 2 entitati:
Pentru un recap in termeni de Linux, click aici.
Fisierul Makefile are ca scop compilarea intregului proiect. El este auto-generat si oferit inspre utilizare, deci puteti respira usurati.
make
Aceasta regula va compila si link-edita intregul proiect. Implicit, asta inseamna generarea unui executabil si a unor fisiere obiect.
bin/realease/eStore
Asadar, dupa o compilare cu succes, noul continut al folderului radacina va fi urmatorul:
make clean
Comanda de mai sus sterge fisierele bin, build si eStore.
Folderul src (sursa) contine 2 foldere:
src/ ┣ Solution/ ┃ ┣ LRUCache/ ┃ ┃ ┣ LRUCache.cpp ┃ ┃ ┗ LRUCache.h ┃ ┣ Product/ ┃ ┃ ┣ DiscountedProduct.cpp ┃ ┃ ┣ DiscountedProduct.h ┃ ┃ ┣ FoodProduct.cpp ┃ ┃ ┣ FoodProduct.h ┃ ┃ ┣ NonFoodProduct.cpp ┃ ┃ ┣ NonFoodProduct.h ┃ ┃ ┣ Product.cpp ┃ ┃ ┣ Product.h ┃ ┃ ┣ ResealedProduct.cpp ┃ ┃ ┣ ResealedProduct.h ┃ ┃ ┣ ReturnedProduct.cpp ┃ ┃ ┗ ReturnedProduct.h ┃ ┣ Server/ ┃ ┃ ┣ Server.cpp ┃ ┃ ┗ Server.h ┃ ┣ ShoppingCart/ ┃ ┃ ┣ ShoppingCart.cpp ┃ ┃ ┗ ShoppingCart.h ┃ ┣ User/ ┃ ┃ ┣ Address.cpp ┃ ┃ ┣ Address.h ┃ ┃ ┣ BasicUser.cpp ┃ ┃ ┣ BasicUser.h ┃ ┃ ┣ PremiumUser.cpp ┃ ┃ ┣ PremiumUser.h ┃ ┃ ┣ User.cpp ┃ ┃ ┗ User.h ┃ ┣ QuerySolver.cpp ┃ ┗ QuerySolver.h ┣ utils/ ┃ ┣ objectFactory/ ~~~~~~ NU MODIFICATI ~~~~~~~ ┃ ┃ ┣ objectFactory.cpp ~~~~~~ NU MODIFICATI ~~~~~~~ ┃ ┃ ┗ objectFactory.h ~~~~~~ NU MODIFICATI ~~~~~~~ ┃ ┣ FinalQuestionsHelper.cpp ~~~~~~ NU MODIFICATI ~~~~~~~ ┃ ┣ FinalQuestionsHelper.h ~~~~~~ NU MODIFICATI ~~~~~~~ ┃ ┣ JSONSerializer.cpp ~~~~~~ NU MODIFICATI ~~~~~~~ ┃ ┣ JSONSerializer.h ~~~~~~ NU MODIFICATI ~~~~~~~ ┃ ┣ TestHelper.cpp ~~~~~~ NU MODIFICATI ~~~~~~~ ┃ ┣ TestHelper.h ~~~~~~ NU MODIFICATI ~~~~~~~ ┃ ┣ utility.cpp ┃ ┗ utility.h ┣ json.hpp ~~~~~~ NU MODIFICATI ~~~~~~~ ┗ main.cpp ~~~~~~ NU MODIFICATI ~~~~~~~
Asadar, luand in calcul mentiunile de mai sus, atentia voastra ar trebui sa fie asupra ierarhiei de fisiere din cadrul folderului Solution. Aici, fiecare clasa/ierarhie de clase se va gasi intr-un folder cu nume sugestiv.
Aceasta sectiune are ca scop formularea unor recomandari care noi credem ca va vor ajuta.
Ca punct de plecare, asigurati-va ca ati facut vazut ghidul pentru Setup Environment Teme.
Nu vrem sa va impunem un 'Tech Stack' pe care sa il folositi pentru a implementa tema - cu toate acestea, vom mentiona ce a functionat foarte bine pentru noi.
Ca idee principala, folosim:
De ce WSL2?
Pe scurt: Avem acces la comenzi Linux din Windows 10, mediu in care ne desfasuram activitatile normale. Implicit, exista integrare cu Git, Make sau g++. Mai multe detalii in ghidul de mai sus.
De ce Visual Studio Code?
Asta e o intrebare mai buna. Din urmatoarele motive:
Desigur, Visual Studio Code ramane o recomandare excelenta si pentru un Environment Linux (adica VM sau Dual Boot).
Pasii de setup ar fi (in mare) acestia:
Dupa ce efectuati tot setup-ul mentionat mai sus, o sa aiba mai mult sens si recomandarea noastra din sectiunea Non Tech, de a nu va apuca in ultima zi. Lucrurile nu sunt grele, dar necesita timp si sunt predispuse erorilor.
Pentru a putea crea și stoca pe server cele două liste neomogene, destinate Produselor și Utilizatorilor, este necesară crearea de clase pentru aceste tipuri de date. Am inclus în scheletul temei fișierele .h și .cpp primite de la superiori, în care sunt descrise și comentate semnăturile funcțiilor, pentru fiecare tip de date, pe care voi trebuie să le implementați.
De asemenea, după cum veți vedea mai târziu, fiecare utilizator va avea alocat un coș de produse. Vom intra în mai multe detalii în cadrul Cerinței 5. Până atunci, completați și metodele clasei ShoppingCart, pe baza semnăturilor și comentariilor lor.
Astfel, pornind de la diagrama UML prezentată la începutul temei și bazându-vă pe cunoștințele proprii, completați metodele ierarhiilor de clase Product și User, pentru a putea stoca mai târziu, pe server, datele necesare. În plus, completați metodelei clasei ShoppingCart.
Implementati urmatoarele metode pentru a obtine punctajul aferent:
Cerința 2 se concentrează asupra clasei Server, în care sunt stocate datele magazinului nostru online. Pe lângă metodele ce trebuie completate, considerăm că este important să înțelegeți și metodele gata implementate, pe care vi le oferim tocmai în acest scop.
După cum puteți observa și în cod, instanța respectivă este stocată într-o variabilă de tip static, iar inițializarea acesteia se face în funcția static Server* ServerInit(), care la prima apelare creează și întoarce instanța de tip Server, iar la apelările ulterioare întoarce instanța deja creată. Astfel, este asigurată unicitatea obiectului de tip Server, în tot spațiul de lucru al programului nostru.
Metodele ce trebuie completate în cadrul acestei cerințe sunt:
Deoarece in acest moment avem stocate pe server toate datele legate de produse si utilizatori, putem filtra cele doua liste pentru a gasi elemente ce ne intereseaza, in functie de valorile lor. Astfel, am gandit Cerinta 3 ca o colectie de interogari/queries, similare cu cele pe care le-am realiza intr-o Baza de Date (in contextul nostru, altă parte a echipei lucrează la partea de interfatare cu baza de date). Am incercat sa prezentam fiecare interogare intr-un contex real.
Din pacate, intr-o dimineata, George a constatat ca vechiul sau espressor s-a stricat. Pentru ca are nevoie rapid de unul nou, el a intrat pe site-ul magazinului nostru. Totusi, George are o problema. Fiind inainte de salariu, el cauta un produs redus. Astfel, cautati in lista de produse espressoarele reduse si returnati intr-o lista aceste produse.
Pentru analiza ulterioara, avem nevoie de toti utilizatorii cu un cost de transport redus. Returnati lista ce contine utilizatorii nonpremium (cei care platesc transportul) care sunt nevoiti sa plateasca un cost pentru transport ≤ 11.5 lei.
Gasiti toate produsele resigilate, cu motivul “lipsa_accesorii” . Sortati-le crescator dupa pret si returnati lista neomogena.
Vrem sa vedem ce produse alimenare se afla in magazin, grupandu-le pe cele cu acelasi nume. (ex mere din Spania si din Polonia). Mai mult, daca intalnim doua produse din aceeasi tara, vrem sa le sortam dupa pret. Astfel, sortati produsele alimentare dupa nume, tara si pret si returnati lista obtinuta.
Tot pentru analize de marketing, vrem sa vedem utilizatorii care au atat adresa de livrare, cat si cea de facturare la casa si locuiesc in judetul cu cei mai multi utilizatori. Sortati lista dupa ID-ul utilizatorilor. Refacem urmatoarele precizari:
{ "type": "nonPremium", "UserId": 1278, "firstName": "Ecaterina", "lastName": "Stefan", "email": "ecaterinastefan@gmail.com", "billingData": { "county": "Mures", "locality": "Iernut", "street": "Mihai_Viteazu", "number": 122, "block": "-", //adresa facturare la casa "apartment": 0 }, "deliveryData": { "county": "Mures", "locality": "Iernut", "street": "Mihai_Viteazu", "number": 122, "block": "-", //adresa livrare la casa "apartment": 0 }, "costTransport": 12.80 }
Deoarece cupoanele de reduceri sunt generate automat, vrem sa vedem utilizatorii premium care au cupoane de reducere pentru telefoane sau imprimante. (Re)facem urmatoarele precizari:
{ "type": "premium", "UserId": 2163, "firstName": "Magdalena", "lastName": "Apostol", "email": "magdalenaapostol@gmail.com", "billingData": { "county": "Calarasi", "locality": "Fundulea", "street": "Parcului", "number": 132, "block": "X13", "apartment": 10 }, "deliveryData": { "county": "Calarasi", "locality": "Fundulea", "street": "Parcului", "number": 132, "block": "X13", "apartment": 10 }, "premiumSubscriptionCost": 98.75, "discounts": [ //exemplu map reduceri [ 1435, 10 ], [ 3669, 8 ], [ 2497, 24 ], [ 5402, 17 ], [ 2888, 24 ] ] }
{ "type": "redus", "category": "telefon", //categoria produsului "id": 311, //3 - redus; 1 - telefon; 1- numar ordine "producer": "Samsung", "name": "Note20", "price": 5120.93, "yearsOfWarranty": 2, "discountPercentage": 14, "quantity": 3 }
Pentru a experimenta cu acest cod, click aici.
Pentru a implementa cerinta, nu este nevoie sa stiti prea multe despre scopul si functionalitatile cache-ului intr-un sistem hardware, dar aici se afla o resursa utila in caz ca sunteti curiosi si vreti sa intelegeti mai bine puterea unui cache intr-un sistem de calcul.
Presupunem ca primim un sir de numere, care pot reprezenta ID-urile unor produse accesate pe site-ul nostru.
1 2 3 2 5 3 4 5 8 9
Primim un sir de 10 numere, iar dimensiunea LRU Cache-ului nostru este de 4 elemente. Asta inseamna ca in oricare moment de timp, noi vom stoca maxim 4 elemente (ultimele accesate).
1 _ _ _ 1 2 1 _ _ 2 3 2 1 _ 3 2 3 1 _ 2 5 2 3 1 5 3 5 2 1 3 4 3 5 2 4 5 4 3 2 5 8 5 4 3 8 9 8 5 4 9
Pentru a obtine punctajul aferent Cerintei 4, implementati urmatoarele metode:
Ultimul concept pe care vrem să îl implementăm este de a da posibilitatea utilizatorilor să adauge sau să scoată produse din coșurile de cumpărături. Aceste operații sunt deservite de Server sub formă de cereri (requests) și primesc un răspuns de tip Bool, în funcție de realizarea cu succes a cererii sau nu.
O astfel de cerere are ca parametri ID-ul utilizatorului care a inițializat-o, pentru a putea accesa coșul de cumpărături corect, ID-ul produslui ce se dorește a fi adăugat în coș și cantitatea dorită din acel produs.
De asemenea, cerința reutilizează coada cu priorități creată la Cerința 4 (LRU Cache), dar voi nu trebuie să apelați efectiv acest update, el făcându-se în background (vedeți funcția TestCerinta5 din clasa TestHelper)
Metodele ce trebuie implementate fac parte din clasa Server și sunt următoarele:
bool requestAddProduct(int userID, int productID, int quantity); bool requestDeleteProduct(int userID, int productID, int quantity);
Multe metode ajutătoare au fost implementate în ierarhia de Produse și în ShoppingCart. Le puteți utiliza pentru rezolvarea cerinței. Aceste metode sunt:
Product: bool checkQuantity(int quantity); // Verifică dacă cantitatea de produs dată ca parametru este disponibilă sau nu. void decreaseQuantity(int quantity); // Crește cantitatea disponibilă a produsului void increaseQuantity(int quantity); // Scade cantitatea disponibilă a produsului ShoppingCart: int getQuantity(int id); // Întoarce cantitatea produsului cu id-ul dat ca parametru. Atenție la cazul în care produsul nu există în coș => return -1 void addProduct(int id, int quantity); // Adaugă produsul în Coș, cu cantitatea dată void raiseQuantity(int id, int quantity); // Crește cantitatea pentru produsul din Coș void lowerQuantity(int id, int quantity); // Scade cantitatea pentru produsul din Coș void deleteProduct(int id); // Sterge produsul din Coș
Vă recomandăm să urmăriți modalitatea de testare a cerinței în funcția TestCerinta5 din clasa TestHelper. De asemenea, vrem să vă oferim următoarele hint-uri legate de această cerință:
Un exemplu de funcționare este prezentat mai jos. Presupunem că avem un sigur utilizator și un singur produs pe Server:
{ "type": "nonPremium", "UserID": 13, "firstName": "Paul", "lastName": "Nastase", "email": "paulnastase@yahoo.com", "billingData": { "county": "Dambovita", "locality": "Moreni", "street": "Closca", "number": 44, "block": "VX3", "apartment": 10 }, "deliveryData": { "county": "Dambovita", "locality": "Moreni", "street": "Closca", "number": 44, "block": "VX3", "apartment": 10 }, "costTransport": 10.40 } { "type": "alimentar", "category": "condimente", "id": 1375, "name": "cimbru", "leiPerKg": 28.59, "countryOfOrigin": "China", "quantity": 6 } Coșul de produse al utilizatorului este inițializat gol. Aplicăm următoarele operații: requestAddProduct(10, 1375, 2) // Return False, deoarece Utilizatorul cu ID 10 nu există pe Server requestAddProduct(13, 2500, 2) // Return False, deoarece Produsul cu ID 2500 nu există pe Server requestAddProduct(13, 1375, -2) // Return False, deoarece quantity <= 0 requestAddProduct(13, 1375, 10) // Return False, deoarece cantitatea cerută e mai mare decât cea disponibilă (6) requestDeleteProduct(13, 1375, 10) // Return False, deoarece nu avem produsul cu ID 1375 în Coș requestDeleteProduct(13, 1375, -10) // Return False, deoarece quantity <= 0 requestAddProduct(13, 1375, 2) // Return True. Se adaugă în Coș cantitatea de 2. În lista de produse, cantitatea disponibilă scade la 4 requestAddProduct(13, 1375, 2) // Return True. Se mai adaugă cantitatea de 2, peste cea din coș. În lista de produse, cantitatea disponibilă scade la 2 requestDeleteProduct(13, 1375, 1) // Return True. Se scade cantitatea de 1 din Coș, devenind 3. Crește cantitatea disponibilă de produs la 3 requestDeleteProduct(13, 1375, 10) // Return True. Vrem să ștergem 10, dar în Coș avem doar 3. Se sterge cantitatea de 3 și se adaugă la cantitatea disponibilă, devenind 6
Pentru a intelege ce trebuie implementat, dar si felul in care lucrurile sunt testate, va trebui sa inspectati 2 entitati:
Checker-ul contine 3 foldere si script-ul de rulare. Cele 3 foldere sunt:
data contine toate informatiile ce ar putea fi procesate. Nu toate testele au nevoie de continutul 'data', dar el este pastrat acolo pentru a satisface structura checker-ului.
out contine output-ul obtinut dupa rularea functiilor implementate de voi. In esenta, folderul acesta va fi rezultatul generat de proiectul vostru.
ref contine 'raspunsul' la care ar fi trebuit sa ajungeti. Checker-ul verifica daca fisierele din 'out' se potrivesc cu cele din 'ref'. Daca da, testul va trece.
Este important sa intelegeti rolul fiecarui folder pentru a face debug. Extrem de util pentru Query-uri (Cerinta 3).
Clasa TestHelper contine o functie pentru fiecare test ce va rula. Ea este apelata din main. Puteti inspecta fiecare functie in parte (aferenta fiecarui test), pentru a intelege mai bine cum sunt implementarile voastre verificate.
Foarte util pentru teste care nu fac citiri din fisier (Cerinta 1, 4, 5).
Pentru a face debug asupra proiectului, trebuie sa puteti genera un executabil care compileaza. Odata ce l-ati generat, va puteti folosi de urmatoarea regula pentru a testa functionarea executabilului:
./eStore date.in <output_file> <numar_test_din_main>
Tema se va incarca pe Moodle, ca arhiva.
Format nume arhiva: GrupaSerie_Nume_Prenume_TemaNr.zip
Puteţi încărca mai multe soluţii, se va lua în considerare ultima solutie incarcata, termen limita 24.01.2020
Arhiva trimisă conține (direct în rădăcină):