Newsgroup: it.comp.java
Titolo: [OT ma ci provo] A proposito di binario

Ciao,
vedendo il post precedente mi e' venuta in mente una situazione che sto
affrontando con i binari.
Attualmente ho questo caso, cerco di affrontarlo in modo molto generico, 
dove data una serie di azioni possono succedere delle reazioni, dopo x reazioni
consecutive il tutto viene validato.
Quindi ho implementato un sistema dove a 1 corrisponde azione e a 0 corrisponde
reazione(diamo per assunto che non possono esserci 2 reazioni consecutive)
111101010
In questo caso le ultime tre azioni hanno avuto conseguente reazione quindi
valido.
Qui il codice che effettua tale controllo(logicamente questo e' "appiattito"
dato che il tutto e' su db etc etc)
// numero di reazioni da controllare
int reazioni_di_controllo = 3;
// valore di controllo per le reazioni
int valore_di_controllo = 0;
// maschera per il bitwise
int maschera_di_controllo = 0;
// mi creo il valore di controllo
for (int i = 0; i < reazioni_di_controllo; i++) { 
        valore_di_controllo += 2 << (i * 2); 
}
// mi creo la maschera per il controllo
maschera_di_controllo = 
        (int) Math.ceil( Math.pow(2, (reazioni_di_controllo * 2) )  - 1);
 
int azioni = 0;
azioni = (azioni << 1) + 1; // azione
azioni = (azioni << 1); // reazione
azioni = (azioni << 1) + 1; // azione
azioni = (azioni << 1); // reazione
azioni = (azioni << 1) + 1; // azione
azioni = (azioni << 1); // reazione
azioni = (azioni << 1); // reazione
azioni = (azioni << 1); // reazione
azioni = (azioni << 1) + 1; // azione
azioni = (azioni << 1) + 1; // azione
azioni = (azioni << 1); // reazione
azioni = (azioni << 1) + 1; // azione
azioni = (azioni << 1); // reazione
azioni = (azioni << 1) + 1; // azione
azioni = (azioni << 1); // reazione
if(valore_di_controllo == (azioni & maschera_di_controllo)) {
        System.out.println("validato");
}
Il tutto funziona correttamente, algoritmo semplice e vistie le quantita' per
ora non ho mai avuto problemi di performace.
Ora pero' devo controllare la variabile temporale, ovvero valutare se una
reazione e' recente oppure no di conseguenza con il sistema sopra descritto
sono a piedi, la sostanza e' quella di dare un peso al tempo definendo
dei "range" e un limite massimo.
Logicamente i dati puntuali li ho ma in tabelle da milioni di record da mettere
in join per risalire alla storia di un record, il sistema della bitstring e'
una aggregazione runtime delle azioni/reazioni(arriva una reazione per un
record, faccio lo shift di 1 se e' valido bene altrimenti sara' per la prossima
volte e poi con una procedura batch vengono aggiornati tutti i dati puntuali
nelle varie tabelle)
Idee per mantenere un sistema di controllo simile e leggero?
Credo di essermi impantanato nel voler continuare a sfruttare in qualche modo il
codice sopra senza pensare ad altre soluzioni, ma magari non la vedo io nel
codice sopra ;)
Mi saro' spiegato? Mah!
Ciao,
crx
-- 
crx
http://www.crx.it

 azioni = (azioni << 1) + 1; // azione
Qui ho "copia incollato" male le righe dato che non possono esserci reazioni
consecutive...volevano essere azioni.
:)
ciao
-- 
crx
http://www.crx.it

Aggiungo qualche elemento postato anche ad un amico che non aveva ben capito il
problema:
Scusate se stresso, non posto piu' domande del genere qui promesso!
****
Uso il sistema binario dove a destra ci sono le azioni piu' recenti e a 
sinistra le meno recenti, poi il binario lo salvo in decimale nel db.
Per il linguaggio questo non ha importanza nel senso...
Il numero di reazioni da contrllare sono 3 quindi le reazioni corrispondono a 
101010 che in decimale e' 42 questo diventa il valore di controllo
La maschera di controllo si crea facendo  (2 potenza (reazioni *2)) - 1 che da 
63 in binario 111111
Poi avveine la storia...
si parte con 0 alla prima azione si fa lo shift
shift + 1 per le azioni e shift normale per reazioni
azioni = 0;
azioni  = (azioni  << 1) + 1  che da 1 in decimale e 1 in binario
poi una reazioni dove shifto solamente
azioni  = (azioni  << 1) che da 2 in decimale e 10 in binario
quindi questo:
azioni = (azioni << 1) + 1; 
azioni = (azioni << 1);
azioni = (azioni << 1) + 1;
azioni = (azioni << 1);
azioni = (azioni << 1) + 1;
azioni = (azioni << 1) + 1;
azioni = (azioni << 1) + 1;
azioni = (azioni << 1) + 1;
azioni = (azioni << 1) + 1;
azioni = (azioni << 1) + 1;
azioni = (azioni << 1);
azioni = (azioni << 1) + 1;
azioni = (azioni << 1);
azioni = (azioni << 1) + 1;
azioni = (azioni << 1);
azioni = (azioni << 1) + 1;
azioni = (azioni << 1);
ha come valore decimale 90026(il valore decimale e' quello utilizzato per il 
salvataggio nel db) e come valore binario
10101111110101010
dove come e' facile vedere, se partendo da destra ci sono i valori piu' 
recenti, le ultime tre azioni hanno avuto una reazione.
Matematicamente per validare il controllo basta fare:
90026 & 63 che da come risultato da 42 che e' uguale il nostro valore di 
controllo.
La & e' l'operatore bitwise utilizzato per il confronto di due stringhe 
binarie di uguale lunghezza per le quali viene fatta una congiunzione 
logica(vero 1 a bit corrispondente 0 falso a bit non corrispondente)
0011 & 
0010
= 0010
nel nostro caso
111111 & 
101010
= 101010
Sino qui tutto e' ok.
Il problema e' che orra devo tenere in considerazione anche il tempo.
In questo sistema non so se le azioni/reazioni "recenti"(quelle a destra) sono 
realmente recenti!
Ovvero una azione/reazione avvenuta ieri ha piu valore di una reazione 
avvenuta 2 mesi fa.
Se io nel db ho:
id: 1
nome: cristian
storia: 90026
id: 2
nome: luca
storia: 23046890
d: 3
nome: pippo
storia: 96107
Poi voglio sapere chi sono le persone reattive basta fare una query cosi:
select * from tabella where (storia & 63) = 42
mi restituisce cristian e luca ma dei due non posso sapere chi ha una reazione 
recente(che per me sarebbe un record piu' importante)
ps: una soluzione l'avrei ma stravolgerebbe completamente la logica di 
aggregazione dei dati e di controllo per questo cercavo di non allontanarmi 
troppo da questo sistema(solito discorso meno tocco...meglio e' :))
Sto provando con ottali e esadecimali per vedere se riesco ad inserire qualche 
elemento per il tempo.
Ciao
Crx
-- 
crx
http://www.crx.it

 elemento per il tempo.
Cosa cambia se hai gia "binarizzato" il tutto?
La informazione temporale la devi mettere da qualche parte, anche con la 
stessa struttura ma da qualche altra parte cosi' non tocchi il 
preesistente e magari dovrai fare un altro "&&".
Fermo restando che da quello che hai scritto, forse ho letto 
superficialmente, non ho compreso il come dove quando e' perche' del 
fattore "tempo" che citi.
--
ac

 fattore "tempo" che citi.
Se hai voglia di leggere di incollo qui sotto un messaggio scritto su un altro
ng sopo essere stato "accusato" di poca chiarezza :) qui il fattore tempo
dovrebbe essere piu' chiaro.
****
Una "azione" si ha quando contatto un utente.
Una "reazione" quando l'utente risponde.
Un esempio concreto(non e' il mio caso ma rende l'idea):
- mando una email ad un utente con un codice(azione)
- l'utente compila un form utilizzando tale codice(reazione)
Ho una tabella dove salvo questi dati in modo aggregato e una serie di tabelle
relazionate tra loro dove salvo i dati in modo dettagliato(tipo di contatto,
tipo di risposta, data, ora etc etc)
La reattivita' e' data da una azione con conseguente reazione per 3(parametro
che puo variare) volte consecutive, nell'esatto momento in cui un utente
risulta reattivo vengono scatenate una serie di operazioni.
Questo controllo viene fatto in tempo reale all'arrivo di ogni reazione e a
causa delle quantita' di record in gioco(si tratta di ~10 milioni di azioni al
giorno) non posso fare query articolate nelle tabelle di relazione altrimenti i
tempi di risposta del sistema cadrebbero a picco, da qui la tabella con il dato
aggregato.
La tabella e' composta cosi(ometto chiavi primarie e indici per comodita'):
utente: varchar
storia: bigint default 0
Oggi invio un contatto a "cristian" quindi ho la prima azione:
insert into tabella (nome, storia) value ('cristian', (storia << 1) +1 );
  valore nel campo storia 1
Il giorno dopo contatto nuovamente "cristian":
update tabella set storia = (storia << 1) + 1 where nome = 'cristian';
  valore nel campo storia 3
"cristian" risponde:
update tabella set storia = (storia << 1) where nome = 'cristian';
  valore nel campo storia 6
verifico se cristian e' reattivo:
select * from tabella where nome = 'cristian' and (storia & 63) == 42
ma non ottengo il record con questa query quindi non e' reattivo
se per i prossimi due contatti "cristian" risponde
-- contatto
update tabella set storia = (storia << 1) + 1 where nome = 'cristian'; 
-- risponde
update tabella set storia = (storia << 1) where nome = 'cristian';
-- contatto
update tabella set storia = (storia << 1) + 1 where nome = 'cristian';
-- risponde
update tabella set storia = (storia << 1) where nome = 'cristian';
a questo puno il valore nel campo storia e' 106
effettuando la verifica
select * from tabella where nome = 'cristian' and (storia & 63) == 42
ottengo il record, quindi "cristian" e' reattivo in modo consecutivo agli ultimi
tre contatti.
Quando voglio controllare quali sono tutti gli utenti reattivi nella tabella
basta fare:
select * from tabella where (storia & 63) == 42
Tutto funziona alla perfezione da oltre 3 anni ma dovra' entrare in gioco anche
la variabile tempo che servira' per differenziare le operazioni da effettuare
nel caso in cui un utente risulti reattivo.
In questo momento non ho modo di sapere se:
- l'ultima reazione e' recente
- all' arrivo dell'ultima reazione la penultima e' recente
- le ultime tre reazioni fatte sono ravvicinate nel tempo oppure no
logicamente "recente" avra' un valore in termini temporali cosi
come "ravvicinate"
"recente" potrebbe essere negli ultimi 15 giorni
e "ravvicinate" che le reazioni siano avveute a non piu' di 10 giorni l'una
dall'altra
