.pragma library


// Types unites :
const UNITE_VOLUME = 1;
const UNITE_TEMPERATURE = 2;
const UNITE_LATITUDE = 3;
const UNITE_LONGITUDE = 4;

// Unités de type Volume :
const UNITE_VOLUME_LITRES = 0;
const UNITE_VOLUME_US_GALLONS = 1;
const UNITE_VOLUME_IMP_GALLONS = 2;

// Unités de type Température :
const UNITE_TEMPERATURE_CELSIUS = 0;
const UNITE_TEMPERATURE_FAHRENHEIT = 1;

// Langues :
const LANGUE_FR = 0;
const LANGUE_EN = 1;
const LANGUE_DE = 2;
const LANGUE_ES = 3;
const LANGUE_PT = 4;
const LANGUE_NL = 5;
const LANGUE_IT = 6;
const LANGUE_LV = 7;    // Lettonie
const LANGUE_CA = 8;    // Catalan


// Positionnement GNSS :
const POSITION_VALEUR_ERRONNEE = 200000000;		// Valeur hors limite de latitude (-90 000 000 à +90 000 000) et longitude (-180 000 000 à +180 000 000)

const SHIPHEART_TYPE_CARTE_INCONNU = -1;
const SHIPHEART_TYPE_CARTE_SHIPBASE = 0;
const SHIPHEART_TYPE_CARTE_SHIPPOWER812 = 1;
const SHIPHEART_TYPE_CARTE_SHIPBS = 2;
const SHIPHEART_TYPE_CARTE_SHIPPOWER4AC = 3;
const SHIPHEART_TYPE_CARTE_SHIPPOWER8DC = 4;

const SHIPHEART_SOURCE_MESURE_CIRCUIT = 1;
const SHIPHEART_SOURCE_MESURE_CAPTEUR = 2;
const SHIPHEART_SOURCE_MESURE_RESERVOIR = 3;
const SHIPHEART_SOURCE_MESURE_BATTERIE = 4;


//=====================================================================================
// Fonctions  : Défini les paramètres d'affichage de la courbe en fonction du type de
//              période de temps choisie.
// Reçoit :     Le type de période
// Retour :     Les différents paramètres de la courbe
//=====================================================================================
function get_parametres_courbe(type_periode_graphique)
{
    switch(type_periode_graphique)
    {
        default:
        case 1:
            return {
                duree: (1 * 1 * 60 * 60),                       // En secondes
                regroupement: 1,                                // En secondes
                graduations_x: 7,                               // Nombre de bandes verticales + 1
                format_x: "HH:mm",                              // exemple : "yyyy-MM-dd HH:mm:ss"
                format: 0                                       // 0=format court ("hh:mm") et 1=format long ("MM/dd hh:mm")
            }

        case 2:
            return {
                duree: (1 * 24 * 60 * 60),                      // En secondes
                regroupement: 1,                                // En secondes
                graduations_x: 13,                              // Nombre de bandes verticales + 1
                format_x: "HH:mm",                              // exemple : "yyyy-MM-dd HH:mm:ss"
                format: 0                                       // 0=format court ("hh:mm") et 1=format long ("MM/dd hh:mm")
            }

        case 3:
            return {
                duree: (7 * 24 * 60 * 60),                      // En secondes
//                regroupement: (2 * 60),                       // En secondes
                regroupement: 1,                                // En secondes
                graduations_x: 8,                               // Nombre de bandes verticales + 1
                format_x: "dd/MM HH:mm",                        // exemple : "yyyy-MM-dd HH:mm:ss"
                format: 1                                       // 0=format court ("hh:mm") et 1=format long ("MM/dd hh:mm")
            }

        case 4:
            return {
                duree: (30 * 24 * 60 * 60),                     // En secondes
//                regroupement: (5 * 60),                         // En secondes
                regroupement: 1,                                // En secondes
                graduations_x: 31,                              // Nombre de bandes verticales + 1
                format_x: "dd",                                 // exemple : "yyyy-MM-dd HH:mm:ss"
                format: 1                                       // 0=format court ("hh:mm") et 1=format long ("MM/dd hh:mm")
            }
    }
}



//=====================================================================================
// Fonctions  : Calcule les valeurs mini et maxi optimales en fonction des valeurs
//              brutes de mini et de maxi de la série de données.
// Reçoit :     La valeur mini et maxi brutes
// Retour :     La valeur mini et maxi optimale
//=====================================================================================
function ajustement_mini_maxi(min, max, nb_graduations)
{
var ratio;

    if ((max < min) || (nb_graduations <= 0)) return(min);      // Si MIN > MAX ou si le nombre de graduations est nul, on ne peut rien faire...

    if (min === max)
    {
        if (min !== 0)
        {
            min = max * 0.95;                                   // On met le min à -5% en-dessous du maxi
            max = max * 1.05;                                   // On met le maxi à 5% au-dessus du mini
        }
        else return {mini: 0, maxi: 0.5 };                        // Si les deux valeurs sont égales à 0, on renvoit arbitrairement 0 et 1 en mini/maxi
    }

    ratio = Math.log10((max - min) / nb_graduations);
    if (ratio < 0) ratio = Math.trunc(ratio) - 1;               // Permet que -1.425 devienne -2
    else ratio = Math.trunc(ratio) + 1;                         // Permet que +1.425 devienne +2

    return {
            mini: Math.floor(min * Math.pow(10, (-ratio)))*Math.pow(10, ratio),
            maxi: Math.ceil(max * Math.pow(10, (-ratio)))*Math.pow(10, ratio),
        };

}


//=====================================================================================
// Fonctions  : Calcule la précision d'affichage optimale en fonction des valeurs brutes
//              de mini et de maxi de la série de données.
// Reçoit :     La valeur mini et maxi brutes
// Retour :     La précision optimale d'affichage
//=====================================================================================
function precision_affichage_mini_maxi(min, max, nb_graduations)
{
    var ratio;

    if ((max < min) || (nb_graduations <= 0)) return(0);       // Dans ce cas, on ne peut rien faire...

    if (min === max)
    {
        if (min !== 0)
        {
            min = max * 0.95;                                   // On met le min à -5% en-dessous du maxi
            max = max * 1.05;                                   // On met le maxi à 5% au-dessus du mini
        }
        else return 0;                                          // Si les deux valeurs sont égales à 0, on renvoit arbitrairement 0 comme précision
    }

    ratio = Math.log10((max - min) / (nb_graduations - 1));           // L'objectif est de définir le nombre de décades de l'intervalle entre 2 graduations.
//console.log("Ratio = " + ratio);

    if (ratio <= -2) return(3);                                  // Si l'intervalle est <= 0.001
    else if (ratio <= -1) return(2);                             // Si l'intervalle est <= 0.01
    else if (ratio <= 0) return(1);                              // Si l'intervalle est <= 0.1
    else return(0);                                             // Si l'intervalle est <= 1
}


//=====================================================================================
// Fonctions  : Génère une chaine de deux digits avec un caractère devant si la valeur
//              est inférieure à 9
// Reçoit :     La valeur et le caractère à ajouter si besoin (en général, '0' ou ' ')
// Retour :     La chaine sur 2 digits
//=====================================================================================
function format_deux_digits(val, lead)
{
    if (val <= 9) return(lead + val);
    else return(val);
}


//=====================================================================================
// Fonctions  : Convertit une grandeur reçue dans son unité par défaut dans l'unité
//              passée en paramètre. La valeur obtenue est formattée avec la précision
//              demandée et le symbole de la nouvelle unité est ajoutée à la fin (si
//              elle n'est pas vide).
// Reçoit :     La valeur à convertir, l'unité cible, le symbole de cette unité (ou
//              une chaine vide si aucune) et la précision (sous forme d'entier >= 0)
// Retour :     La valeur dans la nouvelle unité avec l'unité à la fin si elle est demandée
//=====================================================================================
function conversion_temperature(val, unite, symbole, precision)
{
    var retour;
    var tmp;

    switch(unite)
    {
        //--------------------------------------------------------------------------------
        // Températures :
        case UNITE_TEMPERATURE_CELSIUS:
            retour = val.toFixed(precision);                        // Unité de base des températures
            break;

        case UNITE_TEMPERATURE_FAHRENHEIT:
            retour = ((val * 1.8)+32).toFixed(precision);           // T(°F) = (9/5).T(°C) + 32
            break;

        //--------------------------------------------------------------------------------
        // Autres :
        default:
            retour = val.toFixed(precision);                        // Pour les capteurs dont l'unité de température ne serait pas connue
            break;
    }

    if (symbole !== "") retour = retour + " " + symbole;
    return(retour);
}

//=====================================================================================
// Fonctions  : Convertit une grandeur reçue dans son unité par défaut dans l'unité
//              passée en paramètre. La valeur obtenue est formattée avec la précision
//              demandée et le symbole de la nouvelle unité est ajoutée à la fin (si
//              elle n'est pas vide).
// Reçoit :     La valeur à convertir, l'unité cible, le symbole de cette unité (ou
//              une chaine vide si aucune) et la précision (sous forme d'entier >= 0)
// Retour :     La valeur dans la nouvelle unité avec l'unité à la fin si elle est demandée
//=====================================================================================
function conversion_volume(val, unite, symbole, precision)
{
    var retour;
    var tmp;

    switch(unite)
    {
        //--------------------------------------------------------------------------------
        // Volumes :
        case UNITE_VOLUME_LITRES:
            retour = val.toFixed(precision);                        // Unité de base des volumes
            break;

        case UNITE_VOLUME_US_GALLONS:
            retour = (val / 3.785411784).toFixed(precision);        // V(US Ga) = V(l) / 3.785411784
            break;

        case UNITE_VOLUME_IMP_GALLONS:
            retour = (val / 4.546090).toFixed(precision);            // V(Imp Ga) = V(l) / 4.546090
            break;

        //--------------------------------------------------------------------------------
        // Autres :
        default:
            retour = val.toFixed(precision);                        // Pour les capteurs dont l'unité de volume ne serait pas connue
            break;
    }

    if (symbole !== "") retour = retour + " " + symbole;
    return(retour);
}

//=====================================================================================
// Fonctions  : Transfère vers la fonction correspondant à 'type_unite'
//=====================================================================================
function conversion_unites(val, unite, symbole, precision, type_unite)
{
var retour;

    switch(type_unite)
    {
        case UNITE_VOLUME:
            retour = conversion_volume(val, unite, symbole, precision);
            break;
        case UNITE_TEMPERATURE:
            retour = conversion_temperature(val, unite, symbole, precision);
            break;
        case UNITE_LATITUDE:
            retour = chaine_latitude(val);
            break;
        case UNITE_LONGITUDE:
            retour = chaine_longitude(val);
            break;
        default:
            retour = val.toFixed(precision);                        // Pour les capteurs dont l'unité n'est ni un volume, ni une température
    }

    return(retour);
}


//=====================================================================================
// Fonction  :  Génère une chaine de latitude et/ou de longitude sous la forme 'xx.xxx°N'
//              ou 'xx.xxx°N - xx.xxx°E'
// Reçoit :     La valeur de latitude et/ou de longitude (-1 si pas utile)
// Retour :     La chaine générée
//=====================================================================================
function chaine_position(lat, lon)
{
    var chaine_lat, chaine_lon;
    var retour;

    // Calcul de la chaine de Latitude :
    if (lat !== -1) chaine_lat = chaine_latitude(lat);
    else chaine_lat = "";                                   // Si la valeur n'est pas demandée, cette partie de chaine sera vide

    // Calcul de la chaine de Longitude :
    if (lon !== -1) chaine_lon = chaine_longitude(lon);
    else chaine_lon = "";                                   // Si la valeur n'est pas demandée, cette partie de chaine sera vide

    if ((chaine_lat !== "") && (chaine_lon !== "")) retour = chaine_lat + " , " + chaine_lon;
    else retour = chaine_lat + chaine_lon;                  // Au moins une de vide, donc soit LAT, soit LON, soit ""

    return(retour);
}

//=====================================================================================
// Fonction  :  Génère une chaine de latitude sous la forme 'xx.xxx°N' ou 'xx.xxx°S'
// Reçoit :     La valeur de latitude
// Retour :     La chaine générée ou '---' si erreur
//=====================================================================================
function chaine_latitude(lat)
{
    var chaine_lat
    var retour;
    var suffixe;

    if (lat !== POSITION_VALEUR_ERRONNEE)
    {
        if (lat >= 0) suffixe = "N";                          // Les valeurs positives sont considérées comme au Nord
        else suffixe = "S"                                    // ... et les négatives au Sud

        chaine_lat = Math.trunc(lat) + "°" + ((lat - Math.trunc(lat)) * 60).toFixed(3) + "' " + suffixe;			// On fixe la précision à 3 digits après le point pour les secondes
    }
    else chaine_lat = "---°";                                   // Si la valeur reçue est hors limite, on affiche "---°"

    return(chaine_lat);
}

//=====================================================================================
// Fonction  :  Génère une chaine de longitude sous la forme 'xx.xxx°E' ou 'xx.xxx°W'
// Reçoit :     La valeur de longitude
// Retour :     La chaine générée ou '---' si erreur
//=====================================================================================
function chaine_longitude(lon)
{
    var chaine_lon;
    var retour;
    var suffixe;

    if (lon !== POSITION_VALEUR_ERRONNEE)
    {
        if (lon >= 0) suffixe = "E";                          // Les valeurs positives sont considérées comme à l'Est
        else suffixe = "W"                                    // ... et les négatives à l'Ouest

        chaine_lon = Math.trunc(lon) + "°" + ((lon - Math.trunc(lon)) * 60).toFixed(3) + "' " + suffixe;			// On fixe la précision à 3 digits après le point pour les secondes
    }
    else chaine_lon = "---°";                                   // Si la valeur reçue est hors limite, on affiche "---°"

    return(chaine_lon);
}

//=====================================================================================
// Fonction  :  Vérifie si la chaine reçue en paramètre correspond bien à une adresse IP V4
// Reçoit :     La chaine à vérifier
// Retour :     TRUE si l'adresse est correcte, FALSE sinon
//=====================================================================================
function test_format_adresse_ip_v4(ip) {

    var Reg = new RegExp(/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/);

    return Reg.test(ip);
}



//=====================================================================================
// Fonction  :  Renvoit le nom du type de carte à partir du code de type de carte
// Reçoit :     Le code du type
// Retour :     La chaine de caractère correspondant au type de carte reçu/
//=====================================================================================
function nom_type_module(code)
{
    var nom;

    switch(code)
    {
        //-----------------------------------------
        case SHIPHEART_TYPE_CARTE_INCONNU:
            nom = qsTr("Type non défini");
            break;

        //-----------------------------------------
        case SHIPHEART_TYPE_CARTE_SHIPBASE:
            nom = "ShipBase";
            break;

        //-----------------------------------------
        case SHIPHEART_TYPE_CARTE_SHIPPOWER812:
            nom = "ShipPower812";
            break;

        //-----------------------------------------
        case SHIPHEART_TYPE_CARTE_SHIPBS:
            nom = "ShipBS";
            break;

        //-----------------------------------------
        case SHIPHEART_TYPE_CARTE_SHIPPOWER4AC:
            nom = "ShipPower4AC";
            break;

        //-----------------------------------------
        case SHIPHEART_TYPE_CARTE_SHIPPOWER8DC:
            nom = "ShipPower8DC";
            break;


        //-----------------------------------------
        default:
            nom = qsTr("Modèle inconnu");
            break;
    }

    return(nom);
}

//=====================================================================================
// Fonction  :  Renvoit le nom du type d'équipement à partir du code de type
// Reçoit :     Le code du type
// Retour :     La chaine de caractère correspondant au type d'équipement reçu
//=====================================================================================
function nom_type_equipement(code)
{
    var nom;

    switch(code)
    {
        //-----------------------------------------
        case SHIPHEART_SOURCE_MESURE_CIRCUIT:
            nom = qsTr("Circuit");
            break;

        //-----------------------------------------
        case SHIPHEART_SOURCE_MESURE_CAPTEUR:
            nom = qsTr("Capteur");
            break;

        //-----------------------------------------
        case SHIPHEART_SOURCE_MESURE_RESERVOIR:
            nom = qsTr("Réservoir");
            break;

        //-----------------------------------------
        case SHIPHEART_SOURCE_MESURE_BATTERIE:
            nom = qsTr("Batterie");
            break;

        //-----------------------------------------
        default:
            nom = qsTr("Type inconnu");
            break;
    }

    return(nom);
}


//=====================================================================================
// Fonction  :  Renvoit le nom d'une variabme à partir de son code
// Reçoit :     Le code de la variable
// Retour :     La chaine de caractère correspondant au code variable reçu
//=====================================================================================
function nom_variable(code)
{
    var nom;

    switch(code)
    {
        //---------------------
        case "Circ_consigne":
            nom = qsTr("Consigne");
            break;

        //---------------------
        case "Circ_tension":
            nom = qsTr("Tension");
            break;

        //---------------------
        case "Circ_courant":
            nom = qsTr("Courant");
            break;

        //---------------------
        case "Circ_frequence":
            nom = qsTr("Fréquence");
            break;

        //---------------------
        case "Circ_puissance":
            nom = qsTr("Puissance");
            break;

        //---------------------
        case "Circ_energie":
            nom = qsTr("Energie");
            break;

        //---------------------
        case "Circ_tension_secteur":
            nom = qsTr("Tension");
            break;

        //---------------------
        case "Batt_temperature":
            nom = qsTr("Température");
            break;

        //---------------------
        case "Batt_tension":
            nom = qsTr("Tension");
            break;

        //---------------------
        case "Batt_courant_differentiel":
            nom = qsTr("Courant différentiel");
            break;

        //---------------------
        case "Batt_courant_charge":
            nom = qsTr("Courant de charge");
            break;

        //---------------------
        case "Batt_courant_decharge":
            nom = qsTr("Courant de décharge");
            break;

        //---------------------
        case "Batt_soh":
            nom = qsTr("SOH (state Of Health)");
            break;

        //---------------------
        case "Batt_soc":
            nom = qsTr("SOC (State Of Charge)");
            break;

        //---------------------
        case "Batt_autonomie":
            nom = qsTr("Autonomie");
            break;

        //---------------------
        case "Batt_puissance":
            nom = qsTr("Puissance");
            break;

        //---------------------
        case "Batt_energie":
            nom = qsTr("Energie");
            break;
    }

    return(nom);
}


//=====================================================================================
// Fonctions  : Génère une chaine de caractère correspondant à la taille du fichier
//              dont la valeur, en octet, est reçue en paramètres
// Reçoit :     La taille du fichier, en octets
// Retour :     La chaine
//=====================================================================================
function taille_fichier(taille, langue)
{
    var unite_octet;

    switch(langue)
    {
        //--------------------------------------------------------
        case LANGUE_EN:
        case LANGUE_ES:
        case LANGUE_PT:
        case LANGUE_NL:
        case LANGUE_IT:
        case LANGUE_LV:                 // Lettonie
        case LANGUE_CA:
        default:
            unite_octet = "b";
            break;
        //---------------------------------------------------------
        case LANGUE_FR:
            unite_octet = "o";
            break;
        //---------------------------------------------------------
        case LANGUE_DE:
            unite_octet = "B";
            break;
    }


    // Inférieur à 1ko :

    if (taille < 1000) return (taille + unite_octet);

    // Entre 1ko et moins de 1Mo :
    taille /= 1000;
    if (taille < 10) return (taille.toFixed(1) + "k" + unite_octet);
    if (taille < 1000) return (taille.toFixed(0) + "k" + unite_octet);

    // Entre 1Mo et moins de 1Go :
    taille /= 1000;
    if (taille < 10) return (taille.toFixed(1) + "M" + unite_octet);
    if (taille < 1000) return (taille.toFixed(0) + "M" + unite_octet);

    // Entre 1Go et moins de 1To :
    taille /= 1000;
    if (taille < 10) return (taille.toFixed(1) + "G" + unite_octet);
    if (taille < 1000) return (taille.toFixed(0) + "G" + unite_octet);

    taille /= 1000;
    return (taille.toFixed(1) + "T" + unite_octet);
}



