Cerca con Google

Translate

17 luglio 2015

Tutorial 12 (Difficile) Custom TinyWebDB, salvataggio tabellone HighScore su cloud in MIT App Inventor - Parte 2


Parte 1 del tutorial Custom TinyWebDB HighScore

In questa seconda parte del tutorial per la realizzazione di un gioco con MIT App Inventor 2 con salvataggio degli highscore, vediamo l'applicazione Python da caricare in Google App Engine.

Se non lo avete già fatto studiatevi il tutorial sul custom TinyWebDB e su Google App Engine cliccando QUA , vi servirà anche oggi...

Lo scopo di questa seconda parte del tutorial è spiegarvi quello che ho fatto con l'applicazione Python che gira nella nostra console in Google App Engine.

In pratica ho modificato il servizio "base" usato in MIT App Inventor 2 dal componente TinyWebDB, per accettare come dati da salvare sempre una coppia "tag"/"value" ma nello specifico in "value" gli voglio passare sempre e solo una lista annidiata contenente delle coppie di valori (("NomeGiocatore1","PunteggioGiocatore1"),("NomeGiocatore2","PunteggioGiocatore2",...))
L'applicazione Python leggerà questa stringa; saprà come "interpretarla"; la metterà in ordine partendo dal "PunteggioGiocatorex" più alto ed infine la memorizzerà nel datastore di Google.

Facciamo subito un semplice esempio, se arriva questa stringa (in Python le liste sono rappresentate dalle parentesi quadre e le stringhe sono delimitate da '):

[['Seba','10'], [['Gianfranco','80'], [['Marco','20'],[['Massimo','125']]

L'app Python che ho modificato la prenderà come input e darà come output la stessa lista ma ordinata, quindi:

[['Massimo', '125'], ['Gianfranco', '80'], ['Marco', '20'], ['Seba', '10']]

(se volete provare a giocare un pò con Python, potete usare questo fantastico strumento online CodeSkulptor dove vedete il codice che ho inserito poi nell'app da caricare in GAE)

Per prima cosa dovete caricare la mia app Python personalizzata nella vostra Dashboard di Google App Engine, potete usare lo stesso metodo visto nel tutorial TinyWebDB solo che questa volta il file da caricare (.zip da scompattare e poi caricare tramite Google App Engine Launcher) sarà questo:

Custom TinyWebDB HighScore Service

Cambiate ovviamente "project-id" con il vostro tramite la console di Google App Engine, nel mio esempio il project-id è aihighscoredb-999


In questo modo il server web dove gira la mia app per la gestione degli HighScore sarà raggiungibile al seguente indirizzo (volendo fare le cose fatte bene bisognerebbe disabilitare la funzione "delete", è anche vero che se pubblicate solo il vostro gioco in formato .apk nessuno saprà mai l'indirizzo effettivo del vostro server TinyWebDB):

https://aihighscoredb-999.appspot.com/

Per implementare la vostra versione dovete modificare il file "app.yaml" ed inserire il VOSTRO project-id (quindi cambiatelo da aihighscoredb-999 e metteteci il vostro):


Senza addentrarci ora troppo nei tecnicismi, provate ad aprire il file "main.py" che contiene il codice sorgente Python dell'app che facciamo girare sui server Google.

Tra le tante linee di codice troverete la definizione della funzione "store" che viene richiamata dalla classe "StoreAValue" quando viene eseguito il metodo POST tramite il componente TinyWebDB di App Inventor 2.

Cercando di farla semplice, quando chiamiamo il metodo tramite AI "TinyWebDb1.StoreValue" tra le altre cose viene eseguito il codice nel blocco "def store" che vedete qui sotto:


Come vedete gli vengono passati proprio i valori di "tag" e "value" che ben conosciamo...

Per aiutarmi nella programmazione ho inserito dei comandi di debug (che stampano dei messaggi che possiamo vedere poi nella console GAE).

Il problema più grosso con cui mi sono scontrato è che il "value" passato da App Inventor era una stringa unicode mentre per ordinare i dati in Python mi serviva una struttura di tipo "list" su cui poi eseguire l'ordinamento.

Per i più curiosi spiego i passaggi principali che vengono fatti:

value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore')
Prende la stringa unicode "value", la normalizza (toglie i caratteri unicode) e mi ritorna una stringa "pulita" ascii (esempio se c'è un carattere "à" nel nome del giocatore lo sostituisco con "a").

value = value.replace('"', '')
Prende la stringa value e ci toglie tutti i caratteri " (infatti App Inventor li inserisce per ogni elemento della lista ma a noi in questo momento non ci servono più)

valuelist = [x.split(',') for x in value.strip('[]').split('],[')]
Questa è la parte più complicata...(grazie stackexchange!):
Dalla stringa in "value" rimuovo i caratteri [] e faccio uno split ad ogni sequenza di "],[" poi creo una nuova lista splittando ad ogni carattere "," rimasto.
Ora ho finalmente la mia lista [['nome1','punteggio1'],['nome2','punteggio2',...]]

valuelist = str(sorted(valuelist, key=lambda valuelist: int((valuelist[1])), reverse=True))
Qui ordino la lista (davvero potente Python) "valuelist" con il metodo "sorted", usando come chiave il punteggio (il primo indice di una lista in Python è sempre 0, quindi valuelist[1] contiene il secondo elemento, ovvero proprio il punteggio) e settando il flag reverse=True per ordinare dal più grande al più piccolo.
Usando il metodo str(object) converto l'oggetto "list" di nuovo in una stringa di testo (l'unico tipo di dato che può essere salvato e poi letto da TinyWebDB in AI)

value = valuelist
Visto che non volevo modificare troppo il codice ho usato la variabile d'appoggio "valuelist" negli step precedenti, quindi ora finita l'elaborazione ricopio il valore in "value"

Poi il codice non è più stato cambiato, quindi viene eseguito il codice per il salvataggio nel datastore di Google come il normale custom TinyWebDB service.

Se volete vedere cosa succede durante l'esecuzione della vostra applicazione Python, potete andare nella console App Engine, e portarvi sulla schermata dei log :


Nello specifico guardiamo cosa succede quando viene effettuata una richiesta POST tramite il componente TinyWebDB:


Vedete che gli arriva la lista annidiata e non ordinata ed alla fine viene salvata la stessa lista ma questa volta ordinata in base al punteggio.

Phew! Abbiamo finito, spero di essere stato abbastanza chiaro, ovviamente il codice potrebbe essere migliorato oppure ancora meglio adattato alle vostre esigenze (magari volete memorizzare non solo nome e punteggio ma anche la data in cui questo è stato fatto).
Penso che se mi avete seguito fin qua non sia un problema per voi modificare il codice per fare quello che vi serve!

Riporto per comodità i link a tutti i file del progetto:

Scarica il file sorgente .aia del gioco da QUA
Scarica il file compilato .apk del gioco da QUA
Scarica il file custom TinyWebDB Python da caricare in Google App Engine da QUA


3 commenti:

  1. Ciao Seb.
    Davvero interessante il tutorial che ci hai proposto. Mi chiedevo se l'applicazione Python da caricare in Google App Engine per ordinare le liste potrebbe essere sostituita con questa soluzione che ci propone Taifun https://groups.google.com/forum/#!msg/mitappinventortest/pVA3VUMN5W8/pZLttKYl3-8J. Comunque se così fosse, mi sembra piu' appropriata la tua soluzione in quanto è possibile modificare il codice in Python (tra l'altro ben commentato) personalizzandolo per le proprie app. Insomma far processare operazioni complesse ai server di google (tramite Python e Google App Engine) per restituire in ai2 un "piatto già pronto".
    Ciao e buona estate.

    RispondiElimina
  2. Hai ragione Fabio infatti ero partito anch'io guardando quel tutorial ma poi ho capito che era troppo complicato e si poteva fare in maniera a mio avviso più semplice tramite GaE.
    Una volta capito un po' il meccanismo è cambiando il codice credo che si possano fare cose molto interessanti allo stesso modo di come ho spiegato io in questo tutorial.
    Se realizzi qualcosa di interessante fammi sapere grazie per il commento ciao.

    RispondiElimina
  3. i read your full post and i really enjoyed your post.

    Android Cool Apps

    RispondiElimina