Requisiti
- Quando il sonar rileva un ostacolo a una distanza minore di una soglia prefissata DMIN, le lucciole devono lampeggiare in modo sincronizzato.
- Quando la distanza dell’ostacolo (ri)supera DMIN, le lucciole tornano a lampeggiare in modo random (asincrono).
Analisi dei Requisiti
- Sonar: Un'entità (fisica o simulata) che genera eventi asincroni contenenti dati sulla distanza.
- Soglia DMIN: Il valore critico che determina il cambio di stato del sistema.
- Comportamento Ibrido: A differenza del progetto precedente, la sincronizzazione non è uno stato definitivo. Le lucciole devono possedere due modalità operative intercambiabili (Random e Sincrona).
- Reversibilità: Il sistema deve poter tornare fluidamente allo stato iniziale quando l'ambiente fisico cambia.
Analisi del Problema
Architettura del Sistema Estesa
Il sistema mantiene la separazione in due contesti (ctxfirefly e ctxgrid), ma introduce una nuova fonte di dati: l'evento globale sonar_data : distance(D), generato da un componente hardware reale o da un attore mock (sonarsimulator).
La necessità di alternare tra modalità random e sincrona impone un cambiamento radicale alla logica di controllo. Il Coordinatore non può più limitarsi a emettere un segnale di clock fisso. Deve diventare un coordinatore capace di:
- Ascoltare continuamente i dati del sonar.
- Valutare la condizione
D < DMIN. - Attivare/disattivare dinamicamente il segnale di clock (il "metronomo" da 1500ms) inviando comandi espliciti alle lucciole (
startSyncestopSync).
whenTime) e una reattiva (whenEvent) nello stesso blocco di stato. Per risolvere questo conflitto, è stato introdotto il pattern dello "Stato Vuoto" (work), che funge da snodo non bloccante per l'attore.
Progetto
Il Coordinatore "Intelligente"
Il IsSyncActive. Utilizza uno stato di attesa attiva (work) per alternare la gestione del timer (emissione del clock) e l'arrivo asincrono dei dati del sonar.
State work {// Punto di snodo non bloccante }Transition t0whenTime 1500 -> emitSyncSignalwhenEvent sonar_data -> handleSonarState handleSonar {onMsg ( sonar_data : distance(D) ){ [# var Distance = payloadArg(0).toInt() #] if [# Distance < DMIN #] { if [# !IsSyncActive #] {emit startSync : startSync(1) [# IsSyncActive = true #] } } else {// Logica inversa per stopSync } } }Goto work
Firefly: Attori Ibridi e Reversibili
Le lucciole ora alternano un ciclo interno autonomo (tramite delay randomici) a uno stato reattivo in cui attendono il segnale dal coordinatore.
// --- MODALITÀ ASINCRONA --- State randomFlashing {// Lampeggio con timer interno casuale }Transition t0whenTime 50 -> randomFlashingwhenEvent startSync -> wait_sync// --- MODALITÀ SINCRONA --- State wait_sync {// In attesa del segnale di clock globale }Transition t1whenEvent sync -> flashwhenEvent stopSync -> randomFlashing
Vantaggi della soluzione
- Reattività: Il sistema risponde ai cambiamenti ambientali (sonar) in tempo reale.
- Modularità: La logica della distanza è centralizzata nel coordinatore; le lucciole ignorano cosa sia il sonar e si limitano a obbedire ai segnali di cambio stato.