Torna indietro   Hardware Upgrade Forum > Software > Programmazione

I nuovi schermi QD-OLED di quinta generazione di MSI, per i gamers
I nuovi schermi QD-OLED di quinta generazione di MSI, per i gamers
MSI continua ad investire nel proporre schermi pensati per rispondere alle esigenze dei videogiocatori, utilizzando la quinta generazione di tecnologia QD-OLED sviluppata da Samsung. Il modello MGP 341CQR QD-OLED X36 è lpultima novità al debutto in concomitanza con il CES 2026, uno schermo curvo di ampia risoluzione pensato per i videogiocatori più esigenti
Recensione vivo X300 Pro: è ancora lui il re della fotografia mobile, peccato per la batteria
Recensione vivo X300 Pro: è ancora lui il re della fotografia mobile, peccato per la batteria
vivo X300 Pro rappresenta un'evoluzione misurata della serie fotografica del produttore cinese, con un sistema di fotocamere migliorato, chipset Dimensity 9500 di ultima generazione e l'arrivo dell'interfaccia OriginOS 6 anche sui modelli internazionali. La scelta di limitare la batteria a 5.440mAh nel mercato europeo, rispetto ai 6.510mAh disponibili altrove, fa storcere un po' il naso
Lenovo Legion Go 2: Ryzen Z2 Extreme e OLED 8,8'' per spingere gli handheld gaming PC al massimo
Lenovo Legion Go 2: Ryzen Z2 Extreme e OLED 8,8'' per spingere gli handheld gaming PC al massimo
Lenovo Legion Go 2 è la nuova handheld PC gaming con processore AMD Ryzen Z2 Extreme (8 core Zen 5/5c, GPU RDNA 3.5 16 CU) e schermo OLED 8,8" 1920x1200 144Hz. È dotata anche di controller rimovibili TrueStrike con joystick Hall effect e una batteria da 74Wh. Rispetto al dispositivo che l'ha preceduta, migliora ergonomia e prestazioni a basse risoluzioni, ma pesa 920g e costa 1.299€ nella configurazione con 32GB RAM/1TB SSD e Z2 Extreme
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 09-05-2011, 09:26   #1
tylerdurden83
Senior Member
 
Iscritto dal: Nov 2004
Messaggi: 691
[Qualsiasi / Pseudocodice] Numero variabile di condizioni dentro un if

Ragazzi, ho un problema concettuale più che legato ad un linguaggio in particolare, per cui mi va bene un esempio in qualsiasi linguaggio o pseudocodice.

Attualmente il mio programma ha un blocchetto di codice del tipo

Codice:
if (haProprieta(A)== false && haProprieta(B)== false){
	...
} else if (haProprieta(A)== false && haProprieta(B)== true){
	...
} else if (haProprieta(A)== true && haProprieta(B)== false){
	...
} else if (haProprieta(A)== true && haProprieta(B)== true){
	...
}
A e B sono due proprietà del mio oggetto.
Ora però mi è stato chiesto di far si che possa avere un numero variabile di proprietà.
Il problema è come fare ad avere un numero parametrico di if then else nel mio software?
Ad esempio, nel caso abbia tre proprietà, dovrei avere:

Codice:
if (haProprieta(A)== false && haProprieta(B)== false && haProprieta(C)== false){
	...
} else if (haProprieta(A)== false && haProprieta(B)== false && haProprieta(C)== true){
	...
} else if (haProprieta(A)== false && haProprieta(B)== true && haProprieta(C)== false){
	...
} else if (haProprieta(A)== false && haProprieta(B)== true && haProprieta(C)== true){
	...
} ...
La struttura dati per contenere le proprietà non è un problema.
La creazione dei vari casi, anche usando una funzione ricorsiva, l'ho risolta, ma non riesco a capire se mi può essere d'aiuto (per capirci, ho capito come generare, nel caso di cui sopra, una matrice del tipo

Quote:
0,0,0
0,0,1
0,1,0
0,1,1
...
che in effetti modella i vari blocchetti if then else, ma mi serve a qualcosa? E, se si, come usarla?...

Grazie a tutti, come sempre.
TD
tylerdurden83 è offline   Rispondi citando il messaggio o parte di esso
Old 09-05-2011, 12:59   #2
zuper
Senior Member
 
Iscritto dal: Mar 2001
Città: PV Milano Nord
Messaggi: 3851
dipende molto da che ti serve

devi uscire in qualche punto?

se invece devi fare un matching credo che l'unica sia inserire tutte le variabili in una matrice e fare dei case con quella

case matrice
000 then qualcosa
001 then qualcosa

ecc ecc
__________________
"W la foca, che dio la benedoca"
poteva risolvere tutto la sinistra negli anni in cui ha governato e non l'ha fatto. O sono incapaci o sta bene anche a "loro" cosi.
L'una o l'altra inutile scandalizzarsi.[plutus]
zuper è offline   Rispondi citando il messaggio o parte di esso
Old 09-05-2011, 13:45   #3
WarDuck
Senior Member
 
L'Avatar di WarDuck
 
Iscritto dal: May 2001
Messaggi: 12914
Dovresti essere un po' più preciso.

Quando parli di oggetto ne parli in chiave object oriented?
Quando parli di proprietà associate ad un oggetto, ne parli alla stessa maniera?

O è molto più astratto?

Quali sono i tuoi oggetti, le proprietà cosa descrivono con esattezza?

Se queste proprietà potessero essere associate a dei flags, potresti pensare di creare una struttura simile ad un array di bit.

Se il tuo problema è aggiungere nuove proprietà a run-time, dovresti fare in modo di caricare queste proprietà dall'esterno (ad esempio da file) e creare una struttura apposita.

Un'idea per evitare di usare IF-ELSE è usare una lista o un array di puntatori a funzioni.

Per cui ad esempio in posizione 0 hai una certa funzione, in posizione 1 un'altra, così facendo, in base ad un certo codice potresti lanciare la funzione corrispondente senza usare IF.

Un'altra soluzione è vedere tutto in chiave object oriented, per cui implementi un'oggetto chiamato PROPRIETA', e un oggetto OBJECT che contiene una lista di queste proprietà.

Ma rimaniamo sempre nel campo delle ipotesi, spiega meglio cosa intendi per proprietà, oggetto e quant'altro...
WarDuck è offline   Rispondi citando il messaggio o parte di esso
Old 09-05-2011, 15:14   #4
tylerdurden83
Senior Member
 
Iscritto dal: Nov 2004
Messaggi: 691
Posto un pezzo del codice originale, poi lo commento un pochino.

Codice:
while (iter.hasNext()) {
	Item item = iter.next();
	boolean hasHit =item.hasStat(WoWConstants.Stats.HIT);
	boolean hasExpertise =item.hasStat(WoWConstants.Stats.EXPERTISE);
	if(hasHit && !hasExpertise){
	    // the item has only hit and not expertise
	    if(item.getStat(WoWConstants.Stats.HIT).getAmount()>=leastAmountOfHit && leastAmountOfHit>0){
	        // if this isnt the first item being tested and ...
	        ...
          iter.remove();
          continue;
      }
	    // set leastamountofhit. if this is the first item, set it to that item's hit
	    if(firstItem){
	        leastAmountOfHit=item.getStat(WoWConstants.Stats.HIT).getAmount();
	    } else if(leastAmountOfHit==0 || leastAmountOfHit>item.getStat(WoWConstants.Stats.HIT).getAmount()){
	        // otherwise update it only if this item has less hit, or leastamountofhit is still zero (the first item processed might not verify the hasHit !hasExpertise condition)
	        leastAmountOfHit=item.getStat(WoWConstants.Stats.HIT).getAmount();
	    }
	} else if(!hasHit && hasExpertise){
	    // the item has expertise only, not hit
	    if(item.getStat(WoWConstants.Stats.EXPERTISE).getAmount()>=leastAmountOfExpertise && leastAmountOfExpertise>0){
	        ...
	        iter.remove();
          continue;
      }
	    if(firstItem){
	        leastAmountOfExpertise=item.getStat(WoWConstants.Stats.EXPERTISE).getAmount();
	    } else if(leastAmountOfExpertise==0 || leastAmountOfExpertise>item.getStat(WoWConstants.Stats.EXPERTISE).getAmount()){
	        leastAmountOfExpertise=item.getStat(WoWConstants.Stats.EXPERTISE).getAmount();
	    }
	} else if(hasHit && hasExpertise){
	    // the item has both expertise and hit
	    if(item.getStat(WoWConstants.Stats.HIT).getAmount()>=leastAmountOfHitWhenBothPresent
	            && item.getStat(WoWConstants.Stats.EXPERTISE).getAmount()>=leastAmountOfExpertiseWhenBothPresent
	            && !firstItem){
	        ...
          iter.remove();
          continue;
	    }
	    // the values for items with both must be exclusive to them and updated at once, only if both are higher
	    if(firstItem){
	        leastAmountOfHitWhenBothPresent=item.getStat(WoWConstants.Stats.HIT).getAmount();
	        leastAmountOfExpertiseWhenBothPresent=item.getStat(WoWConstants.Stats.EXPERTISE).getAmount();
	    } else if((leastAmountOfHitWhenBothPresent>item.getStat(WoWConstants.Stats.HIT).getAmount() && leastAmountOfExpertiseWhenBothPresent>item.getStat(WoWConstants.Stats.EXPERTISE).getAmount())
	            || (leastAmountOfHitWhenBothPresent==0 && leastAmountOfExpertiseWhenBothPresent==0) ){
	        leastAmountOfHitWhenBothPresent=item.getStat(WoWConstants.Stats.HIT).getAmount();
	        leastAmountOfExpertiseWhenBothPresent=item.getStat(WoWConstants.Stats.EXPERTISE).getAmount();
	    }
	}
	...
In pratica, ogni item può avere n WoWConstants.Stats (valori di un'enumeration). Tuttavia, solo due delle n Stats mi interessano per decidere se effettuare delle remove da una lista. A seconda di quale è presente sull'i-esimo item, mi comporto diversamente, aggiorno variabili/contatori differenti, etc.

L'obiettivo è slegarmi dall'avere scolpito nel codice questo comportamento soltanto per quei due valori di WoWConstants.Stats, in modo da avere in input una lista di WoWConstants.Stats (1,2,n valori) al suo posto.
tylerdurden83 è offline   Rispondi citando il messaggio o parte di esso
Old 09-05-2011, 17:21   #5
banryu79
Senior Member
 
L'Avatar di banryu79
 
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
Ciao tylerdurden83,
presumo tu non conosca la libreria Guava di Google.
Facendo riferimento ad essa, ed utilizzando Predicate/Predicates e Function/Functions potresti fattorizzare e rendere modulare quest'aspetto della tua applicazione.

Un Predicate<Item> è un oggetto che rappresenta un predicato su un Item: cioè prende in ingresso un Item, e risponde con true se il predicato è vero per quell'Item.

Una Function<O,I> è un oggetto che rappresenta una funzione: prende in input un I (nel tuo caso un Item) e restituisce in output un O (quello che vuoi).
[in pratica Predicate è un caso speciale di Function: prende in input un tipo parametrico e restituisce un booleano]

Immagina ora di mappare (map) un dato predicato con una funzione.
Immagina di rappresentare questa mappa Predicati-Funzioni come una classe che, dato un Item è capace di scegliere ed eseguire su quell'Item la funzione associata al predicato per cui quell'Item è vero.

Un'istanza di tale classe potrà anche aggiungere-rimuovere dalla mappa associazioni arbitrarie di predicati-funzioni a runtime.

*Edit: trovi Predicate e Function nel package com.google.common.base; qualche tutorial nel web lo trovi facilmente, comunque i javadoc dovrebbero essere sufficienti.
Guava poi ha un sacco di altra roba comodissima, in particolare il package com.google.common.collect è una manna, ma puoi sempre vedertela con calma più avanti.
__________________

As long as you are basically literate in programming, you should be able to express any logical relationship you understand.
If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it.
(Chris Crawford)

Ultima modifica di banryu79 : 09-05-2011 alle 17:25.
banryu79 è offline   Rispondi citando il messaggio o parte di esso
Old 09-05-2011, 17:31   #6
sottovento
Senior Member
 
L'Avatar di sottovento
 
Iscritto dal: Nov 2005
Città: Texas
Messaggi: 1722
Quote:
Originariamente inviato da tylerdurden83 Guarda i messaggi
Ragazzi, ho un problema concettuale più che legato ad un linguaggio in particolare, per cui mi va bene un esempio in qualsiasi linguaggio o pseudocodice.

Attualmente il mio programma ha un blocchetto di codice del tipo

Codice:
if (haProprieta(A)== false && haProprieta(B)== false){
	...
} else if (haProprieta(A)== false && haProprieta(B)== true){
	...
} else if (haProprieta(A)== true && haProprieta(B)== false){
	...
} else if (haProprieta(A)== true && haProprieta(B)== true){
	...
}
A e B sono due proprietà del mio oggetto.
Ora però mi è stato chiesto di far si che possa avere un numero variabile di proprietà.
Il problema è come fare ad avere un numero parametrico di if then else nel mio software?
Ad esempio, nel caso abbia tre proprietà, dovrei avere:

Codice:
if (haProprieta(A)== false && haProprieta(B)== false && haProprieta(C)== false){
	...
} else if (haProprieta(A)== false && haProprieta(B)== false && haProprieta(C)== true){
	...
} else if (haProprieta(A)== false && haProprieta(B)== true && haProprieta(C)== false){
	...
} else if (haProprieta(A)== false && haProprieta(B)== true && haProprieta(C)== true){
	...
} ...
La struttura dati per contenere le proprietà non è un problema.
La creazione dei vari casi, anche usando una funzione ricorsiva, l'ho risolta, ma non riesco a capire se mi può essere d'aiuto (per capirci, ho capito come generare, nel caso di cui sopra, una matrice del tipo



che in effetti modella i vari blocchetti if then else, ma mi serve a qualcosa? E, se si, come usarla?...

Grazie a tutti, come sempre.
TD
Direi di si, mi sembra proprio il caso.
Se puoi, la soluzione che hai proposta e' semplice:

Codice:
int condizione = hasProperty(A) ? 1 : 0;
condizione |= hasProperty(B) ? 2 : 0;
condizione |= hasProperty(C) ? 4 : 0;
hai il numero che puo' corrispondere all'indice di una matrice o al case di uno switch....
__________________
In God we trust; all others bring data
sottovento è offline   Rispondi citando il messaggio o parte di esso
Old 09-05-2011, 18:25   #7
tylerdurden83
Senior Member
 
Iscritto dal: Nov 2004
Messaggi: 691
Grazie a entrambi, domani studio e provo e vi farò sapere!
tylerdurden83 è offline   Rispondi citando il messaggio o parte di esso
Old 10-05-2011, 12:45   #8
tylerdurden83
Senior Member
 
Iscritto dal: Nov 2004
Messaggi: 691
Per quanto riguarda la prima strada, ho costruito una funzione ricorsiva per generare la seguente matrice (ad es nel caso, come sopra, di sole due Stat):

Quote:
[!HIT, !EXPERTISE]
[!HIT, EXPERTISE]
[ HIT, !EXPERTISE]
[ HIT, EXPERTISE]
Se aggiungo una terza Stat, mi produce correttamente:

Quote:
[!HIT, !EXPERTISE, !SPIRIT]
[!HIT, !EXPERTISE, SPIRIT]
[!HIT, EXPERTISE, !SPIRIT]
[!HIT, EXPERTISE, SPIRIT]
[ HIT, !EXPERTISE, !SPIRIT]
[ HIT, !EXPERTISE, SPIRIT]
[ HIT, EXPERTISE, !SPIRIT]
[ HIT, EXPERTISE, SPIRIT]
Ora mi manca però il passetto subito dopo, ossia, data ad es la prima riga della matrice di cui sopra, come ottengo l'equivalente di:

Codice:
if(has(Hit)==false AND has(Expertise)== false AND has(Spirit)==false then ...
else if (has(Hit)==false AND has(Expertise)== false AND has(Spirit)==true then ...
Il problema non è chiaramente rimpiazzare Hit, Expertise e Spirit come input del metodo has(Stat), che potrebbero benissimo essere:

Codice:
if(has(Matrix(0,0))==false AND has(Matrix(0,1))== false AND has(Matrix(0,2))==false then ...
else if (has(Matrix(1,0))==false AND has(Matrix(1,1))== false AND has(Matrix(1,2))==true then ...
Il problema è come mettere in AND un numero di condizioni variabili (dato che non posso fare simil-sql, dove chiamo append su una stringa che modella ad es una query, prima di eseguirla). L'unico dato che ho è che se la matrice ha 3 colonne, allora dovrò avere 3 condizioni dentro ogni if, e 2^3 blocchetti if. Come faccio con dei cicli parametrici ad ottenere:

Codice:
if(has(Matrix(0,0))==false AND has(Matrix(0,1))== false AND has(Matrix(0,2))==false then ...
piuttosto che:

Codice:
if(has(Matrix(0,0))==false AND has(Matrix(0,1))== false then ...
etc?


Per quanto riguarda la soluzione di banryu79... non sono sicuro di riuscire a seguirti, non per quelle classi, la documentazione mi pare buona e tutto, ma proprio da un punto di vista concettuale...

Ultima modifica di tylerdurden83 : 10-05-2011 alle 13:09.
tylerdurden83 è offline   Rispondi citando il messaggio o parte di esso
Old 13-05-2011, 12:11   #9
tylerdurden83
Senior Member
 
Iscritto dal: Nov 2004
Messaggi: 691
uppino
tylerdurden83 è offline   Rispondi citando il messaggio o parte di esso
Old 15-05-2011, 16:22   #10
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
Visto che il thread langue diamogli una scossettina.

Uno dei modi più interessanti per risolvere un problema con un software è barare e spudoratamente.

Anzichè chiederci come si risolve il problema possiamo domandarci: data la soluzione che mi piacerebbe avere, che sarebbe comoda dal punto di vista della scrittura del codice, come ci arriviamo?

Ad esempio, sarebbe comodo, dato un Item, poter avere un elenco di proprietà diviso in due parti, una che esprime le proprietà che devono esserci e una quelle che non devono esserci, e collegarlo ad un certo blocco di codice?

Diremmo, in codice:

pippo = lista magica
pippo -> proprietà vere += A
pippo -> proprietà vere += B
pippo -> proprietà false += C
pippo -> se verificato per (Item) -> azione

Potremmo quindi pensare all'else come una concatenazione di pippi

superpippo = pippo1 else pippo2 else pippo3 else pippo4
superpippo -> se verificato per (item) -> azione

L'azione eseguita da superpippo sarebbe l'azione del pippo verificato per il concreto Item.

Un pippo sarebbe parametrico nelle proprietà e nella verità/falsità delle stesse, nell'item e nell'azione da eseguire nel caso in cui le condizioni si verifichino.

Superpippo sarebbe parametrico in pippo. Risulta che potremmo comporre a piacimento delle sequenze di proprietà/azioni da applicare ad una lista di Item per ottenere l'effetto desiderato.

In Scala scriveremmo:

Codice:
package test {

  /**
   * Item di prova
   */
  class Item(name: String) {
    import collection.mutable.HashMap
    private val map = HashMap[String, Any]()

    /**
     * Initializza questo item con un nome ed un set di proprietà
     */
    def this(name: String, properties: (String, Any)*) {
      this(name)
      map ++= properties
    }

    /**
     * true se questo item ha la proprietà col nome in argomento
     */
    def hasStat(statName: String): Boolean = map.contains(statName)

    /**
     * Restituisce il nome dell'item
     */
    override def toString(): String = {
      name
    }
  }

  /**
   * Elenco di proprietà verificabili per esistenza/inesistenza in un item
   */
  class PropVerifier {
    import collection.mutable.ListBuffer
    private val hasList = ListBuffer[String]()
    private val hasNotList = ListBuffer[String]()
    private var action: Option[Item => Unit] = None;

    /**
     * Aggiunge una proprietà che deve esistere nell'item affinchè questo verificatore
     * restituisca true
     */
    def has(propName: String): this.type = {
      hasList.append(propName)
      this
    }

    /**
     * Aggiunge una proprietà che non deve esistere nell'item affinchè questo verificatore restituisca true
     */
    def hasNot(propName: String): this.type = {
      hasNotList.append(propName);
      this
    }

    /**
     * Imposta l'azione che il verificatore intraprende nel caso in cui un item abbia tutte le proprietà che
     * deve avere e non abbia le proprietà che devono mancare
     */
    def then(fun: Item => Unit): this.type = {
      action = Some(fun)
      this
    }

    /**
     * Controlla che l'item in argomento abbia tutte le proprietà che deve avere e manchi di tutte quelle che
     * non deve avere
     */
    def check(item: Item): Boolean = {
      val hasCheck = !hasList.exists(s => item.hasStat(s) == false)
      val hasNotCheck = !hasNotList.exists(s => item.hasStat(s) == true)
      return hasCheck && hasNotCheck
    }

    /**
     * Esegue l'azione associata a questo verificatore
     */
    def takeAction(item: Item) {
      if(action.isDefined) action.get.apply(item)
    }
  }

  /**
   * Una serie di verificatori concatenati l'uno all'altro in reciproca esclusione
   */
  class PropVerifierChain {
    import collection.mutable.ListBuffer
    private val verifiers = ListBuffer[PropVerifier]()

    /**
     * Aggiunge un verificatore alla catena
     */
    def chain(v: PropVerifier): this.type = {
      verifiers.append(v)
      this
    }

    /**
     * Controlla se esiste un verificatore valido per l'item in argomento e lo esegue
     */
    protected def check(item: Item) {
      val applicableVerifier = verifiers.find(e => e.check(item) == true)
      if(applicableVerifier.isDefined) applicableVerifier.get.takeAction(item)
    }

    /**
     * Applica la catena di verificatori ad un insieme di Item
     */
    def apply(items: Iterable[Item]) {
      items.foreach(e => check(e))
    }
  }

  /**
   * Main object
   */
  object Test {

    /**
     * Esegue un test
     */
    def main(args: Array[String]) {

      /* Item di prova */
      val item0 = new Item("pippo", ("exp", 100), ("life", 10))
      val item1 = new Item("jhonny", ("exp", 10))
      val item2 = new Item("carmelo", ("life", 1))
      val item3 = new Item("augusto")

      /* Lista di item da passare alla catena di verificatori */
      val items = List(item0, item1, item2, item3)

      /* Inizializza la catena di verificatori */
      val verifier = new PropVerifierChain()
        /* Passa se item ha exp ma non life */
        .chain(new PropVerifier().has("exp").hasNot("life").then(withExpNotLife))

        /* Passa se item ha life ma non exp*/
        .chain(new PropVerifier().has("life").hasNot("exp").then(withLifeNotExp))

        /* Passa se item non ha life nè exp */
        .chain(new PropVerifier().hasNot("exp").hasNot("life").then(withNotExpLife))

        /* Passa se item ha exp e life */
        .chain(new PropVerifier().has("exp").has("life").then(withExpLife))

      /* Applica il verificatore */
      verifier.apply(items)
    }

    def withExpNotLife(item: Item) {
      println(item + " has exp but not life")
    }

    def withLifeNotExp(item: Item) {
      println(item + " has life but not exp")
    }

    def withNotExpLife(item: Item) {
      println(item + " has not life and exp")
    }

    def withExpLife(item: Item) {
      println(item + " has life and exp")
    }
  }
}
Ma lo stesso vale, salvo la sintassi, per qualsiasi linguaggio general purpose.

Nota che si può facilmente generalizzare la questione per supportare qualsiasi tipo di verifica (le condizioni di un if altro non sono che espressioni generiche le quali restituiscono true o false) o per eseguire insiemi di verifiche parzialmente esclusive (if-else-else, if if if else e via combinando).
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me!
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
Old 15-05-2011, 21:27   #11
tylerdurden83
Senior Member
 
Iscritto dal: Nov 2004
Messaggi: 691
Grazie per il tuo tempo PGI-Bis.

Riguardo il tuo approccio, l'ho letto ma c'è una cosa che non mi è ben chiara.

Ad esempio:

Codice:
/* Inizializza la catena di verificatori */
      val verifier = new PropVerifierChain()
        /* Passa se item ha exp ma non life */
        .chain(new PropVerifier().has("exp").hasNot("life").then(withExpNotLife))
Sostituire "exp", "life" etc è facile. Però hai scritto ".has(...).hasNot(...)". Hai quindi scolpito nel codice una lunghezza "due", per così dire. Hai ovviamente di conseguenza scolpito 4 casi, hasNot+hasNot, has+hasNot, hasNot+has, has+has.

Quello che servirebbe a me è non avere nulla di tutto ciò scolpito.

Per capirci, se questo non fosse java o c++ etc, ma una procedura sql, potrei avere che per la riga della matrice:

Quote:
!has(HIT), has(SPIRIT)
faccio un append di:

Quote:
where HIT = 0 and SPIRIT > 0
se avessi

Quote:
!has(HIT), has(SPIRIT), !has(STAMINA)
la stessa procedura sql mi appenderebbe

Quote:
where HIT = 0 and SPIRIT > 0 and stamina = 0
Chiaro, appendere condizioni ad una stringa per poi eseguire lo statement sql in essa contenuto è ben diverso che avere un numero variabile di condizioni dentro un if nel caso di linguaggi compilati tipo java... o non avrei dovuto chiedere aiuto!

Inizio a pensare che la cosa non si possa proprio risolvere...
tylerdurden83 è offline   Rispondi citando il messaggio o parte di esso
Old 15-05-2011, 22:57   #12
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
Per chiarire, l'esempio permette di combinare un numero indefinito di c'è/non c'è, in sequenze arbitrarie.

Fa cioè esattamente la stessa cosa di un "if-then-else" salvo l'essere limitato alla verifica dell'esistenza/inesistenza di una proprietà (piglia come argomenti degli Item e invoca ha/non ha).

Il test è eseguito su un numero prefissato di stringhe ma nulla vieta che le stringhe non siano scritte nel codice ma arrivino da una gui piuttostochè da un qualsiasi altro flusso dati.

Tuttavia questo è evidente il che mi spinge a pensare che il problema sia da qualche altra parte.

Forse vuoi rendere dinamica anche l'espressione condizionale? Cioè non vuoi limitarti a dire "se ha/non ha una proprietà" ma più in generale poter dire "se una qualsiasi espressione applicata ad un Item è vera/falsa"?

Se è così allora la soluzione è in quella "facile generalizzazione" che forse non pare poi così facile ma basta osservare PropChain per vedere che ciò che gli interessa è semplicemente che una generica espressione booleana su un item sia vera o falsa. Che verifichi o no una proprietà è irrilevante.

Oppure il problema è un altro ancora, nel qual caso non ho capito .
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me!
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
Old 15-05-2011, 23:09   #13
tylerdurden83
Senior Member
 
Iscritto dal: Nov 2004
Messaggi: 691
Immagina questo codice:

Codice:
List<Item> iMieiItem = ....
List<Proprieta> leProprieta = ....

for(Item item : iMieiItem){
    if(leProprieta.length==1){
        // ho solo due casi
        if(item.haProprieta(leProprieta.get(0))){
            ....
        } else {
            ....
        }
    } else if(leProprieta.length==2){
        // ho 4 casi
        if(item.haProprieta(leProprieta.get(0))==false && item.haProprieta(leProprieta.get(1))==false){
            ....
        } else if(item.haProprieta(leProprieta.get(0))==false && item.haProprieta(leProprieta.get(1))==true){
            ....
        } else if(item.haProprieta(leProprieta.get(0))==true && item.haProprieta(leProprieta.get(1))==false){
            ....
        } else if(item.haProprieta(leProprieta.get(0))==true && item.haProprieta(leProprieta.get(1))==true){
            ....
    } else if(leProprieta.length==3){
        // ho 8 casi
        if(item.haProprieta(leProprieta.get(0))==false && item.haProprieta(leProprieta.get(1))==false && item.haProprieta(leProprieta.get(2))==false){
            ....
        } else if(item.haProprieta(leProprieta.get(0))==false && item.haProprieta(leProprieta.get(1))==false && item.haProprieta(leProprieta.get(2))==true){
            ....
    } else if(leProprieta.length==4){
        // ho 16 casi
        ....
}
Come lo scriveresti parametrico sulla lunghezza di leProprieta.length?

Per analogia, è facile scrivere una procedura sql che appende ad una stringa una condizione in più nella clausola where, passando quindi da
Codice:
"where "+leProprieta.get(0)+" >0"
a
Codice:
"where "+leProprieta.get(0)+" >0".concat(" and "+leProprieta.get(1)+" >0")
mentre non è facile passare dinamicamente da
Codice:
if(item.haProprieta(leProprieta.get(0))==false && item.haProprieta(leProprieta.get(1))==false){
a
Codice:
if(item.haProprieta(leProprieta.get(0))==false && item.haProprieta(leProprieta.get(1))==false && item.haProprieta(leProprieta.get(2))==false){
java non mi permette certo di scrivere il mio if come una stringa e poi eseguirlo una volta concatenati i vari pezzetti...

Ultima modifica di tylerdurden83 : 15-05-2011 alle 23:15.
tylerdurden83 è offline   Rispondi citando il messaggio o parte di esso
Old 16-05-2011, 00:16   #14
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
Ahhhhh!

E' facile in Java tanto quanto lo è in SQL: per niente. Per niente perchè è un problema di calcolo combinatorio. L'ultima volta che ho dovuto farci i conti è stato nel 1634 quindi è molto probabile che io stia per dirti un certo numero di panzane, occhio.

Anzichè usare il PropVerifier così com'è devi dichiarare due classi di condizioni (qualcosa che applicato ad un Item resitutisce true/false), una per "HaProprietà" e una per "NonHaProprietà".

Al PropVerifier - che poi sarebbe l'If "dinamico" - dai una lista sola di condizioni.

Vale a dire:

Codice:
  trait Condition {
    def holds(item: Item): Boolean
  }

  class HasProperty(s: String) extends Condition {
    def holds(item: Item) = item.hasStat(s);
    override def toString() = "Ha " + s
  }

  class HasNotProperty(s: String) extends Condition {
    def holds(item: Item) = !item.hasStat(s)
    override def toString() = "Non ha " + s
  }

  class PropVerifier {
    import collection.mutable.ListBuffer
    private val conditions = ListBuffer[Condition]()
    private var action: Option[Item => Unit] = None

    def add(c: Condition): this.type = {
      conditions.append(c)
      this
    }

    def then(fun: Item => Unit): this.type = {
      action = Some(fun)
      this
    }

    def check(item: Item): Boolean = {
      val failure = conditions.exists(c => !c.holds(item))
      !failure
    }

    def takeAction(item: Item) {
      if(action.isDefined) action.get.apply(item)
    }
  }
Che succede a 'sto punto. La stessa cosa di prima solo che stavolta operi sulle combinazioni di condizioni Ha/Non ha generate a partire dalla lista di proprietà.

Il caso 1 (bella forza )

Codice:
  object Test {

    def main(args: Array[String]) {

      /* Item di prova */
      val item0 = new Item("pippo", ("exp", 100), ("life", 10))
      val item1 = new Item("jhonny", ("exp", 10))
      val item2 = new Item("carmelo", ("life", 1))
      val item3 = new Item("augusto")

      val properties = List("exp")
      val conditions = scala.collection.mutable.ListBuffer[Condition]()
      properties.foreach{ p =>
        conditions.append(new HasProperty(p))
        conditions.append(new HasNotProperty(p))
      }
      
      val verifier = new PropVerifierChain();
      for(i <- 0 until properties.size) {
        verifier.chain(new PropVerifier().add(conditions(i)).then(item => println(item + " " + conditions(i))))
      }
      verifier.apply(List(item0, item1, item2, item3))
    }
  }
}
Uso scala perchè è più sintetico ma è uguale in java, ci vuole solo qualche graffa in più.

Il punto è la parte in grassetto. In quel ciclo generi le combinazioni di condizioni ha/non ha dell'insieme che ottieni partendo dalla lista di proprietà.

Esiste al mille per mille la possibilità di generare in un ciclo molto più complicato le combinazioni possibili per un insieme di N condizioni (non ho capito bene la classe delle combinazioni che ti interessano ma credo che siano solo quelle di N elementi): una volta trovato l'algoritmo hai anche risolto il tuo problema.

Dovresti trovare qualcosa cercando "factoradics" in rete.
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me!
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
Old 16-05-2011, 00:51   #15
tylerdurden83
Senior Member
 
Iscritto dal: Nov 2004
Messaggi: 691
La generazione delle combinazioni in realtà l'ho risolta con una funzione ricorsiva che, ad es nel caso di 3 proprietà di input, mi crea una matrice di 8 righe per 3 colonne con tutte le combinazioni da testare.

Quote:
[!HIT, !EXPERTISE, !SPIRIT]
[!HIT, !EXPERTISE, SPIRIT]
[!HIT, EXPERTISE, !SPIRIT]
[!HIT, EXPERTISE, SPIRIT]
[ HIT, !EXPERTISE, !SPIRIT]
[ HIT, !EXPERTISE, SPIRIT]
[ HIT, EXPERTISE, !SPIRIT]
[ HIT, EXPERTISE, SPIRIT]
Ora però come proseguire? Ad esempio, nel caso attuale, non parametrico, limitato a due condizioni, facevo:

Codice:
....
if(!hasHit && hasExpertise){
   // the item has expertise only, not hit
   if(item.getStat(EXPERTISE).getAmount()>=leastAmountOfExpertise && leastAmountOfExpertise>0){
	        ...
   }
   if(leastAmountOfExpertise==0 || leastAmountOfExpertise>item.getStat(EXPERTISE).getAmount()){
       leastAmountOfExpertise=item.getStat(EXPERTISE).getAmount();
   }
} else if(hasHit && hasExpertise){
   // the item has both expertise and hit
   if(item.getStat(HIT).getAmount()>=leastAmountOfHitWhenBothPresent
        && item.getStat(EXPERTISE).getAmount()>=leastAmountOfExpertiseWhenBothPresent
        && !firstItem){
       ...
   }
if((leastAmountOfHitWhenBothPresent>item.getStat(HIT).getAmount() && leastAmountOfExpertiseWhenBothPresent>item.getStat(EXPERTISE).getAmount())
           || (leastAmountOfHitWhenBothPresent==0 && leastAmountOfExpertiseWhenBothPresent==0) ){
       leastAmountOfHitWhenBothPresent=item.getStat(HIT).getAmount();
       leastAmountOfExpertiseWhenBothPresent=item.getStat(EXPERTISE).getAmount();
}
Immagina di sostituire:

Codice:
if(!hasHit && hasExpertise){
che potrebbe modellare la riga di una matrice tipo quella sopra:

Quote:
[!HIT, EXPERTISE]
con

Codice:
if(Matrix(i,j).getStat()==Matrix(i,j).getBoolean() && Matrix(i,j+1).getStat()==Matrix(i,j+1).getBoolean()){
siamo d'accordo che ho parametrizzato l'if originale.
Quest'ultimo aveva scolpito dentro sia i riferimenti a quali stat controllare, sia a cosa eguagliarne il confronto (in pratica !hasHit() aveva scolpito che la stat da controllare era Hit e che la si stava valutando contro false)
Il nuovo if è parametrico sia su quale stat controllare, che se confrontarla con true oppure false.

Quindi, la matrice

Quote:
[!HIT, !EXPERTISE]
[!HIT, EXPERTISE]
[HIT, EXPERTISE]
[HIT, EXPERTISE]
può essere gestita tutta con quel solo if. Ciò fa si che la matrice

Quote:
[SPIRIT, EXPERTISE]
[!SPIRIT, EXPERTISE]
[SPIRIT, EXPERTISE]
[!SPIRIT, !EXPERTISE]
che differisce dalla predecente in due cose, ha SPIRIT invece di HIT, e ha un diverso ordinamento (la prima riga era false-false, ora è true-true) delle Stat, sia analizzabile perfettamente sempre da quel solo if postato sopra.
Cosa rimane scolpito anche nel secondo if? Il fatto che sto valutando due condizioni (non 1, non 3, ma precisamente due).
Il problema è se la matrice diventa di 3 colonne, perchè in java non posso fare

Codice:
String baseQuery = "if(Matrix(i,j).getStat()==Matrix(i,j).getBoolean() && Matrix(i,j+1).getStat()==Matrix(i,j+1).getBoolean()){"

if(la matrice ha 3 colonne){
   baseQuery .concat("&& Matrix(i,j+2).getStat()==Matrix(i,j+2).getBoolean()")
}
Ti faccio un esempio con una sintassi java (perchè è più easy che pl-sql) di quello che saprei fare in sql e vorrei fare in java.

Codice:
List<Item> iMieiItem = ....
List<Proprieta> leMieProprieta = ....
String baseQuery = "select A from B where "

for(Item item : iMieiItem){
     for(Proprieta prop : leMieProprieta){
          baseQuery = baseQuery.concat(prop.getStat+" ")
          if(prop.getBoolean==true){
                baseQuery = baseQuery.concat("> ")                 
          } else {
                baseQuery = baseQuery.concat("<= ")                 
          }
          baseQuery = baseQuery.concat("0")
      }
Questo codice mi restituisce correttamente, per input:

Quote:
[ HIT, !EXPERTISE]

select A from B where HIT > 0 and EXPERTISE <= 0
e per input:

Quote:
[ HIT, !EXPERTISE, SPIRIT]

select A from B where HIT > 0 and EXPERTISE <= 0 and spirit > 0
E' quindi indipendente da quale stat, da se deve esserci o meno, e da quante voglio controllarne, 1, 2, n è indifferente.

Ultima modifica di tylerdurden83 : 16-05-2011 alle 01:04.
tylerdurden83 è offline   Rispondi citando il messaggio o parte di esso
Old 16-05-2011, 12:11   #16
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
Parliamo ma non ci capiamo .

Quello che devi fare è usare la composizione: è la stessa cosa del "concat" solo che anzichè concatenare stringhe concateni invocazioni di metodi di istanze.

Questa è la traduzione in Java della concatenazione di stringhe sql

Codice:
import java.util.Arrays;
import java.util.List;

public class Main {

    public static void main(String[] args) {
        List<Item> items = Arrays.asList(new Item(), new Item(), new Item());
        List<Property> properties = Arrays.asList(new Property("exp"), new Property("life"));
        Query query = new Query();
        for (Item item : items) {
            for (Property prop : properties) {
                if(prop.getBoolean() == true) {
                    query.gt(prop, 0);
                } else {
                    query.let(prop, 0);
                }
            }
        }
    }
}
E questa è la query:

Codice:
import java.util.LinkedList;
import java.util.List;

public class Query {
    
    private static interface Condition {
        boolean eval(Item i);
    }
    
    private List<Condition> conditions = new LinkedList<Condition>();

    public void gt(final Property prop, final int threshold) {
        conditions.add(new Condition() {

            public boolean eval(Item item) {
                return item.getStat(prop.getStat()) > threshold;
            }
        });
    }

    public void let(final Property prop, final int threshold) {
        conditions.add(new Condition() {

            public boolean eval(Item item) {
                return item.getStat(prop.getStat()) <= threshold;
            }
        });
    }
    
    public boolean eval(Item item) {
        for (Condition condition : conditions) {
            if(!condition.eval(item)) return false;
        }
        return true;
    }
}
Probabilmente non ti serve esattamente in questi termini ma Query combina un insieme di condizioni ed è poi in grado di verificare se quella combinazione sia vera o falsa, a prescindere da quante siano o dalla loro natura.
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me!
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
Old 16-05-2011, 12:22   #17
rеpne scasb
Senior Member
 
Iscritto dal: May 2008
Messaggi: 533

Ultima modifica di rеpne scasb : 18-06-2012 alle 17:18.
rеpne scasb è offline   Rispondi citando il messaggio o parte di esso
Old 16-05-2011, 12:36   #18
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
Per come l'ho intesa io la parte che gli interessa sono le "s", cioè la determinazione di falsità o verità di un attributo degli item in relazione ad una proprietà. Cioè non è l'IF che gli serve ma l'espressione che ne determinerebbe il risultato.
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me!
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
Old 16-05-2011, 12:55   #19
rеpne scasb
Senior Member
 
Iscritto dal: May 2008
Messaggi: 533

Ultima modifica di rеpne scasb : 18-06-2012 alle 17:18.
rеpne scasb è offline   Rispondi citando il messaggio o parte di esso
Old 16-05-2011, 13:14   #20
tylerdurden83
Senior Member
 
Iscritto dal: Nov 2004
Messaggi: 691
Il problema è che io non devo avere un solo ritorno booleano a partire da N condizioni in or o and.
In sintesi, non mi interessa avere un modo per dire che FALSE && TRUE = FALSE, oppure che FALSE && FALSE && TRUE = FALSE.

Posto un esempio funzionante da poter lanciare voi stessi:

Codice:
import java.util.LinkedList;
import java.util.List;

public class ConcatenaIf {
    
    private static class Item {
        public int id;
        Item(int id){
            this.id=id;
        }
        public boolean hasStat(Stat s){
            return true;
        }
    }

    private static class Cella {
        public boolean trueOFalse;
        public Stat stat;
        Cella(boolean trueOFalse, Stat stat){
            this.trueOFalse=trueOFalse;
            this.stat=stat;
        }
    }

    private enum Stat {HIT, EXPERTISE};
    private static List<List<Cella>> matrix = new LinkedList<List<Cella>>();

    private static void initMatrix2x2(){
        // costruisco la matrice a mano, ma so come farla dinamicamente, quindi questo non è un problema
        Cella fHit = new Cella(false, Stat.HIT);
        Cella tHit = new Cella(true, Stat.HIT);
        Cella fExp = new Cella(false, Stat.EXPERTISE);
        Cella tExp = new Cella(true, Stat.EXPERTISE);
        List<Cella> riga1 = new LinkedList<Cella>();
        riga1.add(fHit);
        riga1.add(fExp);
        List<Cella> riga2 = new LinkedList<Cella>();
        riga2.add(fHit);
        riga2.add(tExp);
        List<Cella> riga3 = new LinkedList<Cella>();
        riga3.add(tHit);
        riga3.add(fExp);
        List<Cella> riga4 = new LinkedList<Cella>();
        riga4.add(tHit);
        riga4.add(tExp);
        matrix.add(riga1);
        matrix.add(riga2);
        matrix.add(riga3);
        matrix.add(riga4);
    }

    public static void main(String[] args){
        List<Item> oggetti = new LinkedList<Item>();
        oggetti.add(new Item(1));
        oggetti.add(new Item(2));
        oggetti.add(new Item(3));
        initMatrix2x2();
        for(Item item : oggetti){
            for(List<Cella> riga : matrix){
                //if(item.hasStat(riga.get(0).stat)==riga.get(0).trueOFalse
                //        && item.hasStat(riga.get(1).stat)==riga.get(1).trueOFalse){
                        System.out.println("Con l'if commentato qui sopra sto valutando se l'item "+item.id+" corrente" +
                                ((riga.get(0).trueOFalse) ? " ha " : " non ha ")+
                                "la Stat " +riga.get(0).stat + " e se"+
                                ((riga.get(1).trueOFalse) ? " ha " : " non ha ")+
                                "la Stat " +riga.get(1).stat);
                //}
            }
        }
    }
}
Output:

Quote:
Con l'if commentato qui sopra sto valutando se l'item 1 corrente non ha la Stat HIT e se non ha la Stat EXPERTISE
Con l'if commentato qui sopra sto valutando se l'item 1 corrente non ha la Stat HIT e se ha la Stat EXPERTISE
Con l'if commentato qui sopra sto valutando se l'item 1 corrente ha la Stat HIT e se non ha la Stat EXPERTISE
Con l'if commentato qui sopra sto valutando se l'item 1 corrente ha la Stat HIT e se ha la Stat EXPERTISE
Con l'if commentato qui sopra sto valutando se l'item 2 corrente non ha la Stat HIT e se non ha la Stat EXPERTISE
Con l'if commentato qui sopra sto valutando se l'item 2 corrente non ha la Stat HIT e se ha la Stat EXPERTISE
Con l'if commentato qui sopra sto valutando se l'item 2 corrente ha la Stat HIT e se non ha la Stat EXPERTISE
Con l'if commentato qui sopra sto valutando se l'item 2 corrente ha la Stat HIT e se ha la Stat EXPERTISE
Con l'if commentato qui sopra sto valutando se l'item 3 corrente non ha la Stat HIT e se non ha la Stat EXPERTISE
Con l'if commentato qui sopra sto valutando se l'item 3 corrente non ha la Stat HIT e se ha la Stat EXPERTISE
Con l'if commentato qui sopra sto valutando se l'item 3 corrente ha la Stat HIT e se non ha la Stat EXPERTISE
Con l'if commentato qui sopra sto valutando se l'item 3 corrente ha la Stat HIT e se ha la Stat EXPERTISE
Ora, immaginiamo di sostituire nel main la chiamata a initMatrix2x2(); con una a initMatrix8x3(); che genera la matrice 8 righe 3 colonne del caso 3 Stat. Mi sapreste trasformare l'if e la System.out in modo che stampi ad esempio:

Quote:
Con l'if commentato qui sopra sto valutando se l'item 1 corrente non ha la Stat HIT e se non ha la Stat EXPERTISE e se non ha la Stat SPIRIT
...
ovviamente senza aggiungere dentro l'if

Codice:
&& item.hasStat(riga.get(2).stat)==riga.get(2).trueOFalse
o dentro la System.out

Codice:
"la Stat " +riga.get(1).stat + " e se"+
((riga.get(2).trueOFalse) ? " ha " : " non ha ")+
"la Stat " +riga.get(2).stat);

Ultima modifica di tylerdurden83 : 16-05-2011 alle 13:17.
tylerdurden83 è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


I nuovi schermi QD-OLED di quinta generazione di MSI, per i gamers I nuovi schermi QD-OLED di quinta generazione di...
Recensione vivo X300 Pro: è ancora lui il re della fotografia mobile, peccato per la batteria Recensione vivo X300 Pro: è ancora lui il...
Lenovo Legion Go 2: Ryzen Z2 Extreme e OLED 8,8'' per spingere gli handheld gaming PC al massimo Lenovo Legion Go 2: Ryzen Z2 Extreme e OLED 8,8'...
AWS re:Invent 2025: inizia l'era dell'AI-as-a-Service con al centro gli agenti AWS re:Invent 2025: inizia l'era dell'AI-as-a-Se...
Cos'è la bolla dell'IA e perché se ne parla Cos'è la bolla dell'IA e perché se...
Amazon, tutte le offerte e qualche novit...
Sedie gaming in offerta su Amazon: desig...
Scope elettriche in offerta Amazon: mode...
Ricarica EV fino a 22 kW spendendo poco:...
Costa solo 139€ ma fa tutto: Lefant M330...
Amazon Haul spinge sul risparmio: sconti...
Oral-B iO in offerta su Amazon: maxi sco...
I cosmonauti avrebbero riparato tutte le...
Artemis II: la NASA conferma il lancio d...
Il CEO di Embrak Studios difende l'uso d...
Il Trump Phone è sempre più un mistero: ...
OPPO ha svelato la serie Reno 15 "global...
Poste ID diventa a pagamento: l'identità...
7 articoli crollati di prezzo su Amazon ...
Lavatappeti, smacchiatore e Vaporella a ...
Chromium
GPU-Z
OCCT
LibreOffice Portable
Opera One Portable
Opera One 106
CCleaner Portable
CCleaner Standard
Cpu-Z
Driver NVIDIA GeForce 546.65 WHQL
SmartFTP
Trillian
Google Chrome Portable
Google Chrome 120
VirtualBox
Tutti gli articoli Tutte le news Tutti i download

Strumenti

Regole
Non Puoi aprire nuove discussioni
Non Puoi rispondere ai messaggi
Non Puoi allegare file
Non Puoi modificare i tuoi messaggi

Il codice vB è On
Le Faccine sono On
Il codice [IMG] è On
Il codice HTML è Off
Vai al Forum


Tutti gli orari sono GMT +1. Ora sono le: 16:55.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Served by www3v