Igra stavkov - dokumentacija in skelet prototipa

main
Jurij Podgoršek 2024-12-12 21:11:40 +01:00
parent d120ca33f7
commit 55ba5afb93
40 changed files with 512 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

View File

View File

@ -0,0 +1,14 @@
;; This an Artanis ENTRY file, don't remove it!
(use-modules (artanis artanis)
;; Put modules you want to be imported here
;; only for this file, not controllers/views
(artanis utils))
;; Put whatever you want to be called before server initilization here
(init-server #:statics '(png gif jpg jpeg ico html js json csv xml css woff woff2 ttf))
(add-to-load-path (string-append (current-toplevel) "/lib"))
;; Put whatever you want to be called before server running here
(get "/" (lambda (rc) (redirect-to rc "/index.html")))

View File

View File

View File

View File

View File

@ -0,0 +1,308 @@
## -*- indent-tabs-mode:nil; coding: utf-8 -*-
## Copyright (C) 2021
## "Mu Lei" known as "NalaGinrut" <NalaGinrut@gmail.com>
## Artanis is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
## Artanis is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
## You should have received a copy of the GNU General Public License
## along with this program. If not, see <http://www.gnu.org/licenses/>.
## ---------------------------------------------------------------------
## The skeleton of config file, you may modify it on your own purpose.
## DON'T TYPE `;' AT THE END OF LINE!!!
## ---------------------------------------------------------------------
## Please read the manual or /etc/artanis/default.conf if you have problem
## to understand these items.
## Whether to use a database, if disabled, the database won't be initialized
## in the beginning, which saves memory and boot time.
## Some users may want to use GNU Artanis without configuring any databases, if
## that's your case please set it to `false' to avoid unintended errors.
## db.enable = <boolean>
db.enable = true
## What database server should be used, depends on the database installed
## on your machine.
## NOTE: If you use MariaDB then you should set it to mysql.
## db.dbd = mysql | postgresql | sqlite3
db.dbd = sqlite3
## The protocol for connecting the databse. If you use tcp, a socket port
## must be specified in the address. And if you choose socketfile, then you should
## specify the unix socket file managed by database server.
## db.proto = tcp | socketfile
db.proto = tcp
## The address of the database server.
## For example, MariaDB by default uses localhost:3306.
## db.addr = <string>
db.addr = 127.0.0.1:3306
## If you configured the database server to connect to a unix socket file,
## then you should fill this field with the file name.
## db.socketfile = <string>
db.socketfile = false
## User name to connect to the database server.
## db.username = <string>
db.username = root
## Password of the user to connect to the database server.
## db.passwd = <string>
db.passwd =
## The database name.
## db.name = <string>
db.name = igra-stavkov
## The engine of the database server.
## NOTE: for sqlite3, you must leave this field blank, as `db.engine = '
## If you remove this item, the default value InnoDB will be used.
## db.engine = <string>
db.engine = InnoDB
## The size of DB connection pool. If the specified size is less then required,
## then the task will be scheduled and sleep till there's available DB connection.
## db.poolsize = <integer>
db.poolsize = 64
## The management mode of DB connection pool:
## `increase' for increasing the pool size if any necessary, however it won't reduce back.
## `fixed' will not increase the pool size, if it lacks of DB connections, then it will
## be scheduled.
## db.pool = increase | fixed
db.pool = increase
## Whether to encode params automatically.
## (params rc "your_key") will be encoded by uri-encode.
## The username and passwd in :auth will be encoded by uri-encode.
## NOTE: It's your duty to call uri-decode to get proper value.
## NOTE: If you enable db.encodeparams then it's better to decode the related value
## twice in the client-side, since some requests may be sent from browsers, and
## they're already encoded.
## db.encodeparams = <boolean>
db.encodeparams = false
## Enable LPC (Lightweight Persistent Cache), this may require Redis.
## db.lpc = <boolean>
db.lpc = false
## Specify your own server info. It'll be Artanis-x.x.x by default, adding
## the artanis version number.
## server.info = <string>
server.info = GNU Artanis-0.6
## If you want to use Nginx for reversed-proxy, please enable it.
## server.nginx = enable | disable
server.nginx = false
## Charset in server side. utf-8 in default.
## NOTE: Don't change it unless you know what you're doing!
## server.charset = <string>
server.charset = utf-8
## The path of status page. You may customize your own status pages.
## If you're using application folder from `art create', then you may add your
## customized status pages in sys/pages, for example, if you create 404.html in
## sys/pages, then it will overload the original 404 page.
## server.syspage.path = <string>
server.syspage.path = /etc/artanis/pages
## Backlog of the socket.
## NOTE: Don't change it unless you really know what you're doing!
## server.backlog = <integer>
server.backlog = 128
## The length of the work queue in Artanis server.
## server.wqlen = <integer>
server.wqlen = 64
## The trigger mode of epoll. Please read epoll man page to know more.
## server.trigger = edge | level
server.trigger = edge
## The server core which is used for holding high concurrent connections.
## Artanis has a strong server core named Ragnarok, which is based on
## delimited-continuations to provide asynchronous non-blocking high concurrent serving.
## You may choose guile inner server which is weak, but useful when you are running
## Artanis on an operating system lacking key features to run Raganrok. For example,
## in GNU/Hurd, which has no epoll.
## You may choose fibers server implemented with threads and delimited continuations,
## which is preemptable by the timer you set.
## For more details please see https://github.com/wingo/fibers/wiki/Manual.
## server.engine = ragnarok | guile | fibers | <customized engine>
server.engine = ragnarok
## Timeout for any connection to Artanis (in seconds).
## 0 for always short live connections.
## server.timeout = <integer>
server.timeout = 60
## The the timeout for each event polling round, in miliseconds.
## server.polltimeout = <integer>
server.polltimeout = 500
## The buffer size (in bytes) of the connecting socket.
## In Ragnarok server core, the request handling will be scheduled when the socket
## buffer is full. This item affects the performance of socket I/O largely.
## Usually, if you're handling a large amount of small requests, it's better to set
## the buffer size to a small value.
## But if you're providing some kind of downloading or uploading service, it's better
## to set it to a larger one.
## A large buffer size will increase the latency of unserved requests.
## Please read the `Ragnarok server core' chapter to learn the design principle,
## if you need to do some tweaking.
## server.bufsize = <integer>
server.bufsize = 12288
## This is the most significant feature of Ragnarok server core.
## Please remember that there're no threads in GNU Artanis.
## All the tasks are based on delimited continuations, this kind of design is the
## so-called Green Threads, or modern terminology, Co-routines.
## GNU/Linux has introduced a feature named SO_REUSEPORT since 3.9.
## This feature let us start multiple Artanis instances listening to the same socket
## port. When requests come, the Linux kernel will do the necessary lock and allocation
## work for us to dispatch requests to these Artanis instances.
## server.multi = <boolean>
server.multi = false
## Enable WebSocket.
## server.websocket = <boolean>
server.websocket = true
## The path to public directory, this is useful for public static resources,
## for exaample, css/img/js, etc.
## server.pub = <string>
server.pub = pub
## Whether to use Linux specified sendfile interface.
## server.sendfile = <boolean>
server.sendfile = false
## Whether to use POSIX specific mmap for file I/O.
## server.mmapped = <boolean>
server.mmapped = false
## The allowed HTTP methods.
## server.allowedmethods = <methods-list>
server.allowedmethods = HEAD,GET,POST,PUT
## The path to find "manifest.json".
## server.jsmanifest = <string>
server.jsmanifest = pub
## The maximum payload size of WebSocket request in bytes. If it exceeds, then it
## will be segemented.
## websocket.maxpayload = <integer>
websocket.maxpayload = 18446744073709551615
## The minimum payload size of WebSocket request in bytes.
## Enlarge it to avoid slow 1-byte attack (only for fragment).
## websocket.minpayload = <integer>
websocket.minpayload = 1
## If fragment >= 0, then it's the size of the websocket frame fragment.
## If fragment = 0, then the websocket frame will not be fragmented.
## websocket.fragment = <integer>
websocket.fragment = 4096
## Maximum upload size in bytes from WebSocket request, the exceeded request
## will be fobidden.
## websocket.maxsize = <integer>
websocket.maxsize = 1024
## Timeout of WebSocket request, in seconds.
## websocket.timeout = <integer>
websocket.timeout = 64
## If disabled, you will have to use the IP address to connect instead of the
## hostname. e.g. `host.name = lambdachip.com'.
## host.name = <string> | disable
host.name = false
## The URL/IP of your hosting site.
## host.addr = <URL> | <IP>
host.addr = 10.27.3.12
## The listening port of your hosting site.
## host.port = <integer>
host.port = 3000
## Specify the protocol family.
## host.family = ipv4 | ipv6
host.family = ipv4
## Detect host or domain-name from specified path. This is useful when you run GNU Artanis inside a container.
## host.detectpath = <PATH>|<boolean>
host.detectpath = false
## Specify the session files path. Change according to your session engine.
## session.path = <PATH>
session.path = session
## Check the valid session, if it appears in multiple client IP, then fail. This may
## cause problems when your hosting is behind CDN, you may need to disable it if so.
## session.hijackcheck = <boolean>
session.hijackcheck = false
## Specify session engine. Here're supported backends:
## simple: uses hash table for memcache.
## db: uses RDBMS for storing sessions.
## file: stores session information into text files.
## redis: uses Redis for managing sessions.
## session.engine = simple | db | file | redis | redis@addr:port | <third-party-engine>
session.backend = simple
## Specify allowed upload file type, say, upload.types = jpg,png,gif.
## upload.types = <item-list>
upload.types = jpg,png,gif
## The path to put the uploaded files.
## upload.path = <PATH>
upload.path = upload
## The size limitation of uploaded file in bytes.
## upload.size = <interger>
upload.size = 5242880
## The command called by Sendmail module. It's strongly recommended to use `msmtp' to replace `sendmail'.
## mail.sender = <string>
mail.sender = /usr/bin/msmtp
## The maximum age of a cached page in seconds.
## This is the global maxage of any cache.
## If you want to specify maxage for certain page, please read the manual about the Cache.
## cache.maxage = <integer>
cache.maxage = 3600
## Wheather to enable debug mode.
## If you enable debug mode, Artanis will print debug information verbosely.
## The module you modified will be reloaded instantly, and the page view will be rendered as well.
## NOTE: This option will affect the performance, please use it for debug purposes only./
## debug.enable = <boolean>
debug.enable = false
## The paths that needs to be monitored in debug-mode.
## This will take advantage of `inotify' in GNU/Linux kernel.
## NOTE: We may support GNU/Hurd as well, with its file monitor mechanism, in the future.
## debug.monitor = <PATHs>
debug.monitor =
## Cookie expiration time in seconds.
## 1 hour is 3600
## 6 hours 21600
## 1 month 2592000
## cookie.expires = <integer>
cookie.expires = 3600
## End Of Artanis conf.

View File

View File

View File

View File

View File

View File

View File

View File

@ -0,0 +1,36 @@
<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.
<form>
<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>

View File

View File

View File

View File

View File

View File

View File

View File

@ -0,0 +1,3 @@
;; Do not touch anything!!!
;; All things here should be automatically handled properly!!!
()

151
vaja/plan.org 100644
View File

@ -0,0 +1,151 @@
* Plan za vajo
* 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 [[https://dthompson.us/projects/chickadee.html][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 [[https://git.kompot.si/lio/PonsapiCli][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
'
* tekstualna igra stavkov p
** 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.
** 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.
** 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.
** program
Izbrali smo artanis web framework: https://artanis.dev/
Namestitev:
- GNU guix: ~guix install artanis~
- Debian: ~apt install guix; guix install artanis~
*** 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
[[file:./igra-stavkov-1.png]]
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).
*** 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~:
#+begin_src html :tangle ./igra-stavkov/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.
<form>
<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>
#+end_src
Ker artanis privzeto ne prikazuje ~index.html~ datoteke, mu to zaukažemo z vnosom v fajlu ~ENTRY~:
#+begin_src scheme
(get "/" (lambda (rc) (redirect-to rc "index.html")))
#+end_src
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 z ~art 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!
[[file:igra-stavkov-2.png]]
** Nova soba
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):
#+begin_src conf
db.dbd = sqlite3
db.enable = true
#+end_src
In ponovno poženemo strežnik: ~art work -g~