ific: Prof. Dr. Ing. Zamfirescu Bălă Constantin Îndrumător: Prof. Dr. Ing. Zamfirescu Bălă Constantin Absolvent: Schiau Andreea-Roxana Specializarea… [605912]
UNIVERSITATEA “LUCIAN BLAGA” DIN SIBIU
FACULTATEA DE INGINERIE
DEPARTAMENTUL DE CALCULATOARE ȘI INGINERIE ELECTRICĂ
PROIECT DE DIPLOMĂ
Conducător
ș
tiin
ț
ific: Prof. Dr. Ing. Zamfirescu Bălă Constantin
Îndrumător: Prof. Dr. Ing. Zamfirescu Bălă Constantin
Absolvent: [anonimizat],
2019 –
UNIVERSITATEA “LUCIAN BLAGA” DIN SIBIU
FACULTATEA DE INGINERIE
DEPARTAMENTUL DE CALCULATOARE ȘI INGINERIE ELECTRICĂ
ALOCAREA RESURSELOR
INDIVIZIBILE –
ORGANIZAREA
FESTIVALURILOR DE MODĂ
Conducător
ș
tiin
ț
ific: Prof. Dr. Ing. Zamfirescu Bălă Constantin
Îndrumător: Prof. Dr. Ing. Zamfirescu Bălă Constantin
Absolvent: [anonimizat]
1
PLAN
TEMATIC:
formular
care
se
preia
de
la
secretariatul
departamentului,
se
completează
de
către
cadrul
didactic
îndrumător
si
se
înmânează
absolvent: [anonimizat]
2
Cuprins
1
.
Prezentarea Temei
5
1.1 Contextul proiectului
5
1.2 Idea
ș
i scopul lucrării
6
1.3 Structura lucrării
6
1.4 Actualizarea lucrării în cadrul unui concurs de inova
ț
ii
6
2. Considera
ț
ii teoretice
8
2.1 Aplica
ț
ia server
8
2.1.1 Medii de dezvoltare folosite
9
2.1.1.1 Visual Studio
9
2.1.2 Proiectarea bazei de date rela
ț
ională
9
2.1.2.1 Normalizarea bazei de date
10
2.1.3 Microsoft SQL Server
13
2.1.3.1 Entity Framework
13
2.1.3.2 Entity Framework Core
14
2.1.3.3 Entity Framework Code-First
15
2.1.4 ASP .NET Core Web API
16
2.1.4.1 Componentele .Net Framework
16
2.1.4.2 Atributele rutelor
18
2.1.5 Limbajul de programare C#
19
2.1.6.1 Programarea orientată pe obiect
20
2.2 Aplica
ț
ia client
22
2.2.1 Framework-uri
22
2.2.2 Mediul de dezvoltare
23
2.2.3 Angular Framework
23
2.3.1.1 Structura Angular
24
2.3.1.2 Componentele Angular
26
2.3.1.3 Injec
ț
ia de dependen
ț
ă în Angular
28
2.3.1.4 Limbajele folosite în Angular
28
2.3 Problema alocării de resurse
30
2.3.1 Comportamentul strategic atunci când alocăm bunuri indivizibile secven
ț
ial
31
2.3.1.1 Comportamentul strategic
32
2.3.2 Algoritmi implementa
ț
i
34
2.3.2.1 Adjusted Winner
34
2.3.2.2 Descending Demand
35
2.3.2 Utilitatea algoritmului Adjusted Winner
35
3. Descrierea formală a aplica
ț
iei
39
3.1 Arhitectura aplica
ț
iei
39
3.1.1 Arhitectura aplica
ț
iei server
40
3
3.1.2 Func
ț
ionalit ate
41
3.2 Scenarii de utilizare
54
4. Descrierea aplica
ț
iei
56
4.1 Structura aplica
ț
iei server
56
4.1.1 Metoda de alocare a modelelor
56
4.1.2 Algoritmii implementa
ț
i
58
4.1.2.1 Adjusted Winner
59
4.1.2.2 Descending Demand
64
4.1.3 Baza de date
68
4.2 Descrierea aplica
ț
iei web
70
4.2.1 Implementarea aplica
ț
iei client
77
5. Concluzii
ș
i dezvoltăr i ulterioare
84
5.1 Concluzii
84
5.1 Compara
ț
ii între algoritmi
84
5.1 Dezvoltări ulterioare
85
Abrevieri
86
Figuri
87
Bibliografie
89
4
1.
Prezentarea Temei
1.1 Contextul proiectului
În
prezent
numărul
creatorilor
de
design
vestimentar
este
în
continuă
cre
ș
tere,
ceea
ce
înseamnă
că
tot
mai
mul
ț
i
designeri
î
ș
i
doresc
să
î
ș
i
prezinte
colec
ț
iile
pe
o
scenă,
la
festivale
de
modă.
În
cadrul
unui
eveniment
de
prezentare,
fiecare
designer
dore
ș
te
manechinele
potrivite,
care
se
încadrează
în
standardelor
ș
i
cerin
ț
elor
lui,
astfel
încât
crea
ț
ia
să
iasă
în
eviden
ț
ă cât mai bine.
Săptămâna
modei
reprezintă
un
festival
de
modă,
în
care
se
desfă
ș
oară
un
ș
ir
de
evenimente
de-a
lungul
a
aproximativ
7
zile,
la
care
mai
mul
ț
i
designeri
de
modă
î
ș
i
prezintă
colec
ț
iile.
În
cadrul
festivalului,
manechinele
sunt
selectate
si
prezentate
designerilor
pentru
a-
ș
i
alege
preferatele.
Într-o
zi
pot
avea
loc
mai
multe
prezentări,
iar
un
manechin,
din
cauza
timpului
restrâns,
va
putea
fi
disponibil
doar
pentru
un
anumit
număr
limitat
de
prezentări
în
ziua
respectivă.
Un
manechin
poate
fi
ales
ca
preferat
de
mai
mul
ț
i
designeri
care
î
ș
i
prezintă
colec
ț
iile
în
aceea
ș
i
zi.
În
acest
caz,
repartizarea
acestuia
este
necesară
să
se
facă
într-un
mod
cât mai corect.
În
cadrul
organizării,
dezavantajul
major
al
acestor
festivale
îl
reprezintă
distribuirea
manechinelor.
Un
prim
efect
îl
reprezintă
crearea
unui
dezechilibru
în
alegerea
manechinelor
preferate
de
către
designeri.
Acestora
li
se
repartizează
manechine
în
func
ț
ie
de
alegerile
unuia
dintre
manageri,
rezultând
o
repartizare
haotică.
Un
al
doilea
efect,
sugerat
de
acest
aspect,
este
dat
de
instabilitatea
programului
manechinelor,
ajungându-se
deseori
la
situa
ț
ii
în
care
acestea
află
in
ziua
evenimentului
dacă
urmează
să
prezinte
moda
sau
nu,
sau
chiar
sa
fie
mult prea aglomerate în program
ș
i să se întârzie cu începerea evenimentelor.
Bazat
pe
dezavantajele
men
ț
ionate,
în
următoarea
lucrare
de
licen
ț
ă,
se
va
încerca
propunerea
ș
i
implement area
unui
nou
sistem
de
organizare
festivalelor
de
modă,
care
are
ca
scop
repartizarea
manechinelor
în
func
ț
ie
de
preferin
ț
ele
designerilor,
într-un
mod
cât
mai
corect.
5
1.2 Idea
ș
i scopul lucrării
Ideea
lucrării
constă
în
crearea
unui
sistem
de
alocare
a
resurselor
umane,
bazate
pe
anumite
criterii
de
selec
ț
ie,
într-un
mod
cat
mai
corect
ș
i
egal.
Astfel,
designerilor
li
se
vor
aloca
manechinele
dorite.
Pe
lângă
acest
aspect,
sistemul
simplifică
munca
managerului,
repartizarea
făcându-se
automat
pe
loc.
Un
alt
beneficiu
în
cadrul
acestei
lucrări,
îl
reprezintă
rezultarea
unui
program
bine
stabilit
pentru
manechinele,
de-a
lungul
întregului
festival.
Acestea
fiind
în
ș
tiin
ț
ate
cu
privire
la
programul
de
muncă,
ș
tiind
exact
când
unde
ș
i
când
trebuie să meargă.
1.3 Structura lucrării
Această
lucrare
este
organizată
în
patru
capitole,
primul
este
introductiv
ș
i
con
ț
ine
contextul, ideea
ș
i scopul lucrării.
Acesta
este
urmat
de
capitolul
al
doilea,
capitol
ce
con
ț
ine
planul
tematic
alcătuit
din
programele
folosite
în
cadrul
aplica
ț
iei,
limbajul
de
programare
folosit,
teorie
legată
alocarea
modelelor în cadrul festivalelor de modă
ș
i o prezentare detaliată a sistemului proiectului.
În
capitolul
al
treilea,
este
prezentată
arhitectura
aplica
ț
iei
cu
ajutorul
schemelor
logice, a diagramelor
ș
i o prezentare a bazei de date folosite.
Capitolul
al
patrulea
este
format
din
explicarea
codului
în
detaliu
ș
i
prezentarea
acestuia cu ajutorul capturilor de ecran.
1.4 Actualizarea lucrării în cadrul unui concurs de inova
ț
ii
Această
lucrare
a
fost
prezentată
în
cadrul
concursului
Innovation
Labs
de
la
Sibiu,
care
se
desfă
ș
oară
anual.
Actualizarea
lucrării
a
constat
într-o
platformă
de
afi
ș
are
a
modelelor
pentru
a
fi
găsite
de
poten
ț
ialii
investitori,
cum
ar
fi
diverse
firme
de
publicitate,
festivale
de
modă,
designeri
etc.
Pe
lângă
acest
aspect,
platforma
oferă
un
ajutor
pentru
organizarea
repartizării
modelelor
în
cadrul
festivalelor
de
modă,
subiectul
principal
al
licen
ț
ei.
Pentru
a
conving e
juriul
din
cadrul
concursului
că
această
aplica
ț
ie
este
le
foarte
utilă
6
festivalurilor,
am
discutat
cu
câteva
dintre
ele.
Acestea
s-au
arătat
foarte
interesate
iar
unul
dintre ele dore
ș
te să teste ze aplica
ț
ia chiar la următorul evenimen t.
7
2. Considera
ț
ii teoretice
Termenii
de
aplica
ț
ie
client
(front-end)
ș
i
aplica
ț
ie
server
(back-end)
se
referă
la
separarea
preocupărilor
dintre
front-end
ș
i
stratul
de
acces
la
date
al
unei
păr
ț
i
de
software.
În
modelul
client-server,
clientul
este
considerat,
de
obicei,
front-end
ș
i
serverul
este
de
obicei
considerat
ca
fiind
back-end.
Codul
care
este
scris
de
programatorul
de
front-end
rulează
în
browser-ul
utilizatorului,
în
timp
ce
codul
unui
dezvoltator
de
back-end
rulează
pe
serverul
web.
De
exemplu,
dezvoltatorul
din
spate
ar
putea
fi
un
inginer
care
proiectează
ș
i
creează
sistemele
care
realizează
o
activitate
urbană
(electricitate,
apa
etc.),
în
timp
ce
dezvoltatorul
de
front-end
este
cel
care
se
asigură
în
mod
direct,
prin
interac
ț
iunea
cu
sistemele
realizate
că
acestea sunt conectate corespunzător, astfel încât locuitorii să ducă o via
ț
ă decentă.
Figura 1. Aplica
ț
ie server-client
2.1 Aplica
ț
ia server
Aplica
ț
ia
server
este
codul
care
rulează
pe
server,
care
prime
ș
te
cereri
de
la
clien
ț
i
ș
i
con
ț
ine
logica
pentru
a
trimite
datele
corespunzătoare
către
client.
Acesta
reprezintă
toată
tehnologia
necesară
procesării
cererii
de
intrare
ș
i
generării
trimiterii
răspunsului
către
client.
Acesta include trei păr
ț
i majore:
8
●
Serverul
–
un
program
pe
calculator
sau
un
dispozitiv,
care
oferă
func
ț
ionalitate
pentru
alte programe sau dispozitive, numite ”clien
ț
i„
●
Aplica
ț
ia
–
aceasta
este
aplica
ț
ia
care
rulează
pe
server,
care
ascultă
cererile,
prelucrează informa
ț
ii din baza de date
ș
i trimite un răspu ns.
●
Baza de date – utilizată pentru organizarea
ș
i persisten
ț
a datelor. [1]
2.1.1 Medii de dezvoltare folosite
Mediile
de
dezvoltare
folosite
pentru
partea
de
back-end
sunt:
Visual
Studio
ș
i
Microsoft SQL Server
ș
i vor fi prezentate în continuare.
2.1.1.1 Visual Studio
Visual
Studio
este
un
IDE
(Integrated
Development
Enviroment)
care
se
poate
ob
ț
ine
gratuit,
open-source
care
poate
rula
oriunde.
Acesta
oferă
suport
pentru
limbajul
C#
folosit
în
aplica
ț
ie
si
care
urmea ză
să
fie
descris
mai
jos.
Este
un
software
care
consolidează
instrumentele
de
bază
necesare
atât
pentru
scrierea
cât
ș
i
pentru
testarea
software-ului.
Unul
dintre
marile
beneficii
ale
acestuia
este
că
îmbunătă
ț
e
ș
te
produ ctivitatea
dezvoltatorilor
de
software, datorită configura
ț
iei rapide a instrumentelor.
2.1.2 Proiectarea bazei de date rela
ț
ională
Baza
de
date
rela
ț
ională
a
fost
propusă
pe
la
sfâr
ș
itul
anului
1970
de
către
Edgar
Codd, devenind mai apoi modelul de bază de date dominantă pentru aplica
ț
iile comerciale.
Organizarea
datelor
într-o
bază
de
date
rela
ț
ională
se
face
prin
tabele
(sau
rela
ț
ii).
Astfel,
un
tabel
este
alcătuit
din
rânduri
ș
i
coloane.
Un
rând
reprezintă
o
înregistrare
ș
i
o
coloană
se
mai
nume
ș
te
un
câmp
(sau
atribut).
Putem
asimila
un
tabel
de
bază
de
date
cu
o
foaie
de
calcul.
Pentru
că
rela
ț
iile
care
pot
fi
create
între
tabele
permit
o
baza
de
date
rela
ț
ională,
în
cazul
unei
cantită
ț
i
mari
de
date,
aceasta
le
stochează
eficient
ș
i
facilitează
preluarea datelor selectate.
Limbajul
care
a
fost
dezvoltat
pentru
a
lucra
cu
bazele
de
date
rela
ț
ionale
poartă
numele de SQL (Structured Query Language).
9
2.1.2.1 Normalizarea bazei de date
Caracteristica
principală
a
bazei
de
date
rela
ț
ionale
constă
în
rela
ț
ia
care
poate
fi
definită
între
tabele.
Identificarea
rela
ț
iilor
dintre
tabele
reprezintă
parametrul
cel
mai
important în proiectarea unei baze de date rela
ț
ionale. Tipurile de rela
ț
ii includ:
●
One-to-many (unu-la-mul
ț
i)
●
Many-to-many (multi-la-mul
ț
i)
●
One-to-one (unu-la-unu)
●
One-to-many (unu-la-mul
ț
i)
Într-o
bază
de
date
de
„listă
evenimente”,
un
designer
î
ș
i
poate
prezenta
colec
ț
ia
de
haine
de
la
zero
sau
la
mai
multe
evenimente,
în
timp
ce
un
eveniment
este
prezentat
de
un
(
ș
i
numai
unul)
designer.
Într-o
bază
de
date
„festival”,
un
manager
gestionează
zero
sau
mai
mul
ț
i
angaja
ț
i,
în
timp
ce
un
angajat
este
gestionat
de
un
(
ș
i
numai
unul)
manager.
Într-o
bază
de
date
„vânzări
de
produse”,
mai
multe
comenzi
pot
fi
plasate
de
un
client,
în
timp
ce
un
ordin
este
plasat
de
un
anumit
client.
Tipul
acestei
rela
ț
ii
este
cunoscut
sub
numele
de
one-to-many (unu-la-mul
ț
i).
One-to many
Rela
ț
iile
unu-la-m ul
ț
i
nu
pot
fi
reprezentate
doar
într-u n
singur
tabel.
De
exemplu,
într-o
bază
de
date
de
„listă
evenimente”,
putem
începe
cu
un
tabel
numit
Designer,
care
stochează
informa
ț
ii
despre
designeri
(cum
ar
fi
numele,
telefon
ș
i
e-mail).
Pentru
a
stoca
evenimentele
care
urmează
sa
aibe
loc
ale
designerilor,
am
putem
crea
coloane
eveniment1,
eveniment2.
eveniment3,
dar
intervine
o
problemă
cu
privire
la
numărul
mare
de
coloane
care
urmează
să
fie
creat.
Pe
de
altă
parte,
dacă
vom
începe
cu
un
tabel
numit
evenimente,
care
stochează
informa
ț
ii
despre
un
eveniment
(dataEvent,
timeEvent
ș
i
locationEvent),
am
putea
crea
coloane
suplimentare
pentru
a
stoca
informa
ț
ii
despre
(unul)
desginer
(cum
ar
fi
numele.
telefon
ș
i
e-mail).
Cu
toate
acestea,
din
moment
ce
un
designer
poate
avea
mai
multe
evenimente, datele sale vor fi duplicate în mai multe rânduri în tabelul de evenimente.
În
scopul
sprijinirii
rela
ț
iei
unu-la-mul
ț
i,
avem
nevoie
de
a
proiecta
două
tabele:
un
tabel
Events
pentru
a
stoca
informa
ț
ii
despre
evenimente,
cu
eventID
cheie
primară,
ș
i
un
tabel
Designers,
pentru
a
stoca
informa
ț
ii
despre
designeri
cu
designerID
ca
ș
i
cheie
primară.
10
Putem
crea
apoi
rela
ț
ia
unu-la-mul
ț
i
prin
stocarea
cheii
primare
a
tabelului
Designer
(designerID) în tabelul de evenimente, a
ș
a cum este ilustrat mai jos.
Figura 2. Exemplu de legătură unu la mul
ț
i
Coloana
desigerID
în
tabelul
din
events
este
cunoscut
ca
fiind
o
cheie
străină.
Pentru
un
tabel
copil,
o
cheie
externă
este
o
cheie
primară
a
unui
tabel
părinte,
folosit
pentru
a
face
referire la tabelul părinte.
Many-to-many
Într-o
bază
de
date
„vânzări
de
căr
ț
i”,
comanda
unui
singur
client
con
ț
ine
unu
sau
mai
multe
căr
ț
i,
iar
o
carte
poate
să
apară
în
mai
multe
comenzi.
Într-o
bază
de
date
numită
„librărie”,
o
carte
este
scrisă
de
unul
sau
mai
mul
ț
i
autori,
în
timp
ce
un
autor
poate
să
scrie
mai
multe
căr
ț
i.
Tipul
acestei
rela
ț
ii
este
cunoscută
ca
fiind
dată
sub
numele
de
mul
ț
i-la-mul
ț
i.
În
continuare
voi
exemplifica
o
bază
de
date
„vânzări
de
căr
ț
i”.
Pentru
început
voi
crea
două
tabele:
căr
ț
i
ș
i
comenzi.
Tabelul
de
căr
ț
i
con
ț
ine
detalii
despre
căr
ț
i
(precum
numele,
descrierea
si
cantitatea
de
stoc)
cu
cheia
primară
„carteId”.
Tabelul
de
comenzi
urmează
să
con
ț
ină
de
asemenea
ordinele
clientului
(codul
clientului,
dataComenzii,
dataPrimirii
ș
i starea). În tabelul de căr
ț
i nu se pot stoca detalii de spre comandă.
În
scopul
sus
ț
inerii
rela
ț
iei
de
mul
ț
i-la-mul
ț
i,
avem
nevoie
de
a
crea
al
treilea
tabel
(cunoscut
ca
un
tabel
de
jonc
ț
iune),
sub
numele
de
„DetaliiComanda”,
în
cazul
în
care
fiecare
rând
sugerează
un
element
dintr-o
anumită
ordine.
Cheia
primară
din
tabelul
„DetaliiComanda”
este
formată
din
două
coloane:
comandaId
ș
i
carteId,
care
identifică
în
mod
unic
fiecare
rând.
Coloanele
„comandaId”
ș
i
„carteId”
din
tabelul
„DetaliiComanda”
11
sunt
folosite
ca
ș
i
referin
ț
ă
pentru
tabelele
Comenzi
ș
i
Căr
ț
i,
astfel,
acestea
sunt
cheile
străine
din tabelul „DetaliiComanda”.
Figura 3. Exemplu de legătură mul
ț
i-la-mul
ț
i
Această
rela
ț
ie
de
mul
ț
i-la-mul
ț
i
este,
mai
exact,
implementată
ca
fiind
două
rela
ț
ii
unu-la-mul
ț
i,
odată
cu
introducerea
tabelului
de
jonc
ț
iune.
Astfel,
o
comandă
con
ț
ine
mai
multe
elemente
în
„DetaliiComanda”.
O
carte
apare
în
mai
multe
tabeleDetaliiComandă.
Fiecare element din ComandaDetalii are specificat o singură carte.
One-to-One
Într-o
bază
de
date
„alocarea
modelelor”,
un
model
poate
avea
mai
multe
informa
ț
ii
suplimentare
op
ț
ionale,
cum
ar
fi
înăl
ț
imea
ș
i
culoarea
părului.
Men
ț
inerea
lor
în
interiorul
tabelului
de
modele
ar
rezulta
în
tabel
mai
multe
spa
ț
ii
goale.
Mai
mult,
aceste
date
mari
pot
degrada performan
ț
a baze i de date.
În
schimb,
putem
crea
un
alt
tabel
(căruia
îl
denumin
ModelDetails)
pentru
a
stoca
datele
op
ț
ionale.
O
înreg istrare
va
fi
creată
numai
pentru
acele
modele
cu
date
op
ț
ionale.
Celelalte
două
tabele,
Models
ș
i
ModelDetails,
sugerează
o
rela
ț
ie
unu-la-unu.
Aceasta
înseamnă
că
pentru
fiecare
rând
din
tabela
părinte,
există
cel
mult
un
rând
(posibil
zero)
în
tabelul de copii.
O
limitare
pe
care
o
pot
avea
unele
baze
de
date
este
reprezentată
de
numărul
de
coloane
redus
care
pot
fi
create
în
interiorul
unui
tabel.
În
acest
scop,
se
poate
folosi
o
rela
ț
ie
12
de
unu-la-unu
pentru
a
împăr
ț
i
datele
în
două
tabele.
Un
alt
avantaj
al
rela
ț
iei
de
unu-la-unu
este
dat
de
stocarea
anumitor
date
sensibile
într-un
tabel
securizat,
iar
cele
non-sensibile
în
tabelul principal.
Figura.4. Exemplu de legătură unu-la-unu
2.1.3 Microsoft SQL Server
Microsoft
SQL
Server
reprezintă
un
sistem
de
gestionare
a
bazei
de
date
rela
ț
ionale
[2].
Pentru
a
comunica
cu
baza
de
date,
se
folose
ș
te
limbajul
de
interogare
este
SQL
(pronun
ț
at
"ESS-que-el" ).
Acest
limbaj,
conform
ANSI
(American
National
Standards
Institute),
reprezintă
limbajul
standard
pentru
sistemele
de
management
de
baze
de
date
rela
ț
ionale.
Instruc
ț
iunile
SQL
sunt
întrebuin
ț
ate
pentru
a
executa
diverse
sarcini,
cum
ar
fi
actualizarea
sau
preluarea
unor
date
din
baza
de
date.
Câteva
dintre
sistemele
comune
de
management
de
baze
de
date
rela
ț
ionale
care
folosesc
SQL
sunt:
Microsoft
SQL
Server,
Oracle,
Access
etc.
De
ș
i
majoritatea
sistemelor
de
baze
de
date
folosesc
SQL,
un
număr
mare
dintre
ele
au,
de
asemenea,
propriile
extensii
proprietare
suplimentare,
care
sunt
în
majoritatea
cazurilor
utilizate
doar
pe
sistemul
lor.
Prin
urmare,
comenzile
SQL
standard:
„Select”,
„Insert”,
„Update”,
„Delete”,
„Create”
ș
i
„Drop”
pot
fi
folosite
pentru
a
realiza
aproape tot ceea ce este nevoie într-o bază de date.
2.1.3.1 Entity Framework
Entity
Framework
este
un
set
de
tehnologii
care
sprijină
dezvoltarea
de
aplica
ț
ii
software
orientate
pe
date.
Acest
framework
permite
dezvoltatorilor
să
lucreze
cu
date
sub
formă
de
obiecte
ș
i
propr ietă
ț
i
specifice
unui
domeniu,
cum
ar
fi
clien
ț
ii
ș
i
adresele
acestora,
13
fără
a
fi
nevoie
să
se
preocupe
cu
tabelele
bazei
de
date
ș
i
de
modul
în
care
sunt
stocate
datele.
Cu
Entity
Framework,
dezvoltatorii
pot
lucra
la
un
nivel
mai
ridicat
de
abstractizare
când
se
ocupă
de
date
ș
i
pot
crea
ș
i
men
ț
ine,
în
acela
ș
i
timp,
aplica
ț
ii
orientate
spre
date
cu
mai pu
ț
in cod decât în ap lica
ț
iile tradi
ț
ionale [3].
Acest
framework
este
un
ORM
(Object
Relational
Mapper),
reducând
astfel
impedan
ț
a
nepotrivită
între
lumea
orientată
pe
obiecte
de
dezvoltatorii
.NET
framework
ș
i
lumea
bazelor
de
date
rela
ț
ionale.
Entity
Framework
permite
inclusiv
dezvoltatorilor
să
interac
ț
ioneze
direct
cu
modelul
conceptual
al
unei
aplica
ț
ii,
folosind
tehnici
orientate
pe
obiecte familiare.
În
Entity
Framework
se
poate
lucra
cu
datele
aflate
sub
formă
de
obiecte
ș
i
proprietă
ț
i
specifice
unui
anumit
domeniu,
precum
clien
ț
ii
ș
i
adresele
acestora.
Avantajul
acestei
men
ț
ionări
este
dat
de
faptul
că
toate
acestea
se
realizează
fără
a
necesita
preocuparea
cu
tabelele
bazei
de
date,
care
stau
la
fundamentul
coloanelor
ș
i
în
modul
în
care
sunt
stocate
datele.
Framework-ul
folose
ș
te
componenta
de
mapare
pentru
a
transforma
opera
ț
iunile
împotriva
obiectelor,
precum:
crearea,
citirea,
actualizarea
ș
i
ș
tergerea
–
în
opera
ț
iuni
echivalente în baza de date a entită
ț
ii.
2.1.3.2 Entity Framework Core
Microsoft
a
primit
o
mul
ț
ime
de
critici
din
partea
comunită
ț
ii
de
dezvoltare
pentru
programele
Windows
ș
i
a
instrumentelor
lor.
Microsoft,
aflându-se
sub
conducerea
CEO-ului
(director
general)
Satya
Nadella,
a
făcut
un
pas
mare
în
acest
sens
ș
i
a
extins
instrumentele
ș
i framewo rk-ul lor la cross-platform
ș
i open source.
La
început
a
fost
numit
„Entity
Framework
7“,
iar
apoi
i
s-a
schimbat
numele
în
„Entity
–
Framework
Core“,
deoarece
această
ultimă
versiune
nu
este
un
accesoriu
pe
Entity
Framework
original,
ci
mai
degrabă
o
rescriere
completă.
Astfel,
setul
de
caracteristici
pentru
EF
Core
este
foarte
diferit
de
cel
al
EF6,
iar
utilizatorii
existen
ț
i
EF
trebuie
să
fie
con
ș
tien
ț
i
de faptul că trecerea de la una la alta nu este o sarcină mică într-un proiect existent [4].
EF
Core
are
multe
întrebuin
ț
ări
fa
ț
ă
de
EF6.
Vine
cu
o
interfa
ț
ă
îmbunătă
ț
ită
a
liniei
de
comandă,
u
ș
urând
munca
dezvoltatorilor.
Beneficiul
suprem
pentru
dezvoltatori
rămâne
abilitatea de a utiliza framework-ul în mediile non-Windows.
14
Cu
toate
acestea,
EF
Core
are
câte
lipsuri
în
vederea
caracteristicilor
pe
care
le
prevede
EF6.
Astfel,
pentru
a
umple
golurile
sunt
eliberate
actualizările.
Între
timp,
aceste
absen
ț
e
vor
putea
duce
la
frustrare.
Din
acest
motiv,
aceste
considerente
trebuie
luate
în
considerare
înainte
de
a
adopta
EF
Core
pentru
proiect.
Unele
dintre
caracteristicile
care
lipsesc
sunt
următoarele:
rela
ț
iile
de
many-to-many,
fără
o
entitate
„JOIN”
ș
i
încărcarea
înceată (sau lazy loading) .
2.1.3.3 Entity Framework Code-First
No
ț
iunea
de
Entity
Framework
Code-First
a
fost
introdusă
de
Entity
Framework
versiunea
4.1
Code-First.
Această
abordare
este
utilă
în
Domain-Driven
Design
(
o
abordare
a
dezvoltării
de
software
pentru
nevoi
complexe
prin
conectarea
implementării
la
un
model
în
evolu
ț
ie
[5]
).
În
continua re,
prin
acostarea
Code-First,
ne
concentrăm
pe
domeniul
aplica
ț
ie
ș
i
începem
să
creăm
clase
pentru
domeniul
nostru
de
entită
ț
i.
Cu
ajutorul
lui
Database-First
am
crea clase care ar trebui să se potrivească cu design-ul bazei de date [6].
Figura 5. Abordarea Code-First
După
cum
se
observă
în
schema
de
mai
sus,
care
ilustrează
abordarea
Code-First,
API-ul
de
Entity
Framework
va
crea
baza
de
date
bazată
pe
configura
ț
ia
claselor
entită
ț
ilor.
A
ș
adar,
vom
scrie
cod
în
C#
prima
dată,
iar
apoi
Entity
Framework
va
genera
baza
de
date
din codul scris de către noi.
15
2.1.4 ASP .NET Core Web API
ASP
.NET
este
o
platformă
de
dezvoltare
web,
care
beneficiază
de
un
model
de
programare,
o
infrastructură
software
care
cuprinde
diverse
servicii
necesare
pentru
a
construi
aplica
ț
ii web robuste pen tru PC-uri, precum
ș
i pentru dispozitive mobile [7].
Această
platformă
face
parte
din
platforma
Microsoft
.Net
ASP
.NET
ș
i
este
func
ț
ională
pe
partea
de
sus
a
protocolului
HTTP,
utilizând
atât
comenzile
cât
ș
i
politicile
HTTP pentru a stabili o comunicare
ș
i cooperare bilaterală a browser-ului la server.
Scopul
utilizării
platformei
este
pentru
a
produce
aplica
ț
ii
web
interactive,
bazate
pe
date
de
internet.
Aceasta
consistă
într-un
număr
mare
de
controale,
cum
ar
fi
casete
de
text,
butoane
ș
i
etichete
pentru
asamblare,
configurare
ș
i
codul
de
manipulare
pentru
pagini
HTML.
Browserul
trimite
un
formular,
de
pe
web,
la
serverul
web,
iar
serverul
returnează
o
pagină de marcare sau pagină HTML completă ca răspuns.
Activită
ț
ile
utiliza torului
pe
partea
de
client
sunt
transmise
la
server
pentru
a
putea
fi
procesate. Ac
ț
iunile clien tului sunt procesate de server
ș
i urmează declan
ș
area reac
ț
iilor.
Tehnologia
ASP
.NET
func
ț
ionează
pe
.NET
Framework,
care
cuprinde
toate
fun
ț
ionalită
ț
ile
în
materie
de
web.
.NET
Framework
este
conceput
dintr-o
organizare
orientare-obiect.
O
aplica
ț
ie
web
ASP
.NET
este
o
alcătuită
din
pagini.
Astfel,
atunci
când
utilizatorul
solicită
o
pagină
ASP
.NET,
deleagă
IIS
(Internet
Information
Services)
pentru
procesarea paginii în sistemul ASP .NET.
2.1.4.1 Componentele .Net Framework
Common Language Runtime
(CLR)
CLR
se
efectuează
de:
managementul
memorie,
manipularea
excep
ț
iilor,
depanare,
verificarea
de
securitate,
execu
ț
ia
fir,
executarea
de
cod,
codul
de
siguran
ț
ă,
verificare
ș
i
compilare.
Codul
care
este
direct
gestionat
de
CLR,
poartă
numele
de
„cod
gestionat”.
Atunci
când
codul
gestionat
este
compilat,
compilatorul
urmăre
ș
te
convertirea
codului
sursă
într-un
cod
de
CPU,
independent
de
limba
intermediară
(IL).
Codul
IL
urmează
a
fi
compilat
de
un
compilator JIT (Just In Time) în cod nativ, specific CPU-ului.
Class Library .Net Framework
16
Class
Library
.Net
Framework
con
ț
ine
o
bibliotecă
foarte
mare
de
tipuri
reutilizabile:
structuri, clase, interfe
ț
e
ș
i anumite tipuri colective.
Common Language Specification
(Specifica
ț
ii Limba Comună)
Specifica
ț
iile
.NET
pentru
acceptarea
ș
i
integrarea
limbi i
sunt
cuprinse
de
Common
Language Specification.
Common Type System
(Sistemul de tip comun)
În
timpul
rulării,
sistemul
de
tip
comun
oferă
instruc
ț
iuni
despre
declararea,
utilizarea
ș
i gestionarea tipurilor
ș
i despre comunicarea în limba transversal ă.
Metadate
ș
i Ansamblur i
O
informa
ț
ie
binară
care
caracterizează
programul
ș
i
care
poate
fi
stocată
într-un
fi
ș
ier
executabil
portabil
sau
în
memorie,
poartă
numele
de
Metadată.
Ansamblul
reprezintă
o
unitate
logică
care
rezidă
din
manifestul
de
asamblare,
tipul
de
metadate,
codul
IL
ș
i
un
set
de
resurse, de exemplu, fi
ș
ierele de imagine.
LINQ
Folosind
o
sintaxă
care
este
similară
cu
limbajul
de
interogare
SQL,
LINQ
acordă
posibilită
ț
i de interogare a datelor din .NET.
Pentru
a
permite
consumatorilor
să:
creeze,
citească,
actualizeze
ș
i
să
ș
teargă
ordinele,
avem
nevoie
de
a
crea
un
RESTful
Web
API.
Această
ac
ț
iune
se
realizează
prin
implementarea
opera
ț
iilor
CRUD
(
create
=
creare,
read
=
ș
tergere,
update
=
actualizare
ș
i
delete =
ș
tergere
).
17
Figura 6. Opera
ț
iile CRUD
2.1.4.2 Atributele rutelor
ASP.NET
Core
oferă
un
atribut
puternic
rutelor
[8].
Astfel,
se
poate
defini
o
rută
de
nivel
superior
la
clasa
controller,
prin
care
se
reiese
un
traseu
comun
în
care
ac
ț
iunile
se
pot
extinde asupra lui.
Atributul
Route
este
reprezentat
printr-un
ș
ablon
„api
/
[Controller]“.
Conven
ț
ia
specială
„[Controller]“
ac
ț
ionează
ca
un
substituent
pentru
controler
în
context.
Îndreptând
aten
ț
ia
asupra
HttpGet,
se
observă
că
oferim
un
argument
ș
ablon
de
„{id}“.
Astfel
reiese
un
traseu
HTTP
Get
care
se
aseamănă
cu
„api/
comenzi/
1”
(în
cazul
în
care
id-ul
este
o
variabilă).
HTTP GET
– Cerere (Request)
În
colec
ț
ia
noastr ă
de
comenzi,
aproape
fiecare
comandă
are
un
câte
un
identificator
unic. Ac
ț
iunea care se oc upă de această cerere, poate fi scrisă astfel:
HttpGet("api/models/{id}") // api/models/8
Acest
atribuit
va
pregăti
cadrul
ASP
.NET
Core
pentru
tratarea
ac
ț
iunii
ca
un
handler
al
verbului
HTTP
GET
ș
i
să
se
ocupe
de
rutare.
În
continuare,
noi
vom
furniza
un
ș
ablon,
ca
endpoint
de
argument
pentru
atribut.
Pentru
traseu,
ș
ablonul
oferă
cadrul
care
se
va
utiliza
pentru
a
se
potrivi
cu
cererile
primite.
Valoarea
sec
ț
iunii
{id}
din
cadrul
acestui
ș
ablon,
va
corespunde por
ț
iunii trase ului, care este parametrul „id”.
HTTP POST
– Cerere (Request)
Un HTTP Post este o cerere de a crea o resursă. Ac
ț
iunea poate fi scrisă astfel:
HttpPost("api/models")
O
diferen
ț
ă
rapid
vizibilă
fa
ț
ă
de
Get,
este
că
la
ac
ț
iunea
Post
nu
avem
nevoie
de
un
„{id}”
în
ș
ablonul
nostru ,
a
ș
a
cum
ni
se
dă
întregul
obiect
coman dă
prin
corpul
cererii
HTTP
Post.
O
altă
deosebire
este
dată
de
cuvinte
cheie
care
trebuiesc
folosite
în
cadrul
programului:
async pentru a permite utilizarea await.
HTTP PUT
– Cerere (Request)
18
HTTP
Put
reprezintă
o
solicitare
pentru
a
actualiza
o
resursă.
Aceste
verb
are
calitatea
de
a
fi
idempotent.
Aceasta
înseamnă
că,
în
cazul
în
care
are
loc
o
cerere
HTTP
Put,
orice
cerere
care
urmează
HTTP
Put
cu
aceea
ș
i
sarcină
utilă,
ar
avea
ca
rezultat
acela
ș
i
răspuns.
Altfel
spus,
mai
multe
cereri
HTTP
Put
egale,
sunt
nedăunătoare,
iar
resursa
este
afectată
numai pentru prima solicitare.
Acest
verb
seamănă
foarte
mult
cu
verbul
HTTP
Put,
în
care
atributele
ASP
.NET
Core sunt împreună perechi. Ac
ț
iunea este scrisă astfel:
HttpPut("api/orders/{id}")
HTTP DELETE
– Cerere (Request)
Ultima
opera
ț
ie
din
CRUD
este
opera
ț
ia
de
ș
tergere,
iar
aceasta
este
expusă
prin
ac
ț
iunea
care
se
ocupă
de
cererea
HTTP
Delete.
În
urma
acestei
ac
ț
iuni,
rezultă
ș
tergerea
înregistrarea de la ID-ul dat. Ac
ț
iunea este scrisă astfel:
HttpDelete("api/models/{id}")
2.1.5 Limbajul de programare C#
Limbajul
C#
este
un
limbaj
de
programare
creat
de
Microsoft
la
începutul
anilor
2000
ș
i
care
a
apărut
pentru
îndeplinirea
cerin
ț
ele
lumii
moderne,
interconectate.
Acest
limbaj
derivă
din
C
ș
i
C++,
(figura
2)
de
unde
putem
spune
că
este
un
limbaj
de
programare
simplu
ș
i
orientat
pe
obiect.
C#
utilizează
arhitectura
.NET
ce
conferă
o
portabilitate
mare
a
codului
ș
i
permite
programarea
în
limbaj
mixt.
Ca
ș
i
inova
ț
ii,
permite
o
progresare
a
componentelor
software,
foarte
necesare
de
pildă,
în
medii
distribuite.
Astfel,
acest
limbaj
se
poate
caracteriza ca fiind
ș
i orie ntat pe componente, nu numai orientat pe obiect.
Momentan,
C#
reprezintă
una
dintre
cele
mai
populare
limbaje
de
programare.
Este
utilizat de milioane de dezvoltatori din întreaga lume. [9]
19
Figura 7: Arborele genealogic C#
2.1.6.1 Programarea orientată pe obiect
Programarea
orientată
pe
obiecte
este
succesorul
programării
procedurale
(structurale).
Procedurile
de
programare
descriu
programele
ca
fiind
grupuri
de
unită
ț
i
de
cod
reutilizabile
(proceduri)
care
definesc
parametrii
de
intrare
ș
i
ie
ș
ire.
Programele
procedurale
constau în proceduri care se invocă reciproc.
Problema
cu
programarea
procedurală
este
că
reutilizarea
codului
este
grea
ș
i
limitată.
Nu
există
o
modalitate
u
ș
oară
de
a
lucra
cu
structuri
de
date
abstracte
cu
implementări
diferite, precum în programarea orientată pe obiect.
Abordarea
orientată
spre
obiecte
se
bazează
pe
paradigma
că
fiecare
program
func
ț
ionează
cu
date
care
descriu
entită
ț
i
(obiecte
sau
evenimen te).
Avantajele
principale
ș
i
obiective
ale
OOP
sunt
de
a
mării
complexitatea
ș
i
viteza
software-ului,
pentru
a
putea
fi
dezvoltat
mai
u
ș
or.
OOP
permite
reutilizarea
mai
u
ș
oară
a
codului
prin
aplicarea
unui
set
de
reguli. Aceasta sunt: mo
ș
tenirea, încapsularea, abstractizarea
ș
i polimorfismul.
Mo
ș
tenirea
este
principiul
fundamental
al
OOP-ului.
Prin
mo
ș
tenire,
se
în
ț
elege
crearea
unei
clase
dintr-o
clasă
existentă
deja,
astfel
încât
noua
clasă
va
fi
o
versiune
specializată
a
clasei
existente.
Toate
caracteristicile
clasei
de
bază
vor
fi
dobândite
de
clasa
derivată.
Se
poate
crea
o
ierarhie
de
clase,
în
care
o
clasă
derivată
poate
mo
ș
teni
o
clasă
de
bază, din care să derive alte clase. Acest principiu acordă eficien
ț
ă prin reutilizarea codului.
Încapsularea
îmbină
codul
ș
i
datele
pe
care
acesta
le
manipulează,
într-un
singur
obiect.
Aceasta
permite
programatorului
implementarea
abstractizării
dintr-un
program,
prin
intermediul specificatorilor.
20
Abstractizarea
detonă
caracteristicile
esen
ț
iale
ș
i
necesare
ale
unui
obiect
care
îl
deosebe
ș
te
de
toate
celelalte
tipuri
de
obiect
ș
i
permite
afi
ș
area
acestora
în
afara
clasei.
Accesarea acestora poate fi publică, privată sau protected.
Polimorfismul
permite
tratarea
obiectelor
unei
clase
derivate
ca
obiecte
ale
clasei
sale
de bază. Acesta reprezintă o capacitate de a redefini metode pentru clasele derivate.
Principiile OOD
(object orientated design)
Programarea
structurală
ș
i
programarea
orientată
pe
obiect
au
avut
un
rol
foarte
important
în
dezvoltarea
metodologiilor
de
a
scrie
cod
cât
mai
eficient
posibil.
Totu
ș
i,
a
devenit
dificilă
scrierea
unui
program
care
nu
are
aspectul
exterior
atât
al
programării
structurale
cât
ș
i
al
programării
orientate
pe
obiect.
În
acest
scop,
s-a
dezvoltat
designul
orientat
pe
obiect
care
reprezintă
un
proces
de
planificare
a
unui
sistem
de
obiecte,
interac
ț
ionând
în
scopul
rezolvării
unei
probleme
software.
Este
o
abordare
a
designe-ului
software.
Cele
5
principii
OOD-ului
sunt:
principiul
responsabilită
ț
ii
unice,
principiul
deschis-închis,
principiul
de
substitu
ț
ie
al
lui
Liskov,
principiul
de
segregare
a
interfe
ț
ei
ș
i
principiul
inversării
dependen
ț
ei.
Aceste
principii
mai
sunt
denumite
ca
fiind
ș
i
principiile
SOLID datorită denumirii fiecărui principiu care urmează să fie descris mai jos.
Primul
principiu
(in
engleză
The
Single
Responsibility
Principle)
spune
că
o
clasă
ar
trebui
sa
aibă
doar
un
singur
motiv
pentru
care
să
se
schimbe.
Dacă
o
clasă
are
mai
multe
responsabilită
ț
i,
atunci
responsabilită
ț
ile
devin
cuplate.
Schimbările
la
o
singură
responsabilitate pot afecta sau inhiba capacitatea clasei de a se întâlni cu ceilal
ț
i.
Al
2
–
lea
principiu
(The
Open
Closed
Principle)
sugerează
că
o
clasă
trebuie
să
fie
deschisă
pentru
extindere
ș
i
închisă
pentru
modificări.
De
exemplu,
atunci
când
se
schimbă
cerin
ț
ele
este
indicat
să
extindem
comportamentul
acestora
prin
adăugarea
unui
cod,
nu
prin
schimbarea codului vechi care deja func
ț
ionează.
Principiul
de
substitu
ț
ie
al
lui
Liskov
(The
Liskov
Sustitution
Principle)
este
introdus
de
Barbara
Liskov
în
1987.
Acesta
reprezintă
faptul
că
func
ț
iile
care
utilizează
pointeri
sau
referin
ț
e
la
clasele
de
bază,
trebuie
să
utilizeze
obiecte
din
clasele
derivate,
iar
clasele
care
au
fost mo
ș
tenite să nu cuno ască acest lucru.
Principiul
4
de
segregare
al
interfe
ț
ei
(The
Interface
Segretation
Principle)
recomandă
scrierea
a
cât
mai
multor
interfe
ț
e
cu
cu
granula
ț
ie
fină,
care
sunt
specifice
clientului.
Aceasta
21
afirmă
că
modulele
care
încapsulează
politica
de
nivel
înalt
nu
ar
trebui
să
depindă
de
modulele care implementează detalii.
Ultimul
principiu
din
listă
(în
engleză
The
Dependency
Inversion
Principle)
redă
faptul
că
rela
ț
iile
de
depe nden
ț
ă
de
la
nivel
înalt,
la
modulele
de
dependen
ț
e
de
nivel
inferior,
sunt
inversate,
ceea
ce
face
ca
modulatele
de
nivel
înalt
să
fie
independente
de
detaliile
de
implementare
a
modulelor
de
nivel
inferior.
Modulele
de
nivel
înalt
nu
trebuie
să
depindă
de
cele
de
nivel
scăzut,
amândouă
trebuind
să
depindă
de
abstractizare,
iar
abstractizarea
nu
ar
trebui să depindă de detalii. [10]
2.2 Aplica
ț
ia client
Aplica
ț
ia
client
(front-end-ul)
unui
site
web
(aplica
ț
ie
web
sau
mobile)
este
partea
pe
care
utilizatorul
o
vede
ș
i
cu
care
interac
ț
ionează
direct.
Acesta
gestionează
tot
ceea
ce
vizualizează
utilizatorii
prima
dată
în
browser
sau
aplica
ț
ie.
Provocarea
aferentă
dezvoltării
de
front-end
este
că
instrumentele
ș
i
tehnicile
folosite
pentru
a
crea
partea
pe
care
o
vede
ș
i
cu
care
interac
ț
ionează
utilizatorul
în
cadrul
unui
site,
se
modifică
constant,
iar
astfel
dezvoltatorul
trebuie
să
fie
responsabil
în
permanen
ț
ă
cu
privire
la
modul
în
care
se
dezvoltă
domeniul.
Obiectivul
de
a
proiecta
un
site
este
de
a
se
asigura
ca
atunci
când
utilizatorii
vor
deschide
site-ul,
ace
ș
tia
vor
vedea
doar
informa
ț
iile
necesare,
ce
se
doresc
afi
ș
ate,
într-un
format
care
este
u
ș
or
de
citit
ș
i
relevant.
Provocarea
cea
mare
în
acest
demers
vin
de
la
varietatea
de
dispozitive
cu
diferite
dimensiuni
ș
i
rezolu
ț
ii
ale
ecranului,
for
ț
ând
astfel
designerului
să
ia
în
considerare
aceste
aspecte
la
proiectarea
site-ului.
Este
nevoie
ca
ace
ș
tia
să
se
asigure
că
site-ul
lor
apare
corect
în
diferite
browsere
ș
i
sisteme
de
operare,
necesitând
astfel o planificare atentă de partea dezvoltatorului.
2.2.1 Framework-uri
Folosirea
unui
framework
(cadru)
pentru
a
construi
front-end-ul
are
multe
avantaje.
A
ș
a
numitele
„CSS
fram eworks”
sunt
pachete
care
con
ț
in
coduri
prescrie,
standardizate
în
fi
ș
iere
ș
i
foldere.
Acestea
ne
oferă
o
baza
de
la
care
să
încep em
să
construim,
permi
ț
ând
flexibilitatea
cu
designul
final.
De
obicei,
front-end
framework-urile
con
ț
in
următoarele
componente:
22
●
o re
ț
ea car e facilitează organizarea elementelor de design ale site-ului web
●
stiluri
de
fonturi
definite
ș
i
dimensiuni
care
variază
în
acord
cu
func
ț
ia
sa
(tipografie diferită pentru titluri versus paragrafe etc.)
●
componente
pre-construite
ale
site-ului,
cum
ar
fi
panouri
laterale,
butoanele
ș
i
barele de navigare
Câteva
dintre
avantajele
folosirii
framework-urilor
în
front-end
sunt,
în
loc
de
a
porni
codul de la zero sunt următoarele:
●
economisirea
de
timp
–
evident,
dacă
se
începe
scrierea
fiecărei
linii
de
cod
de
unul
singur,
va
dura
mult
mai
mult
pentru
a
lansa
site-ul.
Framework-urile
ne
ajută să începem cu elementele de bază
●
adăugarea
unor
componente
de
bază,
la
care
nu
am
avea
acces
altfel.
Este
în
avantajul
nostru
să
avem
op
ț
iunea
de
a
aborda
un
alt
buton
sau
două,
fără
a
mai necesita vreun efort în plus
●
cunoa
ș
terea
sigură
a
codului
că
într-adevăr
func
ț
ionează.
În
loc
să
petrecem
mult
timp
pentru
a
ne
asigura
că
propriul
cod
nu
func
ț
ionează
(sau
nu
este
compatibil
cu
60%
din
browserele
web),
vom
ș
ti
că
utilizăm
codul
func
ț
ional
presetat
Câteva
dintre
cele
mai
populare
framework-uri
folosite
de
developerii
de
front-end
sunt:
Angular,
React,
Vut
etc.
În
continuare
voi
prezenta
framework-ul
Angular,
deoarece
pe
acesta l-am ales eu să lucrez la aplica
ț
ia de licen
ț
ă.
2.2.2 Mediul de dezvoltare
Programul
folosit
pentru
dezvoltarea
aplica
ț
ii
client
este
Visual
Studio
Code.
Acesta
integrează
simplitatea
unui
editor
de
cod
sursă
cu
instrumente
puternice
de
dezvoltare,
precum
completarea
ș
i
depanarea
codului.
Acesta
este
disponibil
pentru
mai
multe
sisteme
de
operare: macOS, Linux
ș
i Windows.
2.2.3 Angular Framework
Angular
este
un
tip
de
aplica
ț
ie
open
source
bazată
pe
TypeScript,
condusă
de
echipa
Angular
la
Google
ș
i
de
o
comunitate
de
persoane
ș
i
corpora
ț
ii.
Acesta
este
o
rescriere
completă
de
la
aceea
ș
i
echipă
care
a
construit
AngularJS
[11].
Angular
încurajează
23
dezvoltatorii
să
construiască
aplica
ț
ii
care
să
poată
fi
utilizate
pe
web,
mobil
sau
chiar
ș
i
pe
desktop.
Acest
framework
ne
permite
să
scriem
cu
u
ș
urin
ț
ă
SPA
(Single
Page
Applications
–
o
aplica
ț
ie
web
interac
ț
ionează
cu
utilizatorul
prin
rescrierea
dinamică
a
paginii
curente).
Dispune
de
func
ț
ii
precum:
legarea
datelor,
detectarea
modificărilor,
formulare,
rutare
ș
i
navigare
ș
i o implementa re HTTP.
2.3.1.1 Structura Angular
În continuare voi prezenta câteva din principalele fi
ș
iere din Angular.
e2e-directory
Acest
director
este
folosit
doar
pentru
teste.
Este
utilizat
pentru
a
crea
ș
i
configura
o
testare
end-to-end
(e2e).
Pe
scurt,
prin
testarea
de
la
un
capăt
la
celălalt,
se
testează
interac
ț
iunea
dintre
păr
ț
i
separate
ale
aplica
ț
iei,
inclusiv
apelurile
către
bacl-end.
În
principiu,
aplica
ț
ia va fi testată a
ș
a cum o va folosi utilizatorul.
node_modules-directory
Atunci
când
managerul
de
pachete
instalează
toate
dependen
ț
ele
pe
ma
ș
ina
noastră,
le
procesează
pe
toate
la
fel
în
directorul
node_modules.
În
mod
normal,
dimensiunea
acestui
director ajunge pe la sute de magaocte
ț
i.
src-directory
Întregul cod sursă este localizat în acest director, în directorul sursă.
src/app-directory
În
interiorul
directorului
de
aplica
ț
ii,
se
plasează
toate
fi
ș
ierele
care
modifică
aspectul
sau
func
ț
ionalitatea
aplic a
ț
iei.
Acestea
includ
componentele,
modulele,
serviciile,
gardienii
ș
i
conductele (pipes).
Angular
a
generat
deja
o
componentă
numită
AppComponent
în
acest
scop.
Se
compune
din
trei
fi
ș
iere:
app.component.ts,
app.component.html
ș
i
app.component.css.
De
asemenea a creat un nou modul: AppModule (app.module.ts).
src/assets-directory
24
În
acest
director
se
pot
plasa
bunurile
necesare
pentru
aplica
ț
ie,
cum
ar
fi:
imagini,
iconi
ț
e, fonturi etc. Acest e fi
ș
iere se vor difuza împreună cu aplic a
ț
ia creată.
src/assets-directory
Aici se păstrează fi
ș
iere care definesc variabilele din aplica
ț
ie
src/index.html
Acesta
reprezintă
fi
ș
ierul
rădăcină
al
aplica
ț
iei,
deoarece
este
singurul
fi
ș
ier
html,
livrat
în
browser.
Con
ț
ine
toate
meta
informa
ț
iile
din
aplica
ț
ie.
De
asemenea
trebuie
să
con
ț
ină
eticheta
elementu lui
rădăcină
al
aplica
ț
iei
din
interiorul
corpului.
Valoarea
implicită
este:
<app-root></app-root>.
Pe
lângă
acest
aspect,
în
interiorul
fi
ș
ierului
se
poate
scrie
cod
html normal.
src/main.ts
Fi
ș
ierul
principal
.ts
este
punctul
de
intrare
al
aplica
ț
iei.
Tot
ceea
ce
se
află
în
interiorul
acestui
fi
ș
ier
este
apelul
de
func
ț
ii
pentru
a
bootstra
aplica
ț
ia
în
sine.
Aici
se
poate
specifica modul în care modulul angular ar trebui să fie boostrapat.
src/styles.css
Aceasta este foaia de stil globală. Stilurile definite aici sunt aplicate întregii aplica
ț
ii.
src/test.ts
Seamănă
cu
main.ts,
doar
că
este
pentru
testare.
Con
ț
ine
configura
ț
ia
suplimentară
necesară pentru unit teste.
scr/tsconfig.app.json
Acesta
este
un
fi
ș
ier
de
configurare
de
tip
script,
care
include
informa
ț
ii
despre
modul
în care TypeSript trebuie să fie compilat în JavaScript.
scr/tsconfig.spec.json
La
fel
ca
tsconfig.app.json
,
această
configura
ț
ie
se
aplică
numai
atunci
când
se
efectuează teste.
25
angular-cli.json
Acesta
este
fi
ș
ierul
de
configurare
principal
pentru
angular-cli.
În
interiorul
lui
se
poate
schimba
aproape
fiecare
comportament
implicit
al
CLI.
Acesta
este
util
dacă
se
dore
ș
te
altă
structură
de
directoare.
Apoi
îi
putem
spune
CLI-ului
unde
sunt
localizate
fi
ș
ierele
esen
ț
iale, cum ar fi
main. ts.
package.json
Fi
ș
ierul
stochează
toate
metadatele
despre
aplica
ț
ie.
Acesta
con
ț
ine
numele,
versiunea
ș
i
licen
ț
a
proiectului.
De
asemenea
con
ț
ine
informa
ț
ii
despre
toate
dependen
ț
ele
aplica
ț
iei,
ceea ce o face oarecum importantă.
tsconfig.json
Reprezintă
un
fi
ș
ier
de
configurare
typescript
(un
superset
de
JavaScript,
care
oferă
în
primul
rând
tipărire
op
ț
ională
statică,
clase
ș
i
interfe
ț
e),
care
include
informa
ț
ii
despre
modul
în care TypeScript trebuie să fie compilat în JavaScript.
2.3.1.2 Componentele Angular
Pentru
a
facilita
munca
depusă
în
construirea
aplica
ț
iei,
Angular
vine
cu
o
structură
pentru
aranjarea
codului
prin
adăugarea
de
blocuri
mici
care
odată
împreună
aranjate,
rezultă
p aplica
ț
ie frumoasă
ș
i func
ț
ională.
Componentele sunt compuse din trei fi
ș
iere: TypeScript, HTML
ș
i CSS.
26
Figura 8. Componentele Angular
Fi
ș
ierul TypeScript
Con
ț
ine
o
clasă ,
care
este
marcată
ca
o
componentă
de
către
decoratorul
@component.
Un
decorator
este
reprezentat
de
metadata
(date
despre
date)
despre
clasă.
Cu
decoratorul
@component,
această
clasă
ar
trebui
considerată
o
componentă.
Acest
fi
ș
ier
este
inima componentei, deoarece loca
ț
ia celorlalte două fi
ș
iere este descrisă aici.
Când
privim
fi
ș
ierele
angular,
identificarea
componentelor
este
foarte
simplă,
deoarece fiecare dezvoltator urmăre
ș
te conven
ț
ia de numire (naming convention).
Fi
ș
ierul HTML-Templa te
Al
doilea
fi
ș
ier
este
fi
ș
ierul
template
(
ș
ablon).
Tot
ceea
ce
are
de-a
face
cu
afi
ș
area
de
lucruri pe ecra, ar trebui sa fie scris în interiorul acestui template.
Fi
ș
ierul CSS
Ultimul
fi
ș
ier,
este
fi
ș
ierul
care
ț
ine
de
stil.
Acesta
con
ț
ine
stilurile
CSS.
Stilurile
unei
componente
sunt
definite
în
mod
implicit,
ceea
ce
înseamnă
că
dacă
avem
două
componente
care
au
ambele
clasa
css
„container”
(care
ar
trebui
să
arate
diferit)
nu
interferează
una
cu
cealaltă.
Ș
i de data aceast a, fi
ș
ierul urmează aceea
ș
i conven
ț
ie de nume.
Înainte
de
a
putea
cere
de
fapt
o
instan
ț
ă
a
unei
clase/
servicii
în
componen
ț
a
noastră,
trebuie
să
o
declarăm
undeva.
Aceasta
se
face
într-un
modul,
de
exemplu
în
modulul
de
aplica
ț
ii.
27
2.3.1.3 Injec
ț
ia de dependen
ț
ă în Angular
Injectarea
de
dependen
ț
ă
(sau
depedency
injection)
ne
permite
să
distribuim
cu
u
ș
urin
ț
ă
servicii
în
întreaga
aplica
ț
ie.
Astfel,
în
loc
să
adăugăm
o
instan
ț
ă
a
unei
clase
în
fiecare componentă, o cerem în constructorul componentelor noastre.
Framework-ul
Angular
va
avea
grijă
de
acesta
ș
i
va
furniza
instan
ț
a
solicitată
a
acelei
clase
la
timpul
de
execu
ț
ie.
Acest
aspect
ne
oferă
o
flexibilitate
mai
mare
ș
i
ne
permite
să
schimbăm rapid o dependen
ț
ă a tuturor componentelor.
2.3.1.4 Limbajele folosite în Angular
Principalele limbaje de cod folosite în Angular sunt: TypeScript, HTML
ș
i CSS.
TypeScript
TypeScript
este
un
superset,
o
extensie
de-a
limbajului
JavaScript.
TypeScript
este
un
limbaj
puternic
orientat
spre
obiect.
A
fost
proiectat
de
designerul
C#
(Anders
Hejilsberg).
Este atât un limbaj, cât
ș
i un set de instrumente [12].
JavaScript
este
una
dintre
tehnologiile
de
bază
ale
World
Wide
Web-ului.
Potrivit
unui
sondaj,
JavaScript
a
fost
limbajul
de
top
printre
dezvoltatorii
de
front-end
ș
i
nu
pare
să-
ș
i
piardă
popularitatea .
De
aceea,
astăzi
există
atât
de
multe
framework-uri
JavaScript.
Componentele
TypeScript
sunt:
limbajul
–
cuprinde
sintaxa,
cuvintele
cheie
ș
i
adnotările
de
tip
(type
annotations,
ajută
compilatorul
la
verificarea
tipurilor
ș
i
ajută
la
evitarea
erorilor
care se ocupă de tipurile de date)
●
compilatorul
TypeScript
–
converte
ș
te
instruc
ț
iunile
scrise
în
TypeScrip
la
echivalentul său JavaScript
●
serviciul
TypeScript
Language
–
expune
un
strat
suplimentar
în
jurul
miezului
de
compilare
de
bază,
care
sunt
aplica
ț
iile
asemănătoare
editorului.
Acest
serviciu
acceptă
setul
comun
al
unei
opera
ț
ii
tipice
de
editare,
cum
ar
fi
completarea
instruc
ț
iunilor, for matarea codului
ș
i a descrierii, colorare a etc.
28
Figura 9. Componentele TypeScript
HTML
(
Hyper Text Markup Language
)
Acesta reprezintă unul dintre cel mai utilizat limbaj pentru scrierea paginilor Web.
➔
Hyper Text – se referă la modul în care paginile web (documentele HTML) sunt legate
între ele. A
ș
adar, link-ul ( legătura) disponibil pe o pagină web se nume
ș
te hyper text
➔
Markup Language – după cum îi spune
ș
i numele, este un limbaj de marcare, ceea ce
înseamnă că folosirea codului HTML este pentru a „marca” un document text cu etichete care
îi spun unui browser web cum să-l structureze pentru a putea fi afi
ș
at Ini
ț
ial, codul HTML
[13]
La început, codul HTML a fost dezvoltat cu inten
ț
ia de a defini structura
documentelor precum titluri, paragrafe, liste
ș
i a
ș
a mai departe, pentru a favoriza schimbul de
informa
ț
ii
ș
tiin
ț
ifice între cercetători. Însă, acum acest limbaj este folosit pe scară largă chiar,
pentru a formata pagini web cu ajutorul tag-urilor diferite disponibile în limbajul HTML.
CSS
(Cascading Style Sheets)
CSS
este
un
limbaj
de
design
simplu,
destinat
simplificării
procesului
de
prezentare
a
paginilor
web.
Acesta
se
ocupă
de
aspectul
unei
pagini
web.
Prin
utilizarea
CSS,
se
poate
controla
culoarea
textului,
stilului
ș
i
a
fonturilor,
distan
ț
a
dintre
paragrafe,
modul
în
care
sunt
dimensionate
ș
i
dispuse
coloanele,
ce
imagini
de
fond
sau
culori
sunt
utilizate,
modelele
de
aspect,
varia
ț
iile
de
afi
ș
are
pentru
diferite
dispozitive
ș
i
dimensiunile
ecranului,
precum
ș
i
o
varietate
de
alte
efecte
[14].
CSS
este
unul
dintre
limbajele
care
se
înva
ț
ă
u
ș
or
ș
i
oferă
un
control bun asupra prezentării unui document HTML.
29
Câteva dintre avantajele CSS sunt:
●
salvează
timp
–
se
poate
scrie
CSS
o
dată,
iar
apoi
codul
poate
fi
reutilizat
în
mai
multe
pagini HTML
●
încărcarea
rapidă
a
paginilor
–
prin
utilizarea
CSS,
nu
este
necesară
scrierea
tag-urilor
HTML
de
fiecare
dată.
Se
poate
scrie
o
regulă
CSS
a
unei
etichete
ș
i
apoi
aplicată
la
toate
apari
ț
iile etichetei. Astfel , prin mai pu
ț
in cod scris reies perioade de descărcare mai rapide
●
între
ț
inere
u
ș
oară
–
pentru
a
face
o
schimbare
globală,
se
modifică
simplu
stilul
ș
i
toate
elementele paginii web vor fi actualizate automat
●
compatibilitatea
cu
mai
multe
dispozitive
–
prin
paginile
de
stil
se
permite
optimizarea
con
ț
inutului
pentru
mai
multe
tipuri
de
dispozitive.
Prin
utilizarea
aceluia
ș
i
document
HTML,
diferite versiuni ale unui site web pot fi prezentate pentru dispozitive portabile
2.3 Problema alocării de resurse
Alocarea
resurselor
este
o
problemă
frecventă
care
necesită
luarea
deciziilor.
Multe
tipuri
de
resurse
comune
(cum
ar
fi
timpul,
financiarul,
umanul,
calculatul,
materialele
etc.)
sunt
alocate
într-o
manieră
colaborativă
pentru
a
concilia
opinii
divergente
ș
i
pentru
a
satisface
criteriile
de
bunăstare
sau
corectitudine.
Această
problemă
apare
în
multe
situa
ț
ii
din
lumea
reală
atunci
când
un
grup
trebuie
să
împartă
profiturile
sau
activele
de
afaceri,
resursele naturale sau artificiale, foaia de lucru etc.[15]
Alocarea
resurselor
este
văzută
ca
o
problemă
colectivă
de
luare
a
deciziilor
de
agregare
a
preferin
ț
elor
individuale
pentru
o
alternativă
de
alocare
a
resurselor
între
membrii
unui
grup.
Resursele
pot
fi
o
singură
resursă
divizată
(omogenă
sau
eterogenă)
sau
multiple
resurse
indivizibile
(o
singură
unitate
sau
mai
multe
unită
ț
i,
care
pot
fi
sau
nu
pot
fi
distribuite). [15]
În
multe
probleme
de
optimizare
se
urmăre
ș
te
alocarea
unui
set
limitat
de
resurse
a
unui
grup
de
persoane
cu
cerin
ț
e.
Astfel
de
alocări
pot
fi,
în
mod
firesc,
văzute
ca
vectori,
cu
o singură coordonată reprezentând fiecare individ.
30
2.3.1
Comportamentul
strategic
atunci
când
alocăm
bunuri
indivizibile
secven
ț
ial
Există
multe
situa
ț
ii
în
care
trebuie
să
împăr
ț
im
elemente
între
agen
ț
i.
Am
putea
dori
să
împăr
ț
im
locurile
la
studen
ț
i
în
cadrul
cursurilor
sau
jucători
în
echipe.
Există
o
varietate
de
de
mecanisme
folosite
pentru
a
folosi
această
divizare
fără
„plă
ț
i
secundare”.
De
exemplu,
ș
coala
de
afaceri
Hardva rd
folose
ș
te
mecanismul
Draft
(proiectar e)
pentru
alocarea
cursurilor
pentru
studen
ț
i
(Budish
ș
i
Cantillon
2007).
Acest
mecanism
generează
ordinea
priorită
ț
ii
studen
ț
ilor
uniform,
la
întâmplare.
Cursurile
sunt
apoi
alocate
studen
ț
ilor
în
mai
multe
runde.
Fiecare
elev
este
alocat
cursului
preferat,
acesta
fiind
încă
disponibil
pentru
a-
ș
i
schimba
ordinea
priorită
ț
ii.
Din
păcate,
acest
mecanism
nu
este
dovadă
a
strategiei,
studen
ț
ii
trebuind
să-
ș
i aleagă în mod strate gic cursurile (Budish
ș
i Cantillon 2007).
Bourvet
ș
i
Lang
(2011)
iau
în
considerare
aspectele
computa
ț
ionale
ale
unei
proceduri
de
alocare
secven
ț
ială
(studiată
mai
devreme
de
Brams
ș
i
al
ț
ii)
care
generalizează
mai
multe
aspecte
ale
mecanismului
Draft.
Procedura
este
parametrizată
de
o
politică,
o
secven
ț
ă
în
care
agen
ț
ii
se
rotesc
pe
rând
pentru
a
alege
elemente.
De
exemplu,
la
fel
ca
ș
i
în
Draft,
cu
doi
agen
ț
i
ș
i
patru
obiecte,
politica
1221
dă
prima
ș
i
ultima
alegere
primului
agent,
iar
celui
de-al
doilea agent îi repartizează al doilea
ș
i al treilea obiect.
O
perspectivă
bună
a
acestui
mecanism
este
că
preferin
ț
ele
agen
ț
ilor
nu
trebuie
să
fie
provocată.
Bouveret
ș
i
Lang
î
ș
i
asumă
faptul
că
agen
ț
ii
au
utilită
ț
i
adi
ț
ionale
date
de
o
func
ț
ie
comună
de
notare
(de
exemplu,
scoruri
Borda
sau
lexicografice).
Când
agen
ț
ii
au
aceea
ș
i
preferin
ț
ă
de
ordonare,
toate
politicile
dau
aceea
ș
i
sumă
a
utilită
ț
ilor,
iar
mecanismul
este
dovada
strategiei.
Atunci
când
agen
ț
ii
au
comenzi
de
preferin
ț
e
diferite,
comportamentul
strategic
poate
fi
profitabil.
Scopul
acestei
lucrări
este
de
a
studia
aspectele
computa
ț
ionale
ale unui astfel de comportament strategic.
Formal,
avem
un
set
G
de
m
elemente
pe
care
le
împăr
ț
im
între
n
agen
ț
i.
Agentul
i
reprezintă preferin
ț
ele ei prin ordinul liniar Pi peste G. O politică:
O = o1o2….. om
∈
{1, . . . , n}
m
define
ș
te
un
mecanism
de
alocare
în
a
cărui
etapă,
un
agent
selectează
un
element.
Cu
doi
agen
ț
i
scriem
alocarea
(P1,
P2,
O),
construirea
fiind
cu
O,
având
în
vedere
ordinele
de
preferin
ț
ă
P1
ș
i
P2
ș
i
presupunând
că
agen
ț
ii
sunt
adevăra
ț
i.
Prin
aceasta,
în
fiecare
etapă
un
31
agent
î
ș
i
alege
cel
mai
preferat
element
încă
disponibil.
Noi
scriem
rev(P1)
pentru
a
inversa
(rev
de
la
reverse
=
a
inversa)
preferin
ț
ele
P1
ș
i
rev
(O)
pentru
inversarea
ordinului
de
alocare
în politica O.
[16]
Exemplu 1
Fie G = {1,……6}
ș
i O = 1 2121.
Preferin
ț
ele agentului P1 = 1 > 2 > 3 > 4 > 5 > 6
Preferin
ț
ele agentului P2 = 4 > 6 > 2 > 1 > 5 > 3
Obiectul alocat în fiecare rundă a alocării (P1, P2, O) este ilustrată în tabela următoare
O
1
2
1
2
2
1
obiect
1
4
2
6
5
3
2.3.1.1 Comportamentul strategic
Bouveret
ș
i
Lang
(2011)
iau
în
considerare
situa
ț
iile
în
care
agentul
încearcă
să
ob
ț
ină
o
alocare
mai
bună
prin
alegerea
strategică,
presupunând
că
to
ț
i
ceilal
ț
i
agen
ț
i
aleg
cu
sinceritate.
Cu
ajutorul
scorurilor
lexicografice,
ace
ș
tia
arată
că
strategia
optimă
pentru
un
agent
dat
cu
o
anumită
politică
poate
fi
calculată
în
timp
polinomial,
presupunând
că
al
ț
i
agen
ț
i
aleg
cu
sinceritate .
Ace
ș
tia
consideră
că
aflarea
strategiei
optime
este
NP-hard
pentru
scorurile
Borda
(o
familie
e
metode
electorate
cu
un
singur
câ
ș
tigător,
în
care
alegătorii
au
op
ț
iuni
sau
candida
ț
i
în
ordinea
preferin
ț
elor).
Se
pune
problema
ca
un
agent
poate
să
aleagă
strategic
în
timp
ce
ceilal
ț
i
nu
o
fac.
Alocarea
secven
ț
ială
se
pretează
la
o
analiză
teoretică
a
jocului
unde
căutăm
un
echilibru
Nash
nu
î
ș
i
poate
îmbunătă
ț
ii
alocarea
prin
abaterea
unilaterală de la strategia de alegere.
Vedem
procedura
de
alocare
ca
un
joc
secven
ț
ial
repetat
în
care
to
ț
i
agen
ț
ii
au
informa
ț
ii
complete
despre
ordinarea
preferin
ț
elor
celorlal
ț
i
agen
ț
i.
Atunci
când
o
politică
are
un
agent
care
alege
la
rândul
său
mai
multe
elemente,
considerăm
că
acestea
reprezintă
o
singură
mi
ș
care
(deci
dacă
un
agent
alege
b,
apoi
îl
preferă
pe
a,
alegerea
nu
este
una
sănătoasă).
Putem
folosi
induc
ț
ia
backward
(inversă)
pentru
a
găsi
echilibrul
Nash
perfect
al
subjocului
(SPNE
–
subgame
perfect
Nash
equilibrium).
Când
agen
ț
ii
au
acea
ș
i
preferin
ț
ă
la
32
ordonare,
propozi
ț
ia
6
(Bouveret
ș
i
Lang)
demonstrează
că
aceasta
este
alegerea
sinceră.
Pe
de
altă
parte,
când
ordinele
de
preferin
ț
ă
sunt
diferite,
există
echilibrul
în
care
comportamentul nu este sincer.
Exemplu 2
Luam în considerare 4 elemente
ș
i politica alternativă.
Să presupunem că primul agent are ordinul de preferin
ț
ă: 1 > 2 > 3 > 4
în timp ce al doilea are ordinul de preferin
ț
ă: 4 > 2 > 3 > 1
Alegerea
sinceră
alocă
1
ș
i
2
primului
agent,
iar
4
ș
i
3
alocă
celui
de-al
doilea
agent.
Cu
toate
acestea
al
doilea
agent
nu
poate
exploata
sinceritatea
primului
ș
i
manipularea
mecanismului
de
a
ob
ț
ine
o
alocare
mai
bună.
Să
presupunem
că
primul
agent
alege
sincer
1,
dar
cel
de-al
doilea
alege
2.
Acum,
primul
agent
nu
poate
face
altceva
decât
să
aleagă
3,
lăsând
agentului
doi
să
aleagă
4.
În
acest
fel,
al
doilea
agent
ob
ț
ine
o
alocare
mai
bună
(4
ș
i
2),
iar
primul
prime
ș
te
o
alocare
mai
slabă
(1
ș
i
3).
Pentru
a
preveni
acest
lucru,
primul
agent
poate
să
aleagă
în
mod
strategic
printr-o
alegere
nesigură
prima
dată
2.
Ce
mai
rea
alegere
pentru
al
doilea
agent
este
să
aleagă
1.
Indiferent
de
celălalt
element,
a
doilea
agent
alege
(3
sau
4),
iar
primul
agent
va
alege
elementul
lor
cel
mai
preferat,
1.
Prin
urmare,
primul
agent
se
termină
cu
1
ș
i
2,
care
a
fost
aceea
ș
i
alocare
finală
ca
ș
i
în
cazul
sincer.
Cu
toate
acestea,
prin
alegerea
nescrisă
în
acest
fel,
primul
agent
împiedică
al
doilea
agent
să
manipuleze
rezultatul
ș
i
agravarea
alocării
acestora.
Această
strategie
nesinceră
pentru
primul
agent
(alegerea
apoi
1)
ș
i
strategia
sinceră
pentru
al
doilea
agent
(alegerea
4
apoi
3)
este
SPNE
găsită în induc
ț
ia backwa rd.
Comportamentul pentru 2 agen
ț
i
Cu
doi
agen
ț
i,
utilită
ț
i
adi
ț
ionale
ș
i
politica
strict
alternativă,
Kohler
ș
i
Chandraesekaran
(1971)
demonstrează
că
SPNE
poate
fi
calculat
în
timp
liniar
prin
simpla
inversare
a
politicii
ș
i
preferin
ț
ei
de
ordonare.
Avem
următoa rea
extensie
surprinzătoare:
pentru
doi
agen
ț
i
ș
i
orice
politică
(nu
doar
o
alternare
strictă),
un
SPNE
poate
fi
calculată
în
timp
polinomial,
iar
acest
lucru
este
unic,
cu
condi
ț
ia
ca
niciun
agent
să
nu
aibă
aceea
ș
i
utilitate pentru orice pereche de elemente.
Teorema
1:
Cu
doi
agen
ț
i
ș
i
utilită
ț
i
adi
ț
ionale
pentru
orice
politică
O,
alocare
(rev(P2),
rev(P1),
rev(O))
este
un
SPNE.
Mai
mult
de
atât,
alocarea
este
ș
i
unică
dacă
ambii
agen
ț
i
au
preferin
ț
e stricte fa
ț
ă de obiecte.
33
Comportamentul pentru 3 agen
ț
i
Cu 3 agen
ț
i este p osibil să nu mai existe un SPNE.
Exemplu 3
Să presupunem că agentul 1
ș
i 3 au preferin
ț
ele: 1 > 2 > 3 > 4
iar agentul 2 are preferin
ț
ele: 3 > 4 > 1 > 2
Noi
luăm
în
considerare
politica
1231.
Există
două
SPNE.
În
primul,
agen
ț
ii
aleg
cu
sinceritate.
Agentul
1
prime
ș
te
elementele
1
ș
i
4,
agentul
2
prime
ș
te
elementul
3
ș
i
agentul
3
prime
ș
te
elementul
2.
În
celălalt
SPNE,
agentul
1
alege
mai
întâi
punctul
3
strategic.
Agentul
2
ș
i
3
(care
nu
au
niciun
stimulent,
ci
să
aleagă
sincer)
să
ob
ț
ină
elementele
4
ș
i
respectiv
1,
lăsând
elementul
2
pentru
agentul
1.
Cu
utilită
ț
ile
Borda,
agentul
1
are
aceea
ș
i
utilitate
în
ambele.
Acest
exemplu
poate
fi
adaptat
pentru
a
demonstra
că
SPNE
depinde
de
utilită
ț
ile
reale
ș
i nu doar de ordine a preferin
ț
elor. [16]
2.3.2 Algoritmi implementa
ț
i
În
cadrul
aplica
ț
iei
am
folosit
doi
algoritmi
pentru
repartizarea
modelelor
în
func
ț
ie
de
preferin
ț
ele
fiecărui
designer,
astfel
încât
acestea
să
fie
disponibile
pentru
o
singură
prezentare
pe
zi.
Algoritmii
folosi
ț
i
sunt:
Adjusted
Winner
(câ
ș
tigător
ajustat)
ș
i
Descending
Demand (cererea descendentă) care urmează să fie descri
ș
i în continuare.
2.3.2.1 Adjusted Winner
Câ
ș
tigătorul
ajust at
(Adjusted
Winner
cu
N
=
2)
este
descris
de
(Brams
ș
i
Taylor
1996)
ș
i
se
referă
la
două
persoane
sau
două
grupuri
cu
interese
diferite.
Func
ț
ia
de
evaluare
este
aditivă
ș
i
poate
necesita
una
dintre
resurse
ș
i
sfâr
ș
itul
protocolului
de
alocare.
Protocolul
este
echitabil,
fără
invidie,
eficient
Pareto
(reprezintă
o
stare
în
care
îmbunătă
ț
irea
unei
resurse
nu
este
posibilă
fără
deteriorarea
alteia)
.
Se
compune
din
următoarea
secven
ț
ă
de
pa
ș
i:
1.
Fiecare
persoană
distribuie
un
anumit
număr
de
puncte
(adică
100)
peste
resurse
pentru a reflecta evaluarea lui pentru fiecare element;
34
2.
Fiecare
resursă
este
dată
ini
ț
ial
individului
care
îi
atribuie
cel
mai
mare
număr
de
puncte.
Dacă
avem
egalitate
pentru
o
resursă,
acea
resursă
nu
va
fi
atribuită
niciuneia
dintre ele;
3.
Fiecare
persoană
însumează
numărul
de
puncte
totale
pe
care
le-a
primit
ș
i
cel
care
a
primit cel mai mic număr de puncte acum este dat elementului care a avut o egalitate;
4.
Dacă
numărul
de
puncte
totale
pe
care
fiecare
persoană
le-a
primit
este
egal,
stopăm.
În
caz
contrar,
resursele
sunt
transferate
de
la
cei
mai
boga
ț
i
la
cei
mai
săraci
până
când
transferul
de
resurse
este
transferat
de
la
cel
mai
bogat
la
cel
mai
sărac,
până
când
mutarea
unei
resurse
va
determina
cei
mai
boga
ț
i
să
aibă
mai
pu
ț
ine
puncte
totale
decât
cei
mai
săraci.
Această
ultimă
resursă
transferată
trebuie
împăr
ț
ită.
Resursele sunt transferate în ordinea ascendentă a scorului lor asociat;
5.
Scorul
se
calculează
prin
împăr
ț
irea
punctelor
date
de
cele
mai
bogate
către
o
resursă
ș
i a punctelor date de cele mai sărace la aceea
ș
i resursă; [15]
2.3.2.2 Descending Demand
Cererea
descendentă
(Descending
Demand
cu
N>
=
3)
a
fost
propusă
de
Herreiner
ș
i
Puppe
(2002).
Aceasta
presupune
o
ordonare
liniară
asupra
subseturilor
de
resurse.
Prin
urmare,
protocolul
nu
este
adecvat
pentru
un
număr
mare
de
resurse.
Protocolul
este
egalitar
ș
i Pareto eficient. Etapele protocolului sunt:
1.
Protocolul
începe
prin
stabilirea
ordinii
în
care
indivizii
î
ș
i
vor
exprima
pachetul
de
resurse preferat;
2.
În
această
ordine
predefinită,
indivizii
vor
primi
mai
întâi
subsetul
cel
mai
preferat
de
resurse.
Dacă
după
această
rundă
există
o
alocare
fesabilă
prin
combinarea
doar
a
subseturilor
de
resurse
men
ț
ionate
până
acum,
protocolul
se
opre
ș
te.
În
caz
contrar,
în
urma
aceleia
ș
i
ordini
predefinite,
fiecare
individ
va
da
al
doilea
subset
cel
mai
preferat
de
resurse
ș
i
va
încerca din nou să găsească o alocare fezabilă;
3.
Protocolul
continuă
în
acest
fel
până
când
se
găse
ș
te
o
alocare
fezabilă.
Atunci
când
există mai multe solu
ț
ii fezabile, se va alege eficien
ț
a Pareto [15];
2.3.2 Utilitatea algoritmului Adjusted Winner
35
Suntem
în
căutarea
unei
situa
ț
ii
în
care
două
persoane
se
află
în
conflict
total.
Să
presupunem
că
Alice
si
Bob
divor
ț
ează,
iar
ace
ș
tia
sunt
nevoi
ț
i
să-
ș
i
împartă
bunurile.
O
modalitate este dată de procedura Adjusted Winner. Procedura este dată de următoarele:
1.
Fiecărui
individ
are
100
de
puncte
ș
i
are
sarcina
de
a
atribui
puncte
fiecărui
element
care
trebuie
să
fie
luat.
Mai
multe
puncte
înseamnă
că
individul
are
preferin
ț
e
mai
puternice
pentru
a
primi
respectivul
bun.
Din
nou,
presupunem
că
fiecare
individ
este
lacom. De asemenea, presupunem că ace
ș
ti concuren
ț
i nu cunosc punctele celuilalt;
2.
Persoana
care
a
atribuit
cele
mai
multe
puncte
pe
elemente
prime
ș
te
ini
ț
ial
elementul.
Se
adaugă
punctele
pentru
fiecare
persoană
pentru
cât
crede
că
a
atribuit.
Dacă
este
egalitate,
bunul
este
dat
persoanei
cu
cele
mai
pu
ț
ine
puncte.
Persoana
cu
cele
mai
multe puncte va fi ini
ț
ial declarată câ
ș
tigătoare, iar celălal t pierzător;
3.
Pentru
fiecare
obiect
dat
câ
ș
tigătorului
ini
ț
ial,
se
va
calcu la
raportul
de
puncte.
Acesta
se va calcula prin împăr
ț
irea punctelor câ
ș
tigătorului la punctele pierzătorului;
4.
Se
începe
mutarea
obiectelor
de
la
câ
ș
tigătorul
ini
ț
ial,
la
pierzătorul
ini
ț
ial
în
ordine
crescătoare
a
punctelor.
Se
opre
ș
te
când
se
ajunge
ca
un
element
a
cărui
mutare
va
determina
câ
ș
tigătorul
ini
ț
ial
să
aibă
mai
pu
ț
ine
puncte
decât
cel
pierzător
ini
ț
ial.
Acest element va trebui reprezintă un element partajat;
5.
Fie
x
reprezentând
partea
frac
ț
ională
a
elementului
partajat
care
va
fi
mutat
de
la
câ
ș
tigătorul
ini
ț
ial,
la
pierzătorul
ini
ț
ial.
Se
va
scrie
o
formulă
care
echivalează
totalul
punctelor fiecărei păr
ț
i după partajarea acestui element;
6.
Se
rezolvă
ecua
ț
ia
ș
i
se
analizează
diviziunea
finală.
Se
verifică
dacă
totalulurile
de
puncte sunt egale; [17]
36
Exemplu: Alice
ș
i Bob di vor
ț
ează
Luăm
în
calcul
faptul
că
Alice
ș
i
Bob
folosesc
procedura
Adjusted
Winner
ș
i
alocă
punctele astfel:
Obiect
Alice
Bob
Contul de retragere
50
40
Casă
20
35
Cabana de vară
15
14
Investi
ț
ii
10
6
Barcă
5
5
TOTAL
100
100
Pasul
1:
Ini
ț
ial,
Alice
prime
ș
te
contul
de
retragere,
cabana
de
vară
ș
i
investi
ț
iile.
Bob
prime
ș
te ini
ț
ial casa. Subtotalul curent este:
Alice = 50 + 15 + 10 = 75
Bob = 35
Deoarece
Bob
are
subtotal
inferior,
îi
dăm
obiectul
pentru
care
au
egalitate,
barca.
Astfel
subtotalul este dat de:
Alice = 75
Bob = 40
Alice este câ
ș
tigătorul ini
ț
ial
ș
i Bob este pierzătorul ini
ț
ial.
Pasul
2:
Apoi
caclulăm
raportul
de
punctaj
pentru
fiecare
element
pe
care
Alice
a
primit
ini
ț
ial:
Contul de retragere: =
3
5
5
0
,
3
≈
1
4
Cabana de vară: =
1
4
1
5
,
7
≈
1
0
Investi
ț
ii: =
1
4
1
5
,
7
≈
1
0
Pasul
3:
Cel
mai
mic
punctaj
este
cel
cu
cabana
de
vară.
Se
începe
transferarea
lui
de
la
Alice
la Bob. Astfel rezultă un nou subtotal:
Alice = 75 – 15 = 60
Bob = 40 + 14 = 54
37
Următorul
obiect
este
contul
de
retragere.
Dacă
îl
transferăm
de
la
Alice
la
Bob,
noul
subtotal
va fi:
Alice = 60 – 50 = 10
Bob = 54 + 40 = 94
Deoarece
acest
lucru
va
determina
ca
să
aibă
mai
pu
ț
ine
puncte
câ
ș
tigătorul
ini
ț
ial
(Alice),
iar
atunci elementul partajat este contul de retragere.
Pasul
4:
Doar
pentru
a
recapitula,
actualul
subtotal
este
Alice
=
60
ș
i
Bob
=
54.
Apoi
transferăm
frac
ț
ia
x
a
contului
de
retragere
de
la
Alice
la
Bob.
Bob
câ
ș
tigă
o
parte
din
contul
de
pensionare,
astfel
încât
noul
său
total
va
fi
54
+
54x
(cei
40
provin
din
punctul
total
pe
care
Bob
l-a
alocat
pentru
contul
de
retragere).
Alice
pierde
o
parte
din
contul
de
retragere,
astfel încât noul său cont va fi 60 – 50x.
Pasul 5:
Am stabilit apoi aceste două ecua
ț
ii egale:
54 + 40x = 60 – 50x
→
90x = 6
→
x=
=
6
9
0
1
1
5
,
%
≈
6
7
Aceasta însemnă că Bob va primi 6,7% din contul de retragere, iar Alice va păstra 93,3%.
Situa
ț
ia finală
:
Alice ob
ț
ine investi
ț
iile
ș
i 93,3 % din contul de retragere.
Punctul său total este: 10 + 50 (0.933)
56.7.
≈
Bob prime
ș
te casa, caban a de vară, barca
ș
i 6,7% din contul de retragere.
Punctul său total este: 35 + 14 + 5 + 40 (0,067)
.
6
,
≈
5
7
Câteva observa
ț
ii despr e procedura Adjusted Winner
●
se aplică doar pentru doi candida
ț
i;
●
vom ignora cazul unui zero pentru un obiect;
●
dacă
există
un
singur
element,
atunci
acest
element
este
împăr
ț
it
în
mod
egal
între
cele
două;
●
dacă
există
mai
mult
de
un
element,
fiecărei
persoane
li
se
garantează
cel
pu
ț
in
o
parte
dintr-un element;
●
în
timpul
alocării
ini
ț
iale
a
acestei
proceduri,
va
exista
întotdeauna
un
câ
ș
tigător
ini
ț
ial
ș
i
un
pierzător
ini
ț
ial.
Dacă
există
o
egalitate
în
alocarea
totală
a
punctelor,
atunci
s-a
terminat procedura, rezultând că obiectele au fost alocate în mod egal;
38
●
ordinea
alocării
ini
ț
iale
nu
contează.
O
dat
ce
se
decide
câ
ș
tigătorul
ini
ț
ial,
toate
articolele sunt luate în considerare în scopul împăr
ț
irii;
●
dacă
există
un
element
în
care
se
află
egalitate
la
punctele
de
alocare,
cel
mai
probabil
acesta va deveni element partajat;
●
ritmul
ini
ț
ial
este
garantat
tuturor
obiectelor
care
au
fost
alocate
ini
ț
ial.
Aceste
elemente nu vor fi împăr
ț
ite;
●
din
cauza
limitei
de
100
de
puncte,
este
posibil
ca
ini
ț
ial
câ
ș
tigătorului
să
i
se
aloce
ini
ț
ial toate eleme ntele;
●
când
se
ajunge
la
pasul
4,
de
re
ț
inut
că
x
este
procentul
elementului
partajat,
care
este
transferat
către
pierzător
ini
ț
ial.
De
exemplu,
dacă
x
=
43
%,
atunci
cel
care
pierde
ini
ț
ial ob
ț
ine 43% din element, în timp ce câ
ș
tigătorul ini
ț
ial va păstra 57%;
●
Din
cauza
erorilor
de
rotunjire,
este
posibil
ca
totalul
punctului
final
să
nu
se
potrivească, dar ar trebui să fie relativ apropiat unul de altul; [17]
3. Descrierea formală a aplica
ț
iei
3.1 Arhitectura aplica
ț
iei
Prin
arhitectura
aplica
ț
iei
se
sugerează
o
reprezentare
a
modului
în
care
mai
multe
aplica
ț
ii
sunt
pregătite
să
colaboreze.
Aceasta
încearcă
să
ofere
o
încredere
că
suita
de
aplica
ț
ii care este scalabil ă, fiabilă, disponibilă
ș
i u
ș
or de gestionat.
Sistemul este compus din aplica
ț
ia web, apica
ț
ia server
ș
i baza de date.
Figura 10. Arhitectura sistemului
39
3.1.1 Arhitectura aplica
ț
iei server
Aplica
ț
ia server s tă la baza controlării întregului sistem. Conectată la o bază de date,
stochează detaliile clien
ț
ilor, modelelor
ș
i opera
ț
iunile efectuate.
Figura 11. Aplica
ț
ia server
40
Figura 12. Designe-ul aplica
ț
iei WebApi
Modelul
arhitectural
Model-View-Controller
(MVC)
separă
o
aplica
ț
ie
în
trei
componente
principale:
Model,
Vizualizare
ș
i
Controlor.
Acest
model
ajută
la
crearea
aplica
ț
iei
fiind
mai
u
ș
or
de
actualizat
decât
la
aplica
ț
iile
tradi
ț
ionale
molitice.
Fiindcă
aplica
ț
ia este bazată pe m odelul MVC, aceasta con
ț
ine:
●
Modele: clasele care reprezintă datele aplica
ț
iei;
●
Vizualizări: componentele care afi
ș
ează interfa
ț
a cu utilizatorul aplica
ț
iei;
●
Controlor: clase care gestionează cererile browserului;
Acest
model
ajuta
la
crearea
aplica
ț
iei
prin
separarea
diferitelor
aspecte
ale
aplica
ț
iei
(logica
de
intrare,
de
ie
ș
ire
si
de
UI).
Modelul
specifică
unde
trebuie
localizat
fiecare
tip
de
logică în aplica
ț
ie.
3.1.2 Func
ț
ionalitate
Atunci
când
va
începe
aplica
ț
ia,
metoda
Main,
din
clasa
Program
este
apelată.
Aceasta
creează
o
gazdă
web
implicită
utilizând
configurarea
de
pornire,
expunând
aplica
ț
ia
prin
HTTP printr-un port specific.
namespace
ResourceAllocation.Api
{
public
class
Program
{
public
static
void
Main(
string
[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public
static
IWebHostBuilder CreateWebHostBuilder(
string
[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
}
Figura 13. Clasa Main
Crearea modulului Domeniu
Stratul
modul,
sau
Domain
Layer,
va
avea
clasele
noastre
care
vor
reprezenta
designerii
ș
i arti
ș
ti/modele.
În
directorul
ResourceAllocation.Api
am
creat
un
nou
dosar
numit
Domain
în
care
am adăugat clasele noastre.
41
namespace
ResourceAllocation.Domain
{
public
class
Designer
: BaseEntity
{
public
string
Name {
get
;
set
; }
public
string
Surname {
get
;
set
; }
public
string
Mail {
get
;
set
; }
public
int
nrOfArtistsNeeded {
get
;
set
; }
public
DateTime DateTimeShow {
get
;
set
; }
public
String LocationShow {
get
;
set
; }
public
List<DesignerArtists> FavoriteArtists {
get
;
set
; } =
new
List<DesignerArtists>();
[NotMapped]
public
List<DesignerArtists> AllocatedArtists {
get
;
set
; }
[NotMapped]
public
int
Score {
get
;
set
; }
}
}
Figura 14. Clasa Designer din stratul Domeniu
namespace
ResourceAllocation.Domain
{
public
class
Artist
: BaseEntity
{
public
string
Name {
get
;
set
; }
public
int
Height {
get
;
set
; }
public
int
Weight {
get
;
set
; }
public
int
BreastSize {
get
;
set
; }
public
int
WaistSize {
get
;
set
; }
public
int
HipsSize {
get
;
set
; }
public
string
EyesColor {
get
;
set
; }
public
string
HairColor {
get
;
set
; }
public
string
Facebook {
get
;
set
; }
public
string
Instagram {
get
;
set
; }
public
string
Description {
get
;
set
; }
public
string
Photo {
get
;
set
; }
public
string
Gender {
get
;
set
; }
public
IList<DesignerArtists> FavoriteForDesigners {
get
;
set
; }
}
}
Figura 15. Clasa Artist din stratul Domeniu
Clasele
mo
ș
tenesc
o
altă
clasă
numită
BaseEntity
în
care
se
găsesc
proprietă
ț
ile
pentru
id,
pentru
a
identifica
designerul
ș
i
respectiv
modelul,
ș
i
proprietatea
pentru
data
la
care
au
fost înregistrate acestea în baza de date.
namespace
ResourceAllocation.Domain
{
public
class
BaseEntity
42
{
public
Guid Id {
get
;
set
; }
public
DateTime DateCreated {
get
;
set
; }
}
}
Figura 16. Clasa BaseEntity din stratul Domeniu
Proprietă
ț
ile
pentr u
aceste
clase
reprezintă
detaliile
necesare
depre
fiecare
în
parte.
De
exemplu,
la
arti
ș
ti
avem
nevoie
de
culoarea
ochilor,
iar
la
designeri
avem
nevoie
de
loca
ț
ia
la
care
se
desfă
ș
oară
prezen tarea
de
modă.
Pe
lângă
aceste
proprietă
ț
i
specifice,
regăsim
liste
de
tipul
clasei
DesignerArtists.
Pentru
ari
ș
ti,
în
această
listă
este
folosită
pentru
memorarea
designerilor
pentru
care
au
fost
favori
ț
i.
în
cadrul
clasei
de
designeri,
listele
respective
sunt
folosite pentru re
ț
inerea a rti
ș
tilor favori
ț
i
ș
i pentru cei aloca
ț
i.
namespace
ResourceAllocation.Domain
{
public
class
DesignerArtists
{
public
Guid DesignerId {
get
;
set
; }
public
Guid ArtistId {
get
;
set
; }
public
Artist Artist {
get
;
set
; }
public
Designer Designer {
get
;
set
; }
public
int
Order {
get
;
set
; }
}
}
Figura 17. Clasa DesignerArtists din stratul Domeniu
Pe
lângă
aceste
clase
importante
din
cadrul
stratului
Domeniu,
am
mai
creat
alte
clase
AlgorithmResults
ș
i Com monArtistEntity.
namespace
ResourceAllocation.Domain
{
public
class
AlgorithmResult
{
public
List<Designer> Designers {
get
;
set
; }
public
int
Score {
get
;
set
; }
public
double
TimeExecuted {
get
;
set
; }
}
}
Figura 18. Clasa AlgorithmResult din stratul Domeniu
Această
clasă
con
ț
ine
proprietă
ț
i
pentru
stocarea
unor
rezultate,
precum
scorul
ș
i
timpul, executate în urma algoritmului executat, dar
ș
i o listă de designeri.
namespace
ResourceAllocation.Domain
{
public
class
CommonArtistEntity
{
public
Guid FirstDesigner {
get
;
set
; }
43
public
Guid SecondDesigner {
get
;
set
; }
public
Guid ArtistId {
get
;
set
; }
}
}
Figura 19. Clasa CommonArtistEntity din stratul Domeniu
Clasa
con
ț
ine
proprietă
ț
i
pentru
memorarea
detaliilor
artistului
comun
la
cei
doi
designeri:
id-urile
pentru
primul
ș
i
al
doilea
designer
ș
i
id-ul
artistului
comun
în
lista
de
preferate ale celor doi designeri.
Acum,
pentru
că
avem
clasele
de
bază,
suntem
gata
să
le
folosim.
Începem
prin
a
scrie
endpoint-urile (punctele finale) care vor gestiona toate modelele
ș
i designerii.
În
modulul
de
controller-e
vom
adăuga
trei
clase
noi
numite
ArtistsController,
DesignerController
ș
i
ResourceAllocationController.
Prin
conven
ț
ie,
toate
clasele
din
acest
modul
care
se
termină
cu
sufixul
„Controller”
vor
deveni
controllerii
aplica
ț
iei
noastre.
Aceasta
înseamnă
că
ei
vor
face
fa
ț
ă
cererilor
ș
i
răspunsurilor.
Această
clasă
este
nevoită
să
fie
mo
ș
tenită
în
spa
ț
iul
de
nume
(namespace)
Microsoft.AspN etCore.Mvc.
Un
spa
ț
iu
de
nume constă dintr-un grup de clase, interfe
ț
e, enumera
ț
ii
ș
i structuri asociate.
Noul
controller
ar
trebui
să
răspundă
prin
rutele:
api/artists,
api/designeri
ș
i
api/resourceallocation.
Aceasta
se
realizează
prin
adăugarea
atributului
Route
(rută
sau
traseu)
deasupra
numelui
clasei,
specificând
un
substituent
care
indică
faptul
că
traseul
ar
trebui să utilizeze denumirea clasei fără sufixul controller-ului, prin conven
ț
ie.
[Route(
"api/[controller]"
)]
[ApiController]
public
class
ArtistsController
: ControllerBase
{
}
Figura 20. Ruta controller-ului
În
continuare
voi
prezenta
cum
sunt
tratate
cererile
GET
(a
ob
ț
ine).
De
exemplu,
atunci
când
cineva
solicită
date
din
/api/designers
prin
verbul
GET,
API-ul
trebuie
să
returneze to
ț
i designerii. Î n acest scop, am creat un serviciu pentru designeri.
La
nivel
de
concept,
un
serviciu
este,
în
esen
ț
ă,
o
clasă
sau
o
interfa
ț
ă
care
define
ș
te
metode
pentru
a
face
fa
ț
ă
unei
anumite
logici
de
afaceri.
Este
o
practică
obi
ș
nuită
în
multe
limbaje
de
programare
diferite
de
a
crea
servicii
pentru
a
gestiona
logica
afacerii,
cum
ar
fi
autentificarea
ș
i
autoriza rea,
plă
ț
ile,
fluxurile
complexe
de
date,
cache-ul
ș
i
sarcinile
care
necesită
interac
ț
iune
între
alte
servicii
sau
modele.
Folosind
serviciile,
putem
izola
cererea
ș
i
tratarea răspunsului printr-o logică reală, necesară îndeplinirii sarcinilor.
44
Crearea modulului pentru servicii
(Services)
O
clasă
de
servicii
este
un
design
pattern
numit
Repository
Pattern
(modul
de
depozitare), care este utilizat pentru gestiunea datelor din baza de date.
Prin
utilizarea
Repository
Pattern-ului
definim
clasele
de
depozit,
care
încapsulează
în
esen
ț
ă
toată
logica
pentru
a
gestiona
accesul
la
date.
Aceste
depozite
expun
motode
pentru
a
lista,
crea,
modifica
sau
ș
terge
obiecte
dintr-un
anumit
model.
Pe
plan
intern,
aceste
metode
vorbesc
cu
baza
de
date
pentru
a
efectua
opera
ț
ii
CRUD,
izolând
accesul
bazei
de
date
de
restul aplica
ț
iei.
Serviciciile
noastre
trebuie
să
discute
cu
depozitele
de
designeri,
arti
ș
ti
si
algorimtii
de alocare, pentru a putea efectua opera
ț
iuni.
În
directorul
ResourceAllocation.Api
am
creat
un
nou
modul
numit
Services
în
care
am
adăugat
alte
3
sub
module,
pentru
arti
ș
ti,
designeri
ș
i
algoritmii
de
alocare.
În
acestea
am
adăugat
interfe
ț
ele
cores punzătoare.
Interfe
ț
ele
ne
permit
să
adăugăm
comportamentul
dorit
de la implementarea reală.
Folosind
un
mecanism
cunoscut
ca
injec
ț
ie
de
dependen
ț
ă,
putem
implementa
aceste
interfe
ț
e
ș
i
le
putem
izola
de
alte
componente.
Practic,
atunci
când
folosim
injec
ț
ia
de
dependen
ț
ă, definim anum ite comportamente folosind o interfa
ț
ă.
După
acest
pas,
am
creat
clasele
necesare
care
implementează
interfe
ț
ele
respective.
Astfel, obligăm referin
ț
ele din interfe
ț
e, la clasele pe care le-am c reat.
Datorită
implementării
serviciilor,
codul
din
interiorul
controller-elor
se
schimbă
ș
i
devine (de exemplu pentru designeri):
using
System;
using
Microsoft.AspNetCore.Mvc;
using
ResourceAllocation.Domain;
using
ResourceAllocation.Services.Artists;
namespace
ResourceAllocation.Api.Controllers
{
[Route(
"api/[controller]"
)]
[ApiController]
public
class
ArtistsController
: ControllerBase
{
private
readonly
IArtistsService _artistsService;
public
ArtistsController(IArtistsService artistsService)
{
_artistsService = artistsService;
}
45
[HttpGet]
public
IActionResult Get()
{
var
result = _artistsService.GetAll();
return
Ok(result);
}
[HttpGet]
[Route(
"{id:Guid}"
)]
public
IActionResult Get(Guid id)
{
var
result = _artistsService.GetById(id);
return
Ok(result);
}
[HttpPut]
public
IActionResult Put(Artist entity)
{
_artistsService.Add(entity);
return
Ok();
}
[HttpPatch]
public
IActionResult Patch(Artist entity)
{
_artistsService.Update(entity);
return
Ok();
}
[HttpDelete]
[Route(
"{id:Guid}"
)]
public
IActionResult Delete(Guid id)
{
_artistsService.Delete(id);
return
Ok();
}
}
}
Figura 21. Ruta controller-ului
Am
definit
o
func
ț
ie
de
constructor
pentru
controller-ul
nostru
(un
constructor
este
apelat
atunci
când
este
creată
o
nouă
instan
ț
ă
a
unei
clase)
ș
i
prime
ș
te
o
instan
ț
ă
a
serviciului
IDesignerService.
Aceasta
însemnă
că
instan
ț
a
poate
fi
orice
care
implementează
interfa
ț
a
din
serviciu.
Am
stocat
această
instan
ț
ă
intr-o
variabilă
_designersService
privat,
pentru
citire.
Vom
folosi
acest
câmp
pentru
a
accesa
metodele
implementării
serviciului
nostru
de
categorii.
46
Ca
ș
i
remarcă
la
prefixul
de
subliniere
din
cadrul
variabilei,
aceasta
reprezintă
o
altă
conven
ț
ie
comună
care
indică
o
variabilă
privată.
Această
conven
ț
ie
nu
este
recomandată
de
conven
ț
ia
de
denumire
a
.NET-ului,
dar
este
o
practică
foarte
frecventă,
o
modalitate
de
a
evita
utilizarea
cuvântului
„this”
(acesta)
pentru
a
distinge
variabile
locale
a
clasei
.
Eu
personal cred prin folosirea acestei conven
ț
ii, codul este mult mai curat pentru a fi citit.
Sub
constructor,
am
definit
metodele
care
se
ocupă
de
cererile
pentru
/api/designer/,
respectiv
metodele
de:
aducere
a
tuturor
designerilor,
de
aducere
a
unui
singur
designer
în
func
ț
ie de id-ul acestuia, de adăugare, actualizare
ș
i
ș
tergere a unui designer.
Configurarea dependin
ț
ei
Clasa
Startup
din
modulul
rădăcină
al
aplica
ț
iei
este
responsabilă
pentru
configurarea
tuturor
tipurilor
de
configura
ț
ii
atunci
când
începe
aplica
ț
ia.
În
metodele
ConfigureServices
ș
i
Configure
se
configurează
modul
în
care
ar
trebui
să
func
ț
ioneze
aplica
ț
ia
ș
i
componentele
pe
care trebuie să le utilizeze.
În
metoda
ConfigureServices
avem
doar
o
singură
linie
care
configurează
aplica
ț
ia
pentru
utilizarea
conductei
MVC
(Model
View
Controller),
ceea
ce
înseamnă
în
principiu
că
aplica
ț
ia
va
gestiona
cererile
ș
i
răspunsurile
folosind
clase
de
controller.
Prin
această
metodă
accesăm parametrul services, pentru a configura legăturile de dependen
ț
ă.
using
Microsoft.AspNetCore.Builder;
using
Microsoft.AspNetCore.Hosting;
using
Microsoft.AspNetCore.Mvc;
using
Microsoft.EntityFrameworkCore;
using
Microsoft.Extensions.Configuration;
using
Microsoft.Extensions.DependencyInjection;
using
Newtonsoft.Json;
using
ResourceAllocation.DataLayer;
using
ResourceAllocation.DataLayer.Designers;
using
ResourceAllocation.DataLayer.Artists;
using
ResourceAllocation.Services.Designers;
using
ResourceAllocation.Services.Artists;
using
ResourceAllocation.Services.ResourceAllocation;
using
ResourceAllocation.Api.Models;
using
Swashbuckle.AspNetCore.Swagger;
namespace
ResourceAllocation.Api
{
public
class
Startup
{
public
Startup(IConfiguration configuration, IHostingEnvironment env)
{
var
builder =
new
ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
47
.AddJsonFile(
"appsettings.json"
, optional:
false
, reloadOnChange:
true
)
.AddJsonFile(
$"appsettings.
{env.EnvironmentName}
.json"
, optional:
false
, reloadOnChange:
true
)
.AddEnvironmentVariables();
configuration = builder.Build();
Configuration = configuration;
}
public
IConfiguration Configuration {
get
; }
public
void
ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy(
"LocalCorsConfig"
, policy => policy.WithOrigins(
"http://localhost:4200"
));
});
services.AddMvc()
.AddJsonOptions(options => options.SerializerSettings.ReferenceLoopHandling =
ReferenceLoopHandling.Ignore)
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddTransient<IArtistsService, ArtistsService>();
services.AddTransient<IArtistsRepository, ArtistsRepository>();
services.AddTransient<IDesignersService, DesignersService>();
services.AddTransient<IDesignersRepository, DesignersRepository>();
services.AddTransient<IAdjustedWinnerAllocationService, AdjustedWinnerAllocationService>();
services.AddTransient<IDescendingDemandAllocationService, DescendingDemandAllocationService>();
var
connectionStrings =
new
ConnectionStrings();
Configuration.GetSection(
"ConnectionStrings"
).Bind(connectionStrings);
services.AddDbContext<ResourceAllocationDbContext>
(options => options.UseSqlServer(connectionStrings.ResourceAllocationApiContext));
services.AddSwaggerGen(c =>
{
c.SwaggerDoc(
"v1"
,
new
Info { Title =
"My API"
, Version =
"v1"
});
});
}
public
void
Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseDeveloperExceptionPage();
using
(
var
serviceScope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
{
var
context = serviceScope.ServiceProvider.GetRequiredService<ResourceAllocationDbContext>();
context.Database.EnsureCreated();
}
app.UseHttpsRedirection();
48
app.UseMvc();
app.UseCors(
"LocalCorsConfig"
);
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint(
"/swagger/v1/swagger.json"
,
"My API V1"
);
});
}
}
}
Figura 22. Clasa Startup
În linia de cod următoare, din clasa de mai sus, configurăm contextul bazei de date.
services.AddDbContext<ResourceAllocationDbContext>
(options => options.UseSqlServer(connectionStrings.ResourceAllocationApiContext));
Figura x. Configurarea contextului bazei de date
După
configurarea
contextului
bazei
de
date,
legăm
de
asemenea
serviciul
ș
i
depozitul
nostru la clasele respective.
services.AddTransient<IArtistsService, ArtistsService>();
services.AddTransient<IArtistsRepository, ArtistsRepository>();
services.AddTransient<IDesignersService, DesignersService>();
services.AddTransient<IDesignersRepository, DesignersRepository>();
services.AddTransient<IAdjustedWinnerAllocationService, AdjustedWinnerAllocationService>();
services.AddTransient<IDescendingDemandAllocationService,
DescendingDemandAllocationService>();
Figura 23. Legarea serviciului nostru de clase necesare
Cererile HTTP
Un exemplu de endpoint din cadrul aplica
ț
iei este următorul:
[HttpPost]
[Route(
"{id:Guid}/set-favourite-models"
)]
public
IActionResult SetFavouritesArtists(Guid id, [FromBody]List<Guid> ArtistIds)
{
_designersService.SetFavouriteArtists(id, ArtistIds);
return
Ok();
}
Figura x. Endpoint pentru setarea liste de modele favorite
49
Metodele
prezente
în
clasele
de
controller
sunt
numite
ac
ț
iuni
ș
i
au
această
semnătură
deoarece putem returna mai mult decât un posibil rezultat după ce se execută aplica
ț
ia.
În
acest
caz,
dacă
este
invalid
id-ul
designerului
sau
se
întâmplă
ceva
în
neregulă,
va
trebui
să
returnăm
un
răspuns
de
cod
400
(solicitare
gre
ș
ită),
care
con
ț
ine,
în
general,
un
mesaj
de
eroare
pe
care
aplica
ț
iile
client
le
pot
utiliza
pentru
a
trata
problema
sau
putem
avea
un răspuns 200 (succes) cu date dacă totul merge bine.
Exsită
mai
multe
tipuri
de
ac
ț
iuni
pe
care
le
putem
utiliza
ca
răspuns,
dar,
în
general,
putem folosi această interfa
ț
ă, iar ASP.NET Core va folosi o clasă implicită pentru aceasta.
Atributul
FromBody
îi
spune
lui
ASP.NET
Core
să
analizeze
datele
corpului
cererii
în
noua clasă de resurse.
Acum,
putem
pune
în
aplicare
noua
logică
de
rută.
Pa
ș
ii
care
trebuie
urma
ț
i
pentru
a
crea cu succes un nou designer sunt:
●
În
primul
rând,
trebuie
să
validăm
solicitarea
de
intrare.
Dacă
cerea
este
nevalidată,
trebuie să returnăm un răspuns de solicitare care con
ț
ine mesajele de eroare;
●
Dacă
cererea
este
validă,
apelăm
serviciul
nostru,
spunându-i
să
salveze
noul
nostru
designer.
Dacă
logica
de
salvare
este
executată
fără
probleme,
ar
trebui
returnat
un
răspuns
care
con
ț
ine
datele
noului
designer.
Dacă
nu,
ar
trebui
să
ne
dea
o
indica
ț
ie
că
procesul nu a reu
ș
it
ș
i un poten
ț
ial mesaj de eroare;
Aplicarea modelului de solicitare-răspuns
În
cele
ce
urmează
voi
prezenta
una
dintre
cele
trei
clase
(Designer,
Artists
ș
i
ResourceAllocation) în care am folosit modelul de solicitare-răspuns.
namespace
ResourceAllocation.Api.Controllers
{
[Route(
"api/[controller]"
)]
[ApiController]
public
class
DesignersController
: ControllerBase
{
private
readonly
IDesignersService _designersService;
public
DesignersController(IDesignersService designersService)
{
_designersService = designersService;
}
[HttpGet]
public
IActionResult Get()
{
50
var
result = _designersService.GetAll();
return
Ok(result);
}
[HttpGet]
[Route(
"{id:Guid}"
)]
public
IActionResult Get(Guid id)
{
var
result = _designersService.GetById(id);
return
Ok(result);
}
[HttpPost]
[Route(
"{id:Guid}/set-favourite-models"
)]
public
IActionResult SetFavouritesArtists(Guid id, [FromBody]List<Guid> ArtistIds)
{
_designersService.SetFavouriteArtists(id, ArtistIds);
return
Ok();
}
[HttpPut]
public
IActionResult Put(Designer entity)
{
_designersService.Add(entity);
return
Ok();
}
[HttpPatch]
public
IActionResult Patch(Designer entity)
{
_designersService.Update(entity);
return
Ok();
}
[HttpDelete]
[Route(
"{id:Guid}"
)]
public
IActionResult Delete(Guid id)
{
_designersService.Delete(id);
return
Ok();
}
}
}
Figura 24. Clasa Designer
După
validarea
datelor
de
solicitare
a
resurselor
către
modelul
nostru,
îi
transmitem
serviciului nostru să men
ț
ină datele.
Dacă
ceva
nu
reu
ș
e
ș
te,
API-ul
returnează
un
cod
de
eroare .
Dacă
nu,
API-ul
redă
noua
informa
ț
ia dorită (incluzâ nd datele)
ș
i o trimite clientului.
51
Testarea endpoit-urilor folosind Postman
Un
endpoint
HTTP
este
o
adresă
URL
vizată
în
aplica
ț
ia
web,
cum
ar
fi
în
cazul
nostru:
https://localhost:44304/api/
artists
care
combină
protocolul
utilizat
HTTPS
cu
loca
ț
ia
de
re
ț
ea
a
serverului
web
(inclusiv
portul
TCP):
localhost:44304
ș
i
ț
inta
URI
ResourceAllocation API.
MVC
invocă
clasele
controllerului
(
ș
i
metodele
de
ac
ț
iune
din
cadrul
acestora)
în
func
ț
ie
de
adresa
URL
primită.
Logica
implicită
de
rutare
a
adreselor
URL
folosită
de
MVC
utilizează un format ca acesta pentru a determina ce cod dorim să invocăm:
/[Controlor]/[NumeAc
ț
iune]/[Parametrii]
Formatul rutării se află în metoda Configure din fi
ș
ierul Startup.cs descrisă mai sus.
Răsfoind
la
adresa
https
de
mai
sus,
care
reprezintă
ș
i
metoda
de
întâmpinare,
aceasta
rulează
ș
i
returnează
lista
de
arti
ș
ti.
Aspectul
paginii
de
la
această
rută
în
urma
rulării
API-ului este reprezentată în imaginea de mai jos.
Figura 25. Endpoint pentru afi
ș
area arti
ș
tilor
Pentru
a
testa
endpoint-urile
în
aplica
ț
ia
Postman,
vom
porni
rularea
aplica
ț
iei
noastre
server.
Vom
introduce
adresa
API
în
câmpul
pentru
introducerea
adresei
URL
a
solicitării
ș
i
vom selecta castele de GET/ POST/ PUT/ PATCH/ DELETE în func
ț
ie de cererile dorite.
52
Figura 26. Afi
ș
area arti
ș
tilor cu PostMan
În
figura
de
mai
sus
este
reprezentată
afi
ș
area
tuturor
arti
ș
tilor
din
baza
de
date
prin
aplica
ț
ia
Postman.
In
partea
de
sus
a
figurii
se
observă
ruta
pe
care
i-am
dat-o,
iar
în
stânga
acesteia
este
selectat
modul
de
solicitare
(GET).
De
asemea,
în
această
fereastră
mai
este
afi
ș
at si codul „200 OK” ceea ce sugerează că a func
ț
ionat corespunzător.
53
3.2 Scenarii de utilizare
Figura 27. Scenarii de utilizare
●
Pornirea
server-ului:
în
momentul
în
care
este
pornit
serverul
de
date,
se
poate
ini
ț
ia
adăugarea
de
modele
sau
designeri.
Pentru
a
lucra
cu
baza
de
date,
server-ul
va
sta
tot
timpul pornit;
●
Adăugarea
de
modele
ș
i
designeri:
administratorul
are
pe
interfa
ț
a
aplica
ț
iei
câte
un
buton
pentru
adăugarea
de
modele
ș
i
de
designeri
ș
i
o
listă
cu
numărul
total
de
modele
ș
i
designeri
care
se
află
deja
înregistrat
în
baza
de
date.
După
apăsarea
butonului
de
adăugare,
va
apărea
pe
interfa
ț
ă
ecranul
de
adăugare
modele
ș
i
designeri,
detalii
despre
ace
ș
tia,
precum:
nume,
prenume,
dimensiuni
statură
fizică
(pentru
modele),
loca
ț
ia, data
ș
i ora desfă
ș
urării prezentării de modă (pentru designeri) etc.;
●
Modificarea
sau
ș
tergerea
unui
model
sau
a
unui
designer
deja
existent:
administratorul poate actualiza detaliile acestora;
54
●
Vizualizarea
listei
de
modele
precum
ș
i
cea
de
designeri.
Pe
lângă
această
posibilitate,
administratorul
poate
vedea
ș
i
detaliile
despre
fiecare
înregistrare
în
parte,
accesând
un buton care duce la respectivul model/ designer;
55
4. Descrierea aplica
ț
iei
4.1 Structura aplica
ț
iei server
În
următorul
capitol
vor
fi
prezentate
func
ț
ionalită
ț
ile
aplica
ț
iei
sub
forma
schemelor
logice
ș
i legătura între fer estrele din cadrul programului.
4.1.1 Metoda de alocare a modelelor
Fiecare
designer
î
ș
i
selectează
un
număr
cât
mai
mare
de
modele
(mai
mare
decât
numărul
necesar
de
modele)
pe
care
ș
i
le
dore
ș
te
în
cadrul
prezentării
de
modă,
în
ordinea
preferin
ț
elor.
În
acela
ș
i
timp,
designerul
trebuie
sa-
ș
i
selecteze
ș
i
data
împreună
cu
ora
la
care
se petrece evenimentul. Astfel, în func
ț
ie de aceste date îi se vor aloca modelele potrivite.
56
Figura 28. Schemă logică – metoda de alocare
Conform
figurii
anterioare,
este
prezentată
schema
logică
a
metodei
de
alocare
a
modelelor.
Aceasta se execută astfel:
●
Aceasta
începe
prin
adăugarea
de
modele
ș
i
designeri
în
baza
de
date,
împreună
cu
detaliile acestora;
57
●
Urmează
ca
fiecare
designer
să
î
ș
i
aleagă
câte
un
set
de
modele
preferate
(mai
multe
decât
are
nevoie)
ordonate
în
func
ț
ie
de
favorite,
pentru
a
fi
siguri
că
vor
avea
parte
de
cele mai dorite de ei, în urma alocării;
●
Se
verifică
dacă
în
cadrul
listei
de
designeri
există
cel
pu
ț
ini
doi
care
să
aibe
prezentarea în aceea
ș
i zi;
●
Dacă
ace
ș
tia
au
prezentarea
în
aceea
ș
i
zi,
atunci
se
trece
prin
algoritmii
de
alocare,
iar
în
cazul
în
care
modelele
preferate
se
suprapun,
acestea
vor
fi
alocate
corespunzător
pe baza algoritmilor;
●
Dacă
nu
sunt
designeri
care
prezintă
în
aceea
ș
i
zi
sau
chiar
dacă
există
dar
s-a
trecut
deja
prin
algoritmi,
urmează
pasul
în
care
designerilor
le
sunt
aloca
ț
i
atâtea
modele
cât au nevoie de fapt în cadrul prezentării proprii;
4.1.2 Algoritmii implementa
ț
i
Cum
am
descris
ș
i
în
capitolul
anterior,
algoritmii
folosi
ț
i
„Adjted
Winner”
ș
i
„Descending Demand” urmează sa fie expu
ș
i în următoarele rânduri sub formă de scheme.
58
4.1.2.1 Adjusted Winner
Figura 29. Schemă logică – algoritmul „Adjusted Winner”
59
Acest
algoritm
începe
după
ce
s-au
introdus
modelele
ș
i
după
ce
designerii
ș
i-au
selectat
acela
ș
i
număr
de
arti
ș
ti
pe
care
îl
preferă
în
prezentările
lor.
Se
parcurg
pe
rând
toate
modelele.
Dacă
se
întâlne
ș
te
un
model
care
este
preferat
de
cel
pu
ț
in
doi
designeri
care
doresc
să
prezinte
în
aceea
ș
i
zi,
atunci
alocarea
acestuia
se
face
conform
algoritmului.
Pa
ș
ii
sunt
următorii:
●
Modelul este alocat designerului care îl preferă mai mult.
○
De
exemplu,
dacă
modelul
este
cu
o
pozi
ț
ie
mai
sus
în
lista
de
preferate
al
primului
designer
decât
la
cel
de-al
doilea,
atunci
artista
va
fi
alocată
primului
designer.
Lista
celui
de-al
doilea
designer
urmează
să
fie
modificată
prin
ș
tergerea m odelul respectiv pentru care a pierdut lupta;
●
Dacă
modelul
se
află
pe
aceea
ș
i
pozi
ț
ie
la
to
ț
i
designerii,
modelul
va
fi
alocat
designerului care are scorul cel mai mare.
○
Scorul
reprezintă
suma
tuturor
pozi
ț
iilor
modelelor
alocate
până
în
acel
moment pentru fiecare designer în parte;
●
În
cazul
în
care
se
constată
ca
este
egal
scortul,
atunci
modelul
nu
va
fi
alocat
niciunuia dintre designerii respectivi;
Implementare software
În
fereastra
următoare
este
prezetată
implementarea
algoritmului
„Adjusted
Winner”
în limbajul de programare C#.
private
List<Designer> AdjustedWinner (List<Designer> designers,
List<CommonArtistEntity> commonArtists)
{
foreach
(var commonArtist
in
commonArtists)
{
var
firstDesigner = designers.First(x => x.Id == commonArtist.FirstDesigner);
var
firstDesignerArtistPosition = GetModelPosition(firstDesigner, commonArtist);
var
secondDesigner = designers.First(x => x.Id == commonArtist.SecondDesigner);
var
secondDesignerArtistPosition = GetModelPosition(secondDesigner, commonArtist);
if
(firstDesigner.DateTimeShow.Date.Equals(secondDesigner.DateTimeShow.Date))
{
if
(firstDesignerArtistPosition < secondDesignerArtistPosition)
60
{
RemoveCommonArtistFromDesigner(secondDesigner, commonArtist);
}
else
if
(firstDesignerArtistPosition > secondDesignerArtistPosition)
{
RemoveCommonArtistFromDesigner(firstDesigner, commonArtist);
}
else
if
(firstDesignerArtistPosition == secondDesignerArtistPosition)
{
if
(GetDesignerScore(firstDesigner) < GetDesignerScore(firstDesigner))
{
RemoveCommonArtistFromDesigner(firstDesigner, commonArtist);
}
else
if
(GetDesignerScore(firstDesigner) >
GetDesignerScore(secondDesigner))
{
RemoveCommonArtistFromDesigner(secondDesigner, commonArtist);
}
else
{
RemoveCommonArtistFromDesigner(firstDesigner, commonArtist);
RemoveCommonArtistFromDesigner(secondDesigner, commonArtist);
}
}
}
}
foreach
(var designer
in
designers)
{
alllocateNoOfNeededArtists(designer);
}
return
designers;
}
Figura 30. Implementare – Adjusted Winner
Explica
ț
ia codului pentru metoda de implementare este următoarea:
61
●
Se
crează
o
metodă
numită
„AdjustedWinner”
de
tipul
listei
„Designer”
cu
parametrii
de intrare: o listă de designeri
ș
i o listă de arti
ș
ti (modele) comune;
●
Se
parcurge
lista
de
modele
comune,
care
con
ț
ine
to
ț
i
arti
ș
tii
care
se
regăsesc
în
lista
de preferate a designerilor;
●
Se
ini
ț
ializează
două
variabile
în
care
se
re
ț
in
doi
designeri
care
sunt
la
rând
din
cadrul
listei
de
modele
comune:
„firstDesigner”
ș
i
„secondDesigner”.
De
asemenea,
se
mai
crează
două
variabile,
tot
pentru
ace
ș
ti
designeri,
în
care
se
memorează
pozi
ț
ia
artistului
comun
din
cadrul
fiecărei
liste
de
favorite:
„firstDesignerArtistPosition
”,
„secondDesignerArtistPosition ”;
●
Se
verifică
dacă
ace
ș
ti
designeri
au
data
de
prezentare
a
evenimentului
în
aceea
ș
i
zi,
iar
dacă
nu
au,
atunci
se
sare
direct
către
finalul
metodei
în
care
se
alocă
fiecărui
designer atâtea modele cât are nevoie pentru prezentare;
●
Dacă
ace
ș
tia
au
prezentarea
în
aceea
ș
i
zi,
atunci
se
începe
alocarea
modelelor
comune:
○
Se
compară
pozi
ț
iile
modelului
comun
din
cadrul
listelor
de
favorite
ale
celor
doi
designeri
verifică
dacă
pozi
ț
ia
modelului
de
la
primul
designer
este
mai
mică
(cu
cât
pozi
ț
ia
modelului
este
mai
mică,
cu
atât
modelul
este
mai
favorizat) decât pozi
ț
ia modelului celui de-al doilea designer;
ș
Se
verifică
dacă
pozi
ț
ia
modelului
de
la
primul
designer
este
mai
mică
(cu
cât
pozi
ț
ia
modelului
este
mai
mică,
cu
atât
modelul
este
mai
favorizat)
decât
pozi
ț
ia
modelului
celui
de-al
doilea
designer.
Dacă
este,
atunci
se
va
apela
metoda
„RemoveCommonArtistFromDesigner”
cu
parametrii
de
intrare:
„secondDesigner”
ș
i
„commonArtist”,
care
duce la
ș
tergerea modelului din lista celui de-al doilea designer;
ș
Altfel,
dacă
pozi
ț
ia
modelului
de
la
primul
designer
este
mai
mare
decât
pozi
ț
ia
modelului
designerului
următor,
se
va
apela
aceea
ș
i
metodă,
la
fel
ca
mai
sus,
doar
că
primul
parametru
va
fi
schimbat
în
„firstDesigner”
○
În
cazul
în
care
rezultă
egalitate,
se
va
apela
metoda
„GetDesignerScore”
prin
care
se
returnează
un
număr
care
reprezintă
scorul.
Acesta
sugerează
suma
tuturor
pozi
ț
iilor
ini
ț
iale
ale
modelelor
rămase
în
urma
ș
tergerilor
din
cadrul
fiecărei liste;
62
ș
În
cazul
în
care
scorul
primului
designer
este
mai
mic
decât
scorul
celui
de-al
doilea
designer
se
va
apela
aceea
ș
i
metodă
pentru
ș
tergerea
modelului
„RemoveCommonArtistFromDesigner”.
De
data
aceasta
se
va
efectua
ș
tergerea
modelului
de
la
primul
designer,
pentru
că
cu
cât
avem
un
scor
mai
mic
cu
atât
înseamnă
că
au
fost
selectate
cele
mai
favorite modele;
ș
În
cazul
în
care
scorul
primului
designer
este
mai
mare
decât
scorul
celui
de-al
doilea
designer,
se
va
apela
din
nou
aceea
ș
i
metodă
ca
mai
sus,
doar
că
se
vor
folosi
parametrii
necesari
pentru
ș
tergerea
modelului celui de-al doilea designer;
ș
Dacă
se
va
considera
egalitate,
atunci
modelul
va
fi
ș
ters
din
listele
ambilor designeri;
●
Urmează
alocarea
numărului
necesar
de
modele.
Se
parcurg
to
ț
i
designerii
pe
rând
ș
i
se
apelează
metoda
„allocateNoOfNeededArtists”
cu
parametrul
„designer”-ului
care
urmează,
deoarece
schimbările
care
au
fost
necesare
s-au
făcut
deja,
iar
acum
designerii
au
lista
cu
modele
alocate
corect.
Numărul
necesar
de
modele
pentru
fiecare designer este salvat în entitatea acestora;
●
Metoda se încheie prin returnarea listei de designeri, care con
ț
ine noile modificări.
63
4.1.2.2 Descending Demand
Figura 31. Schemă logică – algoritmul „Descending Demand”
64
Algoritmul
Descending
Demand
începe
la
fel
ca
algoritmul
anterior,
după
ce
s-au
introdus
modelele
ș
i
după
ce
designerii
ș
i-au
selectat
acela
ș
i
număr
de
arti
ș
ti
pe
care
îl
preferă
în
prezentările
lor.
În
cazul
în
care
doi
sau
mai
mul
ț
i
designeri
doresc
să
prezinte
în
aceea
ș
i zi, se efectuează u rmătorii pa
ș
i:
●
Se
ia
primul
set
de
modele
care
constă
în
numărul
necesar
de
modele
pentru
prezentare;
●
Se verifică dacă există cel pu
ț
in un model comun în aceste seturi
○
Dacă
există,
atunci
se
trece
la
următorul
set
ș
i
se
reia
pasul
anterior,
până
când
se
găse
ș
te
un
set
potrivit
de
modele,
până
când
nu
mai
există
modele
comune
în seturile la care s-a ajuns
○
Dacă nu există, modelele sunt alocate direct designerilor;
Implementare software
În
fereastra
de
mai
jos
este
prezetată
implementarea
algoritmului
„Descending
Demand”.
public
List<Designer> DescendingDemand(List<Designer> designers,
List<CommonArtistEntity> commonArtists)
{
foreach
(var artist
in
commonArtists)
{
var
firstDesigner = designers.First(x => x.Id == artist.FirstDesigner);
var
secondDesigner = designers.First(x => x.Id == artist.SecondDesigner);
int
smallestPartition = SmallestNoOfArtistsNeeded(firstDesigner, secondDesigner);
if
(firstDesigner.DateTimeShow.Date.Equals(secondDesigner.DateTimeShow.Date))
{
while
(PartitionTesting(firstDesigner, secondDesigner) != smallestPartition &&
firstDesigner.AllocatedArtists.Count != 0 &&
secondDesigner.AllocatedArtists.Count != 0)
{
RemoveArtistsPartition(firstDesigner);
RemoveArtistsPartition(secondDesigner);
}
}
65
secondDesigner.AllocatedArtists = alllocateNoOfNeededArtists(secondDesigner);
firstDesigner.AllocatedArtists = alllocateNoOfNeededArtists(firstDesigner);
}
return
designers;
}
Figura 32. Implementare – Descending Demand
Explica
ț
ia codului pentru metoda de implementare a algoritmului este următoarea:
●
La
fel
ca
în
cazul
algoritmului
anterior,
se
crează
o
metodă
cu
acela
ș
i
tip
de
returnare
ș
i
aceea
ș
i
parametrii
de
intrare,
doar
că
va
avea
numele
conform
algoritmului, respectiv „Descending Demand”;
●
Se
parcurge
lista
de
modele
comune,
care
con
ț
ine
to
ț
i
arti
ș
tii
care
se
regăsesc
în lista de preferate a designerilor;
●
Asemănător cu algoritmul de dinainte, se crează
ș
i se ini
ț
ializează seturile de
variabile: „firstDesigner”
ș
i „secondDesigner”, precum
ș
i
„firstDesignerArtistPosition ”, „secondDesignerArtistPosition”
●
Se
mai
creează
ș
i
o
a
treia
variabilă
(„smallestPartition”)
în
care
se
memorează
cel
mai
mic
numă
de
arti
ș
ti
favori
ț
i
dintre
cei
doi
designeri
care
sunt
la
rând.
Aceasta
se
ini
ț
ializează
cu
valoarea
rezultată
în
urma
apelării
metodei
„SmallestNoOfArtistsNeeded”,
care
returnează
numărul
de
care
avem
nevoie,
având parametrii de intrare cei doi designeri;
●
La
fel
se
verifică
dacă
ace
ș
ti
designeri
au
data
de
prezentare
a
evenimentului
în
aceea
ș
i
zi,
iar
dacă
nu
au,
atunci
se
sare
direct
către
finalul
metodei
în
care
se alocă fiecărui designer atâtea modele cât are nevoie pentru prezentare;
●
În
cazul
în
care
ace
ș
tia
au
prezentarea
în
aceea
ș
i
zi,
atunci
se
începe
alocarea
modelelor pe baza acestui algoritm;
●
Se
trece
printr-o
buclă
care
continuă
până
când
găse
ș
te
parti
ț
iile
de
modele
necesare
preferin
ț
elor
designerilor
ș
i
care
nu
se
suprapun,
apelând
metoda
„PartitionTesting”
care
urmează
să
fie
descrisă
în
cele
ce
urmează.
În
acela
ș
i
timp
se
asigură
(se
pune
condi
ț
ia
în
buclă)
că
mai
are
ce
modele
să
verifice,
deoarece
în
cadrul
buclei
se
apelează
o
metodă
care
ș
terge
setul
de
modele
de
la ambii designeri;
66
public
int
PartitionTesting(Designer firstDesigner, Designer secondDesigner)
{
int
partitionCount = 0;
int
smallestPartition = SmallestNoOfArtistsNeeded(firstDesigner, secondDesigner);
foreach
(var artist
in
firstDesigner.AllocatedArtists)
{
foreach
(var otherArtist
in
secondDesigner.AllocatedArtists)
{
if
(artist.ArtistId != otherArtist.ArtistId && partitionCount != smallestPartition)
{
partitionCount++;
}
else
{
return
partitionCount;
}
}
}
return
partitionCount;
}
Figura 33. Implementare – metoda „PartitionTesting”
În
cadrul
acestei
metode
se
elimiă
seturile/
parti
ț
iile
de
modele
de
care
nu
mai
avem
nevoie, pentru că se suprapun. Aceasta se efectuează astfel:
●
Se
declară
o
variabilă
„partitionCount”
ini
ț
ializată
cu
zero,
în
care
se
va
contoriza
numărul de modele care nu sunt comune din cadrul parti
ț
iei.
●
Se
declară
o
a
doua
variabilă
„smallestPartition”
în
care,
prin
apelarea
metodei
„SmallestNoOfArtistsNeeded”,
se
va
re
ț
ine
cel
mai
mic
număr
de
arti
ș
ti
de
care
are
nevoie unul dintre cei doi designeri;
●
Urmează
parcurgerea
modelelor
din
listele
celor
doi
designeri.
Se
verifică
dacă
modelele
sunt
diferite
ș
i
dacă
valoarea
din
„partitionCount”
este
diferită
de
valoarea
lui
„SmallestNoOfArtistsNeeded”,
iar
dacă
sunt
îndeplinite
aceste
condi
ț
ii,
se
incrementează
contorul
pentru
modelele
care
nu
sunt
comune.
Dacă
s-a
întâlnit
condi
ț
ia
ca
cel
pu
ț
in
două
modele
să
fie
la
fel
sau
s-a
ajuns
la
momentul
în
care
niciun
model
din
parti
ț
ie
nu
se
repetă,
atunci
se
va
ie
ș
i
direct
din
metodă
ș
i
se
va
returna
67
valoarea
variabilei
„partitionCount”,
cu
ajutorul
căreia
se
va
ș
tii
până
în
ce
statiu
s-a
ajuns;
4.1.3 Baza de date
Pentru
crearea
bazei
de
date
am
pornit
de
la
două
idei
de
tabele
principale,
una
pentru
arti
ș
ti
(modele)
ș
i
una
pentru
designeri,
pe
care
cu
ajutorul
frame work-ului,
.Net
Core
a
reu
ș
it
să le genereze automat în baza de date. Astfel am creat clasele: „Artist”
ș
i „Designer”.
public
class
Artist
: BaseEntity
{
public
string
Name {
get
;
set
; }
public
int
Height {
get
;
set
; }
public
int
Weight {
get
;
set
; }
public
int
BreastSize {
get
;
set
; }
public
int
WaistSize {
get
;
set
; }
public
int
HipsSize {
get
;
set
; }
public
string
EyesColor {
get
;
set
; }
public
string
HairColor {
get
;
set
; }
public
string
Facebook {
get
;
set
; }
public
string
Instagram {
get
;
set
; }
public
string
Description {
get
;
set
; }
public
string
Photo {
get
;
set
; }
public
string
Gender {
get
;
set
; }
public
IList<DesignerArtists> FavoriteForDesigners {
get
;
set
; }
}
Figura 34. Entitatea pentru un artist
Clasa
„Artist”
con
ț
ine
câmpurile
necesare
pentru
detaliile
modelelor
(nume,
prenume,
culoarea
părului
etc.)
ș
i
o
listă
de
tipul
unei
alte
clase
(„
DesignerArtists
”)
pentru
a
face
legătura
dintre
cele
două
clase.
În
această
listă
se
vor
re
ț
ine
designerii
pentru
care
este
favorit
modelul
respectiv.
public
class
Designer
: BaseEntity
{
public
string
Name {
get
;
set
; }
public
string
Surname {
get
;
set
; }
68
public
string
Mail {
get
;
set
; }
public
int
nrOfArtistsNeeded {
get
;
set
; }
public
DateTime DateTimeShow {
get
;
set
; }
public
String LocationShow {
get
;
set
; }
public
List<DesignerArtists> FavoriteArtists {
get
;
set
; } =
new
List<DesignerArtists>();
[NotMapped]
public
List<DesignerArtists> AllocatedArtists {
get
;
set
; }
[NotMapped]
public
int
Score {
get
;
set
; }
}
Figura 35. Entitatea pentru un designer
Această
clasă
con
ț
ine,
pe
lângă
datele
necesare
designerului,
două
liste
de
tipul
clasei
„
DesignerArtists
”,
la
fel
ca
în
figura
anterioară,
în
care
se
vor
re
ț
ine
arti
ș
tii
prefera
ț
i
de
designeri
ș
i arti
ș
tii aloca
ț
i în urma algoritmilor aplica
ț
i.
Ambele
clase
mo
ș
tenesc
clasa
BaseEntity,
în
care
se
află
câmpurile
de
id,
care
se
generează în mod unic
ș
i automat,
ș
i data înregistrării unei entită
ț
i.
public
class
BaseEntity
{
public
Guid Id {
get
;
set
; }
public
DateTime DateCreated {
get
;
set
; }
}
Figura 36. Entitatea de bază
În
cadrul
rezultatelor
algoritmilor
executa
ț
i,
ace
ș
tia
re
ț
in
următoarele
proprietă
ț
i:
lista
de
designeri
împreună
cu
tot
ce
ț
ine
de
ei,
scorul
pentru
fiecare
algoritm
ș
i
timpul
în
care
s-au
executat ace
ș
tia.
public
class
AlgorithmResult
{
public
List<Designer> Designers {
get
;
set
; }
public
int
Score {
get
;
set
; }
public
double
TimeExecuted {
get
;
set
; }
}
Figura 37. Entitatea rezultate algoritm
69
To
ț
i
arti
ș
tii
comuni
designerilor
în
cauză
se
re
ț
in
prin
intermediul
id-urilor
lor,
salva
ț
i
într-o
clasă.
Arti
ș
tii
în
cauză
sunt
doi
care
prezintă
în
aceea
ș
i
zi
ș
i
care
doresc
acelea
ș
i
modele,
iar
pentru
aceasta
li
se
re
ț
in
ș
i
id-urile
lor
în
acela
ș
i
loc
în
care
e
află
ș
i
id-urile
modelelor comune.
public
class
CommonArtistEntity
{
public
Guid FirstDesigner {
get
;
set
; }
public
Guid SecondDesigner {
get
;
set
; }
public
Guid ArtistId {
get
;
set
; }
}
Figura 38. Entitatea arti
ș
ti comuni
4.2 Descrierea aplica
ț
iei web
Aplica
ț
ia
web
are
scopul
de
a
aloca
modelele
evenimentelor
corespunzător
cerin
ț
elor
designerilor
ș
i
în
func
ț
ie
de
disponibilitatea
acestora.
De
asemenea,
aplica
ț
ia
oferă
posibilitatea designerilor de a-
ș
i selecta modelele preferate.
Prin
navigarea
în
fereastra
„Fashion
models”
se
poate
observa
listat
toate
modele
înscrise în platformă, conform imaginii de mai jos.
Figura 39. Fereastra „Fa
ș
hion models”
70
În
partea
de
sus
a
paginii
este
afi
ș
at
un
număr
care
reprezintă
totalul
de
modele
afi
ș
ate.
În
această
pagin ă
se
mai
pot
observa,
pe
lângă
pozele
de
profil,
câteva
detalii
importante
de-a
lor
precum:
înăl
ț
imea,
greutatea
ș
i
dimensiunile
corporale.
Mai
multe
detalii
despre aceasta vor fi afi
ș
ate dacă se va da click pe numele lor.
De
asemenea,
această
fereastră
prezintă
ș
i
posibilitatea
de
a
actualiza
ș
i
de
a
ș
terge
modele, despre care voi vorbi în continuare.
O
dată
ce
s-a
dat
click
pe
numele
modelelor,
se
pot
observa
detaliile
despre
acestea,
a
ș
a cum este ilustrat în im aginea de mai jos.
Figura 40. Detalii despre model
În
această
imagine
este
reprezentat
un
tabel
cu
datele
modelului.
Prin
iconi
ț
ele
de
lângă
numele
acestora
se
pot
accesa
paginile
acestora
de
Facebook
ș
i
de
Instagram
în
urma
cărora, designerul î
ș
i poa te face o imagine mai amplă asupra modelului.
În
partea
dreaptă
a
paginii
este
afi
ș
ată
o
imagine
de
profil
prin
care
aceasta
dore
ș
te
să
î
ș
i eviden
ț
ieze cât mai bine trăsăturile.
Pentru
încărcarea
acestei
imagini,
este
nevoie
ca
această
ac
ț
iune
să
se
facă
atunci
când
se
adaugă
un
model
nou
sau
chiar
dacă
modelul
este
deja
înregistrat
în
baza
de
date,
se
poate
executa
o
actualizare
a
datelor.
În
acest
sens,
modelul
va
adăuga
o
rută
de
pe
web
reprezentată de imaginea care se dore
ș
te.
71
În
imaginea
de
mai
jos
este
reprezentată
adăugarea
unui
model
nou
în
baza
de
date.
La
această
pagină
se
ajunge
printr-un
click
de
pe
fereastra
„Fashion
models”
explicată
mai
sus, pe iconi
ț
a de plus din col
ț
ul din dreapta.
Figura 41. Adăugarea unui nou model
De
asemena,
actualizarea
modelului
se
face
tot
printr-un
click,
de
pe
aceea
ș
i
pagină,
doar
că
pe
o
altă
iconi
ț
ă.
Fiecare
model
afi
ș
at
are
în
dreptul
său
o
iconi
ț
ă
prin
care
se
ajunge
la actualizarea ei. În imaginea de mai jos voi prezenta această fereastră.
Figura 42. Editarea unui model deja existent
72
În
cazul
imaginii
de
mai
sus,
actualizarea
(editarea)
persoanei
se
face
asemănător
cu
cea
în
cazul
în
care
se
dore
ș
te
adăugarea
unui
model
nou.
Diferen
ț
a
este
că
nu
mai
sunt
câmpuri
sugestive
pentru
completare,
ci
sunt
câmpuri
completate
deja
cu
datele
deja
existente
ale
modelului
respectiv.
Modificarea
acestor
date
se
poate
efectua
simplu
prin
supra
scrierea
noilor date.
Figura 43 Salvarea noilor date
Pentru
a
salva
noile
date,
se
va
da
click
pe
butonul
de
„save”,
amplasat
la
sfâr
ș
itul
câmpurilor
de
detalii.
Odată
ce
s-a
dat
click
pe
acest
buton,
datele
vor
fi
direct
salvate
în
baza
de date.
Ș
tergea
unui
model
se
face
prin
accesarea
butonului
de
ș
tergere,
de
lângă
cel
de
actualizare.
Butonul
este
reprezentat
printr-o
iconi
ț
ă
în
formă
de
co
ș
de
gunoi.
O
dată
ce
s-a
dat click pe acesta, modelul nu va mai apărea
ș
i va fi
ș
ters din baza de date.
Pentru
accesul
la
designerii
din
cadrul
festivalului,
se
va
accesa
butonul
„Designers”
din dashboard (tablou de bord).
73
Figura 44. Fereastra „Designers”
În
această
fereastră
se
observă
artistele
(modele)
preferate
de
designeri.
Ace
ș
tia
ș
i-au
selectat
un
număr
mai
mare
de
modele
decât
au
ei
nevoie,
pentru
a
se
asigura
că
în
urma
algoritmului
să
primească
numărul
necesar
de
modele.
Numărul
modele
necesar
fiecărui
designer
este
reprezentat
în
câmpul
„Needed”
(necesare).
În
partea
dreaptă
a
paginii
este
reprezentată alocarea modelelor pentru fiecare designer în parte.
Un
detaliu
important
pe
care
îl
con
ț
ine
această
pagină
este
afi
ș
area
datei
ș
i
a
orei
în
care
urmează
să
se
desfă
ș
oare
prezentarea
de
modă.
Acest
detaliu
este
unul
foarte
important,
pentru
că
prezentările
de
modă
care
urmează
să
se
desfă
ș
oare
în
aceea
ș
i
zi
cu
alte
prezentări,
vor
avea
de
suferit
modificări
în
ceea
ce
ț
ine
repartizarea
modelelor.
În
acest
caz
se
va
intra
în
algoritmul
creat
din
spatele
aplica
ț
iei.
Cu
toate
acestea,
repartizarea
arti
ș
tilor
se
va
face
dinamic, apărând to
ț
i deo dată, fără să afecteze în vreun fel utilizatorul.
74
Figura 45. Fereastra pentru actualizarea designerului
Actualizarea
designerului
se
face
asemănător
cu
cea
a
modelelor.
O
iconi
ț
ă
corespunzătoare
va
fi
afi
ș
ată
în
fereastra
„Designeri”
prezentată
mai
sus.
Principala
diferen
ț
ă
dintre
model
ș
i
designer
este
că
designerul
are
afi
ș
ată
ș
i
o
listă
prin
care
sunt
reda
ț
i
arti
ș
tii
favori
ț
i
de
el,
pe
care
i-a
selectat
conform
ferestrei
de
mai
jos.
Navigarea
către
selectarea
acestora se face accesând butonul de actualizare din partea stângă a imaginii.
Figura 46. Selectarea modelelor de către designer
75
Selectarea
artistelor
dorite
se
face
prin
bifarea
căsu
ț
ei
din
cadranul
artistei.
Modelelor
care
au
fost
selectate
deja,
le
rămâne
bifată
căsu
ț
a,
iar
celorlalte
le
rămâne
goală
o
dată
ce
s-a
ajuns la această pagină de la ruta designerului selectat.
De
asemenea,
ordinea
modelelor
este
foarte
importantă
în
selectarea
lor.
Aceasta
reprezintă
cât
de
preferată
este
o
artistă.
Punerea
acestora
în
ordinea
dorită
se
efectuează
prin
mecanismul
trage
ș
i
plasează
(drag
and
drop)
în
care
designerul
ț
ine
apăsat
pe
modelul
dorit
ș
i în a
ș
ează în rândul dorit.
Salvarea
acestor
date
se
efectuează
prin
click-ul
„save”
plasat
la
sfâr
ș
itul
tuturor
modelelor.
Figura 47. Salvarea modelelor selectate
Această
salvare
permite
actualizarea
directă
ș
i
în
baza
de
date,
ceea
ce
înseamnă
că
noua modificare nu v-a necesita timp de a
ș
teptare.
Fereastra
de
diagrame
din
următoarea
imagine
redă
un
grafic
reprezentat
de
scorul
celor doi algoritmi implementa
ț
i (Adjusted Winner
ș
i Descending Demand).
76
Figura 48. Fereastra „Charts”
Atunci
când
se
trece
cu
mouse-ul
peste
un
bloc,
se
indică
un
număr
care
reprezintă
scorul
algoritmului
respectiv.
Algoritmul
cel
mai
bun
este
sugerat
de
blocul
care
are
scorul
cel
mai
mare. În cazul nostru, cel mai favorabil algoritm este algoritmul „Adjuste Winner”.
În
partea
de
jos
a
imaginii
sunt
descri
ș
i
algoritmii
împreună
cu
conceptul
de
implementare al acestora.
4.2.1 Implementarea aplica
ț
iei client
În
continuare
voi
prezenta
modul
în
care
am
creat
un
data
serviciu
pentru
a
consuma
un API-ul ASP.NET Core REST cu modul Http Angular.
Configura
ț
ia
Am
ales
fi
ș
ierul
http-service.ts
pentru
a
scrie
configura
ț
ia.
Dacă
se
va
schimba
ceva
în
acest
loc,
de
exemplu
o
versiune
api
care
este
stocată
în
URL
sau
în
punctul
final/
server,
acele modificări se pot face aici.
import
{ Injectable }
from
'@angular/core'
;
import
{ HttpClient, HttpHeaders }
from
'@angular/common/http'
;
import
{ map }
from
'rxjs/operators'
;
@Injectable()
77
export
class
HttpService {
constructor
(
public
httpClient: HttpClient) {
}
BASE_URL =
'
https://localhost:44304
'
;
FASHION_MODELS =
this
.BASE_URL +
'/api/artists'
;
DESIGNERS =
this
.BASE_URL +
'/api/designers'
;
ALLOCATED_MODELS =
this
.BASE_URL +
'/api/resourceallocation/adjusted-winner'
;
DESCENDING_DEMAND =
this
.BASE_URL +
'/api/resourceallocation/descending-demand'
;
ADJUSTED_WINNER =
this
.BASE_URL +
'/api/resourceallocation/adjusted-winner'
;
contentHeader: HttpHeaders =
new
HttpHeaders({
'Content-Type'
:
'application/json'
,
'Accept'
:
'application/json'
,
'Cache-Control'
:
'no-cache'
,
'Access-Control-Allow-Origin'
:
'http://localhost:4200'
});
public
saveDesigner(designer: any): any {
return
this
.httpClient.put(
this
.DESIGNERS, designer, {headers:
this
.contentHeader});
}
public
getFashionModels() {
return
this
.httpClient.get(
this
.FASHION_MODELS, {headers:
this
.contentHeader});
}
public
getFashionModelById(id) {
return
this
.httpClient.get(
this
.FASHION_MODELS +
'/'
+ id, {headers:
this
.contentHeader});
}
public
saveFashionModel(fashionModel) {
return
this
.httpClient.put(
this
.FASHION_MODELS, fashionModel, {headers:
this
.contentHeader});
}
public
updateFashionModel(fashionModel) {
return
this
.httpClient.patch(
this
.FASHION_MODELS, fashionModel, {headers:
this
.contentHeader});
}
public
deleteFashionModel(id) {
return
this
.httpClient.delete(
this
.FASHION_MODELS +
'/'
+ id, {headers:
this
.contentHeader});
}
78
public
getDesigners() {
return
this
.httpClient.get(
this
.DESIGNERS, {headers:
this
.contentHeader});
}
public
getDesignerById(id) {
return
this
.httpClient.get(
this
.DESIGNERS +
'/'
+ id, {headers:
this
.contentHeader});
}
public
updateDesigner(designer) {
return
this
.httpClient.patch(
this
.DESIGNERS, designer, {headers:
this
.contentHeader});
}
public
deleteDesigner(id) {
return
this
.httpClient.delete(
this
.DESIGNERS +
'/'
+ id, {headers:
this
.contentHeader});
}
public
navigateToSelectModels(id) {
return
this
.httpClient.post(
this
.DESIGNERS +
'/'
+ id, {headers:
this
.contentHeader});
}
public
setFavoriteArtists(id, favoriteArtists) {
return
this
.httpClient.post(
this
.DESIGNERS
+
'/'
+
id
+
'/set-favourite-models'
,
favoriteArtists,
{headers:
this
.contentHeader});
}
public
getAllocatedModels() {
return
this
.httpClient.get(
this
.ALLOCATED_MODELS, {headers:
this
.contentHeader});
}
public
getAdjustedWinnerEvalutation() {
return
this
.httpClient.get(
this
.ADJUSTED_WINNER, {headers:
this
.contentHeader});
}
public
getDescendingDemandEvalutation() {
return
this
.httpClient.get(
this
.DESCENDING_DEMAND, {headers:
this
.contentHeader});
}
}
Figura 49. Configurare conexiune client – server
79
În
codul
de
mai
sus
am
am
pregătit
toate
solicitările
pentru
a
fi
gata
atunci
când
intervine
o
cerere,
un
request
de
a
fi
gata
de
fiecare
dată
când
apelăm
o
func
ț
ie.
Am
importat
următoarele
librăriile
Injectabil,
necesar
pentru
crearea
serviciului
ș
i
HttpClient,
pentru
facilitarea
procesului
de
comunicare.
Am
injectat
modului
HttpClient
in
parametrii
constructorului.
Am
declarat
variabilele
pentru
endpoint-urile
RESTful
API
ș
i
head-urile
Http,
apoi
am
adăugat
func
ț
iile
pentru
toate
endpoint-urile
RESTful
API
CRUD
din
API.
Am
instan
ț
iat variabila http pe ntru a fi de tip httpClient, a
ș
a cum se poate observa în constructor.
Pentru
getFashionModels
sau
getDesigners
ob
ț
inem
toate
înregistrările
găsite
în
baza
de
date
pe
care
o
apelăm
prin
metoda
get
al
obiectului
http
ș
i
îi
transmitem
ca
parametru
adresa
URL.
Diferen
ț
a
la
metodele
getFashionModelById
ș
i
getDesignerById
este
că
la
acestea
trecem
un
parametru
id
ca
parametru
metodei
care
apoi
apelată.
Acest
parametru
reprezintă
antetul
cererii
care
specifică
tipul
de
con
ț
inut
care
este
transmis.
Prin
metodele
de
addDesigner,
addFashionModel
se
adaugă
designeri
ș
i
modele
în
baza
de
date.
Metodele
pentru
actualizarea
acestora
sunt
date
de
metodele
care
con
ț
in
antetul
update.
Prin
invocarea
metodei
delete
se
ș
terg
obiectele
http
(designerii
ș
i
modele).
Pentru
executarea
algoritmilor
dori
ț
i,
respectiv
Adjuste d
Winner
ș
i
Descending
Demand
sunt
metode
separate,
deoarece
ace
ș
tia
pot
da
rezultate
diferite
ș
i
în
majoritatea
cazurile
a
ș
a
se
întâmplă.
Prin
metoda
setFavoriteArtists
se
salvează
arti
ș
tii
(modelele)
favori
ț
i
pentru
fiecare
designer
în
parte,
dând
ca
parametru
id-ul
acestora
în
metodă.
Prin
metoda
navigateToSelectedModels
se
afi
ș
ează
modele pe care le-a selectat designerul respectiv.
Aceste
metode
au
fost
utilizate
în
fi
ș
ierele
component.ts
ș
i
au
fost
scrise
în
limbajul
type
script,
la
fel
ca
cele
de
mai
sus.
Un
exemplu
de
utilizare
pentru
accesarea
modelelor
este
reprezentat în figura de mai jos.
export
class
FashionModelsListComponent
implements
OnInit {
public
fashionModels: any;
constructor
(
public
httpService: HttpService,
public
router: Router) {
}
ngOnInit() {
this
.httpService.getFashionModels().subscribe(response
=>
{
this
.fashionModels = response;
});
}
navigateToFashionModels() {
80
this
.router.navigate([
'/fashion-models'
]);
}
navigateToAddNewFashionModel() {
this
.router.navigate([
'/fashion-models/add'
]);
}
navigateToFashionModelDetails(id) {
this
.router.navigate([
'/fashion-models/details'
], { queryParams: { id: id } });
}
navigateToFashionModelEdit(id) {
this
.router.navigate([
'/fashion-models/edit'
], { queryParams: { id: id } });
}
navigateToFashionModelDelete(id) {
if
(confirm(
'Are you sure to delete this fashion model?'
) ===
true
) {
this
.httpService.deleteFashionModel(id)
.subscribe(result
=>
{
this
.httpService.getFashionModels().subscribe(response
=>
{
this
.fashionModels = response; });
});
}
}
}
Figura 50. Accesarea modelelor
Prin
această
clasă
prima
dată
sunt
afi
ș
ate
toate
modelele
pe
ecran
prin
ngOnInit
care
este
un
hook
life
cycle
(cârlig
ciclu
de
via
ț
ă).
Acesta
este
apelat
de
Angular
pentru
a
indica
că
Angular
a
terminat
crearea
componentei.
În
continuare
sunt
prezentate
metodele
necesare
pentru
afi
ș
area
detaliilor
modelelor,
pentru
ș
tergerea,
actualizarea
ș
i
adăugarea
acestora.
La
metoda
de
ș
tergere,
se
observă
ca
obiectul
este
ș
ters
doar
dacă
s-a
răspuns
pozitiv
la
întrebarea pentru
ș
tergere a acestuia.
Metodele din această clasă sunt folosite în codul html astfel:
<div
class
=
"row"
>
<div
class
=
"col-sm-4"
*ngFor
=
"let fashionModel of fashionModels; index as i"
>
<div
class
=
"card bg-light mb-3"
>
<div
class
=
"card-header"
>
<h4
class
=
"card-title"
>
<span
(click)
=
"navigateToFashionModelDetails(fashionModel.id)"
class
=
"pointer"
>
{{fashionModel.name}}
</span>
<i
class
=
"fa fa-trash btn float-right"
(click)
=
"navigateToFashionModelDelete(fashionModel.id)"
>
81
</i>
<i
class
=
"fa fa-edit btn float-right"
(click)
=
"navigateToFashionModelEdit(fashionModel.id)"
>
</i>
</h4>
<p
class
=
"card-text"
>
Height: {{fashionModel.height}},
Breast: {{fashionModel.breastSize}},
Waist: {{fashionModel.waistSize}},
Hips: {{fashionModel.hipsSize}}
</p>
<img
src
=
"{{fashionModel.photo ? fashionModel.photo :
'assets/images/fashionmodelplaceholder.png'}}"
class
=
"model-image"
/>
</div>
</div>
</div>
</div>
Figura 51. Afi
ș
area modelelor
Aici
se
face
apel
la
metodele
pentru
afi
ș
area
modelelor.
Detaliile
despre
acestea,
cum
ar
fi
măsurile
lor
se
accesează
prin
obiectul
fashionModel,
de
exemplu
fashionModel.height,
pentru
accesa
înăl
ț
imea
acestuia.
În
cadrul
acestei
pagini,
se
afi
ș
ează
toate
modelele
prin
parcurgerea
listei.
În
cazul
în
care
un
model
nu
are
imagine
de
profil,
ii
se
va
atribui
una
în
mod implicit.
Din
această
pagină
se
poate
face
apel
către
alte
pagini,
prin
accesarea
diferitelor
butoane,
cum
ar
fi
butonul
de
editare.
Atunci
când
se
va
da
click
pe
acesta,
se
va
face
un
apel
către
respectiva
metodă
din
component.ts
descrisă
mai
sus,
care
accesează
fi
ș
ierul
de
rutare
dat de figura de mai jos.
import
{ NgModule }
from
'@angular/core'
;
import
{ Routes, RouterModule }
from
'@angular/router'
;
import
{ FashionModelsListComponent }
from
'./fashion-models-list.component'
;
import
{ FashionModelsAddComponent }
from
'./fashion-models-add.component'
;
import
{ FashionModelsDetailsComponent }
from
'./fashion-models-details.component'
;
82
import
{ FashionModelsEditComponent }
from
'./fashion-models-edit.component'
;
import
{ FashionModelsDeleteComponent }
from
'./fashion-models-delete.component'
;
const
routes: Routes = [
{path:
''
, component: FashionModelsListComponent},
{path:
'add'
, component: FashionModelsAddComponent},
{path:
'details'
, component: FashionModelsDetailsComponent},
{path:
'edit'
, component: FashionModelsEditComponent},
{path:
'delete'
, component: FashionModelsDeleteComponent}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export
class
FashionModelsRoutingModule {}
Figura 51. Fi
ș
ierul pentru rutare
83
5. Concluzii
ș
i dezvoltări ulterioare
5.1 Concluzii
Aplica
ț
ia
de
alocare
a
modelelor
în
cadrul
festivalelor
de
modă
a
reprezentat
pentru
mine
o
provocare
din
punct
de
vedere
al
cunoa
ș
terii
tehnologiei.
Înainte
de
a
începe
munca,
nu
aveam
experien
ț
a
de
construi
o
aplica
ț
ie
client
–
server
în
cadrul
unui
site
web
folosind
Visual
Studio
ș
i
Angular.
Pentru
mine,
cea
mai
mare
provocare
a
fost
să
mă
familiarizez
cu
Angular-ul.
Un
framework
foarte
util
ș
i
important
în
dezvoltarea
aplica
ț
iilor
client,
pe
care
am ajuns să îl apreciez pentru func
ț
ionalită
ț
ile sale multiple.
Una
dintre
motiva
ț
iile
pentru
care
am
ales
să
creez
această
aplica
ț
ie
este
datorită
necesită
ț
ii
unei
astfel
de
aplica
ț
ie
în
cadrul
festivalelor.
Pentru
a
fi
sigură
ca
aceasta
este
folositoare,
am
discutat
cu
câ
ț
iva
direct ori
de
festivale,
iar
ace
ș
tia
s-au
arătat
încânta
ț
i,
dorind
să
testeze
aplica
ț
ia chiar la următor ul eveniment.
Atunci
când
am
început
să
lucrez
la
aplica
ț
ie,
mi-am
propus
ca
aceasta
să
con
ț
ină
următoarele
fun
ț
ionalită
ț
i:
●
adăugarea de noi modele
ș
i designeri
●
modificarea detaliilor modelelor
ș
i designerilor deja existen
ț
i
●
posibilitatea
ș
tergerii acestora din baza de date
●
selectarea unei liste de modele preferate pentru fiecare designer
●
alocarea
modelelor
designerilor
în
func
ț
ie
de
preferin
ț
elor
acestora
ș
i
de
disponibilitatea modelelor, într-un mod cât mai corect
ș
i egal
Rezultatul
final
al
lucrării
s-a
transpus
într-o
aplica
ț
ie
care
îndepline
ș
te
toate
obiectivele men
ț
ionate m ai sus.
5.1 Compara
ț
ii între algoritmi
Cei
doi
algoritmi
descri
ș
i
mai
sus
„Adjusted
Winner”
ș
i
„Descending
Demand”
au
fost
ambii
implementa
ț
i
în
cadrul
aplica
ț
iei,
dar
cu
toate
acestea,
unul
singur
a
fost
ales
pentru a afi
ș
a alocara de m odele, rezultatele lor fiind diferite.
Algoritmul
pe
care
l-am
ales
este
„Adjusted
Winner”.
Acesta
s-a
dovedit
a
avea
cel
mai
bun
scor.
Din
punct
de
vedere
al
timpului
de
executare,
algoritmul
„Descending
84
Demand”
este
mai
rapid
decât
celălalt,
dar
aceste
diferen
ț
e
sunt
mult
prea
mici
ș
i
se
pot
vedea
doar
la
mii
de
înregistrări
în
baza
de
date,
motiv
pentru
care
„Ajusted
Winner”
rămâne
algoritmul „câ
ș
tigător”.
5.1 Dezvoltări ulterioare
În
cadrul
concursului
„Innovation
Labs”,
din
luna
martie,
la
care
am
participat
pentru
început
cu
această
aplica
ț
ie,
ideea
mea
a
fost
bine
văzută
de
juriu.
Astfel,
membrii
juriului
m-au
încurajat
spre
a
dezvolta
aplica
ț
ia
pentru
a
fi
folosită
ș
i
în
alte
scopuri.
Ideea
principală
a
constat
într-o
platformă
de
promovare
a
modelelor,
prin
care
mai
multe
persoane
care
au
nevoie
de
modele
pentru
diverse
reclame
publicitare,
prezentări
de
modă
în
afara
festivalelor,
fotografii pentru promovarea de produse etc., le pot găsi mai u
ș
or.
Noul
sistem
la
care
am
încercat
să
lucrez,
dar
pe
care
nu
am
reu
ș
it
să
il
aplic
încă,
îl
voi
explica
în
cele
ce
urmează.
Modelele
î
ș
i
fac
cont
ș
i
î
ș
i
încarcă
poze,
pentru
a
fi
găsite
mai
u
ș
or
de
poten
ț
ialii
clien
ț
i.
Acestea
vor
prezenta
ș
i
un
pre
ț
de
la
care
încep
să
lucreze,
la
care
noi
vom
adăuga
un
comision
care
v-a
fi
plătit
de
clien
ț
i,
atunci
când
doresc
să
rezerve
un
model.
De
asemenea,
modelele
au
posibilitatea
de
a
fi
afi
ș
ate
primele
în
rezultatele
unei
căutări
pentru
a
fi
promovate
ș
i
mai
mult,
în
schimbul
unei
sume
de
bani.
Acest
sistem
seamănă
cu
celebrul
sistem
de
închirieri
de
locuin
ț
e
al
site-ului
„
www.airbnb.com
”.
Avantajul
iedei
aplica
ț
iei
este
că
aceasta
vine
la
pachet
cu
sistemul
de
alocare
a
modelelor
în
cadrul festivalelor de modă, ceea ce reprezintă un plus fa
ț
ă de ceea ce este deja pe pia
ț
ă.
85
Abrevieri
ANSI
American National Standards
Institute
JS
Java Script
API
Application Programming
Interface
LINQ
Language Integrated
Query
CEO
Chief Executive Officer
MVC
Model View Controller
CLI
Comand Line Interface
OOD
Object Orientated design
CLR
Common Language Runtime
OOP
Object Oriented
Programming
CPU
Central Processing Unit
REST
Representational State
Transfer
CRUD
Create, Read, Update, Delete
SOLID
Single responsability
Open–closed principle
Liskov substitution
Interface segregation
Dependency inversion
CSS
Cascading Style Sheets
SPA
Single Page Applications
HTML
Hypertext Markup Language
SQL
Structured Query
Language
HTTP
Hypertext Transfer Protocol
TCP
Ttransmission Control
Protocol
ID
Database Identifier
TS
Type Script
IDE
Integrated Development
Enviroment
UI
User Interface
IL
International Language
URI
Uniform Resource
Identifier
JIT
Just In Time
URL
Uniform Resource
Locator
86
Figuri
Figura 1. Aplica
ț
ie
server-client
8
Figura 13. Clasa Main
35
Figura 2. Exemplu de
legătură unu la mul
ț
i
11
Figura 14. Clasa
Designer din stratul
Domeniu
35
Figura 3. Exemplu de
legătură mul
ț
i-la-mul
ț
i
12
Figura 15. Clasa Artist
din stratul Domeniu
36
Figura.4. Exemplu de
legătură unu-la-unu
13
Figura 16. Clasa
BaseEntity din stratul
Domeniu
36
Figura 5. Abordarea
Code-First
15
Figura 17. Clasa
DesignerArtists din
stratul Domeniu
37
Figura 6. Opera
ț
iile
CRUD
17
Figura 18. Clasa
AlgorithmResult din
stratul Domeniu
37
Figura 7: Arborele
genealogic C#
20
Figura 19. Clasa
CommonArtistEntity din
stratul Domeniu
37
Figura 8. Componentele
Angular
27
Figura 20. Ruta
controller-ului
38
Figura 9. Componentele
TypeScript
29
Figura 21. Ruta
controller-ului
40
Figura 10. Arhitectura
sistemului
33
Figura 22. Clasa
Startup
42
Figura 11. Aplica
ț
ia
server
33
Figura 23.
Legarea serviciului
nostru de clase necesare
43
Figura 12. Designe-ul
aplica
ț
iei WebApi
34
Figura 24. Clasa
Designer
45
87
Figura 25. Endpoint
pentru afi
ș
area arti
ș
tilor
46
Figura 39. Fereastra
„Fa
ș
hion models”
65
Figura 26. Afi
ș
area
arti
ș
tilor cu PostMan
47
Figura 41. Adăugarea
unui nou model
66
Figura 27. Scenarii de
utilizare
48
Figura 42. Editarea unui
model deja existent
66
Figura 28. Schemă
logică – metoda de
alocar
51
Figura 43. Salvarea
noilor date
67
Figura 29. Schemă
logică – algoritmul
„Adjusted Winner”
53
Figura 44. Fereastra
„Designers”
68
Figura 30. Implementare
– Adjusted Winner
55
Figura 45. Fereastra
pentru actualizarea
designerului
69
Figura 31. Schemă
logică – algoritmul
„Descending Demand”
58
Figura 46. Selectarea
modelelor de către
designer
69
Figura 32. Implementare
– Descending Demand
60
Figura 47. Salvarea
modelelor selectate
70
Figura 33. Implementare
– metoda
„PartitionTesting”
61
Figura 48. Fereastra
„Charts”
71
Figura 34. Entitatea
pentru un artist
62
Figura 49. Configurare
conexiune client – server
72
Figura 35. Entitatea
pentru un designer
63
Figura 50. Accesarea
modelelor
75
Figura 36. Entitatea de
bază
63
Figura 51.
Afi
ș
area modelelor
76
Figura 37.
Entitatea rezultate
algoritm
63
Figura 51.
Fi
ș
ierul pentru rutare
77
Figura 38.
Entitatea arti
ș
ti comuni
64
88
Bibliografie
[1] Back-End Architecture – Code Academy,
https://www.codecademy.com/articles/back-end-architecture
[2] Microsoft SQL Server – Wikipedia,
https://ro.wikipedia.org/wiki/Microsoft_SQL_Server
[3] Entity Framework – Microsoft docs,
https://docs.microsoft.com/en-us/previous-versions/gg696172(v=vs.100)
[4] Entity Framework – TutorialPoint,
https://www.tutorialspoint.com/entity_framework/entity_framework_overview.htm
[5] Domain-Driven Design – Wikipedia,
https://en.wikipedia.org/wiki/Domain-driven_design
[6] Entity Framework – Entity Framework Tutorial,
http://www.entityframeworktutorial.net/code-first/what-is-code-first.aspx
[7] ASP .Net Introduction – TutorialsPoint,
https://www.tutorialspoint.com/asp.net/asp.net_introduction.htm
[8] ASP .Net Core Web API Attributes – Dot Net Curry,
https://www.dotnetcurry.com/aspnet/1390/aspnet-core-web-api-attribute
[9] „Fundamentals of Computer Programming with C#”, Svetlin Nakov & Co, 2013
[10] Articol Unchiul Bob,
http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod
[11] Angular – Wikipedia,
https://en.wikipedia.org/wiki/Angular_(web_framework)
[12] TypeScript – TutorialsPoint
https://www.tutorialspoint.com/typescript/typescript_overview.htm
[13] HTML – TutorialsPoint
https://www.tutorialspoint.com/html/html_overview.htm
[14] CSS – TutorialsPoint
https://www.tutorialspoint.com/css/what_is_css.htm
[15] „Computer Supported Collaborative Decision-Making”, Florin Gheorghe Filip,
Constantin-Bălă Zamfirescu, Cristian Ciurea
[16] „Strategic Behaviour when Allocating Indivisible Goods Sequentially”, Thomas
Kalinowski, Nina Narodytska and Toby Walsh, Lirong Xia
[17] Adjusted Winner procedure,
http://math.uga.edu/~pbergonio/Su14/DM/13A.pdf
89
Copyright Notice
© Licențiada.org respectă drepturile de proprietate intelectuală și așteaptă ca toți utilizatorii să facă același lucru. Dacă consideri că un conținut de pe site încalcă drepturile tale de autor, te rugăm să trimiți o notificare DMCA.
Acest articol: ific: Prof. Dr. Ing. Zamfirescu Bălă Constantin Îndrumător: Prof. Dr. Ing. Zamfirescu Bălă Constantin Absolvent: Schiau Andreea-Roxana Specializarea… [605912] (ID: 605912)
Dacă considerați că acest conținut vă încalcă drepturile de autor, vă rugăm să depuneți o cerere pe pagina noastră Copyright Takedown.
