[apps script] Inviare tramite Gmail un’email con allegato da Drive

Questo esempio è la prosecuzione di quanto già visto in [apps script] Inviare tramite Gmail un’email ad un elenco di contatti in Spreadsheet

Voglio apportare solo una piccola modifica al codice per inviare un allegato salvato su Google Drive a tutti i soggetti nella lista. Per i riferimenti di programmazione rimando alla pagina della guida ufficiale.

Per prelevare un file da Google Drive dobbiamo anzitutto ottenere il suo riferimento univoco. Per farlo ci sono diversi modi, nel mio esempio utilizzerò un file pdf come questo qua. Anzitutto lo carico su Drive e poi cliccandoci sopra col destro scelgo Anteprima.

Dal menu in alto a destra seleziono Apri in un’altra finestra.

A questo punto nella barra dell’indirizzo vedrò qualcosa come https://drive.google.com/file/d/1234567890abcdefghijklmnopqrstuvwxyz/view

Copio il codice alfanumerico che ho evidenziato in rosso, che è l’identificativo univoco per ciascun file. Una volta copiato vado a modificare il mio codice nel modo seguente.

In particolare con la prima istruzione aggiunta prelevo il file da Drive, cosa che richiederà dei permessi aggiuntivi.

Mentre con file.getAs(MimeType.PDF) creo il blob del file in formato PDF.

Fatto questo il mio nuovo script invia un’email a ciascun membro della lista con allegato il suddetto file.

Vedi articolo

[python] Esercizio su wxPython e PyOpenGL per disegnare un poligono dato il numero di lati

Quello che voglio realizzare oggi è un semplice programma in Python 2.7, con interfaccia grafica e che permetta di disegnare un poligono regolare dato il numero di lati. In questo esercizio vedremo quindi due cose:

  1. L’utilizzo di wxPython per creare un rudimentale programma con interfaccia grafica
  2. L’utilizzo di PyOpenGL per disegnare dentro ad un canvas una figura geometrica

Il programma che andremo a creare avrà alla fine questo aspetto, con uno spazio per inserire il numero di lati ed un canvas su cui disegnare:

Anzitutto assicuriamoci di disporre di entrambe le librerie, per farlo installiamole con pip eseguendo i seguenti due comandi da terminale:

Una volta installate le librerie possiamo cominciare a creare il nostro programma.

Per prima cosa creiamo una classe per la nostra applicazione, utilizzando wx.Frame e avviando la finestra principale. Il codice di cui avremo bisogno sarà il seguente:

In questo modo creiamo una finestra di dimensione 800 x 600 px con titolo Disegnatore. La nostra applicazione è un’estensione di wx.Frame, laddove un Frame è una finestra le cui dimensioni e posizione possono essere modificate dall’utente (insomma la classica finestra in Windows). Inoltre essa può contenere una barra del titolo, dei menu, dello stato e degli strumenti.

Con wx.App avviamo invece l’applicazione vera e propria, questa classe ci serve per lanciare il contenitore principale dell’applicazione e passiamo come argomento False (che sarebbe così anche di predefinito) per non reindirizzare lo sys.stdout e lo sys.stderr. Per maggiori informazioni rimando alla guida ufficiale su App.

A questo punto voglio aggiungere la casella di testo e il pulsante per impostare il numero di lati. Per farlo dobbiamo usare un wx.Panel, che sostanzialmente è il contenitore degli elementi di controllo e si trova tipicamente dentro un Frame. Per maggiori informazioni leggere qui su Panel.

Modifico quindi il codice nella maniera seguente:

E’ molto importante che il Panel venga istanziato prima del metodo aggPulsanti che poi aggiunge elementi al Panel. Arrivati a questo punto lanciamo il nostro programma e verifichiamo che abbia il seguente aspetto.

A questo punto è l’ora di aggiungere anche il Canvas che ci permetterà di mostrare grafica in OpenGL. Per farlo includiamo anzitutto le librerie necessarie:

Modifichiamo poi il codice nel modo seguente:

E’ importante stabilire le dimensioni del canvas in due variabili s.width e s.height per delle correzioni che apporteremo successivamente, per ora prendiamola per buona così.

A questo punto inizializziamo il canvas aggiungendo le seguenti istruzioni:

Faccio notare che il metodo glClearColor(1, 1, 1, 1) imposta il colore dello sfondo su bianco, mentre il metodo glClearColor(0, 0, 0, 1) lo imposta su nero. I primi tre parametri sono i valori di RGB da 0 a 1.

Siamo arrivati a buon punto e siamo praticamente pronti a disegnare il nostro poligono. Il nostro riferimento è uno spazio cartesiano con gli assi che attraversano a metà il canvas e il punto (0, 0) al centro del canvas stesso. Un poligono regolare ha tanti vertici quanti i lati e ogni vertice poggia su una circonferenza di raggio r.

Questo significa che un angolo α che passa da un vertice all’altro è dato dalla seguente equazione:

\alpha = 2 * \pi / n

Dove n è il numero di lati (o vertici) del poligono. Traduciamo questa formula in Python nel modo seguente:

Avremo bisogno della libreria math che importiamo con:

L’angolo di partenza è arbitrario, però per far sì che il lato superiore del poligono sia parallelo all’asse delle ascisse voglio prendere come angolo di partenza:

\beta = \pi / 2 - \pi / n

Quindi la nostra formula sarà:

Attenzione ad inserire i numeri con almeno una cifra decimale, anche se zero, per assicurarci che Python esegua tutti i calcoli con valori decimali e non tronchi ad interi.

Infine vogliamo definire un raggio fisso per i nostri poligoni, per farlo userò come riferimento l’apotema a (anche se sarebbe sufficienti lato e raggio) nel modo seguente:

apotema = 0.5

lato = apotema * ( 2.0 * \tan( \pi / n ) )

raggio = \sqrt{ (lato/2)^2+apotema^2 }

Il primo vertice avrà quindi coordinate:

( raggio * \cos( \beta ) , raggio * \sin( \beta ) )

Il secondo vertice sarà:

( raggio * \cos( \beta + \alpha ) , raggio * \sin( \beta + \alpha ) )

Il terzo vertice sarà:

( raggio * \cos( \beta + 2 * \alpha ) , raggio * \sin( \beta + 2 * \alpha ) )

E così via.

Traduciamo il tutto nel seguente metodo:

Spostiamoci sul metodo onDraw e modifichiamolo nel modo seguente:

Nel costruttore __init__ della classe aggiungiamo una variabile s.n per il numero di lati, subito dopo le dimensioni del canvas, nel modo seguente:

Se abbiamo fatto tutto correttamente dovremmo vedere qualcosa come questo:

Notiamo subito che il pentagono è deformato ed inoltre manca la possibilità di definire una dimensione a piacere.

Anzitutto occupiamoci della deformazione, essa dipende dal fatto che il canvas ha una dimensione fissa di 1 x 1, che poi viene ripartita in parti decimali. Quindi tale dimensione si adatta poi alle proporzioni del canvas. Per ottenere un pentagono regolare anzitutto dobbiamo introdurre un fattore correttivo, che nel nostro caso sarà dato da:

Aggiungiamo la variabile subito dopo larghezza e altezza impostate in __init__.

Modifichiamo il metodo per disegnare il poligono nel modo seguente:

Adesso il poligono risulta regolare:

Infine attribuiamo un valore personalizzato al numero di lati s.n del poligono. Aggiungiamo i seguenti due metodi alla nostra classe:

E dove abbiamo istanziato s.pulsante aggiungiamo:

In questo modo colleghiamo il metodo s.btn_calcola all’evento wx.EVT_BUTTON che corrisponde alla pressione del pulsante. Con il metodo verificaIntero controlliamo se il valore passato dall’utente sia intero. Se non è intero mostriamo, grazie a wx.MessageBox, un messaggio a video con notifica di errore.

Se abbiamo fatto tutto correttamente otterremo il seguente codice finale:

Se lo eseguiamo abbiamo il nostro programma che ci permetterà di disegnare qualunque poligono regolare:

Vedi articolo

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

Problema: Quando si cerca di giocare una partita online con un altro giocatore amico dopo l’invito ed una breve attesa appare il messaggio “La connessione con l’avversario si è interrotta“.

Soluzione: Una possibile soluzione consiste nel disabilitare il protocollo IPv6 e attivare l’UPnP sul router ed infine riavviare il gioco

Premetto che come ISP ho Fastweb e la soluzione è stata testata sul router in dotazione e Windows 10. Procediamo nel modo seguente.

Cerchiamo il Pannello di controllo nel menu principale:

Andiamo su Rete e Internet:

Poi su Centro connessioni di rete e condivisione

Clicchiamo su Modifica impostazioni scheda nel menu sulla sinistra.

Individuiamo la nostra scheda di rete, nel mio caso Ethernet, e clicchiamo col destro, poi spostiamoci su Proprietà e clicchiamo.

Cerchiamo la voce Protocollo Internet versione 6 (TCP/IPv6) e togliamo la spunta.

Per precauzione impostiamo il DNS sui Google DNS spostandoci su Protocollo Internet versione 4 (TCP/IPv4), selezioniamolo (ma attenzione a NON TOGLIERE la spunta) e poi clicchiamo su Proprietà.

Impostiamo il DNS su 8.8.8.8 e 8.8.4.4

Premiamo OK su tutto quanto.

Adesso controlliamo che sul router sia attivo l’UPnP. Nel caso del router Fastweb andiamo su Home > Casella degli strumenti > Condivisione giochi e applicazioni

Verifichiamo che l’UPnP sia attivo nel modo seguente:

Su un router Netgear D6300 l’opzione si trova tra le impostazioni avanzate:

E dev’essere impostata nel modo seguente:

Fatte tutte queste belle cose riavviamo la connessione cliccando su Disabilita

E poi di nuovo Abilita sulla scheda di rete.

Adesso riavviamo il gioco. Fatto tutto questo il problema dovrebbe essersi risolto e potremo tornare a giocare.

In caso di altri problemi suggerisco anche l’articolo ufficiale Risoluzione dei problemi per connessione per PC

Jordan Pickford, uno dei miei giocatori preferiti, oltre che portiere dell’Everton
Vedi articolo

Installazione Ubuntu 18.04.2 LTS webserver pronto all’uso [per esordienti totali]

Abbiamo già visto come installare Ubuntu 16.04.2 LTS e predisporlo per fare da webserver. Stavolta voglio ripetere la procedura, utilizzando però l’ultima distribuzione a lungo termine ovvero Ubuntu 18.04.2 LTS.

Come al solito eseguiremo l’operazione utilizzando VirtualBox. Per chi lo volesse installare su una macchina fisica la procedura sarebbe comunque analoga.

1. Configurazione Ubuntu Server 18.04.2 LTS

Anzitutto procuriamoci la ISO dal sito ufficiale.

Selezioniamo la seguente configurazione e premiamo download.

A questo punto cominciamo a creare la macchina virtuale sulla quale faremo girare il nostro webserver. Dentro VirtualBox premiamo CTRL+N. Si avvierà la seguente schermata che prepariamo nel modo seguente:

Premiamo su Successivo. Ci verrà chiesto quanta RAM intendiamo assegnare, mettiamo almeno 1024MB (ossia 1GB).

Procediamo e scegliamo di creare un nuovo disco fisso virtuale.

Proseguiamo selezionando VDI e per lo spazio diciamo Allocato dinamicamente (questo vuol dire che il disco virtuale non occuperà immediatamente tutto lo spazio assegnato, ma solo via via che il sistema operativo ne avrà bisogno).

Lasciamo 10 GB di spazio.

A questo punto avviamo la macchina virtuale.e ci verrà chiesto di selezionare un disco di avvio. Se fosse stata una macchina fisica si sarebbe trattato del supporto di installazione, per esempio un CD oppure una penna USB. Nel nostro caso clicchiamo sulla cartellina gialla e andiamo a selezionare il file ISO che abbiamo scaricato in precedenza dal sito ufficiale.

Se abbiamo fatto tutto correttamente dovremmo vedere qualcosa di simile:

Premiamo su Avvia.

A questo punto inizierà il caricamento del programma di installazione finché non ci si presenterà la schermata dove scegliere la lingua.

Selezioniamo inglese. A quanto pare ancora non lo hanno tradotto in italiano.

Premiamo il tasto INVIO.

Usando le frecce direzionali, nella schermata successiva, posizioniamoci sui menu a tendina della lingua e premendo INVIO apriamolo. Selezioniamo la tastiera italiana e premiamo di nuovo INVIO. A questo punto torniamo, premendo la freccia verso il basso, su [Done].

Alla prossima schermata premiamo nuovamente INVIO.

A questo punto ci verrà chiesto come vogliamo configurare la scheda di rete. Se stiamo usando una macchina virtuale come VirtualBox la scheda di rete sarà identificata dal dispositivo enp0s3 (normalmente sarebbe eth0, eth1, ecc…). Premiamo nuovamente INVIO.

Alla richiesta di configurare il proxy lasciamo tutto così com’è e premiamo di nuovo INVIO.

Selezioniamo il mirror predefinito per le repository di Ubuntu premendo semplicemente INVIO.

Nella prossima schermata scegliamo come formattare il disco. In questo esempio voglio utilizzare LVM per la gestione dei dischi, quindi mi sposto sulla seconda voce e premo nuovamente INVIO.

Per maggiori approfondimenti sull’utilizzo del LVM suggerisco questo articolo.

Selezioniamo il disco da partizionare, che è anche l’unico disco di cui disponiamo in questo momento.

Arrivati a questo punto possiamo verificare l’intera configurazione ed apportare, eventualmente, delle modifiche. Nel nostro caso lasciamo tutto tale e quale e procediamo premendo INVIO.

Ci chiederà se siamo sicuri di proseguire. Proseguiamo 🙂

Adesso compiliamo i campi con il nostro nome, il nome del server, lo username e la password. Memorizziamo questi dati perché ne avremo bisogno per accedere al server una volta pronto.

Alla schermata successiva selezioniamo la casella di Installa OpenSSH server premendo la barra spaziatrice. Spostiamoci poi con le frecce su Done e proseguiamo premendo INVIO.

Nella schermata successiva spostiamoci immediatamente su Done premendo il tasto della tabulazione e poi di nuovo INVIO.

A questo punto inizierà l’installazione, non ci resta che aspettare pazientemente che finisca.

Quando sarà tutto finito ci troveremo di fronte ad una schermata come questa, dove ci viene chiesto di riavviare. Premiamo INVIO e riavviamo il sistema.

Poco dopo ci verrà chiesto di rimuovere il dispositivo di installazione. Premiamo semplicemente INVIO e aspettiamo.

ATTENZIONE: Normalmente ci si dovrebbe trovare di fronte alla seguente schermata:

ma operazioni in differita su questa ultima versione di Ubuntu fanno sì che si sovrappongano degli output oltre la schermata di login. Se compare qualcosa di simile a questo è sufficiente premere INVIO per avere accesso alla schermata di login.

A questo punto effettuiamo il login con le credenziali che abbiamo creato in precedenza.

Una volta dentro il sistema digitiamo ifconfig e dovremmo vedere un risultato simile a questo.

Come possiamo notare il server si trova sull’indirizzo 10.0.2.15 che è l’indirizzo automatico assegnato dalla rete virtuale NAT di VirtualBox alla macchina virtuale.

Quello che vogliamo fare adesso è creare una nostra rete NAT personalizzata sulla quale spostare il server. VirtualBox ci permette infatti di creare una rete interna che, rispetto al nostro computer host, sarà raggiungibile all’indirizzo 192.168.56.1. Tale indirizzo sarà, rispetto al server, l’indirizzo esterno con il quale la rete virtuale nella quale si trova il server si affaccerà alla rete nella quale si trova il computer host.

Andiamo perciò sul panello di controllo di VirtualBox, spostiamoci su File > Preferenze (raggiungibile anche premendo CTRL+G).

Spostiamoci su Rete e poi premiamo il pulsante con la scheda di rete e il simbolo più verde . Questo aggiungerà una nuova rete virtuale chiamata NatNetwork (nel mio caso ci sono già altre reti configurate). Restando su NatNetwork premiamo il terzo pulsante a destra con il simbolo dell’ingranaggio .

Impostiamo la rete nel modo seguente scegliendo come ID di rete 10.0.2.0/24:

Con l’IP Calculator possiamo testare i dettagli della rete, ma per quello che ci interessa avremo 254 host dal 10.0.2.1 al 10.0.2.254.

Premiamo OK e spostiamoci nelle impostazioni della nostra macchina virtuale.

Andiamo su Rete e impostiamo come tipo di rete Rete con NAT e il nome Rete Ubuntu, che abbiamo creato prima.

A questo punto torniamo dentro la nostra macchina virtuale e aggiorniamo lo stato della connessione di rete.

Per farlo digitiamo: sudo netplan apply

Digitiamo ifconfig  e verifichiamo l’IP al quale è connesso adesso il nostro server. Nel mio caso è sempre 10.0.2.15

Adesso torniamo nelle Preferenze > Rete e andiamo ad impostare l’inoltro delle porte sulla rete che abbiamo creato.

Dal momento che vogliamo testare il server web con Apache e usare l’SSH per connetterci, dobbiamo inoltrare le porte 80, 443 e la 22.  Per aggiungere nuove regole di inoltro premiamo sul tasto col più verde e compiliamo l’elenco nel modo seguente.

L’indirizzo 192.168.56.1 rappresenta l’indirizzo della scheda di rete virtuale creata da VirtualHost, con la quale possiamo collegarci dal nostro PC alla rete virtuale creata poc’anzi. Fatto tutto questo diamo OK a tutto e proviamo a collegarci alla nostra macchina utilizzando Putty.

Se abbiamo fatto tutto a dovere adesso la macchina dentro la rete NAT virtuale è raggiungibile dall’indirizzo esterno 192.168.56.1.

Configuriamo Putty e premiamo Open.

Se tutto è andato bene ci verrà chiesto di acquisire la chiave per la connessione. Diciamo di sì:

A questo punto entriamo dentro il sistema usando Putty.

Procediamo con l’installazione di Apache e degli altri componenti del server LAMP.

2. Installazione e configurazione Apache

Per installare Apache anzitutto aggiorniamo la repository di Ubuntu digitando:

Quando finisce l’operazione procediamo installando Apache e digitiamo:

Se tutto è andato bene possiamo andare all’indirizzo http://192.168.56.1/ e verificare che si veda una pagina come la seguente:

Questa è la pagina default del nostro server Apache. La possiamo anche modificare andando nella cartella /var/www/html che è la root default del server.

Proviamo a farlo digitando:

Dentro Putty dovremmo vedere qualcosa come questo:

A questo punto usciamo dall’editor nano premendo CTRL+X e poi rimuoviamo il file e mettiamone uno nuovo digitando.

Dentro il file scriviamo semplicemente:

E salviamo premendo CTRL+O. Premiamo INVIO per confermare e CTRL+X per uscire.

Tornando su http://192.168.56.1/ dovremmo vedere qualcosa di analogo a questo:

3. Installazione e configurazione MySQL

Per installare il database MySQL digitiamo:

Premiamo Y alla richiesta di conferma dell’installazione e poi aspettiamo che sia ultimata. Una volta completata digitiamo:

Questo avvierà una procedura di configurazione del nostro database, durante la quale ci verranno richieste diverse cose. Alle varie domande rispondiamo rispettivamente:

Press y|Y for Yes, any other key for No: Y

Please enter 0 = LOW, 1 = MEDIUM and 2 = STRONG: 2

(dove: STRONG Length >= 8, numeric, mixed case, special characters and dictionary file)

New password: )9@JZ21@pam)KUfB)2hc{n[vrK?BAeTU  (questo è un esempio di password che possiamo mettere, questa password ha una qualità di 187bit e una lunghezza di 32 caratteri)

Se la passowrd è buona ci verrà detto qualcosa come:

Estimated strength of the password: 100

Proseguiamo:

Do you wish to continue with the password provided?(Press y|Y for Yes, any other key for No) : Y

Remove anonymous users? (Press y|Y for Yes, any other key for No) : Y

Disallow root login remotely? (Press y|Y for Yes, any other key for No) : Y

Remove test database and access to it? (Press y|Y for Yes, any other key for No) : Y

Reload privilege tables now? (Press y|Y for Yes, any other key for No) : Y

Fatto questo il database è pronto per l’utilizzo.

4. Installazione e configurazione PHP

Procediamo installando il PHP e digitando:

Confermiamo sempre con Y quando ci viene richiesto.

Una volta finito verifichiamo che sotto Apache le pagine index.php siano configurate come pagine predefinite:

Se tutto va bene vedremo qualcosa come:

Notiamo la presenza di index.php quindi possiamo procedere tranquillamente.

Per concludere riavviamo il server Apache.

5. Ulteriori configurazioni

A questo punto dovremmo fare ancora qualche implementazione, configurando alcune cose come:

  1. Sistemare il Firewall
  2. Mettere in sicurezza Apache
  3. Configurare fail2ban ed altri eventuali servizi

Io procederò con un esempio su come configurare un nuovo VirtualHost e installarci sopra WordPress.

6. Configurazione VirtualHost e installazione WordPress

Quello che vogliamo fare adesso è aggiungere un dominio al nostro server, affinché alla richiesta di un sito web su tale dominio esso risponde.

In poche parole voglio aggiungere il sito torregatti.com al mio server. Per farlo dobbiamo aggiungere un host virtuale. (qui un esempio della solita procedura)

Per farlo voglio creare, dentro a /var/www/ una cartella dedicata al dominio e poi aggiungerlo ai VirtualHost di Apache.

Procediamo quindi nel modo seguente creando anzitutto la suddetta cartella che, per motivi di ordine, chiamerò come il dominio:

Adesso assegniamo la cartella ad Apache modificando i permessi e digitando:

Aggiungiamo il VirtualHost in sites-available copiando un modello esistente:

Modifichiamo il file che abbiamo appena copiato ed aperto fino ad ottenere qualcosa di simile:

In questo modo il nostro server risponderà sia al dominio torregatti.com che al sottodominio www.torregatti.com

Salviamo con CTRL+O e confermiamo premendo INVIO.

Abilitiamo il host digitando:

Ricarichiamo Apache digitando:

A questo punto possiamo testare la nostra configurazione da dentro Windows modificando il file hosts in C:\Windows\System32\drivers\etc\ impostandolo nel modo seguente:

Salviamo e verifichiamo dal browser che il risultato sia simile a questo:

7. Installazione e configurazione di WordPress

Adesso voglio concludere installando WordPress sul nostro nuovo dominio appena creato.

Anzitutto spostiamoci dentro la cartella del dominio e scarichiamo WordPress digitando i seguenti comandi:

Installiamo zip e scompattiamo il pacchetto:

Spostiamo tutti i file da dentro la cartella wordpress alla radice del dominio digitando:

Rimuoviamo la cartella wordpress:

Assegniamo tutti i file ad Apache, altrimenti avremo problemi durante l’utilizzo del portale (per esempio nel caricamento delle immagini).

Creiamo ora un database con utente per la torregatti.com

Accediamo al database digitando:

Creiamo un nuovo database digitando:

Creiamo un utente per il database e diamogli tutti i privilegi.

A questo punto andando su http://torregatti.com dovremmo vedere l’installazione di WordPress.

Completiamo tutti i dati che abbiamo già configurato:

Completiamo l’installazione seguendo le istruzioni a video ed abbiamo finito.

Vedi articolo

[python] Esercizio su utilizzo di socket e database

Proviamo a realizzare questo semplice esercizio: vorrei avere un server ed un client che possano comunicare tramite socket, in modo tale che il client possa richiedere al server dei dati, il server preleverà tali dati da un database MySQL e li invierà al client.

Lo schema dell’esercizio è approssimativamente questo:

Per svolgere l’esercizio utilizzerò un database con una tabella clienti costruita nel modo seguente:

In aggiunta utilizzerò una classe MySQLdb personalizzata, sviluppata nel modo seguente e messa nel file database.py:

La cartella dell’intero progetto sarà organizzata nella maniera seguente:

client.py
librerie
└── database.py
└── __init__.py
server.py

Fatte queste premesse andiamo anzitutto a creare il nostro file server.py. Nel codice ho inserito i commenti ai vari passaggi:

Adesso è il momento del client.py.

I risultati che dovremmo vedere sono rispettivamente:

1. Per il server vedo quando è stato avviato, da dove e da quale porta

2. Sul client vedo l’elenco presente sul database.

Vedi articolo

[python] Esercizio su funzioni ricorsive e calcolo tratte dei treni

Facciamo un piccolo programma in Python che ci permetta di gestire le distanze da percorrere tra due stazioni, di partenza ed arrivo.

Abbiamo le seguenti tratte:

Stazione A Stazione B Distanza
Firenze Bologna 100km
Firenze Roma 250km
Roma Napoli 200km
Bologna Milano 220km
Bologna Venezia 150km

Ogni tratta è percorribile sia in andata che in ritorno. Quello che vogliamo è che il programma ci permetta di inserire due città e calcolare la distanza minima da percorrere e le stazioni da attraversare.

Anzitutto vediamo come sono disposti i nodi dell’intero percorso:

Notiamo che in questa configurazione elementare solo Bologna ha 3 rami, mentre tutte le altre città hanno solo 2 rami ciascuna.

Potremmo affrontare l’esercizio lavorando sui nodi oppure sulle tratte. In questa soluzione lavorerò sulle tratte.

Cominciamo quindi creando anzitutto una classe che ci permetta di descrivere ogni tratta come abbiamo visto nel mandato dell’esercizio.

In questo modo dichiariamo 3 variabili private per registrare le due città della tratta e la rispettiva distanza.

Adesso registriamo tutte le tratte in una lista, nel modo seguente:

Ora cominciamo a pensare all’algoritmo che potrebbe permetterci di calcolare il percorso.

Immaginiamo anzitutto la soluzione più semplice, dove io penso di andare da Firenze a Napoli. Su questa tratta non ci sono diramazione e sostanzialmente il percorso che dovrà venire fuori sarà Firenze – Roma – Napoli.

Fase 1:

Faccio un ciclo su ogni elemento della lista tratte[] e cerco anzitutto dove è presente la città di partenza. Siccome la città può essere sia in A che in B, per ogni oggetto Tratta dovrò implementare un metodo all’interno dell’oggetto stesso che mi permetta di valutare se la città sia presente in modo comodo. Implementiamo quindi la classe nel modo seguente:

Il metodo presente(citta) mi permette di valutare se la città sia presente nella tratta.

Fase 2:

Se trovo la città di partenza su una tratta allora controllo se l’altra città della tratta sia quella di arrivo. Allo stesso tempo registro la città di partenza all’interno di una lista percorso[] in modo da metterla come partenza del percorso complessivo.

Quindi se l’altra città è quella di arrivo posso chiudere il percorso, altrimenti passo il controllo sull’altra città.

Quando mi trovo nella riga 10 capisco anche che ho trovato la fine del percorso, quindi posso salvare l’intero percorso da qualche parte. Siccome potrei avere molteplici percorsi possibili decido di salvare il percorso in una lista globale chiamata percorsi = []

Modifichiamo quindi il codice nel modo seguente:

Adesso analizziamo due aspetti dell’ultima istruzione, quella dove richiamo la funzione.

Anzitutto voglio tirare fuori dalla tratta l’altra città, rispetto alla città di partenza. Per farlo implemento la classe principale nel modo seguente:

In questo modo quando mi trovo per esempio sulla tratta Firenze – Roma posso passare all’oggetto tratta Firenze, che conosco essendo il punto di partenza e chiedergli di darmi l’altra città della tratta, in questo caso Roma.

Il secondo aspetto che voglio evidenziare è che passo la lista percorso[] alla funzione medesima in partenza dall’altra città, per farlo utilizzo l’istruzione []+percorso, in caso contrario percorso passerebbe per riferimento e qualora fosse passato su più rami verrebbe elaborato contemporaneamente da più rami. Io invece voglio che resti un oggetto singolo e lineare per ogni percorso.

Arrivati a questo punto del codice la situazione è la seguente:

  1. Prendo in input partenza DA = Firenze e A = Napoli
  2. Aggiungo DA (Firenze) al percorso[]
  3. Passo a setaccio la lista delle tratte[]
  4. In posizione 0 trovo la tratta Firenze – Bologna a cui DA appartiene
  5. Controllo se A (Napoli) appartiene alla tratta
  6. Dal momento che non appartiene, prendo l’altra città della tratta, ovvero Bologna e la passo come nuovo DA alla funzione medesima
  7. La funzione ricomincia e aggiungendo DA (Bologna) al percorso[]
  8. Scorro la lista delle tratte[] in cerca di DA (Bologna)
  9. Trovo che DA nella posizione 0 sulla tratta Firenze – Bologna
  10. LOOP INFINITO!

Fase 3:

Devo evitare il loop infinito in cui il percorso possa tornare indietro. Per farlo modifico la mia funzione aggiungendo il seguente controllo all’inizio:

In questo modo controllo che il punto di partenza DA non sia già presente nel percorso[].

Adesso ricomincio a controllare il mio algoritmo da capo:

  1. Prendo in input partenza DA = Firenze e A = Napoli
  2. Aggiungo DA (Firenze) al percorso[]
  3. Passo a setaccio la lista delle tratte[]
  4. In posizione 0 trovo la tratta Firenze – Bologna a cui DA appartiene
  5. Controllo se A (Napoli) appartiene alla tratta
  6. Dal momento che non appartiene, prendo l’altra città della tratta, ovvero Bologna e la passo come nuovo DA alla funzione medesima
  7. La funzione ricomincia e aggiungendo DA (Bologna) al percorso[]
  8. Scorro la lista delle tratte[] in cerca di DA (Bologna)
  9. Trovo che DA nella posizione 0 sulla tratta Firenze – Bologna
  10. L’altra città (Firenze) è uguale ad A? No, quindi ripasso l’altra città come nuovo DA alla funzione medesima
  11. La funzione si interrompe, perché DA (Firenze) è già presente in percorso[]
  12. Torno al punto 9
  13. In posizione 3 trovo Bologna – Milano dentro tratte[] dove appartiene il mio DA
  14. Questo pezzo di codice adesso si ripete uguale a quello tra 10 e 12 fino a chiudersi su Milano e Venezia che terminano il percorso
  15. Trono al punto 3
  16. In posizione 1 trovo la tratta Firenze – Roma a cui DA (Firenze) appartiene
  17. Controllo se A (Napoli) appartiene alla tratta
  18. Dal momento che non appartiene, prendo l’altra città della tratta, ovvero Roma e la passo come nuovo DA alla funzione medesima
  19. La funzione ricomincia e aggiungendo DA (Roma) al percorso[]
  20. Scorro la lista delle tratte[] in cerca di DA (Bologna)
  21. Trovo che DA nella posizione 1 sulla tratta Firenze – Roma
  22. L’altra città (Firenze) è uguale ad A? No, quindi ripasso l’altra città come nuovo DA alla funzione medesima
  23. La funzione si interrompe, perché DA (Firenze) è già presente in percorso[]
  24. Torno al punto 20
  25. Trovo che DA nella posizione 2 sulla tratta Roma – Napoli
  26. Controllo se A (Napoli) appartiene alla tratta
  27. Napoli appartiene alla tratta nel pezzo di codice if t.presente(a)
  28. A questo punto aggiungo A (Napoli) alla fine di percorso[]
  29. Aggiungo il percorso[] ai percorsi[] con l’istruzione percorsi.append(percorso)

Fase 4:

Apporto ancora un paio di correzioni tecniche alla mia funzione per evitare inutili duplicati.

A questo punto posso scrivere la parte principale del mio programma con:

Per stampare il percorso faccio una join su ogni percorso che trovo dentro a percorsi[]

Fase 5:

Aggiungo soltanto un metodo per calcolare le distanze. Potrei farlo anche in modi più ottimizzato, ma per le finalità di questo esercizio ci accontentiamo di percorrere tutte le stazioni, esclusa l’ultima, e di calcolare la distanza tra la stazione corrente e la successiva sommandole tutte insieme.

A tale proposito aggiunto un metodo che mi permetta di valutare se 2 città appartengono entrambe alla tratta ed un getter per la distanza.

La funzione quindi sarà:

Fatto tutto questo posso completare il mio programma nella sua versione finale nel modo seguente:

Se volessimo complicare un po’ lo schema potremmo aggiungere altre tratte:

Ed ottenere una versione finale del programma in questo modo:

Il nostro nuovo programma genererà un output come questo:

Vedi articolo

[Excel] Sommare tariffe giornaliere diverse per data usando le matrici in Excel

Per chiunque fosse interessato a lavorare sulla matrici in Excel ho pubblicato un simpatico esercizio sul sito di Mummu Academy al seguente link:

[Excel] Sommare tariffe giornaliere diverse per data usando le matrici in Excel

Vedi articolo

Tow Point Hospital su Steam crash con errore TPH.exe e codice eccezione 0xc0000005

Questo codice di errore si verifica probabilmente perché c’è un file corrotto del gioco (o banalmente un aggiornamento andato male).

Si avvia il gioco e dopo un po’ va in crash senza motivo apparente.

Soluzione: bisogna verificare l’integrità dei file di gioco tramite lo strumento di Steam

Per farlo procedere nel modo seguente:

  1. Aprire Steam e andare su Libreria > Giochi
  2. Nell’elenco sulla sinistra cliccare col destro sul gioco e selezionare Proprietà

  3. Selezionare la scheda File locali e poi premere su Verifica integrità dei file di gioco
  4. Attendere la fine della procedura. Se il problema era di integrità si verrà avvisati che c’erano uno o più file corrotti e che saranno scaricati di nuovo. Si potrà notare attivo un download nell’omonima sezione.
  5. Fine. Adesso si può giocare di nuovo.

Vedi articolo

[excel] Come creare una password casuale di lunghezza arbitraria con un’unica formula

Mi sono chiesto se ci fosse un modo, utilizzando Excel, di generare una password casuale di lunghezza arbitraria con una singola formula.

Naturalmente utilizzando VBA sarebbe semplicissimo, si potrebbe creare una propria funziona ed utilizzarla all’interno della formula. In alternativa si potrebbe creare una tabella di riferimento e generare la password a partire da essa (qui c’è un esempio interessante).

Però mi sono impuntato a voler creare una singola formula, utilizzando le funzioni disponibili nativamente in Excel, per generare una password di lunghezza arbitraria.

Soluzione veloce

Per chi non avesse voglia di proseguire nell’analisi della questione la soluzione è la seguente (per 1 singolo carattere preso tra maiuscole, minuscole, numeri e caratteri speciali):

Per generare una password di 2 caratteri basta concatenare la formula precedente per 2 volte, di 3 caratteri per 3 volte ecc (di seguito l’esempio per 2 caratteri):

Spiegazione

Anzitutto partiamo dalla seguente idea. Se avessi un vettore di 3 caratteri, potrei estrarre casualmente uno dei tre caratteri?

Per farlo mi è sufficiente scrivere:

Ad ogni ricalcolo del foglio questa formula pescherà casualmente un valore tra 10, 20 e 30. Tra le parentesi graffe {} ho inserito una matrice (nello specifico un vettore colonna) di 3 valori. Il punto fa da separatore di riga, altrimenti il backslash farebbe da separatore di colonna.

In ogni caso la presente formula sarebbe equivalente alla seguente situazione:

In A4 in questo caso vedrei un valore casuale preso tra A1:A3.

Seconda idea. Sarebbe possibile generare, al posto dei suddetti valori, dei valori casuali che escano fuori da una funzione? Purtroppo Excel non consente di scrivere esplicitamente una matrice contenente a sua volta delle funzioni, senza passare dall’utilizzo delle celle.

Allora mi sono chiesto: ci sarà un modo per scrivere una stringa e trasformarla in un vettore mediante un separatore di stringa (una specie di str_split per intendersi nel PHP)? Se la stringa è composta di singoli caratteri che dovranno diventare elementi del vettore è effettivamente possibile.

Possiamo cioè trasformare il nome Noctis nel vettore {“N”.”o”.”c”.”t”.”i”.”s”}

Per farlo è sufficiente utilizzare:

Faccio notare che INDIRETTO prendere le righe dalla 1 alla 6. Con RIF.RIGA generiamo un vettore di riferimenti equivalente a {1.2.3.4.5.6}. Per inciso la funzione sarebbe potuta anche essere così:

Dal momento però che mi fa fatica scrivere tutto il vettore da 1 a 6 (più che altro se fosse stato più lungo sarebbe risultato abbastanza impensabile) preferisco generarlo con questo semplice trucchetto.

A questo punto abbiamo capito che possiamo spezzare una stringa arbitraria nel vettore dei caratteri che la compongono.

Adesso prendiamo in considerazione la seguente tabella ASCII.

Grazie alla funzione CARATT.UNI posso estrarre un carattere a partire dal suo riferimento numerico nella suddetta tabella (nello specifico qualunque carattere UNI-CODE, ma non è il momento di approfondire la cosa).

Per esempio se digito:

Ottengo la lettera p minuscola.

Quindi posso generare caratteri casuali mischiando questa funzione con CASUALE.TRA nel modo seguente.

Caratteri maiuscoli:

Caratteri minuscoli:

Caratteri speciali:

Per generare invece i numeri da 0 a 9 mi basta utilizzare:

Quindi usando la formula:

Posso generare una stringa di 4 caratteri contenente un numero casuale, una maiuscola casuale, una minuscola casuale e un carattere speciale casuale.

Inserendo questa dentro la suddetta formula con STRINGA.ESTRAI posso estrarre i quattro caratteri dalla stringa in un vettore di caratteri casuali con la seguente formula:

A questo punto inserendo il tutto dentro a INDICE ottengo la precedente formula e il gioco è fatto.

Per generare delle password casuali di 16 caratteri come queste:

!#lKTHLb0nx2Z(0H
7&x(128’#L#(t6B3
,77YJ”lu35%LKYVm
svkA.ur1Y””+#r*t
15I35t1Z”(/Lz#0a

Ci sarebbe sufficiente utilizzare la formula un po’ più lunga e ripetuta come detto all’inizio.

 

Vedi articolo

[wordpress] Too few arguments to function wpdb::prepare()

Soluzione veloce: Nella funzione $wpdb->prepare() va aggiunto almeno un argomento, che può essere anche array(), nella maniera seguente $wpdb->prepare( “SELECT * FROM tabella” , array() ).

Questo errore si presenta perché nella funzione $wpdb->prepare() manca un argomento, ovvero quello dei parametri da “preparare” dentro la query. Supponiamo per esempio di avere una variabile $id che vada inserita in una query. La seguente operazione sarebbe sbagliata:

L’errore sarebbe sia pratico che concettuale. Anzitutto questa scrittura di per se non necessita del $wpdb->prepare() dal momento che la variabile è già inserita nella stringa.

In secondo luogo la definizione della funzione prevede l’utilizzo di almeno due argomenti, come descritto qui: wpdb::prepare( string $query, array|mixed $args )

La funzione corretta sarebbe:

Oppure:

 

Vedi articolo