Per installare GitHub desktop su Linux Mint, bisogna seguire questa procedura:
Appunti di programmazione: pezzi di codice, note, soluzioni e algoritmi.
martedì 16 dicembre 2025
venerdì 26 settembre 2025
GODOT - Elemento dietro e davanti ad un oggetto
Questo "valore Y" viene considerato prendendo il centro della "croce" che appare sull'oggetto (cioè la posizione del suo "posizionamento").
lunedì 22 settembre 2025
GODOT - Uso dei timer
Mi è capitato di dover inserire un timer nel codice GDScript per gestire degli eventi temporizzati senza utilizzare un singolo elemento aggiunto ai nodi (cosa che potrebbe essere problematica se si devono temporizzare più effetti/azioni).
La definizione/inizializzazione del timer è abbastanza semplice:
self.timer = Timer.new() # creo una nuova variabile di tipo Timer
self.timer.autostart = false # indico che non deve partire in automatico
self.timer.one_shot = true # indico che deve "girare" solo una volta
self.timer.paused = false # indico che il timer non è "in pausa"
Però... per poter partire, il timer dev'essere inserito in un nodo per poter funzionare!
$NodeInTree.add_child(self.timer)self.timer.timeout.connect(self._on_timeout)
self.timer.start(5)
func _on_timeout() -> void:
passlunedì 15 settembre 2025
GODOT - Risoluzione per cellulari Android
Per avere l'applicazione a schermo intero, la risoluzione corretta è: 2400x1080 (almeno, sul mio OnePlus Nord CE 5G).
E' possibile ovviamente utilizzare il viewport per definire delle risoluzioni minori, che "scalino".
Usando la 1200x540, l'effetto è gradevole e non è "pixellato".
domenica 14 settembre 2025
GODOT - Icone per Android
Provando a realizzare un'icona adatta ad un'app per android, mi sono accorto che il sistema "taglia" l'immagine con il contenuto centrale anziché utilizzare l'intera immagine.
In pratica, producendo un'icona 432x432 (come da guida dell'Export), si ottiene un'icona più piccola. Per cui bisogna considerare visibile esclusivamente il campo 284x284 all'interno dell'icona.
Per un'analisi dettagliata su come creare le icone per Android, andare qui.
mercoledì 10 settembre 2025
LOVE2D - Formattazione di stringhe
In Love2d è possibile utilizzare la funzione string.format per stampare (o, in generale, formattare) i dati. Considerando la mancanza di una funzione di serializzazione per il salvataggio dei dati, è bene sapere come funziona questa formattazione.
In pratica, funziona come la printf in C: utilizza una combinazione di caratteri particolari per indicare che tipologia di dato si vuole stampare.
Ecco una lista delle tipologie di dato stampabili:
%s stringa
%d decimale o intero
%f formattazione a virgola mobile (ad esempio, per math.pi stampa 3.141593)
%e formattazione scientifica (ad esempio, per math.pi stampa 3.141593e+00)
$E formattazione scientifica (ad esempio, per math.pi stampa 3.141593E+00)
%g formattazione "automatica" (ad esempio, per math.pi stampa 3.141593)
%G formattazione "automatica" (ad esempio, per math.pi stampa 3.141593)
%o valore in base ottale
%x valore in base esadecimale
%c carattere
%q codice Lua
Da notare l'ultima tipologia, utilissima per stampare esattamente quello che ha interpretato il codice Lua!
Altre informazioni si possono trovare a questo indirizzo:
martedì 9 settembre 2025
GODOT - Animare un contatore "score"
Per animare un contatore di score, bisogna usare uno script e sfruttare il "delta" fornito dalla funzione "process".
Questo lo script di esempio:
var finished = true
var time = 0.0
var time_to_current_score = 2.0
var a = true
var score = 1001
func _process(delta):
if finished and a:
time += delta
text = str(int(time / time_to_current_score * score))
if time >= time_to_current_score:
a = false
text = str(score)
GODOT - Impostare i font per la Pixel Art
Ho ricreato un giochetto sviluppato con il framework Love2d in Godot ed uno dei problemi più grossi che ho riscontrato è stato... come visualizzare correttamente il font senza antialiasing o altre "storture grafiche".
In Love2d, una volta impostato il filtro come "nearest", il gioco è fatto. Il rendering è perfetto.
In Godot non è così: il solo filtro non è sufficiente...
Dopo aver impostato la scena (per i test ho inserito uno sfondo, una label ed ho impostato una risoluzione di 384x216 in fullscreen), questi sono i passaggi da fare:
Gestione del file con il font
- doppio click sul file .ttf
- impostare Antialiasing a "None"
- cliccare "Reimport"
Gestione del progetto
- nella schermata General > Display > Window, impostare lo stretch mode a "viewport"
- nella schermata General > Rendering > Textures, impostare su Default Texture Filter il valore "Nearest"
Se questo non basta, ci sono altre impostazioni... che al momento non ho trovato nei menu (e che avevo visto mentre impazzivo per risolvere questo problema).
GODOT - Esportare per Windows
Per prima cosa, va installato il template di progetto.
Bisogna cliccare sul link "manage" nella "guida agli errori" (in basso), poi cliccare su "Go online" e quindi scaricare il pacchetto appropriato.
Altra cosa da scaricare e configurare: il file RCEdit.
Si trova a questo indirizzo: https://github.com/electron/rcedit/releases
Per configurarlo, cliccare su Editor > Editor Settings... > Export > Windows ed inserire il collegamento al file nella casella "rcedit".
A questo punto, è possibile impostare i vari parametri e quindi cliccare su "Export Project...".
A questo punto, Godot genererà un file eseguibile. Da notare che è di... dimensioni considerevoli!
GODOT - Esportare per Android
Con Godot è possibile sviluppare dei giochi che possono essere caricati sul cellulare (nel mio caso, un device Android).
Per farlo i passaggi sono molteplici, vediamo quindi la lista dettagliata.
No Export Template
Quando compare questo errore, bisogna cliccare su "Manage Export Template" (in basso), apparirà la schermata del Manager. Per prima cosa, bisogna assicurarsi di "essere online" (c'è un'opzione sotto la gestione del download), quindi si seleziona "Download and Install".
Java SDK e Android SDK
Per la produzione di un pacchetto Android corretto, è necessario che sulla macchina sia installato sia Android Studio che l'openSDK di Java, che si può trovare a questo indirizzo:
https://adoptium.net/temurin/releases/?variant=openjdk17
Una volta installati i due software, impostare i percorsi degli SDK in:
Editor > Editor Settings... > Export > Android
Nota:
Godot produce giochi per l'SDK 34, quindi è necessario scaricare il corretto SDK da Android Studio.
Impostare il Preset
Queste sono le opzioni da impostare:
- dopo aver aggiunto la tipologia "Android", bisogna assicurarsi che sia selezionata l'architettura "arm64"
- bisogna indicare la versione del codice (un numero intero)
- come "Export Format", impostare "Export APK"
- bisogna indicare un "Unique Name" nella forma del "dominio inverso" (ad esempio: com.google.NomeProgetto)
- il name sarà il nome dell'applicazione
Nota:
per la pubblicazione sul Play Store, bisogna registrare una chiave ".keystore" tramite questo comando:
keytool -v -genkey -keystore NOMEAPP.keystore -alias NOMEAPP -keyalg RSA -validity 10000
Il comando chiederà alcune info, bisognerà compilare ogni elemento.
Chiave di debug
La chiave di debug dovrebbe già essere attiva e presente nel gestore (presumo sia un'impostazione di base di Godot 4.4).
Se non è così, bisogna usare questo comando:
keytool -keyalg RSA -genkeypair -alias USERNAMEDEBUG -keypass PASSWORD -keystore debug.keystore -storepass PASSWORD -dname "CN=Android Debug,O=Android,C=US" -validity 9999 -deststoretype pkcs12
A questo punto, questi comandi si caricano negli Editor Settings.
Se tutto è a posto (e se il cellulare è collegato ed ha il Debug Sviluppatore attivo), comparirà il tasto "deploy" in alto a destra.
In questo modo, è possibile debuggare il gioco direttamente sul cellulare!
Problemi nel debug
Può capitare che, tentando il deploy di un gioco, il programma restituisce un errore di installazione. Se restituisce l'errore:
INSTALL_PARSE_FAILED_NO_CERTIFICATES
C:\Users\[UTENTE PC]\AppData\Local\Android\Sdk\build-tools
Per un bug, il programma cerca di usare la prima versione che trova (sul mio PC usava la 29) e questo dava problemi nella "firma" del pacchetto, rendendolo "invalido" e quindi non installabile.
Eliminando le cartelle precedenti alla 34, il problema si risolve.
lunedì 8 settembre 2025
GODOT - Nascondere la visualizzazione all'esterno di margini desiderati
- Clip Content (sotto Layout)
- Clip Children -da impostare a "Clip Only"- (sotto "Visibility")
venerdì 5 settembre 2025
GODOT - creazione di nodi dinamicamente a runtime
Lo spawning di elementi è una costante di moltissimi giochi (si usa anche nei giochi più semplici).
Per fare questo ci serviranno le seguenti scene:
- l'oggetto da riprodurre
- l'oggetto che gestisce la produzione di elementi
Prendiamo ad esempio un gioco di carte. Ho l'oggetto Carta, l'oggetto Mazzo ed il Board (sono tre scene con i dettagli all'interno).
Ognuno di questi nodi avrà il suo script collegato.
Carta
Nello script, andrà creata la funzione initialize() che configurerà il contenuto, ma al momento non concentriamoci sul suo funzionamento.
Mazzo
Lo script del mazzo prevede alcuni elementi importanti (il numero di carte, l'array con le carte all'interno, etc) ed una variabile fondamentale:
@export var cardNode: PackedScene
Questa variabile contiene la scena che andrà "duplicata" per generare tutte le carte del mazzo, e con @export sarà possibile associare il nodo desiderato direttamente dall'editor della scena.
Questa è la funzione per la creazione di tutte le carte (nell'esempio, facciamo 32 carte):
func initialize() -> void:
for i in range(self.numMaxCards):
var c: Node2D = self.cardNode.instantiate()
# al momento passo il contatore, ma si può caricare tutti i dati
# per "generare" la carta
c.initialize(i)
c.visible = false
# aggiunge la carta al mazzo
self.cardsInDeck.append(c)
# mescola il mazzo
self.cardsInDeck.shuffle()
Ci sono poi altre funzioni che servono a gestire il mazzo (numero di carte rimaste / pesca una carta / etc).
Board
Per la scena Board, nella funzione _ready() (o reset, se serve), bisogna instanziare il mazzo e poi inizializzarlo.
A questo punto, il mazzo conterrà il numero di nodi Carta voluto, ognuno con il suo dettaglio.
GODOT - uso di GDscript e scene globali
Nello sviluppo di un videogame, è utile avere delle strutture (variabili, funzioni, etc) che siano accessibili da ogni pezzo di codice.
Le "variabili globali", insomma.
In Godot è possibile farlo, piazzando variabili e codice in uno script e poi aggiungendolo all'autoload.
Procedura:
- nella sezione "FileSystem", cliccare con il tasto destro e selezionare "New Script..."
- impostare il nome dello script (global o environment o generic_functions)
- inserire nello script tutto ciò che il sistema deve sapere e "condividere"
- aprire "Project" > "Project Settings..."
- selezionare la voce di menu "Globals"
- selezionare la sezione "Autoload"
- inserire lo script nel campo "Path" (o cliccare sulla cartellina e selezionarlo con il mouse)
- inserire il nome del nodo a cui si avrà accesso nel resto degli script (occhio a maiuscole e minuscole)
- cliccare "+ Add"
E' anche possibile inserire anche delle scene nella sezione "Globals > autoload", per facilitare l'accesso ai componenti.
Potrebbe essere interessante per passare dati tra una scena e l'altra.
giovedì 4 settembre 2025
LOVE2D - Abilitare il fullscreen dal gioco
E' possibile far partire il gioco in "fullscreen" oppure si può impostarlo da codice. Vediamo come impostarlo da codice.
Partiamo dal passaggio al fullscreen.
I passaggi sono:
- recuperare i "mode" della finestra (dimensioni e flag)
- salvare la posizione attuale in una variabile (opzionale, serve per il ripristino)
- impostare mode con il fullscreen
local w, h, flags = love.window.getMode()
local pos_x, pos_y, pos_index = love.window.getPosition()
Position = {
x = pos_x ,
y = pos_y ,
displayindex = pos_index
}
flags.fullscreen = true
love.window.setMode(0, 0, flags)
Se invece vogliamo tornare alla finestra, i passaggi sono più o meno "inversi":
flags.fullscreen = false
flags.borderless = false
flags.resizable = false
love.window.setMode(DIM.W, DIM.H, flags)
love.window.setPosition( Position.x, Position.y, Position.displayindex )
Nota: DIM.W e DIM.H sono le dimensioni "originali" della finestra (vedere post precedente sullo "scalare" la grafica).
LOVE2D - Grafica "scalare"
Ho creato uno o due giochetti in pixelart ed uno dei problemi che ho dovuto affrontare è stato... "scalare" la grafica per evitare di fare un "gioco per formiche".
Questo è un piccolo tutorial che spiega cosa serve fare per gestire "scaling" (più avanti ci sarà un post sul fullscreen).
Per prima cosa, è necessario scegliere una dimensione "standard" da cui partire. Per ottenere il miglior effetto di "scaling", bisogna che la grafica di arrivo (ad esempio, la risoluzione -ormai standard- 1920x1080) sia un moltiplicatore esatto della grafica di partenza.
Le due opzioni più sensate sono il x3 ed il x4, che hanno rispettivamente le seguenti dimensioni:
x3 640x360
x4 480x270
x5 384x216
Nota: si può ovviamente lavorare ad un progetto con risoluzioni iniziali "standard", ad esempio 640x480, bisogna però "ridurre" il moltiplicatore e gestire il translate.
La prima cosa da fare è inserire il filtro "nearest" per disegnare i pixel senza "blur". Questo va fatto prima di qualsiasi aggiunta di asset (creati con newImage), in questo modo tutto sarà "nitido":
love.graphics.setDefaultFilter("nearest", "nearest")
Definiamo, a questo punto, una dimensione standard (quella utilizzata per il gioco, di norma indicata come "virtuale" -VR-) e la dimensione "finale" in finestra:
DIM_VR = {
W = 384 ,
H = 216
}
DIM = {
W = 384 * 2 ,
H = 216 * 2
}
Per far partire il gioco alla dimensione corretta, impostare gli stessi valori di DIM anche nel love.conf(t):
function love.conf(t)
t.window.width = 384
t.window.height = 216
end
Eventualmente, si possono impostare gli stessi valori nel love.load():
function love.load()
local w, h, flags = love.window.getMode()
if w ~= DIM.W or h ~= DIM.H then
love.window.setMode(DIM.W, DIM.H, flags)
end
end
Concentriamoci sul love.draw(t), dove andremo a "sistemare" la scala della grafica.
Per disegnare correttamente il tutto, useremo un "buffer" e "scaleremo" quello.
I passaggi necessari sono questi:
- recupero delle dimensioni della finestra
- creazione del canvas
- calcolo della scala come "moltiplicatore intero"
- impostazione del canvas
- impostazione della scala
- eventuale traslazione per disegnare il tutto
- disegno della schermata di gioco
- chiusura del canvas
- disegno a video del tutto
Il codice, quindi, è:
function love.draw(dt)
-- dimensioni finestra
local screenSizeX, screenSizeY = love.graphics.getDimensions()
-- creazione canvas
local framebuffer = love.graphics.newCanvas(screenSizeX, screenSizeY)
-- calcolo scala
local scale = math.floor(math.min(screenSizeX / DIM_VR.W, screenSizeY / DIM_VR.H))
-- gestione del canvas e scala
love.graphics.setCanvas(framebuffer)
love.graphics.push()
love.graphics.scale(scale, scale)
-- gestione del translate
trans_x = (screenSizeX - DIM_VR.W * scale) / 2
trans_y = (screenSizeY - DIM_VR.H * scale) / 2
love.graphics.translate(trans_x, trans_y)
-- DISEGNO DELLA SCHERMATA DI GIOCO
love.graphics.draw(Asset)
-- reset
love.graphics.setCanvas()
love.graphics.pop()
-- disegno del canvas
love.graphics.draw(framebuffer, 0, 0)
end
Innestando questo codice, il sistema disegnerà la pagina della dimensione voluta in modo "scalato". Se la scala effettiva non è "intera", il disegno verrà centrato nella schermata.
Nota: a questo punto bisogna solo ricordarsi che l'intera grafica è "scalata", per cui se si utilizza il mouse come input, per ottenere la posizione corretta è necessario dividere il valore di X e Y per la scala!
martedì 2 settembre 2025
LOVE2D - Garbage collector
Facendo un test con un videogame che sto sviluppando, mi sono accorto che il quantitativo di RAM "mangiata" dal programma aumentava a vista d'occhio, fino a rendere instabile il sistema.
A quanto pare, il garbage collector non veniva chiamato correttamente dal framework, quindi l'ho impostato manualmente nella sezione love.update() di main.lua:
function love.update(dt)
collectgarbage("collect")
end
In questo modo il sistema pulisce costantemente ed infatti la RAM non è più stata "fagocitata".
giovedì 28 agosto 2025
WINDOWS - Variabili d'ambiente
Mi è appena capitato di entrare in un server, cercare di aprire il pannello per la gestione delle variabili d'ambiente e ricevere un errore rundll32.exe:
Il sistema, però, funziona... quindi si può aprire direttamente il pannello lanciando questo comando da un prompt con permessi di amministratore:
"C:\Windows\system32\rundll32.exe" sysdm.cpl,EditEnvironmentVariables
Questo aprirà il pannello e, da lì, è possibile gestire le variabili di ambiente (come il PATH).
mercoledì 27 agosto 2025
LOVE2D - Pubblicazione sul web
Ho iniziato lo sviluppo di un videogame in lua/love2d e volevo ospitarlo su itch.io, che offre anche il sistema per "giocarlo online" direttamente sul browser.
La procedura per ottenere un file giocabile (usa love.js come estensione di node.js) non è propriamente semplice e richiede (su windows) un po' di lavoro.
Utilizzeremo "makelove" (il repository si trova qui: https://github.com/idbrii/love-makelove ).
1. Installazione dei requisiti necessari
Procedura:
- installare python
- inserire il percorso di installazione e la directory "Scripts" nel PATH
- aprire un prompt (cmd.exe) come amministratore (sennò il sistema installa le librerie in locale)
- lanciare il seguente comando: pip3 install makelove
- assicurarsi che il tutto sia aggiornato, lanciando: python3 -m pip install --upgrade setuptools (i setuptools servono per la gestione dei packages)
- spostarsi nella directory in cui è presente il sorgente del gioco
- lanciare il comando: makelove --init e compilare i dati richiesti
A questo punto, abbiamo un file di configurazione per la produzione dei "pacchetti".
Lovejs non è previsto di base, quindi bisogna andare ad editare il file makelove.toml.
Procediamo a modificare il file di configurazione, aprendo il file makelove.toml con un qualsiasi editor (anche VS Code).
Un esempio potrebbe essere questo:
name = "TITOLO_GIOCO"
love_version = "11.5"
default_targets = ["win64","lovejs"]
build_directory = "PUBLISH"
love_files = [
"+*",
"-*/.*",
"-./PUBLISH/*",
]
[lovejs]
title = "TITOLO GIOCO" # used on the resulting web page
memory = "20000000" # starting memory of the webpage (default is 20 MB)
Nota: memory dev'essere grande abbastanza da contenere l'intero "pacchetto del gioco" prodotto. Arrotondate per eccesso.
L'importante è includere il target "lovejs".
Ora si salva e si chiude.
3. Pacchetti
Passiamo alla produzione dei pacchetti. La procedura è:
- aprire un prompt cmd
- lanciare il comando: makelove --version-name 1
Nota: ho aggiunto il sistema di gestione della versione, per facilitare le varie build.
Ora abbiamo, nella cartella indicata nel conf (io ho messo PUBLISH), una cartella con la versione e con dentro i pacchetti generati.
Il pacchetto potrebbe essere completo, ma prima di pubblicare i dati conviene modificare il codice della pagina che caricherà il gioco nel browser.
Bisogna entrare nella cartella lovejs e decomprimere il file .zip contenuto qui dentro.
All'interno del file bisogna modificare il file index.html ed il file theme\love.css
Queste le modifiche al file index.html:
eliminare il tag <h1> dentro al <center> in alto
modificare le dimensioni iniziali del canvas "loadingCanvas" con le dimensioni del gioco
eliminare il <footer> con i credits (presente un overlay che interferisce con il gioco)
modificare la funzione js function drawLoadingText(text) in questo modo:
var canvas = loadingContext.canvas;
loadingContext.fillStyle = "rgb(0, 0, 0)";
loadingContext.fillRect(0, 0, canvas.scrollWidth, canvas.scrollHeight);
loadingContext.font = '1em helvetica';
loadingContext.textAlign = 'center'
loadingContext.fillStyle = "rgb( 200, 200, 200 )";
loadingContext.fillText(text, canvas.scrollWidth / 2, canvas.scrollHeight / 2);
Queste invece le modifiche al file love.css:
- eliminare l'immagine di sfondo dal tag "body" (background-image)
- cambiare il colore di sfondo e del testo con uno "consono" al gioco (ad esempio... nero e bianco)
- cambiare i colori delle ancore (link, visited, hover), anche se non dovrebbero essercene
A questo punto, si sostituiscono i due file nello zip e si carica su itch.io.
martedì 26 agosto 2025
WINDOWS 11 - Refresh nelle cartelle
Da quando ho iniziato ad usare Windows 11, mi sono imbattuto in un problema abbastanza noioso: quando copio un file / creo una nuova directory / rinomino qualcosa, la modifica non appare. Devo premere F5 per vedere la modifica.
Per risolvere il problema, si deve eseguire questa procedura:
- si apre una cartella qualsiasi
- si clicca sui tre pallini orizzontali nel menu in alto (si trovano alla fine del menu, non totalmente a destra)
- si clicca su "Opzioni"
- si clicca sulla linguetta "Visualizzazione"
- nelle "Impostazioni avanzate:" (sotto), si scende fino a "Riquadro di spostamento
- si mette la spunta su "Espandi fino a cartella aperta"
Dopo aver salvato, il sistema fare il refresh automatico nelle cartelle (e nel desktop).
Ormai non mi chiedo più che c'entri quest'impostazione con il problema riscontrato, ma... è Windows. Solo chi l'ha programmato lo sa.
giovedì 7 agosto 2025
LUA+LOVE2D - Creare un eseguibile del gioco
Lua (in combinazione con Love2d) è un linguaggio di programmazione che permette di creare "facilmente" dei videogame.
Essendo un linguaggio "scriptato", però, non è possibile compilare un eseguibile.
E' possibile, però, creare un eseguibile in pochi, semplici passaggi:
- zippare tutti i file del programma, assicurandosi che il file main.lua sia nella root dello zip
- aprire un prompt di CMD nella directory in cui è presente lo .zip (CMD, non PowerShell!)
- lanciare questo comando:
copy /b "C:\Program Files\lua\LOVE\love.exe"+AirFighters.zip AirFighters.exe
In questo modo, verrà creato un file .exe che permetterà di lanciare il gioco.
Per poter "distribuire" il gioco, però, non basta l'eseguibile. Dovrete copiare anche tutte le .dll contenute nella directory di love.exe .
Per la modifica dell'icona, è necessario invece utilizzare uno strumento esterno.
lunedì 4 agosto 2025
SQL SERVER - ricerca di % tramite LIKE
In SQL Server, il carattere '%' si utilizza come wildcard per le ricerche. E se volessi cercare proprio quel carattere?
La soluzione è metterlo "tra quadre":
... WHERE campo LIKE '%testo [%]%'In questo modo, il sistema lo riconoscerà come "carattere" e la ricerca funzionerà correttamente.
lunedì 28 luglio 2025
SQL Server - aggiornamento password utenza
A volte, la modifica ad un'utenza non può andare a buon fine, e compare un errore che fa riferimento a "MUST_CHANGE set to ON".
Per risolvere il problema, basta usare uno script:
USE Master
GO
ALTER LOGIN utenteDaVariare WITH PASSWORD = 'password123'
GO
ALTER LOGIN utenteDaVariare WITH
CHECK_POLICY = OFF,
CHECK_EXPIRATION = OFF;
lunedì 23 giugno 2025
LINUX - reload dei mount caricati in /etc/fstab
Invece di riavviare il PC/server per caricare le nuove modifiche a /etc/fstab (o in caso qualcosa si sia incastrato), basta lanciare il seguente comando:
# mount -a
Questo comando ricarica tutti i mount presenti.
mercoledì 23 aprile 2025
POWERSHELL - Eseguire uno script non firmato con le policy
In windows 11, gli script di powershell sono "bloccati" se non hanno una firma digitale.
E' possibile bypassare questo blocco impostando una policy meno restrittiva per l'esecuzione dei comandi.
Per prima cosa, vediamo quali sono le policy impostate:
Get-ExecutionPolicy -List
Se non c'è una ExecutionPolicy impostata, verrà indicato Undefined.
Per permettere l'esecuzione, bisogna cambiare la policy per gli scope "CurrentUser" o "LocalMachine".
Per impostare una policy, si utilizza questo comando:
Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope CurrentUser
Nota: questo serve solo ad eseguire "temporaneamente" uno script senza la necessità di firmarlo. Una volta conclusa l'attività, conviene reimpostare la policy a "Undefined" per mantenere integra la sicurezza.
martedì 1 aprile 2025
WINDOWS - Accesso ad un singolo PC per un utente di dominio
E' possibile limitare l'accesso ad una singola postazione (o ad un numero limitato di postazioni) per un utente di dominio.
Bisogna accedere al server che gestisce l'Active Directory, aprire le proprietà dell'utente, andare nella TAB "Account", cliccare su "Log On To..." e quindi indicare il nome della macchina (o delle macchine) a cui garantire l'accesso.
lunedì 17 marzo 2025
WINDOWS - Link ad un RDP specifico
E' possibile generare un link ad un RDP (Remote Desktop Protocol o Connessione al Desktop Remoto) che punta ad una postazione specifica.
Per farlo, si crea un link con "crea collegamento" e quindi si inserisce questo comando:
mstsc.exe /v:PC-name
Nota: bisogna sostituire "PC-name" con il nome del PC (ma va bene pure l'IP).
giovedì 6 febbraio 2025
SQL SERVER - Controllare se un indice esiste
use DATABASE_NAME;
if exists (
select top (1) object_id as index_exists
from sys.indexes
where name = N'index_name'
and object_id = object_id(N'schema_name.table_name')
)
begin
print 'Found index "index_name" on "schema_name.table_name".';
end;
else
begin
print 'Did not find index "index_name" on "schema_name.table_name".';
end;
giovedì 30 gennaio 2025
ANDROID STUDIO - Ridurre la RAM dell'emulatore
Utilizzare Android Studio su un computer con Windows 11 e 8 giga di RAM è possibile, anche se bisogna scendere a qualche compromesso.
Contesto
Partiamo del contesto: mantenendo aperti solo alcuni programmi (pochi), la RAM utilizzata si aggira attorno al 56% del totale.
Android Studio "mangia" da solo circa 1,5 GB di RAM ed avviare un qualsiasi "device virtualizzato" di fatto ammazza il PC (a parte rari casi...), che praticamente smette di rispondere ai comandi finché non si riesce (a fatica) a chiudere l'AVD e poi Android Studio.
Soluzione
C'è però una soluzione di compromesso: abbassare la RAM utilizzata dall'AVD.
Di base, questo valore non è modificabile dall'interfaccia, ma si può modificare dentro i file di configurazione del dispositivo virtualizzato.
Per prima cosa, creiamo un nuovo device virtualizzato con le caratteristiche che vogliamo. Nel mio caso, ho simulato il mio cellulare personale con Android 13 (quindi Android SDK Platform 33).
A questo punto, bisogna cliccare sul burger menu, quindi su Tools e poi su Device Manager. Si aprirà un riquadro a destra.
Bisogna cliccare sui tre pallini accanto al nuovo device virtualizzato e quindi su Show on disk.
Una volta aperta la directory con i file del device, bisogna:
- cancellare (se presente) la cartella hardware-qemu.ini.lock
- aprire il file hardware-qemu.ini, trovare la riga hw.ramSize e cambiare il valore (io ho impostato 2048)
- aprire il file config.ini, trovare la riga hw.ramSize e cambiare il valore (io ho impostato 2048)
A questo punto, dopo aver riavviato Android Studio per caricare le modifiche, controllando i dettagli del device virtualizzato (identificate il device sotto Device Manager, cliccate sui tre pallini e selezionate View Details) dovreste trovare il nuovo quantitativo di RAM che avete impostato.
La macchina quindi si avvierà con la RAM specificata, che così non andrà ad appesantire il sistema operativo. Ovvio che risulterà un po' inchiodata... però almeno il sistema continuerà a rispondere ai comandi!
mercoledì 29 gennaio 2025
JAVASCRIPT - Replace di tutte le istanze trovate
const stringToEdit = 'tom;jack;jones';
const newString = stringToEdit.replace(/;/g, ' | ');
giovedì 23 gennaio 2025
SQL SERVER - arrotondare i DATETIME
In SQL Server, per arrotondare i DATETIME si utilizzano le funzioni DATEADD e DATEDIFF, in pratica si sottrae il tipo di valore che si vuole arrotondare a 0 (minuti, secondi, ore, etc).
Questo è un esempio:
DECLARE @dt DATETIME
SET @dt = '09-22-2007 15:07:38.850'
SELECT DATEADD(mi, DATEDIFF(mi, 0, @dt), 0) -- ritorna 2007-09-22 15:07:00.000
SELECT DATEADD(HOUR, DATEDIFF(HOUR, 0, @dt), 0) -- ritorna 2007-09-22 15:00:00.000
mercoledì 22 gennaio 2025
PYTHON - Uscire da 2 o più loop annidati
Facendo esercizi di programmazione (soprattutto Advent of Code e CodeWars) mi sono imbattuto in alcuni casi in cui, trovato un valore -ad esempio in una matrice- sarei dovuto uscire da due loop annidati.
Guardando in rete ci sono parecchi metodi per effettuare questa operazione (uso di try/catch, refactoring della funzione in modo che a quel punto esca dalla stessa, etc), però quello che mi è parso più sensato è l'utilizzo di una variabile di controllo.
Prendiamo ad esempio la ricerca della prima coppia di numeri contenuti in una lista che sono perfettamente divisibili (quindi senza resto) tra loro, con lo scopo di trovare il risultato di questa divisione.
Il codice è questo:
result = -1
el = [9, 4, 5, 7, 12, 3]
# variabile di controllo
found = False
for i in range(len(el)):
for j in range(i + 1, len(el)):
if el[i] % el[j] == 0:
result = el[i] // el[j]
found = True
break
if found:
break
print(result)
Utilizziamo la variabile found per indicare che il valore è stato trovato e mettiamo dentro ogni ciclo un controllo seguito da un break.
In questo modo, una volta trovato il risultato siamo sicuri di uscire da entrambi i cicli.
PYTHON - Split senza elementi vuoti
Ci sono dei casi in cui usare la funzione .split() può generare dei valori "vuoti" all'interno della lista prodotta.
In alcuni casi, questo è utile e quell'elemento va mantenuto. Potrebbe però esserci la necessità di processare solo i valori presenti in una stringa e magari in questa stringa ci sono degli "spazi di troppo"... lo split (che non utilizza espressioni regolari) non riesce a distinguere un singolo carattere " " (uno spazio) da un "blocco di spazi".
Come si tolgono, quindi, gli elementi vuoti? Con la funzione filter.
Funzionamento di base
La funzione applica ad ogni elemento "iterable" una funzione passata, usando questo formato:
f = filter(lambda x: x > 18, userAgeList)
Rimozione delle stringhe vuote
Se però noi al posto della funzione passiamo None, la funzione rimuove tutti i valori che sono considerati "nulli" da Python (per cui la stringa vuota, gli zeri, il valore None):
f = filter(None, userAgeList)
Se invece abbiamo una lista "mista" e vogliamo togliere esclusivamente i valori "" (e non 0 o None), bisogna specificare una funzione precisa:
f = filter(lambda x: x != '', s)
martedì 21 gennaio 2025
WINDOWS - Spegnere il PC da riga di comando
Spegnere un PC Windows da riga di comando potrebbe tornare utile quando si è connessi e si sta lavorando in desktop remoto (anche perché l'opzione non è presente nel menu start).
Il comando è:
shutdown /s /t 0
venerdì 17 gennaio 2025
SQL SERVER - Più valori in un singolo campo con STUFF
A volte è necessario recuperare più di un valore associato ad un record, ma senza produrre più record "duplicati".
Ad esempio, vorremmo ottenere l'elenco degli utenti con i gruppi ad esso associati o un elenco di utenti (per nome) con tutti gli account associati.
Nel primo caso, potremmo avere questa lista di utenti nella tabella "sys_utenti":
utente
----------------------------------------
m.rossi
a.bianchi
p.verdi
Con questi permessi nella tabella "sys_gruppiUtente":
utente | gruppo
----------------------------------------
m.rossi | admin
m.rossi | ufficioIT
a.bianchi | ufficioAmministrazione
p.verdi | segreteria
p.verdi | ufficioVendite
E vorremmo ottenere:
utente | listaGruppi
----------------------------------------
m.rossi | admin;ufficioIT
a.bianchi | ufficioAmministrazione
p.verdi | segreteria;ufficioVendite
Questo risultato si può ottenere utilizzando la funzione STUFF:
SELECT DISTINCT
sUte.utente,
ISNULL(STUFF(( SELECT DISTINCT ';' + sUtGp.gruppo
FROM sys_gruppiUtente AS sUtGp
WHERE sUtGp.utente = sUte.utente
FOR
XML PATH('')
), 1, 1, ''), '') AS gruppi
FROM sys_utenti AS sUte
ORDER BY sUte.utente
La query è leggermente complessa, utilizza una subquery per costruire i valori da restituire che, grazie alla mappatura in XML, produce una tabella ridotta e poi la "impacchetta" con STUFF.
La costruzione della tabella ridotta utilizza la mappatura XML: grazie la clausola FOR XML -che trasforma la "tabella dei dati" in una struttura XML- e poi specifica PATH('') -che indica a SQL di non usare nessun elemento per racchiudere i dati-.
La funzione STUFF, invece, consente di inserire una stringa in un'altra stringa eliminando un numero di caratteri specificato nella posizione iniziale della prima stringa e inserendo la seconda stringa in tale posizione.
I parametri sono:
- la tabella dei dati di origine
- la posizione da cui iniziare l'elaborazione
- il numero di caratteri da sostituire
- la stringa con cui fare la sostituzione
Nel nostro caso, abbiamo questi valori:
- la tabella "mappata" in xml
- la posizione iniziale della stringa (in SQL, si parte da 1 e non da 0!)
- il numero dei caratteri nella stringa di prefisso (';' è un solo carattere)
- una stringa vuota con cui fare la sostituzione (in questo modo, si fa effettivamente l'eliminazione)
Questo è un sistema flessibile e potente per ricostruire alcune informazioni utili.
Nota:
è importante notare l'inserimento di una stringa di X caratteri per separare i valori, che verrà successivamente rimossa da STUFF per il primo valore.
In pratica, da una stringa ;valoreA;valoreB otterremo valoreA;valoreB.
Nota:
il collegamento tra la subquery usata nella SELECT e la query principale è dato dal WHERE, che collega un campo della subquery ad un campo della query principale.
Questo è uno dei pochi casi (se non l'unico, forse) in cui si possono usare riferimenti esterni allo scope della query in oggetto (nel nostro caso, la subquery).
giovedì 9 gennaio 2025
PYTHON - Utilizzo di numeri complessi per la gestione di "mappe"
Analizzando le soluzioni di altri sviluppatori per risolvere i problemi dell'Advent of Code del 2024, ho trovato una soluzione semplice ed elegante per gestire le mappe.
La soluzione canonica per la gestione di una "mappa" (cioè una tabella fatta di righe e colonne) è utilizzare un dizionario con una tupla contenente le coordinate come chiave ed il dato caricato dentro come valore.
Utilizzando poi una struttura del genere, c'è bisogno di elaborare un sistema per recuperare e gestire le coordinate "x" e "y" presenti nella tupla, soprattutto nel caso dobbiamo "muoverci" all'interno della mappa o processare elementi attigui.
Ad esempio, se siamo nella casella (0, 0) e vogliamo spostarci in basso e a destra di una riga finendo in (1, 1), dobbiamo effettuare un calcolo che mappi i dati e faccia le somme:
a = (0, 0)
dest = tuple(map(sum, zip(a, (1, 1))))
Una soluzione che facilita questo genere di calcoli utilizza i numeri complessi, cioè i numeri che combinano una parte reale ed una parte immaginaria.
Dato che il dato è composto da due parti, è possibile usare il valore reale per definire la coordinata della riga ed il valore immaginario per definire la coordinata della colonna.
In questo modo, per effettuare la stessa operazione di prima basta sommare un valore "numerico" al dato:
a = complex(0, 0)
dest = a + 1 + 1j
PYTHON - Il costrutto WITH per leggere un file e processarlo
Per leggere il contenuto di un file, si può utilizzare i comandi l'apertura e la chiusura di un file e, in mezzo, il codice per leggere e processare il contenuto... oppure si sfrutta lo statement with.
Questo costrutto rimpiazza un blocco try-catch ed assicura che le risorse invocate vengano chiuse dopo il loro utilizzo.
Nel caso di un'attività su un file, si assicura che il suddetto file venga chiuso.
Questo è un esempio di utilizzo:
fileInput = "test.txt"
rows = []
with open(fileInput, "r") as file:
for r in file.readlines():
rows.append(r.strip())