Table of Contents
1. Plan za vajo
1.1. predlogi
- tekstualna igra stavkov
- tista s sestavljanjem povedi je pa iz une igre, mi smo dostkrat igral, neki v smislu, da mora igrat 6+ ljudi in pol vsak napise na vrh lista eno stvar in pol prepogne in list krozi – po vrsti grejo neki takega: kdo, kdaj, kje, zakaj, s cim, kaj dela … pol pa ven loh pridejo kr zabavni stavki … in da je odprto na spletni strani skos naslednje vprasanje, ko se odgovori zadnja stvar (kaj dela), se izpise poved med ze dokoncane, in se zacne nova
- igra v chickadee-ju
- klon she-bo? (https://www.myabandonware.com/game/she-bo-a6f)
- igra v canvasu (preko hoot) - v brskalniku
- Command line tool za prevode - prepis ponsapi-cli v guile
- CI (continuous integration) sistem:
- https://codeberg.org/jjba23/byggsteg
- tegale bi lahko uporabili ^
- ideja: imeti spletno stran, ki jo na njej sami lahko v zivo urejas (ima vgrajen urejevalnik) in v kolikor testi passajo, se kar sproti deploya
2. tekstualna igra stavkov
2.1. meta
Sem pišemo plan za program igranja igre. Poskušamo kratko in jedrnato opisati prvi prototip, ki naj čimprej deluje in je zavoljo enostavnosti karseda podoben igranju v živo. Ob pisanju se poraja veliko idej, za katere je bolje, da se potencialno uvedejo kasneje, sicer se cilj delujočega prototipa sproti prehitro oddaljuje.
2.2. homepage
Na home page imamo kratka navodila in formo nova igra s poljem stevilo igralcev. Submitanje forme te pelje na zgeneriran link, ki ga posljes soigralcem.
Na tem koraku se generira seja glede na število igralcev.
2.3. seja igre
Meta Podatki
- hash, ki je url
- stevilo igralcev
Vsak igralec dobi svoj id (in session). Nato se mu po vrsti prikazujejo vprasanja in on izpolnjuje vprasanja. Novo vprasanje se ti pojavi, ko vsi odgovorijo na trenutno vprasanje (lahko imamo nek semaforcek, kdo je ze odgovoril).
Igra "prepozna" obiskovalca nekako unikatno - lahko je session in cookie (kar se uporablja za user tracking), lahko pa je nek ID v browser local storage, ki zavaruje uporabnika pred cross-site trackingom. (@TODO tole je manjša komplikacija). Unikatna prepoznava je pomembna za deterministično prelivanje odgovorov.
Ko oddaš odgovore, te pelje na link za rezlultate, kjer piše, koliko odgovorov igralcov še čakamo. Ko so vsi oddali odgovore, se ti izpiše stavek, ki ga lahko prebereš ostalim igralcem.
2.4. program artanis
Izbrali smo artanis web framework: https://artanis.dev/ Namestitev:
- GNU guix:
guix install artanis
- Debian:
apt install guix; guix install artanis
2.4.1. boilerplate
Artanis ima orodje za terminal, imenovano art
. Z orodje mdr. pripravimo skelet novega projekta: art create igra-stavkov
.
Strežnik potem lahko poženemo z ukazoma:
cd igra-stavkov
art work
Strežnik se nam odpre na naslovu http://127.0.0.1:3000
Stran tako deluje samo lokalno, če jo želimo deliti z drugimi na omrežju, spremenimo konfiguracijo; v datoteki conf/artanis.conf
spremenimo host.addr = 127.0.0.1
v lasten IP naslov (v mojem primeru host.addr = 10.27.3.12
)
Drugi potem stran vidijo na naslovu http://<ip_naslov>:3000
, v času in kraju pisanja tega dokumenta je to http://10.27.3.12:3000
(deluje pa samo CTK wifi omrežju, na katerega sem trenutno povezan).
2.4.2. navodila za igro
Igro lahko igrata dva ali več igralcev. Igralci skupaj sestavljajo stavke, tako da vnaprej odgovarjajo na vprašanja:
- Kdo?
- Kdaj?
- Kje?
- zakaj?
- S čim?
- Kaj dela?
- v živo
Vsak igralec potrebuje listek in pisalo. Igralci skupaj odgovarjajo na vprašanja, po vsakem odgovoru pa listek prepognejo in podajo naprej. Svoj naslednji odgovor nato napišejo pod prepognjen del in spet podajo listek naprej. Ko odogovorijo na vsa vprašanja, še enkrat podajo listek naprej naslednjemu igralcu in preberejo cel stavek.
- na naši aplikaciji
Na naši aplikaciji je igra zelo podobna. Izberete število igralcev in ustvarite novo sobo za igranje. Povezavo do sobo pošljete soigralcem in po vrsti odgovarjate na vprašanja, dokler ne izpolnite vseh. Vsakemu igralcu se na koncu izpiše en sestavljen stavek.
Ustvarimo nov fajl na lokaciji
pub/index.html
:<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>igra stavkov</title> </head> <body> <h1>igra stavkov</h1> <h2>v živo</h2> <p> Vsak igralec potrebuje listek in pisalo. Igralci skupaj odgovarjajo na vprašanja, po vsakem odgovoru pa listek prepognejo in podajo naprej. Svoj naslednji odgovor nato napišejo pod prepognjen del in spet podajo listek naprej. Ko odogovorijo na vsa vprašanja, še enkrat podajo listek naprej naslednjemu igralcu in preberejo cel stavek. </p> <h2>prek spleta (naša varianta)</h2> <p> Vsak igralec potrebuje računalnik z brskalnikom in internetno povezavo. Dobavna veriga obsega rudnike redkih kovin, silicij, proizvodnjo čipov, komunikacijsko mrežo, etcetera. </p> <p> Na naši aplikaciji je igra zelo podobna. Izberete število igralcev in ustvarite novo sobo za igranje. Povezavo do sobo pošljete soigralcem in po vrsti odgovarjate na vprašanja, dokler ne izpolnite vseh. Vsakemu igralcu se na koncu izpiše en sestavljen stavek. </p> <form method="POST" action="/soba/ustvari"> <label for="num-of-players">Izberi število igralcev</label> <input type="number" min="1" name="num-of-players" id="num-of-players"></input> <input type="submit" value="igraj"> </form> </body> </html>
Ker artanis privzeto ne prikazuje
index.html
datoteke, mu to zaukažemo z vnosom v fajluENTRY
:(get "/" (lambda (rc) (redirect-to rc "index.html")))
Sprememba se ne zgodi "avtomatsko", ampak moramo prekiniti proces
art work
(Ctrl+C
), in ga ponovno pognati (art work
). Lahko ga pa poženemo tudi zart work -g
, načinu za razhroščevanje, ki ponovno naloži izvorno kodo, ko se le ta spremeni.Domača stran se nam zdaj naloži!
2.4.3. Nova soba
- (podatkovni) model sobe
Zavoljo enostavnosti v
conf/artanis.conf
omogočimo podporo za sqlite3 bazo (ki je v fajlu in tako nismo odvisno od dodatne programske opreme za shranjevanje stanja):db.dbd = sqlite3 db.enable = true
In ponovno poženemo strežnik:
art work -g
Soba ima dve lastnosti; unikaten ID in število igralcev.
Ustvarimo model zanjo:
art draw model soba
Tako se generira skelet podatkovnega modela za sobo v
app/models/soba.scm
, ki ga dopolnimo s potrebnimi podatki:(import (artanis mvc model)) (create-artanis-model soba ;ime modela (id auto (#:primary-key)) (stevilo_igralcev tinyint (#:not-null)))
- krmilnik (controller) sobe
Naloga krmilnika je, da ustvari novo sobo in igralko pelje na pravilni link za igranje, shranjuje odgovore in na koncu prikaže stavek.
Ustvarimo ga z ukazom:
art draw controller soba listek
To nam ustvari dva nova fajla,
app/controllers/soba.scm
, s katerim bomo omogočili obisk ustvarjene sobe terapp/view/soba/listek.html.tpl
, šablono za formular vnosa odgovorov (listek).Najprej pa moramo sobo narediti. V
ENTRY
dodamo pod prej ustvarjeno preusmeritev na index.html POST handler:
2.4.4. Forma za vprasanje
Forma za posamezno vprasanje
<form> <label for="vprasanje">{vprasanje}</label> <input id="vprasanje" name="vprasanje" type="textarea"></input> <input type="submit" value="odgovori"> </form>
Forma se submita glede na session cookie, ki ga ima igralec, k dolocenemu igralcu.
Submitanje vrne tip podatka listek. Ce listek nima vseh odgovorov, vrnemo formo z vprasanjem. Ce ima vse odgovore, prikazemo stavek.
2.4.5. Podatkovni model
listek:
- id od sobe (tip: string)
- kaj (tip odogovor - uuid)
- kdaj (tip odogovor)
- kje
- zakaj
- kako
- kaj
odgovor:
- vrednost (text)
- session igralca
- uuid
2.4.6. sablona za listek
Ce je listek ze izpolnjen - prikazi cel listek, to je sestavljen stavek.
Ce listek ni izponjen, prikazi samo zadnje neizpoljneno vprasanje.
Submitanje forme ti vrne naslednji listek (ce ga je igralec pred tabo izpolnil).
(list 10 20 30)
2.5. program guile web server
Primer za guile web server.
Začnemo z vključitvijo modula za spletni strežnik.
Beremo dva dokumenta iz uradne dokumentacije: https://www.gnu.org/software/guile/manual/html_node/Web-Server.html https://www.gnu.org/software/guile/manual/html_node/Web-Examples.html
#!/usr/bin/env guile !# (use-modules (web server)) (define (igra-stavkov-handler request request-body) (values '((content-type . (text/plain))) "IGRA STAVKOV SE PRIČENJA. OHOHO")) ;; tukajo mramo prebrat index.html in ga iprkazat ;; (define index-file (open-input-file "./nova-igra-stavkov/index.html")) ;; (let (contents (call-with-input-file "file.txt" get-string-all))) (run-server igra-stavkov-handler)
2.5.1. navodila
Dodamo html file z navodili:
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>igra stavkov</title> </head> <body> <h1>igra stavkov</h1> <h2>v živo</h2> <p> Vsak igralec potrebuje listek in pisalo. Igralci skupaj odgovarjajo na vprašanja, po vsakem odgovoru pa listek prepognejo in podajo naprej. Svoj naslednji odgovor nato napišejo pod prepognjen del in spet podajo listek naprej. Ko odogovorijo na vsa vprašanja, še enkrat podajo listek naprej naslednjemu igralcu in preberejo cel stavek. </p> <h2>prek spleta (naša varianta)</h2> <p> Vsak igralec potrebuje računalnik z brskalnikom in internetno povezavo. Dobavna veriga obsega rudnike redkih kovin, silicij, proizvodnjo čipov, komunikacijsko mrežo, etcetera. </p> <p> Na naši aplikaciji je igra zelo podobna. Izberete število igralcev in ustvarite novo sobo za igranje. Povezavo do sobo pošljete soigralcem in po vrsti odgovarjate na vprašanja, dokler ne izpolnite vseh. Vsakemu igralcu se na koncu izpiše en sestavljen stavek. </p> <form method="POST" action="/soba/ustvari"> <label for="num-of-players">Izberi število igralcev</label> <input type="number" min="1" name="num-of-players" id="num-of-players"></input> <input type="submit" value="igraj"> </form> </body> </html>
Potem prilagodimo handler, da vrne html dokument, ki je zgoraj definiran.
#!/usr/bin/env guile !# (use-modules (web server) (ice-9 binary-ports)) (define (igra-stavkov-handler request request-body) (values '((content-type . (text/html))) (call-with-input-file "index.html" get-bytevector-all))) ;; tukajo mramo prebrat index.html in ga iprkazat (display "strežnik igre stavkov teče: http://localhost:8080") (run-server igra-stavkov-handler)
Zdaj moramo pa procesirat obrazec. In sicer preberemo iz request
vrednost num-of-players
:
#!/usr/bin/env guile !# (use-modules (web server) (web request) (web response) (web uri) (ice-9 binary-ports)) (define (request-path-components request) (split-and-decode-uri-path (uri-path (request-uri request)))) (define (not-found request) (values (build-response #:code 404) (string-append "Stran ni najdena: " (uri->string (request-uri request))))) (define (ustvari-novo-sobo request-body) (display request-body) (values '((content-type . (text/html))) (string-append "<h1>Ustvari novo sobo za " st-igralcev " igralcev</h1>"))) (define (igra-stavkov-handler request request-body) (let ((pot (request-path-components request))) (cond ((equal? pot '()) (values '((content-type . (text/html))) (call-with-input-file "index.html" get-bytevector-all))) ((equal? pot '("soba" "ustvari")) (ustvari-novo-sobo request-body)) (else (not-found request))))) (display "strežnik igre stavkov teče: http://localhost:8080") (run-server igra-stavkov-handler)
#!/usr/bin/env guile !# (use-modules (web server) (web request) (web response) (web uri) (ice-9 binary-ports)) (define (request-path-components request) (split-and-decode-uri-path (uri-path (request-uri request)))) (define (not-found request) (values (build-response #:code 404) (string-append "Stran ni najdena: " (uri->string (request-uri request))))) (define (debug-info request body) (respond `((h1 "Debug!") (table (tr (th "header") (th "value")) ,@(map (lambda (pair) `(tr (td (tt ,(with-output-to-string (lambda () (display (car pair)))))) (td (tt ,(with-output-to-string (lambda () (write (cdr pair)))))))) (request-headers request)))))) (define (ustvari-novo-sobo request-body) (display request-body) (values '((content-type . (text/html))) "<h1>Ustvari novo sobo!</h1>")) (define (igra-stavkov-handler request request-body) (let ((pot (request-path-components request))) (cond ((equal? pot '()) (values '((content-type . (text/html))) (call-with-input-file "index.html" get-bytevector-all))) ((equal? pot '("soba" "ustvari")) (debug-info request request-body)) (else (not-found request))))) (display "strežnik igre stavkov teče: http://localhost:8080") (run-server igra-stavkov-handler)