PDA

View Full Version : [CICLO 18] Storia 1


Jocchan
12-06-2006, 09:41
Storia: bugfix e refactoring



Punti cardine da tenere a mente durante i lavori:

* Mai fare a gara a chi finisce il task per primo, meglio procedere con calma, altrimenti perderemo molto più tempo in seguito
* Evitiamo di complicarci la vita, esiste di certo una soluzione più semplice di quella che abbiamo pensato di implementare
* MAI aggiungere elementi non richiesti esplicitamente dai task: se mai serviranno, se ne parlerà nelle prossime storie
* Comunichiamo il più possibile, se qualcosa nelle specifiche non è chiaro discutiamone tutti i dettagli fino ad eliminare ogni dubbio, anche il più insignificante
* Postare sempre la test list PRIMA di mettere mano al codice

Jocchan
13-06-2006, 11:15
18.1.1: 71104 completato
Scrivere la classe LogWriter che scrive l'elenco delle Action eseguite divise per turno e l'ultimo stato del GridController.

18.1.2: cdimauro:2 giorni
Scrivere la classe LogReader per leggere il file di Log e memorizzarlo in una struttura dati in memoria

18.1.3:
Scrivere la classe LogPlayer per eseguire le Action memorizzate nel log letto da LogReader

18.1.4: Ufo13:
Refactoring di BigGem

18.1.5:
Refactoring degli State

18.1.6:
Refactoring di Grid

71104
13-06-2006, 18:42
ok, allora proviamo con l'1 :mc:
esamino il codice, stendo una test list, e do la stima dei giorni

71104
13-06-2006, 18:49
ho capito perché nessuno si prenota: del task 1 non si capisce niente ed è propedeutico ai successivi 2, e tutti hanno paura per le loro ditine a fare gli ultimi 3 senza aver prima fatto i primi 3 :mc:

come deve apparire in definitiva un log scritto da questa LogWrite? esempio pratico di log? "l'ultimo stato del GridController" significa che alla fine subito prima di chiudere un log devo metterci lo stato del GridController?

71104
13-06-2006, 19:10
tutto chiaro, ho sentito VICIUS su MSN che mi ha spiegato quello che non capivo

Bonfo
13-06-2006, 19:54
Altra chiave di lettura del task che ti propongo. ;)

Cerca di capire cosa deve essere obbligatoriamente presente nel log per poter riprodurre lo stato del gioco. :rolleyes:

71104
13-06-2006, 20:19
premessa: questo task è una rogna perché richiede che il file sia scritto in modo che rileggendolo il programma possa ricreare lo stato del programma; a scriverlo come testo leggibile da un umano non ci vuole niente, ma a scriverlo in binario è un casino perché tocca per esempio scrivere anche il nome della classe finale di una certa Action in modo tale che rileggendolo il programma possa istanziare il giusto tipo di Action.

MFC dispone di un sistema di serializzazione che risolve questo problema in maniera eccellente, mi devo riguardare bene come funziona e fare come fa lui. per intanto ciò che verrà scritto nel log sarà semplicemente una stringa costruita dalla Action, la quale conterrà, oltre al nome della classe, ulteriori dati utili specifici per ogni tipo di Action; per ora però è solo una stringa, a renderli dati binari e rileggibili dal programma ci penserò dopo :mc:


refactoring pre-task:

- trasformare DroppableAction in una classe (è inutile che sia un'interfaccia)
- aggiungere a DroppableAction un metodo pubblico getLogText che ritorni in forma di oggetto String una sua descrizione (da implementare in maniera specifica in ciascuna Action)


test per la classe LogWriter:

- testare che LogWriter crei un file il cui nome viene passato al costruttore
- testare un metodo LogWriter.logAction(Action) che scriva nel log il testo ottenuto in un dato momento da Action.getLogText
- testare che il metodo scriva un marker nel file se quando viene chiamato il tempo corrente è maggiore di almeno 50 ms rispetto all'ultimo tempo registrato (50 ms è la durata di un turno, modificabile da GameConfig)


test di integrazione con Grid:

- testare che forEachDroppable chiami DroppableAction.logAction

Bonfo
13-06-2006, 21:01
a renderli dati binari e rileggibili dal programma ci penserò dopo :mc:


Mi sa che non è un problema tuo, ma del task dopo ;)

71104
13-06-2006, 21:40
infatti leggerli (col sistema di serializzazione MFC-like) è un problema del task dopo, ma voglio comunque analizzare il da farsi così se non altro aiuto chi lo fa; e poi renderli binari è comunque compito mio ^^

cdimauro
14-06-2006, 08:02
Prendo il 2: 2 giorni dopo il completamento del task 1. :D

Alberto, ma come formato non puoi usare un semplice file di testo?

NomeAzione [Parametri]

Con [Parametri] chiaramente opzionale (ed eventualmente separati da spazi, se ce n'è più d'uno.).

Ecco la test list:
- accertarsi che la lista sia vuota all'inizio;
- accertarsi che l'azione sia letta sia fra quelle contemplate;
- accertarsi che dopo aver introdotto un elemento, la lista non sia vuota;
- accertarsi che dopo aver inserito 2 elementi, il secondo sia consecutivo al primo;
- accertarsi che l'ultimo elemento letto dal file sia uno stato (quello di GridController).


Per quanto riguarda le rifattorizzazioni di BigGem e Grid, io direi di considerare questo thread alla stregua di un cantiere aperto in cui buttare giù tutte le informazioni su come procedere.

Dovremmo cominciare col definire l'interfaccia comune a tutti i tipi di oggetti che deve gestire Grid, e che ne possono cambiare lo stato (e cambiare stato a loro volta). Che ne dite?

fek
14-06-2006, 14:13
Chi si occupa di 3, 4, 5, 6?

Ufo13
14-06-2006, 18:10
Chi si occupa di 3, 4, 5, 6?

Io continuo con il 4 :)

cdimauro
15-06-2006, 09:08
Eventualmente al 3 potrei pensarci anch'io, dopo aver sviluppato il 2.

Per gli altri task, come dicevo, direi di parlarne in questo thread e di lavorarci un po' tutti.

Bonfo
15-06-2006, 12:46
Per gli altri task, come dicevo, direi di parlarne in questo thread e di lavorarci un po' tutti.


Quoto :D :D

Jocchan
16-06-2006, 10:16
Per favore, mi aggiornate sullo stato dei task?

Ufo13
16-06-2006, 11:03
Io sto procedendo con il refactoring :)

cdimauro
16-06-2006, 13:04
Io aspetto che Alberto finisca il suo task.

71104
18-06-2006, 11:28
ok, ci sono quasi, manca solo l'integrazione con Grid...

cdimauro, poi ti spiego qui sul forum i dettagli per rileggere il log (è binario)

Bonfo
18-06-2006, 12:06
Siccome sono disponibile, non full-time, ma a sufficenza per concludere qualcosa, volevo dare una mano con i refactoring degli ultimi 3 task.

Mentro attendo che qualcuno che ci sta già lavorando sopra mi dia qualche dritta (Ufo?? :D) provo a dare un occhio a come è messa la situazione ;)

fek
18-06-2006, 12:30
Alberto a che punto siamo con il primo refactoring?

71104
18-06-2006, 13:41
il primo task è completo, i test sono verdi, ma il gioco funziona male: sto LogWriter scrive *troppa* roba nel log O.o'
tanto che (se ho ben capito quello che è successo quando l'ho avviato) la JVM non è riuscita a tenere la velocità con cui il gioco scriveva nel log, e ne è stata scritta solo parte: il gioco funzionava rallentato e sulla console appariva un'enormità di messaggi.

cdimauro può anche cominciare il suo task, nel frattempo io cerco di indagare sul problema, ma intanto una causa posso già dirvela: ci sono un paio di actions che non dovrebbero esistere, una per esempio serve solamente a contare quante dinamiti ci sono nella griglia: è un hack, è concettualmente errato, perché quella non è una action, è solo un modo per sfruttare il doppio for contenuto nel metodo forEachGem. secondo me va corretto, poiché abbiamo stabilito che una action deve essere l'unico modo per modificare lo stato della griglia, non per effettuare un fetch di dati; ed è esattamente per questo motivo che noi nel log registriamo le actions: perché riproducendole otterremo esattamente lo svolgimento di una partita nel gioco, ma nel log è inutile avere registrata una action che mi dice che in quel momento io ho contato quante dinamiti c'erano nella griglia, giusto? :)

un'altra cosa che volevo fare prima cmq era sistemare ancora un po' i test case: GridTestCase va diviso, va creata una classe base EnvironmentTestCase che inizializzi solo l'environment, e da essa deve derivare GridTestCase che oltre all'environment inizializza anche Grid. non c'entra nulla col mio task solo apparentemente: me ne sono accorto aggiungendo il LogWriter ad Environment (mi sembrava ottimo come design e anche la soluzione più semplice per risolvere un certo problema nell'effettuare alcuni test di integrazione del LogWriter in Grid)

71104
18-06-2006, 13:44
ah a proposito, ho aggiunto un test per il GameLoop: testa che tutti i campi dell'environment siano inizializzati (compreso il LogWriter :p).

71104
18-06-2006, 13:53
primi risultati dell'indagine :p

quando il logWriter lanciava eccezione per non essere riuscito a scrivere qualcosa nel log, forEachDroppable catturava col try-catch e stampava lo stack trace; commentando la riga che stampava lo stack trace il gioco va fluido e veloce come prima e sulla console non appare più niente, ma il fatto che venissero stampati quegli stack trace voleva dire che certe volte il logWriter non è in grado di scrivere sul file, e chiaramente non va bene; e la cosa assurda è che giocando neanche una ventina di secondi ho ottenuto quasi 6 mega di log -_-'

mi sa che tocca aggiungere un'opzione in config per disattivare il logging :stordita:

thebol
18-06-2006, 19:05
ci sono un paio di actions che non dovrebbero esistere, una per esempio serve solamente a contare quante dinamiti ci sono nella griglia: è un hack, è concettualmente errato, perché quella non è una action, è solo un modo per sfruttare il doppio for contenuto nel metodo forEachGem. secondo me va corretto, poiché abbiamo stabilito che una action deve essere l'unico modo per modificare lo stato della griglia, non per effettuare un fetch di dati;

le action infatti erano nate per altri motivi..

cmq non si possono rendere loggabili selettivamente solo alcune action?

Bonfo
18-06-2006, 19:42
le action infatti erano nate per altri motivi..

cmq non si possono rendere loggabili selettivamente solo alcune action?

No. :mad:
O meglio si potrebbe ( ;) ), ma in realtà il problema che 71104 ha esposto è di design.
Ovvero è un indice di allarme che ci dice che tra un po' saremo terribilmente legati dal nostro stesso codice e non riusciremo più a sviluppare in modo efficace. :O

I refactoring di questa storia servono appunto per quello.
Probabilmente dopo essere morti a mettere a posto Droppable e Grid, moriremo per mettere a posto State e Action.

Se non risolviamo questi problemi la velocità dello sviluppo, che già ora va come un triciclo con le ruote sgonfie, raggiungere terribilemnte lo 0 assoluto :sob:

VICIUS
19-06-2006, 09:04
In effetti 5 megabyte di log per pochi secondi di gioco sono veramente troppi. Si potrebbe comprimere lo stream usando gzip prima di scriverlo ma mi sembra solo una pezza. Guardando il testo del .dat ho notato che ci sono una marea di nomi di funzioni interne al codice e persino dei pezzi di stacktrace.
(java.io.NotSerializableException(Vx �5 xr java.io.ObjectStreamExceptiond�k9� xr java.io.IOExceptionlsde%� xr java.lang.Exception� > ; � xr java.lang.Throwable�5'9w� L causet Ljava/lang/Throwable;L)
Per ora te l'ho segnato completato ma devi sistemare tutte queste prima che cdimauro possa cominciare il suo task.

ciao ;)

thebol
19-06-2006, 09:24
No. :mad:
O meglio si potrebbe ( ;) ), ma in realtà il problema che 71104 ha esposto è di design.
Ovvero è un indice di allarme che ci dice che tra un po' saremo terribilmente legati dal nostro stesso codice e non riusciremo più a sviluppare in modo efficace. :O

I refactoring di questa storia servono appunto per quello.
Probabilmente dopo essere morti a mettere a posto Droppable e Grid, moriremo per mettere a posto State e Action.

Se non risolviamo questi problemi la velocità dello sviluppo, che già ora va come un triciclo con le ruote sgonfie, raggiungere terribilemnte lo 0 assoluto :sob:

imho non cè nessun problema di design. In teoria basta aggiungere un metodo isLoggable a abstractDroppable. E il fatto che una action sia loggabile o no non mi pare una forzatura.

Bonfo
19-06-2006, 10:07
imho non cè nessun problema di design. In teoria basta aggiungere un metodo isLoggable a abstractDroppable. E il fatto che una action sia loggabile o no non mi pare una forzatura.

Sono d'accrodissimo...isLoggable sarebbe una ottima soluzione per determinare se la action va loggata o meno.

Quello che volevo dire era altro: se 71104 durante il suo task si è reso conto che delle Action non sono vere Action, bhè...bisogna cercare di capire se è vero ed evenbtualmente risolvere.

Siccome la definizione che Fek ha proposto di Action mi convince molto, direi che quelle "finte" Action vanno eliminte il prima possibile per non trovarci poi come con BigGem e Droppable.

thebol
19-06-2006, 10:18
Sono d'accrodissimo...isLoggable sarebbe una ottima soluzione per determinare se la action va loggata o meno.

Quello che volevo dire era altro: se 71104 durante il suo task si è reso conto che delle Action non sono vere Action, bhè...bisogna cercare di capire se è vero ed evenbtualmente risolvere.

Siccome la definizione che Fek ha proposto di Action mi convince molto, direi che quelle "finte" Action vanno eliminte il prima possibile per non trovarci poi come con BigGem e Droppable.

io le action le concepivo come un azione sulla gemma.
Questa azione poi veniva fatta su piu gemme usando forEachGem.

Se per azioni si intende solo modifica, ok vanno tolte.
Altrimenti (verificare se esiste una dinamite con certe caratteristiche puo essere un azione, aldilà del fatto che si potrebbe fare una bella forEachDynamite..), si possono rendere loggabili o no le varie action.

Si potrebbe al limite fare 2 interfacce diverse, e discriminare con 2 forEachDroppable, se qualcuno non digerisce gli if e i getType :asd:

cdimauro
19-06-2006, 10:25
primi risultati dell'indagine :p

quando il logWriter lanciava eccezione per non essere riuscito a scrivere qualcosa nel log, forEachDroppable catturava col try-catch e stampava lo stack trace; commentando la riga che stampava lo stack trace il gioco va fluido e veloce come prima e sulla console non appare più niente, ma il fatto che venissero stampati quegli stack trace voleva dire che certe volte il logWriter non è in grado di scrivere sul file, e chiaramente non va bene; e la cosa assurda è che giocando neanche una ventina di secondi ho ottenuto quasi 6 mega di log -_-'

mi sa che tocca aggiungere un'opzione in config per disattivare il logging :stordita:
6MB di log per pochi secondo sono decisamente troppi (e considerando che si tratta di dati binari e non strighe, che in genere occupano di più, è abbastanza preoccupante).
C'è qualcosa che non va nel nostro codice. Nella pausa pranzo provo a dargli un'occhiata.

Ufo13
19-06-2006, 11:11
6MB di log sono decisamente troppi :)

thebol
19-06-2006, 11:19
fra l'altro loggando solo le action ci si perde alcune modifiche alla griglia, tipo quelle degli state...

VICIUS
19-06-2006, 11:24
La questione delle action in effetti non è da sottovalutare ma a mio avviso ha una soluzione abbastanza semplice. Basta creare un'altro tipo di Action e chiamarlo Query che invece di modificare lo stato di grid ritorna delle informazioni. In pratica dovremmo portare tutte quelle action che fanno uso di getResult a questa nuova categoria.

ciao ;)

71104
19-06-2006, 11:29
ho capito come fare per ridurre le dimensioni del log :)

ho studiato meglio al serializzazione in Java, ci tocca riscrivere i metodi readObject e writeObject; quelli predefiniti scrivono troppa roba che non ci serve ;)

a questo punto mi sembra chiaro che se io mi occupo dei vari writeObject cdimauro si occuperà dei read :D

ottima l'idea della classe Query, ma abbiamo dei tempi piuttosto stringenti e non possiamo aspettare che arrivino i task; è possibile lavorare anche al di fuori dei task se l'idea è approvata dai coach? sempre rigorosamente in TDD ovviamente

71104
19-06-2006, 11:33
ah, una cosa: i metodi readObject e writeObject devono essere privati, perciò non possiamo testarli

VICIUS
19-06-2006, 11:35
ah, una cosa: i metodi readObject e writeObject devono essere privati, perciò non possiamo testarli
Non puoi fare una funzione ubblica che richiama la writeObject privata?

ciao ;)

71104
19-06-2006, 11:46
Non puoi fare una funzione ubblica che richiama la writeObject privata? si però così il test mi assicura che la funzione pubblica scriva i dati sul file, non writeObject :p ^^
cmq ok

71104
19-06-2006, 12:28
no, come non detto: ho provato a metterli pubblici e non gliene frega niente, perciò si possono testare tranquillamente :)

Bonfo
19-06-2006, 12:48
La questione delle action in effetti non è da sottovalutare ma a mio avviso ha una soluzione abbastanza semplice. Basta creare un'altro tipo di Action e chiamarlo Query che invece di modificare lo stato di grid ritorna delle informazioni. In pratica dovremmo portare tutte quelle action che fanno uso di getResult a questa nuova categoria.

ciao ;)

MI PIACE !! :D

71104
19-06-2006, 13:10
dopo pranzo voglio fare un refactoring del task 18.1.1: forse oltre che a ridurre le dimensioni del log riesco ad eliminare tutti gli if :D

thebol
19-06-2006, 13:16
La questione delle action in effetti non è da sottovalutare ma a mio avviso ha una soluzione abbastanza semplice. Basta creare un'altro tipo di Action e chiamarlo Query che invece di modificare lo stato di grid ritorna delle informazioni. In pratica dovremmo portare tutte quelle action che fanno uso di getResult a questa nuova categoria.

ciao ;)
secondo me conviene discriminare piu fra azioni loggabili e non loggabili, anche perchè il getResult non puo essere messo nel tipo base, visto che diverse action/Query hanno result diversi.

cmq le 2 idee alla fine sono simili, una vale l'altra ;)

71104
19-06-2006, 14:35
cmq le 2 idee alla fine sono simili, una vale l'altra ;) assolutamente no, tra le due c'è una differenza importante: aggiungere un metodo isLoggable implica necessariamente un if che controlla il risultato di quel metodo! scommettiamo che con una apposita classe Query viene un if di meno? ;)
per quanto riguarda il getResult hai ragione, ma non c'è bisogno di mettere quel metodo nella classe base.

thebol
19-06-2006, 14:41
assolutamente no, tra le due c'è una differenza importante: aggiungere un metodo isLoggable implica necessariamente un if che controlla il risultato di quel metodo! scommettiamo che con una apposita classe Query viene un if di meno? ;)
per quanto riguarda il getResult hai ragione, ma non c'è bisogno di mettere quel metodo nella classe base.

scusa non avevo specificato che parlavo dell'idea delle 2 interfacce loggable/nonloggable ;)

cdimauro
19-06-2006, 15:08
Alberto, ho rivisto il codice e mi sembra che ci stiamo complicando la vita più del dovuto.

Faccio una proposta (indecente ovviamente, altrimenti non sarei io :D): loggiamo e riproduciamo gli eventi ricevuti in input.

La chiave di tutto è GameLoop.processInput(): a ogni sua chiamata dovrebbe essere associato un game turn univoco e progressivo, che ci servirà anche per la lettura e riproduzione degli eventi.

Introdotto questo concetto, a grandi linee la mia idea è questa:
- LogWriter dovrebbe diventare un listener per l'InputDevice corrente (la tastiera), che quindi riceverà tramite notify tutti gli eventi da esso erogati; basta loggarli con il game turn ad esso associato;
- LogReader (ma a questo punto lo chiamerei LogPlayer) dovrebbe diventare un InputDevice (con le ultime rifattorizzazioni che ho fatto, è banale farlo diventare tale. ;)) e quindi, dopo aver letto tutto il file di log alla partenza, "rispondere" agli update di processInput() effettuando i notify ai vari listener che gli sono attaccati (come il bimbo al capezzolo della mamma :p).

Come puoi capire, non ci dovrebbe volere molto. Abbiamo già tutto pronto: basta usarlo.

A naso direi che per qualche secondo il file di log dovrebbe diventare di 3 ordini di grandezza più piccolo. :p

Inoltre, e secondo me è la cosa più importante, non dobbiamo imbordellare mezzo mondo per implementare questo task, e perderci ancora altro tempo. Stiamo perdendo veramente TROPPO tempo per i task nell'ultimo periodo (colpa anche mia, che a casa sono azzoppato coi PC. Stasera madre e figlia sono a cena fuori con le altre mamme dell'asilo: ne approfitto per smanettere un po' sul PC e rimetterlo in carreggiata :asd: ).

K.I.S.S. rulez :sofico:

OK, preparo la corda per la mia impiccagione... :D

P.S. Ovviamente questo cambiamento è da discutere, visto che si tratta di cambiare i requisiti del customer. ;)

thebol
19-06-2006, 15:14
Alberto, ho rivisto il codice e mi sembra che ci stiamo complicando la vita più del dovuto.

Faccio una proposta (indecente ovviamente, altrimenti non sarei io :D): loggiamo e riproduciamo gli eventi ricevuti in input.

La chiave di tutto è GameLoop.processInput(): a ogni sua chiamata dovrebbe essere associato un game turn univoco e progressivo, che ci servirà anche per la lettura e riproduzione degli eventi.

Introdotto questo concetto, a grandi linee la mia idea è questa:
- LogWriter dovrebbe diventare un listener per l'InputDevice corrente (la tastiera), che quindi riceverà tramite notify tutti gli eventi da esso erogati; basta loggarli con il game turn ad esso associato;
- LogReader (ma a questo punto lo chiamerei LogPlayer) dovrebbe diventare un InputDevice (con le ultime rifattorizzazioni che ho fatto, è banale farlo diventare tale. ;)) e quindi, dopo aver letto tutto il file di log alla partenza, "rispondere" agli update di processInput() effettuando i notify ai vari listener che gli sono attaccati (come il bimbo al capezzolo della mamma :p).

Come puoi capire, non ci dovrebbe volere molto. Abbiamo già tutto pronto: basta usarlo.

A naso direi che per qualche secondo il file di log dovrebbe diventare di 3 ordini di grandezza più piccolo. :p

Inoltre, e secondo me è la cosa più importante, non dobbiamo imbordellare mezzo mondo per implementare questo task, e perderci ancora altro tempo. Stiamo perdendo veramente TROPPO tempo per i task nell'ultimo periodo (colpa anche mia, che a casa sono azzoppato coi PC. Stasera madre e figlia sono a cena fuori con le altre mamme dell'asilo: ne approfitto per smanettere un po' sul PC e rimetterlo in carreggiata :asd: ).

K.I.S.S. rulez :sofico:

OK, preparo la corda per la mia impiccagione... :D

P.S. Ovviamente questo cambiamento è da discutere, visto che si tratta di cambiare i requisiti del customer. ;)

sottoscrivo ampiamente.
Era stata scartata quest'ipotesi perche il log doveva essere riprocucibile senza l'uso del timer, e con i soli eventi era un po dura...

cdimauro
19-06-2006, 15:54
OK grazie. :) Con le ultime rifattorizzazioni dovrebbe essere tutto molto, ma molto più semplice.

Una precisazione comunque: è chiaro che la riproduzione del log ha senso soltanto se è associato alle STESSE KeyMap usate dal client che l'ha generato (i tasti che ha scelto di usare l'utente).
Questo perché sono ormai gli stessi InputDevice ad effettuare la traslazione al loro interno, dentro update(), e quindi con la notify() ai listener viene passato il dato già "cucinato". ;)

thebol
19-06-2006, 15:56
OK grazie. :) Con le ultime rifattorizzazioni dovrebbe essere tutto molto, ma molto più semplice.

Una precisazione comunque: è chiaro che la riproduzione del log ha senso soltanto se è associato alle STESSE KeyMap usate dal client che l'ha generato (i tasti che ha scelto di usare l'utente).
Questo perché sono ormai gli stessi InputDevice ad effettuare la traslazione al loro interno, dentro update(), e quindi con la notify() ai listener viene passato il dato già "cucinato". ;)

e se si logga il keyEvent?
oppure direttamente l'handler?

cdimauro
19-06-2006, 16:32
Basta loggare l'Event che tutti i listener ricevono dall'InputDevice, a mio avviso. :)

Non passerei nemmeno dall'handler, che è già "troppo lontano" (si passa per InputReactor & co.).

Loggando gli eventi saremmo già a un livello molto alto e i cambiamenti al codice sarebbero realmente pochi: tutto il resto del codice non verrebbe toccato di una virgola.

thebol
19-06-2006, 16:35
Basta loggare l'Event che tutti i listener ricevono dall'InputDevice, a mio avviso. :)

Non passerei nemmeno dall'handler, che è già "troppo lontano" (si passa per InputReactor & co.).

Loggando gli eventi saremmo già a un livello molto alto e i cambiamenti al codice sarebbero realmente pochi: tutto il resto del codice non verrebbe toccato di una virgola.

giusto.
e che non ho capito se la riproduzzione sarebbe influenzata dalla configurazione della tastiera :confused:

71104
19-06-2006, 16:56
cesare, ho letto il postone :p
ok, capito quello che dici, ma non mi sembra che vada in contrasto con l'80% di quello che ho fatto finora, perché in un modo o nell'altro qualche classe che scrive dati binari sul log ci deve stare :)
per il rimanente 20%, si tratta di cambiare l'interazione tra LogWriter e Grid, che deve diventare interazione tra LogWriter e qualunque cosa rappresenti la periferica di input.

ed infine x quanto riguarda le dimensioni del log, io per quanto mi riguarda un po' le ho già ridotte :D
non sarà specificamente la tua idea di loggare gli input anziché le actions (cmq da rivedere, altrimenti il concetto di action perde di utilità, senza contare che come hai detto tu non è ciò che aveva chiesto il customer) a cambiare le dimensioni del log: il log è grosso perché i metodi predefiniti writeObject della JVM scrivono un sacco di roba inutile, tocca rifarli a mano classe per classe e quindi scrivere solo ciò che serve.

Bonfo
19-06-2006, 17:25
L'idea di Cesare è quella che in qualche modo avevo già proposto io, anche se in un altro ambito.

http://www.hwupgrade.it/forum/showpost.php?p=12569163&postcount=205

Sono convintissimo che trasformare il log in un input device sia la cosa migliore.

Ora due punti:
- In realtà il playBack deve poter essere gestito come un "filmato", ovvero devo poter partire da un momento qualunque e essere portatop avanti e indietro, ciopè indipendente dal tempo :D

- Quindi la divisione tra Reader e Player deve rimanere. Il primo mette tutte le informazioni in una struttura dati apposta, oppure wrappa la risorsa come se fosse una struttura dati, poi il Player utilizzerà questa risosrsa per comandare il game ;)

71104
19-06-2006, 18:35
L'idea di Cesare è quella che in qualche modo avevo già proposto io, anche se in un altro ambito.

http://www.hwupgrade.it/forum/showpost.php?p=12569163&postcount=205

Sono convintissimo che trasformare il log in un input device sia la cosa migliore. a me invece sinceramente pare che sia meglio registrare le actions piuttosto che gli input, se veramente una action diventa l'unico modo per modificare Grid... rirpdourre gli input mi sembra una soluzione che potrebbe rivelarsi difficoltosa nel riprodurre l'esatta sincronizzazione tra input e tempo che passa: che succederebbe in fase di playback se in fase di registrazione ad un certo punto si accumulassero in queue un certo numero di input gestiti non immediatamente a causa per esempio di qualche altro processo che toglie CPU alla JVM? in fase di playback dovresti calcolare anche questo... non si tratta banalmente di mandare a GridController una marea di input che come arrivano arrivano, no, devi anche considerare che quando la partita è avvenuta originariamente quel dato input è arrivato mentre il controller si trovava in quel dato stato e la coppia di gemme era in quella precisissima posizione... e anche con la migliore delle implementazioni il tutto è facilmente soggetto a dissincronie (non so se si dice così :D) a causa per es. di errori nei floating point (so che le coordinate da un po' di tempo sono state convertite a int, ma la gravità se non erro è ancora floating point...)

per dirlo in altre parole:
- se tu registri solo gli input ti perdi tutte le informazioni di sincronizzazione tra l'input e il gioco
- se tu registri tutte le actions, tu registri qualunque fattore che abbia provocato dei cambiamenti in Grid, perciò registri implicitamente anche gravità, crush, ecc. e siccome abbiamo la certezza che se una action B è avvenuta dopo una action A allora nel log B starà sicuramente dopo A, hai automaticamente la certezza di riprodurre il tutto in perfetta sincronia

molto meglio la seconda insomma, anche molto più semplice visto che memorizzare informazioni sulla sincronizzazione tra gioco e input richiederebbe gestione a parte imho molto complessa!

se ormai stiamo facendo la seconda, e con la seconda non ti puoi sbagliare, perché mai cambiare dovendone quindi discutere col customer e introducendo altri ritardi? :cry:

Ora due punti:
- In realtà il playBack deve poter essere gestito come un "filmato", ovvero devo poter partire da un momento qualunque e essere portatop avanti e indietro, ciopè indipendente dal tempo :D fico :D
questa mi piace :)

- Quindi la divisione tra Reader e Player deve rimanere. Il primo mette tutte le informazioni in una struttura dati apposta, oppure wrappa la risorsa come se fosse una struttura dati, poi il Player utilizzerà questa risosrsa per comandare il game ;) hum, hum, hum... si, indubbiamente non è che possiamo andare ogni volta a rileggere indietro nel file, anche perché usando il sistema di serializzazione di Java degli oggetti la cosa non è possibile.

thebol
19-06-2006, 20:02
a me invece sinceramente pare che sia meglio registrare le actions piuttosto che gli input, se veramente una action diventa l'unico modo per modificare Grid... rirpdourre gli input mi sembra una soluzione che potrebbe rivelarsi difficoltosa nel riprodurre l'esatta sincronizzazione tra input e tempo che passa: che succederebbe in fase di playback se in fase di registrazione ad un certo punto si accumulassero in queue un certo numero di input gestiti non immediatamente a causa per esempio di qualche altro processo che toglie CPU alla JVM? in fase di playback dovresti calcolare anche questo... non si tratta banalmente di mandare a GridController una marea di input che come arrivano arrivano, no, devi anche considerare che quando la partita è avvenuta originariamente quel dato input è arrivato mentre il controller si trovava in quel dato stato e la coppia di gemme era in quella precisissima posizione... e anche con la migliore delle implementazioni il tutto è facilmente soggetto a dissincronie (non so se si dice così :D) a causa per es. di errori nei floating point (so che le coordinate da un po' di tempo sono state convertite a int, ma la gravità se non erro è ancora floating point...)

per risolvere questo problema imho basta il gameTurn :)
al tot gameTurn tizio ha spinto questo e questo tasto.

fra l'altro mi sembra piu semplice da realizzare quest'ipotesi, visto che per usare le action, dovremmo fare in modo che solo le action possano modificare grid, cosa che ora non è vera.

71104
19-06-2006, 22:21
allora mettila su questi termini: indipendentemente da come verrà completato il sistema di log, io farò in modo di refattorizzare e rendere le action l'unico modo per modificare Grid :Prrr:

thebol
20-06-2006, 06:37
allora mettila su questi termini: indipendentemente da come verrà completato il sistema di log, io farò in modo di refattorizzare e rendere le action l'unico modo per modificare Grid :Prrr:
YANGI!!!1!!!111 :Prrr:


ps.secondo mè sarebbe una restrizione eccessiva. Concordo che il logger o Config non debbano modificare grid :asd:, ma limitare le modifiche alle action non lo vedo utile. Centralizzeresti la chiamata alle modifiche di grid, ma tralasciando il log, quale sarebbe il vantaggio, apparte aver aggiunto delle costrizioni.

Ad esempio per le dinamiti:
vengono cancellate da una action che viene eseguita a ogni giro di update(+ o -), ma questa action dipende dal fatto che la dinamite sia settata cancellabile.
Questo puo avvenire in 2 modi, o l'utente rilascia il tasto oppure passano 5 sec.
Nel primo caso è un eventHandler che cerca la dinamite da cancellare(tramite una action), nell'altro è la dinamite che nella sua update controlla che non sia scaduto il timeout, e quando scade si setta da cancellare.

Si potrbbe fare in modo che la dinamite quando scade il timeout lanci la action, ma sarebbe una forzatura di design imho.

cdimauro
20-06-2006, 07:36
giusto.
e che non ho capito se la riproduzzione sarebbe influenzata dalla configurazione della tastiera :confused:
Perché se, ad esempio, è stato loggato il tasto Code.KEY_E che nella configurazione del giocatore corrisponde poi a Code.UP, mentre nella macchina che deve far girare il playback del log a quella configurazione non corrisponde niente oppure un altro evento, è chiaro il playback non riprodurrà esattamente lo scenario del giocatore.

Attualmente c'è un mapping interno all'implementazione della tastiera, quale InputDevice, ma è sostanzialmente un'associazione 1 a 1 fra il codice della tastiera e l'evento corrispondente. Quindi al tasto KEY_E di LWJGL corrisponde Code.KEY_E.

Poiché il log degli eventi avviene al livello più alto possibile, ossia subito dopo questa traslazione interna (quando la tastiera richiama il notify dei listener), è chiaro che la traslazione successiva, ossia da evento "grezzo" (legato ancora alla tastiera) a quello "raffinato" (ossia l'evento che corrisponde alla direzione o ai bottoni), non è ancora avvenuto.
E poiché dipende, appunto, dalla mappa utilizzata in locale dal client che ha generato il log, oltre al log per la riproduzione corretta sarà necessario anche la mappa di traslazione usata dal client (KeysConfig).

thebol
20-06-2006, 07:48
Perché se, ad esempio, è stato loggato il tasto Code.KEY_E che nella configurazione del giocatore corrisponde poi a Code.UP, mentre nella macchina che deve far girare il playback del log a quella configurazione non corrisponde niente oppure un altro evento, è chiaro il playback non riprodurrà esattamente lo scenario del giocatore.

Attualmente c'è un mapping interno all'implementazione della tastiera, quale InputDevice, ma è sostanzialmente un'associazione 1 a 1 fra il codice della tastiera e l'evento corrispondente. Quindi al tasto KEY_E di LWJGL corrisponde Code.KEY_E.

Poiché il log degli eventi avviene al livello più alto possibile, ossia subito dopo questa traslazione interna (quando la tastiera richiama il notify dei listener), è chiaro che la traslazione successiva, ossia da evento "grezzo" (legato ancora alla tastiera) a quello "raffinato" (ossia l'evento che corrisponde alla direzione o ai bottoni), non è ancora avvenuto.
E poiché dipende, appunto, dalla mappa utilizzata in locale dal client che ha generato il log, oltre al log per la riproduzione corretta sarà necessario anche la mappa di traslazione usata dal client (KeysConfig).

ok.
E' possibile inserire un ulteriore strato per dei tasti logici, che rappresentino la funzione che fanno(up, blow, etc), oppure sostituire questo strato al Code.*?

In questa maniera, loggando il tasto logico, la mappa risulterebbe inutile, no?

cdimauro
20-06-2006, 07:49
allora mettila su questi termini: indipendentemente da come verrà completato il sistema di log, io farò in modo di refattorizzare e rendere le action l'unico modo per modificare Grid :Prrr:
Alberto, ma perché ti devi andare a complicare la vita? Oggettivamente, col tuo LogWriter non avrai nemmeno bisogno di farlo diventare un Listener: avevo dimenticato che GameLoop è già un listener, e quindi riceve esattamente gli stessi eventi degli input dei due giocatori.

In soldoni: ti bastano 3 (TRE) righe di codice su GameLoop per implementare il log:
- gameTurn.Reset() (o gameTurn = 0); // alla creazione di GameLoop
- gameTurn.Advance() (o gameTurn++); // all'inizio di processInput();
- logWrite.writeEvent(gameTurn.get(), event); // all'inizio di notify().

E hai finito! Anzi, aggiungiamoci pure il salvataggio del seed alla creazione di GameLoop e arriviamo a ben 4 (QUATTRO) istruzioni.

logWrite dovrà avere soltanto 2 metodi: uno per salvare il seed quale primo dato del file di log e quello per scrivere gli eventi.
Puoi benissimo usare anche un file di testo in cui metti tutti i dati separati da un semplice spazio (gameturn, event.code event.state, event.timestamp).

I problemi di sincronizzazione si risolvono facilmente, perché a un evento è sempre associato il relativo timestamp (oltre che al gameTurn ovviamente, ma quest'ultimo serve per inserire un "lotto" di eventi tutti in una volta nel flusso di input): basta usare sempre MockTimer in fase di playback (non si può fare altrimenti: il tempo di sistema è cambiato e NON si può usare Timer), e procedere con degli opportuni timer.advance() per far "passare il tempo" com'è stato per il client (basta avanzare della differenza fra il timestamp dell'evento e il valore corrente del timer).

Che poi, parliamoci chiaramente, sarà compito di chi dovrà scrivere il logPlayer (e sono d'accordo con quanto è stato poi detto: separiamoli pure). ;)

Per il resto, concordo con le osservazioni fatte dagli altri.

Vediamo cosa dice anche Jocchan, che il customer.

Dimenticavo: non è affatto vero che con le modifiche che fai soltanto le action potranno cambiare modificare. Per quanto detto, sono gli eventi di input che lo fanno, perché è da essi che vengono generate, eventualmente, le azioni. ;)

cdimauro
20-06-2006, 07:56
ok.
E' possibile inserire un ulteriore strato per dei tasti logici, che rappresentino la funzione che fanno(up, blow, etc), oppure sostituire questo strato al Code.*?

In questa maniera, loggando il tasto logico, la mappa risulterebbe inutile, no?
Sì, ma in questo modo il codice dovrebbe essere spostato a un livello più basso, esattamente nelle notify di tutti listener (i due Input e GameLoop; mentre adesso basta intercettare soltanto GameLoop).

Si può fare, ma si complica un po' il codice. Niente d'eccezionale, sia chiaro. :)

Anzi, se non richiede tanto tempo, magari è la soluzione che si può implementare da subito (basta "rendere disponibili" GameTurn e LogWriter anche agli Input, oltre all'InputDevice e al Timer), così tagliamo la testa al toro e non rimettiamo più mano a questo codice... :D

cdimauro
20-06-2006, 07:59
L'idea di Cesare è quella che in qualche modo avevo già proposto io, anche se in un altro ambito.

http://www.hwupgrade.it/forum/showpost.php?p=12569163&postcount=205

Sono convintissimo che trasformare il log in un input device sia la cosa migliore.
Idem. :)
Ora due punti:
- In realtà il playBack deve poter essere gestito come un "filmato", ovvero devo poter partire da un momento qualunque e essere portatop avanti e indietro, ciopè indipendente dal tempo :D
Implementazione banale: basta resettare il gioco ogni volta e avanzare fino al punto (cioé al GameTurn :D) desiderato.
E' molto meglio che implementare il codice "antigravità" per "andare indietro nel tempo"... :asd:
- Quindi la divisione tra Reader e Player deve rimanere. Il primo mette tutte le informazioni in una struttura dati apposta, oppure wrappa la risorsa come se fosse una struttura dati, poi il Player utilizzerà questa risosrsa per comandare il game ;)
Va benissimo. :)

Bonfo
20-06-2006, 10:50
.....
In soldoni: ti bastano 3 (TRE) righe di codice su GameLoop per implementare il log:
- gameTurn.Reset() (o gameTurn = 0); // alla creazione di GameLoop
- gameTurn.Advance() (o gameTurn++); // all'inizio di processInput();
- logWrite.writeEvent(gameTurn.get(), event); // all'inizio di notify().

E hai finito! Anzi, aggiungiamoci pure il salvataggio del seed alla creazione di GameLoop e arriviamo a ben 4 (QUATTRO) istruzioni.

logWrite dovrà avere soltanto 2 metodi: uno per salvare il seed quale primo dato del file di log e quello per scrivere gli eventi.
Puoi benissimo usare anche un file di testo in cui metti tutti i dati separati da un semplice spazio (gameturn, event.code event.state, event.timestamp).

I problemi di sincronizzazione si risolvono facilmente, perché a un evento è sempre associato il relativo timestamp (oltre che al gameTurn ovviamente, ma quest'ultimo serve per inserire un "lotto" di eventi tutti in una volta nel flusso di input): basta usare sempre MockTimer in fase di playback (non si può fare altrimenti: il tempo di sistema è cambiato e NON si può usare Timer), e procedere con degli opportuni timer.advance() per far "passare il tempo" com'è stato per il client (basta avanzare della differenza fra il timestamp dell'evento e il valore corrente del timer).
....


Se non fossi spostato ti sposerei io !!! :kiss: :D :D

cdimauro
20-06-2006, 11:45
Esagerato! :p

cdimauro
20-06-2006, 11:56
Sì, ma in questo modo il codice dovrebbe essere spostato a un livello più basso, esattamente nelle notify di tutti listener (i due Input e GameLoop; mentre adesso basta intercettare soltanto GameLoop).

Si può fare, ma si complica un po' il codice. Niente d'eccezionale, sia chiaro. :)

Anzi, se non richiede tanto tempo, magari è la soluzione che si può implementare da subito (basta "rendere disponibili" GameTurn e LogWriter anche agli Input, oltre all'InputDevice e al Timer), così tagliamo la testa al toro e non rimettiamo più mano a questo codice... :D
C'era qualcosa che non mi quadrava in questo discorso: i miei sensi di ragno ronzavano come dei dannati e non mi hanno lasciato in pace. :p

Così com'è non potrebbe andare bene come soluzione.

Il motivo è presto detto: se salviamo nei log soltanto gameturn, event.code, event.state e event.timestamp, perdiamo un'informazione importantissima: a quale giocatore sono associati? :eek:

Questo perché traslando dall'evento "grezzo" (es: Code.KEY_E) all'evento "cucinato" (es: Code.UP), che avviene all'intero dell'input associato a un giocatore, quest'ultimo (l'evento "cucinato") rappresenta ormai "astrattamente" ciò che "si deve fare". E va benissimo perché, in fin dei conti, stiamo lavorando su un ben preciso giocatore.

Quindi sarebbe meglio conservare anche l'informazione relativa al giocare.

Potremmo usare la codifica usata in KeysConfig. Ad esempio P1.UP è l'evento Code.UP associato al giocatore 1.

Quindi una riga che rappresenta un evento potrebbe essere fatta così:

0 P2.BLOW 1 1234567

GameTurn: 0
Giocatore: #2
Evento: Code.BLOW
Stato: State.PRESSED
Timestamp: 1234567

Dovremmo esserci a questo punto. ;)

Jocchan
20-06-2006, 12:24
Ma non abbiamo un file di log diverso per ogni giocatore?

thebol
20-06-2006, 12:29
forse, e dico forse, puo mancare la gestione del pattern per le stone, che non so bene come venga generato..

Bonfo
20-06-2006, 12:43
Ma non abbiamo un file di log diverso per ogni giocatore?

Per come è il gioco non ha senso.
infatti le stone dipendono in modo strettissimo dal giocatore di fianco.
Quindi senza sapere cosa fa quel gicoator e non avremmo l'informazione sulle stone.

Indubbiamente se incominciamo a salvare l'informazione sulle incoming stone di ogni griglia risolviamo il problema. Ma non mi picae molto.

Comunque il costumer sei tu :D :D

Bonfo
20-06-2006, 12:43
forse, e dico forse, puo mancare la gestione del pattern per le stone, che non so bene come venga generato..

Già...bisogna salvarsi pure quello. :rolleyes:

thebol
20-06-2006, 13:08
Per come è il gioco non ha senso.
infatti le stone dipendono in modo strettissimo dal giocatore di fianco.
Quindi senza sapere cosa fa quel gicoator e non avremmo l'informazione sulle stone.

Indubbiamente se incominciamo a salvare l'informazione sulle incoming stone di ogni griglia risolviamo il problema. Ma non mi picae molto.

Comunque il costumer sei tu :D :D

considera cmq che uno puo anche farsi una partita da solo...

cdimauro
20-06-2006, 13:09
forse, e dico forse, puo mancare la gestione del pattern per le stone, che non so bene come venga generato..
Se viene generato casualmente, conservando il seed siamo a posto.

Ma non so come funziona... :(

71104
20-06-2006, 14:24
ma oltre al pattern delle stones lo stesso identico problema si pone anche per l'estrazione delle gemme, anch'essa casuale; il seed usato è lo stesso in entrambi i players (che infatti hanno sempre le stesse identiche gemme) ma cambia ad ogni partita, e tocca salvare nel log pure quello. salvare un log sta diventando una cosa piuttosto dispersiva, secondo me serve un sistema centralizzato per le modifiche di Grid, ecco perché insisto tanto sulle Action; facendo passare ogni minima modifica a Grid per un canale unico, sappiamo che deviando quel canale nel file di log abbiamo memorizzato vita morte e miracoli di una partita, l'idea è questa.

e se i dati se li salviamo come stringhe poi leggerli è un macello (scusa cesare ma come fai, usi il tokenizer?? O.o), servono binari, solo che ovviamente così com'è adesso non va bene, la JVM mi salva una marea di roba inutile che provvederò a togliere (un po' l'ho già fatto). il discorso di salvare dati binari o testuali comunque è indipendente da quello delle action e del listener.

serve urgentemente il parere di fek altrimenti non andiamo avanti; appena si pronuncia fek faremo tutti come dice lui ^^

thebol
20-06-2006, 14:44
ma oltre al pattern delle stones lo stesso identico problema si pone anche per l'estrazione delle gemme, anch'essa casuale; il seed usato è lo stesso in entrambi i players (che infatti hanno sempre le stesse identiche gemme) ma cambia ad ogni partita, e tocca salvare nel log pure quello.


lo salvi a inizio partita e basta..

salvare un log sta diventando una cosa piuttosto dispersiva, secondo me serve un sistema centralizzato per le modifiche di Grid, ecco perché insisto tanto sulle Action; facendo passare ogni minima modifica a Grid per un canale unico, sappiamo che deviando quel canale nel file di log abbiamo memorizzato vita morte e miracoli di una partita, l'idea è questa.

secondo me è una costrizione di design che non ci serve. E ulteriori refactoring rallenterebbero solo lo sviluppo. E inutile stare a ricercare il design perfetto(ognuno ha i suoi vantaggi e i suoi limiti). Abbiamo una soluzione che non ci costa refactoring, mi pare piu semplice questa strada.



e se i dati se li salviamo come stringhe poi leggerli è un macello (scusa cesare ma come fai, usi il tokenizer?? O.o), servono binari, solo che ovviamente così com'è adesso non va bene, la JVM mi salva una marea di roba inutile che provvederò a togliere (un po' l'ho già fatto). il discorso di salvare dati binari o testuali comunque è indipendente da quello delle action e del listener.


non vedo cosi drammatico salvare una stringa tipo quella ipotizzata da cdimauro, con le utils offerte da java. Ed in piu le stringhe sono piu "portabili" da versione a versione.

cdimauro
20-06-2006, 14:46
Sì, ho visto che nel codice ci sono diverse chiamate per ottenere i seed, ma salvarli non è un problema.
Avevo già in mente di "convogliare" tutte le chiamate a system.nanoTime() in una classe che permetteva di fare il tracking dei semi generati, per poi salvarli alla fine. In riproduzione questa classe tornerebbe banalmente la sequenza dei semi memorizzata.

Per la memorizzazione si possono benissimo appendere queste informazioni alla fine del file di log, alla fine della partita (quando non ci sono più eventi da salvare): il reader provvederà poi a leggere correttamente eventi e seed (che comunque dovrebbero essere in numero limitato) e smistarli negli appositi vettori / liste FIFO.

Per quanto riguarda il formato di memorizzazione, si può usare quello che vuoi, anche in binario, per me non c'è problema.
Con le stringhe mi sono trovato sempre bene (soprattutto perché posso controllare il log con un editor, ed effettuare modifiche e aggiunte ;)) e non credo che sia difficile trovare una funzione che esegue uno split di una stringa in base a un carattere: esiste nelle librerie di ogni linguaggio.

Sono d'accordo con te, comunque: aspettiamo anche il parere di fek e decidiamo il da farsi.

thebol
20-06-2006, 14:53
Sì, ho visto che nel codice ci sono diverse chiamate per ottenere i seed, ma salvarli non è un problema.
Avevo già in mente di "convogliare" tutte le chiamate a system.nanoTime() in una classe che permetteva di fare il tracking dei semi generati, per poi salvarli alla fine. In riproduzione questa classe tornerebbe banalmente la sequenza dei semi memorizzata.


ho fatto una ricerca veloce di nanoTime, ma ho trovato che è usata solo in randomGenerator :confused:.

e il seed viene usato internamente alla classe randomGenerator e per essere salvato sul log all'inizio :confused: :confused:

cdimauro
20-06-2006, 15:14
Mumble mumble. nanoTime() viene richiamata direttamente anche in GameLoop.initPlayField().

A questo punto basterebbe sostituirlo con un (new RandomGenerator()).getSeed() e poi aggiungere a questa classe il salvataggio su LogWriter dei seed generati, e avremmo risolto il problema. :p

P.S. In realtà nanoTime() viene richiamata anche da Timer(), ma per altri scopi, per cui si può benissimo lasciare così come il suo codice. ;)

thebol
20-06-2006, 15:21
Mumble mumble. nanoTime() viene richiamata direttamente anche in GameLoop.initPlayField().

quel valore è quello che inizializza nel costruttore randomGenerator(anzi i 2 RandomGenerator, uno per playField) che verra poi utilizzato in gioco

...
...
una veloce ricerca di dove viene utilizzato il costruttore randomGenerator senza prametri....
viene usato in qualche test, qualche factoryMethod, qualche costruttore inutilizzato ( :mad: da togliere !!! :mad: ) e in pattern :|

Pattern perciò non usa il seed generato da gameLoop........questo vuol dire che i pattern generati dai 2 playField sono diversi(era previsto jocchan?)

Il tutto si puo risolvere salvando il seed del pattern, facendogli usare il seed di gameLoop, oppure loggando le chiamata a nanoTime, oppure loggando il pattern iniziale, oppure boh :Prrr:

cdimauro
20-06-2006, 15:36
A prescindere da tutto, se usiamo sempre RandomGenerator per generare i seed (quindi anche per GameLoop, visto che adesso usa direttamente nanoTime), non risolviamo comunque il problema dei log dei seed? ;)

Poi che venga usato lo stesso seed di GameLoop o meno, è assolutamente indifferente. O no? C'è qualcosa che non sto ancora afferrando? :confused:

thebol
20-06-2006, 16:05
A prescindere da tutto, se usiamo sempre RandomGenerator per generare i seed (quindi anche per GameLoop, visto che adesso usa direttamente nanoTime), non risolviamo comunque il problema dei log dei seed? ;)


e gameLoop che usa nanoTime per inizializzare randomGenerator!
Questo è indispensabile perche il randomGenerator deve essere diverso per playField, ma devono essere inizializzati con lo stesso seed(quello trovato da gameLoop e passato)


Poi che venga usato lo stesso seed di GameLoop o meno, è assolutamente indifferente. O no? C'è qualcosa che non sto ancora afferrando? :confused:

Pattern potrebbe in effetti usare il seed di RandomGenerator. Ce solo un piccolo problema. L'unico oggetto che ha un link a randomGenerator e la Queue.

Piccolo paliativo.
Anche playField tiene il seed(non RandomGem), perche gli serve per loggare.

Ora il pattern viene creato in crushState, come variabile statica.
Variabile statica? :confused: :confused:
ebbene si :muro: (ci eravamo gia accorti di sta cosa, ma evidentemente nessuno si è ricordato di metterla apposto..)

mmm direi che possiamo partire da qua per mettere apposto il giro :asd:

cdimauro
20-06-2006, 16:42
OK, ma non siamo messi mica male: risolti questi problemi far loggare tutti i seed a RandomGenerator (passandogli il LogWriter alla creazione) diventerà una bazzecola, no? :D

thebol
20-06-2006, 17:01
OK, ma non siamo messi mica male: risolti questi problemi far loggare tutti i seed a RandomGenerator (passandogli il LogWriter alla creazione) diventerà una bazzecola, no? :D

in teoria si =D

Jocchan
20-06-2006, 17:04
KISS :D
Scegliamo la soluzione più semplice.

EDIT: mi ha detto un uccellino (Fek) che bisogna loggare le action, senza abomini tipo isLoggable... e che se logghiamo i tasti parte la mannaia del revert :eek:

71104
20-06-2006, 17:59
EDIT: mi ha detto un uccellino (Fek) che bisogna loggare le action, senza abomini tipo isLoggable... e che se logghiamo i tasti parte la mannaia del revert :eek: MHWUAHWUAHUWAHUWAHUWHAUWHAWUAUWA LO SAPEVO XDXDXDXDXDXDXD :asd: :Prrr: UGA BUGA :sofico: :banned: :Prrr: :D :D :D

71104
20-06-2006, 18:00
parto a razzo col "code hunting": strumenti di search di eclipse alla mano, fuori tutti i riferimenti a Grid: Action deve diventare l'unico modo per modificare Grid (e non state lì impalati, datemi na mano :Prrr: )

71104
20-06-2006, 18:25
ok ragazzi, fate update che ho cambiato alcune cose e adesso le dimensioni del log sono assolutamente minimali: vi sfido a ridurle ulteriormente ;)
giocando per qualche minuto è venuto un log di 2 mega; tanto dite? be', considerando che ogni volta che vedete scendere le gemme di un pixel vengono registrate svariate actions...

Bonfo
20-06-2006, 18:40
Ora il pattern viene creato in crushState, come variabile statica.
Variabile statica? :confused: :confused:
ebbene si :muro: (ci eravamo gia accorti di sta cosa, ma evidentemente nessuno si è ricordato di metterla apposto..)


L'ho fatto io per risolvere uno dei bug della FirstPlayable. Era il modo più semplice per avere un pattern uguale per entrambi i campi durante la partita....al punto che è uguale a tutte le partite della stessa istanza dell'applicazione.


EDIT: mi ha detto un uccellino (Fek) che bisogna loggare le action, senza abomini tipo isLoggable... e che se logghiamo i tasti parte la mannaia del revert :eek:


Mi fido...ma quando può viene a fare un salto per spiegarci questa scelta??
Siamo o non siamo qui per imparare :D :D

71104
20-06-2006, 19:20
Mi fido...ma quando può viene a fare un salto per spiegarci questa scelta?? il motivo percui vanno loggate le action l'ho già ampiamente spiegato anche io qualche post fa: serve un sistema di centralizzazione; poi, isLoggable è un abominio perché è una getType; il discorso di due interfacce separate Loggable/NonLoggable è già molto meglio, ma alla fine è la stessa cosa che usare una classe Query a parte, quindi per chiarezza tanto vale la seconda, ma forse neanche servirà, bisogna vedere; ed infine se logghiamo gli input cala la mannaia perché è un sistema troppo indiretto e alla fine potremmo scoprire che causa delle imprecisioni della riproduzione della partita; inoltre secondo me è troppo dispersivo: i seed vanno loggati a parte, e questo costituisce una sorta di eccezione nel design, di caso particolare: loggare solo una cosa (come le action) è una soluzione molto più lineare e di conseguenza (anche se forse adesso a voi non sembra) più semplice.

detto questo, farebbe piacere anche a me sentire ogni tanto che il Coach non se l'è data a gambe ma è ancora presente :mc: :D

thebol
20-06-2006, 19:34
EDIT: mi ha detto un uccellino (Fek) che bisogna loggare le action, senza abomini tipo isLoggable... e che se logghiamo i tasti parte la mannaia del revert :eek:

non sono d'accordo. Rischiamo di dover fare del lavoro in piu(refactoring) per una soluzione che è mesi che e stata proposta e non va avanti. In un momento in cui la "forza lavoro" non è certo abbondante.

Abbiamo una soluzione, semplice, che richiede poche modifiche e poco invasiva.
Invece dobbiamo centralizzare le modifiche a grid(cosa che ho gia detto, non ritengo essenziale se non per l'implementazione del log by action), implementare il log in maniera binaria(ha i suoi vantaggi, ma è meno portabile).

E sopratutto in questa maniera nel playback del log ci perdiamo tutte le cose che non sono modificare grid. Sia in ottica di debugging, sia in ottica di demoPlayer, questo mi sembra un bel limite.

Che alla fine potremmo scoprire che la versione byHandler produce delle imprecisioni nella riproduzione della partita, non vuol dire nulla, potrei dire lo stesso della versione byAction.

loggare il seed non è un eccezione, fa parte della partita. Non è obbligatorio loggare tutte cose uguali.


ps.una spiegazione sul perche fek preferisca la versione byAction, sarebbe gradita. Capisco che è il coach, e che ne sa a furgoni, ma sarebbe anche didatticamente interessante ;)

71104
20-06-2006, 20:20
loggare il seed non è un eccezione, fa parte della partita. Non è obbligatorio loggare tutte cose uguali. non è obbligatorio ma è più semplice: se devi loggare solo le action scrivi solo il codice per loggare le action; se invece devi loggare gli input, i seed e una miriade di altre cosette devi scrivere il codice per loggare gli input, i seed, e pure la miriade... è dispersivo!

e poi mamma mia quante storie per una funzionalità che dovrebbe essere di importanza in teoria secondaria... stiamo perndendo più tempo a discuterne che altro :(

a un certo punto a me va bene pure se facciamo come dite voi vista l'importanza così secondaria della cosa, però l'anno scorso noi il Coach l'abbiamo scelto apposta per queste situazioni: ci deve essere qualcuno che ascolta i pareri di tutti, decide e non si discute; "e chi non è d'accordo lo sarà col tempo".

anche se fek non scrive sul forum però penso che legga: ogni tanto vedo la lucetta verde.

Jocchan
20-06-2006, 21:03
non è obbligatorio ma è più semplice: se devi loggare solo le action scrivi solo il codice per loggare le action; se invece devi loggare gli input, i seed e una miriade di altre cosette devi scrivere il codice per loggare gli input, i seed, e pure la miriade... è dispersivo!

e poi mamma mia quante storie per una funzionalità che dovrebbe essere di importanza in teoria secondaria... stiamo perndendo più tempo a discuterne che altro :(

a un certo punto a me va bene pure se facciamo come dite voi vista l'importanza così secondaria della cosa, però l'anno scorso noi il Coach l'abbiamo scelto apposta per queste situazioni: ci deve essere qualcuno che ascolta i pareri di tutti, decide e non si discute; "e chi non è d'accordo lo sarà col tempo".

anche se fek non scrive sul forum però penso che legga: ogni tanto vedo la lucetta verde.

Caro Berto, non ti ho mai quotato con più gioia :D
Perfettamente d'accordo con te ^^

thebol
21-06-2006, 01:04
non è obbligatorio ma è più semplice: se devi loggare solo le action scrivi solo il codice per loggare le action; se invece devi loggare gli input, i seed e una miriade di altre cosette devi scrivere il codice per loggare gli input, i seed, e pure la miriade... è dispersivo!


certo ma se ora loggi solo le action, il tutto funziona?
no, quindi è dispersivo, fare un refactoring per far si che grid sia modificabile solo dalle action :)


e poi mamma mia quante storie per una funzionalità che dovrebbe essere di importanza in teoria secondaria... stiamo perndendo più tempo a discuterne che altro :(


è una funzionalità che è in ballo da un bel po, proprio per la complessita di realizzare un logger dipendente dalle action. sono 3 o 4 cicli che gira..
Non che sia impossibile, ma non si puo stravolgere il codice a ogni nuova funzionalità.(a meno che non ci siano altre soluzioni, escludendo barbatrucchi)


a un certo punto a me va bene pure se facciamo come dite voi vista l'importanza così secondaria della cosa, però l'anno scorso noi il Coach l'abbiamo scelto apposta per queste situazioni: ci deve essere qualcuno che ascolta i pareri di tutti, decide e non si discute; "e chi non è d'accordo lo sarà col tempo".

d'accordissimo, ma se prende una decisione che non condivido io lo dico, e cerco di motivarne il perche.

poi ovviamente, qualsiasi decisione va bene anche a me.

thebol
21-06-2006, 01:06
L'ho fatto io per risolvere uno dei bug della FirstPlayable. Era il modo più semplice per avere un pattern uguale per entrambi i campi durante la partita....al punto che è uguale a tutte le partite della stessa istanza dell'applicazione.


devono essere uguali, quindi possono prendere il seed del randomGenerator =D

cdimauro
21-06-2006, 07:58
x Alberto. Non sono d'accordo con le tue motivazioni.

Io vedo Diamonds come una funzione che, ricevendo gli stessi input (eventi, seed) allo stesso momento (gameturn, timestamp degli event) DEVE generare lo stesso output.

Non conosco altri "input" all'infuori degli eventi e dei seed, quindi non è che si possa gridare allo scandalo se ci sono due informazioni diverse da loggare anziché una (le action). Non si tratta, quindi, di "una miriade".

Non sono nemmeno d'accordo quando parli di chiarezza, di "indirezione" e di imprecisione di riproduzione: le modifiche al codice sarebbero minimali e molto chiare, dirette perché si agisce direttamente sugli input della "funzione" Diamonds, e infine la precisione di riproduzione è assolutamente garantita dall'accoppiata gameturn / timestamp.

Infatti il recording e il playback degli eventi te lo ritrovi anche nelle API di WIndows che ami tanto :D (i journal hook) che alcune software house usano per realizzare dei tutorial, registrando tutti gli eventi generati dal sistema (tasti premuti, movimenti del mouse, eventi di timer, ecc.) e riproducendoli poi sul PC dell'utente.

Anche il MAME, il più famoso emulatore, registra e riproduce tutti gli eventi di input ricevuti per permettere di riprodurre ESATTAMENTE una partita, che consente:
- allo staff di risalire in maniera precisa al momento in cui s'è verificato un eventuale bug nell'emulatore e correggerlo;
- al giocatore di mostrare gli amici quanto è stato bravo. :sofico:

Ma di esempi come questi te ne posso portare a tonnellate. ;)

Quindi le motivazioni di fek saranno sicuramente altre: avrà una visione diversa su come dev'essere implementato il log e il playback, che ci spiegherà al suo ritorno.

Nel frattempo lavoriamo sulle action, come ci ha chiesto di fare. Non credo che ci sia altro da discutere sull'argomento: la decisione è stata presa e procediamo in tal senso.

Per il resto, sono d'accordo con thebol e Bonfo. :)

P.S. Il coach è presente, non se l'è data a gambe. Non può scrivere, ma legge tutto. ;)

thebol
21-06-2006, 08:21
P.S. Il coach è presente, non se l'è data a gambe. Non può scrivere, ma legge tutto. ;)

solo ora ho visto il suo nuovo user title :doh:

Bonfo
21-06-2006, 09:30
solo ora ho visto il suo nuovo user title :doh:
:confused: :confused:

Edit: ho capito adesso :doh:

:D :D

71104
21-06-2006, 11:12
ROTFL UN'ALTRA VOLTA :rotfl: :rotfl: :rotfl:
ma che mattacchione quel fek :D :D :D

cdimauro
21-06-2006, 11:14
Guarda, mi sarei incazzato come una bestia pure io con quel tizio. Non commento oltre per evitare anch'io ripercussioni.

VICIUS
21-06-2006, 11:16
ROTFL UN'ALTRA VOLTA :rotfl: :rotfl: :rotfl:
ma che mattacchione quel fek :D :D :D
Smetti di ridere come un lamer e torna a lavorare su Diamonds! :mad: :D

ciao ;)

Bonfo
21-06-2006, 11:40
ROTFL UN'ALTRA VOLTA :rotfl: :rotfl: :rotfl:
ma che mattacchione quel fek :D :D :D

:rotfl: :rotfl: :rotfl:

EDIT: ma per quanto tempo???

VICIUS
22-06-2006, 22:55
Ci sono news?
Possibile che ogni volta che scompare la minaccia di fek che vi spezza le ditine vi adagiate sugli allori? Jocchan tira fuori la grattugia! :D

ciao ;)

Bonfo
23-06-2006, 00:11
Sono nella cacca :coffee: :coffee:

Posso garantire solo il task bisettimanale...perchè alemno quello lo voglio fare :muro:

Per il resto... :cry: :cry:

71104
23-06-2006, 02:17
sto refattorizzando GemQueue e test relativi; committo quando ho tutto verde, per ora mi falliscono due test che devo rifare daccapo e sono difficili perché devo ancora capire come devo prendere i numeri da passare al mock per estrarre le gemme che voglio io. questo refactoring è dovuto all'eliminazione di quell'abominio di DynamiteCountAction, e successivamente ho in mente di refattorizzare anche tutte le action in modo da renderle l'unico modo di modificare Grid.

Jocchan
23-06-2006, 08:32
Sto potenziando lo sbucciaginocchia.

Bonfo
24-06-2006, 10:59
DIAMOCI SOTTO TEAM :D

Allora, proprio con il pensiero dello sbucciaginocchia rilancio il da farsi:
- Bisogna assolutmante arrivare ad avere BigGem come un Droppable.
- fatto questo grid deve cambiare ...e dovrebbe cambiare tanto.
- A quel punto ci sono gli state e le Action che ci aspettano.

Siccome siamo in stato di crisi:
- Scrivere sul forum, sempre, per qualsiasi cagata.
Se qualcosa non va e non capiamo, non perdiamo mezzora in tentatvi, scriviamo e, mentre continiuamo a tentare, c'è la speranza che qualcuno risolva il problema.
- Essere presenti sul forum. Anche per gli universitri che si stanno sapccando sotto gli esami ( :cry: ), c'è il tempo ogni 2 ore di fare un salto e scrivere.
- Coordinarsi il più possibile.
E qui ritrona in campo il forum come base...poi gli istant messanger aiutano ;)

Bonfo
24-06-2006, 11:00
Provo a guardare come gestire al sprite di BigGem.
Ufo aveva pensato a TiledSprite.
Vediamo ;)

EDIT:
ecco cosa bisognerebbe fare per risolvere questo e fare in modo che anche le bigGem diventino Bright.

SONO PROPOSTE. (l'1 e il 2 non sono sequenziali)

BigGemSprite.1: mettere a posto la gestione di Bright dentro Sprite (uno stateModifier??).
BigGemSprite.2: realizzare la classe TiledSprite estendendo Sprite.(Vedi dopo)
BigGemSprite.3: ineserire la TiledSprite in BigGem
BigGemSprite.4: BigGem non è più un drawable. Coreggere tutti gli utilizzi di BigGem come drawable.

TiledSprite: praticamente deve essere una sprite a cui gli si chiede di disegnarsi e lei sfrutta le informazioni per disgenare N elementi invece che 1 come fa sprite. Il punto chiave è la gestione delle posizioni.
Se tutto va comer deve andare drovebbe sparire BigGemTileType.

Provo a vedere che posso fare con l'1.

Bonfo
24-06-2006, 11:36
Managgia Vic, a te e ai tuoi Modifiers :D :D
Non li capisco :cry:

Ora Bright è gestito da Sprite e fa schifio.
Se io volessi utilizzare uno stateModifier che dovrei fare??

Vic rispondi :ave: :ave:

71104
24-06-2006, 13:00
occhio che anche io sto refattorizzando Grid... sto rendendo Action l'unico modo per modificare Grid, così quasi tutti i metodi pubblici di Grid se ne andranno e avremo enormi semplificazioni esattamente dove ne avevamo bisogno ;)

Bonfo
24-06-2006, 14:36
OK...messaggio ricevuto.

Bonfo
24-06-2006, 16:26
Mi sono fermato nell'esplorare Bright.
Finchè non capisco bene i modifier non so bene come muovermi.
(@Vic: quando passi cercami su MSN, facciamo 2 chiacchere e vedo di mettere a posto questa cosa).

Per TiledSprite non ho avuto grande successo. :(
Ho revertato tutto.
Stasera ci riprovo :asd:

71104
24-06-2006, 16:47
il refactoring delle actions procede bene; ci sono ancora tante cose da fare ma procede bene. affinché una action sia l'unico modo per... basta mi sono stufato di ripeterlo :D avete capito no? affinché ciò sia vero il metodo di applicazione della action ha cambiato di significato: se prima applyOn era fatto per essere applicato tramite forEachDroppable su ogni elemento della griglia, adesso c'è un altro metodo, apply, che serve semplicemente ad applicare la action sulla griglia. questo metodo riceve in ingresso l'oggetto Grid e la lista degli elementi, poiché una action riceve accesso speciale al membro privato gridElements di Grid; dal momento che solo la action riceve come parametro questo membro privato di Grid, la action è l'unico modo ecc. ecc.
come design mi sembra perfetto, no? :cool:
c'è anche da dire che, siccome spesso è comunque necessario applicare la action su ogni singolo droppable facendo un'iterazione, allora ho comunque mantenuto il meccanismo di forEachDroppable e di applyOn, spostando però forEachDroppable in AbstractDroppableAction (consideratelo come una specie di "supporto di base" da parte di AbstractDroppableAction per iterazioni su tutta la matrice di elementi) e rendendo protetto il metodo applyOn (prima era pubblico).

Bonfo
24-06-2006, 18:58
Mi piace...
...non ho ancora visto il codice, ma il ragioamento mi sembra ottimo ;)

jappilas
24-06-2006, 20:50
il refactoring delle actions procede bene; ci sono ancora tante cose da fare ma procede bene.
:)
il metodo di applicazione della action ha cambiato di significato: se prima applyOn era fatto per essere applicato tramite forEachDroppable su ogni elemento della griglia, adesso c'è un altro metodo, apply, che serve semplicemente ad applicare la action sulla griglia.
se il metodo era chiamato execute() le "Grid Action" facevano pandàn con le MenuAction... :asd:
come design mi sembra perfetto, no? :cool: mi piace assai :)
(avrei voluto riuscire a concepirlo io :mbe: )

Bonfo
25-06-2006, 02:16
Ho fatto un po' di prove per realizzare TiledSprite per le BigGem.
Ci sarei anche riuscito, ma ho un po' di problemi con Position. :(

Mi sa che sto accavallando qualcosa, il che mi puzza di design sbagliato. :muro:

Comunque domani appena ho un po' di tempo faccio il secondo giro di prova.
Ora sono cotto...domani provo a fare un resconto un po' più competo. :zzz:

EDIT: mi è venuta una ideona e domani la provo.
Se tutto va bene la DrawAction muore e il tutto si ridurra ad un:

for(Droppable droppable:gridElements)
{
droppable.getSprite().draw(engine);
}


naturalmente le BigGem diventano grid element :D :D
...il che vuol dire l'arrayList di BigGem che sparisce :asd: :asd:

VICIUS
25-06-2006, 09:42
Managgia Vic, a te e ai tuoi Modifiers :D :D
Non li capisco :cry:

Ora Bright è gestito da Sprite e fa schifio.
Se io volessi utilizzare uno stateModifier che dovrei fare??

Vic rispondi :ave: :ave:
Non li capisci perché qualcuno a cancellato parte degli state modifier, che ora non esistono più, ma si è scordato dei pezzi in giro cosi sembra che ci sono ancora :D

ciao ;)

71104
25-06-2006, 11:12
può essere che sia stato io :p
ma di sicuro non in questo refactoring, se l'ho fatto l'ho fatto un bel po' di tempo fa...

Bonfo
25-06-2006, 13:43
Non li capisci perché qualcuno a cancellato parte degli state modifier, che ora non esistono più, ma si è scordato dei pezzi in giro cosi sembra che ci sono ancora :D

ciao ;)

Quindi... ?? :uh: :wtf:

71104
25-06-2006, 13:55
qualcuno si sbrighi a trasformare le BigGems in Droppable e ad eliminare quella bigGemList che ce n'è bisogno come er pane :help:
dai su, che se siamo bravi possiamo uscire da questa crisi in maniera brillante e molto più forti di prima :D

Bonfo
25-06-2006, 14:24
qualcuno si sbrighi a trasformare le BigGems in Droppable e ad eliminare quella bigGemList che ce n'è bisogno come er pane :help:
dai su, che se siamo bravi possiamo uscire da questa crisi in maniera brillante e molto più forti di prima :D

Detto: Fatto...o quasi.
Abbiamo TiledSprite!! :sofico:
O meglio, ho una implementazione che funziona.
Ora devo:
- mettere a posto dei test vecchi (usano dei metodi pubblici che devono essere privati)
- sviluppare TiledSprite in TDD

Dopo questa mossa il passo verso l'eliminazione di BigGemList è mooolto vicino :yeah:

P.S.: mi sa che per oggi è impossibile che riesca a fare il commit :cry:

71104
25-06-2006, 15:13
ehm, almeno fai un bell'updatone che sennò ti tocca fare un merge che la metà basta :D

in due giorni e mezzo di "crisi" ho fatto complessivamente 20 commit asd :D

Bonfo
25-06-2006, 16:47
ehm, almeno fai un bell'updatone che sennò ti tocca fare un merge che la metà basta :D

in due giorni e mezzo di "crisi" ho fatto complessivamente 20 commit asd :D

Ho notato :asd: :asd: :asd:

Bonfo
25-06-2006, 17:32
Ho fatto un paio di conti.
L'unica data certa che posso dare per il commit di TiledSprite è mercoledì :(
Cerco di anticipare il prima possibile, ma non posso garantire nulla.

Se volete vi passo l'implemntazione.
Funziona, ma non è venuta fuori da una prova, non da TDD :Prrr:
Quindi vale meno di un soldo bucato :doh:

71104
25-06-2006, 20:48
Se volete vi passo l'implemntazione.
Funziona, ma non è venuta fuori da una prova, non da TDD :Prrr:
Quindi vale meno di un soldo bucato :doh: puoi scrivere la prova qui sul forum? che qui tocca sbrigarsi: mi dici esattamente cosa deve fare questa classe e per cosa è concepita, e la rifacciamo entrambi in TDD: il primo che la finisce la committa

cdimauro
26-06-2006, 08:05
Io sono sempre convinto che dovremmo avere un'interfaccia unica per tutti gli oggetti che interagiscono fra di loro e con la griglia, e che si "comportano" in maniera diversa a seconda della loro "natura".

Bonfo
26-06-2006, 09:50
puoi scrivere la prova qui sul forum? che qui tocca sbrigarsi: mi dici esattamente cosa deve fare questa classe e per cosa è concepita, e la rifacciamo entrambi in TDD: il primo che la finisce la committa

Il problema è che AbstractDroppable e BigGem si disegano in modo diverso: la prima passa la responsabilità a sprite mentre l'altra fa da sè implementando drawable.

Sono possibili 2 scelte:
- anche AbstractDroppable diventa un drawable;
- BigGem si appoggia su una Sprite "potenziata" che è in grado di gestire il disegno mediante Tile.

Ecco cosa deve fare TiledSprite...sgravare dal disegno BigGem.
Ovvero l'invocazione deve cambiare da BigGem.draw() a BigGem.getSprite().draw()

In BigGem c'è tutto fatto...pasta copiare :asd:

Il problema sono i test. Molte cose sono testate attraverso metodi pubblici che devono essere privati...bisognerebbe riuscire a testare tutto mediante il solo metodo draw :(

Praticamente TestBigGemDrawing deve diventare TestTiledSprite :D

Vabbè...vi passo l'implemenatzione ;)

Bonfo
26-06-2006, 10:08
Io sono sempre convinto che dovremmo avere un'interfaccia unica per tutti gli oggetti che interagiscono fra di loro e con la griglia, e che si "comportano" in maniera diversa a seconda della loro "natura".

Per adesso BigGem e AbstractDroppable si stanno unificando...a forza di :boxe:, ma si stanno unendo.

Mancherebbe GemsPair... :fiufiu:

71104
26-06-2006, 11:03
Il problema sono i test. Molte cose sono testate attraverso metodi pubblici che devono essere privati...bisognerebbe riuscire a testare tutto mediante il solo metodo draw :( ALT! capito perfettamente il problema; quei metodi non devono assolutamente rimanere pubblici, il test case da te citato deve probabilmente essere rifatto da zero. per testare TiledSprite è sufficiente progettare un mock dell'engine che memorizzi tutti i quadrati disegnati; dici che una cosa del genere ti aiuterebbe nei test? se si provo a farlo io.

71104
26-06-2006, 11:04
Io sono sempre convinto che dovremmo avere un'interfaccia unica per tutti gli oggetti che interagiscono fra di loro e con la griglia, e che si "comportano" in maniera diversa a seconda della loro "natura". il mio refactoring delle actions è un primo passo :p

thebol
26-06-2006, 11:13
il mio refactoring delle actions è un primo passo :p
come hai pensato di fare con la gravita?
se non sbaglio viene prevalentemente settata negli state, ora come ora..

cdimauro
26-06-2006, 11:23
Per adesso BigGem e AbstractDroppable si stanno unificando...a forza di :boxe:, ma si stanno unendo.

Mancherebbe GemsPair... :fiufiu:
OK. E poi trattiamo tutti questi oggetti (Gem, BigGem, GemsPair, ecc.) come Droppable & Drawable?

cdimauro
26-06-2006, 11:24
ALT! capito perfettamente il problema; quei metodi non devono assolutamente rimanere pubblici, il test case da te citato deve probabilmente essere rifatto da zero. per testare TiledSprite è sufficiente progettare un mock dell'engine che memorizzi tutti i quadrati disegnati; dici che una cosa del genere ti aiuterebbe nei test? se si provo a farlo io.
MockEngine funziona già così. ;)

public int getNumberOfQuadsDrawn()

:D
il mio refactoring delle actions è un primo passo :p
Speriamo non sia l'ultimo. :p C'è tanto lavoro da fare... :muro:

71104
26-06-2006, 11:26
MockEngine funziona già così. ;)

public int getNumberOfQuadsDrawn() non intendevo solo quello: è necessario poter riottenere anche i dati relativi ai singoli quadrati oltre al numero complessivo di quadrati disegnati, però mi sono accorto che il mock attuale fa anche questo :)

Bonfo, problema risolto: praticamente devi riscrivere i test per il disegno "tiled" usando il MockEngine ;)

Bonfo
26-06-2006, 13:04
non intendevo solo quello: è necessario poter riottenere anche i dati relativi ai singoli quadrati oltre al numero complessivo di quadrati disegnati, però mi sono accorto che il mock attuale fa anche questo :)

Bonfo, problema risolto: praticamente devi riscrivere i test per il disegno "tiled" usando il MockEngine ;)

Ottimo.
Se avessi tempo ... :cry: :cry: :muro: :muro:

Io mercoledì mattina ho un esame e sono nel rush finale...quindi anche la testa è poco lucida.
O lo fa qualcun'altro al posto mio, o lo si fa in pair oppure si aspetta mercoledì pomeriggio.

A me va bene tutto ;)

71104
26-06-2006, 14:02
hum, allora mi sa che aspetteremo mercoledì pomeriggio... :\
io l'esame ce l'ho domani; solitamente ogni tanto interrompo lo studio e faccio qualche modifica su DC, ma oggi mi pare difficile

Bonfo
26-06-2006, 15:07
hum, allora mi sa che aspetteremo mercoledì pomeriggio... :\
io l'esame ce l'ho domani; solitamente ogni tanto interrompo lo studio e faccio qualche modifica su DC, ma oggi mi pare difficile

Capito.
Allora...provo a fare un test ogni tanto.
Non si sa mai che riesco ad anticipare i tempi :(

VICIUS
26-06-2006, 19:35
Ho dato un'altra breve occhiata al file di log e sono rimasto decisamente colpito dalla dimensione con cui cresce il file. Si parla per la precisione di 145 KByte di testo ogni secondo. Capisco che volevamo loggare per gameturn e solo gli stati ma se questo è il risultato non è una soluzione accettabile e ci conviene implementare la soluzione di cesare. Oltre a pigliare 50mbyte per una singola partita di 3 minuti la cpu è balzata da 17/20% a 80/85% e il gioco scatta visibilmente qui sulla mia macchina.

ciao ;)

71104
26-06-2006, 21:33
vedrai che migliorerà: molte delle actions che ci sono per ora sono "sballate", nel senso che non devono essere actions. al limite posso rifare LogWriter in modo che non usi la serializzazione di Java ma un sistema nostro, ma scrivere un file di testo piuttosto che un file binario (come propone cesare) non è certo la soluzione più ottimizzata.

PS: avrai forse notato che in uno dei miei commit ho scritto una cosa tipo "ridotte le dimensioni del file di log, adesso sono minime"; intendevo dire che non avrei potuto ridurle ulteriormente continuando ad usare la serializzazione di Java e le actions attuali; cambiando questi due fattori (preferibilmente solo il secondo) le dimensioni si riducono eccome... :)
potrebbe essere un problema notevole invece quello delle prestazioni, ma da quanto ho capito attualmente il programma produce due tipi di log: direi che i due log di testo playerOne.log e playerTwo.log si possono anche eliminare...

cdimauro
27-06-2006, 07:27
La soluzione che ho proposto io la possiamo adottare quando vogliamo, perché è molto semplice e si implementa in poco tempo.

Per adesso lasciamo che Alberto finisca il suo lavoro di rifattorizzazione del codice, scartando anche le action che non si devono loggare, e vediamo a quanto arriva il log.

Il problema serio è rappresentato dall'eccessivo utilizzo di CPU, ma vedremo poi col codice finale se sarà ancora così rilevante o accettabile.

Alberto, per quanto riguarda i log, secondo me è meglio fare a meno delle routine de/serializzazione di Java: c'è troppo overhead (non soltanto per lo spazio occupato).

Quando logghi le action, il "controllo della situazione" ce l'hai tu: scrivi in un file le informazioni minimali per poter ricostruire l'azione.
E' indifferente che tu lo faccia usando un file di testo o un file binario: scegli pure quello che ti risulta più comodo / conveniente.

La mia prima scelta in casi come questo è quasi sempre un file di testo perché preferisco produrre informazioni leggibili, ed eventualmente modificabili velocemente col blocco note, perché mi aiuta molto col debug. Ma è una mia scelta, appunto (e tra l'altro non definitiva: si può sempre adottare un formato binario a debug concluso ;)).

VICIUS
27-06-2006, 11:29
vedrai che migliorerà: molte delle actions che ci sono per ora sono "sballate", nel senso che non devono essere actions. al limite posso rifare LogWriter in modo che non usi la serializzazione di Java ma un sistema nostro, ma scrivere un file di testo piuttosto che un file binario (come propone cesare) non è certo la soluzione più ottimizzata.

PS: avrai forse notato che in uno dei miei commit ho scritto una cosa tipo "ridotte le dimensioni del file di log, adesso sono minime"; intendevo dire che non avrei potuto ridurle ulteriormente continuando ad usare la serializzazione di Java e le actions attuali; cambiando questi due fattori (preferibilmente solo il secondo) le dimensioni si riducono eccome... :)
Ok. Allora aspetto un'altro po'. Vediamo se raggiungi livelli accettabili.

potrebbe essere un problema notevole invece quello delle prestazioni, ma da quanto ho capito attualmente il programma produce due tipi di log: direi che i due log di testo playerOne.log e playerTwo.log si possono anche eliminare...
Il vecchio sistema di log va eliminato. Ma quello che mi puzza è il fatto che nel log vanno a finire segnalazioni di centinaia di eccezioni per NotSerializable. Le ho contate solo ad occhio ma sembrano piu di 50 per ogni secondo. Tutte queste eccezioni potrebbero tranquillamente essere la causa del rallentamento e di un bel po di banda per il log.

ciao ;)

71104
27-06-2006, 16:45
Il vecchio sistema di log va eliminato. Ma quello che mi puzza è il fatto che nel log vanno a finire segnalazioni di centinaia di eccezioni per NotSerializable. Le ho contate solo ad occhio ma sembrano piu di 50 per ogni secondo. Tutte queste eccezioni potrebbero tranquillamente essere la causa del rallentamento e di un bel po di banda per il log. in effetti si, le avevo notate anch'io... probabilmente la JVM non riesce a completare tutte le richieste di scrittura perché sono troppe...

forse in effetti è meglio lasciar perdere sta serializzazione di Java, mi sa che darò un'occhiata a come funzionava quella di MFC che andava a meraviglia :mbe:

Bonfo
28-06-2006, 00:00
in effetti si, le avevo notate anch'io... probabilmente la JVM non riesce a completare tutte le richieste di scrittura perché sono troppe...

forse in effetti è meglio lasciar perdere sta serializzazione di Java, mi sa che darò un'occhiata a come funzionava quella di MFC che andava a meraviglia :mbe:

...scusa la domanda da ignorante: ma abbiamo proprio bisogno della serializazzione?? :mbe:

Ovvero dobbiamo salvare proprio quell'istanza di Action o, piuttosto, non ci basta avere le informazioni per istanziarne una?? :rolleyes:

71104
28-06-2006, 02:04
è la stessa cosa, solo che nella tua seconda ipotesi dovrei fare io un lavoro che fa già uno strumento nativo di Java; comunque lo sto facendo, perché lo strumento nativo di Java il lavoro lo fa male (troppo overhead)

Bonfo
28-06-2006, 18:25
Cappero ragazzi: sono in ritardo.

Non riesco a committare TiledSprite entro oggi.
Ho fallito la deadline che vi avevo comunicato...mi sgrido da solo :ncomment:

Spero di fare al più presto possibile...
:ave: :ave: :ave:

71104
29-06-2006, 03:05
le dimensioni del log adesso sembrano veramente all'osso; rimane un problema di performance che dovrebbe sparire non appena eliminato il vecchio sistema di logging. il log cresce all'incirca a 12-13 kb al secondo (contro i 150 di prima se ricordo bene, e contro gli N megabyte al secondo della primissima versione :D)

ho provato a fare qualche esperimento per introdurre una classe LogReader, e ho concluso che non ci serve: ci serve solo la classe per il playback. la classe LogReader servirebbe se avessimo il tempo e la possibilità di implementare il buffering del log in modo da poter scorrere la partita a piacere, ma credo che non siamo proprio in condizioni, quindi cdimauro passiamo direttamente al playback.

@cdimauro, ti spiego come deve funzionare: in modalità di playback in qualche modo il gameloop anziché chiamare i metodi di update dei due playfield deve chiamare una sorta di doOneStep della classe di playback; questo metodo deve leggere dal log tutti i token di tipo ActionToken e deve fermarsi quando arriva ad un TurnMarkerToken; fintanto che legge action tokens deve applicare alle griglie la action letta, quando legge un turn marker il metodo deve ritornare al chiamante, cioè il gameloop, che attenderà la fine del turno.

per realizzare il tutto secondo me sarebbe una buona cosa introdurre un AbstractGameLoop e derivare un PlaybackGameLoop oltre al GameLoop originario. tutta la roba in comune ovviamente la metti in AbstractGameLoop.

ora un problema: il LogWriter memorizza le actions ma non memorizza a quale delle due griglie è stata associata una action... nella formulazione del task originale questo problema non era stato previsto, e richiederà un grosso e noioso lavoro su parametri e prototipi in classi varie :cry:

Jocchan, VICIUS, questo lavoro si sta dilungando parecchio e penso che nel frattempo qualcun altro potrebbe tranquillamente svolgere altri task percui non potreste metterci in rilievo un elenco di features da implementare? :help:
sennò non finiamo mai :help:

non è che si potrebbe momentaneamente lasciar perdere il sistema dei task? e magari riprenderlo quando il progetto riaprirà ufficialmente? ^^'
perché quando si ha la lista delle cose da fare il team lavora meglio :D
è più divertente spuntare le entries della lista una dopo l'altra piuttosto che fare una cosa come i task che ricordano tanto dei compiti per casa ^^

71104
29-06-2006, 03:10
dimenticavo: cdimauro, il sistema di playback secondo me è possibile realizzarlo senza if, perciò se a un certo punto devi mettere un if che non riesci ad eliminare dimmelo :D

71104
29-06-2006, 03:13
Cappero ragazzi: sono in ritardo.

Non riesco a committare TiledSprite entro oggi.
Ho fallito la deadline che vi avevo comunicato...mi sgrido da solo :ncomment:

Spero di fare al più presto possibile...
:ave: :ave: :ave: se a bloccarti è qualcuno di quei test del caucaso fregatene e commentali: il refactoring che stai facendo è troppo importante, semmai quando hai committato guardo il diff e cerco di correggere io qualche test (ma più che altro è probabile che rifarò l'intero case fatto bene -.-')

cdimauro
29-06-2006, 07:29
Nella pausa pranzo do un'occhiata al codice.

Però se non c'è un'associazione precisa e veloce a quale griglia è associata un'azione, ci saranno problemi nella realizzazione del player...

Comunque se devo introdurre una classe PlaybackGameLoop preferisco a questo punto realizzare il LogReader da cui attingere: mi sembra una soluzione più leggibile.

Quanto agli if, non dovrei averne bisogno: non mi piace il codice "get type like". :p

Bonfo
29-06-2006, 17:24
se a bloccarti è qualcuno di quei test del caucaso fregatene e commentali: il refactoring che stai facendo è troppo importante, semmai quando hai committato guardo il diff e cerco di correggere io qualche test (ma più che altro è probabile che rifarò l'intero case fatto bene -.-')

No no, oltre a quello ho proprio fatto male i conti :(

71104
30-06-2006, 01:16
COLPO DI GENIO!!! mi è venuto in mente come fare per differenziare nel log le actions relative all'una o all'altra griglia!! :yeah:
quanto mi piace programmare senza if MWHAUHWUAHUWAHUWHAUWA :sbonk:

EDIT: prima di applicarlo però servirà parecchio refactoring... sarà dura far funzionare questo sistema di logging

cdimauro
30-06-2006, 07:18
Allora aspetto che tu finisca, perché attualmente leggendo il solo log non ho modo di smistare le action alle griglie di competenza. ;)

^TiGeRShArK^
30-06-2006, 11:06
Ok. Allora aspetto un'altro po'. Vediamo se raggiungi livelli accettabili.


Il vecchio sistema di log va eliminato. Ma quello che mi puzza è il fatto che nel log vanno a finire segnalazioni di centinaia di eccezioni per NotSerializable. Le ho contate solo ad occhio ma sembrano piu di 50 per ogni secondo. Tutte queste eccezioni potrebbero tranquillamente essere la causa del rallentamento e di un bel po di banda per il log.

ciao ;)
:stordita:
ah ecco.....
allora si verificava quello che dicevo nell'altro topic... :mbe:
mi pareva un pò impossibile che risucisse a serializzare oggetti con campi non serializzabili..:stordita:
Mi sa che se si vuole continuare la strada del log con la serializzazione di java bisogna decidere chiaramente cosa ci serve per mantenere le informazioni essenziali dei vari oggetti, dichiarando tutti gli altri campi transient.....
e ovviamente i campi non dichiarati transient devono essere tutti oggetti serializzabili, pena eccezioni a catena di cui sopra :p

thebol
30-06-2006, 11:09
spostato dall'altro thread...

:stordita:
sono sempre + confuso sul codice del log.....
come fa a funzionare la serializzazione se gli oggetti serializzati contengono campi non serializzabili e neanche transient?
non spara eccezioni a palla? :mbe:
e inoltre, anche correggendo questo problema, non è troppo pesante serializzare anche oggetti pesanti del calibro di istanze di engine?:confused:

si, ma è stata scelta quest'opzione.
Quano (e se) si valutera che è troppo pesante, si provera qualcos'altro.

ps.sono cmq d'accordo con te. 71104 sta facendo refactoring su refactoring per arrivare alla gestione del log, quando l'avremmo potuto avere da molto meno. Questo non per dire che i refactoring non andavano fatti,(non voglio tornare a discutere su questa cosa..), ma per dire che per quanta riguarda il task sul log, lo si poteva risolvere per vie piu brevi. Poi magari non funzionava, ma ci si metteva molto meno(anzi, ci si mette poco anche adesso) a farlo.

Ripeto, questo a prescindere dal fatto che i refactoring fatti siano leciti o no.

ps.si potrebbe lasciar perdere la serializzazione e continuare a farlo driven by action, serializzando le info necessarie per le action in stringhe. Non so quanto sia fattibile(un costruttore per le action by string, oppure un metodo per le action che accetti una stringa, e inizializzi il proprio stato, oppure boh)

^TiGeRShArK^
30-06-2006, 11:22
spostato dall'altro thread...



si, ma è stata scelta quest'opzione.
Quano (e se) si valutera che è troppo pesante, si provera qualcos'altro.

ps.sono cmq d'accordo con te. 71104 sta facendo refactoring su refactoring per arrivare alla gestione del log, quando l'avremmo potuto avere da molto meno. Questo non per dire che i refactoring non andavano fatti,(non voglio tornare a discutere su questa cosa..), ma per dire che per quanta riguarda il task sul log, lo si poteva risolvere per vie piu brevi. Poi magari non funzionava, ma ci si metteva molto meno(anzi, ci si mette poco anche adesso) a farlo.

Ripeto, questo a prescindere dal fatto che i refactoring fatti siano leciti o no.

ps.si potrebbe lasciar perdere la serializzazione e continuare a farlo driven by action, serializzando le info necessarie per le action in stringhe. Non so quanto sia fattibile(un costruttore per le action by string, oppure un metodo per le action che accetti una stringa, e inizializzi il proprio stato, oppure boh)
no ma il punto fondamentale è un altro a parte le dimensioni....
non spara eccezioni a raffica come diceva vicius quando vengono serializzati oggetti contenenti campi non serializzabili?
Proprio per quel motivo, oltre che per ridurre le dimensioni del log, sono necessari i campi transient (e ovviamente i campi che non sono transient devono essere serializzabili).

^TiGeRShArK^
30-06-2006, 11:26
X cesare

ecco appunto...
non so quali action serializzi, ma praticamente tutte quelle che ho guardato contenevano dei campi non serializzabili......
e viste le eccezioni notate da vicius mi pare che la causa sia proprio questa....
Giustamente Java non riesce a serializzare degli oggetti che contengano campi non serializzabili e che non siano transient...
cmq ora devo scappare...
continuiamo dopo il discorso...
ma x favore vedete se riuscite a verificare se ancora spara queste eccezioni xkè in quel caso il problema è proprio questo dei campi interni delle varie classi serializzate :p

cdimauro
30-06-2006, 11:33
Il problema è proprio questo Danilo: la serializzazione non serve, ma soprattutto porterà a dei disastri, visto che abbiamo a che fare con dati oggettivamente non serializzabili (tanto per fare un esempio: stiamo usando le JNI).

Proprio il fatto che vengano generate delle eccezioni (che, come dice Fran, sono appunto "eccezioni" :p), è un chiaro sintomo che c'è qualcosa di profondamente sbagliato in quest'approccio.

Soprattutto è concettualmente inutile andare memorizzare informazioni come anche la BigGemList, visto che quest'informazione dovrebbe essere già presente correttamente nella griglia SE il playback delle action è avvenuto correttamente (in sostanza: la BigGemList è figlia dell'evolversi della griglia. Non c'è bisogno di portarcela dietro ogni volta, perché si "genera" / "modifica" "automaticamente").

Non aggiungo altro, visto che, anche nel caso in cui finalmente si arrivasse a completare i task per la scrittura, lettura ed esecuzione delle action, comunque non raggiungeremmo il vero obiettivo di questa storia (che non è certo quello di scrivere, leggere ed eseguire action).

Le rifattorizzazioni, comunque, vanno fatte: su questo sono d'accordissimo.

71104
30-06-2006, 15:28
no ma il punto fondamentale è un altro a parte le dimensioni....
non spara eccezioni a raffica come diceva vicius quando vengono serializzati oggetti contenenti campi non serializzabili? ehm, scusate... :fagiano:
1) le eccezioni a palla da me non le spara più da un bel po'
2) le dimensioni del log ora vanno a una dozzina di kb al secondo (mediamente) contro gli svariati megabyte di prima; qualsiasi cosa si faccia non penso si possa ridurre ulteriormente: memorizziamo solo lo stretto indispensabile ed in formato binario...

71104
30-06-2006, 15:30
Soprattutto è concettualmente inutile andare memorizzare informazioni come anche la BigGemList e mica le memorizzo infatti... :fagiano: :fagiano: :fagiano:

Non aggiungo altro, visto che, anche nel caso in cui finalmente si arrivasse a completare i task per la scrittura, lettura ed esecuzione delle action, comunque non raggiungeremmo il vero obiettivo di questa storia (che non è certo quello di scrivere, leggere ed eseguire action). :read:

cdimauro
30-06-2006, 15:35
e mica le memorizzo infatti... :fagiano: :fagiano: :fagiano:
L'ultimo codice del repository riporta questo:
private void writeObject(ObjectOutputStream out) throws IOException
{
out.writeObject(bigGems);
}

private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
{
bigGems = (BigGemList)in.readObject();
}

per CreateNewBigGemsAction.
:read:
Sì, ho letto, e torno a ripetere la stessa cosa: non si raggiungerebbe comunque il vero obiettivo di questi task.

Comunque te ne renderai conto quando finiremo tutto (e dovremo di nuovo andare a rimetterci mano).

71104
30-06-2006, 15:40
L'ultimo codice del repository riporta questo:
private void writeObject(ObjectOutputStream out) throws IOException
{
out.writeObject(bigGems);
}

private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
{
bigGems = (BigGemList)in.readObject();
}

per CreateNewBigGemsAction. ah quelle, avevo capito la lista presente in Grid... e allora cambia quei metodi, anche se in realtà credo che quelle vadano memorizzate; comunque non è un buon motivo per cambiare approccio; tu cosa suggerisci al posto dell'utilizzo della serializzazione di Java?

cdimauro
30-06-2006, 16:01
ah quelle, avevo capito la lista presente in Grid... e allora cambia quei metodi, anche se in realtà credo che quelle vadano memorizzate;
Leggi il mio messaggio di risposta a Danilo: ho scritto perché non sarebbe necessario. ;)
comunque non è un buon motivo per cambiare approccio; tu cosa suggerisci al posto dell'utilizzo della serializzazione di Java?
A tua scelta: semplice file di testo o binario che riporti esclusivamente:
- inizio di un turno;
- identificativo dell'azione più eventuali parametri NECESSARI (BigGemList non lo è, a mio avviso, come ho riportato sopra).

Questo dovrebbe semplificare e risolvere i problemi con la serializzazione, ma rimangono gli altri di cui ho parlato alla fine (il vero scopo non verrebbe comunque raggiunto).

Bonfo
30-06-2006, 16:05
(il vero scopo non verrebbe comunque raggiunto).

E parla chiaro!! :mad: :asd: :asd:
Quale sarebbe il vero scopo??

cdimauro
30-06-2006, 16:19
Riprodurre esattamente una partita. :)

A proposito di partite: vado a vedermi Germania - Argentina. :D

Buon fine settimana a tutti :)

71104
30-06-2006, 16:24
A tua scelta: semplice file di testo o binario che riporti esclusivamente:
- inizio di un turno;
- identificativo dell'azione più eventuali parametri NECESSARI (BigGemList non lo è, a mio avviso, come ho riportato sopra). e la serializzazione che ha che non va?

71104
30-06-2006, 16:28
Leggi il mio messaggio di risposta a Danilo: ho scritto perché non sarebbe necessario. ;) tolta ^^

^TiGeRShArK^
30-06-2006, 17:58
e la serializzazione che ha che non va?
appunto...con la serializzazione è possibile eliminare tutte le informazioni inutili definendo i campi non necessari come transient...
in quel modo saranno registrate solo le informazioni utili....
solo che non so quanto senso abbia registrare tutte le action...
a noi basta sapere che una certa action sia stata effettuata durante un game-turn se non ho capito male...
a quel punto basterebbe memorizzarsi in un file di testo il nome della action eseguita e a quale grid viene applicata senza ricorrere alla serializzazione.
mi sa che questo è l'approccio + semplice :p

71104
30-06-2006, 19:23
e la serializzazione che fa di più? :)
se ci fai caso la maggiore parte dei metodi writeObject e readObject per adesso sono vuoti, li riempiremo se servirà; e quelli non vuoti forse si possono anche svuotare (come ho fatto per quello che memorizzava la lista delle big gems, errore mio: non mi ero accorto che era la stessa che c'è in Grid :p).
in più, sai qual è il vantaggio nell'usare la serializzazione anziché fare a mano? che quando vai a rileggere il log è Java a costruirti l'oggetto giusto anziché noi facendo il parsing del nome della action (introducendo magari un bello switchone e una catena di if...) ;)

Bonfo
01-07-2006, 14:04
FINITO :winner:

Ho committato TiledSprite.
Facendola in TDD è venuta ancora più semplice di quella che avevo fatto prima ;)

Ora BigGem è a tutti gli effetti un Droppable, direi, quindi grid può eliminare la lista di BigGem e aggiungerla alla lista dei ElementsInGrid.

Inoltre ora, messi a posto canMoveDown e moveDown di BigGem, si può eliminare la lsita di gemme da quest'ultima ;)

71104
01-07-2006, 14:22
ottima notizia, ma il periodo di pausa dagli esami per me è finito, devo ricominciare a studiare :(

ho committao quel poco che ho fatto oggi, da qui deve continuare qualcun altro e fare le seguenti cose:

1) testare le actions non testate
2) testare la serializzazione delle actions, che finora non è stata testata per nessuna action
3) completare PlaybackLoop ed integrarla con Game

a quel punto avremo una prima riproduzione della partita, che però farà schifo perché alcune cose ancora non le logghiamo: non tutto ancora in Grid cambia per mezzo di una action, ma quando avremo sistemato Grid dovremmo avere (tra gli altri vantaggi) un playback perfetto. e non dite che si faceva prima a registrare gli input perché lo so benissimo che si faceva prima, ma il codice rimaneva incasinato tale e quale e il progetto si sarebbe fermato un'altra volta dopo pochi giorni (come al solito).

e poi loggare le actions è un metodo più preciso ed elegante (infatti è ciò che ha richiesto fek).

71104
01-07-2006, 14:35
ah, comunque a parte tutto dei miglioramenti nel codice in quest'ultimo periodo ci sono stati.

Bonfo
01-07-2006, 15:14
Ragazzi...mi manca tanto così per cancellare quintalate di codice :boxe: :perfido:
Ecco il prossimo passo:
mettere a posto moveDown e canMoveDown di BigGem.
Se riesco elimino la lista di gemme da BigGem e a quel punto...

..BERSERK !!! :asd: :asd:

Bonfo
01-07-2006, 18:03
Forse il fatto che il checkstyle mi dice che tra AbstractDroppable e BigGem ci sono 15 line in comune è un buon segno ?? :mbe:

:asd: :asd:

^TiGeRShArK^
01-07-2006, 18:39
:fiufiu:
ma a proposito di checkstyle...
sicuri di usare ant prima del commit? :mbe:
la build era rotta perchè TestPlaybackLoop non conteneva alcun test...
gli ho aggiunto un testNothing proprio per evitare questo problema visto che ancora si deve completare... :p

Bonfo
02-07-2006, 02:47
ATTENZIONE!

Sono verso la conclusione di un'enorme refactroing.
Sto appianando gli ultimi test, spero.
Datemi tempo fino a domani alle 13...vi prego :ave: :ave:

EDIT: forse mi ci vorrà molto di più :cry: :cry:

^TiGeRShArK^
02-07-2006, 12:30
com'è andata bonfo?

Bonfo
02-07-2006, 14:50
com'è andata bonfo?

Sono ancora qui che lotto :boxe:
Ho deciso che oggi ce la faccio.
Comunque :D

Praticamente sta sparendo il concetto di BigGem dal codice....forse siamo riusciti a frla diventare un Droppable :sperem:

thebol
02-07-2006, 15:08
Sono ancora qui che lotto :boxe:
Ho deciso che oggi ce la faccio.
Comunque :D

Praticamente sta sparendo il concetto di BigGem dal codice....forse siamo riusciti a frla diventare un Droppable :sperem:


io devo committare un refactoring di dynamite, che coinvolge dynamite e marginalmente la droppableFactory. Non penso che ti crei tanti problemi, ma cmq aspetto :)

Bonfo
02-07-2006, 15:23
io devo committare un refactoring di dynamite, che coinvolge dynamite e marginalmente la droppableFactory. Non penso che ti crei tanti problemi, ma cmq aspetto :)

Vai pure!! ;)
quella roba non mi sembra doi averla toccata proprio.

Anzi una domnda...chi mi trova la riga di codice cove viene rimossa dalla griglia la Chest che genera una crush?? :muro: :muro:

Bonfo
02-07-2006, 15:34
Caperraccio mi sono perso!!!

Qualcuno si ricorda come funzionano i punteggi?? :mc:

^TiGeRShArK^
02-07-2006, 15:58
Caperraccio mi sono perso!!!

Qualcuno si ricorda come funzionano i punteggi?? :mc:
:stordita:
nel senso quali parti di codice regolano i punteggi?:confused:
ora vedo se ci capisco qualcosa.....:mbe:

^TiGeRShArK^
02-07-2006, 16:03
a quanto ho capito dovrebbero essere i metodi closeChain e computeTotalScore di grid....
poi c'è removeCrushedGem in AbstractCrushAction che richiama il metodo addGem e addGemWithBonus di ScoreCalculator...
mi pare che non ci sia altro....:mbe:

Bonfo
02-07-2006, 17:04
a quanto ho capito dovrebbero essere i metodi closeChain e computeTotalScore di grid....
poi c'è removeCrushedGem in AbstractCrushAction che richiama il metodo addGem e addGemWithBonus di ScoreCalculator...
mi pare che non ci sia altro....:mbe:

Sì...ci sono arrivato 20 min fa.
Grazi ein ogni caso ;)

Bonfo
02-07-2006, 17:58
AIUTO :cry:

Ho capito.
Considerando che i prossimi giorni sono impegnato e qui le cose vanno per le lunghe mi ci vporrà un bel po' per committare.

Quindi fate quello che volete :D :D

In ogni caso io non mollo :boxe:

Bonfo
02-07-2006, 20:20
Ci sono quasi.
Stanotte mi sa che riesco a finire :D :D

Poi faccio un mega post per dirvi quello che ho fatto. :read:

^TiGeRShArK^
02-07-2006, 23:39
Ci sono quasi.
Stanotte mi sa che riesco a finire :D :D

Poi faccio un mega post per dirvi quello che ho fatto. :read:
:winner:
Vai così.. mi dispiace solo di non esserti stato molto d'aiuto... :sob:

Bonfo
03-07-2006, 03:15
:winner: :winner: :winner:

RAGAZZI HO FINITO. :yeah:

Ecco cosa ho fatto.
- BigGem è un droppable: ora tutti i comportamenti differenziati tra BigGem e altri droppable sono stati per la maggior parte uniti.
- BigGem non è più costituito da gemme: questo ha permesso una forte omogenizzazione della gestione dei diversi droppable. La difficoltà che introduce è che bisogna sempre ragionare come se un Droppable fosse un BigGem. Inosomma, ore BottomRow e RightColumn di Cell servono.
- Lo score ora è associato ai DroppableColor: semplifica tutta la gestione.
- Grid non ha più al suo interno la lista delle BigGem che è stato inglobata in gridsElement. Ora Grid è quasi totalmente avulsa da BigGem

- DrawAction l'ho lasciata...ma non la usa più nessuno :sofico: :sofico:

Praticamente la code base non è più la stessa.
ATTENZIONE: ho il checkstyle pendente ( :muro: ) ...ma non ce la facevo più...dovevo committare.

Ecco cosa rimane da fare:
- far passare il checkstyle (Perdono :ave:) : siamo al punto in cui tra AbstractDroppable e BigGem si può fattorizzare. Mi sa che ne esce una nuova gerarchia:

AbstractDroppable
/ \
AbstractSingleDoppable BigGem
|
tutto il resto

- eliminare tutti i metodi non usati o usati solo nei test.
- rifattorizzzare i test (sarebbe bello far saprire tutti i TODO)
- Cercare di far saprire tutti i comportamenti differenziati per BigGem: alcune cose alla base dievranno un po' più complicate perchè dovranno essere generalizzate per BigGem (ovvero scandire sempre tutta la dimensione della Cell di Droppable), ma per il resto il codice dovrebbe benneficarne moltissimo.

Se lavoriamo bene molte action spariranno. :sofico:
Ad esempio, ora la CanMoveDownAction si risolverebbe così

for(Droppable droppable:gridElements)
{
if(droppable.getMovingDownObject().canMoveDown(this))
{
return true;
}
}

return false;

Ora vado a letto dopo 2 giorni di coding intenso. :coffee:

I prossimi giorni ci sarò poco...devo recuperare con lo studio. Ho un esame mercoledì :cry:
Comuque sul forum ci sono :asd: :asd:

thebol
03-07-2006, 07:11
:winner: :winner: :winner:

RAGAZZI HO FINITO. :yeah:

[cut]




grande!!! :)

cdimauro
03-07-2006, 08:00
e la serializzazione che ha che non va?
Che finora ha portato più problemi che soluzioni ai nostri problemi. :p
in più, sai qual è il vantaggio nell'usare la serializzazione anziché fare a mano? che quando vai a rileggere il log è Java a costruirti l'oggetto giusto anziché noi facendo il parsing del nome della action (introducendo magari un bello switchone e una catena di if...) ;)
Switchone (catena di if no, perché si dovrebbe conoscere a priori su quali oggetti si sta operando) che è semplicemente spostato: dalla nostra applicazione alla libreria Java. Mica viene eliminato del tutto. ;)
ottima notizia, ma il periodo di pausa dagli esami per me è finito, devo ricominciare a studiare :(

ho committao quel poco che ho fatto oggi, da qui deve continuare qualcun altro e fare le seguenti cose:

1) testare le actions non testate
2) testare la serializzazione delle actions, che finora non è stata testata per nessuna action
3) completare PlaybackLoop ed integrarla con Game
OK, gli darò un'occhiata nella pausa pranzo.
a quel punto avremo una prima riproduzione della partita, che però farà schifo perché alcune cose ancora non le logghiamo: non tutto ancora in Grid cambia per mezzo di una action, ma quando avremo sistemato Grid dovremmo avere (tra gli altri vantaggi) un playback perfetto.
Ti stai sbagliando: come avevo già scritto, otterremo soltanto la riproduzione delle action, NON della partita.
e non dite che si faceva prima a registrare gli input perché lo so benissimo che si faceva prima, ma il codice rimaneva incasinato tale e quale e il progetto si sarebbe fermato un'altra volta dopo pochi giorni (come al solito).
Alberto, la rifattorizzazione del codice e il registrare e riprodurre gli input non sono mica due cose mutuamente esclusive. :D

Che il codice abbia bisogno di uno sfoltimento / semplificazione / riorganizzazione, lo si sapeva a prescindere dalla soluzione che avremmo adottato per i log. ;)
e poi loggare le actions è un metodo più preciso ed elegante (infatti è ciò che ha richiesto fek).
Più preciso non direi proprio: la precisione sta nella bontà del logging che viene effettuato.
Se dimentichi di loggare una action o qualche suo parametro, le conseguenze le puoi immaginare.

Se invece logghi gli eventi, lo fai per TUTTI: mica te ne dimentichi qualcuno per strada. :p E quindi li riproduci tutti: precisione assoluta in questo caso. ;)

Anche sull'eleganza, è tutto da vedere: per me è molto più elegante semplicemente sfruttare il modello InputDevice / listener, che abbiamo già implementato, funziona benissimo, e che NON richiede NESSUNO stravolgimento del codice.

Tant'è che per il playback delle action avremo bisogno di "duplicare" GameLoop in modo da "biforcare" il codice a seconda se si sta eseguendo il gioco normalmente oppure in una sessione di playback.

Cosa che col modello InputDevice / listener non serve assolutamente: il playback sarebbe rappresentato soltanto da un altro InputDevice a cui sono attaccati i listener. InputDevice che viene passato loro sotto forma di una nuova Keyboard, che rende disponibile Environment.
Quindi NESSUNA modifica a GameLoop et similia, nessun "coupling" del codice (si tratta di fornire soltanto un'implementazione alternativa per l'interfaccia Keyboard... ;))

Il vantaggio di catturare e riprodurre gli input è che, come diceva Fran, si tratta di una soluzione di più alto livello: si tratta di eventi che "ci dicono" quello che s'è verificato dentro la griglia.

Comuunque è inutile tornare nuovamente sull'argomento: ne abbiamo ampiamente discusso, ed entrambe le soluzioni presentano pregi e difetti. Fran ha scelto la soluzione delle action perché ha una certa visione di come dovrebbero andare le cose, e l'abbiamo accettata tutti.
Non si accettano, però, le frecciatine che scappano ogni tanto sul logging degli eventi. :Prrr:

x Bonfo. Complimenti!!! :)

thebol
03-07-2006, 09:06
Switchone (catena di if no, perché si dovrebbe conoscere a priori su quali oggetti si sta operando) che è semplicemente spostato: dalla nostra applicazione alla libreria Java. Mica viene eliminato del tutto. ;)


basterebbe poi usare una mappa stringa->evento(sotto forma di oggetto gia creato o .class) per dimenticarsi degli if.

Le stringhe le scrivi spaziate dalla virgola.

In java ti procuri dalla stringa unica l'array di stringhe(evento, stato[pressed released] e gameturn) con un istruzione.


Per scrivere il logo si puo usare una mappa inversa .class -> stringa.

thebol
03-07-2006, 09:26
altra cosa che mi è venuta in mente...

Noi serializziamo degli oggetti, ma cambiando versione del gioco(o semplicemente l'impl di una action) il log continua ad andare?

cdimauro
03-07-2006, 09:42
basterebbe poi usare una mappa stringa->evento(sotto forma di oggetto gia creato o .class) per dimenticarsi degli if.

Le stringhe le scrivi spaziate dalla virgola.

In java ti procuri dalla stringa unica l'array di stringhe(evento, stato[pressed released] e gameturn) con un istruzione.


Per scrivere il logo si puo usare una mappa inversa .class -> stringa.
Anche le mappe fanno "uso" di if. :)

Sono delle catene hash, che utilizzano il confronto per controllare se l'oggetto su cui stanno lavorando al momento corrisponde a quello desiderato: se sì, finisce la ricerca, altrimenti si prosegue (ed eventualmente finisce per mancanza di elementi da valutare).

Correggo anche quanto avevo scritto: non c'è uno switchone, ma una sequenza di if (almeno uno per verificare se la catena non ha più elementi).

Gli if non si possono eliminare completamente. :p
altra cosa che mi è venuta in mente...

Noi serializziamo degli oggetti, ma cambiando versione del gioco(o semplicemente l'impl di una action) il log continua ad andare?
Se le action rimangono le stesse, dovrebbe continuare a funzionare, altrimenti no.

Comunque non è un problema che c'interessa: il playback del log dev'essere relativo soltanto all'ultima versione "di produzione" di Diamonds. ;)

thebol
03-07-2006, 09:46
Anche le mappe fanno "uso" di if. :)

Sono delle catene hash, che utilizzano il confronto per controllare se l'oggetto su cui stanno lavorando al momento corrisponde a quello desiderato: se sì, finisce la ricerca, altrimenti si prosegue (ed eventualmente finisce per mancanza di elementi da valutare).

Correggo anche quanto avevo scritto: non c'è uno switchone, ma una sequenza di if (almeno uno per verificare se la catena non ha più elementi).

Gli if non si possono eliminare completamente. :p


una hashmap però no, o sbaglio?
Ha tempo di accesso costante(non considerando il load factor e la collisione di chiavi..).


cmq intendevo nel eliminare gli if dal codice ;)

thebol
03-07-2006, 09:47
Se le action rimangono le stesse, dovrebbe continuare a funzionare, altrimenti no.

Comunque non è un problema che c'interessa: il playback del log dev'essere relativo soltanto all'ultima versione "di produzione" di Diamonds. ;)

perderebbe la funzione di debugging...

VICIUS
03-07-2006, 09:56
A questo punto sarebbe utile avere da qualche parte nel log il numero di revisione del repository con cui è stato creato il file di log.

ciao ;)

VICIUS
03-07-2006, 10:03
:winner: :winner: :winner:

RAGAZZI HO FINITO. :yeah:
Grandissimo :D :mano:

ciao ;)

cdimauro
03-07-2006, 10:10
una hashmap però no, o sbaglio?
Non lo so: non ho mai visto il sorgente. Comunque per questo genere di applicazioni si usano sempre delle tavole hash. ;)
Ha tempo di accesso costante(non considerando il load factor e la collisione di chiavi..).
E' costante "statisticamente".
cmq intendevo nel eliminare gli if dal codice ;)
OK :)
perderebbe la funzione di debugging...
In tal caso, come suggerisce VICIUS, meglio loggare anche il numero di revisione. :)

cdimauro
03-07-2006, 10:12
A questo punto sarebbe utile avere da qualche parte nel log il numero di revisione del repository con cui è stato creato il file di log.

ciao ;)
Benissimo. Ma vedrai che non sarà l'unica informazione "strana" (leggi: diversa dalle action :D) che bisognerà conservare... :asd:

^TiGeRShArK^
03-07-2006, 20:59
Non lo so: non ho mai visto il sorgente. Comunque per questo genere di applicazioni si usano sempre delle tavole hash. ;)

E' costante "statisticamente".

OK :)

In tal caso, come suggerisce VICIUS, meglio loggare anche il numero di revisione. :)
se non ricordo male le hashmap hanno tempo di accesso costante e indipendente dal numero degli elementi perchè la posizione dell'elemento cercato viene fornita direttamente dalla funzione hash utilizzata.
Le hashtable invece hanno una dipendenza anke dal load factor in quanto ad ogni funzione hash sono associati più oggetti che devono essere restituiti linearmente.
Per questo le hashmap e table hanno come svantaggio una maggiore occupazione di memoria, però hanno il non trascurabile vantaggio di accedere agli elementi con complessità o(1) (x le HashMap) e o(n/x) con x il load factor se non erro (x le hash table) e cmq sono prestazioni enormemente superiori rispetto ad un'implementazione con array e algoritmi di ricerca vari che utilizzano comunque dei confronti per ricercare un elemento.
Tutto questo sempre se mi ricordo ancora qualcosa di algoritmi e strutture dati :p

cdimauro
04-07-2006, 07:20
se non ricordo male le hashmap hanno tempo di accesso costante e indipendente dal numero degli elementi perchè la posizione dell'elemento cercato viene fornita direttamente dalla funzione hash utilizzata.
Mi suona strano: come fa a essere indipendente dal numero di elementi e rimanere costante come tempo di accesso?
Le hashtable invece hanno una dipendenza anke dal load factor in quanto ad ogni funzione hash sono associati più oggetti che devono essere restituiti linearmente.
Per questo le hashmap e table hanno come svantaggio una maggiore occupazione di memoria, però hanno il non trascurabile vantaggio di accedere agli elementi con complessità o(1) (x le HashMap) e o(n/x) con x il load factor se non erro (x le hash table) e cmq sono prestazioni enormemente superiori rispetto ad un'implementazione con array e algoritmi di ricerca vari che utilizzano comunque dei confronti per ricercare un elemento.
Tutto questo sempre se mi ricordo ancora qualcosa di algoritmi e strutture dati :p
Io ho trovato questo: http://java.sun.com/j2se/1.4.2/docs/api/java/util/HashMap.html

"This implementation provides constant-time performance for the basic operations (get and put), assuming the hash function disperses the elements properly among the buckets. Iteration over collection views requires time proportional to the "capacity" of the HashMap instance (the number of buckets) plus its size (the number of key-value mappings). Thus, it's very important not to set the initial capacity too high (or the load factor too low) if iteration performance is important.

An instance of HashMap has two parameters that affect its performance: initial capacity and load factor. The capacity is the number of buckets in the hash table, and the initial capacity is simply the capacity at the time the hash table is created. The load factor is a measure of how full the hash table is allowed to get before its capacity is automatically increased. When the number of entries in the hash table exceeds the product of the load factor and the current capacity, the capacity is roughly doubled by calling the rehash method."

Come implementazione mi sembra una hash table. ;)

Bonfo
04-07-2006, 23:19
ORA SONO UN PO' ARRABBIATO ANCH'IO. :mad: :incazzed: :ncomment:

Non può essere che lascio la build ROTTA notificandolo a lettere cubiltali nel post e nessuno per 2 giorni interi non fa nulla....certo, direte, "perchè non lo fai tu??"

Bhè...io ho lavorato nel week-end circa 30 ore (e ricordatevi che per qualquno per fare refactoring o task bastano 10 minuti :mad: ) e domani mattina ho un esame.

Perdonatemi se non faccio di più...ma almeno uno che mi avesse sgridato che ho lasciato la build rotta o almeno avesse fatto un post per dire "ci sto provando" oppure "che cavolo debbo fare" o ancora "Bonfo: ma che cazzo hai fatto!!"

Non voglio assolutamente puntare il dito su niente e nessuno, voglio solo incitare il team a farci sotto per concludere questo tremendo periodo di chiusura del progetto...ripeto: PROGETTO CHIUSO.
In realtà io ho lavorato sul qualcosa che è stato deciso non si finirà mai!!!
Quindi, ripeto...AL LAVORO.

P.S.: forse sono solamente un po' pazzo... :asd: :asd:
vabbè...torno a studiare le ultime cose :coffee:

71104
04-07-2006, 23:50
nonnò, a puntare il dito l'hai puntato eccome, sull'intero team: io però non sono incluso tra i puntati perché ho lavorato orientativamente anche più di te e ho un'esame domani pure io.

ammetto una mia colpa: in futuro devo organizzarmi meglio nello studio. è l'ennesima volta che sbaglio sempre su questa stessa cosa nella mia vita, e come se non bastasse stavolta non so perché sto iniziando ad avere seri problemi di concentrazione su cose che non siano inerenti la programmazione vera e propria (vi giuro che non riesco a studiare ne' algebra ne' combinatoria :muro: ).

voi che siete più saggi di me datevi un po' da fare in questo periodo nero, fatevi ispirare dalla splendida partita che ha appena giocato l'Italia (mortacci, 2 gol distanziati di manco un minuto, giusto perché a causa della sfortuna che abbiamo avuto durante tutta la partita rischiava di esserci ambiguità su quale fosse la squadra più forte, quindi per stare proprio sicuri abbiamo preferito segnare due gol anziché uno... :asd: :asd: :asd: ).

cisc
04-07-2006, 23:57
ragazzi, io sono incasinato forte con gli esami..un progetto da fare, e sto avendo un sacco di problemi a farlo...per le prossime settimane sono totalmente out....cercherò di recuperare dopo...

Bonfo
05-07-2006, 01:41
nonnò, a puntare il dito l'hai puntato eccome, sull'intero team: io però non sono incluso tra i puntati perché ho lavorato orientativamente anche più di te e ho un'esame domani pure io.


Già siamo tutti messi malaccio :cry:
Comunque non volevo fare la conta su chi ha lavorato di più (naturlamente io :Prrr: :asd: ).
Ripeto...circa un mese fa se lasciavo la Build rotta dopo circa un femto-secondo mi ritrovavo con le ditine dei piedi e delle mani spezzate...ora no.
Voglio le dita rotte !!! :muro: (:asd: )

In realtà cerco di incitare il team, me compreso (che so essere scansafatiche e peggio organizzato di te 71104 :D )
Sto solo cercando di capire...è proprio impossibile sacrificare 5-6 ore (non raccontiamoci la storia dei 10 minuti ;) ) per Dimaonds??

Vi prego...tiriamo fuori gli attributi!!! :ave: :ave:

voi che siete più saggi di me datevi un po' da fare in questo periodo nero, fatevi ispirare dalla splendida partita che ha appena giocato l'Italia (mortacci, 2 gol distanziati di manco un minuto, giusto perché a causa della sfortuna che abbiamo avuto durante tutta la partita rischiava di esserci ambiguità su quale fosse la squadra più forte, quindi per stare proprio sicuri abbiamo preferito segnare due gol anziché uno... :asd: :asd: :asd: ).

:winner: FORZA ITALIA :winner:

P.S.: non è un mesaggio politico ( :Puke: )

^TiGeRShArK^
05-07-2006, 01:51
ORA SONO UN PO' ARRABBIATO ANCH'IO. :mad: :incazzed: :ncomment:

Non può essere che lascio la build ROTTA notificandolo a lettere cubiltali nel post e nessuno per 2 giorni interi non fa nulla....certo, direte, "perchè non lo fai tu??"

Bhè...io ho lavorato nel week-end circa 30 ore (e ricordatevi che per qualquno per fare refactoring o task bastano 10 minuti :mad: ) e domani mattina ho un esame.

Perdonatemi se non faccio di più...ma almeno uno che mi avesse sgridato che ho lasciato la build rotta o almeno avesse fatto un post per dire "ci sto provando" oppure "che cavolo debbo fare" o ancora "Bonfo: ma che cazzo hai fatto!!"

Non voglio assolutamente puntare il dito su niente e nessuno, voglio solo incitare il team a farci sotto per concludere questo tremendo periodo di chiusura del progetto...ripeto: PROGETTO CHIUSO.
In realtà io ho lavorato sul qualcosa che è stato deciso non si finirà mai!!!
Quindi, ripeto...AL LAVORO.

P.S.: forse sono solamente un po' pazzo... :asd: :asd:
vabbè...torno a studiare le ultime cose :coffee:
:sob:
non avevo capito un cacchio :fagiano:
avevo letto il tuo post ma m'era lievemente sfuggito che la build era rotta...e la mail è da un pò che non la guardo :fiufiu:
se riesco la aggiusto domani...:muro:

cdimauro
05-07-2006, 07:39
x Bonfo: il problema è che il progetto è formalmente chiuso e non abbiamo più un coach che ci segue e che ci "spezza le ditine".

Fran non ha più scritto un solo messaggio da quando è stato sospeso, pur avendo già scontato da tempo la sospensione.

Hai ragione: siamo tutti incasinati, ma alla fine, se ci fai caso, quelli che si scrivono e si occupano di portare avanti il progetto sono sempre i soliti.

Vuoi sapere perché non ho fixato io la build corrotta? Per vedere se qualcun altro c'avrebbe messo mano.
Non che ci volesse molto, visto che si tratta soltanto di "addomesticare" l'odiato CheckStyle, ma neppure questo lavoro di pochi minuti è stato fatto, come hai giustamente fatto notare.

Direi che la cosa si commenta da sé, ed è molto triste...

EDIT: la build è a posto adesso. Ha impiegato più tempo Ant per eseguire la build che io a scrivere 2 linee di codice per azzittire CheckStyle...

thebol
05-07-2006, 09:19
x Bonfo: il problema è che il progetto è formalmente chiuso e non abbiamo più un coach che ci segue e che ci "spezza le ditine".

Fran non ha più scritto un solo messaggio da quando è stato sospeso, pur avendo già scontato da tempo la sospensione.

Hai ragione: siamo tutti incasinati, ma alla fine, se ci fai caso, quelli che si scrivono e si occupano di portare avanti il progetto sono sempre i soliti.

Vuoi sapere perché non ho fixato io la build corrotta? Per vedere se qualcun altro c'avrebbe messo mano.
Non che ci volesse molto, visto che si tratta soltanto di "addomesticare" l'odiato CheckStyle, ma neppure questo lavoro di pochi minuti è stato fatto, come hai giustamente fatto notare.

Direi che la cosa si commenta da sé, ed è molto triste...

EDIT: la build è a posto adesso. Ha impiegato più tempo Ant per eseguire la build che io a scrivere 2 linee di codice per azzittire CheckStyle...
imho ci conviene portare a termine gli ultimi refactoring, e gli ultimi task(appena ho tempo sistemo le dinamiti, ho avuto anche io poco tempo in sti giorni..). Poi però va fatto della situazione, vedere chi cè, chi non cè, chi puoi tornare, e vedere cosa fare in futuro. Ed eventualmente riorganizzarsi.

cdimauro
05-07-2006, 09:25
D'accordo.

^TiGeRShArK^
05-07-2006, 11:42
- far passare il checkstyle (Perdono :ave:) : siamo al punto in cui tra AbstractDroppable e BigGem si può fattorizzare. Mi sa che ne esce una nuova gerarchia:

AbstractDroppable
/ \
AbstractSingleDoppable BigGem
|
tutto il resto

mi sfugge una cosa...
L'introduzione di AbstractSingleDroppable nel refactoring quale utilità ha?
Non sarebbe più logico fare estendere direttamente tutti da AbstractDroppable?
(ah...queste sono considerazioni così ad occhio perchè ancora lo devo guardare per bene il codice di AbstractDroppable e di BigGem :p)

thebol
05-07-2006, 11:45
mi sfugge una cosa...
L'introduzione di AbstractSingleDroppable nel refactoring quale utilità ha?
Non sarebbe più logico fare estendere direttamente tutti da AbstractDroppable?
(ah...queste sono considerazioni così ad occhio perchè ancora lo devo guardare per bene il codice di AbstractDroppable e di BigGem :p)

a occhio dovrebbe contenere metodi comuni alle SingleDroppable ma non alle bigGem.

^TiGeRShArK^
05-07-2006, 11:55
a occhio dovrebbe contenere metodi comuni alle SingleDroppable ma non alle bigGem.
e allora perchè lo dobbiamo fare estendere da AbstractDroppable se AbstractDroppable dovrebbe contenere i metodi delle SingleDroppable?
Se non sbaglio checkstyle segnalava un metodo che era in comune tra AbstractDroppable e BigGem..
cmq ora mi studio per bene il codice e vedo ke si può fare :p

^TiGeRShArK^
05-07-2006, 11:58
e allora perchè lo dobbiamo fare estendere da AbstractDroppable se AbstractDroppable dovrebbe contenere i metodi delle SingleDroppable?
Se non sbaglio checkstyle segnalava un metodo che era in comune tra AbstractDroppable e BigGem..
cmq ora mi studio per bene il codice e vedo ke si può fare :p
Ah.. ora ho capito che intendevi forse :p
che praticamente bisogna raggruppare i metodi comuni alle gemme singole in SingleDroppable e quindi in AbstractDroppable si lasciano solo i metodi comuni tra BigGem e AbstractDroppable (+ o -)
giusto?:mbe:

cdimauro
05-07-2006, 12:44
Sarebbe meglio avere soltanto un AbstractDroppable, o un Droppable, per gestire tutti i tipi di oggetti.

thebol
05-07-2006, 13:20
Sarebbe meglio avere soltanto un AbstractDroppable, o un Droppable, per gestire tutti i tipi di oggetti.

parlando di metodi pubblici si.

In AbstractSingleDoppable ci dovrebbero andare solo metodi protected usati dalle classi figlie(se ne esistono).


Forse ci potrebbero andare anche metodi pubblici dichiarati abstract in AbstractDoppable, ma che hanno l'implmentazione in comune fra tutti i AbstractSingleDoppable (e diversa per le bigGem).

Il disegno diventa complesso, ma puo essere utile per riutilizzare il codice.

^TiGeRShArK^
05-07-2006, 14:39
parlando di metodi pubblici si.

In AbstractSingleDoppable ci dovrebbero andare solo metodi protected usati dalle classi figlie(se ne esistono).


Forse ci potrebbero andare anche metodi pubblici dichiarati abstract in AbstractDoppable, ma che hanno l'implmentazione in comune fra tutti i AbstractSingleDoppable (e diversa per le bigGem).

Il disegno diventa complesso, ma puo essere utile per riutilizzare il codice.
infatti..sto cercando di capire come muovermi proprio in quella direzione...

^TiGeRShArK^
05-07-2006, 15:25
mamma che casino...
ci sono una marea di cose ridondanti....:mbe:
penso che ci vorrà un bel pò per finre tutto e non so se faccio in tempo entro oggi....
Cmq la semplificazione alla fine per quanto riguarda il codice duplicato di biggem e abstractdroppable dovrebbe essere notevole...
ci sto mettendo molto anche perchè queste parti di codice rispetto all'ultima volta sono completamente diverse :D

Bonfo
05-07-2006, 15:53
Ecco come funziano le cose (nella mia ottica):
tutti gli oggetti sono un Droppable e tutto è gestito da quella interfaccia.

Ora parliamo di implementazione.
BigGem, per esempio, implementa l'interfacca ExtendibleObject, cose che AbstractDroppable non fa, come è giusto che sia.

Quindi sono indubbiamente 2 classi diverse.

Ora però entrambe hanno il metodo moveDown implementato uguale, e anche i metodi che relalizzano l'interfaccia gridObject sono molto simili quindi: perchè non possiamo fattorizzare il tutto in un super classe??

Qundi si poterbbe avere una supercalsse da dove derivano le classi BigGem e ClasseDeiDroppableSingoli.

Ed ecco da dove viene la gerarchia che ho proposto. :D

^TiGeRShArK^
05-07-2006, 16:00
Ecco come funziano le cose (nella mia ottica):
tutti gli oggetti sono un Droppable e tutto è gestito da quella interfaccia.

Ora parliamo di implementazione.
BigGem, per esempio, implementa l'interfacca ExtendibleObject, cose che AbstractDroppable non fa, come è giusto che sia.

Quindi sono indubbiamente 2 classi diverse.

Ora però entrambe hanno il metodo moveDown implementato uguale, e anche i metodi che relalizzano l'interfaccia gridObject sono molto simili quindi: perchè non possiamo fattorizzare il tutto in un super classe??

Qundi si poterbbe avere una supercalsse da dove derivano le classi BigGem e ClasseDeiDroppableSingoli.

Ed ecco da dove viene la gerarchia che ho proposto. :D
si infatti :D
sto procedendo proprio in quel modo :D
però è un bel casino :mbe:
Ho fatto estendere AbstractDroppable a BigGem x ora facendo estendere agli altri droppables AbstractSingleDroppable che in questo momento non è altro che la vecchia AbstractDroppable.
Però mi falliscono una marea di test su BigGem e sto cercando di scoprire quali pezzi mi sono dimenticato :fiufiu:

jappilas
05-07-2006, 16:10
Ecco come funziano le cose (nella mia ottica):
tutti gli oggetti sono un Droppable e tutto è gestito da quella interfaccia.
...
Ed ecco da dove viene la gerarchia che ho proposto. :D
credo che, una volta che arrivi a una gerarchia che soddisfi il requisito "posso trasformare semplicemente una bigGem in una bigStone e trattarla come Droppable?" sei praticamente alla generalizzazione totale, quindi alla perfezione :D

^TiGeRShArK^
05-07-2006, 16:18
build verde :D
però ancora ho solo gestito BigGem e AbstractDroppable :p
Ora devo fare estendere AbstractSingleDroppable da AbstractDroppable e poi limare il tutto :D

^TiGeRShArK^
05-07-2006, 17:06
qualcuno sa il motivo di questa differenza tra moveDown di BigGem e di AbstractDroppable? :confused:
BigGem:

public void moveDown(Grid grid)
{
if(!canMoveDown(grid))
{
return;
}

if(canMoveButNotWithFullGravity(grid))
{
getSprite().getPosition().setY(grid.getRowUpperBound(getCell().getTopRow()));
return;
}

getSprite().translate(0, grid.getActualGravity());

if(getSprite().getPosition().getY() > grid.getRowUpperBound(getCell().getTopRow()))
{
getCell().setRow(getCell().getTopRow()+1);
}
}

AbstractDroppable:

public void moveDown(Grid grid)
{
if(canMoveButNotWithFullGravity(grid))
{
getSprite().getPosition().setY(grid.getRowUpperBound(getCell().getTopRow()));
return;
}

getSprite().translate(0, grid.getActualGravity());

if(getSprite().getPosition().getY() > grid.getRowUpperBound(getCell().getTopRow()))
{
getCell().setRow(getCell().getTopRow()+1);
}
}

^TiGeRShArK^
05-07-2006, 17:35
quel pezzo l'ho sistemato....
qualcuno mi sa spiegare l'utilità di questi due metodi?:mbe:

public boolean isFalling()
{
return !stopped;
}


public boolean isNotFalling()
{
return !isFalling();
}

appena finisco le altre cosine da mettere a posto elimino isNotFalling sostituendolo con !isFalling() :O

thebol
05-07-2006, 17:58
quel pezzo l'ho sistemato....
qualcuno mi sa spiegare l'utilità di questi due metodi?:mbe:

public boolean isFalling()
{
return !stopped;
}


public boolean isNotFalling()
{
return !isFalling();
}

appena finisco le altre cosine da mettere a posto elimino isNotFalling sostituendolo con !isFalling() :O


indica se la droppable che fa parte della gemsPair sta cadendo.
viene anche usata per capire se una droppable fa parte della gemsPair ed è controllata(nelle crush, che non devono coinvolgere le gemme che fanno parte della gemsPair)

^TiGeRShArK^
05-07-2006, 18:09
indica se la droppable che fa parte della gemsPair sta cadendo.
viene anche usata per capire se una droppable fa parte della gemsPair ed è controllata(nelle crush, che non devono coinvolgere le gemme che fanno parte della gemsPair)
si questo l'avevo capito :p
mi sfuggiva l'utilità di due metodi che sono palesemente ridondanti e non credo aiutino neanche la leggibilità in quanto io preferisco il ! al posto di un not nel nome del metodo :D
Cmq ho appena finito e committato il refactoring...
Ora uccido uno di quei due metodi :asd:
ah.. un'altra cosa..
c'è checkstyle che mi ha proprio rotto :muro:
non ho potuto usare i campi protected all'interno di AbstractDroppable perchè a lui non piacevano e ho dovuto usare dei campi private che hanno complicato un pò la struttura del codice..:muro:

^TiGeRShArK^
05-07-2006, 18:13
tra l'altro ho appena beccato un bug macroscopico che non so se è stato introdotto da questo refactoring o c'era già:mbe:
Praticamente andando a creare una BigGem da 6 in verticale quando si mette l'ultima pietra la gemmona scompare :confused:
Vi risultava già da prima 'sto bug o è appena nato? :mbe:

^TiGeRShArK^
06-07-2006, 02:04
:fiufiu:
ancora nessuno che mi da notizie riguardo il bug macroscopico che ho visto?:confused:
ora capisco come si sentiva bonfo qdo nessuno ha corretto la build :mbe: (e io idiota ke non ho capito ke era rotta :muro: )

cdimauro
06-07-2006, 07:31
si questo l'avevo capito :p
mi sfuggiva l'utilità di due metodi che sono palesemente ridondanti e non credo aiutino neanche la leggibilità in quanto io preferisco il ! al posto di un not nel nome del metodo :D
Io preferisco l'operatore not al posto di un molto meno leggibile simbolo ! :p
Cmq ho appena finito e committato il refactoring...
Ora uccido uno di quei due metodi :asd:
ah.. un'altra cosa..
c'è checkstyle che mi ha proprio rotto :muro:
non ho potuto usare i campi protected all'interno di AbstractDroppable perchè a lui non piacevano e ho dovuto usare dei campi private che hanno complicato un pò la struttura del codice..:muro:
In effetti è una grossa rottura.
:fiufiu:
ancora nessuno che mi da notizie riguardo il bug macroscopico che ho visto?:confused:
ora capisco come si sentiva bonfo qdo nessuno ha corretto la build :mbe: (e io idiota ke non ho capito ke era rotta :muro: )
E capisci anche la frustrazione che può avere uno nel non poter nemmeno farsi una partititina perché Diamonds viaggia a 1fps sulla sua macchina... :(

x Jappilas. Droppable only & forever. :D

Bonfo
06-07-2006, 14:06
:fiufiu:
ancora nessuno che mi da notizie riguardo il bug macroscopico che ho visto?:confused:
ora capisco come si sentiva bonfo qdo nessuno ha corretto la build :mbe: (e io idiota ke non ho capito ke era rotta :muro: )

Ora il problema è : è stata rimossa dalla griglia o semplicemente non viene disegnata??

P.S.: ottimo lavoro Tiger :mano:

Bonfo
06-07-2006, 14:17
hmmm :wtf:

A me la gemma si è creata senza problemi.
avevo una L e poi ho aggiunto un acoppia di 2 Diamond.

Forse non ho capito il bug :wtf:

Bonfo
06-07-2006, 14:19
Ma eri in Versus Mode o Advanced??
Non dovrebbe cambiare nulla, però non si sa mai :asd:

^TiGeRShArK^
06-07-2006, 14:37
Ma eri in Versus Mode o Advanced??
Non dovrebbe cambiare nulla, però non si sa mai :asd:
ero in versus...
non se se cambi qualcosa..
ora do un'okkiata allo screen che hai fatto e provo a riprodurlo in caso :p

^TiGeRShArK^
06-07-2006, 14:38
hmmm :wtf:

A me la gemma si è creata senza problemi.
avevo una L e poi ho aggiunto un acoppia di 2 Diamond.

Forse non ho capito il bug :wtf:
doh... a te l'ha creata x bene :mbe:
forse il prob è ke da me c'era una gemma che è caduta accanto al gemmone proprio nel momento in cui si è formata....
vedo se riesco a fare qualke screen ora :p

^TiGeRShArK^
06-07-2006, 14:46
ecco qui:
http://img410.imageshack.us/img410/4863/bug3x27xr.jpg (http://imageshack.us)
Praticamente appena quella coppia di diamanti è caduta in quel modo è scomparso il gemmone :mbe:

71104
06-07-2006, 15:14
dio santo, sta a vedere che mi arrivano altri 4 listati di quell'odiosa insertAndUpdate... :muro:

^TiGeRShArK^
06-07-2006, 16:42
dio santo, sta a vedere che mi arrivano altri 4 listati di quell'odiosa insertAndUpdate... :muro:
:confused:

71104
06-07-2006, 18:40
:confused: test sempliciiiiiiiii :cry:

se andiamo avanti con quei test kilometrici che simulano le situazioni più assurde con quella maledetta insertAndUpdate non finiremo MAI

^TiGeRShArK^
06-07-2006, 19:14
test sempliciiiiiiiii :cry:

se andiamo avanti con quei test kilometrici che simulano le situazioni più assurde con quella maledetta insertAndUpdate non finiremo MAI
e infsatti pure a me stanno sulle balle quei test con insertandupdate...
ma xkè c'è qualche altro modo x testare queste situazioni ora come ora? :confused:

71104
06-07-2006, 20:31
tanto per cominciare vorrei capire a che cacchio serve l'update dopo l'insert; successivamente si potrebbe osservare che molti di quei test sono effettuati a un livello alto che si potrebbe abbassare per semplificare il test stesso.

thebol
07-07-2006, 17:36
tanto per cominciare vorrei capire a che cacchio serve l'update dopo l'insert; successivamente si potrebbe osservare che molti di quei test sono effettuati a un livello alto che si potrebbe abbassare per semplificare il test stesso.

sono test che inseriscono gemme, e fanno update del gridController facendo avanzare il timer. Non ci vedo nulla di cosi complicato...

Non si puo prescindere da questi test. Le singole funzionalità formano nel loro insieme una funzionalità piu grande che va testata. Questo permette di cambiare la logica sottostante(il livello basso, gli oggetti che realizzano la funzionalità o parte di essa) garantendo che il comportamento(a livello alto) rimanga lo stesso.

E quello che capita col TDD.
Si scrivono n funzionalità(integrate tutte in gridController ad esempio) e poi si fattorizzano le entita piu piccole testandole singolarmente, scorporando da gridController. Ma la funzionalita di gridController deve continuare a essere garantita dai test.

Il discorso non è cosi semplice. Bisognerebbe testare tutto anche a livello di playField? a mio parere no perchè in teoria playField potrebbe contenere gridController che si comportano diversamente, come gia succede per la normal e extended version.
Ma i test funzionali servono proprio per evitare che futuri refactoring cambi le funzionalità del sistema.

Quando ho introdotto gli stati, avevo una serie di test che testavano il comportamento di update di gridController.

Ho introdotto n oggetti stato, che poi piano piano sono stati testati uno a uno, ma i test di update di gridController sono rimasti. In questa maniera se qualcun altro domani arriva e vuole fare il refactoring usando un pattern ai bignè alla crema, ha cmq i test che garantiscono il mantenimento delle funzionalità.

^TiGeRShArK^
08-07-2006, 02:09
sono test che inseriscono gemme, e fanno update del gridController facendo avanzare il timer. Non ci vedo nulla di cosi complicato...

Non si puo prescindere da questi test. Le singole funzionalità formano nel loro insieme una funzionalità piu grande che va testata. Questo permette di cambiare la logica sottostante(il livello basso, gli oggetti che realizzano la funzionalità o parte di essa) garantendo che il comportamento(a livello alto) rimanga lo stesso.

E quello che capita col TDD.
Si scrivono n funzionalità(integrate tutte in gridController ad esempio) e poi si fattorizzano le entita piu piccole testandole singolarmente, scorporando da gridController. Ma la funzionalita di gridController deve continuare a essere garantita dai test.

Il discorso non è cosi semplice. Bisognerebbe testare tutto anche a livello di playField? a mio parere no perchè in teoria playField potrebbe contenere gridController che si comportano diversamente, come gia succede per la normal e extended version.
Ma i test funzionali servono proprio per evitare che futuri refactoring cambi le funzionalità del sistema.

Quando ho introdotto gli stati, avevo una serie di test che testavano il comportamento di update di gridController.

Ho introdotto n oggetti stato, che poi piano piano sono stati testati uno a uno, ma i test di update di gridController sono rimasti. In questa maniera se qualcun altro domani arriva e vuole fare il refactoring usando un pattern ai bignè alla crema, ha cmq i test che garantiscono il mantenimento delle funzionalità.
ok capito..
quindi mi sa ke dobbiamo usare x forza insertupdate...
ma mi sfugge una cosa..
come mai il test realtivo al bug macroscopico attuale non fallisce? :mbe:
mi pare di averne visto uno che simulava quella situazione...sempre se non ricordo male data la tarda ora :p

EDIT ho visto nell'altro thread