Archivi categoria: guide

Infiltrazioni di acqua nella Rover 75

Fino ad ora ho sperimentato due tipi di infiltrazioni di acqua nella mia Rover 75. Una di queste (si suppone) sta causando la mancanza di alimentazione alle pompe del carburante (sia quella anteriore che quella interna al serbatoio), per cui nel 99% delle volte girando la chiave nel cruscotto, comunque non giunge alcuna differenza di potenziale ai motorini e la macchina non è in grado di avviarsi; questa infiltrazione è dovuta all’accumulo di acqua in una vaschetta appena aldisopra della centralina e dei fusibili, dove un tubo di scarico di gomma dovrebbe prevenire la cosa, ma non ci riesce se vi capita di vivere in un qualche posto dove foglie e semi cadono frequentemente dagli alberi sulla vostra macchina.

rover 75 sotto il cofano
L'area sotto il cofano dove avviene il misfatto, la vasca d'acqua è subito vicino alla cerniera del cofano lato passeggero.
tubo di scarico di gomma
Questa vaschetta appare sporca, ma in realtà è stata abbondantemente pulita, figuratevi cosa poteva esserci prima. Inutile a dirsi, si era riempita d'acqua, che poi è debordata all'interno della macchina, cadendo sopra la centralina e la scatola dei fusibili, per finire sul tappetino lato passeggero.
tubo di scarico
Mio padre sostiene che lo scopo di questa forma sia quella di impedire che i residui solidi finiscano nel vano sottostante lo scarico, permettendo il passaggio solo dell'acqua. Io invece penso che sia semplicemente una progettazione stupida. La prima cosa solida che finisce dentro il tubo tappa l'uscita... nel mio caso si era riempito tutto di semi di pino quasi fino all'orlo.
tubo di scarico di gomma tagliato
Problema risolto, ho tagliato via la punta a becco di flauto ed ora il passaggio è aperto.

Ho scoperto la seconda infiltrazione per puro caso. Come dicevo la pompa del gasolio anteriore era ferma, e sono andato a controllare anche quella posteriore, quindi ho rimosso il sedile posteriore… e sorpresa, ho trovato una piscinetta d’acqua in un punto affossato della base metallica subito dietro al coperchio dell’alloggiamento della pompa interna al serbatoio. Ho seguito il passaggio dell’acqua sin dentro il bagagliaio, ma lì le tracce diventavano scarse, siccome era quasi tutto asciutto, anche se ho notato per caso una macchia sulla parete laterale.

rover 75 bagagliaio
Ho asciugato l'acqua stagnante all'angolo del bagagliaio con lo spazio della ruota, si può notare chiaramente l'area bagnata tutta attorno.
rover 75 infiltrazione bagagliaio
Questa macchia verticale ha tradito l'infiltrazione in questa zona del bagagliaio.
rover 75 decorazione argento
La freccia rossa punta alla zona dove l'acqua si insinua sotto la decorazione cromata e passa attraverso il buco della vite che la fissa in posizione.
guarnizione difettosa
Questo è il colpevole, la guarnizione rotonda premuta contro il metallo lasciava comunque passare l'acqua dall'esterno.
rover 75 doccia bagagliaio
Ho rimontato tutto per testare la tenuta della guarnizione, quindi ho innaffiato abbondantemente la zona sospettata di infiltrazione (notare l'arcobaleno di cortesia)
infiltrazione d'acqua nel bagagliaio
Eccovelo, un rivoletto di acqua scende direttamente dalla guarnizione.
acqua nel bagagliaio
Piccola piscina formatasi nel bagagliaio nello stesso punto dove avevo già asciugato l'acqua presente (che si era accumulata in quantità molto superiori). Non appena si frena o si marcia in discesa, l'acqua cola in avanti e va ad accumularsi proprio sotto il sedile posteriore.

Ho aggiunto generose quantità di silicone in corrispondeza del foro nella carrozzeria dove passa la vite, sia dall’esterno che dall’interno, ed ho rimontato tutto; dovrebbe essere sufficientemente isolato per ora. Per sicurezza, ho ripetuto l’isolamento con silicone su tutte le altre guarnizioni simili (ce ne sono due per lato).

Il problema della mancata alimentazione alle pompe del gasolio permane, questa macchina continua a prendermi in giro; non appena sembra che la cosa sia risolta, basta riprovare a girare la chiave nel quadro, e nuovamente le pompe sono morte. A questo punto, sospetto un cavo di alimentazione ossidato, o qualcosa del genere.

Il driver di rete bridged Virtualbox rallenta la velocità della LAN

Quando sono passato dal WiFi ad una connessione fisica con cablaggio CAT5E dal router nell’altra stanza a questo PC, sono saltato da velocità di trasferimento dei file di massimo 2-3MB/s (ma quasi sempre 1MB/s, spesso meno) a 11-12MB/s.

Ultimamente ho notato come la velocità per scaricare alcuni fansub dal server domestico era scesa a 5-6MB/s, esattamente la metà di quella a cui ero abituato; dall’icona di rete nell’area di notifiche di Windows 7 ho notato che era presente un secondo adattatore di rete, che ho fatto risalire alla scheda virtuale di rete in modalità bridged installata da Virtualbox. Siccome l’avevo recentemente installato per testare una cosa di cui ora non ho più bisogno, ho disinstallato Virtualbox, e non appena il driver dell’adattatore di rete virtuale è stato rimosso, la velocità tornata a 11-12MB/s.

Questo dovrebbe essere un comportamento normale?

Query MySQL con ORDER BY,GROUP BY per ordinare e rimuovere righe doppie

Apparentemente questo è un dilemma piuttosto discusso; molti “niubbi” di MySQL (me compreso) vogliono usare un SELECT su righe di una tabella, dove sanno che il campo ‘a’ ha valori ripetuti più volte, ma vogliono estrarre una sola riga per ogni valore, al tempo stesso facendo in modo tale che la riga estratta, tra tutte quelle disponibili, sia quella che ha il campo ‘b’ col valore più basso, o alto, o lungo, o corto tra tutte le possibili… bene, il primo tentativo che fanno questi niubbi è una query come questa:

SELECT a, b, c FROM table WHERE <conditions> ORDER BY b DESC GROUP BY a

e ottenendo un errore si rendono conto che non è possibile, perché la sintassi MySQL vuole che la clausola GROUP BY venga prima di quella ORDER BY, come nel seguente esempio:

SELECT a, b, c FROM table WHERE <conditions> GROUP BY a ORDER BY b DESC

In questo caso però, le righe prima vengono sfoltite rimuovendo i doppioni del campo ‘a’ (con un criterio che non possiamo scegliere noi), e solo dopo vengono ordinate per ‘b’, e questo non ci serve.

Quindi come si fa per ordinare prima le righe così come ci servono, e poi rimuovere quelle di troppo?

Per essere brevi, ecco come:

SELECT t.a, t.b, t.c
  FROM table t
  JOIN (SELECT MIN(b) as b
    FROM table
    GROUP BY a) t2 ON t2.b = t.b
  WHERE <condizioni>
  GROUP BY a
  ORDER BY NULL

Quello che fa questo “scheletro di query”, è ordinare le righe per il campo ‘b’ (in senso crescente, cioè ASC, siccome è stata usata la  funzione MIN(), altrimenti potreste usare MAX() per un ordinamento decrescente, e/o altre funzioni in base al tipo di ordinamento che vi serve) all’interno dell’operatore JOIN, e quindi raggruppa per valori unici del campo ‘a’ le righe nella query esterna. L’operatore ORDER BY NULL serve a evitare che l’interprete MySQL perda tempo a ordinare le righe risultanti, siccome un ordinamento viene già fatto con l’operatore GROUP BY. La query è efficace, ma poco efficiente, siccome risulta molto lenta.

All’inizio pensavo che mi sarei dovuto accontentare, tuttavia non soddisfatto, siccome imparando PHP e MySQL sono col tempo diventato ossessionato con l’ottimizzazione per le prestazioni, ho pensato di provare un approccio alternativo, cioè richiedere via SQL le righe “grezze”, e poi rielaborarle successivamente in PHP.

Esaminiamo questo approccio:

$results=doquery("
  SELECT a, b, c
    FROM table
    WHERE <condizioni>
  ");
$datagrid=array();
while ($slot=mysql_fetch_array($results)) $datagrid[]=$slot;
sort($datagrid);
$compare="";
foreach ($datagrid as $k=>$row)
  if ($row[0]==$compare)
    unset($datagrid[$k]);
  else
    $compare=$row[0];

Alla fine di questas routine, $datagrid contiene tutti i dati di cui avete bisogno, e solo quelli; spieghiamo:

  • la query SQL restituisce le righe non processate che corrispondono alle condizioni di WHERE, quindi con i doppioni del campo ‘a’, e senza nessun ordinamento particolare
  • dopo aver inserito i campi delle righe in un array multidimensionale, la funzione PHP sort() si occupa dell’ordinamento dell’array in base agli elementi dei sotto-array, prima per subarray[0], poi per subarray[1] e così via (apriamo una parentesi su questo discorso: se cercate su internet “ordinamento di un array multimensionale in PHP” -meglio se in inglese-, troverete ogni tipo di script artigianale, come se la sola funzoine sort() funzionasse solo sugli array monodimensionali; beh, io ho PHP5 sul mio hosting, ed ho provato a passare il suddetto array multimendionale a sort(), sorpresa delle sorprese l’ha messo in ordine esattamente come serviva a me; se però per voi non dovesse funzionare, recatevi sulla pagina di php.net dedicata alla funzione sort, e nella sezione dei commenti troverete molti esempi già compilati di script “casalinghi”, anche se non saranno mai veloci come sort() che è una funzione propria di PHP)
  • la stringa $compare è inizializzata, e usata nel successivo ciclo foreach per fare un unset() di tutti i subarray dove l’elemento [0] (il nostro campo ‘a’) è uguale a quello del precedente subarray, quindi rimuovendo i duplicati oltre la prima riga

Dopo di ciò potete passare l’array risultate ad un’altra routine per processare i dati così come vi servono.

Per portare la performance ancora oltre, nel caso abbiate bisogno di eseguire una procedura semplice sui dati ottenuti, potete modificare il ciclo foreach dell’esempio come segue:

foreach ($datagrid as $row)
  if ($row[0]!=$compare) {
    $compare=$row[0];
    <routine di elaborazione in questo spazio>
  }

Chiarendo, questo ciclo foreach non si occupa di eliminare i subarray duplicati, ma si limita ad eseguire la routine di elaborazione solo sulla prima istanza di un subarray, ignorando le copie successive; in questo modo, tagliate diverse volte sui tempi di esecuzione:

  1. risparmiate il tempo di un secondo foreach per scorrere l’array ed eseguire le operazioni di elaborazione, siccome queste vengono lanciate direttamente dal primo foreach
  2. evitate di lanciare la funzione unset() tante volte quanti sono i doppioni
  3. risparmiate i cicli di CPU e la memoria necessari a definire un secondo array per contenere i dati sfoltiti, siccome state lavorando direttamente sul primo array costruito sui risultati della query
  4. semplificate il foreach perché non richiedete più un elemento associativo ($k=>$row) ma solo il valore dell’elemento

Con i miei benchmark (su un set di dati MOLTO ristretto, lo ammetto), ho misurato un incredibile aumento di prestazioni di cento volte (già, 100 volte più veloce) per l’ordinamento/sfoltimento in PHP, paragonato al “doppio GROUP BY” in MySQL (0.08 secondi per MySQL/PHP, contro 8 secondi per la query complessa, su 100 iterazioni). I vostri risultati potrebbero essere diversi, ma partendo da un vantaggio di cento volte, c’è molto spazio di manovra.

Ricerca invertita in MySQL: controlla se le parole chiave nel campo corrispondono ad un testo

Di solito, “cercare in un database” significa cercare quelle righe che contengono un “documento” in un campo, che corrisponde a delle parole chiave (di solito usando la funzione MATCH AGAINST); mettiamo invece che vogliate fare il contrario, cioè avete una tabella con delle righe che contengono un campo in cui avete memorizzato delle parole chiave, e volete selezionare solo quelle righe in cui le parole chiave corrispondono ad un testo o un particolare documento. Questa è quella che io chiamo una ricerca invertita.

Uno scenario reale: avete un sito di offerte di lavoro, ed i candidati cercano annunci di loro gradimento, ma non ne trovano nessuno, oppure ce ne sono troppo pochi e non interessanti. O continuano a collegarsi al sito ripetendo la ricerca periodicamente (ad esempio con le parole chiave “veterinar* gatt*“, perché vogliono prendersi cura degli animali, e hanno un debole per i gatti in praticolare), o si iscrivono al feed RSS di quella ricerca (se ne avete uno)… oppure “salvano” la ricerca e aspettano che sia il sito ad inviare loro una mail non appena compare un nuovo annuncio pertinente, ed è qui che torna utile questo articolo.

Salvare le parole chiave per ogni utente in una tabella MySQL è semplice, ma quanto è semplice verificare se un annuncio appena inserito corrisponde alle parole chiave? In PHP, costruireste un array delle parole chiave, e per ogni elemento richiamereste strpos() per verificare che siano tutte contenute nel testo.

In MySQL la funzione INSTR() è l’equivalente di strpos() in PHP, ma non potete salvare degli array in un campo (intendo array veri e propri, non serializzati), e d’altra parte salvare tante righe quante sono le parole chiave scelte da ogni utente è sconveniente, siccome la normalizzazione non è necessaria: un “insieme di parole chiave” è quasi sempre unico per ogni utente che si iscrive ad una ricerca, per cui ha senso salvarlo in un campo testuale nella forma di “parola1,parola2,parola3,…“; anche qui, in PHP useremmo explode(“,”,$parole) per ottenere un array, ma in MySQL non esiste nessuna funzione simile, per cui è necessario crearne una.

Idealmente, avreste bisogno di una funzione a cui passare il testo/documento in vostro possesso (la somma di titolo e corpo dell’offerta di lavoro, in questo caso), la stringa nella forma “parola1,…,parolaN“, e un parametro per indicare che il delimitatore (“colla” nel caso di implode/explode) è una virgola, quindi:

funzione(document, keywords, delimiter)

Questa funzione dovrebbe restituire un valore intero positivo se tutte le parole chiave sono presenti nel testo, oppure 0 in caso contrario.

La funzione che ho messo assieme incollando informazioni prese un po’ dovunque è:

DELIMITER ;;

DROP FUNCTION IF EXISTS `matchkwdarray`;;
CREATE FUNCTION `matchkwdarray`(`str` text, `arr` text, `delimit` tinytext) RETURNS char(1) CHARSET utf8
 DETERMINISTIC
BEGIN
 DECLARE i INT DEFAULT 1;
 DECLARE matches INT DEFAULT 1;
 DECLARE token TINYTEXT;
 label:WHILE(matches>0) DO
 SET token=replace(substring(substring_index(arr, delimit, i), length(substring_index(arr, delimit, i - 1)) + 1), delimit, '');
 IF token='' THEN LEAVE label; END IF;

 SET matches=INSTR(str, token);
 SET i=i+1;
 END WHILE;
 RETURN matches;
END;;

DELIMITER ;

Per aggiungere questa funzione al vostro database MySQL, potete collegarvi sia tramite CLI, sia usando una interfaccia web al database, come dovranno fare tutti gli utenti su un hosting condiviso, non avendo accesso alla linea di comando; phpMyAdmin, rigonfio com’è, non supporta comunque routine e funzioni, per cui avete bisogno di un altro DB manager, ed io ho scelto Adminer che svolge il suo lavoro egregiamente, più rapido di phpMyAdmin, e tutto in un piccolissimo singolo file PHP di circa 150kb.

Un esempio d’uso della funzione:

SELECT matchkwdarray('questo è solo un piccolo test molto semplice', 'solo,test', ',')
Restituisce: 2

SELECT matchkwdarray('questo è solo un piccolo test molto semplice', 'casa,albero', ',')
Restituisce: 0

SELECT matchkwdarray('questo è solo un piccolo test molto semplice', 'solo,test,semplice,albero', ',')
Restituisce: 0

Questa funzione è efficiente: appena verifica che una parola chiave non è contenuta nel testo interrompe la procedura e restituisce subito 0; ovviamente, se non cercate una precisione del 100% ma vi accontentate di una corrispondenza inferiore, potete modificarla per verificare comunque tutte le parole chiave, e restituire una percentuale di corrispondenza; potete anche rimuovere l’ultimo carattere dalle singole parole in modo tale che siano ammesse più varianti delle stesse.

Una query MySQL SELECT con numerose condizioni WHERE è più veloce

Per un certo motivo volevo aggiungere più condizioni WHERE ridondanti all’interno di una query MySQL SELECT, ma temevo di rallentare l’esecuzione della stessa.

In breve, sto lavorando a questo sito di annunci, dove per ogni oggetto c’è una tabella contenente tra le altre le righe comune_id, provincia_id e regione_id. Conoscendo il valore di comune_id, è possibile usare la query:

SELECT * FROM oggetti WHERE comune_id='12'

invece di:

SELECT * FROM oggetti WHERE comune_id='12' AND provincia_id='34' AND regione_id='56'

siccome i risultati sono gli stessi… ma conviene?

Ho preparato un veloce test:

include "db.inc.php";
$creationstart=strtok(microtime()," ")+strtok(" ");
for($i=0;$i<=999;$i++)
 $test=doquery("SELECT * FROM oggetti WHERE comune_id='58003'");
$creationend=strtok(microtime()," ")+strtok(" ");
$creationtime=number_format($creationend-$creationstart,4);
echo "solo comune: $creationtime<br />";

$creationstart=strtok(microtime()," ")+strtok(" ");
for($i=0;$i<=999;$i++)
 $test=doquery("SELECT * FROM oggetti WHERE comune_id='58003' AND provincia_id='58' AND regione_id='12'");
$creationend=strtok(microtime()," ")+strtok(" ");
$creationtime=number_format($creationend-$creationstart,4);
echo "tutti i parametri: $creationtime<br />";

A sorpresa, ci è voluto un tempo variabile dai 2.4s ai 4.5s per eseguire le 1000 iterazioni con “tutti i parametri”, mentre la versione “solo comune” richiedeva circa 0.4s in più. All’inizio ho pensato che si trattasse della cache MySQL in azione, ma invertendo la posizione delle due routine all’interno del codice i risultati sono rimasti gli stessi.

Quindi, anche se vi sembra ridondante, aggiungere più clausole WHERE ... AND ... nelle vostre query accelera l’esecuzione della ricerca.

This article has been Digiproved

Attivare il force feedback del Logitech Driving Force Wheel in windows

Qualche tempo fa ho ottenuto in regalo da Freecycle il Logitech Driving Force (ancora grazie Claudia), un volante per la Playstation 2 che avevo letto essere compatibile anche col PC, infatti usa una normale porta USB; appena collegato è stato riconosciuto da Windows 7 che lo ha configurato come un normale controller per giochi, anche se non ne supportava tutte le funzioni; in Need For Speed: Hot Pursuit la mancanza del force feedback, e la presenza della zona morta al centro rendevano quasi noioso il gioco; finalmente mi è venuta l’idea, dopo averne letto su un altro sito web, di scaricare il “Logitech Profiler”, una utility di configurazione per i controller ludici logitech; purtroppo sul sito ufficiale la pagina del Driving Force non è presente, ce ne sono solo per le versioni aggiornate (Driving Force qualchecosa), ma ho comunque prelevato la versione per Windows 7 64bit (ci sono versioni anche per Windows XP e Vista) dalla pagina di un altro volante, il G27, trattandosi da quanto ho capito sempre dello stesso file per tutti i controller. Ebbene, quando dopo l’installazione ho lanciato il programma, si è finalmente acceso il led del force feedback sul volante dopo che sono stati installati dei driver aggiornati, ed ho potuto usare il Driving Force a pieno, e hot pursuit si è trasformato in un gioco divertentissimo!

Rumori e vibrazioni di airbag passeggero e cruscotto Rover 75

I rumori di vibrazioni nel cruscotto mentre guido mi fanno impazzire, né più né meno.

Ho iniziato a guidare la mia Rover 75 da meno di un anno, e per i primi tempi la soddisfazione di avere un’auto classica ed elegante mi ha aiutato a soprassedere sui numerosi rumoretti che si sentivano dovunque durante la guida (soprattutto nella zona dell’airbag del passeggero), ad ogni modo sono arrivato ad un punto in cui mi saltavano tanto i nervi che ogni tanto davo forti schiaffi dovunque sul cruscotto tentando disperatamente di far cessare le vibrazioni, ma anche, lo ammetto, per sfogare la rabbia che mi provocava la cosa.

Devo ringraziare MikeM dei forum MG-Rover per le istruzioni scritte che mi hanno aiutato nella procedura di risoluzione del problema, e ispirato a creare questa guida anti-vibrazioni per immagini.

rover 75 glovebox removal screws
Questo portaoggetti è stato già smontato, comunque facciamo finta che non lo sia: bisogna rimuovere le sette viti di tipo torx evidenziate in rosso, le tre inferiori si trovano sotto il tappetino sintetico che deve essere scollato a forza dal fondo. Per rendere più comodo l'accesso alle viti vanno rilasciati i braccetti di plastica evidenziati in verde, in modo da poter aprire completamente lo sportello.
rover 75 glovebox arm hinge
Vista ravvicinata dei "dentini" che vanno spinti da entrambi i lati per far aprire completamente lo sportello.
rover 75 glovebox socket
Questo è il buco vuoto dopo aver rimosso il vano portaoggetti; evidenziato in verde è visibile lo spinotto di alimentazione della luce che va staccato prima di tirare completamente fuori il cassetto; la parte che vi interessa si trova dietro la parete superiore del buco, bisogna accedervi da sotto nella direzione della freccia rossa.
rover 75 bcu near glovebox
Questo è il guastafeste: la BCU (body control unit, anche se sulla scatola è scritto "Control Unit Body"); in verde ho evidenziato il bullone che fissa la scatola al pannello metallico visibile subito sotto; in pratica, la punta del bullone, a circa 2000 giri per minuto del motore vibra sbattendo contro la struttura metallica tubolare nella zona indicata dalla freccia rossa.
packaging plastic sheet
Serve qualcosa da interporre tra le due estremità metalliche, dovrebbe andar bene qualunque cosa, ma io ho usato questo foglio di plastica da imballaggi, che saggiamente avevo tenuto da parte per eventuali usi futuri.
rover 75 bcu rattle isolation
Ho preso circa 10cm di striscia di plastica, l'ho piegata in due, ho tirato verso il basso il pannello metallico liberando un certo spazio tra bullone e tubo metallico, ed ho fatto scorrere tra le due parti il materiale isolante; una volta rilasciata la scatola si è poggiata sullo strato interposto; da quel momento non ho sentito più alcuna vibrazione da sotto l'airbag passeggero.
rover 75 dash under panel
Giacché c'ero, ho deciso di risolvere le vibrazioni anche sotto il cruscotto nella zona del tachimetro; in rosso sono evidenziate le due viti da rimuovere, in verde indico le zone da cui sembravano originare i rumori.
rover 75 isolated under dash panel
Ho usato buona parte del materiale da imballaggio rimanente per formare una specie di cuscino attorno ai tre gancetti di ritenzione indicati dalle frecce verdi; alle due estremità ho fermato il tutto con un po' di nastro isolante; basta rimettere tutto in posizione per non sentire più nulla neppure in quella zona.

  This article has been Digiproved

Estrarre una stringa tra due chiavi in un testo con uno script shell bash

L’altro giorno, da totale incompetente, stavo scrivendo uno script in bash per processare una pagina HTML, cercare un URL al suo interno, e scaricare il contenuto di quell’URL, in maniera ricorsiva per una serie di pagine; l’avevo già compilato in linguaggio AutoHotKey, tuttavia il mio PC con Windows non è sempre acceso, mentre il mio server domestico linux sì, quindi ho deciso che sarebbe stato opportuno imparare un po’ di linguaggio bash per rendere la procedura più efficiente.

In questo script devo estrarre un segmento di stringa contenuto tra due parole chiavi note, o “token” in inglese, per ottenere l’URL di cui ho bisogno; in AutoHotKey salvavo la posizione di entrambe le parole chiavi, quindi operavo una istruzione di substring tra questi due offset, e stavo cercando di far lo stesso in bash, siccome stavo pedissequamente traducendo lo script, piuttosto semplice, da un linguaggio all’altro.

Con mia sorpresa, questa non è una cosa che si può fare in bash, siccome l’unica operazione di ricerca di una stringa all’interno di un’altra stringa in realtà cerca il primo carattere della parola chiave; quindi, per esempio, se si cerca “mio” all’interno di “La melliflua pelliccia del mio gatto è marrone”, si ottiene 3, e non 27 come ci si aspetterebbe, perché come dicevo expr index "$string" $substring restituisce solo la posizione del primo carattere di substring, quindi la prima posizione di “m” nella stringa.

In realtà, a me non serviva conoscere la posizione delle parole chiavi, purché riuscissi ad estrarre la stringa tra loro due, quindi ogni operazione che servisse a questo scopo andava bene; purtroppo me ne sono reso conto solo dopo aver buttato un’ora di tempo a cercare la soluzione, quindi pubblico i miei risultati per far risparmiare tempo a chi dovesse finire su questa pagina.

Fondamentalmente consiste nel tagliare dalla stringa tutto quello che precede la prima parola chiave (inclusa la prima chiave), e quindi tagliare dalla stringa così ottenuta tutto quello che segue la seconda patola chiave (seconda chiave inclusa):

#dichiarazione delle variabili
testo="lungotestodacontrollare"
primachiave="qualcosa"
secondachiave="qualcosaltro"

#elaborazione vera e propria
stringacentrale=${testo#*$primachiave}
stringacentrale=${stringacentrale%%$secondachiave*}

Questo restituisce $stringacentrale come la stringa contenuta tra la prima occorrenza di $primachiave (simbolo # singolo), e la prima occorrenza di $secondachiave (doppio simbolo %, che indica l’occorrenza più distante dalla fine della stringa).

  This article has been Digiproved

La calibrazione delle batterie agli ioni di litio, punti di vista

Sono un frequentatore abituale dei forum di XDA da quando ho felicemente iniziato ad usare il mio HTC HD2 Leo (in realtà, l’ho appena portato in un centro di raccolta per farlo riparare in garanzia… touchscreen morto, sigh). Da allora, ho iniziato a leggere di “strane” pratiche riguardanti le batterie Li-Ion e l’uso che bisognerebbe farne per prolungarne la durata. Sin da prima di tutto ciò, quando ancora usavo pocketpc più anziani (tutti iPaq) avevo l’abitudine di usare la batteria fino a circa il 30% per poi ricaricarla, e evitavo per quanto possibile di ricaricarla prima che “fosse ora”; dall’altra parte, si trovano dovunque guide che sostengono che le batterie LiIon migliorano tanto di più quanto più frequentemente vengono caricate, e peggiorano con cariche infrequenti e più “piene” (sicuro, infatti tutti i possessori di portatili sono in grado di confermare come le batterie migliorano col tempo usandoli sempre attaccati all’alimentatore… come no).

Quello che segue è un estratto di una guida tratta da un sito a caso (in realtà i passaggi sono piuttosto costanti dovunque leggete, anche sui thread di XDA):

  1. Consumate la batteria fino a quando il telefono non si spegne da solo
  2. Riaccendetelo e aspettate che si spenga da solo di nuovo
  3. Rimuovete la batteria per 10 secondi
  4. Reinserite la batteria ma lasciate il telefono spento
  5. Ricaricate il telefono fino a quando non arriva al massimo, e poi ancora per un’altra ora
  6. **Solo per chi ha eseguito il root** Da un terminale, inviate il comando su, e successivamente “rm /data/system/batterystats.bin”
  7. Consumate la batteria fino a quando non si spegne il telefono
  8. Accendete il telefono e caricatelo per almeno 8 ore
  9. Scollegato il cavo dal telefono, spegnetelo, e poi ricaricatelo per un’altra ora
  10. Scollegate il telefono, accendetelo, aspettate due minuti
  11. Spegnete nuovamente il telefono, e caricatelo per un’altra ora
  12. Riprendere l’uso normale

Ora, l’ultima delle mie intenzioni è criticare il lavoro svolto da queste persone (davvero), tuttavia, personalmente (molto personalmente), penso che in qualunque punto di quell’elenco si protebbe inserire la seguente istruzione:

  • Vestitevi con un kilt a strisce bianche e verdognole, e, mentre indossate SOLO quello, durante una notte di luna piena, saltate attorno al telefono in carica urlando “LIIIITIIIOOOOOOO”

e si intonerebbe perfettamente con il tenore generale della lista.

Per precisare inoltre, quando il telefono vi dice che è completamente carico, significa che ha smesso di inviare corrente elettrica alla batteria; in altre parole, una volta che la lucetta è diventata verde, potete lasciarlo attaccato al caricabatterie un giorno intero, dal punto di vista pratico non farà alcuna differenza.

Io so di essere un caso estremo, tuttavia posso in tutta sincerità portare la mia esperienza: possiedo la batteria standard originale, ed ho comprato da venditori cinesi su ebay altri 3 cloni (1230mAh, perfettamente identiche all’originale se non fosse per un codice a barre un po’ più piccolo), assieme ad un caricabatterie da tavolo.

Uso il telefono fino a quando non scende circa al 20% di carica (ultimamente arrivo al 10%, o anche al 5% se sto facendo qualcosa che non mi va di interrompere, come guardare telefilm), quindi tiro fuori la batteria, e inserisco la successiva, carica (sono numerate da 1 a 4). La batteria esaurita finisce direttamente nel caricatore da tavolo (o in tasca, fino a quando non torno a casa).

Uso raramente il caricabatterie da accendisigari in auto, ma regolarmente uso il telefono in macchina come lettore MP3 o navigatore.

Sono arrivato, con un uso leggero, fino a 4 giorni di durata. Si, ho scritto bene, QUATTRO giorni di vita della batteria, ovviamente senza ricariche intermedie; avrò usato poco il telefono, ma si tratta pur sempre di 96 ore, e non succedeva neppure con i Nokia di 10 anni fa che la batteria durasse così tanto. Mi volete dire che con quei trucchetti la durata sarebbe ancora maggiore?

  This article has been Digiproved

La velocità delle funzioni PHP di ricerca su stringhe dipende dall'”ago”

Stavo giocando con alcuni test di prestazioni su dei templates nel mio post precedente, e sono incappato in una scoperta interessante riguardante il modo in cui funziona strpos, e conseguentemente tutte le altre funzioni di tipo “cerca (e sostituisci)” come str_replace, strrpos, stripos, str_ireplace, substr_replace, persino preg_match and preg_replace (ho testato solo str_replace e preg_match, ma suppongo ci siano gli stessi risultati per tutte le altre).

  1. Userò in questo articolo la convenzione di php.net, e chiamerò “ago” la stringa che state cercando, e “pagliaio” la stringa all’interno della quale effettuate la ricerca
  2. Conoscere questi risultati è utile in pratica solo se potete scegliere quali aghi inserire nel pagliaio, per poterli poi cercare successivamente, cioè se state costruendo un template
  3. Ho già cercato per controllare se questa “trovata” era già stata documentata da qualcun altro, ma così non sembra, quindi se mi fossi perso qualcosa evitate di aggredirmi

Mettiamo che stiate creando lo schema per un template, dove inserirete dei tag che dovranno essere sostituiti dai contenuti generati dinamicamente dal vostro sito. Potete chiamarli come volete purché siano stringhe uniche all’interno del modello, quindi per esempio %tag% o {tag} o <!–tag–> o ~tag~ (o come vi pare). Magari pensate che scegliere quale tipo di carattere di delimitazione usare per il nome del tag dipenda solo dai vostri gusti personali, e lo pensavo pure io prima di scoprire questa cosa per puro caso, comunque vi dico subito che se il template consiste in codice HTML ben formato, allora usare per esempio ~tag~ sarà molto più veloce che usare <!–tag–>.

Il principio generale è che cercare un ago che inizia con un carattere “raro” è molto più veloce che cercare un ago che inizia con un carattere molto comune all’interno del pagliaio.

Per esempio, se il vostro pagliaio è un estratto di un ebook, cercare “%ciao” (se presente) sarà molto più rapido che cercare “ciao”.  La giustificazione di questo? Evidentemente la funzione in C che cerca la stringa, inizia col cercare il primo carattere, e una volta trovato vede se quello successivo corrisponde, e così via; quindi cercando “ciao” la funzione incapperà in tutte le “c” per controllare se sono seguite da una “i”, se sì poi verificherà se c’è una “a”, ma se ad esempio la parola è “ciarpame”, la funzione verificando l’assenza della “o” finale dovrà scartare il lavoro ed il tempo impiegato, e proseguire. Invece il carattere “%” è raro, se non unico, all’interno di un testo “normale”, quindi la funzione dovrà “fermarsi” molte meno volte a controllare prima di trovare una corrispondenza piena.

Mettiamo questa teoria alla prova, ecco il codice:

$creationstart=strtok(microtime()," ")+strtok(" ");
for ($i=0;$i<100000;$i++) $testpos=strpos($test,"malesuarda");
$creationend=strtok(microtime()," ")+strtok(" ");
$creationtime=number_format($creationend-$creationstart,4);
echo "malesuarda $testpos: ".$creationtime."<br />";

$creationstart=strtok(microtime()," ")+strtok(" ");
for ($i=0;$i<100000;$i++) $testpos=strpos($test,"%malesuada");
$creationend=strtok(microtime()," ")+strtok(" ");
$creationtime=number_format($creationend-$creationstart,4);
echo "%malesuada $testpos: ".$creationtime."<br />";

Spieghiamo un po’ di cose: $test è una stringa relativamente lunga, definita precedentemente nel codice (è composta da un testo lorem ipsum con diversi paragrafi, per 13kb totali), all’interno della quale ho scelto una parola a caso, “malesuada“, che viene ripetuta diverse volte, e ho cambiato due occorrenze di questa parola, entrambe verso la fine della stringa, per renderle uniche, una è diventata malesuarda, cioè ho aggiunto una “r”, e l’altra (più avanti nella stringa) invece è stata modificata in %malesuada, quindi alla fine ho caricato lo script PHP; ho aggiunto un echo per $testpos in modo da confermare che le stringhe fossero state realmente trovate da strpos.

Come atteso, ecco i risultati:

malesuarda 10970: 3.5609
%malesuada 11514: 0.7632

Sostituendo strpos con qualunque altra funzione elencata all’inizio dell’articolo otterrete valori simili.

  This article has been Digiproved