Leaderboard con Firebase |LA VENDETTA|


LEADERBOARD CON FIREBASE

|LA VENDETTA| 

Benvenuti!

Oggi andremo a vedere come risolvere le imperfezioni riscontrate nell'altro articolo relativo alla classifica, per praticità partiremo direttamente con il codice e le varie riflessioni e ti rimando al post originale per tutte le altre info 👉 PRIMO POST . Come anticipato con il metodo precedente non si potevano registrare due giocatori con lo stesso punteggio ,offuscato dalla praticità nel riordinare e richiamare i tag non ho valutato questo aspetto, poco male sarà sempre una procedura in più mostrata. Sfortunatamente anche questo articolo inizia con qualche lacrima visto che per farmi perdonare volevo introdurre il componente dictionaries ma ho riscontrato vari errori , forse anche a causa di firebase, e non avendo ora tempo per studiare una soluzione dovrò temporeggiare. Ho introdotto qualche passaggio in più per evidenziare tutti i vari punti ma volendo potrete semplificare accorpando qualche blocco, partiamo subito creando due variabili lista che chiameremo temp e points e aggiungiamo anche un clock da designer editor e vedremo perché. La prima cosa che andremo a fare è impostare il button per l'invio del nome utente e del punteggio, entrambi questi valori potrebbero verine da delle variabili, io per praticità li inserirò in delle textbox per poter inserire i valori e inviarli a firebase. Come prima cosa ho introdotto una condizione per verificare se il valore introdotto come punteggio sia un numero e se i campi che sto inviando sono vuoti , in questo caso le textbox che utilizzerò, il tutto sarà concatenato usando l'operatore logico and visto che devono essere verificate tutte insieme. I due blocchi and
che vedete sul lato destro uno dentro l'altro è la stessa scrittura che usiamo all'interno del codice solo che ho cambiato la visualizzazione per praticità di lunghezza, questa versione compatta si ottiene con click di destra sul blocco e poi selezionando
collapse block. Il blocco is empty lo ritroviamo nella sezione text ed unito con la negazione not all'interno di logic ci permettono di verificare proprio se non è vuoto. Adesso con StoreValue salviamo il nome utente come tag e il punteggio come value , in questo modo anche più utenti potranno avere lo stesso punteggio e un giocatore comparirà solo una volta in classifica. Cancelliamo le textbox per il prossimo inserimento e procediamo con richiamare la lista di tutti i tag che questa volta non saranno tutti i punteggi ma tutti i giocatori, il blocco in questione è GetTagList. Questa è l'ipotesi in cui i campi sono editati correttamente mentre in caso contrario nell'else avremo il componente notifier per comunicare che ci sono errori nella compilazione dei vari valori. Che cosa succede nel momento in cui richiamiamo i valori di tutti i tag? When firebase TagList , uno dei blocchi di firebase, si attiva recuperando tutti questi valori e salvandoli all'interno della variabile value che troviamo sul blocco stesso, azzeriamo le liste che useremo e le textbox per visionare la nostra classifica, e adesso facciamo partire il nostro for each
 Una volta dato in pasto la lista dei tag (direttamente value) , per ognuno di loro, richiameremo il suo valore grazie a call GetValue che ricevendo item ad ogni nuovo passaggio chiamerà tutti i tag, finita questa operazione setteremo il clock attivo che andrà ad attivare l'ultimo passaggio. Infatti mentre GetValue chiama il database per ricevere le informazioni relative ai tag indicati (nel nostro caso tutti) il suo blocco amico GotValue ci fornisce sia il valore del tag che del suo valore, cosa che prima non avevamo. Ad ogni nuova ricezione dobbiamo salvare questi valori in qualche modo e qui mi sarebbe piaciuto introdurre il dictionaries visto che gioca proprio sulla corrispondenza di due valori particolari keys e values salvandoli in un formato facile da recuperare, non a caso ricorda proprio la struttura usata da firebase tag e value. Sfortunatamente questo non è stato possibile ma l'idea di salvare i dati in modo da accoppiarli e quindi collegarli tra loro mi piaceva molto visto che dovremo ordinare i tag e riallineare con i propri valori. Per questo motivo ho preferito salvare in una lista temporanea ogni elemento della lista come una lista a sua volta composta da due valori , ma attenzione invertiamo la posizione perché il primo dei due valori mi servirà come chiave per cercare nella lista , grazie ad un blocco molto interessante. Ricapitolando appena arrivano i valori del primo tag li salvo nella lista temporanea entrambi nella stessa posizione , quindi come elemento 1 della lista. Questo metodo si chiama lista di liste visto che ogni elemento della lista è esso stesso una lista. Al secondo arrivo salveremo nella posizione 2 l'elemento composto dalla lista valore e tag . La struttura sarà questa:
  • Elemento 1 della lista temp : - elemento 1 value1 - elemento 2 tag1 
  • Elemento 2 della lista temp : - elemento 1 value2 - elemento 2 tag2
  • Elemento 3 della lista temp : - elemento 1 value3 - elemento 2 tag3
  • Elemento 4 della lista temp : - elemento 1 value4 - elemento 2 tag4
Per fare questo nel campo dell'item dobbiamo semplicemente utilizzare un make a list per introdurre contemporaneamente due valori; il secondo blocco blue add item to list invece lo useremo nel modo canonico per creare una lista con tutti i punteggi. Una volta finito tutti i valori la palla ritorna al blocco precedente che attiva l'orologio settando enabled su true. Quando aggiungiamo l'orologio da designer editor andiamo nelle impostazioni sul lato destro e togliamo la spunta a enabled false e la lasciamo a AlwaysFires, l'interval lo settiamo molto basso , anche 100, perché ci serve solo per temporeggiare. Mi è già capitato con altri componenti e procedure dove aggiungendo un piccolo distacco temporale il codice funzioni correttamente mentre senza il codice si blocca. Fate anche voi la prova con e senza il clock e ditemi cosa succede. Probabilmente un programmatore saprebbe spiegarci il perché ma visto che io non lo sono accontentiamoci del mio escamotage 😂. 

Una volta attivato l'orologio al suo primo TIC manda in esecuzione la procedura che fantasiosamente ho lasciato nominata procedure e si spegne settando nuovamente enabled false. Questa procedura altro non è che la continuazione del blocco precedente che si blocca, quindi se volete fare la prova tutto quello che vedremo adesso dovrà andare al posto del primo blocco enabled true.
Per ultimare la nostra classifica dobbiamo prima di tutto ordinare in maniera decrescente (usando l'estensione vista nel tutorial precedente dove troverete anche il link per il download) i nostri valori e quindi salviamo nella variabile points sè stessa ma ordinata in maniera crescente grazie al metodo BubbleSort ( che sarà protagonista dei prossimi tutorial dove lo replicheremo sia con scratch che con AppInventor ) e poi invertita con il blocco reverse che dal colore ormai avrete imparato a collegare ai blocchi delle liste. Adesso non ci serve altro che portare i nostri dati visibili a schermo. Impostiamo un bel ciclo che scorra tutta la lista for each item prelevando tutti i valori dei punteggi ordinati nel modo corretto. Nel primo caso la label points sarà riempita ad ogni giro con il valore attuale unito , andando a capo \n, con il valore selezionato dalla lista così da incolonnare tutti gli elementi. Nel secondo caso la procedura è la medesima ma per selezionare l'elemento nella lista temp usiamo un blocco molto carino look up in pairs. Questo blocco da una lista di coppie, proprio come l'abbiamo creata noi, va a cercare l'elemento identificato come key (sarebbe il primo elemento della lista formata dai due elementi value-tag che abbiamo realizzato ) e ci restituisce il suo compagno , cioè il secondo elemento. Ecco perché abbiamo salvato le coppie usando prima il punteggio e poi il nome utente, perché una volta ordinata la lista, fornendo come key il valore del punteggio ci ritornerà il nome del giocatore.
Adesso è proprio ora di andare a nanna ma vi lascio i compiti da fare 😂  cercare un metodo per salvare e richiamare l'ultimo punteggio fatto in modo da confrontarlo con il nuovo e caricare il valore solo se maggiore del precedente, in questo modo avremo sempre e solo l' high score per ogni giocatore.

EDIT
Io però lo avevo detto che era tardi e dovevo andare a nanna 😂

Dobbiamo fare una piccola modifica o meglio aggiungere un piccolo pezzo perché mi sono accorto che se due utenti fanno lo stesso punteggio look up in pairs riconosce ( e direi giustamente ) solo il primo dei due non avendo nessuna funzione o simile per andare oltre nella ricerca. Ho realizzato quindi un blocco per cancellare i valori già inseriti in modo che questa situazione non si venga a verificare.

Come potete notare ho aggiunto un blocco alla fine della procedura che ad ogni ciclo cancella il valore già inserito così da non creare problemi.
Prima di tutto ho inizializzato una variabile locale che ho chiamato index ponendola pari a uno per il primo giro, si perché adesso andremo a scorrere la lista per effettuare una verifica, e ho inserito una condizione affinché lo stesso index non possa superare la lunghezza della lista in cui effettua la verifica, infatti non possiamo ricercare un elemento che abbia un indice inesistente. Inseriamo quindi un while test che continuerà a verificare che i due elementi inseriti siano diversi tra loro (li vedremo tra poco) e se sono effettivamente diversi entrando nella sezione do aumenteremo il nostro index per effettuare nuovamente la verifica. Fin quando la risposta alla domanda test  è vera (quindi i due elementi sono diversi) continueremo ad aumentare index e ci servirà per scorrere tutta la nostra lista temp alla ricerca del termine che in quel momento è stato lavorato dal for each precedente che andava a prendere il punteggio e il relativo utente collegato. Nel momento in cui invece i due elementi sotto il controllo del while risulteranno uguali non entreremo nella sezione do ma passeremo oltre andando a eliminare il termine in questione. 
Vediamo adesso i due termini che andiamo a verificare: il secondo lo conosciamo ed è quello proveniente dal blocco look up in pairs il primo invece è un elemento che preleviamo dalla lista global temp e come indice usiamo proprio index ma se ricordiamo bene come abbiamo gestito i dati questo elemento è proprio una lista formata da due elementi. Aguzzando la vista possiamo notare che ho utilizzato due volte il blocco select list item inserendo nel primo , come lista in cui cercare, proprio il blocco appena spiegato e prelevando l'indice numero due. Ricapitoliamo il primo elemento del while. Select list item va a prelevare il secondo elemento della lista che troviamo come primo elemento della nostra lista temp. La nostra lista temp ha come secondo elemento il  nome dell'utente che altro non è che il valore che troviamo con look up in pairs, se questi due valori sono uguali andrò a cancellare la coppia appena processata dal nostro for each per evitare che in caso di punteggio uguale di due utenti non arrivi mai a selezionare il secondo dei due per inserirlo in classifica. Sunto del sunto: il for each prende il punteggio dalla lista points lo inserisce in label insieme ad altri punteggi già presenti, fa lo stesso con il nome utente prelevandolo dalla lista temp come compagno di coppia prelevato tramite la key (sarebbe item, che è il punteggio) entra nel nuovo blocco e scorre la lista per trovare la coppia appena inserita e cancellarla tramite index. Tutto questa procedura perché non ho un riscontro diretto dell'indice collegato ad un elemento lista a differenza degli elementi normali dove possiamo usare il blocco che ci riferisce la sua posizione in lista.
Fine! 😔 Che dire amici al momento non sono riuscito a trovare una valida alternativa , appena la trovo la posto, se invece la trovate prima voi scrivete nei commenti o mandatemi una mail 😁
 
  
  
 Se hai apprezzato il mio lavoro offrimi un bel caffè 😍

 

Commenti

Ciao, spero ti piaccia il blog. Se ti fa piacere qui puoi offrirmi un caffè!

Post popolari in questo blog

GOOGLE SCRIPT & KODULAR READ, WRITE, UPDATE, DELETE

Tu lo conosci THUNKABLE?