Diferència entre revisions de la pàgina «Web Services: exemple Escacs»

De Cacauet Wiki
Salta a la navegació Salta a la cerca
 
(Hi ha 9 revisions intermèdies del mateix usuari que no es mostren)
Línia 25: Línia 25:
 
*** { color:'b', tipus:'peo', fila:2, col:3 }
 
*** { color:'b', tipus:'peo', fila:2, col:3 }
 
*** ...
 
*** ...
* torn: nº de torn (parells=mou blanca, senars=mou negra)
+
** torn: nº de torn (parells=mou blanca, senars=mou negra)
* inici: data + hora d'inici de partida (timestamp)
+
** inici: data + hora d'inici de partida (timestamp)
  
 
<br>
 
<br>
  
 
== Especificació ==
 
== Especificació ==
 +
El flux de la partida serà el següent:
 +
# Quan un usuari entra, se li assigna una partida en espera amb un identificador (pid).
 +
# L'usuari pot veure les pid en espera mitjançant el WS (/en_espera)
 +
# L'usuari pot seleccionar una de les partides amb el que es considera iniciada la partida.
 +
# L'oponent pot consultar si algú ha acceptat la seva partida mitjançant el WS (/partida)
 +
# Ambdós jugadors estan assabentats de l'estat de la partida, poden procedir a moure les peces adequadament.
 +
  
 
{| border="1" class="wikitable" style="border-collapse:collapse;"
 
{| border="1" class="wikitable" style="border-collapse:collapse;"
Línia 38: Línia 45:
 
! OUT (JSON)
 
! OUT (JSON)
 
|-
 
|-
| /partida
+
| /login
| ''pid'': id de partida (GET)
+
| ''nick'': pseudònim de l'usuari<br>''email'': adreça electrònica
| ''status'': ok/error<br>''msg'': detalls del error<br>''partida'': totes les dades de la partida
+
| ''status'': ok/error<br>''msg'': detalls del error<br>''uid'': identificador d'usuari<br>''pid'': partida oberta
 
|-
 
|-
 
| /en_espera
 
| /en_espera
 
|  
 
|  
| ''status'': ok/error<br>''msg'': detalls del error<br>''usuaris'': [] array d'usuaris en espera
+
| ''status'': ok/error<br>''msg'': detalls del error<br>''usuaris'': [] array de partides en espera (pid + nick)
 
|-
 
|-
 
| /juga
 
| /juga
| ''uid_adversari'': uid de la persona amb qui ens volem enfrontar<br>''uid_usuari'': la nostra uid
+
| ''pid'': pid de la partida en la que vols entrar.<br>''uid_usuari'': la nostra uid
 
| ''status'': ok/error<br>''msg'': detalls del error<br>''partida'': totes les dades de la partida
 
| ''status'': ok/error<br>''msg'': detalls del error<br>''partida'': totes les dades de la partida
 
|-
 
|-
| /login
+
| /partida
| ''nick'': pseudònim de l'usuari<br>''email'': adreça electrònica
+
| ''pid'': id de partida (GET)
| ''status'': ok/error<br>''msg'': detalls del error<br>''uid'': identificador d'usuari
+
| ''status'': ok/error<br>''msg'': detalls del error<br>''partida'': [] totes les dades de la partida
 
|-
 
|-
 
| /mou
 
| /mou
| ''pid'': id de partida<br>''fila_inici''<br>''col_inici''<br>''fila_dst''<br>''col_dst''
+
| ''uid'': usuari<br>''pid'': id de partida<br>''fila_inici''<br>''col_inici''<br>''fila_dst''<br>''col_dst''
| ''status'': ok/error<br>''msg'': detalls del error<br>''partida'': totes les dades de la partida
+
| ''status'': ok/error<br>''msg'': detalls del error<br>''partida'': [] totes les dades de la partida
 
|}
 
|}
 +
 +
<br>
 +
 +
== Ús de la API i comprovacions ==
 +
Per poder efectuar una partida haurem de seguir el següent procés:
 +
# <code>/login</code> : aconsegueixo el meu <code>uid</code>
 +
# <code>/en_espera</code> : aconsegueixo llista d'usuaris que volen començar partida
 +
# <code>/juga</code> : creem i comencem partida (<code>pid</code>)
 +
# <code>/mou</code> : efectuem moviments en la partida
 +
 +
El WS ha de controlar la partida. Per tant haurà de comprovar una sèrie de regles per donar un moviment per bo (en el mètode <code>mou</code>):
 +
* Comprovar que el lloc de destí és correcte per la peça a l'origen.
 +
* Comprovar que entremig del origen i destí no hi ha alguna peça obstaculitzant el pas (excepte pel cavall)
 +
* Comprovar si al lloc de destí hi ha una peça enemiga, i si la hi ha, eliminar-la de la partida.
 +
* Comprovar si el moviment ha creat una situació d'escac i mat, fet que acabaria la partida.
 +
* Retornar <code>{status:true}</code> o <code>{status:false}</code> si el moviment és correcte.
  
 
<br>
 
<br>
Línia 63: Línia 86:
 
== Recomanacions ==
 
== Recomanacions ==
 
* Instal·la mongodb, pymongo i cherrypy
 
* Instal·la mongodb, pymongo i cherrypy
* Fes un script que crei una partida amb les figures, etc.
+
* Crea el servidor bàsic amb ''cherrypy'' com en l'exemple del final.
 +
* Crea el endpoint <code>/login</code> com l'exemple, i afegeix les comprovacions:
 +
** Si existeix el mateix email i nick, retorna el uid existent
 +
** Si existeix el mateix email modifica el nick i retorna el uid
 +
** Si existeix el mateix nick amb diferent email li retorna error
 +
* Fes un mètode (p.ex. <code>/juga</code>) que crei una partida amb les figures amb la posició inicial
  
 
<br>
 
<br>
 +
 +
== Servei bàsic amb CherryPy ==
 +
<syntaxhighlight lang="python">
 +
import cherrypy, pymongo
 +
 
 +
class Escacs(object):
 +
    def __init__(self):
 +
        self.client = pymongo.MongoClient()
 +
        self.db = self.client.escacs
 +
        self.usuaris = self.db.usuaris
 +
        self.partides = self.db.partides
 +
   
 +
    @cherrypy.expose
 +
    def index(self):
 +
        return "SUPER ESCACS !!!!"
 +
 +
    @cherrypy.expose
 +
    @cherrypy.tools.json_in()
 +
    @cherrypy.tools.json_out()
 +
    def login(self):
 +
        # agafem dades
 +
        dades_in = cherrypy.request.json
 +
        email = dades_in["email"]
 +
        nick = dades_in["nick"]
 +
        # guardem l'usuari
 +
        uid = self.usuaris.save( {"email":email,"nick":nick,"estat":"en espera"} )
 +
        usuari = self.usuaris.find_one( {"_id":uid} )
 +
        # transformem el _id en string per que sigui JSON-serializable (si no, dona error)
 +
        usuari["_id"] = str(uid)
 +
        # retornem dades d'usuari
 +
        return usuari
 +
 +
cherrypy.quickstart( Escacs() )
 +
</syntaxhighlight>
 +
 +
 +
== Testejant l'exemple amb UnitTest ==
 +
Podeu anar a [[Unit Tests en Python]] per veure com efectuar tests sobre aquest WS.

Revisió de 15:47, 28 feb 2020

Article anterior: Web Services

Objectius[modifica]

Proposem un exercici amb web services. Volem fer un joc d'escacs disponible per diversos clients (aplicació browser desktop, aplicació mòbil, etc.)

En l'anterior article Web Services es proposa treballar amb MongoDB i utilitzar el framework CherryPy. Fes-li un cop d'ull per veure exemple pertinent.

Passem a especificar les diverses funcions que necessitem per implementar el WS:


Objectes del servei[modifica]

Els objectes de més alt nivell (usuaris, partides) corresponen a les col·leccions de MongoDB.

  • Usuari:
    • uid
    • Nick
    • email
    • estat
  • Partida:
    • pid
    • jugador_blanques: uid
    • jugador_negres: uid
    • fitxes: [] array amb les diverses peces del taulell i les seves posicions
      • { color:'b', tipus:'peo', fila:2, col:3 }
      • ...
    • torn: nº de torn (parells=mou blanca, senars=mou negra)
    • inici: data + hora d'inici de partida (timestamp)


Especificació[modifica]

El flux de la partida serà el següent:

  1. Quan un usuari entra, se li assigna una partida en espera amb un identificador (pid).
  2. L'usuari pot veure les pid en espera mitjançant el WS (/en_espera)
  3. L'usuari pot seleccionar una de les partides amb el que es considera iniciada la partida.
  4. L'oponent pot consultar si algú ha acceptat la seva partida mitjançant el WS (/partida)
  5. Ambdós jugadors estan assabentats de l'estat de la partida, poden procedir a moure les peces adequadament.


API
Endpoint IN (GET o POST+JSON) OUT (JSON)
/login nick: pseudònim de l'usuari
email: adreça electrònica
status: ok/error
msg: detalls del error
uid: identificador d'usuari
pid: partida oberta
/en_espera status: ok/error
msg: detalls del error
usuaris: [] array de partides en espera (pid + nick)
/juga pid: pid de la partida en la que vols entrar.
uid_usuari: la nostra uid
status: ok/error
msg: detalls del error
partida: totes les dades de la partida
/partida pid: id de partida (GET) status: ok/error
msg: detalls del error
partida: [] totes les dades de la partida
/mou uid: usuari
pid: id de partida
fila_inici
col_inici
fila_dst
col_dst
status: ok/error
msg: detalls del error
partida: [] totes les dades de la partida


Ús de la API i comprovacions[modifica]

Per poder efectuar una partida haurem de seguir el següent procés:

  1. /login : aconsegueixo el meu uid
  2. /en_espera : aconsegueixo llista d'usuaris que volen començar partida
  3. /juga : creem i comencem partida (pid)
  4. /mou : efectuem moviments en la partida

El WS ha de controlar la partida. Per tant haurà de comprovar una sèrie de regles per donar un moviment per bo (en el mètode mou):

  • Comprovar que el lloc de destí és correcte per la peça a l'origen.
  • Comprovar que entremig del origen i destí no hi ha alguna peça obstaculitzant el pas (excepte pel cavall)
  • Comprovar si al lloc de destí hi ha una peça enemiga, i si la hi ha, eliminar-la de la partida.
  • Comprovar si el moviment ha creat una situació d'escac i mat, fet que acabaria la partida.
  • Retornar {status:true} o {status:false} si el moviment és correcte.


Recomanacions[modifica]

  • Instal·la mongodb, pymongo i cherrypy
  • Crea el servidor bàsic amb cherrypy com en l'exemple del final.
  • Crea el endpoint /login com l'exemple, i afegeix les comprovacions:
    • Si existeix el mateix email i nick, retorna el uid existent
    • Si existeix el mateix email modifica el nick i retorna el uid
    • Si existeix el mateix nick amb diferent email li retorna error
  • Fes un mètode (p.ex. /juga) que crei una partida amb les figures amb la posició inicial


Servei bàsic amb CherryPy[modifica]

import cherrypy, pymongo
	  
class Escacs(object):
    def __init__(self):
        self.client = pymongo.MongoClient()
        self.db = self.client.escacs
        self.usuaris = self.db.usuaris
        self.partides = self.db.partides
    
    @cherrypy.expose
    def index(self):
        return "SUPER ESCACS !!!!"

    @cherrypy.expose
    @cherrypy.tools.json_in()
    @cherrypy.tools.json_out()
    def login(self):
        # agafem dades
        dades_in = cherrypy.request.json
        email = dades_in["email"]
        nick = dades_in["nick"]
        # guardem l'usuari
        uid = self.usuaris.save( {"email":email,"nick":nick,"estat":"en espera"} )
        usuari = self.usuaris.find_one( {"_id":uid} )
        # transformem el _id en string per que sigui JSON-serializable (si no, dona error)
        usuari["_id"] = str(uid)
        # retornem dades d'usuari
        return usuari

cherrypy.quickstart( Escacs() )


Testejant l'exemple amb UnitTest[modifica]

Podeu anar a Unit Tests en Python per veure com efectuar tests sobre aquest WS.