lunedì, 21 Aprile 2025

[javascript] Realizzare un gioco di carte tipo Memory utilizzando jQuery

Obiettivo: realizzare un semplice gioco di carte tipo Memory, utilizzando JavaScript e il framework jQuery.

Per chi non conoscesse il Memory, il gioco consiste nel cercare di indovinare le coppie di carte uguali. All’inizio possono venir mostrate tutte le carte (se vogliamo dare un’aiuto iniziale) che poi vengono coperte; a quel punto si tirano su due carte per volta per vedere se sono uguali: se lo sono le lasciamo scoperte, altrimenti le ricopriamo e procediamo col sollevare un’altra coppia e così via.

La versione giocabile del gioco, realizzato come illustrato nell’articolo, si trova in fondo all’articolo

Il gioco può essere elaborato in diverse varianti, a fini di questo semplice esercizio prendiamo in considerazione le seguenti regole:

  1. Al primo turno vengono mostrate per un attimo tutte le carte, dopodiché vengono nascoste
  2. Quando il giocatore solleva due carte uguali queste vengono lasciate scoperte e vengono assegnati dei punti
  3. Se le carte non sono uguali le ricopriamo nuovamente
  4. Per ogni coppia di carte scoperte assegniamo dei punti, determinati anche in base allo scorrere del tempo (prima si scoprono e più punti si guadagnano); diamo un punteggio maggiorato se le carte vengono trovate uguali in sequenza
  5. Una volta che tutte le carte sono state scoperte il gioco finisce

Prima di procedere oltre nello sviluppo del programma vediamo di cosa avremo bisogno (e cosa ho utilizzato):

Detto questo il risultato che vogliamo ottenere sarà simile a questo qua:

Costruiamo adesso l’idea del programma, che andremo a sviluppare come una singola classe in JavaScript che conterrà tutte le varie funzioni.

Il funzionamento lo potremmo riassumere in questo modo:

Cominciamo quindi costruendo la nostra pagina in HTML che conterrà lo script, per farla utilizziamo il prototipo base di Bootstrap nel modo seguente:

Alla riga 15 abbiamo il pezzo di codice che riguarda il contenitore del gioco, nel mio caso un div. Questa parte si ricollega a quella direttamente utilizzata nel javascript, nel file carte.js.

Affinché la classe funzioni in questo modo dobbiamo far sì che il costruttore accetti per argomento un dizionario e lo utilizzi per parametrizzare le opzioni dell’oggetto. Cominciamo quindi costruendo anche la nostra classe nel modo seguente:

Nel nostro costruttore dichiareremo le impostazioni come una variabile globale this.impostazioni = {}. Faccio notare che, a differenza di altri linguaggi di programmazione, le variabili (eccettuati i casi dei getter e dei setter) non possono essere dichiarate a livello di classe, ma esclusivamente dentro i metodi. Il prefisso this fa sì che la variabile sia globale, sebbene con alcune specifiche eccezioni che vedremo.

Implementiamo ulteriormente la classe nel modo seguente:

Per far sì che le impostazioni dell’utente si sovrappongano alle impostazioni predefinite utilizziamo l’istruzione this.impostazioni = Object.assign({},this.impostazioni,impostazioni). In questo modo uniamo i due dizionari in un nuovo dizionario vuoto e trascriviamo tutto su this.impostazioni. In questo caso è molto importante l’ordine, difatti this.impostazioni viene assegnato prima di impostazioni, dizionario che contiene la parametrizzazione a livello utente. Così le nuove impostazioni andranno a sovrascrivere quelle precedenti, creando il dizionario definitivo delle impostazioni.

Adesso andiamo a creare il metodo di caricamento nella maniera seguente:

Qui stiamo utilizzando due metodi che non abbiamo ancora dichiarato, ovvero this.creazioneStile() e this.creazioneHome(). Con this.contenitore = $(this.impostazioni.contenitore); intercettiamo il contenitore predefinito in precedenza e applichiamo, successivamente gli stili di base. Avrei potuto utilizzare anche un file CSS separato per la parametrizzazione degli stili, ma allo scopo di esercizio ho preferito fare tutto tramite JavaScript all’interno della classe stessa.

Delle istruzioni precedenti è molto importante passare l’opzione this.contenitore.css("position", "relative"); che definirà la posizione del contenitore come relativa. In questo modo potremo utilizzare internamente i riferimenti assoluti per posizionare i vari elementi. Senza la dichiarazione di posizione relativa in modo esplicito, gli elementi interni si sarebbero posizionati rispetto al primo oggetto genitore del contenitore che abbia una posizione dichiarata esplicitamente.

Per il metodo this.creazioneStile() procediamo nel modo seguente:

Sostanzialmente creiamo una sezione <style></style> all’interno del codice dentro la quale andremo ad aggiungere tutti gli stili. Per evitare sovrapposizioni esterne al contenitore anteponiamo ad ogni stile il descrittore in CSS del contenitore con this.impostazioni.contenitore. Infine aggiungiamo il gruppo di stile nell’intestazione con l’istruzione $('html > head').append(stile);

Dentro questo metodo procederemo ad aggiungere via via i vari stili di cui abbiamo bisogno.

Per il metodo this.creazioneHome() procediamo aggiungendo la seguente porzione di codice:

In questo metodo andremo a creare this.creazioneGioco() che verrà richiamato al click su START nella schermata di inizio. Quello che mi interessa in particolare durante questo passaggio è l’utilizzo di this. All’interno dell’evento click this si riferisce all’elemento oggetto del click. Di conseguenza non è più utilizzabile per riferirsi agli oggetti della classe. Per poterlo utilizzare dobbiamo riassegnarlo ad una variabile locale nel metodo genitore, come per esempio var questo = this;

In questo modo dentro l’evento di click potremo utilizzare l’istruzione questo.creazioneGioco(); che richiama un metodo della classe medesima (che dobbiamo ancora creare).

Per la creazione del gioco procediamo nel modo seguente:

Siccome il gioco potrà essere creato diverse volte, per esempio quando si riavvia durante la partita, oppure dopo che si è vinto, ci dobbiamo assicurare che tutte le variabili di gioco vengano inizializzate, ed eventualmente reimpostate, qui.

I metodi che mi interessano in particolare sono:

  1. this.carte = $.merge($.merge([], this.impostazioni.immagini), this.impostazioni.immagini); che ci consente di creare le 16 carte di cui avremo bisogno. Ricordiamoci che le carte sono in coppie quindi le 8 carte iniziali dovranno essere duplicate. Per farlo voglio unire lo stesso dizionario, dentro this.impostazioni.immagini, a se medesimo. Affinché la funzione $.merge non crei un puntatore sul vettore, continuando ad aggiungere le solite immagini ad ogni riavvio successivo e quindi scombinando il gioco, bisogna usare il trucco di chiamare il metodo con un vettore vuoto a cui viene accodato il vettore originale, con l’istruzione $.merge([], this.impostazioni.immagini). Adesso abbiamo creato un vettore completamente nuovo, che potremo poi accodare al solito vettore di prima ripetendo il passaggio una seconda volta. Se non si procede in questo modo al primo riavvio del gioco si rischieranno di avere 3 o 4 carte dello stesso tipo, perché in totale non saranno più 16 ma 32, poi 48 ecc.
  2. this.carte.sort(() => Math.random() - 0.5); che ci permette di ordinare casualmente le carte. Non è un metodo particolarmente efficiente e non produce nemmeno un livello di casualità particolarmente affidabile. Per generare una password non sarebbe quindi molto opportuno, ma per gli scopi che ci servono ai fini del gioco va benissimo, specialmente per la sua brevità di scrittura. Questa scrittura è anche la medesima di this.carte.sort(function(){ return Math.random() - 0.5; });
  3. $('#combo'+this.impostazioni.idunivoco).hide(); che nasconde il contenitore delle combo (poi vedremo meglio)
  4. for(var i = 0; i < 16; i++ ) this.creaCarta(i); che inserisce le carte nell’ordine casuale determinato dal primo punto

Procediamo adesso con la creazione del menu utilizzando this.creazioneMenu();

Faccio notare che il metodo di “restart” è praticamente identico al metodo che abbiamo visto per lo “start” nella home. Stessa procedura. Nel menu abbiamo aggiunto una voce per il punteggio corrente, una per il tempo trascorso e il tasto che consenta di ricominciare.

La creazione del timer implicherà due diversi passaggi, nella maniera seguente:

Il metodo contatoreTimer() si richiamerà su se stesso ogni 500 millisecondi su se stessa, aggiornando lo stato del gioco e dichiarando infine la conclusione dello stesso. In tale contesto andremo anche a calcolare il tempo trascorso e ad aggiornarlo nella visualizzazione.

Arriviamo adesso alla parte più importante, quella dove creiamo le carte e definiamo il funzionamento del gioco. Ricordiamoci che ogni carta dovrà essere cliccabile.

Per gestire la rotazione delle carte stiamo utilizzando jQuery Flip, che ci permette sostanzialmente di ruotare gli elementi sia manualmente che ad ogni click.

Per ogni carta, procedendo in ordine, definiamo quindi le singole proprietà di CSS e attribuiamo la caratteristica flip. Dopodiché al click su ogni carta procediamo con l’impostazione della struttura di gioco. Anzitutto verifichiamo che il gioco sia iniziato e che la carta sia cliccabile. Se la carta è giocabile e non è ancora stata aperta, apriamola con $(this).flip(false). Leggiamo il nome della carta con var cartagiocata = $(this).attr('data-nome'). Se la carta attuale non è ancora stata impostata, allora impostiamola e blocchiamo la carta con $(this).attr('data-giocabile',0). In caso contrario vuol dire che abbiamo già aperto una carta e quindi dobbiamo verificare se il risultato sia corretto o meno. Se la carta attuale è uguale a quella giocata allora vuol dire che è tutto corretto; blocchiamo quindi la carta, aumentiamo il conteggio delle carte aperte consecutivamente con questo.consecutivi++, incrementiamo il punteggio con questo.incrementaPunteggio() e conteggiamo il numero totale di carte aperte (8 coppie trovate equivale alla fine del gioco). Se le carte non sono uguali, allora diamo 800 millisecondi all’utente per poterle vedere entrambe e poi richiudiamole e reimpostiamole giocabili.

Nel suo complesso il codice che avremo creato sarà il seguente (ho incluso alcuni altri commenti specifici nel codice, per spiegare i singoli passaggi):

Per chiunque volesse cimentarsi nel gioco ne riporto di seguito anche la versione giocabile. Inutile dire che ci sarebbero ulteriori possibilità di perfezionamento e che nel gioco ci sono anche alcuni bug che accadono quando si clicca troppo rapidamente tra una carta e l’altra.

Facendo un po’ di prove per ora il meglio che sono riuscito a ottenere, senza usare sotterfugi come screenshot e simili, è stato il seguente risultato:

[excel] Creare un grafico variabile che si adatti alla lunghezza della serie, sfruttando le matrici

Obiettivo: voglio realizzare un grafico che prenda in input n valori x e y, dove n è un valore arbitrario. Questo significa che se imposto n = 7 allora avrò 7 valori di x e y opportunamente calcolati. Per esempio potrebbe trattarsi del valore annuale delle rate di un mutuo calcolato su n anni; quindi se metto 10 anni mi aspetto un grafico con 10 colonne, se metto 20 anni mi aspetto un grafico con 20 colonne, ecc.

Nel caso specifico voglio realizzare qualcosa che dia il seguente risultato.

Per una simulazione con n = 25 anni

Per una simulazione con n = 30 anni

Faccio notare che il grafico è rimasto lo stesso, non ho dovuto rifarlo, ma è aumentato il numero di valori sull’asse delle ascisse in base al numero di anni prescelto.

Per l’esercizio voglio anche sfruttare le nuove possibilità offerte dal recente aggiornamento di Office 365 in merito al calcolo e alla visualizzazione delle matrici.

La versione di Excel che ho utilizzato è la Versione 1912 (build 12325.20298) e non tutte le funzionalità potrebbero essere disponibili nelle versioni precedenti.

Detto tutto questo cominciamo.

Anzitutto quello che voglio realizzare, a titolo di esercizio, è un simulatore semplificato di investimento con mutuo. Vogliamo cioè costruire il business plan per la realizzazione di un qualche progetto che avrà un rendimento annuale e per il quale vogliamo chiedere un finanziamento. I dati di cui avremo bisogno in input saranno quindi

  1. Valore complessivo del progetto (es. 250.000€)
  2. Valore del mutuo per il finanziamento iniziale (mutuo calcolato a tasso fisso su una percentuale del valore del progetto, per esempio l’80% al 3% in 15 anni con rate mensili)
  3. Entrate annuali per il progetto operativo (es. 30.000€ / anno)
  4. Durata del progetto (es. 30 anni)
  5. Tasso di inflazione (es. 2%)

Predisponiamo quindi i valori in input a partire dalla cella C4 nel modo seguente:

Di tutti i valori l’unico calcolato è il valore della rata, dove abbiamo la seguente formula:

Rinominiamo il foglio su cui stiamo lavorando in MUTUO, questo ci servirà dopo:

Adesso calcoliamo i valori di gestione disponendoli nel modo seguente a partire dalla cella H4.

Calcoliamo gli anni che partiranno da 0 fino all’anno indicato in D10. Se in D10 ci fosse 30 il numero totale di anni sarebbe quindi 31. Il numero di anni sarà quindi sempre n + 1. Dal punto di vista teorico l’anno 0 è quello degli investimenti pre-operativi; non è indispensabile ai fini dell’esercizio ma, sebbene stiamo facendo un esempio semplificato, facciamo le cose per bene.

Voglio che gli anni siano generati, come tutto il resto, in modo dinamico senza dover predisporre un numero massimo di valori possibili. Per farlo sfruttiamo le funzioni sulle matrici di excel nel modo seguente:

Inserendo questo valore in H5 nelle celle sottostanti verranno automaticamente completati i dati conseguenti. Selezionando la cella H5 ci verrà mostrata una selezione blu sottostante:

I dati evidenziati non sono inseriti nelle celle, ma generati automaticamente in quanto il risultato in H5 è una matrice colonna contenente i valori calcolati.

Procediamo in modo analogo per le colonne seguenti. Dal momento che vogliamo che ogni colonna sia generata per intero e non debba fare affidamento sulla colonna a fianco, procederemo col calcolo matriciale. Per le rate inseriremo in I5 la seguente formula:

Nel caso specifico dobbiamo usare un doppio se, perché la funzione =E() non è compatibile col calcolo matriciale. Con il primo SE verifichiamo che l’anno sia maggiore di 0, con il secondo SE verifichiamo che l’anno sia minore o uguale all’anno finale del mutuo, in tal caso inseriamo il valore della rata in D12, altrimenti lasciamo a 0.

Per la colonna dei costi, che, come nell’immagine precedente, avrà in realtà un unico valore e il resto a 0, inseriamo la seguente formula:

In pratica l’unico costo iniziale che abbiamo è la parte del progetto non coperta dal mutuo, calcolata con la formula -D4*(1-D7)

Nella colonna delle entrate inseriamo la seguente formula:

In modo analogo a prima quando l’anno è maggiore di 0 allora mettiamo il valore delle entrate annuali in D9. Il risultato lo dividiamo per (1+2%)^anno, dove il 2% è il tasso di inflazione e l’anno è l’anno corrente. Potremmo discutere se mettere al primo anno come anno 1 oppure 0, ma non è questa la sede. Nel mio caso lascerò il valore a 1.

A questo punto scriviamo la colonna della cassa. Questa è la più semplice da realizzare perché è semplicemente la somma delle precedenti tre formule, messe in fila una dopo l’altra.

Adesso vogliamo calcolare il cumulativo di cassa. Qui le cose si complicano perché lo vogliamo fare sulle matrici.

Per intendersi ipotizziamo di avere i seguenti valori: 1, 2, 3, 4, 5

Il valore cumulativo sarebbe dunque: 1, 3, 6, 10, 15

Ovvero la somma di tutti i valori precedenti al valore corrente.

Adesso noi sappiamo che l’istruzione RIF.RIGA(INDIRETTO("1:"&(D10+1))) ci dà dei valori che vanno da 1 a n+1. I valori della cassa si troveranno via via in L5:L[x] dove L[x] sarà in sequenza: L5, L6, L7 ecc.

Quindi possiamo sfruttare l’istruzione precedente sommandole un +4 per trovare tutti i valori di L[x] di cui abbiamo bisogno.

In questo modo verrà generata una serie di matrici contenenti ciascuna i valori da sommare. Per capirsi, riprendendo la sequenza numerica di prima, il risultato sarebbe simile a questo:

La funzione =SOMMA() applicata alla seconda matrice darebbe purtroppo un UNICO risultato. Per ottenere una matrice colonna con la somma delle singole righe della matrice quadrata dobbiamo usare la funzione =SOMMA.SE(). La condizione di somma sarà banalmente <>0

La formula che quindi andremo ad inserire sarà:

Fatte tutte queste belle cose avremo costruito la tabella come mostrato prima.

Questa tabella cambierà automaticamente di dimensione in base al numero di anni. Se per esempio mettessimo gli anni del mutuo a 8 e l’operatività complessiva a 15 passeremmo a qualcosa come questo:

A questo punto andiamo a realizzare il grafico. Per farlo sfrutteremo la definizione dei nomi.

Anzitutto andiamo in Formule > Gestione nomi

Da qui definiremo i nomi nel modo seguente:

Attribuiamo un nome e creiamo un riferimento. In tutti i casi sfrutteremo la funzione scarto che partirà sempre dalla riga 5 e si estenderà per una altezza di n – 1 valori, dal momento che la colonna possiede un titolo. Creiamo quindi i seguenti nomi:

CASSA

CUMULATIVO

ANNI

Andiamo adesso ad inserire un istogramma da Inserisci > Grafici

In seleziona dati aggiungiamo due voci di serie, nello specifico CASSA e CUMULATIVO

Nel nome della serie scriviamo via via la descrizione, per esempio Cassa, mentre nei valori scriviamo:

Ricordiamoci che MUTUO è il nome del foglio. E’ molto importante anteporre alla definizione del nome il nome del foglio, altrimenti non funzionerà.

Alla voce etichette inseriamo:

Il risultato che otterremo sarà simile a questo:

Fatto questo otterremo un grafico simile al seguente:

Per trasformare il flusso cumulativo in una linea, anziché nell’istogramma, clicchiamo col destro su una delle colonne arancioni e scegliamo Cambia tipo di grafico serie…

Nella finestra che si aprirà selezioniamo, dal menu a tendina, la voce Linee

Se abbiamo fatto tutto bene otterremo un grafico come il seguente:

Il grafico cambierà dimensione al variare dei valori in input.

Il vantaggio di questa soluzione è che potremmo inserire valori assolutamente arbitrari per la lunghezza complessiva dei dati, senza doverla predisporre in anticipo. Se per esempio scegliessimo la durata del progetto su 500 anni, andrebbe comunque bene.

[FIFA20] La connessione con l’avversario si è interrotta

Esattamente come succedeva con FIFA19 anche con FIFA20 giocare online è un terno al lotto. Pertanto rimando anzitutto al precedente articolo per alcuni suggerimenti, come l’attivazione dell’UPnP e le verifiche sul firewall. La soluzione che propongo qui è pregare antiche divinità egizie quali Bast oppure Osiride, affinché siano caritatevoli e permettano di giocare.

Dico questo perché dopo diversi tentativi, spesso senza aver cambiato nulla rispetto alla situazione precedente, il gioco decide di partire, quindi la soluzione potrebbe essere: ritenta e sarai più fortunato. Lo con un pizzico di frustrazione perché è veramente incredibile.

Una cosa che talvolta, ma sottolineo talvolta e qui lo dico e qui lo nego, sembra aiutare è disattivare il protocollo IPv6 e riavviare la connessione dalla scheda di rete.

Per farlo, come ho scritto anche nel precedente articolo, basta andare sul Pannello di Controllo > Rete e Internet > Centro connessioni di rete e condivisione

Sulla destra clicchiamo sulla voce Modifica impostazioni scheda

Si aprirà l’elenco delle nostre schede di rete. Individuiamo la nostra scheda di rete e clicchiamo col destro sopra, poi andiamo su Proprietà:

Da qui rimuoviamo il protocollo IPv6 da quelli selezionati, ottenendo una schermata simile:

A questo punto diamo OK e torniamo sulla scheda di rete. Clicchiamoci sopra col destro e scegliamo Disabilita.

NB: Io queste operazioni le ho provate a gioco avviato, senza spegnerlo o riavviarlo.

Quando la scheda si disabilita clicchiamo di nuovo col destro e scegliamo Abilita come prima.

Torniamo al gioco, che nel frattempo ci avviserà che la connessione è stata perduta, e premiamo eventualmente R3 per ricollegarci dal menu principale (dovrebbe riconnettersi da solo dopo poco).

Adesso ritentiamo la fortuna. Ho avuto l’impressione che questa procedura sortisse qualche effetto, ma dal momento che sono stati fatti diversi tentativi a vuoto potrebbe essere stata anche solo un’incredibile coincidenza.

Sono arrivato anche a supporre che sia sufficiente riavviare la connessione, senza dover disabilitare l’IPv6.

Per la configurazione generale rimando all’articolo: [FIFA19] La connessione con l’avversario si è interrotta

Sottolineo il fatto che tutto il resto è rimasto inalterato (tentativi quali disabilitare il firewall non avevano sortito alcun effetto) e che semplicemente, insistendo per quei 20 minuti buoni che ti fanno perdere la pazienza, il gioco ad un certo punto decideva che era possibile giocare in rete.

Quando si dice che serve tanta pazienza…

[python] Disegnare un fiocco di neve con OpenGL, Python e pygame

Visto che siamo in tema natalizio vediamo come disegnare un fiocco di neve con Python, OpenGL e pygame.

Questo esercizio riprende in parte quanto già visto per disegnare un poligono sempre con Python e OpenGL.

Anzitutto assicuriamoci di avere installate le librerie PyOpenGL e pygame, qualora non le avessimo sarà sufficiente installarle mediante pip con i seguenti due comandi:

Fatto questo possiamo cominciare a predisporre il nostro programma.

Anzitutto voglio fare un breve approfondimento su alcune funzioni che andremo ad utilizzare.

Cominciamo da gluPerspective. Questa funzione accetta 4 argomenti:

  • fovy: sostanzialmente l’angolo di visione in gradi, come illustrato nell’immagine di seguito
  • aspect ratio: il rapporto tra altezza e larghezza, sostanzialmente ci andiamo ad inserire il rapporto tra le dimensioni del nostro schermo (poi ne discutiamo meglio)
  • zNear: il piano più vicino dopo il quale comincia la visione
  • zFar: il piano più lontano al quale termina la visione
Risultato immagini per gluPerspective"
Immagine presa da GLUT and OpenGL by Robby T. Tan

Ricordiamoci che andremo a disegnare un oggetto in 3D, che dovrà essere posizionato all’interno del tronco di piramide definito dai due piani e dall’angolo di apertura. Se l’oggetto dovesse uscire da questo spazio semplicemente non risulterebbe visibile sullo schermo (o risulterebbe parzialmente tagliato). Da questo si capisce come l’angolo di apertura determinerà la prospettiva e lo spazio di interazione dell’oggetto. La situazione sostanzialmente è la seguente:

Per maggiori approfondimenti consiglio anche una lettura veloce a Perspective distortion (photography)

Dal momento che andrò a posizionare i nostri oggetti a partire da (0,0,0) voglio anche spostare il punto di visione (viewpoint) indietro, in modo da farceli entrare, altrimenti non sarebbero visibili. Per farlo utilizzo la funzione glTranslatef che prendere come argomenti i valori x, y e z sui quali effettuare la traslazione.

Infine voglio disegnare delle linee usando i rispettivi vertici. Per farlo dovrò aggiungere coppie di vertici alla “matrice del mondo” con il metodo glVertex3fv. Nel caso specifico posso disegnare una linea orizzontale che vada da (0,0,0) a (1,0,0) scrivendo le seguenti quattro righe di codice:

Se volessi disegnare un quadrato dovrei disegnare tutte le linee a coppie di vertici, nel modo seguente:

Sostanzialmente quello che facciamo in questo caso potrebbe essere riassunto col seguente schema:

Disegniamo le varie linee del quadrato seguendo le direzioni delle frecce rosse.

Adesso se volessimo limitarci a disegnare un quadrato e farlo ruotare davanti alla telecamera potremmo scrivere il seguente programma:

Grazie a glClearColor(0, 0, 0.1, 1) coloriamo lo sfondo di un blu scuro. Eseguendo il programma vedremo qualcosa di simile:

Il quadrato sarà in movimento ovviamente, grazie alla funzione glRotatef che ruota la matrice del mondo.

Arrivati a questo punto ci manca solo di disegnare il fiocco di neve, ovvero preparare le coppie di vertici di tutte le linee del fiocco di neve stesso.

Per farlo voglio seguire il seguente schema:

Partiamo dal basso e disegniamo un ramo di lunghezza L. Prendiamo come riferimento un angolo α di 45° (ovvero π/4). Alla fine del ramo teniamo conto dell’angolo di arrivo e disegniamo altri due rami, ciascuno spostato di 45°. Procediamo in avanti ripetendo questo schema per n iterazioni.

Creiamo quindi due classi, una per il Fiocco e una per ciascun Ramo, nel modo seguente (nei commenti in Python ulteriori dettagli):

Fatto tutte questo reintegriamo il tutto nella nostra classe iniziale FioccoDiNeve.

Se abbiamo fatto tutto correttamente otterremo il nostro fiocco di neve frattale ruotante in questo modo:

[FIFA20] Avviare FIFA 20 da Steam e utilizzare il controller DualShock della PS4 su PC

Un’altra soluzione, per usare il DS4 su PC, alternativa all’uso del DS4Windows di cui ho parlato nel precedente articolo, è lanciare FIFA20 direttamente da Steam Big Picture, utilizzando la gestione del controller di Steam stesso (che ricordo essere perfettamente compatibile con i controller PS4).

Per farlo basta seguire la seguente procedura:

1. Disabilitare la sovrapposizione in gioco di Origin

Andare su Origin > Impostazioni applicazione > Origin in gioco e disabilitare l’opzione Attiva Origin in gioco.

In questo modo Origin non interferirà con Steam.

2. Aggiungere il gioco in Steam

A questo punto apriamo Steam e andiamo su Giochi > Aggiungi un gioco non di Steam alla libreria…

Si aprirà una lista di programmi da cui cerchiamo e selezioniamo FIFA20 (nell’immagine di seguito c’è per esempio FIFA19 che non ho aggiunto ancora su Steam).

Spuntiamo il gioco desiderato e premiamo il tasto Aggiungi i programmi scelti.

Fatto questo vedremo comparire il gioco nella nostra lista di giochi.

3. Configuriamo FIFA20 affinché si avvii senza la schermata di Start.

Dal momento che voglio avviare il gioco da Steam Big Picture, che viene controllato dal controller, voglio saltare la noiosa schermata delle impostazioni e di avvio che si apre di predefinito con FIFA.

Per farlo vado a modificare il file in [...]\Origin Games\FIFA 20\FIFASetup\config.ini che si trova nella cartella di installazione del gioco.

Apriamo il file con un editor di testo e aggiungiamo, in fondo, la seguente riga: AUTO_LAUNCH = 1

Una volta modificato il file dovremmo vedere qualcosa come questo al suo interno:

Salviamo e chiudiamo il file.

4. Per giocare avviamo Steam Big Picture

A questo punto possiamo avviare Steam Big Picture cliccando sull’apposita icona in alto a destra.

Da dentro l’applicazione possiamo lanciare FIFA20 e sfruttare le configurazioni e la gestione del controller della PS4 da parte di Steam.

In aggiunta così possiamo anche sfruttare tutte le opzioni della sovrapposizione Steam, compresi gli screenshot con F12.

[FIFA 20] Giocare utilizzando il controller della PS4 sul PC con DS4Windows

Dopo diverse peripezie sono giunto alla conclusione che per FIFA20 la soluzione migliore sia usare Steam Big Picture per le configurazioni del controller PS4. Qui la spiegazione su come fare.

Origin proprio non ne vuole sapere di rendere compatibili i controller DualShock di PS4 con i propri giochi, quindi bisogna munirsi di soluzioni alternative. Nel caso specifico si può usare DS4Windows. Però anche in questo caso le sorprese non mancano. Se con FIFA 19 basta avviare il programma, con FIFA 20 bisogna anche ricorrere all’opzione Hide DS4 Controller.

Anzitutto scarichiamo l’ultima versione di DS4Windows. Possiamo farlo dalla pagina del progetto ufficiale.

Scarichiamo l’ultima versione e scompattiamola nella posizione che preferiamo.

Troveremo un elenco di file in questo modo:

Se vogliamo possiamo aggiungere, per comodità, il collegamento all’eseguibile nel Menu Start. Per farlo clicchiamo col destro sull’eseguibile e selezioniamo l’opzione Aggiungi a Start.

Fatto tutto questo avviamo DS4Windows.exe.

Se non lo abbiamo ancora configurato partirà l’installazione del ViGEmBus Driver.

Nel mio caso cliccherò sullo Step 1: Installa the ViGEmBus Driver.

A questo punto spostiamoci sulla scheda delle impostazioni e spuntiamo l’opzione Hide DS4 Controller.

E’ possibile che ci appaia un messaggio di questo genere: Warning: Could not open DS4 90:89:5F:94:F3:53 exclusively. You must quit other applications like UWP apps (Netflix), Steam, Uplay, NVIDIA IN-GAME before activating the 'Hide DS4 Controller' option. For more info check https://github.com/Ryochan7/DS4Windows/wiki/Exclusive-Mode-(Hide-DS4-Controller-config-option)-tips-and-issues

Il programma ci sta avvisando, in sostanza, che altri programmi impediscono la disattivazione del controller che Windows vede automaticamente. Finché non lo disattiviamo il gioco vedrà entrambi i controller, sia quello creato dal DS4Windows, che quello installato direttamente su Windows stesso.

In poche parole, sul pannello di controllo, da Pannello di controllo > Hardware e suoni > Dispositivi e stampanti si vedranno 2 controller che in realtà sono uno solo:

Affinché l’operazione vada a buon fine dobbiamo disattivare tali programmi, chiudendo quindi tutte le applicazioni come Steam, Uplay oppure Origin stesso.

Inoltre dobbiamo disattivare anche la Sovrapposizione NVIDIA che utilizza il controller.

Per farlo andiamo su NVIDIA GeForce Experience cliccando col destro sull’icona nel vassoio di sistema:

Andiamo sulle impostazioni cliccando sull’ingranaggio in alto a destra:

Da qui deselezioniamo sovrapposizione di gioco.

A questo punto dovremmo essere in grado di usare tranquillamente il controller della PS4 emulato da DS4Windows.

Nel caso ci fossero problemi su questo ultimo passaggio riavviare il PC e prima di avviare qualunque altro programma far partire DS4Windows.

Se dopo il riavvio il controller continuasse a dare problemi, oppure non fosse accessibile a DS4Windows, andare in Pannello di controllo > Hardware e suoni > Dispositivi e stampanti e cliccare col destro su Wireless Controller selezionando l’opzione Rimuovi dispositivo.

Una volta rimosso staccare il cavo USB dal controller e riattaccarlo, aspettando l’installazione dei driver da parte di Windows.

Stimare budget e fattibilità di una campagna su Facebook (simulatore in Excel)

Link (anche in fondo) al Simulatore campagna pubblicitaria su Facebook (Excel)

Quando si intende fare una campagna pubblicitaria online bisogna tenere conto di diversi fattori, oltre che degli obiettivi per cui la campagna è pensata.

A differenza della pubblicità tradizionale (quella che si potrebbe fare sui giornali, sulla TV oppure sui cartelloni per strada) nelle campagne online è possibile verificare le conversioni prodotte dalla campagna stessa.

Con conversioni si intendono quelle azioni intraprese dagli utenti che hanno visto la pubblicità e per le quali la campagna pubblicitaria era stata pensata. Nel caso di una campagna pubblicitaria finalizzata alla promozione di prodotti, la conversione equivale all’acquisto di un prodotto. La conversione potrebbe essere anche l’iscrizione ad una newsletter, una richiesta di contatto o preventivo ecc.

Il processo di conversione può essere sintetizzato nel seguente schema:

 

Analizziamo brevemente i singoli passaggi del processo:

  1. Impressioni: le volte che la pubblicità viene mostrata, se la pubblicità viene mostrata 30.000 volte allora si avranno 30.000 impressioni. Le impressioni sono sempre maggiori o uguali al pubblico raggiunto. Un pubblico di 20.000 persone potrebbe generare 30.000 impressioni. Questo vorrebbe dire che in media ogni persona raggiunta ha visto la pubblicità 1,5 volte. Questo valore viene chiamato anche frequenza.
  2. Visite (o click): il numero di persone che, dopo aver visto la pubblicità, decidono di interagire con essa (o più semplicemente cliccano sull’inserzione). Il rapporto tra quelli che vedono la pubblicità e quelli che decidono di cliccare si chiama CTR (Click-through rate, in italiano “percentuale di click”). In generale come CTR medio si prende, in assenza di ulteriori dati statistici, un valore del 1%. Un CTR del 2% può essere già considerato ottimo. Questo valore dipende ovviamente anche dal messaggio pubblicitario stesso e da altri elementi. Un CTR molto elevato non è garanzia di alcun tipo di successo; significa solamente che le persone cliccano frequentemente sulla pubblicità. Un messaggio pubblicitario fuorviante potrebbe produrre un CTR molto elevato, che non corrisponde poi ad alcuna conversione significativa. Inoltre ad ogni click, in una campagna online, è associato un CPC (costo per click), ovvero quanto spendiamo per ogni click ottenuto. Se il CPC fosse di 0,50€ vorrebbe dire che per ogni click pendiamo 0,50€.
  3. Leads: sono semplicemente dei potenziali acquirenti, persone interessate al prodotto, che ancora non hanno deciso di acquistare il prodotto stesso. Un lead potrebbe “condurre” (di qui il nome) anche altri eventuali clienti all’acquisto del prodotto, tramite per esempio il passaparola, sebbene egli stesso poi non effettui alcun acquisto. E’ importante tenere conto dei lead solo dal punto di vista concettuale; significa che dobbiamo pensare la nostra campagna in modo che le pagine ad essa dedicata (le landing page) suggeriscano oppure consentano all’utente di lasciare i propri dati di contatto o memorizzare la pagina, per poter essere contattato successivamente o recuperare facilmente l’accesso al prodotto. Dal punto di vista statistico del processo di conversione i lead possono essere ignorati.
  4. Acquisti: sotto il termine acquisto si intende qui la finalizzazione della conversione, cioè quell’azione per cui la campagna è stata pensata. Nella maggior parte dei casi si tratta appunto dell’acquisto di un prodotto, ma potrebbe anche trattarsi di una richiesta di contatto, una donazione, un’iscrizione ad una newsletter o un gruppo, ecc. Il rapporto tra il numero di visitatori e il numero di acquisti, ovvero conversioni, viene chiamato tasso di conversione. Se per esempio ottengo 200 visite dalla campagna (click) e ne conseguono 2 acquisti, il tasso di conversione sarà del 1%. In media il tasso di conversione, in mancanza di ulteriori dati statistici a disposizione, oscilla tra il 1% e il 3%. Il tasso di conversione è anche chiamato CVR o CR (conversion rate)

Appurato tutto questo vediamo come valutare una campagna pubblicitaria su Facebook.

Anzitutto procuriamoci dei dati statistici sull’andamento del mercato, a tale proposito utilizzerò quelli pubblicati da WordStream: Facebook Ad Benchmarks for YOUR Industry [2019]

A titolo di esempio immaginiamo di voler fare una campagna pubblicitaria per vendere dei prodotti casalinghi (vasi, piatti, accessori, complementi d’arredo).

WordStream ci informa che il mercato (Home & Garden) di riferimento ha i seguenti valori:

CTR 0,71%

CPC 2,78$ = 2,50€

CVR 7,02%

Da questi valori possiamo calcolare il costo di una singola conversione (CPA, costo per azione o cost per action) nel modo seguente:

CPA=\frac{1}{CVR}*CPC=\frac{CPC}{CVR}

Nel nostro caso specifico avremmo quindi:

CPA=\frac{2,50}{0,0702}=35,61

Questo significa che per vendere 1 prodotto tramite la pubblicità dobbiamo spendere 35,61€

Questo è il valore più importante da tenere in considerazione. In generale si stima che il budget destinabile ad una campagna pubblicitaria rispetto al valore dell’evento (o dei prodotti che si intendono vendere) si dovrebbe aggirare entro il 12% di quest’ultimo.

Questa proprietà può essere estesa ai singoli prodotti, per cui se un prodotto viene venduto a 100€, il massimo che possiamo spendere in pubblicità per venderlo non dovrebbe superare i 12€. Naturalmente questo valore varia notevolmente da prodotto a prodotto e dai margini che abbiamo sul valore dei prodotti stessi.

Esempio: se intendiamo vendere delle camere di albergo mediante una campagna pubblicitaria, dobbiamo tener conto del fatto che sulle OTA le percentuali che vengono prelevate per la vendita si aggirano dal 15% al 18%. Questo significa che possiamo valutare la nostra campagna prendendo il 15% o il 18% come valore di riferimento. Se quindi una camera costa 80€ a notte possiamo spendere fino a 12€ o 14,40€ per cercare di venderla tramite una campagna pubblicitaria. Se la campagna pubblicitaria richiedesse una cifra superiore per venderla potremmo valutare se fare la campagna per la vendita di pacchetti vacanze (più notti per più persone) oppure rinunciare e affidarci alle OTA. Se per esempio il CPA fosse di 33€, vorrebbe dire che dovremmo vendere servizi (camere) ad almeno 183,33€ (nel nostro caso dovremmo proporre, nella pubblicità, non la singola notte, quanto prenotazioni da almeno 3 notti, dove 3 x 80€ = 240€).

Detto questo abbiamo capito quindi che attraverso una campagna online dobbiamo cercare di vendere prodotti per almeno 296,75€.

Dal momento che vendere casalinghi a questo prezzo non è facile (per proseguire sulla nostra ipotesi), dobbiamo valutare che tipo di offerta promuovere attraverso la campagna. Alcune idee potrebbero essere:

  1. Incentivare una spesa di almeno 300€ (spedizioni gratuite, sconti, promozioni future, ecc)
  2. Aggregare i prodotti in pacchetti (vendere per esempio set dello stesso prodotto o set preconfezionati di prodotti pronti all’uso)
  3. Cambiare pubblico di destinazione (cambiare cioè il target; anziché vendere ai privati, potremmo indirizzare la campagna ad altri rivenditori, oppure ad albergatori che vogliono comprare set del medesimo prodotto per arredare diverse stanze nello stesso modo ecc.)

Attenzione! Resta il fatto che non possiamo sperare di vendere efficacemente prodotti che hanno un valore inferiore, per esempio un vaso da 20€, laddove la spesa per ottenere la vendita è di 35,61€

Da questo si deduce un altro fatto importante: le campagne online non sono adatte alla vendita di qualsiasi prodotto.

Per facilitare questo tipo di calcoli ho realizzato un piccolo simulatore in Excel, che ci permette anche di tenere conto di ulteriori dati statistici, quali la dimensione del pubblico, il costo di gestione della campagna, la frequenza di visualizzazione della campagna ecc.

Immettendo i dati di poco prima otterremmo qualcosa di simile a questo:

Nella mia ipotesi ho immaginato una campagna da 5€ al giorno, per una durata totale di 10 giorni ed un pubblico di 10.000 persone. Il valore dei prodotti è di 20€. Il calcolatore mi dirà chiaramente che la campagna non è sostenibile.

Se cambiassi il valore dei prodotti a 300€ otterrei il seguente risultato:

Se adesso provassi ad aumentare il budget giornaliero, portandolo a 60€ al giorno, otterrei di nuovo una campagna fuori dai parametri preimpostati.

Questo perché raggiungendo la saturazione del pubblico (ricordiamoci che sto ipotizzando un pubblico di 10.000 individui) aumenterei la frequenza di visualizzazione che, secondo quanto suggerito da Facebook stesso, non dovrebbe superare i 2 punti. Più è alta la frequenza e più la campagna è onerosa.

E’ altrettanto vero che anche con un budget di 10€ al giorno ed un costo di gestione della campagna (quello che pago a chi la configura e gestisce) di 150€, la campagna resta non fattibile.

Per chiunque volesse cimentarsi in questo genere di simulazioni metto a disposizione il simulatore in Excel utilizzato qui sopra:

Simulatore Facebook Ads

Il simulatore è stato realizzato per il Corso di Social Media Marketing della Mummu Academy di Firenze.

[c#] Creare una classe per stampare con i font installati nella stampante

L’obiettivo è quello di inviare del testo alla stampante utilizzando i font nativi al suo interno e la libreria gdi32.dll di Windows. Questa volta integreremo tutto in una semplice applicazione in C#.

Anzitutto creiamo un semplice form con una TextBox chiamata txtTesto ed un Button chiamato btnStampa.

Aggiungiamo poi una nuova classe che estenda la classe System.Drawing.Printing.PrintDocument

Per usare la classe anzitutto dobbiamo implementare alcuni metodi e creare i corrispondenti per le funzioni della libreria GDI32.

A tale scopo utilizzeremo l’istruzione [DllImport("gdi32.dll")] prima delle specifiche definizioni.

Le funzioni che dobbiamo implementare sono rispettivamente: CreateFont, SelectObject, DrawText, DeleteObject

Per maggiori riferimenti alle singole funzioni consiglio di visionare il sito Pinvoke.net

Detto tutto questo costruiamo la classe nel modo seguente:

Eseguiamo il test della funzione nel form principale:

In questo modo stamperemo attraverso la stampante predefinita.

Nel mio caso una stampante Samsung M2070, che riconosce come font “Courier New“.

[python] Utilizzare Python su Apache (configurazione con XAMPP)

Anzitutto assicuriamoci di avere Python installato sul nostro computer. Nel mio esempio procederò con l’installazione su Windows, ma anche nel caso di un server Linux la procedura è pressoché la medesima.

1. Individuiamo la cartella di installazione di Python

Nel mio caso l’eseguibile di Python si trova in D:/Python27/python.exe

Appuntiamoci questo valore perché ci servirà per dopo.

2. Configuriamo Apache modificando il file httpd.conf

Utilizzando XAMPP è sufficiente aprire il pannello di controllo e recarsi su Apache > Config > Apache (httpd.conf)

3. Aggiungiamo il handler per gli script cgi

In fondo al file di configurazione aggiungiamo le seguenti due righe per attivare la gestione degli script cgi

In questo modo permettiamo ad apache di interpretare i file con estensione .py come script eseguibili mediante applicazioni interne al computer.

4. Aggiungiamo index.py alle pagine di default

Esattamente per quello che succede per index.htm oppure index.php, vogliamo che anche index.py venga letta come pagina predefinita di una cartella. (potremmo metterne anche altre a piacere)

Per farlo modifichiamo sempre il file httpd.conf che abbiamo aperto prima. Identifichiamo il punto dove c’è scritto <IfModule dir_module> e modifichiamo la configurazione nel modo seguente, aggiungendo index.py all’elenco

5. Riavviamo apache

Che lo si stia facendo su XAMPP, oppure su un server LAMP, a questo punto riavviamo Apache, banalmente premendo Stop e Start in sequenza.

6. Creiamo la prima pagina in Python

Dentro la cartella htdocs creiamo una cartella a piacere, che allo scopo di questo esempio io chiamerò python.

Dentro la cartella creiamo un file chiamato index.py con dentro le seguenti istruzioni:

Ricordiamoci l’indirizzo preso all’inizio al punto 1. Il percorso di installazione di Python andrà incluso in ciascun file. Inoltre è essenziale il primo print, che permette al browser di interpretare il contenuto come una pagina html.

Le prime 2 righe dovranno essere presenti in ogni pagina che si occuperà dell’output.

7. Esempio di una pagina semplice

Ovviamente dovremo aggiungere tutti gli opportuni tag del HTML, cosa che potremmo fare in questo modo:

8. Raccogliere i dati da POST e GET

Infine vediamo come raccogliere i dati dai due metodi principali con i quali l’utente può interagire con la nostra pagina web, il get e il post.

Per farlo importiamo anzitutto la libreria CGI aggiungendo in cima al file, dopo il percorso all’eseguibile di Python, import cgi

Avremo bisogno anche di gestire eventuali errori che se no non verranno mostrati nell’output. Per farlo importiamo anche cgitb aggiungendo le seguenti due righe:

L’intestazione del nostra file diventerà:

A questo punto per raccogliere i dati, sia da POST che da GET utilizziamo l’istruzione dati = cgi.FieldStorage()

Modifichiamo tutta la pagina per funzionare con un piccolo form che utilizzi entrambi i metodi:

Faccio notare che se si cerca di chiamare la pagina http://127.0.0.1/python/?dati_form=1 si incorrerà in un errore come il seguente (senza la suddetta libreria avremmo visualizzato una pagina bianca):

Questo perché la chiave valore non è definita all’interno del contenitore dati.

Aggiungiamo quindi un controllo nel modo seguente:

 

[bash] Script per reimpostare i permessi della cartella system su Plesk

Oggi mi sono trovato di fronte al problema di reimpostare tutti i permessi sulla cartella /var/www/vhosts/system/ appartenente a Plesk.

Nel caso specifico esiste un articolo di riferimento della guida di Plesk su come reimpostare i permessi e quali dovrebbero essere quelli corretti. Per l’articolo originale vedere: How to restore default permissions in the virtual host directory on Linux?

Nell’articolo è possibile trovare anche un file bash che però non reimposta i permessi sulla cartella system.

Allora ne ho realizzato uno mio, seguendo lo schema dei permessi illustrato nell’articolo medesimo:

Il codice in bash è il seguente: