Differences
This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
|
pp:2026:scala:t01 [2026/03/16 16:42] ana.ailiesei |
pp:2026:scala:t01 [2026/03/25 19:19] (current) ldaniel typo |
||
|---|---|---|---|
| Line 1: | Line 1: | ||
| ===== Tema 1 PP – Casa de marcat ===== | ===== Tema 1 PP – Casa de marcat ===== | ||
| - | Publicare: ''?? martie 2026''\\ | + | Publicare: ''25 martie 2026''\\ |
| - | Deadline: ''?? aprilie 2026'' | + | Deadline: ''17 aprilie 2026'' |
| - | Schelet de cod: {{:pp:2025:scala:tema1_pp_2025.zip|}} | + | Schelet de cod: {{:pp:2026:scala:tema1_pp_2026_skel_v1.zip|}} |
| - | + | ||
| - | După ce ați descărcat scheletul, creați un proiect nou din IntelliJ în Scala, în care copiați folderele și fișierul din arhivă în root-ul proiectului (folderul ''src'' va fi suprascris). Dați restart la IDE și ar trebui să funcționeze. | + | |
| <note warning>După deadline fiecare student va prezenta tema la laborator, explicând în detaliu implementarea.</note> | <note warning>După deadline fiecare student va prezenta tema la laborator, explicând în detaliu implementarea.</note> | ||
| Line 11: | Line 9: | ||
| <note important>În soluție nu aveți voie să programați cu efecte laterale. Folosiți declarații doar ''val'', nu <del>var</del>.</note> | <note important>În soluție nu aveți voie să programați cu efecte laterale. Folosiți declarații doar ''val'', nu <del>var</del>.</note> | ||
| - | [Obiectivul acestei teme este implementarea unui program care simuleaza functionarea unei case de marcat, proces care consta in scanarea unor produse si adaugarea acestora pe o lista pentru calculul sumei de platit. Pentru a implementa acest proiect, avem nevoie de doua module importante: modulul de decodificare a codului de bare de pe produs si modulul de baza de date, care stocheaza informatiile despre denumirea, pretul si cantitatea produselor disponibile.] | + | Obiectivul acestei teme este implementarea unui program care simuleaza functionarea unei case de marcat, proces care consta in scanarea unor produse si adaugarea acestora in cosul de cumparaturi. Pentru a implementa acest proiect, avem nevoie de trei module importante: |
| + | * Partea 1: modulul de decodificare a codului de bare de pe produs | ||
| + | * Partea 2: modulul de tabele folosit pentru a stoca informatiile despre produse, cum at fi denumirea, pretul si codul de bare | ||
| + | * Partea 3: operatii uzuale de gestionare a cosului de cumparaturi, de exemplu adaugarea de produse, stergerea sau modificarea cantitatii | ||
| ===== 1. Coduri de bare ===== | ===== 1. Coduri de bare ===== | ||
| Un cod de bare este o reprezentare vizuală a datelor, ușor de citit de dispozitive. De obicei datele descriu proprietăți ale obiectului pe care se află codul de bare. | Un cod de bare este o reprezentare vizuală a datelor, ușor de citit de dispozitive. De obicei datele descriu proprietăți ale obiectului pe care se află codul de bare. | ||
| Line 43: | Line 45: | ||
| Pentru fiecare cifră din al doilea grup (pozițiile 8->13) există o singură codificare posibilă (codificare **R** paritate ''pară'' ). | Pentru fiecare cifră din al doilea grup (pozițiile 8->13) există o singură codificare posibilă (codificare **R** paritate ''pară'' ). | ||
| + | <hidden Tabelul codificarilor L, G si R pentru cifre> | ||
| ^ Cifra ^ Codificare-L ^ Codificare-G ^ Codificare-R^ | ^ Cifra ^ Codificare-L ^ Codificare-G ^ Codificare-R^ | ||
| | **0** | **0001101** | **0100111** | **1110010**| | | **0** | **0001101** | **0100111** | **1110010**| | ||
| Line 55: | Line 57: | ||
| | **8** | **0110111** | **0001001** | **1001000**| | | **8** | **0110111** | **0001001** | **1001000**| | ||
| | **9** | **0001011** | **0010111** | **1110100**| | | **9** | **0001011** | **0010111** | **1110100**| | ||
| + | |||
| + | </hidden> | ||
| + | |||
| Observații: | Observații: | ||
| * Codul de bare începe cu o cifră codificată ''impar'' și se termină cu o cifră codificată ''par'', astfel scannerele pentru codurile de bare pot determina orientarea și să citească și de la stânga la dreapta, dar și invers. | * Codul de bare începe cu o cifră codificată ''impar'' și se termină cu o cifră codificată ''par'', astfel scannerele pentru codurile de bare pot determina orientarea și să citească și de la stânga la dreapta, dar și invers. | ||
| Line 64: | Line 69: | ||
| După cum am spus anterior, prima cifră se numește cifră de paritate. | După cum am spus anterior, prima cifră se numește cifră de paritate. | ||
| Cifra de paritate ''nu'' este reprezentată direct printr-o succesiune de bare și spații, ci este codificată indirect, prin alegerea unei combinații de moduri de codificare L sau G pentru primul grup de 6 cifre, conform tabelului de mai jos. Practic, este suficient să știm ce codificare a fost folosită pentru fiecare dintre cele 6 cifre din primul grup pentru a determina cifra de paritate asociată. Dacă combinația găsită nu este asociată cu o cifră din tabelul de mai jos codul este invalid. | Cifra de paritate ''nu'' este reprezentată direct printr-o succesiune de bare și spații, ci este codificată indirect, prin alegerea unei combinații de moduri de codificare L sau G pentru primul grup de 6 cifre, conform tabelului de mai jos. Practic, este suficient să știm ce codificare a fost folosită pentru fiecare dintre cele 6 cifre din primul grup pentru a determina cifra de paritate asociată. Dacă combinația găsită nu este asociată cu o cifră din tabelul de mai jos codul este invalid. | ||
| + | |||
| + | <hidden Tabelul codificarilor in functie de cifra de paritate> | ||
| + | |||
| ^ Cifra de paritate ^ Primul grup ^ | ^ Cifra de paritate ^ Primul grup ^ | ||
| | **0** | **LLLLLL**| | | **0** | **LLLLLL**| | ||
| Line 76: | Line 84: | ||
| | **9** | **LGGLGL**| | | **9** | **LGGLGL**| | ||
| + | </hidden> | ||
| === Calculare cifră de control === | === Calculare cifră de control === | ||
| Line 121: | Line 130: | ||
| </code> | </code> | ||
| - | === Algoritm === | + | <hidden Explicarea in detaliu a algoritmului> |
| + | **1. Transformarea imaginilor** | ||
| Primim o matrice de biți 0 și 1, reprezentând imaginea în formatul alb-negru descris anterior. Decupăm din matricea de pixeli rândurile din mijloc și rulăm algoritmul de identificare a barelor pe toate aceste rânduri, pentru a avea șanse mai mari de succes. Vrem să găsim barele din imagine, așa că grupăm biții identici și consecutivi în tupluri de tipul **(<număr_repetări>, <bit>)**, unde tuplul descrie grosimea și culoarea barei din imagine. Va rezulta următorul comportament:\\ | Primim o matrice de biți 0 și 1, reprezentând imaginea în formatul alb-negru descris anterior. Decupăm din matricea de pixeli rândurile din mijloc și rulăm algoritmul de identificare a barelor pe toate aceste rânduri, pentru a avea șanse mai mari de succes. Vrem să găsim barele din imagine, așa că grupăm biții identici și consecutivi în tupluri de tipul **(<număr_repetări>, <bit>)**, unde tuplul descrie grosimea și culoarea barei din imagine. Va rezulta următorul comportament:\\ | ||
| <nowiki> | <nowiki> | ||
| Line 127: | Line 138: | ||
| </nowiki> | </nowiki> | ||
| \\ | \\ | ||
| + | |||
| + | **2. Identificarea unui posibil cod de bare** | ||
| Căutăm o secvență de 59 de bare pentru fiecare rând din imagine în care identificăm secvențele de start și de stop.\\ | Căutăm o secvență de 59 de bare pentru fiecare rând din imagine în care identificăm secvențele de start și de stop.\\ | ||
| Secvențele de 59 de bare care conțin secvențele de start și stop din fiecare rând sunt returnate de funcția ''checkRow'', a cărei implementare este dată de echipă.\\ | Secvențele de 59 de bare care conțin secvențele de start și stop din fiecare rând sunt returnate de funcția ''checkRow'', a cărei implementare este dată de echipă.\\ | ||
| + | |||
| + | **3. Identificare cifre** | ||
| Din secvența de 59 de bare extragem grupuri de 4 bare care reprezintă codificarea unei cifre (după ce am eliminat secvențele de bare care marchează start, centru și sfârșit). Pentru primele 6 cifre găsim codificarea cea mai apropiată L sau G, iar pentru ultimele 6 cifre găsim cea mai apropiată codificare R. | Din secvența de 59 de bare extragem grupuri de 4 bare care reprezintă codificarea unei cifre (după ce am eliminat secvențele de bare care marchează start, centru și sfârșit). Pentru primele 6 cifre găsim codificarea cea mai apropiată L sau G, iar pentru ultimele 6 cifre găsim cea mai apropiată codificare R. | ||
| + | |||
| + | Pentru a putea face acest lucru, avem nevoie sa masuram cat de aproape este codificarea obtinuta din poza cu codificarea reala. O cifra e reprezentata prin 4 bare, fiecare bara avand o anumita latime. Se poate ca in realitate, patternul pe care il intalnim sa nu se potriveasca perfect cu niciuna dintre reprezentari. Priviti urmatorul exemplu (codificarea L a cifrei 4: 0100011): | ||
| + | <code> | ||
| + | ░░░░ = 0 | ||
| + | ████ = 1 | ||
| + | ░░░░████░░░░░░░░░░░░████████ = Codificare L pentru cifra 4 | ||
| + | ░░░░█████░░░░░░░░░░█████████ = Codificare citita de fapt | ||
| + | </code> | ||
| + | |||
| + | Codificarea pe care am citit-o de fapt difera putin de cea a cifrei 4. Cat de mare este aceasta diferenta va fi masurata de distanta. Va va fi explicata formula ei de calcul in exercitii. | ||
| Pentru a identifica cifra codificată de un set de 4 bare vom calcula distanța dintre secvența de bare din poză și secvențele de bare pentru codificările L, G sau R. Vom alege codificarea cea mai apropiată (de distanță minimă) pentru fiecare din cele 12 cifre. | Pentru a identifica cifra codificată de un set de 4 bare vom calcula distanța dintre secvența de bare din poză și secvențele de bare pentru codificările L, G sau R. Vom alege codificarea cea mai apropiată (de distanță minimă) pentru fiecare din cele 12 cifre. | ||
| + | |||
| + | **4. Calcul lungimi relative** | ||
| De la formatul descris pentru bare vom lua grupe de câte 4 bare care reprezintă o cifră și vom trece la formatul dimensiunilor relative ale segmentelor, impărțind numărul de aparitii la lungimea totală.\\ | De la formatul descris pentru bare vom lua grupe de câte 4 bare care reprezintă o cifră și vom trece la formatul dimensiunilor relative ale segmentelor, impărțind numărul de aparitii la lungimea totală.\\ | ||
| Line 145: | Line 172: | ||
| </nowiki>\\ | </nowiki>\\ | ||
| - | Având codificările standard ale cifrelor în același format, vom alege codificarea care începe cu același bit și pentru care distanța (suma modulelor diferențelor dintre rapoartele aflate pe aceeași poziție) este minimă, adică codificarea pentru care barele respectă proporții de grosime similare. | + | Tinand seama de bitul cu care incepe codificarea rezultata **din poza** (in exemplul de mai sus este 0) vom alege codificarea cea mai similara pentru o cifra bazat pe distanta cea mai mica (vezi explicatia de la pasul 3). |
| + | |||
| + | **5. Cifra de paritate si cifra de control** | ||
| După ce am identificat ultimele 12 cifre ale codului de bare, vom determina cifra de paritate. Pentru a determina cifra de paritate ne vom uita la paritatea codificărilor identificate pentru cele 6 cifre din primul grup. [[#cifra_de_paritate| vezi mai sus]]. | După ce am identificat ultimele 12 cifre ale codului de bare, vom determina cifra de paritate. Pentru a determina cifra de paritate ne vom uita la paritatea codificărilor identificate pentru cele 6 cifre din primul grup. [[#cifra_de_paritate| vezi mai sus]]. | ||
| Line 152: | Line 181: | ||
| Dacă cifra de control este corectă, am identificat toate cifrele și întoarcem rezultatul. Altfel întoarcem None. | Dacă cifra de control este corectă, am identificat toate cifrele și întoarcem rezultatul. Altfel întoarcem None. | ||
| + | |||
| + | </hidden> | ||
| + | |||
| <hidden Recapitulare functii de ordin superior> | <hidden Recapitulare functii de ordin superior> | ||
| Line 526: | Line 558: | ||
| def &&(other: FilterCond) = ??? | def &&(other: FilterCond) = ??? | ||
| def ||(other: FilterCond) = ??? | def ||(other: FilterCond) = ??? | ||
| - | def !! = ?? | + | def unary_! = ?? |
| // Puteti sa adaugati mai multi operatori :) | // Puteti sa adaugati mai multi operatori :) | ||
| } | } | ||
| Line 556: | Line 588: | ||
| - | **2.3.1.** Vom defini operatiile ce se pot realiza pe o tabela folosind TDA-ul ''PP_SQL_Table''. Funcția ''eval'' trebuie sa apeleze metodele corespunzatoare definite in ''Table''. | + | **2.3.1.** Vom defini operatiile ce se pot realiza pe o tabela folosind TDA-ul ''PP_SQL_Table''. Funcția ''eval'' trebuie sa apeleze metodele corespunzatoare definite in ''Table''. Ne vom folosi de mostenire pentru a oferi implementari specifice functiei eval pentru fiecare tip de operatie. |
| <code scala> | <code scala> | ||
| Line 646: | Line 678: | ||
| </code> | </code> | ||
| ===== Testare ===== | ===== Testare ===== | ||
| - | În folderul src/test din proiect se află Test.scala, care poate fi rulat din IntelliJ apăsând pe butonul de Run din partea stângă a codului. Fiecare test are un buton propriu și poate fi rulat separat. Există teste pentru cele mai importante funcții, vă recomandăm să testați funcțiile de bază înainte de a începe implementarea task-urilor avansate. | + | În folderul src/test din proiect se află testele. Testele pot fi rulate din terminal folosind comanda: |
| - | La rularea testelor veți primi și un punctaj, după specificațiile din enunț. | ||
| - | |||
| - | Dacă folosiți terminalul: | ||
| <code>sbt test</code> | <code>sbt test</code> | ||
| + | |||
| + | Puteti testa singuri functionalitatea temei folosind functia main din fisierul Main.scala dupa ce ati implementat toate functiile. Ar trebui ca primul cod de bare sa fie recunoscut si al doilea nu. | ||
| + | |||
| + | Din terminal puteti rula proiectul folosind comanda: | ||
| + | |||
| + | <code>sbt run</code> | ||
| ===== Submisie arhiva ===== | ===== Submisie arhiva ===== | ||