21.04.2022: Am adăugat o clarificare legata de existența directorului .git în arhiva, aceasta este opțională
În cadrul acestei teme veți avea de implementat un Marketplace prin intermediul căruia mai mulți producători își vor oferi produsele spre vânzare, iar mai mulți cumpărători vor achiziționa produsele puse la dispoziție.
Marketplace-ul este unul destul de simplu, cu două tipuri de produse (ceai și cafea) ce vor fi comercializate de către producători. Acesta va fi intermediarul dintre producători și consumatori, prin el realizându-se achiziția de produse: producătorul (producer) va produce o anumită cantitate de produse de un anumit tip / mai multe tipuri cumpărătorul (consumer) va cumpăra o anumită cantitate de produse de un tip / de mai multe tipuri. De asemenea, Marketplace-ul va pune la dispoziția fiecărui cumpărător câte un coș de produse (cart) (acesta va fi folosit pentru rezervarea produselor care se doresc a fi cumpărate).
Vor exista mai mulți producători ce vor produce obiectele de tip cafea / ceai. Fiecare produs va fi furnizat într-o anumită cantitate. Un producător poate produce atât obiecte de tip cafea, cât și de tip ceai.
În momentul în care un client își dorește să cumpere anumite produse dintr-un magazin, acesta va avea nevoie de un coș de cumpărături pe care să îl folosească în scopul rezervării acestora. Astfel, de fiecare dată când un client își începe cumpărăturile, acesta va primi din partea Marketplace-ului un coș de cumpărături, căruia îi va fi asociat un id. Clientul poate:
Marketplace-ul ce va trebui implementat va simula problema Multi Producer Multi Consumer (MPMC).
Pentru rezolvarea acestei teme va trebui să completați clasele Marketplace, Producer
, și Consumer
cu o implementare corectă a metodelor deja definite.
Rezolvarea temei va fi concentrată preponderent pe metodele clasei Marketplace, metode ce vor fi apelate atât de producător, cât și de cumpărător în clasele aferente ale acestora.
Operația efectuată de către producător este cea de publicare a produselor sale. Implementarea metodei publish
va fi făcută în clasa Marketplace.
Vor exista doua tipuri de operații pe care clientul le poate efectua asupra coșului de cumpărături:
add_to_cart
⇒ adaugă un produs în coșremove_from_cart
⇒ șterge un produs din coș
Ambele metode (add_to_cart
și remove_from_cart
) vor trebui implementate în clasa Marketplace.
În momentul în care un consumator adaugă un produs în coșul pentru cumpărături, produsul respectiv va deveni indisponibil pentru ceilalți clienți ai Marketplace-ului. Clientul își va putea plasa comanda prin apelarea metodei place_order
(din clasa Marketplace).
În cazul în care un produs este eliminat din coșul pentru cumpărături, acesta devine disponibil pentru ceilalți clienți ai Marketplace-ului.
Funcționalitatea clasei Producer
este să:
Producer
produce secvențial numărul de produse și tipul din cadrul fișierului de intrare și așteaptă după realizarea fiecărui produs un număr de secunde specificat. Informațiile se preiau din fișierul de intrare și are următorul format pentru produse[“id”, cantitate, timp-așteptare]
.
Funcționalitatea clasei Consumer
este să:
Modulul Product conține reprezentările claselor Coffee și Tea.
Marketplace-ul limitează numărul de produse ce pot fi publicate de către un producător. În momentul în care s-a atins limita, producătorul nu mai poate publica altele până nu sunt cumpărate. El va reîncerca să publice după un timp definit în fișierul de test.
Dacă un cumpărător nu găsește un produs în marketplace, el va încerca mai târziu, după un timp definit în fișierul de test.
Testarea se va realiza folosind atât unittest
e, cât și teste funcționale.
Pentru testarea funcțiilor din Marketplace
veți folosi modulul de unittesting al limbajului Python.
Pentru a testa comportamentul clasei Marketplace
definiți în fișierul marketplace.py
o clasă de testare numită TestMarketplace
.
Clasa TestMarketplace
va testa funcționalitatea tuturor metodelor definite de Marketplace
: register_producer
, publish
, new_cart
, add_to_cart
, remove_from_cart
, place_order
.
Dacă definiți alte metode, va trebui să adăugați teste și pentru acestea.
Vă recomandăm să folosiți metoda setUp pentru a inițializa o instanță a clasei testate (Marketplace
) și orice altceva ce vă ajută în testarea codului.
Un exemplu de utilizare a metodei setUp
este disponibil în documentație.
Testarea se va face cu ajutorul a două tipuri de fișiere, cele de input și cele de output ({id}.in și {id}.out), primul fiind în format JSON. Fișierul {id}.in va reprezenta fișierul de intrare și va conține configurările necesare pentru fiecare clasă în parte, iar fișierul {id}.out va reprezenta fișierul de ieșire prin intermediul căruia se va verifica corectitudinea implementării temei.
Fișierele de input vor fi fișiere JSON ce vor conține următoarele chei:
Exemplu conținut fișier de intrare și fișierul corespunzător de ieșire:
Pentru a putea compara fișierele de ieșire obținute de voi cu cele de referința, scriptul de testare va ordona output-ul rezultat, întrucât avem de-a face cu multithreading.
Vrem să utilizăm fișiere de logging în aplicațiile pe care le dezvoltăm pentru a putea urmări flowul acestora a.î. să ne ajute în procesul de debug.
Folosind modulul de logging, trebuie să implementați un fișier de log, numit “marketplace.log”, în care veți urmări comportamentul clasei Marketplace
.
În fișierul de log veți nota, folosind nivelul info()
, toate intrările și ieșirile în/din metodele clasei Marketplace
. În cazul metodelor care au parametrii de intrare, informația afișată la intrarea în funcție va afișa și valorile parametrilor.
Fișierul va fi implementat folosind RotatingFileHandler: astfel se poate specifica o dimensiune maximă a fișierului de log și un număr maxim de copii istorice. RotatingFileHandler ne permite să ținem un istoric al logurilor, fișierele fiind stocate sub forma “file.log”, “file.log.1”, “file.log.2”, … “file.log.max”.
Vă încurajăm să folosiți fișierul de log și pentru a înregistra erori detectate.
În mod implicit, timestamp-ul logurilor folosește timpul mașinii pe care rulează aplicația (local time). Acest lucru nu este de dorit în practică deoarece nu putem compara loguri de pe mașini aflate în zone geografice diferite. Din acest motiv, timestampul este ținut în format UTC/GMT. Asigurați-vă că folosiți gmtime, și nu localtime. Pentru aceasta trebuie să folosiți metoda formatTime.
O descriere completă a cum puteți utiliza modului de logging este prezentă în categoria HOWTO a documentației.
Arhiva temei va fi încărcată pe moodle
Arhiva trebuie să conțină:
marketplace.py
, producer.py
, consumer.py
.py
folosite în dezvoltareREADME
.git
redenumit în git
pentru a permite verificarea automată a temei
tests
.
Tema se va implementa Python>=3.7.
Notarea va consta în 80 pct acordate egale între testele funcționale, 10 pct acordate pentru unitteste și 10 pct acordate pentru fișierul de logging. Depunctări posibile sunt:
Se acordă bonus 5 pct pentru adăugarea directorului .git
și utilizarea versionării în cadrul repository-ului.
Vom testa sursele voastre cu pylint configurat conform fișierului pylintrc
din cadrul repo-ului dedicat temei. Atenție, rulăm pylint doar pe modulele completate și adăugate de voi, nu și pe cele ale testerului.
Deoarece apar diferențe de scor între versiuni diferite de pylint, vom testa temele doar cu ultima versiune. Vă recomandăm să o folosiți și voi tot pe aceasta.
Vom face depunctări de până la -5pct dacă verificarea făcută cu pylint vă dă un scor mai mic de 8.
Pentru a clona repo-ul și a accesa resursele temei 1:
student@asc:~$ git clone https://gitlab.cs.pub.ro/asc/asc-public.git student@asc:~$ cd asc/assignments student@asc:~/assignments$ cd 1-marketplace
Pentru întrebări sau nelămuriri legate de temă folosiți forumul temei.
ATENȚIE să nu postați imagini cu părți din soluția voastră pe forumul pus la dispoziție sau orice alt canal public de comunicație. Dacă veți face acest lucru, vă asumați răspunderea dacă veți primi copiat pe temă.