1 Introduzione


La classe “ParametriEdInput”



Scaricare 459.5 Kb.
Pagina12/15
29.03.2019
Dimensione del file459.5 Kb.
1   ...   7   8   9   10   11   12   13   14   15
3.1.2.2 La classe “ParametriEdInput”:
Questa classe è una lista di possibili parametri ed input che ogni componente può avere. Sono tutti inizializzati a “False” e verranno settati solo quando il componente verrà creato.


3.1.2.3 La classe “DragCanvas”:
Questa classe rappresenta il vero e proprio programma ed è suddivisa in due parti: nella prima viene costruito il layout della finestra e la griglia, nella seconda vengono creati i componenti e viene fatto il controllo della composizione.

Subito dopo l’inizializzazione delle variabili globali viene settato il tipo di cursore del mouse (con il comando “self.SetCursor”), successivamente viene impostato come sfondo il bitmap “griglia2” che si trova nella cartella “bitmaps” (con il comando “self.bg_bmp=”).

Poi segue l’inserimento di una serie di colonne di bitmap che servono per fare da contenitore per i componenti; particolare importanza ha la “barra2.bmp” che descrive il nome dei decodificatori e dei codificatori (che sono anche disegnati su ciascun componente sotto forma di sigla).

Successivamente vengono creati i veri e propri componenti: viene importato il bitmap specifico dalla cartella “bitmaps” e viene creata un’istanza della classe “DragShape” passandole come parametro l’immagine caricata precedentemente; poi vengono settati a “True”tutti i suoi parametri, viene assegnato all’istanza il suo tipo (con il comando “self.type=”).


Ogni componente ha un tipo diverso che verrà utilizzato al momento della costruzione del circuito (che verrà utilizzato per il controllo della presenza di possibili errori); le coppie componente-tipo sono le seguenti:


COMPONENTI

TIPO ( INTERO)




GENERATOR

4

ENPUNCTURE

1

RSENCODER

5

CENCODER

7

CHANNEL

2

DEPUNCTURE

3

VDECODER

8

RSDECODER

6

COMPARATOR

9

Il componente viene posizionato attraverso l’assegnamento di due valori alla sua variabile “shape.pos” (che è di tipo “wxPoint”)che prende due interi come parametri ( rappresentanti l’ascissa e l’ordinata nello schermo del suo angolo superiore sinistro).

Una volta riempiti tutti questi campi, l’istanza di “DragShape” viene inserita in un vettore chiamato “shapes” attraverso il comando “ self.shapes.append(shape)”.

Visto che durante la costruzione di un circuito possono essere riutilizzati più volte gli stessi componenti, tutte queste operazioni fanno parte del corpo di un ciclo “for”che visualizza più componenti dello stesso tipo (sovrapponendoli).

Questa operazione viene ripetuta nove volte (cioè per ogni componente).

Seguono poi le chiamate degli eventi e le loro descrizioni; le prime tre chiamate di evento (EVT_ERASE_BACKGROUND(self, self.OnEraseBackground), EVT_PAINT(self, self.OnPaint),EVT_LEFT_DOWN(self, self.OnLeftDown)) sono delle chiamate standard per il “drag and drop”: si occupano della selezionabilità di un oggetto e della allocazione di memoria per l’oggetto che viene scelto.

La chiamata più importante è sicuramente “EVT_LEFT_UP(self, self.OnLeftUp)” dove viene richiamata la procedura “OnLeftUp” che è quella che si occupa della composizione del circuito e della verifica degli errori di costruzione.

La procedura “OnLeftUp” parte dal rilascio del pulsante sinistro del mouse (quindi da quando viene rilasciato il componente ); per prima cosa vengono salvate le attuali coordinate del pezzo rilasciato (cioè “self.pos.x” e “self.pos.y”)e memorizzate in due vettori dichiarati globali che sono “matrix” e “ordinate”.

Nel primo array viene salvata, nella posizione “self.pos.x”, il tipo del componente; nel secondo, sempre nella posizione “self.pos.x”, viene salvata l’ordinata del componente (cioè “self.pos.y”).

In questo modo, scorrendo i due vettori si può sapere che ad un determinato punto dello schermo c’è un componente di un determinato tipo.

Si sarebbe potuta utilizzare anche una matrice, ma in Python le matrici non esistono con la normale distribuzione; per utilizzarle è infatti necessario scaricare un pacchetto di nome “NumPy” che si occupa di funzioni matematiche e strutture dati più complesse; il programma però ne avrebbe risentito nella sua portabilità, visto che il pacchetto in questione è ancora in pre-alpha e non è ancora molto diffuso e quindi la maggior parte degli utenti non avrebbe potuto utilizzare il programma.

Salvate le coordinate, viene fatto un controllo sulla variabile “type” del componente in uso e, a seconda del tipo, vengono effettuate delle operazioni diverse.

Se è stato trascinato sulla griglia un generatore, verrà inserito in un vettore globale chiamato “circuito” il tipo del generatore nella posizione “indice”(altra variabile globale inizializzata a zero).

Il vettore “circuito” ha lo scopo di memorizzare in ordine tutti i tipi dei componenti inseriti nel circuito, in modo che, quando il circuito sarà completo, si potranno trovare eventuali errori di costruzione.

Successivamente la variabile “indice” viene incrementata di una unità e vengono salvate in altre due variabili l’ascissa e l’ordinata del generatore (con le istruzioni” self.ordinatagen=self.dragShape.pos.y , self.ascissaesatta=self.dragShape.pos.x+83”).

Queste due variabili sono necessarie per l’allineamento automatico dei pezzi che vengono inseriti; infatti, se l’inserimento risulterà corretto, i componenti successivi verranno riposizionati tutti ad altezza “ordinatagen” ed avranno come ascissa l’ascissa del componente precedente più 83 (che rappresenta la larghezza di ogni componente); in questo modo i lati contigui dei pezzi inseriti combaceranno.

Se invece è stato inserito un codificatore di tipo “Enpuncture” (ovvero se il tipo risulta uguale ad 1) vengono eseguiti dei controlli diversi : per prima cosa vengono salvate le coordinate del componente in due variabili locai “a” e “j”; successivamente viene eseguito un ciclo “while” con una guardia che parte da zero ed arriva fino a duecento.

Per ogni iterazione del ciclo vengono esaminati i contenuti dei vettori “martix” e “ordinate”, partendo da quelli che hanno un indice pari all’indice del componente in esame meno duecento fino ad arrivare a quelli che si trovano nella posizione di indice precedente al componente.

Una volta che il contenuto dei due vettori è stato salvato in altre due variabili locali di nome “b” e “d” viene fatto un controllo da un “if”: se il tipo estratto dal vettore “matrix” corrisponde a quello di un generatore oppure ad un qualunque codificatore o decodificatore e se l’ordinata del pezzo è compresa nell’intervallo [d-100,d+100] (con “d” ordinata del componente inserito precedentemente) allora il tipo del componente in esame viene inserito nel vettore “circuito” nella posizione “indice”; poi la variabile indice viene incrementata di una unità ed infine il componente viene riposizionato correttamente attraverso il controllo delle variabili “ordinatagen” e “ascissaesatta”.

In seguito viene eseguita un istruzione di “break” per uscire dal ciclo “while”.

Nel caso in cui, scorrendo tutto il vettore “matrix”, non si trovino pezzi inseriti precedentemente (cioè z =199) oppure si trovi un pezzo diverso sia dal generatore che dal codificatore, viene chiamata una procedura definita come “runErrore3()” che visualizza un frame contenente un messaggio di errore; quindi il pezzo viene riposizionato nella barra dei componenti e la sua ordinata e la sua ascissa vengono cancellate dai vettori “matrix” e “ordinate”.

Lo stesso tipo di controllo verrà effettuato anche per gli altri pezzi con l’unica differenza che nel caso del canale verrà controllato se prima del suo inserimento ci sia un codificatore, mentre nel caso del decodificatore è necessario che prima sia stato inserito un canale oppure un qualunque decodificatore.

Per quanto riguarda il Confrontatore (o Printerr) è necessario che prima di lui sia stato posizionato un decodificatore.

Dopo aver fatto i controlli ed i dovuti inserimenti dei tipi nel vettore “circuito”, non è detto che il circuito sia stato costruito correttamente: infatti potrebbero essere presenti errori dovuti alla violazione del vincolo decodificatore-codificatore (Cap. 2 , fig. 2.7), cioè potrebbero essere stati inseriti decodificatori senza che il rispettivo codificatore sia stato usato e viceversa.

Per questo motivo , dopo l’inserimento del Codificatore, viene fatto un ulteriore controllo sul vettore “circuito” che individua questi tipi di errori.

Per prima cosa viene copiato, attraverso un ciclo “for”, il vettore “circuito” in un altro vettore chiamato “verificacir”, poi viene eseguito un ciclo “while” che itera tante volte quanto il valore della variabile “indice”; nel corpo del ciclo viene selezionato il primo elemento di “verificacir”, se questi è un Enpuncture allora viene eseguito un altro ciclo che controlla se nel vettore, dopo l’Empuncture, è presente un Depuncture ed in caso affermativo i loro rispettivi valori vengono sovrascritti con l’intero “666”.

Se invece il primo elemento è un Rsencoder oppure un Cencoder verrà cercato il rispettivo decodificatore ed in caso affermativo verranno sovrascritti con “666”.

Finita questa operazione viene eseguito un altro ciclo che sovrascrive anche i canali , il Generatore ed il Confrontatore; a questo punto, se il circuito è stato costruito correttamente, nel vettore “verificacir” si dovrebbero trovare, fino alla posizione “indice”, solo celle di valore “666” e quindi viene eseguito un ciclo che ricontrolla il vettore.

Nel caso in cui ci siano dei valori diversi da “666” vuol dire nella costruzione del circuito sono stati inseriti dei decodificatori senza il corrispettivo codificatore o viceversa e quindi viene eseguito il metodo “runErrore5( )” che stampa un messaggio di errore ed invita l’utente a ricostruire dall’inizio il circuito.

Le seguenti tre istruzioni ( self.dragShape.shown = True , self.dragShape.Draw(dc), self.dragShape = None ) servono per visualizzare il componente sullo schermo e liberare la memoria dall’immagine del componente.


Seguono una serie di comandi che fungono da ponte tra questo progetto e la sua futura continuazione , con molta probabilità questa parte verrà totalmente riscritta, ma ho preferito non cancellarla totalmente perché sono presenti alcune strutture ed alcuni comandi che potrebbero servire per il futuro sviluppo (come la bufferizzazione dell’input da tastiera ed il passaggio di oggetti come parametro di procedura) e quindi facilitare il compito di chi continuerà questo programma.
Questi comandi ricontrollano il vettore “circuito” e per ogni componente fanno apparire una serie di finestre che chiedo il settaggio dei parametri e l’input di ogni componente.




Condividi con i tuoi amici:
1   ...   7   8   9   10   11   12   13   14   15


©astratto.info 2019
invia messaggio

    Pagina principale