
## com.exprivia.data-viewer - Istruzioni per l'integrazione

### Descrizione
Le classi del pacchetto **data-viewer** implementano la visualizzazione delle
orbite di un satellite in un dato intervallo di tempo (permettendo la 
selezione di un orbita), e la successiva visualizzazione dei dati del 
prodotto associato all'orbita selezionata. I dati visualizzati (_variables_)
possono essere di tipo **POINT** o **AREA**.

Come stabilito, la sessione di **Data/Projects** (visualizzazione e selezione
delle orbite), e le due sessioni di visualizzazione dati (**Data/PointVariables** 
e **Data/AreaVariables**) sono implementate come _scene_ separate.

La comunicazione tra scene avviene mediante **ScriptableObjects**. Prima di 
effettuare il cambio scena, un componente della scena corrente scrive dei
valori in uno ScriptableObject. Dopo il cambio scena, un componente della
nuova scena legge i valori dallo ScriptableObject, e li usa per inizializzare
la nuova scena.

Ciascuna delle tre scene di questo pacchetto è composta da un istanza di un 
_prefab_ (i tre _prefab_ sono inclusi nel pacchetto), più un componente esterno al 
_prefab_, che si occupa della inizializzazione dello stesso, leggendo i dati da uno 
ScriptableObject.

La comunicazione tra la scena **DataProducts** e le due scene successive 
(**PointDataView** e **AreaDataView**) avviene mediante un istanza di uno scriptable object 
definito all'interno del pacchetto **data-viewer** (di nome **OrbitSelectConfig**), 
e quindi visibile da entrambe le scene.

La comunicazione tra la scena **DataProducts** e la scena precedente (sviluppata
separatamente in un altro progetto) deve avvenire mediante uno ScriptableObject
definito nell'altro progetto, e quindi non accessibile dalle classi del 
pacchetto **data-viewer**. Questo richiede un pò di lavoro per l'integrazione:


### Modifche da fare all'interno del progetto che lancierà la scena DataProducts: 

Nel progetto che implementa la scena precedente alla scena DataProducts, dovremo
aggiungere un nuovo script, chiamato **DataSessionConfig** e con questo contenuto:

```
using System;
using UnityEngine;

[CreateAssetMenu(fileName = "DataSessionConfig", menuName = "Data Session Config")]
public class DataSessionConfig : ScriptableObject
{
    public string dataType; // "POINT" or "AREA"
    public string satelliteId; // "ERS-1", "ERS-2"
    public DateTime StartTime;/*
    public DateTime EndTime;/*
}

```

Lo script **DataSessionConfig** dovrà essere esportato con il resto del 
pacchetto (dove è implementata la scena precedente).

Inoltre, prima di effettuare il cambio scena, un componente della scena precedente
dovrà scrivere i seguenti dati in uno scriptable object di tipo **DataSessionConfig**,
(assegnabile da Inspector):

 - **string dataType** che specifica il tipo di dati da visualizzare, e può essere 
settato a "POINT o a "AREA".

 - **string satelliteId** è una stringa di identificazione del satellite selezionato,
per esempio "Cryosat" o "ERS-1".

 - **DateTime StartTime** e **DateTime EndTime** specificano il periodo temporale
le cui orbite devono essere visualizzate.



### Integrazione del pacchetto nel progetto dell'applicazione: 

1. importare il pacchetto data-viewer dal PackageManager di Unity.
(importare anche il pacchetto dove è implementata la scena precedente)

2. In una cartella dentro l'Assets folder (tipo Assets/Config), creare uno
scriptable object di tipo **DataSessionConfig** (tasto destro: dal menu, 
scegliere "Create/Data Session Config"). Questo è lo scriptable object dal 
quale la scena DataProducts riceverà informazioni dall'alto.

3. creare anche uno scriptable object di tipo **OrbitSelectConfig** (tasto 
destro: dal menu, scegliere "Create/Satellite Data Config/Orbit Select").
Questo è lo scriptable object con il quale la scena DataProducts passerà
informazioni alla scena successiva.

4. Nella scena precedente a DataProducts, fornire una referenza alla nuova
istanza di **DataSessionConfig** al componente che effettua il cambio scena,
in modo che prima di cambiare scena, possa scriverci i valori come descritto sopra.

5. creare una nuova scena, chiamandola DataProducts.

6. nella scena DataProducts, aggiungere un istanza del 
prefab **OrbitSelectSubsession**, dalla cartella Prefabs del pacchetto 
data-viewer.

7. trascinare il gameobject appena aggiunto dalla scena ad una cartella
nell'Asset folder (tipo Assets/Prefabs), e scegliere l'opzione di creare
una **Prefab Variant**.

8. Nella scena DataProducts, modificare il campo **orbitSelectConfig** del 
componente **OrbitSelectSubsession**, facendolo puntare all'oggetto creato 
nel punto [3]. 

9. Creare un nuovo script di nome **OrbitSelectSessionInitializer** in 
Assets/Scripts, con il seguente contenuto:

```
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;

public class OrbitSelectSessionInitializer : MonoBehaviour
{
    public DataSessionConfig dataSessionCfg;
    public SatellitePointDataConfig[] pointDataSatellites;
    public SatelliteAreaDataConfig[] areaDataSatellites;
    public OrbitSelectSubsession subsession;

    public void Start()
    {
        if (dataSessionCfg.dataType == "POINT")
        {
            foreach(var s in pointDataSatellites)
            {
                if (s.satelliteId == dataSessionCfg.satelliteId)
                {
                    subsession.Initialize(s, dataSessionCfg.StartTime, dataSessionCfg.EndTime);
                    return;
                }
            }
            Debug.LogError($"OrbitSelectSessionInitializer: Invalid satelliteId {dataSessionCfg.satelliteId} for POINT data");
        }
        else if (dataSessionCfg.dataType == "AREA")
        {
            foreach (var s in areaDataSatellites)
            {
                if (s.satelliteId == dataSessionCfg.satelliteId)
                {
                    subsession.Initialize(s, dataSessionCfg.StartTime, dataSessionCfg.EndTime);
                    return;
                }
            }
            Debug.LogError($"OrbitSelectSessionInitializer: Invalid satelliteId {dataSessionCfg.satelliteId} for AREA data");
        }
        else
        {
            Debug.LogError($"OrbitSelectSessionInitializer: Invalid dataType {dataSessionCfg.dataType}");
        }
    }
}	

```

10. Nella scena DataProducts, creare un nuovo GameObject ed aggiungere un 
componente della nuova classe **OrbitSelectSessionInitializer**.

11. dall'inspector, settare il field **dataSessionCfg** (del nuovo componente)
allo scriptable object creato nel punto [2]

12. sempre dall'inspector, settare il field **OrbitSelectSubsession** del nuovo 
componente verso il componente attaccato alla root del prefab.

13. Nella cartella Assets/Config, creare istanze di scriptable object dei
tipi **SatellitePointDataConfig** e/o **SatelliteAreaDataConfig** (tasto 
destro: dal menu, scegliere "Create/Satellite Data Config/POINT Data Config",
oppure "Create/Satellite Data Config/AREA Data Config"), e configurarli come
descritto più in basso.

14. dall'inspector, aggiungere gli oggetti  **SatellitePointDataConfig** 
e/o **SatelliteAreaDataConfig** alle liste **pointDataSatellites** 
e **areaDataSatellites** del componente **OrbitSelectSessionInitializer**.

15. copiare le scene **PointDataViewScene** e/o **AreaDataViewScene** dal 
pacchetto DataViewer nella cartella Assets/Scenes dell'applicazione. 
Rinominarle se si vogliono usare nomi diversi.

16. Nella scena DataProduct, specificare i nomi delle due nuove scene (o una
sola, se il satellite supporta solo dati POINT o solo dati AREA) nei 
campi **Point Data Scene Name** e **Area Data Scene Name** del 
componente **OrbitSelectSubsession**

17. Tutte e tre le scene (DataProduct, PointDataViewScene e AreaDataViewScene)
andranno aggiunte alla lista delle scene nella finestra **Build Settings**.


### Configurazione di SatellitePointDataConfig: 

Ciascun oggetto di tipo **SatellitePointDataConfig** racchiude i parametri
necessari per poter visualizzare dati di tipo **POINT** relativi ad un 
singolo satellite.

Nello specifico:

**Satellite Id** è una stringa che identifica il satellite. Queste stringhe
devono essere le stesse che vengono scritte nello scriptable object di tipo 
**DataSessionConfig** (vedi il punto [2] sopra). Per esempio "Cryosat".

**Date Extraction Func** è una referenza ad uno scriptable object di tipo
derivato da DateExtractionFunc, che implementa una funzione che estrae due
date (start/end) dai nomi dei prodotti sul server. Esistono tre varianti
già pronte all'uso, relative ai diversi tipi di filename usati sui diversi 
server sui quali ho fatto dei test. 
Si trovano in Packages/DataViewer/Config e si chiamano CryosatDateExtractionFunc,
ERSPointDateExtractionFunc, e ERSAreaDateExtractionFunc. Scegliere quella che
funziona, o implementare una nuova classe derivando da DateExtractionFunc.

**Time Range Extraction Func** è una referenza ad uno scriptable object di tipo
derivato da TimeRangeExtractionFunc, che estrae date dal testo contenuto nel 
file TimeRange.txt, sul server. 
Ce ne sono due varianti pronte all'uso nella cartella Packages/DataViewer/Config:
ERS1TimeRangeExtractionFunc e ERS2TimeRangeExtractionFunc. Scegliere quella che
funziona, o implementare una nuova classe derivando da TimeRangeExtractionFunc.

**Url** è l'indirizzo della pagina principale dell'archivio dati sul server.
A questo indirizzo si trova il file TimeRange.txt (che specifica il time range
coperto dall'intero archivio), e le sottocartelle Index (con la lista dei 
prodotti associati a ciascun giorno) e Products (con i dati binari dei prodotti)

**Tle History Filename** è il path ad un file di testo (con formattazione TLE,
_two-line element_) che continene i dati necessari per ricostruire le orbite
di questo satellite nel tempo. [vedi quì](https://gportal.jaxa.jp/gpr/assets/mng_upload/GCOM-C/TLE_en.pdf) per
ulteriori info sul formato tle.
Credo che questo file vada scaricato dal web. Chiedere a Massimo Ricci.
Il file tle va salvato all'interno della cartella StreamingAssets, e il path da
inserire in questo campo è relativo a questa cartella (eg tle/cryosatTleHistory.txt).

**Profile Filename** è il path a un file xml di tipo ProductProfile, che 
continene le informazioni necessarie al parsing dei file binari dei pacchetti.
Per alcuni dettagli sul formato di questi file vedi il JIRA task **EUAT-23**.
Anche in questo caso, il path da inserire in questo campo è relativo alla
cartella StreamingAssets.



### Configurazione di SatelliteAreaDataConfig: 

Ciascun oggetto di tipo **SatelliteAreaDataConfig** racchiude i parametri
necessari per poter visualizzare dati di tipo **AREA** relativi ad un 
singolo satellite.

Alcuni campi sono gli stessi che per SatellitePointDataConfig:

**Satellite Id** è una stringa che identifica il satellite

**Date Extraction Func** è un riferimento a un DateExtractionFunc, per il
parsing dei filename dei prodotti

**Time Range Extraction Func** è un riferimento a un DateExtractionFunc, per il
parsing del contenuto del file TimeRange.txt, che sta sul server.

**Url** è l'indirizzo alla root dell'archivio, sul server. Nel caso di dati di 
tipo AREA, questo path viene usato per leggere il file TimeRange.txt e i file .idx 
all'interno della cartella Index.

**Tle History Filename** è il path al file in formato tle con i parametri
delle orbite di questo satellite.


La differenza principale tra la configurazione per dati di tipo POINT e 
dati di tipo AREA è che per i dati di tipo POINT, i valori di tutte le variabili
(eg "Sea Temperature", "Elastic Ocean Tide" ecc) sono salvati in un unico file
binario, mentre per i dati di tipo AREA, ciascuna variabile è salvata in un 
file binario separato.

Nella configurazione di **SatelliteAreaDataConfig** bisognerà quindi fornire
la lista delle variabili da visualizzare, aggiungendo elementi alla lista **Area Variables**.

Per ciascun elemento, vanno settati i seguenti campi:

**Variable Name** Nome della variabile (in realtà credo che questo non venga usato)
**Profile Filename** è il path al file xml che specifica il profilo del prodotto
da usare per scaricare dati di questa variabile. Nota che il ProductProfile in questo
caso avrà una singola variabile nella lista.
**Url** è l'indirizzo alla root dell'archivio per questa singola variabile, sul 
server. 

Nota che l'api fa affidamento sul fatto che la lista dei prodotti ottenuta dai 
file .idx scaricati dalla url principale (quella del field url della classe
SatelliteAreaDataConfig) sia valida per tutte le variabili.
Questo è implicito nel fatto che l'utente sceglie prima il prodotto (l'orbita)
e poi la variabile, e non viceversa.










