Differences

This shows you the differences between two versions of the page.

Link to this comparison view

asc:teme:tema1 [2022/03/26 22:22]
eduard.staniloiu
asc:teme:tema1 [2024/04/06 18:12] (current)
eduard.staniloiu [Precizări încărcare]
Line 1: Line 1:
-====== Tema 1 - Marketplace ​====== +====== Tema 1 - Le Stats Sportif ​======
  
 <note important> ​   ​ <note important> ​   ​
-  * **Deadline:​** ​11 aprilie ​2021, ora 23:55. Primiți un bonus de 10% pentru trimiterea temei cu zile înaintea ​acestui termen, adică înainte de aprilie ​2021, ora 23:55. +  * **Deadline:​** ​<​del>​7 aprilie</​del>​ 14 aprilie ​2024, ora 23:55. Primiți un bonus de 10% pentru trimiterea temei cu zile înaintea ​datei de 7 aprilie, adică înainte de <​del>​5</​del>​ 10 aprilie ​2024, ora 23:55. 
-    * **Deadline hard:​** ​18 aprilie ​2021, ora 23:55. Veți primi o depunctare de 10% din punctajul maxim al temei pentru fiecare zi de întârziere,​ până la maxim 7 zile, adică până pe 18 aprilie ​2021, ora 23:55. +    ​<del>* **Deadline hard:​** ​14 aprilie ​2024, ora 23:55. Veți primi o depunctare de 10% din punctajul maxim al temei pentru fiecare zi de întârziere,​ până la maxim 7 zile, adică până pe 14 aprilie ​2024, ora 23:55.</​del>​ 
-    * **Responsabili:​** [[voichita.iancu@cs.pub.ro|Voichița Iancu]], [[eduard.staniloiu@cs.pub.ro | Eduard Stăniloiu]],​ [[giorgiana.vlasceanu@gmail.com | Giorgiana Vlăsceanu]]  +    * **Responsabili:​** [[ andreicatalin.ouatu@gmail.com | Andrei Ouatu]], [[andreitrifu.acs@gmail.com|Andrei Trifu]], [[ adumitrescu2708@stud.acs.upb.ro| Alexandra Dumitrescu]],​[[eduard.staniloiu@cs.pub.ro | Eduard Stăniloiu]], [[ radunichita99@gmail.com | Radu Nichita]], [[ioana.profeanu@gmail.com| Ioana Profeanu]], [[giorgiana.vlasceanu@gmail.com | Giorgiana Vlăsceanu]]  
-    * **Autori:** [[LucaIstrate@gmail.com|Luca Istrate]], [[adriana.draghici@cs.pub.ro|Adriana Draghici]], [[soareloredana97@gmail.com|Loredana Soare]], [[eduard.staniloiu@cs.pub.ro | Eduard Stăniloiu]]+    * **Autori:** [[eduard.staniloiu@cs.pub.ro | Eduard Stăniloiu]], [[giorgiana.vlasceanu@gmail.com | Giorgiana Vlăsceanu]]
 </​note>​ </​note>​
  
 <note tip> <note tip>
-  * Dată publicare: ​28 martie +  * Dată publicare: ​25 martie 
-  * Dată actualizare enunț28 martie+  * Actualizare deadline2 aprilie
 </​note>​ </​note>​
- 
  
 ===== Scopul temei ===== ===== Scopul temei =====
  
   * Utilizarea eficientă a elementelor de sincronizare studiate la laborator   * Utilizarea eficientă a elementelor de sincronizare studiate la laborator
-  * Implementarea unei aplicații concurente utilizând o problemă clasică (Multi Producer, Multi Consumer+  * Implementarea unei aplicații concurente utilizând o problemă clasică (client - server
-  * Aprofundarea anumitor elemente din Python (clase, elemente de sintaxă, ​thread-uri, sincronizare,​ precum și folosirea modulelor Python pentru lucrul cu thread-uri)+  * Aprofundarea anumitor elemente din Python (clase, elemente de sintaxă, ​threaduri, sincronizare,​ precum și folosirea modulelor Python pentru lucrul cu threaduri)
  
 ===== Enunț ===== ===== Enunț =====
  
-Î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.+În cadrul acestei teme veți avea de implementat un server python care va gestiona o serie de requesturi plecând de la un set de date în format ​*csv(comma separated values). 
 +Serverul va oferi statistici pe baza datelor din csv.
  
-=== Marketplace ​===+=== Setul de date ===
  
-Marketplace-ul este unul destul ​de simplucu **două tipuri de produse (ceai și cafea)** ce vor fi comercializate ​de către ​producătoriAcesta va fi intermediarul dintre producători și consumatori,​ prin el realizându-se achiziția de produse: ​ +[[https://​catalog.data.gov/​dataset/​nutrition-physical-activity-and-obesity-behavioral-risk-factor-surveillance-system|Setul ​de date]] conține informații despre nutrițieactivitatea fizică și obezitate în Statele Unite ale Americii în perioada 2011 - 2022. 
-producătorul ​(producerva produce o anumită cantitate de produse de un anumit tip / mai multe tipuri +Datele au fost colectate ​de către ​U.S. Department of Health & Human Services
-cumpă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 ​fi cumpărate).+Informațiile sunt colectate per stat american ​(ex. California, Utah, New Yorkși spund următorului **set de întrebări**
 +  * '​Percent of adults who engage in no leisure-time physical activity'​ 
 +  * '​Percent of adults aged 18 years and older who have obesity'​ 
 +  * '​Percent of adults aged 18 years and older who have an overweight classification'​ 
 +  * '​Percent of adults who achieve at least 300 minutes a week of moderate-intensity aerobic physical activity or 150 minutes a week of vigorous-intensity aerobic activity ​(or an equivalent combination)
 +  ​'​Percent of adults who achieve at least 150 minutes a week of moderate-intensity aerobic physical activity or 75 minutes a week of vigorous-intensity aerobic physical activity and engage in muscle-strengthening activities on 2 or more days a week'​ 
 +  ​'​Percent of adults who achieve at least 150 minutes ​week of moderate-intensity aerobic physical activity or 75 minutes a week of vigorous-intensity aerobic activity (or an equivalent combination)
 +  * '​Percent of adults who engage in muscle-strengthening activities on 2 or more days a week'​ 
 +  * '​Percent of adults who report consuming fruit less than one time daily'​ 
 +  * '​Percent of adults who report consuming vegetables less than one time daily'
  
-=== Producător ===+Valorile pe care le veți folosi în calculul diverselor statistici la care răspunde aplicația voastră se găsesc în coloana **Data_Value**.
  
-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.+===== Detalii ​de implementare =====
  
-=== Consumator ===+Aplicația server pe care o dezvoltați este una multi-threaded. 
 +Atunci când serverul este pornit, trebuie să încărcați fișierul csv și să extrageți informațiile din el a.î. să puteți calcula statisticile cerute la nivel de request.
  
-În momentul în care un client își dorește să cumpere anumite produse dintr-un magazinacesta 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ăturicăruia îi va fi asociat un //id//. Clientul poate: +Întrucât procesarea datelor din csv poate dura mai mult timpmodelul implementat ​de către server va fi următorul: 
-  * adăuga produse în coș => produsele respective devin indisponibile pentru ceilalțclienți + * un endpoit (ex. '/​api/​states_mean'​) ​care primește requestul ​și va întoarce clientului ​un **job_id** (ex. "​job_id_1"​"​job_id_2",​ ..., "​job_id_n"​) 
-  * șterge produse din coș => produsele respective devin disponibile pentru ceilalți clienți + * endpointul '/api/get_results/job_id'​ care va verifica dacă job_id-ul este valid, rezultatul calculului este gata sau nu și va returna un răspuns corespunzător (detalii mai jos)
-  * plasa o comandă+
  
-===== Descrierea implementării =====+=== Mecanica unui request ​===
  
 +Asociază un job_id requestului,​ pune jobul (closure care încalsulează unitatea de lucru) într-o coadă de joburi care este procesată de către un **Thread pool**, incrementează job_id-ul intern și returnează clientului job_id-ul asociat.
  
-Marketplace-ul ce va trebui implementat ​va simula problema **Multi Producer Multi Consumer ​(MPMC)**. +Un thread ​va prelua un job din coada de joburi, ​va efectua operația asociată ​(ceea ce a fost capturat de către closure) ​și va scrie rezultatul calculului într-un fișier ​cu numele job_id-ului în directorul **results/​**.
-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 șde cumpărător în clasele aferente ale acestora.+=== Requesturile ​pe care trebuie să le implementațsunt ===
  
-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//​.+== /api/states_mean ==
  
-Vor exista doua tipuri de operații pe care clientul le poate efectua asupra coșului de cumpărături: +Primește o întrebare (din **setul ​de întrebări** de mai sus) și calculează media valorilor înregistrate (**Data_Value**) ​din intervalul total de timp (2011 - 2022) pentru fiecare stat, și sortează crescător după medie.
-  ​''​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). +== /​api/​state_mean ==
-Î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ă+Primește o întrebare (din **setul de întrebări** de mai sus) și un stat, și calculează media valorilor înregistrate (**Data_Value**) din intervalul total de timp (2011 - 2022).
-  ​furnizeze produselor pe care producătorul le pune la dispoziție+
  
 +== /api/best5 ==
  
-<note important>''​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]''​.</​note> ​+Primește o întrebare (din **setul ​de întrebări** de mai sus) și calculează media valorilor înregistrate (**Data_Value**) ​din intervalul total de timp (2011 2022) și întoarce primele 5 state.
  
 +== /api/worst5 ==
  
-Funcționalitatea clasei ''​Consumer''​ este să: +Primește o întrebare (din **setul de întrebări** de mai sus) și calculează media valorilor înregistrate (**Data_Value**) ​din intervalul total de timp (2011 - 2022) șîntoarce ultimele 5 state.
-  ​primească id-ului coșului ​de cumpărături +
-  ​adauge / elimine ​din coșul ​de cumpărături anumite cantitățde produse +
-  * plaseze comenzi+
  
-Modulul **Product** conține reprezentările claselor **Coffee** și **Tea**.+<note tip> 
 +În funcție de întrebare, primele state pot să aibă fie cel mai mic sau cel mai mare scor. 
 +De exemplu, pentru întrebarea:​ "​Percent of adults who engage in no leisure-time physical activity",​ primele state (best) vor avea scorurile cele mai mici, iar worst vor avea scorurile cele mai mari. 
 +Pentru întrebarea:​ "​Percent of adults who engage in muscle-strengthening activities on 2 or more days a week", primele state (best) vor avea scorurile cele mai mari, iar worst vor avea scorurile cele mai mici. 
 +</​note>​
  
-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.+== /​api/​global_mean == 
  
-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.+Primește o întrebare (din **setul de întrebări** de mai sus) și calculează media valorilor înregistrate (**Data_Value**) din intervalul total de timp (2011 - 2022) din întregul set de date.
  
-<note important>Se consideră timp de așteptare ​după: +== /​api/​diff_from_mean == 
-  ​* adăugarea unui produs + 
-  * semnalizarea că nu se găsește un produs +Primește o întrebare (din **setul de întrebări** de mai sus) și calculează diferența dintre global_mean și state_mean pentru toate statele. 
-  * semnalizarea faptul ​că este plină coada asociată producătorului + 
-</note>+== /​api/​state_diff_from_mean == 
 + 
 +Primește o întrebare (din **setul de întrebări** de mai sus) și un stat, și calculează diferența dintre global_mean și state_mean pentru statul respectiv. 
 + 
 +== /​api/​mean_by_category == 
 + 
 +Primește o întrebare (din **setul de întrebări** de mai sus) și calculează valoarea medie pentru fiecare segment (**Stratification1**) din categoriile (**StratificationCategory1**) fiecărui stat. 
 + 
 +== /​api/​state_mean_by_category == 
 + 
 +Primește o întrebare (din **setul de întrebări** de mai sus) și un stat, și calculează valoarea medie pentru fiecare segment (**Stratification1**) din categoriile (**StratificationCategory1**). 
 + 
 +== /​api/​graceful_shutdown == 
 + 
 +Răspunde la un apel de tipul GET și va duce la notificarea Thread Poolului despre încheierea procesării. 
 +Scopul acesteia este de a închide aplicația într-un mod graceful: nu se mai acceptă requesturi noi, se termină de procesat requesturile înregistrate până în acel moment (drain mode) și apoi aplicația poate fi oprită. 
 + 
 +== /api/jobs == 
 + 
 +Răspunde la un apel de tipul GET cu un JSON care conține toate JOB_ID-urile de până la acel moment și statusul lor. 
 +De exemplu: 
 +<code> 
 +
 +  "​status":​ "​done"​ 
 +  "​data":​ [ 
 +    { "​job_id_1":​ "​done"​},​ 
 +    { "​job_id_2":​ "​running"​},​ 
 +    { "​job_id_3":​ "​running"​} 
 +  ] 
 +
 +</​code>​ 
 + 
 +== /​api/​num_jobs ==  
 + 
 +Răspunde la un apel de tipul GET cu numărul joburilor rămase de procesat. 
 +După un /​api/​graceful_shutdown și o perioadă de timp, aceasta ar trebui să întoarcă valoarea 0, semnalând astfel că serverul flask poate fi oprit. 
 + 
 +== /​api/​get_results/<​job_id>​ == 
 + 
 +Răspunde la un apel de tipul GET (job_id-ul este parte din URL). 
 +Acesta verifică dacă job_id-ul primit este valid și răspunde cu un JSON corespunzător, ​după cum urmează: 
 + 
 +1. JOB_ID-ul este invalid 
 +<​code>​ 
 +{ 
 +  ​"​status":​ "​error",​ 
 +  "​reason":​ "​Invalid job_id"​ 
 +
 +</​code>​ 
 + 
 +2. JOB_ID-ul este valid, dar rezultatul procesării nu este gata 
 +<​code>​ 
 +{ 
 +  ​"​status":​ "​running",​ 
 +
 +</​code>​ 
 + 
 +3. JOB_ID-ul este valid și rezultatul procesării este gata 
 +<​code>​ 
 +
 +  "​status":​ "​done",​ 
 +  "​data":​ <​JSON_REZULTAT_PROCESARE>​ 
 +
 +</​code>​ 
 + 
 +=== Server === 
 + 
 +Implementarea serverului se face folosind framework-ul ​**flask** și va extinde scheletul de cod oferit. 
 +Mai multe detalii despre Flask găsiți mai jos. 
 +Deasemeni, un tutorial extensiv (pe care vi-l recomandăm) este [[https://​blog.miguelgrinberg.com/​post/​the-flask-mega-tutorial-part-i-hello-world|The flask mega tutorial]]. 
 + 
 +Python Flask este un micro-framework web open-source care permite dezvoltatorilor să creeze aplicații web ușor și rapid, folosind limbajul de programare Python. 
 +Flask este minimalist și flexibil, oferind un set de instrumente de bază pentru crearea unei aplicații web, cum ar fi rutele URL, gestionarea cererilor și a sesiunilor, șablonarea și gestionarea cookie-urilor. 
 +Cu Flask, dezvoltatorii pot construi rapid API-uri sau aplicații web de dimensiuni mici și medii. 
 + 
 +== Instalare și activarea mediului de lucru == 
 + 
 +Pentru a instala Flask, creați-vă un mediu virtual (pentru a nu instala pachete global, pe sistem) folosind comanda 
 +<​code>​ 
 +$ python -m venv venv 
 +</​code>​ 
 + 
 +Activați mediul virtual 
 +<​code>​ 
 +$ source venv/​bin/​activate 
 +</​code>​ 
 + 
 +Și instalați pachetele din fișierul **requirements.txt** 
 +<​code>​ 
 +$ python -m pip install -r requirements.txt 
 +</​code>​ 
 + 
 +Pașii de creare a mediului virtual și de instalare a pachetelor ​se regăsesc în fișierul Makefile. 
 +Astfel, pentru a vă crea spațiul de lucru, rulați următoarele comenzi în interpretorul vostru de comenzi (verificat în ''​bash''​ și ''​zsh''​) 
 +<​code>​ 
 +make create_venv 
 +source venv/​bin/​activate 
 +make install 
 +</​code>​ 
 + 
 +== Quickstart == 
 + 
 +O rută în cadrul unei aplicații web, cum ar fi în Flask, reprezintă un URL (Uniform Resource Locator) specific către care aplicația web va răspunde cu un anumit conținut sau funcționalitate. 
 +Atunci când un client (de obicei un browser web) face o cerere către serverul web care zduiește aplicația Flask, ruta determină ce cod va fi executat și ce răspuns va fi returnat clientului. 
 +În Flask, rutele sunt definite folosind decoratori care leagă funcții Python de URL-uri specifice, permitând astfel aplicației să răspundă în mod dinamic la cereri (requesturi). 
 + 
 +În Flask, puteți defini o rută care răspunde la un apel de tip **GET** folosind decoratorul **@app.route()** și specificând metoda *HTTP* (**methods=['​GET'​]**). 
 +Pentru a răspunde la un apel de tipul **POST** (apel folosit pentru a trimite date de către un client către server) folosim același decorator și specificăm **methods=['​POST'​]**. 
 +De exemplu: 
 + 
 +<​code>​ 
 +from flask import request 
 + 
 +@app.route('/',​ methods=['​GET'​]) 
 +def index(): 
 +    return '​Aceasta este o rută care răspunde la un apel de tip GET' 
 + 
 +@app.route('/​post',​ methods=['​POST'​]) 
 +def post_route():​ 
 +    data = request.json ​ # Se obțin datele JSON trimise prin POST 
 +    return '​Aceasta este o rută care răspunde la un apel de tip POST'​ 
 +</​code>​ 
 + 
 +În cazul API-urilor este un best practice ca datele returnate să fie în format JSON, pentru a fi ușor de prelucrat de către alte servicii în mod programatic. 
 +Pentru a returna un obiect JSON în Flask, vom folosi helperul ​**jsonify()** ca în exemplul de mai jos: 
 + 
 +<​code>​ 
 +from flask import request, jsonify 
 + 
 +@webserver.route('/​api/​post_endpoint',​ methods=['​POST'​]) 
 +def post_endpoint():​ 
 +    if request.method == '​POST':​ 
 +        # Presupunem ​că metoda conține date JSON 
 +        data = request.json 
 +        print(f"​got data in post {data}"​) 
 +         
 +        # Procesăm datele primite 
 +        # Pentru exemplu, vom returna datele primite 
 +        response = {"​message":​ "​Received data successfully",​ "​data":​ data} 
 +        return jsonify(response) 
 +    else: 
 +        # Nu acceptăm o altă metodă 
 +        return jsonify({"​error":​ "​Method not allowed"​}),​ 405 
 +</​code>​ 
 + 
 +=== Structura input-ului și a output-ului === 
 + 
 +Interacțiunea cu serverul se va face pe bază de mesaje JSON, după cum este descris mai jos. 
 +Vă recomandăm să vă uitați în suita de teste, în directoarele input și output pentru a vedea informațiile mult mai detaliat. 
 + 
 +== Input == 
 + 
 +Un input pentru un request care primește doar o întrebare în următorul format: 
 +<​code>​ 
 +
 +  "​question":​ "​Percent of adults aged 18 years and older who have an overweight classification"​ 
 +} 
 +</code> 
 + 
 +Unul care așteaptă o întrebare și un stat are următorul format: 
 +<​code>​ 
 +
 +  "​question":​ "​Percent of adults who engage in no leisure-time physical activity",​ 
 +  "​state":​ "South Carolina"​ 
 +
 +</​code>​ 
 + 
 +== Output == 
 + 
 +Un răspuns JSON va avea mereu structura:​ 
 +<​code>​ 
 +
 +  "​status":​ "​done",​ 
 +  "​data":​ <​JSON_REZULTAT_PROCESARE>​ 
 +
 +</​code>​ 
 + 
 +**JSON_REZULTAT_PROCESARE** este un obiect JSON așa cum se regăsește în directorul output, pentru fiecare endpoint din directorul tests.
  
 ===== Testare ===== ===== Testare =====
  
-Testarea se va realiza folosind atât ''​unittest''​e, cât și teste funcționale.+Testarea se va realiza folosind atât unitteste, cât și teste funcționale. 
 + 
 +==== Rularea testelor ==== 
 + 
 +Pentru a rula testele, folosiți fișierul ''​Makefile''​. 
 +Într-un shell 1) activați mediul virtual și 2) porniți serverul 
 +<​code>​ 
 +source venv/​bin/​activate 
 +make run_server 
 +</​code>​ 
 + 
 +Într-un alt shell 1) activați mediul virtual și 2) porniți checkerul 
 +<​code>​ 
 +source venv/​bin/​activate 
 +make run_tests 
 +</​code>​ 
 + 
 +<note important>​ 
 +Trebuie să vă asigurați că ați activat mediul virtual înainte de a rula comenzile din make. 
 +<​code>​ 
 +source venv/​bin/​activate 
 +</​code>​ 
 + 
 +Dacă nu ați activat mediul virtual, ''​make''​ vă va arunca următoarea eroare (linia, ex 8, poate să difere). 
 +<​code>​ 
 +Makefile:8: *** "You must activate your virtual environment. Exiting..."​. ​ Stop. 
 +</​code>​ 
 + 
 +</​note>​
  
 ==== Unittesting ==== ==== Unittesting ====
  
-Pentru testarea funcțiilor din ''​Marketplace'' ​veți folosi modulul de [[https://​docs.python.org/​3/​library/​unittest.html | unittesting]] al limbajului Python.+Pentru testarea funcțiilor din **server** ​veți folosi modulul de [[https://​docs.python.org/​3/​library/​unittest.html | unittesting]] al limbajului Python.
  
 <spoiler Click pentru sumar despre unittesting>​ <spoiler Click pentru sumar despre unittesting>​
Line 114: Line 325:
 </​spoiler>​ </​spoiler>​
  
-Pentru a testa comportamentul ​clasei ''​Marketplace'' ​definiți în fișierul ''​marketplace.py''​ o clasă de testare numită ''​TestMarketplace''​. +Pentru a testa comportamentul definiți în fișierul ''​unittests/​TestWebserver.py''​ o clasă de testare numită ''​TestWebserver''​. 
-Clasa ''​TestMarketplace''​ va testa funcționalitatea tuturor ​metodelor ​definite de ''​Marketplace'':​ ''​register_producer'',​ ''​publish'',​ ''​new_cart'',​ ''​add_to_cart'',​ ''​remove_from_cart'',​ ''​place_order''​.+Clasa ''​TestWebserver''​ va testa funcționalitatea tuturor ​rutelor ​definite de voi.
 Dacă definiți alte metode, va trebui să adăugați teste și pentru acestea. Dacă definiți alte metode, va trebui să adăugați teste și pentru acestea.
  
-Vă recomandăm să folosiți metoda [[https://​docs.python.org/​3/​library/​unittest.html#​unittest.TestCase.setUp | setUp]] pentru a inițializa o instanță a clasei testate ​(''​Marketplace''​) ​și orice altceva ce vă ajută în testarea codului.+Vă recomandăm să folosiți metoda [[https://​docs.python.org/​3/​library/​unittest.html#​unittest.TestCase.setUp | setUp]] pentru a inițializa o instanță a clasei testate și orice altceva ce vă ajută în testarea codului.
 Un exemplu de utilizare a metodei ''​setUp''​ este disponibil în [[https://​docs.python.org/​3/​library/​unittest.html#​organizing-test-code | documentație]]. Un exemplu de utilizare a metodei ''​setUp''​ este disponibil în [[https://​docs.python.org/​3/​library/​unittest.html#​organizing-test-code | documentație]].
- 
- 
-==== Testarea Funcțională și Formatul Testelor ==== 
- 
-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: 
-  * marketplace 
-  * products 
-  * producers 
-  * consumers 
- 
-Exemplu conținut fișier de intrare și fișierul corespunzător de ieșire: 
-<spoiler Click pentru exemplu> 
-<code json> 
-{ 
-   "​products":​ { 
-       "​id1":​ { 
-           "​product_type":​ "​Coffee",​ 
-           "​name":​ "​Arabica",​ 
-           "​price":​ 10, 
-           "​acidity":​ 5.1, 
-           "​roast_level":​ "​medium"​ 
-       }, 
-       "​id2":​ { 
-           "​product_type":​ "​Tea",​ 
-           "​name":​ "Earl Grey", 
-           "​price":​ 10, 
-           "​type":​ "​Green"​ 
-       } 
-   }, 
-   "​consumers":​ [ 
-       { 
-           "​name":​ "​cons1",​ 
-           "​retry_wait_time":​ 0.1, 
-           "​carts":​ [ 
-               [ 
-                   { "​type":​ "​add",​ "​prod":​ "​id1",​ "​qty":​ 2 }, 
-                   { "​type":​ "​remove",​ "​prod":​ "​id1",​ "​qty":​ 1 } 
-               ], 
-               [ 
-                   { "​type":​ "​add",​ "​prod":​ "​id2",​ "​qty":​ 3 } 
-               ] 
-           ] 
-       } 
-   ], 
-   "​producers":​ [ 
-       { 
-           "​name":​ "​prod1",​ 
-           "​products":​ [ 
-               [ "​id1",​ 1, 0.1 ], 
-               [ "​id2",​ 1, 0.1 ] 
-           ], 
-           "​republish_wait_time":​ 0.2 
-       }, 
-       { 
-           "​name":​ "​prod2",​ 
-           "​products":​ [ 
-               [ "​id2",​ 1, 0.2 ] 
-           ], 
-           "​republish_wait_time":​ 0.2 
-       } 
-   ], 
-   "​marketplace":​ { 
-       "​queue_size":​ 8 
-   } 
-} 
-</​code>​ 
-  
-Conținut fișier de ieșire: 
- 
-<​code>​ 
-cons1 bought Coffee(name='​Arabica',​ price=10, acidity=5.1,​ roast_level='​medium'​) 
-cons1 bought Tea(name='​Earl Grey', price=10, type='​Black'​) 
-cons1 bought Tea(name='​Earl Grey', price=10, type='​Black'​) 
-cons1 bought Tea(name='​Earl Grey', price=10, type='​Black'​) 
-</​code>​ 
- 
-</​spoiler>​ 
- 
-<note warning>​Atât conținutul fișierului de intrare, cât și conținutul fișierului de ieșire sunt descrise în [[https://​gitlab.cs.pub.ro/​asc/​asc-public/​-/​blob/​master/​assignments/​1-marketplace/​skel/​test-gen/​README_TESTS.md| README]] </​note>​ 
- 
-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. 
  
 ===== Logging ===== ===== Logging =====
Line 208: Line 336:
 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. 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 [[https://​docs.python.org/​3/​library/​logging.html | logging]], trebuie să implementați un fișier de log, numit "marketplace.log", în care veți urmări comportamentul ​clasei ''​Marketplace''​.+Folosind modulul de [[https://​docs.python.org/​3/​library/​logging.html | logging]], trebuie să implementați un fișier de log, numit "webserver.log", în care veți urmări comportamentul ​serverului.
  
-Î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.+În fișierul de log veți nota, folosind nivelul ''​info()'',​ toate intrările și ieșirile în/​din ​rutele implementate. 
 +Î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 [[https://​docs.python.org/​3/​library/​logging.handlers.html#​logging.handlers.RotatingFileHandler | 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"​. Fișierul va fi implementat folosind [[https://​docs.python.org/​3/​library/​logging.handlers.html#​logging.handlers.RotatingFileHandler | 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"​.
  
Line 220: Line 349:
 O descriere completă a cum puteți utiliza modului de logging este prezentă în categoria [[https://​docs.python.org/​3/​howto/​logging.html | HOWTO]] a documentației. O descriere completă a cum puteți utiliza modului de logging este prezentă în categoria [[https://​docs.python.org/​3/​howto/​logging.html | HOWTO]] a documentației.
  
-===== Precizări încărcare ​/ VMChecker ​=====+===== Precizări încărcare ===== 
 + 
 +Arhiva temei va fi încărcată pe [[https://​curs.upb.ro/​2023/​mod/​assign/​view.php?​id=157094|moodle]]
  
-Arhiva temei va fi încărcată pe [[https://​vmchecker.cs.pub.ro/​ui/#​ASC|vmchecker]]. 
 /* Arhiva temei (fişier .zip) va fi uploadată pe site-ul cursului şi trebuie să conţină: */ /* Arhiva temei (fişier .zip) va fi uploadată pe site-ul cursului şi trebuie să conţină: */
  
-Arhiva trebuie să conțină:​ +Arhiva ​(fişier .zip) trebuie să conțină:​ 
-  * director ''​tema''​ cu fișierele temei: ''​marketplace.py'',​ ''​producer.py'',​ ''​consumer.py''​ +  * fișierele temei și alte fișiere ''​.py''​ folosite în dezvoltare ​()
-  * alte fișiere ''​.py''​ folosite în dezvoltare+
   * ''​README''​   * ''​README''​
-  * director .git +  * (opțional) fișierul ''​git-log''​ (Îl obțineți rulând comanda ''​git log > git-log''​) 
-<note tip>​Pentru a documenta realizarea temei, vă recomandăm să folosiți template-ul de [[https://gitlab.cs.pub.ro/asc/asc-public/-/blob/​master/​assignments/​README.example.md|aici]]+  * un exemplu ​de conținut al arhivei este mai jos 
 +    <​code>​ 
 +    api_server.py 
 +    app/ 
 +    app/routes.py 
 +    app/​task_runner.py 
 +    app/​data_ingestor.py 
 +    app/__init__.py 
 +    README 
 +    unittests/ 
 +    unittests/mytests.py 
 +    git-log 
 +    </code> ​    
 + 
 +<​note>​ 
 +Repository-ul pe care îl folosiți în procesul de implementare este necesar să fie privat.
 </​note>​ </​note>​
 +
 +<note tip>
 +Pentru a documenta realizarea temei, vă recomandăm să folosiți template-ul de [[https://​gitlab.cs.pub.ro/​asc/​asc-public/​-/​blob/​master/​assignments/​README.example.md|aici]]
 +</​note>​
 +
  
 ===== Punctare ===== ===== Punctare =====
Line 260: Line 409:
 <note warning> <note warning>
 Temele vor fi testate împotriva plagiatului. Orice tentativă de copiere va fi depunctată conform [[asc:​regulament|regulamentului]]. Temele vor fi testate împotriva plagiatului. Orice tentativă de copiere va fi depunctată conform [[asc:​regulament|regulamentului]].
 +Rezultatele notării automate este orientativă și poate fi afectată de corectarea manuală.
 </​note>​ </​note>​
  
Line 269: Line 419:
  
 Vom face depunctări de până la -5pct dacă verificarea făcută cu pylint vă dă un scor mai mic de 8. Vom face depunctări de până la -5pct dacă verificarea făcută cu pylint vă dă un scor mai mic de 8.
- 
  
 ==== Observații ==== ==== Observații ====
Line 278: Line 427:
   * Bug-urile de sincronizare,​ prin natura lor sunt nedeterministe;​ o temă care conţine astfel de bug-uri poate obţine punctaje diferite la rulări succesive; în acest caz punctajul temei va fi cel dat de tester în momentul corectării   * Bug-urile de sincronizare,​ prin natura lor sunt nedeterministe;​ o temă care conţine astfel de bug-uri poate obţine punctaje diferite la rulări succesive; în acest caz punctajul temei va fi cel dat de tester în momentul corectării
   * Recomandăm testarea temei în cât mai multe situații de load al sistemului și pe cât mai multe sisteme pentru a descoperi bug-urile de sincronizare   * Recomandăm testarea temei în cât mai multe situații de load al sistemului și pe cât mai multe sisteme pentru a descoperi bug-urile de sincronizare
- 
  
 ===== Resurse necesare realizării temei ===== ===== Resurse necesare realizării temei =====
Line 287: Line 435:
 student@asc:​~$ git clone https://​gitlab.cs.pub.ro/​asc/​asc-public.git student@asc:​~$ git clone https://​gitlab.cs.pub.ro/​asc/​asc-public.git
 student@asc:​~$ cd asc/​assignments student@asc:​~$ cd asc/​assignments
-student@asc:​~/​assignments$ cd 1-marketplace+student@asc:​~/​assignments$ cd 1-le_stats_sportif
 </​code>​ </​code>​
 +
  
 ===== Suport, întrebări și clarificări ===== ===== Suport, întrebări și clarificări =====
  
-Pentru întrebări sau nelămuriri legate de temă folosiți [[https://​curs.upb.ro/​2021/​mod/​forum/​view.php?​id=182065|forumul temei]]. ​+Pentru întrebări sau nelămuriri legate de temă folosiți [[https://​curs.upb.ro/​2023/​mod/​forum/​view.php?​id=148546|forumul temei]]. ​
  
 <note important>​ <note important>​
Line 300: Line 449:
  
 </​note>​ </​note>​
- 
- 
  
asc/teme/tema1.1648326135.txt.gz · Last modified: 2022/03/26 22:22 by eduard.staniloiu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0