VISOKOŠOLSKI STROKOVNI ŠTUDIJ Računalništvo in informacijske tehnologije POROČILO PRAKTIČNEGA IZOBRAŽEVANJA v Tom88 d.o.o. Maribor Čas opravljanja od 1.4.2014 do 15.6.2014 Mentor Tomaž Kokot, univ. dipl. ing. ekonomije Študent Danijel Cigula Vpisna številka E1055643 E pošta danijel.cigula@student.um.si Telefon 041 730876
i
ii
KAZALO UVOD... 1 1 OPIS GOSPODARSKE DRUŽBE IN PRODUKTOV... 2 1.1 LifeSal...2 1.2 ŠOU Ljubljana...2 1.3 Maribor Live...3 1.4 Borut Pahor...3 1.5 Pinatio...3 2 OPIS PRAKTIČNEGA IZOBRAŽEVANJA... 4 3 STROKOVNO PODROČJE ALI PROJEKT... 4 3.1 Načrtovanje...5 3.2 Prijava...7 3.3 Registracija...9 3.4 Dogodki... 10 3.5 Razpisi... 11 3.6 Iskanje... 13 3.7 Potisna sporočila... 13 3.8 Obveščanje po elektronski pošti... 16 4 SKLEP... 20 iii
KAZALO SLIK Slika 3.1: Zgradba informacijskega sistema...5 Slika 3.2: Struktura spletne strani...6 Slika 3.3: Struktura nadzorne plošče...7 Slika 3.4: Prijavno okno spletne strani...7 Slika 3.5: Prijavno okno nadzorne plošče...8 Slika 3.6: Registracijsko okno...9 Slika 3.15: Podroben pogled razpisa...12 Slika 3.8: Iskalnik spletne strani...13 Slika 3.4: Okno za potisna sporočila...16 Slika 3.5: Okno za obveščanje po elektronski pošti...17 Slika 3.6: Okno za uporabljanje nastavitev obveščanja preko elektronske pošte...19 KAZALO PROGRAMSKIH KOD Programska koda 3.1: Primer shranjevanja podatkov v polje in klic metode iz modela...10 Programska koda 3.1: Nastavitve potisnih sporočil za ios...14 Programska koda 3.2: Pošiljanje potisnih sporočil za ios...15 Programska koda 3.3: Pošiljanje potisnih sporočil za Android...15 Programska koda 3.4: Inicializacija elektronske pošte...18 UPORABLJENE KRATICE CI CodeIgniter CSS - Cascading Style Sheets HTML - Hyper Text Markup Language PHP - Hypertext Preprocessor REST - Representational state transfer iv
UVOD V tretjem letniku visokošolskega študija Računalništvo in informacijske tehnologije je potrebno opraviti praktično usposabljanje. Sam sem opravljal v startup podjetju Tom88 d.o.o., ki ima sedež v Mariboru. Zaupan mi je bil razvoj in načrtovanje spletnih vsebin. Za implementacijo sem uporabljal jezik PHP. Za lažji in hitrejši razvoj sem uporabljal PHP ogrodje CodeIgniter. 1
1 OPIS GOSPODARSKE DRUŽBE IN PRODUKTOV Tom88 d.o.o. je mlado podjetje, ki se ukvarja z razvojem IT rešitev. Ustanovljeno je bilo leta 2012, kot startup podjetje. Startup podjetje, ali zagonsko podjetje, ustanovijo ljudje, ki želijo spremeniti svet, oziroma stvari okoli sebe. V ta namen je bilo ustanovljeno podjetje Tom88 d.o.o. Podjetje se natančneje ukvarja z razvojem mobilnih, spletnih in namiznih aplikacij ter z grafičnim oblikovanjem. V podjetju smo se zbrali študentje iz Maribora, kateri študiramo na različnih fakultetah. Tomaž Kokot, študent druge stopnje Ekonomskoposlovne fakultete v Mariboru je skrbel za vodenje podjetja. 1.1 LifeSal Brezplačen farmacevtsko-zdravstveni pripomoček, namenjen uporabnikom pametnih mobilnih telefonov s platformami ios, Android in Windows Phone 9. Aplikacija uporabniku omogoča: prihranek pri nakupu lekarniških izdelkov, pregled vpliva vremena na počutje, nastavitev opomnikov za zdravila in kontracepcijo, prikaz lekarn v vaši bližini, menstrualni koledar, beleženje dnevnega vnosa kalorij s pomočjo števca kalorij, izračun indeksa telesne mase (ITM). 1.2 ŠOU Ljubljana Aplikacija omogoča študentom interaktivno povezavo s organizacijo ŠOU v Ljubljani. Spremljate lahko: dogodke, zabave, izobraževanja, razpise, poslušate radio, pregled zemljevida s fakultetami in študentskimi domovi, podatke o organizaciji. 2
1.3 Maribor Live Maribor Live je aplikacija izdelana za mestno občino Maribor. Uporabniki lahko šreko nje spremljajo dogajanja skozi spletne kamere, postavljene na različnih mestih v Mariboru. 1.4 Borut Pahor Aplikacija je bila izdelana za predvolilno kampanijo predsednika Republike Slovenije. Naročnik je bil Borut Pahor saj je želel vzpostaviti stik za mlajšo populacijo preko sodobnih tehnologij. Izdelana je bila mobilna aplikacija preko katere je obveščal o dogodkih in novicah. 1.5 Pinatio Pinatio je informacijski sistem, namenjen organizacijam za interaktivno komunikacijo z gledalci ali uporabniki. Za komunikacijo obsega mobilni in spletni odjemalec. Komunikacija in obdelava podatkov poteka realno časovno. 3
2 OPIS PRAKTIČNEGA IZOBRAŽEVANJA Ob prihodu v podjetje je bila moja prva naloga vzpostavitev delovnega okolja. Ker za operacijski sistem že uporabljal Ubuntu Desktop 13.10 sem namestil še samo takimenovani LAMP programski snop. Programski snop obsega Apache, MySQL in PHP. Za razvoj smo uporabljali orodje PhpStorm, katera smo si morali prav tako namestiti. Že v času študija me je razvoj spletnih rešitev zanimal, zato sem že imel osnovno znanje na tem področju. Po kratki seznanitvi z orodji sem dobil projekt»šou informator«. Projekt takšne velikosti sem delal prvič zato mi je bilo pomembno, da sem od vsega začetka zraven. Sodeloval sem pri načrtovanju izgleda in funkcionalnostih z naročnikom. Tako sem si lahko naredil nekakšen načrt razvoja. Opis same spletne aplikacije in njenega razvoja bomo opisali v naslednjem poglavju. 3 STROKOVNO PODROČJE ALI PROJEKT Izdelati sem moral spletno storitev, katera bo stregla podatke mobilnim aplikacijam in družbeno spletno stran»informator«, kateri se bo uporabljal za obveščanje in informiranje študentov o dogodkih, novicah in razpisih. Pri implementaciji sem uporabil programski jezik PHP, JavaScript, označevali jezik HTML5 in slogovni jezik CSS3. Za hitrejši in lažji razvoj spletne storitve in spletne strani sem uporabil PHP ogrodje CodeIgniter. Spletno storitev sem izdelal po arhitekturi REST. Uporabil sem tudi priljubljeno JavaScript knjižnico jquery. Za boljši uporabniško izkušnjo sem uporabil ogrodje Bootstrap za izgradnjo odzivnih spletnih strani in uporabil še izdelane gradnike. V nadaljevanju bomo na kratko pogledali načrtovanje in opisali implementacijo posameznih funkcionalnosti 4
3.1 Načrtovanje Pred implementacijo smo naredili načrt celotnega informacijskega sistema. Kot prikazuje Slika 3.1 imamo dve podatkovni bazi. Novo, ki smo ustvarili mi in v njej hranimo: dogodke kategorije za dogodke razpise priponke za razpise uporabnike administratorje fakultete ključe aplikacij za potisna sporočila operacijskega sistema ios ključe aplikacij za potisna sporočila operacijskega sistema Android obvestila oglasne bloke Slika 3.1: Zgradba informacijskega sistema Do novic pa dostopamo v bazo, katero že uporabljajo na njihovi spletni strani Študentske organizacije Univerze v Ljubljani. 5
Spletno stran smo pred implementacijo dobro načrtovali. Preučili smo funkcionalnosti spletne aplikacije in njihovo uporabo. Na Slika 3.2 vidimo strukturo strani spletne strani v vazi načrtovanja. Slika 3.2: Struktura spletne strani Do strukture, kot je vidna na Slika 3.3 za nadzorno ploščo smo prišli po skrbnem načrtovanju. Zadali smo si cilj, da ima administrator pregled nad vsemi funkcionalnostmi in lahko iz nadzorne plošče proži vse funkcionalnosti. 6
Slika 3.3: Struktura nadzorne plošče 3.2 Prijava Obiskovalci spletne strani lahko prebirajo dogodke, novice in razpise. Prijava na dogodek je omogočena samo v primeru prijave študenta v aplikacijo. To storijo preko prijavnega okna, ki je viden na Slika 3.4, kjer vpišejo elektronski naslov in geslo. Slika 3.4: Prijavno okno spletne strani 7
Pri dostopi v nadzorno ploščo se je prav tako potrebno vpisati z administratorjevim računom. To storimo preko prijavnega okna, ki je viden na Slika 3.5, kjer je potrebno vpisati uporabniško ime in geslo. Slika 3.5: Prijavno okno nadzorne plošče Natančneje bomo opisali prijavo uporabnika v spletno stran. Kot smo že povedali se prijavi preko prijavnega okna. Vneseni podatki se pošljejo v krmilnik (angl. controller) prijava kjer se kliče metoda vpis. V metodi pridobimo poslana podatka preko: $this->input->post('inputemail', true); Z klicem metode login() iz knjižnice login_uporabnik, z parametroma email in geslo, preverimo ali se ujemata z tistim v podatkovni bazi in vrnemo vrednost bool: $this->login_uporabnik->login($email, $geslo); Geslo zašifriramo s pomočjo funkcije hash('sha512', $geslo). V metodi prijava se v primeru, da je prijava uspela, ustvari seja v katero se zabeležijo id in email uporabnika, kot tudi čas prijave in unikaten id. Čas se zabeleži, da lahko uporabnika po določenem času v primeru neaktivnosti izpišemo. Tako se zavarujemo, če se uporabnik pozabi izpisati iz računa. V primeru, da je bila prijava neuspešna iz kakršnega koli razloga, krmilnik izpiše opozorilo. Ponudimo mu tudi možnost ponastavitve gesla, kjer mora vnesti svoj elektronski naslov. Ponastavitev gesla poteka v dveh korakih, da se zavarujemo pred zlorabi ponastavitve gesla. Kot prvo uporabnik na vnesen naslov dobi povezavo na katero klikne. Sistem mu na elektronski naslov pošlje novo geslo s katerim se potem lahko vpiše. 8
3.3 Registracija Obiskovalec skozi postopek registracije pridobi uporabniško ime in geslo s katerim se lahko potem prijavi v sistem in prijavlja na različne dogodke. Uporabnik na spletni strani najde povezavo do okna za registracijo. Na Slika 3.6 vidimo registracijsko okno. Slika 3.6: Registracijsko okno Uporabnik mora vnesti ime, priimek, telefonsko številko, fakulteto kjer študira, elektronski naslov, datum rojstva in geslo. Fakulteto izbere z klikom na»izberi fakulteto«, kjer se mu odpre modalno okno z vsemi fakultetami iz Univerze v Ljubljani. Prav tako izbere datum rojstva s pomočjo knjižnice DatePicker. Preverjanje vnesenih podatkov opravljamo že na strani uporabnika, kjer s pomočjo JavaScript-a na primer preverimo ali se vneseni gesli ujemata in ali je elektronski naslov v pravilni obliki. Podatke pošljemo v krmilnik prijava, kjer se kliče metoda registracija. V metodi še enkrat preverimo vse vnesene podatke na pravilnost. V primeru kakšne napake uporabnika obvestimo, da je prišlo do napake in naj registracijo prosim ponovi. Uporabnik je podatke vnesel pravilno potem se vsi podatki shranijo v polje in pošljejo v model uporabniki_model, kjer se shranijo v bazo. Primer shranjevanja v polje in klic metode iz modela vidimo v Programska koda 3.1. 9
$arr_data=array( 'email' => $this->input->post('inputemail', true), 'geslo' => $this->input->post('inputgeslo', true), 'fakulteta' => $this->input->post('inputfakulteta', true), 'ime' => $this->input->post('inputime', true), 'priimek' => $this->input->post('inputpriimek', true), 'tk_fakulteta' => $this->input->post('inputfakultetahidden', true), 'telefonska' => $this->input->post('inputtelefonska', true), 'datum_rojstva' =>date("y-m-d", strtotime($this->input->post('inputdatumrojstva', true))), 'query' => friendlyurl($this->input->post('inputime', true)." ". $this->input- >post('inputpriimek', true)) ); $this->uporabniki_model->dodajuporabnika($arr_data); Programska koda 3.1: Primer shranjevanja podatkov v polje in klic metode iz modela Po uspešnem zaključku registracije krmilnik uporabnika preusmeri na prijavno okno, kjer se lahko prijavi. 3.4 Dogodki Pri implementaciji dogodkov smo si najprej določili lastnosti dogodka. Dogodek ima: id: Unikatno število, naslov: Tekstovna oblika omejena na 70 znakov, kratek opis: Tekstovna oblika omejena na 160 znakov, kraj dogodka: Tekstovna oblika, začetek dogodka: Izbira s pomočjo koledarja, konec dogodka: izbira s pomočjo koledarja, vprašanje: Tekstovna oblika, odgovor: Tekstovna oblika, slika: Izbira datoteke, razpored: Tekstovna oblika, omejeno število prijav: Potrditveno polje, število prostih mest: Število 10
rok prijave: Izbira s pomočjo koledarja, cena: Število, tag: Radijski gumb, koordinate: Izbira na zemljevidu, vsebina: Bogata tekstovna oblika. Krmilnik dogodki ima naslednje metode: index(): Privzeta metoda, ki se zažene če izrecno ne navedemo metodo v krmilniku. Metoda s pomočjo modela pridobi podatke iz podatkovne baze o dogodki in zgradi pogled. pogled(): Ima vhodni parameter $dogodek_query. V primeru, da parameter ni bil podan ima vrednost false. Metoda preveri ali se vhodni parameter ujema z podatkovno bazo dogodi. V primeru ujemanja se zgradi pogled, kjer so vidni podrobni podatki določene novice. prijava(): Z to metodo opravljamo prijave in odjave na dogodke. Metoda je razdeljena na tri dele in sicer prvi del, kadar se uporabnik prijavlja na dogodek, drugi del je za odjavo od dogodka in tretji del je varnostni, ki ob kakršni koli napaki to sporoči uporabniku. Dogodek ima čas pričetka in čas ko se konča. Časa se upošteva pri prijavi in odjavi. Pri prijavi na dogodek se preveri ali se uporabnik lahko prijavi. Z knjižnice login_uporabnik pridobimo id trenutno prijavljenega uporabnika. Prijavo opravimo preko modela dogodki_model, ki od id-ju uporabnika in id-ju dogodka v bazo shrani prijavo uporabnika na dogodke. Odjava od dogodka potega na podoben način kot prijava, le da se v bazi shrani odjava. V primeru, da je dogodek omejen na prosta mesta se pri vsaki prijavi ali odjavi izračuna, koliko še je prostih mest. Pri pregledu dogodka pote uporabnik vidi ali še je možna prijava ali pa so bila vsa mesta že zasedena. 3.5 Razpisi Prav tako smo pred implementacijo naredili načrt razpisov. Določili smo lastnosti razpisa: id: Unikatno število, naslov: Tekstovna oblika omejena na 70 znakov, kratek opis: Tekstovna oblika omejena na 160 znakov, rok prijave: Izbira s pomočjo koledarja, elektronski naslov kontaktne osebe: Tekstovna oblika, 11
predmet razpisa: Tekstovna oblika, slika: Izbira datoteke, priponke: Izbira datoteke, pogoji: Bogata tekstovna oblika, vsebina: Bogata tekstovna oblika. Krmilnik razpisi ima naslednje metode: index(): Zgradi pogled na katerem je seznam zadnjih šest razpisov. pogled(): Ima vhodni parameter $razpis_query, ki ima vrednost false v primeru, da ni bil podan. Z modelom razpisi_model preveri v bazo ali se parameter ujema z razpisom. V primeru napake se izpiše opozorilo drugače se zgradi pogled, kjer so vse informacije razpisa vključno z priponkami, kot je to videno na Slika 3.7. Slika 3.7: Podroben pogled razpisa 12
3.6 Iskanje Spletna stran z veliko vsebine, ki se dnevno posodablja, mora biti narejena tako, da je čim bolj pregledna. K temu zelo pripomore iskalnik vsebine. Primer kako izgleda iskalnik na spletni strani»informator«je na Slika 3.8. Slika 3.8: Iskalnik spletne strani 3.7 Potisna sporočila Potisna sporočila (angl. Push Notification) dovolijo aplikaciji, da vas obvešča čeprav aplikacije trenutno ne uporabljate. Programerji imajo možnost nastavitve zvoka in izgleda sporočila. V nadaljevanju bomo opisali implementacijo potisnih sporočil za operacijska sistema ios in Android. Pri implementaciji potisnih sporočil za operacijski sistem ios smo si pomagali z CodeIgniter knjižnico APNS (angl. Apple Push Notification), ki jo je izdelal Benjamin Ortuzar Seconde. Knjižnica ima nastavitveni del, ki ga vidimo na Programska koda 3.2. Za potisna sporočila rabimo certifikat in geslo, ki ga prejme razvijalec mobilne aplikacije. 13
<?php /* Apple Push Notification Configurations APN Permission file */ $config['permissionfile'] = APPPATH.'certifikat.pem'; /* APN Private Key's Passphrase */ $config['passphrase'] = '**********'; Programska koda 3.2: Nastavitve potisnih sporočil za ios Pri implementaciji za Android smo si pa pomagali s CodeIgniter knjižnico GMC (angl. Google Cloud Messaging), ki jo je izdelal Anton Gorodezkiy. Obe knjižnici smo uporabilo v krmilniku obvescanje. Krmilnik ima naslednje metode: index(): Pokliče metodo dodajanje() dodajanje(): Metoda se proži kadar administrator obvesti mobilne aplikacije. Metoda preveri vnos naslova obvestila in vsebine obvestila. Pri napaki se obveščanje prekine in izpiše napaka. V primeru, da podatki ustrezajo kriterijem se najprej v bazo shrani čas, naslov in vsebina obveščanja. Preko modela obvestila_model se pridobijo vsi ključi ios in Android aplikacij. Pokliče se metoda obvesti(), ki ima parametre polje ključev obeh operacijskih sistemov, naslov in vsebino obvestila. obvesti(): Metoda prejme vhodne parametre polje ključev obeh operacijskih sistemov, naslov in vsebino obvestila. Pokliče metodo ios in metodo android. ios(): Metoda naloži knjižnico apn in v zanki obvesti vse ključe v polju z sporočilom. Podrobno lahko vidimo v Programska koda 3.3. 14
$this->load->library('apn'); $rez=array(); foreach ($arr as $i){ $this->apn->connecttopush(); $send_result = $this->apn->sendmessage($i['key'], $sporocilo, 1, 'default' ); if(!$send_result) $rez[]=$i['id']; $this->apn->disconnectpush(); } return $rez; Programska koda 3.3: Pošiljanje potisnih sporočil za ios android(): Metoda naloži knjižnico gmc in objektu knjižnice v zanki doda ključe prejemnikov. Kot je vidno na Programska koda 3.4 ustvari polje z naslovom in vsebino obvestila, katerega potem pripne potisnemu sporočilu. Določimo lahko tudi čas življenja sporočila in na koncu pošljemo. $this->load->library('gcm'); foreach ($arr as $a){ $this->gcm->addrecepient($a['key']); } $data=array( "Naslov" => $naslov, "Vsebina" => $vsebina ); $this->gcm->setdata($data); $this->gcm->setttl(500); if ($this->gcm->send()) return $this->gcm->messagesstatuses; else return $this->gcm->messagesstatuses; Programska koda 3.4: Pošiljanje potisnih sporočil za Android 15
Na Slika 3.9 je okno preko katerega lahko administrator pošilja potisna sporočila uporabnikom mobilen aplikacije. Vpogled ima tudi v zadnjih 10 obveščan. Kontrolnik za obveščanje je implementiran tako, da se lahko nadgradi še na ostale mobilne operacijske sisteme ne, da bi bilo potrebno kaj spreminjat uporabniški vmesnik. Slika 3.9: Okno za potisna sporočila 3.8 Obveščanje po elektronski pošti študentska organizacija lahko preko elektronske pošte ciljno obvešča študente o novostih. Študentje pri registraciji zraven elektronskega naslov, ki je potreben za obveščanje, še izpolnijo fakulteto, kjer študirajo in datum rojstva. Na Slika 3.10 vidimo okno za obveščanje po elektronski pošti. Administrator ima velik nabor lastnosti, kakšno ciljno skupino hoče obvestiti. Obvešča lahko posamezno po fakultetah ali pa po njihovi starosti. Starost smo izračunali iz datuma rojstva za vsakega študenta. 16
Slika 3.10: Okno za obveščanje po elektronski pošti Pri implementaciji uporabniškega vmesnika za obveščanje po elektronski pošti smo si pomagali z knjižnico jquery UI. Knjižnica je zgrajena iz JavaScript knjižnice jquery. Z njo lahko enostavno gradimo interaktivne spletne vmesnike. Kot je vidno na Slika 3.10 smo uporabili gradnik drsnik (angl. Slider) z katerim lahko izbiramo območje. V našem primeru je območje starost. Na levem drsniku nastavljamo spodnjo mejo starosti na desnem pa zgornjo mejo starosti študentov. Za obveščanje preko elektronske pošte smo implementirali krmilnik email. Krmilnik ima naslednje metode: index(): Pokličemo metodo obvesti(). nastavitve(): Metoda naloži pogled kot je viden na Slika 3.11. V primeru, da so bile dodane nove nastavitve pa pokliče metodo dodajanje(). obvesti(): Metoda naloži pogled kot je viden na Slika 3.10. Administrator izbere želeno ciljno skupino in vnese vsebino obvestila. Metoda obvesti() najprej preveri ali so bili podani vsi potrebni podatki. Tako v primeru, da se obveščajo vse fakultete se pokliče metoda posljiemailobestilavse() drugače pa posljiemailobvestilaposamezno(). dodajanje(): Metoda prejme preko metode post podatke domeno, uporabniško ime in geslo za poštni predal. Preverimo na praviln0ost podatkov in s pomočjo model email_model v podatkovni bazo shranimo nastavitve. Te nastavitve se potem pri vsakem pošiljanju elektronske pošte inicializirajo iz podatkovne baze. 17
posljiemailobvestilaposamezno(): Metoda iz baze pridobi nastavitve poštnega predala in inicializiramo nastavitve kot to vidimo v Programska koda 3.5. Iz podatkovne baze naredimo poizvedbo po uporabnikih, ki ustrezajo zahtevam administratorjevega obveščanja. Z foreach zanko gremo skozi uporabnike in pošljemo elektronsko pošto. $this->load->model('admin/email_model'); $emailconf=$this->email_model->getemailnastavitve(); $nastavitve = Array( 'protocol' => 'smtp', 'smtp_host' => $emailconf['host'], 'smtp_port' => 587, 'smtp_user' => $emailconf['user'], 'smtp_pass' => $emailconf['pass'], 'smtp_timeout' => 30, 'charset' => 'UTF-8', 'wordwrap' => TRUE, 'mailtype'=>'html' ); Programska koda 3.5: Inicializacija elektronske pošte posljiemailobestilavse(): Metoda naredi inicializacijo elektronske pošte kot je to vidno v Programska koda 3.5. Prav tako naredi poizvedbo v podatkovni bazo in pošlje elektronsko pošto uporabnikom. emailtest(): Metoda je namenjena preverjanju nastavitev za elektronsko pošto. Preizkus lahko naredi na oknu, ki je vidno na Slika 3.11. 18
Slika 3.11: Okno za uporabljanje nastavitev obveščanja preko elektronske pošte 19
4 SKLEP Skozi postopek praktičnega izobraževanja sem pridobil veliko novih izkušenj. Kot sem že zgoraj opisal sem sodeloval pri načrtovanju in implementaciji spletnih aplikacij. Tako sem znanje pridobljeno v šoli izkoristil in nadgradil. Izkusil sem prav tako, kako poteka delo v ekipi, kjer ne gre vedno vse po načrtih. Ker sem delo opravljal v startup podjetju smo ves čas bili enakopravni člani. Zelo je lahko vsak član aktivno sodeloval z svojimi idejami in pobudami. Potem pa smo se, kot ekipa odločili, kaj in kako bomo naredili. V ta namen, bi se zahvalil celotni ekipi Tom88 d.o.o. za sprejem in sodelovanje. Kot študent tretjega letnika, si nisem mogel predstavljati, da bom sposoben delati v ekipi programerjev. Ta ekipa me je sprejela in mi v primeru kakšnih težav takoj priskočila na pomoč. 20