tag:blogger.com,1999:blog-7171633387149483562024-02-07T05:56:38.742+01:00weRockFedericohttp://www.blogger.com/profile/12664789548240220803noreply@blogger.comBlogger67125tag:blogger.com,1999:blog-717163338714948356.post-51298785480995892372013-11-05T00:04:00.000+01:002013-11-05T11:49:01.146+01:00Da HTML::Mason a Mason2... primi passiAttenzione, questa pagina potrebbe contenere inesattezze: sono soltanto degli appunti su cui sto ancora lavorando!<br />
<h3>
Installazione Mason2</h3>
La nuova versione di HTML::Mason si chiama semplicemente Mason, ed è un sistema per la creazione di template e contenuti dinamici.<br />
<br />
A differenza di HTML::Mason, la nuova versione si occupa di gestione pura dei template ed è stata resa indipendente dall'ambiente Web, la parte di integrazione con il server Web è invece che è realizzata dal framework Poet, tramite utilizza PSGI/Plack.<br />
<br />
L'installazione di Poet si può fare in questo modo:
<br />
<br />
<pre>cpanm -S --notest Poet
</pre>
<br />
e poiché Mason è un prerequisito, verrà installato anch'esso. <i>cpanminus</i> è un componente per la gestione di pacchetti presenti in CPAN.
<br />
<br />
Installiamo anche <i>Mason::Plugin::PSGIHandler</i> con il quale possiamo creare il nostro primo sito funzionante:
<br />
<br />
<pre>mkdir /var/wwwmason
mason_psgi_setup /var/wwwmason/firstapp/
</pre>
<br />
ora per lanciare il nostro sito possiamo usare il seguente comando
<br />
<br />
<pre>cd /var/wwwmason/firstapp/; plackup -r
</pre>
<br />
e il nostro applicativo sarà in ascolto su <i>http://localhost:5000</i><br />
se vogliamo configurare Apache per caricare il nostro sito, proviamo così:<br />
<br />
<pre><Location "/firstapp"></pre>
<pre> SetHandler perl-script
PerlResponseHandler Plack::Handler::Apache2
PerlSetVar psgi_app /var/wwwmason/firstapp/app.psgi
</pre>
<pre></Location></pre>
<br />
attenzione che sembra convenga utilizzare <i>plackup -r </i>per lo sviluppo, mentre la soluzione su Apache va bene per i sistemi in produzione ma risulta difficoltoso ricaricare l'applicativo senza fare il restart di Apache: <a href="http://stackoverflow.com/questions/6124010/how-do-you-deploy-a-psgi-script-in-apache-without-restarting">How do you deploy a PSGI script in Apache without restarting?</a><br />
<br />
verificare anche i permessi della directory <i>/var/wwwmason/firstapp/data</i> dove Mason va a creare la cache ed i file precompilati.Federicohttp://www.blogger.com/profile/12664789548240220803noreply@blogger.com0tag:blogger.com,1999:blog-717163338714948356.post-72695866543704076022013-01-09T19:53:00.000+01:002013-01-09T19:53:00.149+01:00Obtain name, type and precision for columns in DBII had to find the structure (name, type, and precision for every column) of a table, connected via JDBC using DBI, and this is how I did it:
<pre class="brush: perl; gutter: false;">
#!/usr/bin/perl
use DBI;
my $host = '127.0.0.1';
my $url = 'jdbc:Cache://127.0.0.1/SOURCE';
my $dbo = DBI->connect("dbi:JDBC:hostname=$host;port=9001;url=$url", 'username', '***')
or die $DBI::errstr;
my $qry = $dbo->prepare("select * from custom.table");
$qry->execute();
print "Structure of $table \n\n";
my $num_fields = $qry->{NUM_OF_FIELDS};
for (my $i=0; $i< $num_fields; $i++) {
my $field = $qry->{NAME}->[$i];
my $type = $qry->{TYPE}->[$i];
my $precision = $qry->{PRECISION}->[$i];
print "$field, $type, $precision\n";
}
$qry->finish();
</pre>Federicohttp://www.blogger.com/profile/12664789548240220803noreply@blogger.com0tag:blogger.com,1999:blog-717163338714948356.post-55599734385521275262012-10-15T10:30:00.000+02:002012-10-15T10:30:03.956+02:00Nuova SIM e controlli di sicurezza vodafoneCausa acquisto nuovo cellulare, che richiede la Micro-SIM, e causa taglio artigianale SIM non andato a buon fine, mi reco ad un vodafone point per richiedere una nuova Micro-SIM funzionante.<br />
<br />
L'operatrice mi richiede il cartellino con il codice fiscale.<br />
Poi mi chiede il numero di telefono che scrivo su di un post-it.<br />
<br />
Poi mi consegna, gratuitamente, la nuova Micro-SIM, già immediatamente funzionante.<br />
<br />
Hey! Ma l'operatrice non mi ha chiesto carta d'identità o passaporto, nemmeno la patente, ed il codice fiscale non è un documento di riconoscimento, non ha la foto, non ha nessun sistema di sicurezza (PIN, Microchip, RFID, o quant'altro) ed è semplicemente riproducibile.<br />
<br />
Senza controlli aggiuntivi, chiunque può richiedere una nuova SIM a nome di chiunque altro....!Federicohttp://www.blogger.com/profile/12664789548240220803noreply@blogger.com0tag:blogger.com,1999:blog-717163338714948356.post-47548780702648621752012-07-12T16:45:00.002+02:002012-07-12T17:48:31.173+02:00PDF firmati digitalmente... alcuni appuntiCome gestire un PDF firmato digitalmente:<br />
<br />
<a href="http://www.egov-pa.it/component/content/article/7-articoli/firma-digitale/11-come-gestire-un-pdf-firmato-digitalmente.html">http://www.egov-pa.it/component/content/article/7-articoli/firma-digitale/11-come-gestire-un-pdf-firmato-digitalmente.html</a><br />
<br />
deploy delle impostazioni di sicurezza:<br />
<br />
<a href="http://blogs.adobe.com/pdfitmatters/2010/02/deploying_acrobat_to_import_se.html">http://blogs.adobe.com/pdfitmatters/2010/02/deploying_acrobat_to_import_se.html</a><br />
<br />
come esportare/importare le opzioni di sicurezza:<br />
<br />
<a href="http://learn.adobe.com/wiki/download/attachments/52658564/acrobat_reader_security_9x.pdf#page=37">http://learn.adobe.com/wiki/download/attachments/52658564/acrobat_reader_security_9x.pdf#page=37</a><br />
<br />
okay non è un vero post, sono solo degli appunti che mi servono... intanto lo pubblico, poi se sarà... scriverò un articolo più completo.Federicohttp://www.blogger.com/profile/12664789548240220803noreply@blogger.com0tag:blogger.com,1999:blog-717163338714948356.post-24319751145535940962012-01-02T23:32:00.000+01:002012-01-03T12:44:15.318+01:00Chi è il mio CSR?Sono sempre stato un professionista nel ricordare PIN, password, codici di accesso vari. E quando mi rendo conto che non vale la pena ricordare, so che devo scrivere le credenziali in un posto comodo e sicuro.<br />
<br />
Ma con il SecureCode delle carte di credito MasterCard ho sempre avuto un brutto rapporto.<br />
<br />
Oltre al codice scritto sulla carta di credito, ed oltre al codice di sicurezza stampato sul retro, alcuni esercizi commerciali su Internet richiedono, per le carte MasterCard, anche l'inserimento di un SecureCode, in pratica una password da associare alla carta. Fatto sta che la prima volta ero di fretta... inserire nuova password... confermare nuova password... nuova password inserita a caso ... pagamento andato a buon fine! Yuppy!<br />
<br />
Ma da quella volta non me ne è più andata bene una! Grazie a dio, prima di sbagliare il codice per tre volte, è sempre possibile cliccare su "SecureCode dimenticato", inserire qualche piccolo dettaglio personale (e probabilmente noto a tutto il mondo tipo data nascita codice fiscale etc. etc.), ed inserire un nuovo codice, bello fiammante, pronto per essere scordato.<br />
<br />
E se invece digita la password errata per ben tre volte? Io ho dovuto chiamare mia sorella, che mi ha prestato la sua di carta e meglio ancora, mi ha anche accompagnato fino in stazione dove ho preso appena in tempo il treno per Milano con il biglietto appena acquistato. Ma se non c'è così tanta fretta, a mente lucida, si telefona al numero verde scritto sulla carta, si comunica qualche dato personale, et voilà! Codice resettato, al prossimo acquisto se ne inserisce uno di nuovo (probabilmente è ciò che dovrà fare mia sorella visto che il codice che le ho inserito proprio non me lo ricordo).<br />
<br />
Fatto sta che mentre stavo acquistando un biglietto Venezia - New York dal sito della Delta Airlines, al momento dell'inserimento del Secure Code mi esce questo inquietante e criptico errore:
<br />
<br />
<pre>Your authentication could not be completed because of a system error.</pre>
<pre>If this happens consistently, please contact your CSR.
</pre>
<br />
Provo. Riprovo. Esco. Riprenoto. Reinserisco i dati. Cancello i moduli. Mi sconnetto e riconnetto. Ricompilo.<br />
<br />
Sempre, consistently, lo stesso errore!<br />
<br />
Così, non so perché, ma provo a rifare tutto utilizzando Internet Explorer al posto di Chrome. Clicco su "Secure code dimenticato" (ovvio, no? ormai non ci provo neanche più. sometimes life it's so easy!), imposto il nuovo secure code e... volo prenotato!!!<br />
<br />
Non posso crederci. New York, aspettami!Federicohttp://www.blogger.com/profile/12664789548240220803noreply@blogger.com0tag:blogger.com,1999:blog-717163338714948356.post-14478707281919060982011-11-08T17:00:00.000+01:002011-11-09T16:44:24.992+01:00Google, catch 22Cosa c'è di meglio che aprire Google per trovare una risposta, sentirsi fortunati perché Google ci porta precisamente sulla domanda di un tizio con il nostro stesso problema, e però l'unica risposta è un tizio incazzato nero che dice: ma è mai possibile? ancora questa domanda? Perché invece di continuare a farci perdere del tempo, prima di scrivere una domanda non cerchi un po' su Google?Federicohttp://www.blogger.com/profile/12664789548240220803noreply@blogger.com0tag:blogger.com,1999:blog-717163338714948356.post-12136441920928328152011-09-01T12:50:00.000+02:002011-09-01T12:50:05.581+02:00Google Italy Blog: Musica a tutto Chrome, anche in estate la tua musi...<a href="http://googleitalia.blogspot.com/2011/08/musica-tutto-chrome-anche-in-estate-la.html?spref=bl">Google Italy Blog: Musica a tutto Chrome, anche in estate la tua musi...</a>: Stanchi della radiolina portatile, delle canzoni trasmesse in spiaggia, del numero limitato di brani sulla vostra playlist? L’estate è tempo...Federicohttp://www.blogger.com/profile/12664789548240220803noreply@blogger.com0tag:blogger.com,1999:blog-717163338714948356.post-46324289647610657372011-07-29T14:44:00.003+02:002011-07-29T14:57:13.443+02:00Programmatori pazziBene o male, ma soprattutto male, qualunque sviluppatore impara a scrivere qualche piccola applicazione per il Web.<br />
<br />
Magari abbiamo scritto la nostra applicazione per tenere traccia delle attività da svolgere, come pagare la bolletta del metano, ricordarsi di revisionare la macchina, portare Tobia alla toelettatura per cani, consegnare un nuovo prototipo al cliente, o pagare gli alimenti per la prole alla ex fidanzata. L'accesso all'applicativo sarà previa autenticazione, e gli utenti potranno inserire i propri dati, leggerli in tabella, ricercarli, filtrarli.<br />
<br />
Poi che cosa manca? Gli utenti, oltre ad interagire con l'applicativo Web, vorranno scaricare i dati e portarli sul telefonino, farsene una copia su chiavetta, o importarli in Excel e farci qualche piccola elaborazione.<br />
<br />
Da qualche parte nella pagina si dovrà predisporre un link o una paginetta di download, e gli utenti, dopo aver aggiustato qualche filtro, potranno scaricare il file sul proprio client e gestirlo come preferiscono.<br />
<br />
E quindi, il programmatore medio che cosa si inventa? Generalmente la tecnica scelta si attesta intorno a queste soluzioni:<br />
<br />
<ol>
<li>si crea una bella <i>crontab </i>sul server, con una riga che viene eseguita ogni tot giorni, che crea una estrazione per ogni utente in <i>\var\www\home\downloads\attivita-nomeutente.dat</i>;</li>
<li>la pagina di download, quando viene richiamata, inizia a scrivere un file in <i>\var\www\home\downloads\attivita-nomeutente.dat</i>. Una volta competato il file, viene mandato in output un bel link all'estrazione appena creata;</li>
<li>la pagina di download richiama un processo sul server che inizia a scrivere un file in <i>\var\www\home\downloads\attivita-nomeutente.dat</i>. Poichè il processo è asincrono, si mette uno sleep di 5 secondi in modo da dare il tempo al processo asincrono di completare il file. Poi ci mettiamo un bel link al file appena generato.</li>
</ol>
Notate qualche cosa di strano?<br />
<br />
La prima tecnica è molto limitata: come possiamo applicare dei filtri? Ma uno sviluppatore creativo è in grado di risolvere anche questo: in fondo, quanto ci vuole a creare in anticipo tutti i file con tutti i filtri possibili ed immaginabili, tutti già preimpostati?<br />
Per la seconda tecnica, uno script con privilegi di scrittura su di una cartella che poi verrà servita tramite server HTTP è il sogno di ogni criminale informatico. Ma se proprio non ci sono altre possibilità, conviene almeno sapere che oltre al <i>chmod 777</i> o all'<i>Everyone Full Control</i> esistono anche svariate vie di mezzo.<br />
Per la terza ogni commento è superfluo. Posso solo giurare di aver visto anche questo!<br />
<br />
Se però non avete notato altro, forse la sicurezza informatica non è il vostro mestiere, e probabilmente non lo sarà mai.<br />
<br />
Il vero problema, grosso come un pilone portante del Burj Khalifa di Dubai, è che se mettiamo un file in <i>\var\www\home\downloads\</i> l'utente vi potrà accedere felicemente andando al link <i>http://www.example.com/downloads/attivita-nomeutente.dat</i> ma oltre al nostro amico autorizzato vi potrà entrare anche tutto il resto del mondo. Certo, disabilitare il browsing delle directory è senz'altro un'idea brillante, ma non basta.<br />
<br />
Il concetto è che al nostro Web Server non importa assolutamente nulla dell'autenticazione che abbiamo sviluppato nel nostro programma: abbiamo implementato un sistema di autenticazione per le nostre paginette Web? Bene. Abbiamo utilizzato un framework che implementa la parte di sicurezza? Meglio ancora. Ma questo sistema lo dobbiamo implementare anche per i nostri file. Solo allora possiamo servire le nostre pagine, dinamicamente, e protette dalle nostre credenziali.<br />
<br />
(Ci sono casi in cui generare precedentemente i file da far scaricare agli utenti è cosa buona e giusta; tra l'altro il Web Server è sicuramente molto più veloce del nostro script nel servire le pagine; in questi casi però cerchiamo almeno di dare ai file un indirizzo URL casuale).Federicohttp://www.blogger.com/profile/12664789548240220803noreply@blogger.com0tag:blogger.com,1999:blog-717163338714948356.post-66589725142360189282011-07-21T17:48:00.001+02:002011-07-26T14:10:48.622+02:00Sviluppare per il Web 2.0?Ho iniziato a sviluppare applicativi Web aziendali, pubblicati sulla Intranet, fin dal 1998.<br />
Al tempo l'azienda non era nemmeno collegata ad Internet, per cui non avevo ancora a disposizione una casella di posta elettronica aziendale, e le linee di collegamento tra le varie sedi distaccate erano decisamente molto lente.<br />
<br />
La piattaforma per cui sviluppavo era Windows NT, con Internet Information Server, e gli applicativi erano realizzati con tecnologia ASP in linguaggio VBScript. Il database era spesso un Microsoft Access (dite quello che volete, ma si tratta di un prodotto miracoloso!) o, quando eravamo fortunati, un SQL Server.<br />
<br />
Dopo pochi anni sono passato allo sviluppo per Apache su Linux, ma ho accuratamente scelto di evitare il PHP. So che il PHP è molto amato dalle comunità di sviluppo, ma quando si impara a conoscere un prodotto come ASP, passare al PHP sembra fare salto indietro di secoli. In ASP c'era un solo RecordSet, lo stesso RecordSet di Access, lo stesso di SQL Server, lo stesso di qualsiasi altro database di sistema. Non un RecordSet simile con le stesse funzioni: era proprio la stessa libreria di sistema: di per se, ASP era un sistema molto scarno, ma che si appoggiava largamente alle librerie di Windows.<br />
<br />
Nel mondo PHP invece ogni diverso database aveva del codice diverso per essere gestito. La connessione ad un MySql era diversa dalla connessione ad un PostgreSQL, diversa dalla connessione ad un ODBC, diversa la connessione da una qualsiasi altra fonte dati. Diversa da qualsiasi connessione a qualsiasi database sviluppato per la console di Linux o per qualche applicativo client server.<br />
<br />
(A vete intuito per quale ragione nel mondo Windows si parla di DLL Hell, mentre nel mondo Linux no? Ho il sospetto che nel mondo Linux vada di moda la riscrittura del codice piuttosto che la condivisione delle librerie... nonostante questo, avrei comunque qualche bella storia di .so Hell da raccontare!)<br />
<br />
Per cui ho deciso che lo strumento per cui avrei sviluppato sarebbe stato il linguaggio Perl.<br />
Non si tratta di un linguaggio per puristi, ma in fondo chi se ne importa? Ho programmato in qualsiasi cosa mi sia capitata per le mani, e l'ho trovato fin da subito un prodotto molto efficiente. E pazienza che la sintassi fosse orrenda e poco coerente: una volta abituati al VBScript, non si può che migliorare!<br />
<br />
La cosa che mi ha convito fin subito del Perl era la sua immensa collezione di librerie, per connettersi o per gestire qualsiasi cosa (database, periferiche, API di sistema, c'era addirittura del codice per gestire il proprio account MySpace, il tutto via codice...!). Generalmente le librerie del Perl erano di buona qualità e progettate con buon gusto. Inoltre, da non trascurare il fatto che la stessa libreria che si utilizzava per sviluppare applicativi di sistema era la stessa libreria da utilizzare per lo sviluppo Web: avevo finalmente trovato la coerenza anche nel mondo Linux!<br />
<br />
Ma soprattutto avevo trovato il miglior framework per il Web esistente sulla terra: <a href="http://www.masonhq.com/">HTML::Mason</a>!<br />
Il suo concetto di ereditarietà era favoloso: potevi concentrarti nello scrivere una paginetta che mostrava il contenuto della pagina, e tutto il resto, dal vestito grafico, alle connessioni al database, alle autorizzazioni necessarie, venivano ereditate secondo uno schema deciso in fase di progettazione.<br />
<br />
Purtroppo si trattava di un sistema molto difficile da installare e da configurare (non vi sto a raccontare di tutti i conflitti di librerie di sistema per riuscire a farlo funzionare... quando inizi ad utilizzare componenti che non sono presenti in una distribuzione e sono scarsamente utilizzati, anche il mondo dei pacchetti e delle dipendenze mostra i suoi limiti) ma una volta predisposto il tutto diventava uno strumento davvero veloce per sviluppare applicazioni Web complesse.<br />
<br />
L'ultimo applicativo che ho sviluppato era una specie di Cartella Clinica, con dati dei pazienti, variazioni anagrafiche, esami di laboratorio, esami radiologici, prescrizioni farmaceutiche, il tutto visualizzabile via Web oppure scaricabile in formato leggibile dal software del medico, previo accesso tramite utente e password.<br />
<br />
Le fonti di dati erano MySql, Oracle, SQL Server (eh sì, vi si poteva accedere anche da Linux!), o file di testo importati tramite crontab.<br />
Le pagine erano realizzate in XHTML, con CSS, con qualche bello spunto preso da <a href="http://www.csszengarden.com/">CSS Zen Garden</a>. JavaScript, come era giusto fare al tempo, era ridotto al minimo e si limitava a pre-convalidare i Form.<br />
<br />
Poi si sa come vanno le cose nella pubblica amministrazione. Lo sviluppo interno viene abbandonato, e viene appaltato all'esterno. Così il mio lavoro non consiste più nel progettare e realizzare programmi, ma consiste nel riuscire a far funzionare programmi scritti da terzi, con tecniche di programmazione arcaiche e/o discutibili, e che <strike>probabilmente</strike> sicuramente avrei potuto scrivere meglio!<br />
<br />
Negli ultimi cinque anni il mondo del Web è cambiato, il nuovo Web si chiama Web 2.0.<br />
Cosa bisogna imparare per restare al passo?<br />
Ho scelto di utilizzare il Google App Engine, questo richiede di imparare a programmare in Python ma (database a parte) tutto ciò che si utilizzava sotto Apache è ancora molto attuale. E all'autenticazione, il lato debole di ogni applicativo Web, non ci pensa più il programmatore ma se ne occupa Google!<br />
La lista seguente serve soprattutto a me, per capire che cosa è cambiato dal punto in cui ero rimasto. Non è definitiva e la aggiornerò quando serve:<br />
<br />
<ul>
<li>XHTML è stato abbandonato. Il successore di HTML4.01 è HTML5</li>
<li>Un applicativo, per essere funzionale ed apparire moderno, deve utilizzare AJAX</li>
<li>Utilizzare JavaScript non è più un tabù!</li>
<li>Creare a mano il proprio JavaScript è tabù: dove possibile, utilizzare JQuery o altre librerie standard!</li>
<li>Il framework standard di Google App Engine è Django. Non so se sarà il mio preferito, forse dovrei approfondire Pylons (che deriva in qualche modo da HTML::Mason)</li>
<li>Non bisogna dimenticarsi di integrare il proprio applicativo con Facebook e altri social networks, come ad esempio Google+.</li>
</ul>
Happy coding!Federicohttp://www.blogger.com/profile/12664789548240220803noreply@blogger.com2tag:blogger.com,1999:blog-717163338714948356.post-2257309259674654512011-06-29T21:29:00.002+02:002011-06-29T21:29:49.596+02:00Federico on Soundcloud<object height="225" width="100%"> <param name="movie" value="http://player.soundcloud.com/player.swf?url=http%3A%2F%2Fapi.soundcloud.com%2Fplaylists%2F903128"></param> <param name="allowscriptaccess" value="always"></param> <embed allowscriptaccess="always" height="225" src="http://player.soundcloud.com/player.swf?url=http%3A%2F%2Fapi.soundcloud.com%2Fplaylists%2F903128" type="application/x-shockwave-flash" width="100%"></embed> </object> <span><a href="http://soundcloud.com/federico-thiella/sets/federico-set-on-soundcloud">Federico Set on Soundcloud</a> by <a href="http://soundcloud.com/federico-thiella">Federico Thiella</a></span>Federicohttp://www.blogger.com/profile/12664789548240220803noreply@blogger.com0tag:blogger.com,1999:blog-717163338714948356.post-47080941394046425212011-04-18T21:27:00.000+02:002011-04-18T21:27:24.802+02:00S-ciopa, el dissionario rùstegoSulla falsa riga di <a href="http://www.urbandictionary.com/">urbandictionary</a>, ed aiutato dall'estrema pazzia della mia amica Marina, è con estrema fierezza che presento <a href="http://s-ciopa.appspot.com/">S-ciopa, el dissionario rùstego</a>!<br />
<br />
Il progetto è realizzato in Python, e sfrutta il Google App Engine. Lato programmazione potrei fare di meglio, lo so, ma una volta tanto ho pensato di puntare di più sui contenuti, e lasciare lo sviluppo nei ritagli di tempo. Poi si vedrà, non è ancora finita :-)<br />
<br />
Naturalmente di dizionari Veneti autorevoli se ne trovano quanti se ne vuole, sul web o in libreria. Con questo progetto volevamo soltanto dimostrare al mondo (se mai ce ne fosse ancora bisogno...) che forse forse un po' di svitol nelle rotelle della testa ci manca anche a noi...Federicohttp://www.blogger.com/profile/12664789548240220803noreply@blogger.com0tag:blogger.com,1999:blog-717163338714948356.post-22696326164572849412011-03-05T15:38:00.001+01:002011-03-05T15:40:39.442+01:00Free e-books e audio-books<p><a href="http://www.gutenberg.org">Project Gutemberg</a>: raccolta di libri di pubblico dominio in formato elettronico.
</p>
<p>
<a href="http://www.librivox.org">LibriVox</a>: raccolta di audio books di pubblico dominio, letti da volontari :-)
</p>Federicohttp://www.blogger.com/profile/12664789548240220803noreply@blogger.com0tag:blogger.com,1999:blog-717163338714948356.post-66296582246275700712011-03-04T12:02:00.000+01:002011-03-04T12:02:43.614+01:00Scorrere un file in perlPer scorrere un file in Perl con record a larghezza fissa, si può partire da questo codice:
<pre class="brush: perl; gutter: false;">
#!/usr/bin/perl -w
open(my $fh, "<", $nomefile) or die $!;
while(read($fh, $buf, larghezza)) {
# fai qualcosa con $buf, es. richiama la funzione unpack
}
</pre>
se invece si vuole leggere un file di testo, con gli a capo al punto giusto, si può usare questo codice che legge tutto il file e lo carica in un array:
<pre class="brush: perl; gutter: false;">
#!/usr/bin/perl -w
open(SRC, $nomefile) || die("Impossibile aprire il file di origine!");
@righe=<SRC>;
close(SRC);
</pre>
oppure si può leggere lo stesso file, ma una riga per volta:
<pre class="brush: perl; gutter: false;">
#!/usr/bin/perl -w
open(SRC, $nomefile) || die("Impossibile aprire il file di origine!");
while (<SRC>) {
# fai qualcosa con la riga corrente $_
}
</pre>
sono banalità, ma siccome non programmo mai con un unico linguaggio di programmazione ma con quello che capita... non mi ricordo mai le sintassi, e allora le scrivo qui così le ritrovo subito!
Naturalmente in Perl ci sono altri mille modi diversi per leggere un file!Federicohttp://www.blogger.com/profile/12664789548240220803noreply@blogger.com1tag:blogger.com,1999:blog-717163338714948356.post-35210483444272314662011-03-04T11:21:00.004+01:002011-03-04T12:02:03.345+01:00Come leggere l'elenco di file in una directory in perl?Utilizzando il perl, come si può ottenere l'elenco di file presenti nella directory corrente?
È semplice, ma siccome non mi ricordo mai lo posto qui!
<pre class="brush: perl; gutter: false;">
#!/usr/bin/perl -w
@files = <*.txt>;
foreach $file (@files) {
print $file . "\n";
}
</pre>
in questo caso vengono listati tutti i files con estensione .txt.Federicohttp://www.blogger.com/profile/12664789548240220803noreply@blogger.com2tag:blogger.com,1999:blog-717163338714948356.post-80175563535858424192011-01-18T21:37:00.000+01:002011-01-18T21:37:44.839+01:00CSS-101: The easy way to learn CSS<p>Ho letto la segnalazione nella Smashing Newsletter numero 25, e la rilancio qui per ricordarmi di controllare quando avrò un po' di tempo! :-)</p>
<p>
Libri e video sono ottimi strumenti per lo studio, ma quando si tratta di CSS i tutorial on line si rivelano spesso migliori, perché permettono di giocare con il codice, e vedere i risultati al volo.</p>
<p>
In questo sito sono raccolti molti trucchi, e molte spiegazioni sul perché un certo comando produce un determinato risultato:
</p>
<p><a href="http://www.css-101.org/">CSS 101</a>
</p>
<p>Non ho ancora provato, ma non voglio lasciarmi sfuggire questo link!</p>Federicohttp://www.blogger.com/profile/12664789548240220803noreply@blogger.com0tag:blogger.com,1999:blog-717163338714948356.post-92106908373284500162011-01-12T23:10:00.001+01:002011-01-12T23:20:53.854+01:00New song: Tie me up!<p>Dopo un lungo periodo di silenzio, finalmente riesco a pubblicare un nuovo pezzo strumentale intitolato <b>Tie me up</b>! :-)</p>
<p>
<div style="width:473px; border:solid #999999 1px; background-image:url('http://www.soundclick.com/images/elogos/SC_ExtBG.png')">
<a href='http://www.soundclick.com/alienmindbender'>
<div style="background-color:width:460px; height:45px; cursor:pointer; background-image:url('http://www.soundclick.com/images/elogos/SC_460.png');"></div></a>
<div id="lower"><object type="application/x-shockwave-flash" allowScriptAccess="never" allowNetworking="internal" height="60" width="473" data="http://www.soundclick.com/player/V2/mp3player.swf">
<param name="allowScriptAccess" value="never" />
<param name="allowNetworking" value="internal" />
<param name="movie" value="http://www.soundclick.com/player/V2/mp3player.swf" />
<param name="loop" value="false" />
<param name="menu" value="false" />
<param name="quality" value="high" />
<param name="wmode" value="transparent" />
<param name="flashvars" value="playType=single&songid=10100841&scid=10100841&q=hi&ext=1&autoplay=0" />
<param name="scale" value="noscale" />
<param name="salign" value="b" />
<param name="bgcolor" value="#000000" />
</object></div></div>
</p>
<p>
ho ancora molti progetti vaganti nell'hard disk... spero di completarli e pubblicarli presto!
</p>
<a href="http://www.last.fm/music/Alien+Mindbender"><img src="http://cdn.last.fm/labels_images/badges/blue.png" width="153" height="53" alt="Free MP3s on Last.fm" /></a>Federicohttp://www.blogger.com/profile/12664789548240220803noreply@blogger.com0tag:blogger.com,1999:blog-717163338714948356.post-84407821854965658432010-12-30T17:36:00.000+01:002010-12-30T17:36:00.061+01:00ElementTree: primi test!Sto un po' giocherellando con la classe <a href="http://effbot.org/zone/element-index.htm">ElementTree</a>, libreria di Python che serve a semplificare la gestione dei documenti XML.<br />
<br />
Questo codice scansiona alcuni documenti di esempio e li scrive nella console, strutturati ad albero:<br />
<br />
<pre class="brush: python; gutter: false;">
from elementtree.ElementTree import Element
from elementtree.ElementTree import parse
import urllib
proxies = {'http': 'http://proxy:80'}
def scanNode(node, depth):
for element in node.getchildren():
if element.text and element.text.strip():
print " "*depth + element.tag, "(" + element.text + ")"
else:
print " "*depth + element.tag
if element.getchildren():
scanNode(element, depth+1)
def parseTree(url):
print "--] Parsing di " + url + " [--"
tree = parse(urllib.urlopen(url, proxies=proxies))
print tree.getroot().tag
scanNode(tree.getroot(), 2)
print
def main():
parseTree("http://www.w3schools.com/xml/note.xml")
parseTree("http://www.w3schools.com/xml/cd_catalog.xml")
parseTree("http://www.w3schools.com/xml/plant_catalog.xml")
parseTree("http://www.w3schools.com/xml/simple.xml")
if __name__ == "__main__":
main()
</pre>
<br/>
Semplice semplice, ma lo scrivo qui perché mi può sempre servire!Federicohttp://www.blogger.com/profile/12664789548240220803noreply@blogger.com0tag:blogger.com,1999:blog-717163338714948356.post-22494097204763727012010-12-19T11:28:00.001+01:002011-07-29T10:22:59.013+02:00Unix e le password di default...Qualche settimana fa ricevo un avviso automatico che segnala un probabile malfunzionamento ad un apparato hardware che abbiamo in sala macchine.<br />
Ora, generalmente non mi occupo di queste cose, ma visto che in ufficio non c'era nessun altro prendo in carico la segnalazione e chiamo l'assistenza:
<br />
<br />
<b>Tecnico help desk</b>: <i>Sì, sembrerebbe proprio un guasto hardware, se è così faccio subito uscire un tecnico per la riparazione. Possiamo fare un po' di troubleshooting per avere conferma che si tratti di proprio un guasto hardware?</i><br />
<b>Io</b>: <i>Certamente... ma mi deve spiegare come fare perché non è un apparato che conosco o che gestisco io!</i><br />
<b>Tecnico help desk</b>: <i>Allora intanto si colleghi alla console....</i><br />
<b>Io</b>: V<i>a bene! Mi dia un attimo di tempo che devo recuperare la password...</i><br />
<b>Tecnico help desk</b>: <i>La password? Nessun problema, quella gliela posso comunicare io!</i><br />
<b>Io</b>: <i>Ah, però! Conoscete le password degli apparati dei clienti? Che efficienza! :-)</i><br />
<b>Tecnico help desk</b>: A<i>llora, le detto le credenziali: l'utente è root, e la password abcde123</i><br />
<b>Io</b>: <i>Ehm, abcde123? Ma cos'è? La password di default?? Perché c'è una leggera probabilità che nella nostra azienda le password di default vengano modificate...</i><br />
<b>Tecnico help desk</b>: (silenzio)<br />
<b>Io</b>: <i>Ehm, ma è la prima volta che vi capita un cliente che modifica la password dei propri apparati?</i><br />
<b>Tecnico help desk</b>: (silenzio)<br />
<br />
Una volta recuperata la vera password, ed una volta confermato il guasto hardware, nel giro di un paio d'ore arriva
il tecnico on site:<br />
<br />
<b>Tecnico on site</b>: <i>Questo è il pezzo da sostituire. Ora dobbiamo entrare nella console e disabilitare
quello guasto prima di scollegarlo.</i><br />
<b>Io</b>: <i>OK, mi collego alla console...</i><br />
<b>Tecnico on site</b>: <i>Perfetto... l'utente è root e la password è abcde123....</i><br />
<br />
Sistemato anche questo, chiamo il nostro consulente e chiedo conferma che il problema sia stato risolto:<br />
<br />
<b>Consulente</b>: <i>Allora! Prima di lasciare andare via il tecnico, puoi fare qualche controllo?</i><br />
<b>Io</b>: <i>Certamente! Basta che mi spieghi come fare...</i><br />
<b>Consulente</b>: <i>Allora, ti colleghi alla console, la password è abcde123 e....</i><br />
<br />
Uhm!
Ho l'impressione che nel mondo Unix la sicurezza non sia sempre presa molto sul serio...Federicohttp://www.blogger.com/profile/12664789548240220803noreply@blogger.com0tag:blogger.com,1999:blog-717163338714948356.post-80256511525376693422010-12-16T09:45:00.002+01:002010-12-16T22:14:20.773+01:00Bejeweled: determinare se ci sono ancora mosse disponibili<p>Come determinare se in una partita di Bejeweled ci sono ancora delle mosse disponibili?</p>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjM8PDrNnoO2ZFoo-7bPulOsyMq-PX982MKOa7LgcKEcV6mcfJgMVFtf2GxliKAiU5o5UCQNor4o_DTA519rjubJTBCgIzAKycp7qTVMxWCyA8ObrHRTXhb-HyEaiNVckGLY-CRhJaxRb4/s1600/bejeweled-game.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"><img border="0" height="240" width="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjM8PDrNnoO2ZFoo-7bPulOsyMq-PX982MKOa7LgcKEcV6mcfJgMVFtf2GxliKAiU5o5UCQNor4o_DTA519rjubJTBCgIzAKycp7qTVMxWCyA8ObrHRTXhb-HyEaiNVckGLY-CRhJaxRb4/s320/bejeweled-game.jpg" /></a></div>
<p>
L'input della funzione è una matrice MxN in cui il valore rappresenta uno dei colori.</p>
<p>
Per stabilire se ci siano ancora mosse possibili, ho pensato sia sufficiente ricercare nella matrice se ci sono tre pattern fissi, e naturalmente i relativi pattern inversi, che però sono già compresi se effettuo il controllo in tutte e quattro le direzioni.</p>
<p>
I pattern sono i seguenti:</p>
<pre>
XXyX
XyX
X
XXy
X
</pre>
<p>
Ed y deve essere diversa da X, oppure si può ignorare? Io voglio che sia diversa, casomai basta eliminare il confronto!</p>
<p>
Poi ho pensato che invece di verificare a mano se le coordinate sono fuori dalla matrice, ci starebbe bene un bel TRY...EXCEPTION! Provo a cercare il pattern... se viene sollevata un'eccezione, vuol dire che il pattern non c'è! Spero non sia un sacrilegio... sono pigro lo so... però è il modo migliore per rendere leggibile il codice!</p>
<p>
Questo è il mio codice <i>Python</i>... linguaggio che ancora non conosco bene! Quindi ci saranno sicuramente dei giganteschi errori di stile (ehm ad esempio non c'è un modo migliore per gestire le matrici??) ma speriamo ci siano solo quelli, e che la soluzione sia abbastanza corretta!</p>
<pre class='brush: python; gutter: false;'>
# esempio di matrice di colori
matrice = [ [1, 1, 2, 4, 4],
[1, 2, 9, 3, 4],
[8, 9, 8, 9, 8],
[7, 6, 5, 4, 3] ]
altreMosse = False
def cella(direzione, a, b):
# restituisce la cella a,b della matrice, ruotata secondo la direzione
try:
if direzione==0: return matrice[a][b]
elif direzione==1: return matrice[len(matrice)-1-a][b]
elif direzione==2: return matrice[a][len(matrice[0])-1-b]
elif direzione==3: return matrice[len(matrice)-1-a][len(matrice[0])-1-b]
except:
raise Exception
def Pattern1(direzione, a, b):
# ricerca il pattern XXyX
try:
return (cella(direzione, a, b) == cella(direzione, a, b+1) and
cella(direzione, a, b) != cella(direzione, a, b+2) and
cella(direzione, a, b) == cella(direzione, a, b+3))
except:
return False
def Pattern2(direzione, a, b):
# ricerca il pattern XyX
# X
try:
return (cella(direzione, a, b)!=cella(direzione, a, b+1) and
cella(direzione, a, b)==cella(direzione, a+1, b+1) and
cella(direzione, a, b)==cella(direzione, a, b+2))
except:
return False
def Pattern3(direzione, a, b):
# ricerca il pattern XXy
# X
try:
return (cella(direzione, a, b)==cella(direzione, a, b+1) and
cella(direzione, a, b)!=cella(direzione, a, b+2) and
cella(direzione, a, b)==cella(direzione, a+1, b+2))
except:
return False
for direzione in range(0, 4):
for a in range(0, len(matrice)):
for b in range(0, len(matrice[0])):
altreMosse = altreMosse or Pattern1(direzione, a, b)
altreMosse = altreMosse or Pattern2(direzione, a, b)
altreMosse = altreMosse or Pattern3(direzione, a, b)
print "Ancora mosse? ", altreMosse
</pre>Federicohttp://www.blogger.com/profile/12664789548240220803noreply@blogger.com0tag:blogger.com,1999:blog-717163338714948356.post-78244345765680178182010-11-01T18:56:00.000+01:002010-11-01T18:56:10.674+01:00Shining DeepI see dark around me<br/>
Blue skies turn black into the gloom<br/>
Your eyes shining through the night<br/>
Angel tears, and demon love<br/>
<br/>
Living on, long before the sunrise<br/>
Getting lost in a world of fantasies<br/>
Until the morning bright light<br/>
steals away all our fancy dreams<br/>
<br/>
Sometimes I feel that I'm going nowhere<br/>
Waiting for something I can never have<br/>
Lost in time, can you feel my heart beating<br/>
How will it go? I can barely see my way<br/>
<br/>
I don't know how to escape from here<br/>
A cold wind blows down the avenue<br/>
But don't mind, we will find our way<br/>
A way out to be pleased again<br/>
<br/>
Lasting sorrow, don't look back and wonder<br/>
Keep on moving, dancing all night long<br/>
And still I can't forget the words you said<br/>
Whispers in my ears<br/>
<br/>
Sometimes I feel that I'm going nowhere<br/>
Searching for something I can never have<br/>
Lost in time, can you feel my heart beating<br/>
How will it go? I can barely see my way<br/>
<br/>
What should we do to live on?<br/>
What should we do, just killing time?<br/>
What should we do to raise our heads?<br/>
What should we do just to survive?<br/>
<br/>
I've seen the end, I can't hold on<br/>
Can't find my way back anymore<br/>
And silver light still shines so bright<br/>
And shines so deep inside my eyes<br/>Federicohttp://www.blogger.com/profile/12664789548240220803noreply@blogger.com0tag:blogger.com,1999:blog-717163338714948356.post-87777092996728555432010-10-27T09:45:00.000+02:002010-12-16T09:12:55.420+01:00Process KillerQuando un programma va in crash la colpa viene attribuita sempre al programmatore. Mentre quando un programma si blocca, o è troppo lento, è di certo per qualche misfatto dell'amministratore di sistema. Anche se magari il programma è scritto con i piedi ed è propenso all'inchiappettamento di tutti i server su cui gira.<br />
<br />
Per ristabilire un po' di giustizia divina, ho pensato di killare senza pietà tutti i processi che utilizzano ferocemente la CPU per più di un determinato tempo. Metodo barbaro, ma molto in voga negli Unix dei vecchi tempi... e non solo.<br />
<br />
Naturalmente nel mio caso si tratta di processi che dovrebbero essere molto leggeri ma per qualche strana ragione si incastrano e finiscono per utilizzare il processore a pieno regime, infastidendo anche tutti gli utenti di programmi buoni e gentili.<br />
<br />
Come punto di partenza, direi di dare un'occhiata all'output del comando <i>pslist</i>, che lista tutti i processi in esecuzione su di una macchina (locale o remota, a patto di avere i privilegi necessari):<br />
<br />
<pre class='brush: shell; gutter: false;'>pslist v1.29 - Sysinternals PsList
Copyright (C) 2000-2009 Mark Russinovich
Sysinternals
Process information for ER-MEJO:
Name Pid Pri Thd Hnd Priv CPU Time Elapsed Time
Idle 0 0 2 0 0 23:05:50.623 0:00:00.000
System 4 8 114 4338 52 0:11:32.114 28:42:03.487
smss 252 11 3 30 340 0:00:00.171 28:42:03.487
csrss 348 13 9 1033 2744 0:00:06.645 28:41:51.132
wininit 416 13 3 79 992 0:00:00.093 28:41:50.414
explorer 4448 8 36 1252 69768 0:07:39.797 28:41:04.882
iexplore 3772 8 13 382 7172 0:00:04.539 3:14:05.766
iexplore 5788 8 22 704 97632 0:05:51.345 3:14:02.648
PsList 4136 13 1 151 1980 0:00:00.187 0:00:00.172
</pre><br />
le cui colonne interessanti sono le prime due (nome del process e PID) e le ultime due:<br />
<br />
<strong>Elapsed Time:</strong> tempo totale di esecuzione del processo<br />
<strong>CPU Time:</strong> tempo effettivamente utilizzato dal processo<br />
<br />
ad esempio <i>explorer</i> è in esecuzione da 28 ore e 41 minuti, e durante questo periodo ha utilizzato la cpu per 7 minuti e 39 secondi. Proviamo a rilanciare il <i>psexec</i> e a vedere che cosa succede:<br />
<br />
<pre class='brush: shell; gutter: false;'>Name Pid Pri Thd Hnd Priv CPU Time Elapsed Time
Idle 0 0 2 0 0 23:06:42.540 0:00:00.000
System 4 8 114 4342 52 0:11:32.426 28:42:33.493
smss 252 11 3 30 340 0:00:00.171 28:42:33.493
csrss 348 13 9 1050 2744 0:00:06.645 28:42:21.138
wininit 416 13 3 79 992 0:00:00.093 28:42:20.420
explorer 4448 8 42 1295 71484 0:07:40.234 28:41:34.888
iexplore 3772 8 13 389 7600 0:00:04.617 3:14:35.772
iexplore 5788 8 23 716 95520 0:05:53.513 3:14:32.654
PsList 1792 13 1 151 1988 0:00:00.171 0:00:00.156
</pre><br />
il comando è stato lanciato circa 30 secondi dopo il primo, ed infatti tutto gli <i>Elapsed Time</i> sono aumentati circa di 30 secondi, processo <i>PsList</i> escluso ma se osserviamo bene si tratta di un nuovo processo con un nuovo PID.<br />
<br />
Anche la colonna <i>CPU Time</i> è variata per alcuni processi, e se dividiamo il delta del <i>CPU Time</i> per il delta dell'<i>Elapsed Time</i> possiamo ottenere... <strong>la percentuale di utilizzo del processore</strong> di questo processo relativamente la periodo di tempo intercorso tra i due lanci del comando <i>psexec</i>.<br />
<br />
Da notare che se la macchina dispone di più processori nel <i>Task Manager</i> di Windows vedremo la percentuale riferita a tutte le CPU: un processo che gira su di un singolo processore non potrà quindi superare il 25% di CPU se la macchina dispone di 4 processori.<br />
<br />
Con il comando psexec invece non ci dobbiamo preoccupare del numero di processori che ha la macchina: il tempo di CPU utilizzato diviso il tempo di CPU avuto è disposizione può variare da zero a uno ed è l'utilizzo effettivo del signolo processore.<br />
<br />
Ho scritto questo codice in Python che controlla ad intervalli regolari un elenco di server, e che giustizia tutti i processi che durante questo periodo di tempo hanno consumato più del 90% della propria CPU:<br />
<br />
<pre class="brush: python">from __future__ import division
import subprocess
import re
import time
word = dict()
pausa = 30
servers = ('citrix01', 'citrix02', 'citrix03', 'server', 'server-2')
def milliSeconds(time):
tm = re.match("(\d*)\:(\d*)\:(\d*)\.(\d*)", time)
if tm:
return long(tm.group(1)) * 60*60*1000 + long(tm.group(2)) * 60*1000 + long(tm.group(3)) * 1000 + long(tm.group(4))
else:
return 0
def getProcess(server, nome):
pslist = subprocess.Popen('"c:\program files\utils\pslist.exe" \\\\' + server + ' ' + nome, shell=False, stdout=subprocess.PIPE)
for line in pslist.stdout:
proc = re.match("^(\w+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+([\w\:\.]+)\s+([\w\:\.]+)", line)
if proc:
serverPid = server + '.' + proc.group(2)
if serverPid in word:
if (milliSeconds(proc.group(7))-milliSeconds(word[serverPid][1]))/(milliSeconds(proc.group(8))-milliSeconds(word[serverPid][2]))>0.90:
subprocess.Popen('"c:\program files\utils\pskill.exe" \\\\' + server + ' ' + word[serverPid][4])
else:
if proc.group(1) <> "Idle" and proc.group(1) <> "System":
word[serverPid] = [proc.group(1), proc.group(7), proc.group(8), server, proc.group(2)]
def main():
while True:
for server in servers:
getProcess(server, 'winword')
time.sleep(pausa)
if __name__ == "__main__":
main()
</pre><br />
da sistemare per bene... e da usare con opportuna cautela!Federicohttp://www.blogger.com/profile/12664789548240220803noreply@blogger.com0tag:blogger.com,1999:blog-717163338714948356.post-63547579343053775542010-10-25T23:07:00.000+02:002010-10-25T23:07:22.206+02:00QR CodeBella l'idea di utilizzare codici a barre a due dimensioni, detti <a href="http://it.wikipedia.org/wiki/QR_Code">Codici QR</a>, per memorizzare vari tipi di informazioni comprese URL:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLh-jTvwdaIyVEJL_wPPw553ss5VePwMXv4_Rnrw5M3qSBGeXS1wl_PrABCBfCEBo64tM5VrwBkKOIDHDH7Asu5hZFjdJt0ncQqxXk7iYC82rCoUCTDUFZQ96McLFuTf2IPFkHmaAwZxM/s1600/qrcode.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLh-jTvwdaIyVEJL_wPPw553ss5VePwMXv4_Rnrw5M3qSBGeXS1wl_PrABCBfCEBo64tM5VrwBkKOIDHDH7Asu5hZFjdJt0ncQqxXk7iYC82rCoUCTDUFZQ96McLFuTf2IPFkHmaAwZxM/s1600/qrcode.png" /></a></div><br />
chissà se in casa Google si stanno attrezzando per interpretare questi codici ed includerli nel PageRank?<br />
E simpatica anche l'idea di Semapedia.org che propone di <a href="http://it.semapedia.org/">linkare il mondo fisico a quello virtuale</a>!<br />
<br />
Ma... cliccare su link a caso su di un browser non è mai una stata buona idea. Non è che un giorno tutto ciò comporterà qualche problema di sicurezza? O_o<br />
Meglio pensarci per tempo, che non si sa mai!Federicohttp://www.blogger.com/profile/12664789548240220803noreply@blogger.com0tag:blogger.com,1999:blog-717163338714948356.post-8090947819907876652010-10-25T22:46:00.001+02:002010-10-25T22:49:42.387+02:00Dati oggettivi ed interpretazioneRiguardo ai grafici che riportano l'andamento delle temperature della terra e che vengono presentati al grande pubblico, una cosa importante da sapere è che per ottenerli non è sufficiente inserire tutti i dati a disposizione su di un foglio Excel, cliccare su "Inserisci Grafico", e vedere che cosa ne viene fuori.<br />
I grafici che vediamo sono il risultato di anni di analisi e pulizia.<br />
<br />
Mi ricordo un fatto curioso e poco conosciuto, e cioè che tutti i grafici delle temperature degli ultimi anni presentavano un rapido aumento intorno alla metà degli anni 40, seguiti da una altrettanto rapida diminuzione.<br />
Questa variazione era insolita, gli scienziati l'hanno considerata come un dato sporco o una anomalia, ed hanno deciso di "eliminarla".<br />
<br />
Tutti i grafici ufficiali sono pertanto stati ripuliti e non presentano questo andamento.<br />
<br />
Il procedimento seguito dagli scienziati, naturalmente, è corretto: i dati grezzi sono per loro natura pieni di sporchi, errori, rumore... ed il loro compito è di riuscire ad isolare il vero andamento delle temperature escludendo tutte le sporcizie; il picco in questione è stato isolato perché "stonava" e non pareva avere spiegazione logica, tuttavia eliminare dei dati ad intuito, senza sapere bene il perché, è sempre una sconfitta.<br />
<br />
Leggevo su Le Scienze di Aprile 2009 un articolo in cui si dava finalmente una spiegazione a questo picco anomalo.<br />
Da una analisi più approfondita si è visto che l'aumento riguardava infatti le temperature dei mari. Durante gli anni della guerra le navi di rilevazione erano soprattutto statunitensi mentre le navi internazionali avevano diminuito le rilevazioni.<br />
<br />
Nelle navi internazionali la temperatura delle acque veniva rilevata tramite secchi calati in acqua che si raffreddano se portati in superficie, mentre nelle navi statunitensi si misurava la temperatura dell'acqua di raffreddamento dei motori, che è più calda della vera temperatura del mare.<br />
<br />
Le temperature, naturalmente, erano già state corrette per tenere conto di questo fatto, ma dopo questo studio si è visto che la correzione da applicare non era precisa e doveva essere modificata.<br />
<br />
Da un lato è stato dimostrato che l'intuizione è stata esatta e che quindi bene avevano fatto gli scienziati ad eliminare questo dato.<br />
<br />
Da un altro punto di vista significa che anche la scienza, pur con dati assolutamente oggettivi a disposizione, è sempre e comunque soggetta all'intuito ed all'interpretazione umana.Federicohttp://www.blogger.com/profile/12664789548240220803noreply@blogger.com0tag:blogger.com,1999:blog-717163338714948356.post-30965909382128303242010-10-25T22:18:00.000+02:002010-10-25T22:18:34.863+02:00Scegliere i colori: programmatori e buon gusto!La scorsa settimana cercavo un paio di mensole colorate da abbinare ad un mobiletto da mettere in sala. Non trovando nulla di interessante ho provato a chiedere un parere ad un dipendente Ikea, il quale mi ha mostrato delle mensole più larghe rispetto al mobiletto, con un altro spessore, e di colore simile ma diverso.<br />
<br />
Credo che i programmatori, quando devono scegliere i colori per i propri programmi o per le pagine web, siano come i dipendenti Ikea: completamente privi di ogni buon gusto.<br />
<br />
Capita spesso di vedere utilizzate combinazioni estreme di colori: serve un rosso, un verde, od un blu? Niente di più semplice, si sceglie un buon #ff000 per il rosso, un #00ff00 come verde, e per finire un buon blu #0000ff:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2sRhdBMCiixka_RWXs8GDM8CrBExAgNW4BlEHa7lCA3Id4fUf4J1buLnImzh_JVD2xXa7YDGTI3B-h9XOR-VVN3JjFMJfpXkWFpRhKg4PsQAc12wuFJUFPZ2fgv2laRPiMBzMIp6hSmY/s1600/colori_shock.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2sRhdBMCiixka_RWXs8GDM8CrBExAgNW4BlEHa7lCA3Id4fUf4J1buLnImzh_JVD2xXa7YDGTI3B-h9XOR-VVN3JjFMJfpXkWFpRhKg4PsQAc12wuFJUFPZ2fgv2laRPiMBzMIp6hSmY/s1600/colori_shock.jpg" /></a></div><br />
ma questi colori sono pesanti, difficili da combinare, ed assolutamente stonati. La prima regola da ricordare è tutte le combinazioni di colori più estreme devono sempre essere evitate!<br />
<br />
Molto meglio utilizzare qualche combinazione più leggera, come ad esempio questa con codice #74A697, #FC8626 e #15766F:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPAbs_DxwS-2r0wKkx3y0XaFY8T1gDe2lPLk7lTTmPuhGxakIfecymuoA7yKVWpTxAyw8sHcfFp6-Mcjs8m7vnLhe4RkGQ-hwL0Eb-OBOU2ZQkUHxF7pGlhYV0Sx3wsOxYutJKq5Yj8QE/s1600/colori_leggeri.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPAbs_DxwS-2r0wKkx3y0XaFY8T1gDe2lPLk7lTTmPuhGxakIfecymuoA7yKVWpTxAyw8sHcfFp6-Mcjs8m7vnLhe4RkGQ-hwL0Eb-OBOU2ZQkUHxF7pGlhYV0Sx3wsOxYutJKq5Yj8QE/s1600/colori_leggeri.jpg" /></a></div><br />
Questi colori stancano di meno e si combinano più facilmente. Ma come scegliere una buona palette di colori?<br />
<br />
Un grafico probabilmente non ha nemmeno bisogno di porsi questa domanda, ma un trucco che può usare anche un non grafico consiste nello scegliere una foto colorata, ed estrarre da essa una combinazione di colori che ci piace:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgH7GbgTEQfFPJ4dSV9OGneFPkWXFkgT2cYnXCamy4iHMbew5eD7S2H2Zw547YNwd5xx_EIjHG1GkGNbS46BjFPNl9s9pCOmsUdK3YmmKnErDu5yINobsow5GFN85kz82OW2g1LEe7dods/s1600/london_big_ben_phone_box1-224x300.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgH7GbgTEQfFPJ4dSV9OGneFPkWXFkgT2cYnXCamy4iHMbew5eD7S2H2Zw547YNwd5xx_EIjHG1GkGNbS46BjFPNl9s9pCOmsUdK3YmmKnErDu5yINobsow5GFN85kz82OW2g1LEe7dods/s1600/london_big_ben_phone_box1-224x300.jpg" /></a></div><br />
prendiamo un po' della cabina telefonica... ed un altro po' del taxi giallo... ecco qui i nostri amici #e02a2f, #f6d06d e #fbab20:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikkDatmiczJEky-ufUffCYEbCpLqd3oRdFofKY2WL_NMYMpN8ccc2ML4DxObWc8oEl8Q54KI3KIFiEGbhDHY8Jot6GVvZriD1nB5cHk-3B8Mb5ZNxVILxurk2Ki7Lvmh9OA4jDp_CBBKM/s1600/colori_londra.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikkDatmiczJEky-ufUffCYEbCpLqd3oRdFofKY2WL_NMYMpN8ccc2ML4DxObWc8oEl8Q54KI3KIFiEGbhDHY8Jot6GVvZriD1nB5cHk-3B8Mb5ZNxVILxurk2Ki7Lvmh9OA4jDp_CBBKM/s1600/colori_londra.jpg" /></a></div><br />
che possono essere combinati in questo modo:<br />
<br />
<table><thead>
<tr style="background: #e02a2f; color: black;"> <th>Data</th> <th>Euribor 1 mese</th> <th>Euribor 2 mesi</th> <th>Euribor 3 mesi</th> <th>Euribor 6 mesi</th> </tr>
</thead> <tbody>
<tr style="background: #f6d06d;"> <td><strong>18 ottobre 2010</strong></td> <td>0,78%</td><td>1,00%</td><td>1,22%</td><td>1,49%</td> </tr>
<tr style="background: #fbab20;"> <td><strong>19 ottobre 2010</strong></td> <td>0,79%</td><td>1,01%</td><td>1,23%</td><td>1,50%</td> </tr>
<tr style="background: #f6d06d;"> <td><strong>20 ottobre 2010</strong></td> <td>0,81%</td><td>1,02%</td><td>1,24%</td><td>1,51%</td> </tr>
<tr style="background: #fbab20;"> <td><strong>21 ottobre 2010</strong></td> <td>0,82%</td><td>1,03%</td><td>1,25%</td><td>1,51%</td> </tr>
<tr style="background: #f6d06d;"> <td><strong>22 ottobre 2010</strong></td> <td>0,82%</td><td>1,03%</td><td>1,25%</td><td>1,52%</td> </tr>
</tbody> </table><br />
Naturalmente è solo un esempio, ma come punto di partenza va sempre bene.<br />
Poi magari... un giorno lontano... sistemerò anche i colori di questo blog!Federicohttp://www.blogger.com/profile/12664789548240220803noreply@blogger.com1tag:blogger.com,1999:blog-717163338714948356.post-44471611862553131992010-10-15T15:28:00.000+02:002010-10-15T15:28:49.604+02:00Negare Group Policy ad un utente o gruppoApplicare una policy di dominio ad un numero ristretto di utenti è molto semplice: nella sezione <i>Security Filtering</i> del tab <i>Scope</i> si seleziona l'elenco dei gruppi a cui tale policy va applicata:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZVqbk5GPnH-Dw5AZ8ho9i-fkM0fntn9QjdwXbAnDHi79nEwudYANs1ME8SHMSRW_ExQjY46RtmkcBGsVtFQIcFWgCCbwCNMyERp5bwwoy7_4DHCivEhnwKBEtX1UXAgOTeKReoYCcGcg/s1600/Cattura.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="315" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZVqbk5GPnH-Dw5AZ8ho9i-fkM0fntn9QjdwXbAnDHi79nEwudYANs1ME8SHMSRW_ExQjY46RtmkcBGsVtFQIcFWgCCbwCNMyERp5bwwoy7_4DHCivEhnwKBEtX1UXAgOTeKReoYCcGcg/s320/Cattura.jpg" width="320" /></a></div><br />
ma per applicare una policy a tutti tranne ad un singolo utente? Gestire il tutto con i gruppi è possibile, ma spesso complicato. Bisogna quindi ricorrere ad un barbatrucco!<br />
<br />
Ci spostiamo nel tab Delegation, aggiungiamo l'utente (od il gruppo) da escludere, e nelle proprietà avanzate togliamo i permessi di lettura della policy:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdT1bD7faZLqWSNP1eVJ8ooOWG0DbJpdmXvOgl50MqlT_YokIGOc5Tu3dpGn0s3-YmYk0sU5-MWI9SjqLp3wkaTjKjLiLaL7AzAEJB8lzrKfgmXd3SXUi7MwlxvDV-CYwUAOcMhucovj4/s1600/Nega.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdT1bD7faZLqWSNP1eVJ8ooOWG0DbJpdmXvOgl50MqlT_YokIGOc5Tu3dpGn0s3-YmYk0sU5-MWI9SjqLp3wkaTjKjLiLaL7AzAEJB8lzrKfgmXd3SXUi7MwlxvDV-CYwUAOcMhucovj4/s320/Nega.jpg" width="314" /></a></div><br />
See you soon!Federicohttp://www.blogger.com/profile/12664789548240220803noreply@blogger.com0