Documentação da API "iarotas.com.br"

Iniciar IA rotas

Este é um exemplo de código HTML e JavaScript para inicializar um mapa:


        <!DOCTYPE html>
        <html lang="pt-BR">
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>Mapa com IArotas</title>
            
            <!-- Importação do IArotas -->
            <link rel="stylesheet" href="https://iarotas.com.br/IArotas/IArotas.css" />
            <script src="https://iarotas.com.br/IArotas/IArotas.js"></script>
        
            <style>
                /* Define o tamanho do mapa */
                #map {
                    height: 500px;
                    width: 100%;
                }
            </style>
        </head>
        <body>
        
            <h2>Mapa com IArotas</h2>
            <div id="map"></div>
        
            <script>
                document.addEventListener("DOMContentLoaded", function () {
                    // Inicializa o mapa e define o centro e o zoom
                    const map = L.map('map').setView([-19.9269086, -43.9386425], 13);
        
                    // Adiciona um mapa base
                    L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
                        maxZoom: 19,
                        attribution: ''
                    }).addTo(map);
        
                    // Definição de dois pontos e ajuste de limites do mapa
                    const bounds = L.latLngBounds([
                        [-19.9269086, -43.9386425], // Ponto 1
                        [-19.7996, -44.018]         // Ponto 2
                    ]);
                    map.fitBounds(bounds); // Ajusta o zoom para incluir os pontos
        
                    // Adiciona marcadores nos pontos
                    L.marker([-19.9269086, -43.9386425]).addTo(map)
                        .bindPopup("Ponto 1: Belo Horizonte").openPopup();
        
                    L.marker([-19.7996, -44.018]).addTo(map)
                        .bindPopup("Ponto 2: Região Metropolitana");
        
                    // Desenha uma linha entre os dois pontos
                    L.polyline([
                        [-19.9269086, -43.9386425],
                        [-19.7996, -44.018]
                    ], { color: 'blue' }).addTo(map);
                });
            </script>
        
        </body>
        </html>
            

Funcionalidades

1. map.fitBounds(bounds)

O que faz: Ajusta a visualização do mapa para que todos os marcadores ou elementos estejam visíveis dentro de uma área delimitada.

const bounds = L.latLngBounds([
            [-19.9269086, -43.9386425], // Coordenadas do ponto 1
            [-19.7996, -44.018]         // Coordenadas do ponto 2
        ]);
        map.fitBounds(bounds); // Ajusta o zoom para mostrar ambos os pontos

2. map.setView(center, zoom)

O que faz: Define o centro e o nível de zoom do mapa.

map.setView([-19.9269086, -43.9386425], 13); // Centraliza o mapa nas coordenadas e define o zoom para 13

3. L.tileLayer(url, options)

O que faz: Adiciona uma camada de tiles (imagens de mapa) ao mapa. Pode ser usado para carregar mapas de diferentes provedores, como OpenStreetMap, Google Maps, etc.

L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
                maxZoom: 19,
                attribution: ''
            }).addTo(map); // Adiciona o mapa

4. L.latLngBounds([])

O que faz: Cria um retângulo geográfico que define uma área delimitada por coordenadas. Útil para ajustar o zoom do mapa ou verificar se um ponto está dentro de uma área.

const bounds = L.latLngBounds([
                [-19.9269086, -43.9386425], // Coordenadas do ponto 1
                [-19.7996, -44.018]         // Coordenadas do ponto 2
            ]);

5. L.polyline([])

O que faz: Desenha uma linha no mapa conectando uma série de coordenadas.

const polyline = L.polyline([
                [-19.9269086, -43.9386425], // Coordenadas do ponto 1
                [-19.7996, -44.018]         // Coordenadas do ponto 2
            ], { color: 'blue' }).addTo(map); // Adiciona uma linha azul ao mapa

6. L.divIcon(options)

O que faz: Cria um ícone personalizado usando HTML e CSS. Útil para criar marcadores personalizados.

const customIcon = L.divIcon({
                className: 'custom-icon', // Classe CSS para estilização
                html: '
' }); L.marker([-19.9269086, -43.9386425], { icon: customIcon }).addTo(map); // Adiciona um marcador personalizado

7. L.marker(latlng, options)

O que faz: Adiciona um marcador no mapa em uma localização específica.

L.marker([-19.9269086, -43.9386425]).addTo(map); // Adiciona um marcador no mapa

8. L.icon(options)

O que faz: Cria um ícone personalizado para marcadores. Pode ser usado para definir ícones personalizados com imagens.

const customIcon = L.icon({
                iconUrl: 'marker-icon.png', // URL da imagem do ícone
                iconSize: [38, 38],        // Tamanho do ícone
                iconAnchor: [19, 38]       // Ponto de ancoragem do ícone
            });
            L.marker([-19.9269086, -43.9386425], { icon: customIcon }).addTo(map); // Adiciona um marcador com ícone personalizado

9. Endpoint busca lat/long


                async function buscarLatLong(endereco) {
                    try {
                        // Faz a requisição POST para a API
                        const response = await fetch('https://iarotas.com.br/api/address', {
                            method: 'POST',
                            headers: {
                                'Content-Type': 'application/json',
                                'Authorization': `Bearer ${token}`
                            },
                            body: JSON.stringify([{
                                "codigo": "001", // Código fixo (ajuste conforme necessário)
                                "endereco": endereco // Endereço passado como parâmetro
                            }])
                        });
                
                        // Verifica se a requisição foi bem-sucedida
                        if (!response.ok) {
                            throw new Error(`Erro na requisição: ${response.status} ${response.statusText}`);
                        }
                
                        // Converte a resposta para JSON
                        const data = await response.json();
                
                        // Exibe a resposta da API no console
                        console.log('Resposta da API:', data);
                    } catch (error) {
                        // Captura e exibe qualquer erro que ocorra
                        console.error('Erro ao buscar lat e long:', error);
                    }
                }
        

10. Endpoint busca endereço



            async function buscaEndereco(lat, lon) {
                const url = 'https://iarotas.com.br/api/getAddressFromCoordinates';
            
                try {
                    const response = await fetch(url, {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json',
                            'Authorization': token
                        },
                        body: JSON.stringify({
                            lat: lat,
                            lon: lon
                        })
                    });
            
                    if (!response.ok) {
                        throw new Error(`Erro: ${response.status} - ${response.statusText}`);
                    }
            
                    const data = await response.json();
                    console.log('Endereço:', data);
                    return data;
                } catch (error) {
                    console.error('Erro ao buscar endereço:', error);
                    throw error;
                }
            }
    

Importação de Arquivos KML e JSON

A API também permite a importação de arquivos KML e JSON. O arquivo KML deve seguir o padrão da versão 2.2.

Exemplo de Importação de KML:

<kml xmlns="http://www.opengis.net/kml/2.2">
            <Document>
                <name>Exemplo KML</name>
                <Placemark>
                    <name>Ponto 1</name>
                    <Point>
                        <coordinates>-43.9386425,-19.9269086,0</coordinates>
                    </Point>
                </Placemark>
            </Document>
        </kml>

Exemplo de Código JavaScript para Importação de KML:


        document.getElementById('fileInput').addEventListener('change', function (event) {
            const file = event.target.files[0];
        
            if (!file) {
                alert('Por favor, selecione um arquivo KML.');
                return;
            }
        
            const reader = new FileReader();
        
            reader.onload = function () {
                const kmlText = reader.result;
        
                // Parseia o KML
                const parser = new DOMParser();
                const kml = parser.parseFromString(kmlText, 'application/xml');
        
                // Verifica se é um KML versão 2.2
                const kmlNamespace = kml.documentElement.namespaceURI;
                if (kmlNamespace !== 'http://www.opengis.net/kml/2.2' && kmlNamespace !== 'http://earth.google.com/kml/2.2') {
                    alert('Por favor, importe um arquivo KML na versão 2.2.');
                    return;
                }
        
                // Processa os Placemarks
                const places = [];
                const placemarks = kml.getElementsByTagName('Placemark');
        
                for (let placemark of placemarks) {
                    const name = placemark.querySelector('name')?.textContent || 'Sem nome';
                    const point = placemark.querySelector('Point > coordinates');
                    
                    if (point) {
                        const [longitude, latitude] = point.textContent.trim().split(',').slice(0, 2).map(parseFloat);
                        
                        places.push({
                            name: name,
                            latitude: latitude,
                            longitude: longitude
                        });
                    }
                }
        
                const jsonResult = { places };
        
                // Exibe o JSON no console e na tela
                console.log('JSON Gerado:', jsonResult);
                document.getElementById('output').textContent = JSON.stringify(jsonResult, null, 2);
            };
        
            reader.readAsText(file);
        });

Exemplo de Importação de JSON:

{
                    "clientes": [
                        {
                            "cliente": "AAAA",
                            "lat": -19.9269086,
                            "long": -43.9386425
                        },
                        {
                            "cliente": "AAAB",
                            "lat": -19.7996,
                            "long": -44.018
                        },
                        {
                            "cliente": "AAAC",
                            "lat": -19.7664,
                            "long": -44.0875
                        },
                        {
                            "cliente": "AAAD",
                            "lat": -19.7710406,
                            "long": -44.085105099999964
                        },
                        {
                            "cliente": "AAAE",
                            "lat": -19.7661033,
                            "long": -44.08916310000001
                        },
                        {
                            "cliente": "AAAF",
                            "lat": -19.7644771,
                            "long": -44.08510910000001
                        },
                        {
                            "cliente": "AAAG",
                            "lat": -19.777820260984598,
                            "long": -44.07835782527009
                        },
                        {
                            "cliente": "AAAH",
                            "lat": -19.789935,
                            "long": -43.98953399999999
                        },
                        {
                            "cliente": "AAAI",
                            "lat": -19.7870624,
                            "long": -43.989568099999985
                        },
                        {
                            "cliente": "AAAJ",
                            "lat": -19.788533,
                            "long": -43.98746900000003
                        },
                        {
                            "cliente": "AAAK",
                            "lat": -19.7961202,
                            "long": -43.9956219
                        },
                        {
                            "cliente": "AAAL",
                            "lat": -19.792588,
                            "long": -44.00928120000003
                        },
                        {
                            "cliente": "AAAM",
                            "lat": -19.7920557,
                            "long": -44.004045700000006
                        },
                        {
                            "cliente": "AAAN",
                            "lat": -19.79675247,
                            "long": -43.98719409
                        },
                        {
                            "cliente": "AAAO",
                            "lat": -19.7979982,
                            "long": -43.9842711
                        },
                        {
                            "cliente": "AAAP",
                            "lat": -19.79155474,
                            "long": -43.98569003
                        },
                        {
                            "cliente": "AAAQ",
                            "lat": -19.780135,
                            "long": -43.98307990000001
                        },
                        {
                            "cliente": "AAAR",
                            "lat": -19.8152031,
                            "long": -43.95794510000002
                        },
                        {
                            "cliente": "AAAS",
                            "lat": -19.8146927,
                            "long": -43.959083599999985
                        },
                        {
                            "cliente": "AAAT",
                            "lat": -19.8076724,
                            "long": -43.96997870000001
                        },
                        {
                            "cliente": "AAAU",
                            "lat": -19.7554866,
                            "long": -43.99227910000002
                        },
                        {
                            "cliente": "AAAV",
                            "lat": -19.8213896,
                            "long": -43.9664677
                        },
                        {
                            "cliente": "AAAW",
                            "lat": -19.803566847760596,
                            "long": -43.98036913486253
                        },
                        {
                            "cliente": "AAAX",
                            "lat": -19.8023,
                            "long": -44.0015
                        },
                        {
                            "cliente": "AAAY",
                            "lat": -19.8109506,
                            "long": -44.0103441
                        },
                        {
                            "cliente": "AAAZ",
                            "lat": -19.8813562,
                            "long": -44.04655730000002
                        },
                        {
                            "cliente": "AABA",
                            "lat": -19.87953114,
                            "long": -44.05006467
                        },
                        {
                            "cliente": "AABB",
                            "lat": -19.8280580372522,
                            "long": -43.9651262418335
                        },
                        {
                            "cliente": "AABC",
                            "lat": -19.78754233,
                            "long": -44.00940284
                        },
                        {
                            "cliente": "AABD",
                            "lat": -19.8163818,
                            "long": -44.01220209999997
                        },
                        {
                            "cliente": "AABE",
                            "lat": -19.8037448,
                            "long": -43.978814599999964
                        },
                        {
                            "cliente": "AABG",
                            "lat": -19.8983689,
                            "long": -44.00464459
                        },
                        {
                            "cliente": "AABH",
                            "lat": -19.780548,
                            "long": -43.9873192
                        },
                        {
                            "cliente": "AABI",
                            "lat": -19.75472570220318,
                            "long": -44.000903505371085
                        },
                        {
                            "cliente": "AABJ",
                            "lat": -19.7534337,
                            "long": -44.08234620000002
                        },
                        {
                            "cliente": "AABK",
                            "lat": -19.7919086,
                            "long": -44.021448899999996
                        },
                        {
                            "cliente": "AABL",
                            "lat": -19.812937736532078,
                            "long": -43.96358329783096
                        },
                        {
                            "cliente": "AABM",
                            "lat": -19.8047293,
                            "long": -44.00051389999999
                        },
                        {
                            "cliente": "AABN",
                            "lat": -19.8158764,
                            "long": -43.9827315
                        },
                        {
                            "cliente": "AABO",
                            "lat": -19.8134122,
                            "long": -43.984250799999984
                        },
                        {
                            "cliente": "AABP",
                            "lat": -19.8118355,
                            "long": -43.982843900000034
                        },
                        {
                            "cliente": "AABQ",
                            "lat": -19.8117667,
                            "long": -43.9824375
                        },
                        {
                            "cliente": "AABR",
                            "lat": -19.8083693,
                            "long": -43.98123169999997
                        },
                        {
                            "cliente": "AABS",
                            "lat": -19.8110799,
                            "long": -43.9802732
                        },
                        {
                            "cliente": "AABT",
                            "lat": -19.815,
                            "long": -43.9589
                        },
                        {
                            "cliente": "AABU",
                            "lat": -19.8223,
                            "long": -43.9598
                        },
                        {
                            "cliente": "AABV",
                            "lat": -19.8159,
                            "long": -43.9634
                        },
                        {
                            "cliente": "AABW",
                            "lat": -19.8159065,
                            "long": -43.96347539999999
                        },
                        {
                            "cliente": "AABX",
                            "lat": -19.8152276,
                            "long": -43.963773300000014
                        },
                        {
                            "cliente": "AABY",
                            "lat": -19.8877761,
                            "long": -44.048009500000035
                        },
                        {
                            "cliente": "AABZ",
                            "lat": -19.8803989,
                            "long": -44.04785939999999
                        },
                        {
                            "cliente": "AACA",
                            "lat": -19.881847408729886,
                            "long": -44.04613688888549
                        },
                        {
                            "cliente": "AACB",
                            "lat": -19.88699432609985,
                            "long": -44.04438537665176
                        },
                        {
                            "cliente": "AACC",
                            "lat": -19.808,
                            "long": -43.9834
                        },
                        {
                            "cliente": "AACD",
                            "lat": -19.8195756633002,
                            "long": -43.973805189757535
                        },
                        {
                            "cliente": "AACE",
                            "lat": -19.872891211740253,
                            "long": -43.98580198531952
                        }
                    ]
                }

Exemplo de Código JavaScript para Importação de JSON:


                    // Evento para carregar o arquivo JSON
                    document.getElementById('jsonFileInput').addEventListener('change', function (event) {
                        const file = event.target.files[0];
                    
                        if (file) {
                            const reader = new FileReader();
                    
                            reader.onload = function (e) {
                                try {
                                    const jsonData = JSON.parse(e.target.result);
                                    processJson(jsonData);
                                } catch (err) {
                                    alert('Erro ao processar o JSON: ' + err.message);
                                }
                            };
                    
                            reader.readAsText(file);
                        }
                    });
                    
                    // Função para processar o JSON
                    function processJson(data) {
                        if (!data.places || !Array.isArray(data.places)) {
                            alert('O JSON não contém a estrutura esperada.');
                            return;
                        }
                    
                        showLoading(); // Inicia o carregamento
                    
                        data.places.forEach(async (place) => {
                            if (place.type === 'polygon') {
                                processPolygon(place);
                            } else if (place.type === 'line') {
                                await processLine(place);
                            }
                        });
                    
                        hideLoading(); // Finaliza o carregamento após o processamento
                        alert('JSON processado e renderizado no mapa!');
                    }
                    
                    // Função para processar polígonos
                    function processPolygon(place) {
                        L.polygon(place.coordinates, {
                            color: place.color,
                            fill: place.fill,
                            fillOpacity: place.fill ? 0.5 : 0,
                            opacity: place.outline ? 1 : 0
                        }).addTo(map);
                    }
                    
                    // Função para processar linhas
                    async function processLine(place) {
                        if (place.realignRoute) {
                            try {
                                const updatedCoordinates = await realignRoute(place.coordinates);
                                place.coordinates = updatedCoordinates.coordinates;
                                console.log('Coordinates realigned:', updatedCoordinates.coordinates);
                            } catch (error) {
                                console.error('Erro ao realinhar a rota:', error);
                                return;
                            }
                        }
                    
                        L.polyline(place.coordinates, {
                            color: place.color,
                            fill: place.fill,
                            fillOpacity: place.fill ? 0.5 : 0,
                            opacity: place.outline ? 1 : 0
                        }).addTo(map);
                    }
                    
                    // Função para realinhar a rota via API
                    async function realignRoute(coordinates) {
                        const token = gerarToken();
                    
                        const response = await fetch('https://iarotas.com.br/api/realignRoute', {
                            method: 'POST',
                            headers: {
                                'Content-Type': 'application/json',
                                'Authorization': `Bearer ${token}`
                            },
                            body: JSON.stringify({ coordinates })
                        });
                    
                        if (!response.ok) {
                            throw new Error('Falha ao realinhar a rota');
                        }
                    
                        return response.json(); // Retorna as novas coordenadas
                    }
                    
        });

Tipos de Roteirizadores

A API oferece três tipos de roteirizadores, cada um com funcionalidades específicas:

Exemplo de implementação de cada roteirizador

Roteirização Simples - React


                        // JSON de entrada com os clientes
                        const jsonData = {
                            "clientes": [
                                {
                                    "cliente": "AAAA",
                                    "lat": -19.9269086,
                                    "long": -43.9386425
                                },
                                {
                                    "cliente": "AAAB",
                                    "lat": -19.7996,
                                    "long": -44.018
                                },
                                {
                                    "cliente": "AAAC",
                                    "lat": -19.7664,
                                    "long": -44.0875
                                }
                            ]
                        };
                        
                        // Variáveis para armazenar a base (se existirem)
                        let latitudeBase = null;  // Defina a latitude da base, se necessário
                        let longitudeBase = null; // Defina a longitude da base, se necessário
                        
                        // Função assíncrona para enviar os dados
                        async function enviarDados(data) {
                            const url = 'https://iarotas.com.br/api/routerv1';
                            const token = gerarToken();
                        
                            showLoading(); // Exibe um indicador de carregamento (supondo que essa função já esteja implementada)
                        
                            try {
                                // **Adiciona a base à lista de clientes antes do envio, se existir**
                                if (latitudeBase !== null && longitudeBase !== null) {
                                    data.clientes.unshift({
                                        cliente: "BASE",
                                        lat: latitudeBase,
                                        long: longitudeBase
                                    });
                                }
                        
                                // Faz a requisição para a API
                                const response = await fetch(url, {
                                    method: 'POST',
                                    headers: {
                                        'Content-Type': 'application/json',
                                        'Authorization': token
                                    },
                                    body: JSON.stringify(data)
                                });
                        
                                // Converte a resposta para JSON
                                const responseData = await response.json();
                        
                                console.log("Resposta da API:", responseData);
                                return responseData;
                        
                            } catch (error) {
                                console.error("Erro ao enviar os dados:", error);
                            } finally {
                                hideLoading(); // Oculta o indicador de carregamento (caso tenha implementado essa função)
                            }
                        }
                        
                        // Chamando a função para enviar os dados
                        enviarDados(jsonData);
                        

Roteirização Simples - Python


                        import requests
                        import json
                        
                        # JSON de entrada com os clientes
                        json_data = {
                            "clientes": [
                                {
                                    "cliente": "AAAA",
                                    "lat": -19.9269086,
                                    "long": -43.9386425
                                },
                                {
                                    "cliente": "AAAB",
                                    "lat": -19.7996,
                                    "long": -44.018
                                },
                                {
                                    "cliente": "AAAC",
                                    "lat": -19.7664,
                                    "long": -44.0875
                                }
                            ]
                        }
                        
                        # Variáveis para armazenar a base (se existirem)
                        latitude_base = None  # Defina a latitude da base, se necessário
                        longitude_base = None  # Defina a longitude da base, se necessário
                        
                        # Função para gerar o token (exemplo)
                        def gerar_token():
                            return "seu_token_aqui"
                        
                        # Função para enviar os dados
                        def enviar_dados(data):
                            url = 'https://iarotas.com.br/api/routerv1'
                            token = gerar_token()
                        
                            # Adiciona a base à lista de clientes antes do envio, se existir
                            if latitude_base is not None and longitude_base is not None:
                                data["clientes"].insert(0, {
                                    "cliente": "BASE",
                                    "lat": latitude_base,
                                    "long": longitude_base
                                })
                        
                            # Faz a requisição para a API
                            try:
                                response = requests.post(
                                    url,
                                    headers={
                                        'Content-Type': 'application/json',
                                        'Authorization': token
                                    },
                                    data=json.dumps(data)
                                )
                                response_data = response.json()
                                print("Resposta da API:", response_data)
                                return response_data
                            except Exception as error:
                                print("Erro ao enviar os dados:", error)
                            finally:
                                # Oculta o indicador de carregamento (caso tenha implementado essa função)
                                pass
                        
                        # Chamando a função para enviar os dados
                        enviar_dados(json_data) 
                    

Roteirização Simples - PHP


                <?php
                
                // JSON de entrada com os clientes
                $jsonData = [
                    "clientes" => [
                        [
                            "cliente" => "AAAA",
                            "lat" => -19.9269086,
                            "long" => -43.9386425
                        ],
                        [
                            "cliente" => "AAAB",
                            "lat" => -19.7996,
                            "long" => -44.018
                        ],
                        [
                            "cliente" => "AAAC",
                            "lat" => -19.7664,
                            "long" => -44.0875
                        ]
                    ]
                ];
                
                // Variáveis para armazenar a base (se existirem)
                $latitudeBase = null;  // Defina a latitude da base, se necessário
                $longitudeBase = null; // Defina a longitude da base, se necessário
                
                // Função para gerar o token (exemplo)
                function gerarToken() {
                    return "seu_token_aqui";
                }
                
                // Função para enviar os dados
                function enviarDados($data) {
                    $url = 'https://iarotas.com.br/api/routerv1';
                    $token = gerarToken();
                
                    // Adiciona a base à lista de clientes antes do envio, se existir
                    if ($latitudeBase !== null && $longitudeBase !== null) {
                        array_unshift($data['clientes'], [
                            "cliente" => "BASE",
                            "lat" => $latitudeBase,
                            "long" => $longitudeBase
                        ]);
                    }
                
                    // Faz a requisição para a API
                    $options = [
                        'http' => [
                            'header'  => [
                                'Content-Type: application/json',
                                'Authorization: ' . $token
                            ],
                            'method'  => 'POST',
                            'content' => json_encode($data)
                        ]
                    ];
                    $context  = stream_context_create($options);
                    $result = file_get_contents($url, false, $context);
                
                    if ($result === FALSE) {
                        echo "Erro ao enviar os dados";
                    } else {
                        $responseData = json_decode($result, true);
                        echo "Resposta da API: ";
                        print_r($responseData);
                        return $responseData;
                    }
                }
                
                // Chamando a função para enviar os dados
                enviarDados($jsonData);
                ?>
                    

Roteirização Simples - Java


                        import java.io.OutputStream;
                        import java.net.HttpURLConnection;
                        import java.net.URL;
                        import java.util.ArrayList;
                        import java.util.List;
                        import com.google.gson.Gson;
                        
                        public class Main {
                        
                            // JSON de entrada com os clientes
                            static class Cliente {
                                String cliente;
                                double lat;
                                double longi;
                        
                                Cliente(String cliente, double lat, double longi) {
                                    this.cliente = cliente;
                                    this.lat = lat;
                                    this.long = longi;
                                }
                            }
                        
                            static class JsonData {
                                List clientes = new ArrayList<>();
                            }
                        
                            // Variáveis para armazenar a base (se existirem)
                            static Double latitudeBase = null;  // Defina a latitude da base, se necessário
                            static Double longitudeBase = null; // Defina a longitude da base, se necessário
                        
                            // Função para gerar o token (exemplo)
                            static String gerarToken() {
                                return "seu_token_aqui";
                            }
                        
                            // Função para enviar os dados
                            static void enviarDados(JsonData data) {
                                String url = "https://iarotas.com.br/api/routerv1";
                                String token = gerarToken();
                        
                                // Adiciona a base à lista de clientes antes do envio, se existir
                                if (latitudeBase != null && longitudeBase != null) {
                                    data.clientes.add(0, new Cliente("BASE", latitudeBase, longitudeBase));
                                }
                        
                                // Faz a requisição para a API
                                try {
                                    URL apiUrl = new URL(url);
                                    HttpURLConnection conn = (HttpURLConnection) apiUrl.openConnection();
                                    conn.setRequestMethod("POST");
                                    conn.setRequestProperty("Content-Type", "application/json");
                                    conn.setRequestProperty("Authorization", token);
                                    conn.setDoOutput(true);
                        
                                    Gson gson = new Gson();
                                    String jsonInputString = gson.toJson(data);
                        
                                    try (OutputStream os = conn.getOutputStream()) {
                                        byte[] input = jsonInputString.getBytes("utf-8");
                                        os.write(input, 0, input.length);
                                    }
                        
                                    int responseCode = conn.getResponseCode();
                                    if (responseCode == HttpURLConnection.HTTP_OK) {
                                        System.out.println("Resposta da API: " + new String(conn.getInputStream().readAllBytes()));
                                    } else {
                                        System.out.println("Erro ao enviar os dados: " + responseCode);
                                    }
                                } catch (Exception e) {
                                    e.printStackTrace();
                                } finally {
                                    // Oculta o indicador de carregamento (caso tenha implementado essa função)
                                }
                            }
                        
                            public static void main(String[] args) {
                                JsonData jsonData = new JsonData();
                                jsonData.clientes.add(new Cliente("AAAA", -19.9269086, -43.9386425));
                                jsonData.clientes.add(new Cliente("AAAB", -19.7996, -44.018));
                                jsonData.clientes.add(new Cliente("AAAC", -19.7664, -44.0875));
                        
                                enviarDados(jsonData);
                            }
                        }
    

Roteirização com Veículos - React


                        // JSON de entrada com os clientes com a placa do veiculo
                        const jsonData = {
                            "clientes": [
                                {
                                    "cliente": "AAAA",
                                    "lat": -19.9269086,
                                    "long": -43.9386425,
                                    "placa": "Placa A"
                                },
                                {
                                    "cliente": "AAAB",
                                    "lat": -19.7996,
                                    "long": -44.018,
                                    "placa": "Placa B"
                                },
                                {
                                    "cliente": "AAAC",
                                    "lat": -19.7664,
                                    "long": -44.0875,
                                    "placa": "Placa C"
                                }
                            ]
                        };
                        
                        // Variáveis para armazenar a base (se existirem)
                        let latitudeBase = null;  // Defina a latitude da base, se necessário
                        let longitudeBase = null; // Defina a longitude da base, se necessário
                        
                        async function enviarDados(data) {
                            const url = 'https://iarotas.com.br/api/routerPlates';
                            const token = gerarToken(); // Supondo que essa função gera um token de autorização
                        
                            try {
                                // Verifica se as coordenadas da base estão disponíveis
                                if (latitudeBase !== null && longitudeBase !== null) {
                                    // Adiciona o cliente "BASE" no início do array de clientes
                                    data.clientes.unshift({
                                        cliente: "BASE",
                                        lat: latitudeBase,
                                        long: longitudeBase
                                    });
                                }
                        
                                // Faz a requisição POST para a API
                                const response = await fetch(url, {
                                    method: 'POST',
                                    headers: {
                                        'Content-Type': 'application/json',
                                        'Authorization': token
                                    },
                                    body: JSON.stringify(data) // Converte os dados para JSON
                                });
                        
                                // Verifica se a resposta da requisição foi bem-sucedida
                                if (!response.ok) {
                                    throw new Error(`Erro na requisição: ${response.statusText}`);
                                }
                        
                                // Converte a resposta para JSON
                                const responseData = await response.json();
                        
                                // Retorna os dados da resposta
                                return responseData;
                        
                            } catch (error) {
                                // Captura e trata qualquer erro que ocorra durante a requisição
                                console.error('Erro ao enviar dados:', error);
                                throw error; // Rejeita a promessa para que o erro possa ser tratado externamente
                            }
                        }

                        // Exemplo de uso
                        // enviarDados(jsonData);
            

Roteirização com Veículos - Python


                        import requests
                        import json
                        
                        # JSON de entrada com os clientes com a placa do veiculo
                        json_data = {
                            "clientes": [
                                {
                                    "cliente": "AAAA",
                                    "lat": -19.9269086,
                                    "long": -43.9386425,
                                    "placa": "Placa A"
                                },
                                {
                                    "cliente": "AAAB",
                                    "lat": -19.7996,
                                    "long": -44.018,
                                    "placa": "Placa B"
                                },
                                {
                                    "cliente": "AAAC",
                                    "lat": -19.7664,
                                    "long": -44.0875,
                                    "placa": "Placa C"
                                }
                            ]
                        }
                        
                        # Variáveis para armazenar a base (se existirem)
                        latitude_base = None  # Defina a latitude da base, se necessário
                        longitude_base = None  # Defina a longitude da base, se necessário
                        
                        def gerar_token():
                            # Supondo que essa função gera um token de autorização
                            return "seu_token_aqui"
                        
                        def enviar_dados(data):
                            url = 'https://iarotas.com.br/api/routerPlates'
                            token = gerar_token()
                        
                            try:
                                # Verifica se as coordenadas da base estão disponíveis
                                if latitude_base is not None and longitude_base is not None:
                                    # Adiciona o cliente "BASE" no início do array de clientes
                                    data["clientes"].insert(0, {
                                        "cliente": "BASE",
                                        "lat": latitude_base,
                                        "long": longitude_base
                                    })
                        
                                # Faz a requisição POST para a API
                                response = requests.post(url, json=data, headers={
                                    'Content-Type': 'application/json',
                                    'Authorization': token
                                })
                        
                                # Verifica se a resposta da requisição foi bem-sucedida
                                response.raise_for_status()
                        
                                # Converte a resposta para JSON
                                response_data = response.json()
                        
                                # Retorna os dados da resposta
                                return response_data
                        
                            except requests.exceptions.RequestException as error:
                                # Captura e trata qualquer erro que ocorra durante a requisição
                                print('Erro ao enviar dados:', error)
                                raise error  # Rejeita a exceção para que o erro possa ser tratado externamente
                        
                        # Exemplo de uso
                        # enviar_dados(json_data)
            

Roteirização com Veículos - PHP


                        <?php
                        // JSON de entrada com os clientes com a placa do veiculo
                        $jsonData = [
                            "clientes" => [
                                [
                                    "cliente" => "AAAA",
                                    "lat" => -19.9269086,
                                    "long" => -43.9386425,
                                    "placa" => "Placa A"
                                ],
                                [
                                    "cliente" => "AAAB",
                                    "lat" => -19.7996,
                                    "long" => -44.018,
                                    "placa" => "Placa B"
                                ],
                                [
                                    "cliente" => "AAAC",
                                    "lat" => -19.7664,
                                    "long" => -44.0875,
                                    "placa" => "Placa C"
                                ]
                            ]
                        ];
                
                        // Variáveis para armazenar a base (se existirem)
                        $latitudeBase = null;  // Defina a latitude da base, se necessário
                        $longitudeBase = null; // Defina a longitude da base, se necessário
                
                        function gerarToken() {
                            // Supondo que essa função gera um token de autorização
                            return "seu_token_aqui";
                        }
                
                        function enviarDados($data) {
                            $url = 'https://iarotas.com.br/api/routerPlates';
                            $token = gerarToken();
                
                            try {
                                // Verifica se as coordenadas da base estão disponíveis
                                global $latitudeBase, $longitudeBase;
                                if ($latitudeBase !== null && $longitudeBase !== null) {
                                    // Adiciona o cliente "BASE" no início do array de clientes
                                    array_unshift($data['clientes'], [
                                        "cliente" => "BASE",
                                        "lat" => $latitudeBase,
                                        "long" => $longitudeBase
                                    ]);
                                }
                
                                // Faz a requisição POST para a API
                                $options = [
                                    'http' => [
                                        'header'  => "Content-Type: application/json\r\nAuthorization: $token\r\n",
                                        'method'  => 'POST',
                                        'content' => json_encode($data),
                                    ],
                                ];
                                $context  = stream_context_create($options);
                                $response = file_get_contents($url, false, $context);
                
                                // Verifica se a resposta da requisição foi bem-sucedida
                                if ($response === FALSE) {
                                    throw new Exception('Erro na requisição');
                                }
                
                                // Converte a resposta para JSON
                                $responseData = json_decode($response, true);
                
                                // Retorna os dados da resposta
                                return $responseData;
                
                            } catch (Exception $error) {
                                // Captura e trata qualquer erro que ocorra durante a requisição
                                echo 'Erro ao enviar dados: ' . $error->getMessage();
                                throw $error;  // Rejeita a exceção para que o erro possa ser tratado externamente
                            }
                        }
                
                        // Exemplo de uso
                        // enviarDados($jsonData);
                        ?>
                    

Roteirização com Veículos - Java


                        import java.io.OutputStream;
                        import java.net.HttpURLConnection;
                        import java.net.URL;
                        import java.util.ArrayList;
                        import java.util.List;
                        import com.google.gson.Gson;
                        
                        public class Main {
                        
                            // JSON de entrada com os clientes com a placa do veiculo
                            static class Cliente {
                                String cliente;
                                double lat;
                                double longi;
                                String placa;
                        
                                Cliente(String cliente, double lat, double longi, String placa) {
                                    this.cliente = cliente;
                                    this.lat = lat;
                                    this.longi = longi;
                                    this.placa = placa;
                                }
                            }
                        
                            static class JsonData {
                                List clientes = new ArrayList<>();
                            }
                        
                            // Variáveis para armazenar a base (se existirem)
                            static Double latitudeBase = null;  // Defina a latitude da base, se necessário
                            static Double longitudeBase = null; // Defina a longitude da base, se necessário
                        
                            public static String gerarToken() {
                                // Supondo que essa função gera um token de autorização
                                return "seu_token_aqui";
                            }
                        
                            public static String enviarDados(JsonData data) throws Exception {
                                String url = "https://iarotas.com.br/api/routerPlates";
                                String token = gerarToken();
                        
                                try {
                                    // Verifica se as coordenadas da base estão disponíveis
                                    if (latitudeBase != null && longitudeBase != null) {
                                        // Adiciona o cliente "BASE" no início do array de clientes
                                        data.clientes.add(0, new Cliente("BASE", latitudeBase, longitudeBase, null));
                                    }
                        
                                    // Converte os dados para JSON
                                    Gson gson = new Gson();
                                    String jsonInputString = gson.toJson(data);
                        
                                    // Faz a requisição POST para a API
                                    HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
                                    conn.setRequestMethod("POST");
                                    conn.setRequestProperty("Content-Type", "application/json");
                                    conn.setRequestProperty("Authorization", token);
                                    conn.setDoOutput(true);
                        
                                    try (OutputStream os = conn.getOutputStream()) {
                                        byte[] input = jsonInputString.getBytes("utf-8");
                                        os.write(input, 0, input.length);
                                    }
                        
                                    // Verifica se a resposta da requisição foi bem-sucedida
                                    if (conn.getResponseCode() != 200) {
                                        throw new RuntimeException("Erro na requisição: " + conn.getResponseMessage());
                                    }
                        
                                    // Converte a resposta para JSON
                                    try (java.util.Scanner scanner = new java.util.Scanner(conn.getInputStream(), "UTF-8")) {
                                        String responseData = scanner.useDelimiter("\\A").next();
                                        return responseData;
                                    }
                        
                                } catch (Exception error) {
                                    // Captura e trata qualquer erro que ocorra durante a requisição
                                    System.err.println("Erro ao enviar dados: " + error.getMessage());
                                    throw error;  // Rejeita a exceção para que o erro possa ser tratado externamente
                                }
                            }
                        
                            public static void main(String[] args) throws Exception {
                                JsonData jsonData = new JsonData();
                                jsonData.clientes.add(new Cliente("AAAA", -19.9269086, -43.9386425, "Placa A"));
                                jsonData.clientes.add(new Cliente("AAAB", -19.7996, -44.018, "Placa B"));
                                jsonData.clientes.add(new Cliente("AAAC", -19.7664, -44.0875, "Placa C"));
                        
                                // Exemplo de uso
                                // enviarDados(jsonData);
                            }
                        }
            

Roteirização com Divisão de Carga - React


                        // JSON de entrada com os clientes com a placa do veiculo
                        const jsonData = {
                            "clientes": [
                                {
                                    "cliente": "AAAA",
                                    "nomeCliente": "PADARIA SOL NASCENTE LTDA",
                                    "lat": -19.7996,
                                    "long": -44.018
                                },
                                {
                                    "cliente": "AAAB",
                                    "nomeCliente": "PADARIA DO CAMPO LTDA",
                                    "lat": -19.7589369,
                                    "long": -43.9941235
                                },
                                {
                                    "cliente": "AAAC",
                                    "nomeCliente": "PADARIA ESTRELA DA MANHÃ LTDA",
                                    "lat": -19.8200142,
                                    "long": -43.9605643
                                }
                            ],
                            "veiculos": [
                                {
                                    "placa": "PLACA1",
                                    "capacidade": "100"
                                },
                                {
                                    "placa": "PLACA2",
                                    "capacidade": "600"
                                },
                                {
                                    "placa": "PLACA3",
                                    "capacidade": "300"
                                }
                            ],
                            "pedidos": [
                                {
                                    "cliente": "AAAA",
                                    "peso": "100.000"
                                },
                                {
                                    "cliente": "AAAB",
                                    "peso": "600.000"
                                },
                                {
                                    "cliente": "AAAC",
                                    "peso": "300.000"
                                }
                            ]
                        };
                        
                        // Variáveis para armazenar a base (se existirem)
                        let latitudeBase = null;  // Defina a latitude da base, se necessário
                        let longitudeBase = null; // Defina a longitude da base, se necessário
                        
                        async function enviarDados(data) {
                            const url = 'https://iarotas.com.br/api/routerAndDistribute';
                            const token = gerarToken(); // Supondo que essa função gera um token de autorização
                        
                            try {
                                // Verifica se as coordenadas da base estão disponíveis
                                if (latitudeBase !== null && longitudeBase !== null) {
                                    // Adiciona o cliente "BASE" no início do array de clientes
                                    data.clientes.unshift({
                                        cliente: "BASE",
                                        lat: latitudeBase,
                                        long: longitudeBase
                                    });
                                }
                        
                                // Faz a requisição POST para a API
                                const response = await fetch(url, {
                                    method: 'POST',
                                    headers: {
                                        'Content-Type': 'application/json',
                                        'Authorization': token
                                    },
                                    body: JSON.stringify(data) // Converte os dados para JSON
                                });
                        
                                // Verifica se a resposta da requisição foi bem-sucedida
                                if (!response.ok) {
                                    throw new Error(`Erro na requisição: ${response.statusText}`);
                                }
                        
                                // Converte a resposta para JSON
                                const responseData = await response.json();
                        
                                // Retorna os dados da resposta
                                return responseData;
                        
                            } catch (error) {
                                // Captura e trata qualquer erro que ocorra durante a requisição
                                console.error('Erro ao enviar dados:', error);
                                throw error; // Rejeita a promessa para que o erro possa ser tratado externamente
                            }
                        }
                        
                        // Exemplo de uso
                        // enviarDados(jsonData);
            

Roteirização com Divisão de Carga - Python


                        import json
                        import requests
                        
                        # JSON de entrada com os clientes com a placa do veiculo
                        json_data = {
                            "clientes": [
                                {
                                    "cliente": "AAAA",
                                    "nomeCliente": "PADARIA SOL NASCENTE LTDA",
                                    "lat": -19.7996,
                                    "long": -44.018
                                },
                                {
                                    "cliente": "AAAB",
                                    "nomeCliente": "PADARIA DO CAMPO LTDA",
                                    "lat": -19.7589369,
                                    "long": -43.9941235
                                },
                                {
                                    "cliente": "AAAC",
                                    "nomeCliente": "PADARIA ESTRELA DA MANHÃ LTDA",
                                    "lat": -19.8200142,
                                    "long": -43.9605643
                                }
                            ],
                            "veiculos": [
                                {
                                    "placa": "PLACA1",
                                    "capacidade": "100"
                                },
                                {
                                    "placa": "PLACA2",
                                    "capacidade": "600"
                                },
                                {
                                    "placa": "PLACA3",
                                    "capacidade": "300"
                                }
                            ],
                            "pedidos": [
                                {
                                    "cliente": "AAAA",
                                    "peso": "100.000"
                                },
                                {
                                    "cliente": "AAAB",
                                    "peso": "600.000"
                                },
                                {
                                    "cliente": "AAAC",
                                    "peso": "300.000"
                                }
                            ]
                        }
                        
                        # Variáveis para armazenar a base (se existirem)
                        latitude_base = None  # Defina a latitude da base, se necessário
                        longitude_base = None  # Defina a longitude da base, se necessário
                        
                        def gerar_token():
                            # Supondo que essa função gera um token de autorização
                            return "seu_token_aqui"
                        
                        def enviar_dados(data):
                            url = 'https://iarotas.com.br/api/routerAndDistribute'
                            token = gerar_token()
                        
                            try:
                                # Verifica se as coordenadas da base estão disponíveis
                                if latitude_base is not None and longitude_base is not None:
                                    # Adiciona o cliente "BASE" no início do array de clientes
                                    data["clientes"].insert(0, {
                                        "cliente": "BASE",
                                        "lat": latitude_base,
                                        "long": longitude_base
                                    })
                        
                                # Faz a requisição POST para a API
                                response = requests.post(
                                    url,
                                    headers={
                                        'Content-Type': 'application/json',
                                        'Authorization': token
                                    },
                                    data=json.dumps(data)  # Converte os dados para JSON
                                )
                        
                                # Verifica se a resposta da requisição foi bem-sucedida
                                response.raise_for_status()
                        
                                # Converte a resposta para JSON
                                response_data = response.json()
                        
                                # Retorna os dados da resposta
                                return response_data
                        
                            except requests.exceptions.RequestException as error:
                                # Captura e trata qualquer erro que ocorra durante a requisição
                                print(f'Erro ao enviar dados: {error}')
                                raise  # Rejeita a exceção para que o erro possa ser tratado externamente
                        
                        # Exemplo de uso
                        # enviar_dados(json_data)
            

Roteirização com Divisão de Carga - PHP


                        <?php
                        // JSON de entrada com os clientes com a placa do veiculo
                        $jsonData = [
                            "clientes" => [
                                [
                                    "cliente" => "AAAA",
                                    "nomeCliente" => "PADARIA SOL NASCENTE LTDA",
                                    "lat" => -19.7996,
                                    "long" => -44.018
                                ],
                                [
                                    "cliente" => "AAAB",
                                    "nomeCliente" => "PADARIA DO CAMPO LTDA",
                                    "lat" => -19.7589369,
                                    "long" => -43.9941235
                                ],
                                [
                                    "cliente" => "AAAC",
                                    "nomeCliente" => "PADARIA ESTRELA DA MANHÃ LTDA",
                                    "lat" => -19.8200142,
                                    "long" => -43.9605643
                                ]
                            ],
                            "veiculos" => [
                                [
                                    "placa" => "PLACA1",
                                    "capacidade" => "100"
                                ],
                                [
                                    "placa" => "PLACA2",
                                    "capacidade" => "600"
                                ],
                                [
                                    "placa" => "PLACA3",
                                    "capacidade" => "300"
                                ]
                            ],
                            "pedidos" => [
                                [
                                    "cliente" => "AAAA",
                                    "peso" => "100.000"
                                ],
                                [
                                    "cliente" => "AAAB",
                                    "peso" => "600.000"
                                ],
                                [
                                    "cliente" => "AAAC",
                                    "peso" => "300.000"
                                ]
                            ]
                        ];
                
                        // Variáveis para armazenar a base (se existirem)
                        $latitudeBase = null;  // Defina a latitude da base, se necessário
                        $longitudeBase = null; // Defina a longitude da base, se necessário
                
                        function gerarToken() {
                            // Supondo que essa função gera um token de autorização
                            return "seu_token_aqui";
                        }
                
                        function enviarDados($data) {
                            $url = 'https://iarotas.com.br/api/routerAndDistribute';
                            $token = gerarToken();
                
                            try {
                                // Verifica se as coordenadas da base estão disponíveis
                                if ($latitudeBase !== null && $longitudeBase !== null) {
                                    // Adiciona o cliente "BASE" no início do array de clientes
                                    array_unshift($data["clientes"], [
                                        "cliente" => "BASE",
                                        "lat" => $latitudeBase,
                                        "long" => $longitudeBase
                                    ]);
                                }
                
                                // Faz a requisição POST para a API
                                $options = [
                                    'http' => [
                                        'header'  => "Content-Type: application/json\r\nAuthorization: $token\r\n",
                                        'method'  => 'POST',
                                        'content' => json_encode($data),
                                    ],
                                ];
                                $context  = stream_context_create($options);
                                $response = file_get_contents($url, false, $context);
                
                                // Verifica se a resposta da requisição foi bem-sucedida
                                if ($response === FALSE) {
                                    throw new Exception("Erro na requisição");
                                }
                
                                // Converte a resposta para JSON
                                $responseData = json_decode($response, true);
                
                                // Retorna os dados da resposta
                                return $responseData;
                
                            } catch (Exception $error) {
                                // Captura e trata qualquer erro que ocorra durante a requisição
                                echo 'Erro ao enviar dados: ' . $error->getMessage();
                                throw $error; // Rejeita a exceção para que o erro possa ser tratado externamente
                            }
                        }
                
                        // Exemplo de uso
                        // enviarDados($jsonData);
                        ?>
                    

Roteirização com Divisão de Carga - Java


                        import com.google.gson.Gson;
                        import java.io.IOException;
                        import java.net.URI;
                        import java.net.http.HttpClient;
                        import java.net.http.HttpRequest;
                        import java.net.http.HttpResponse;
                        
                        public class Main {
                        
                            // JSON de entrada com os clientes com a placa do veiculo
                            static String jsonData = """
                                {
                                    "clientes": [
                                        {
                                            "cliente": "AAAA",
                                            "nomeCliente": "PADARIA SOL NASCENTE LTDA",
                                            "lat": -19.7996,
                                            "long": -44.018
                                        },
                                        {
                                            "cliente": "AAAB",
                                            "nomeCliente": "PADARIA DO CAMPO LTDA",
                                            "lat": -19.7589369,
                                            "long": -43.9941235
                                        },
                                        {
                                            "cliente": "AAAC",
                                            "nomeCliente": "PADARIA ESTRELA DA MANHÃ LTDA",
                                            "lat": -19.8200142,
                                            "long": -43.9605643
                                        }
                                    ],
                                    "veiculos": [
                                        {
                                            "placa": "PLACA1",
                                            "capacidade": "100"
                                        },
                                        {
                                            "placa": "PLACA2",
                                            "capacidade": "600"
                                        },
                                        {
                                            "placa": "PLACA3",
                                            "capacidade": "300"
                                        }
                                    ],
                                    "pedidos": [
                                        {
                                            "cliente": "AAAA",
                                            "peso": "100.000"
                                        },
                                        {
                                            "cliente": "AAAB",
                                            "peso": "600.000"
                                        },
                                        {
                                            "cliente": "AAAC",
                                            "peso": "300.000"
                                        }
                                    ]
                                }
                                """;
                        
                            // Variáveis para armazenar a base (se existirem)
                            static Double latitudeBase = null;  // Defina a latitude da base, se necessário
                            static Double longitudeBase = null; // Defina a longitude da base, se necessário
                        
                            static String gerarToken() {
                                // Supondo que essa função gera um token de autorização
                                return "seu_token_aqui";
                            }
                        
                            static String enviarDados(String data) throws IOException, InterruptedException {
                                String url = "https://iarotas.com.br/api/routerAndDistribute";
                                String token = gerarToken();
                        
                                try {
                                    Gson gson = new Gson();
                                    var jsonObject = gson.fromJson(data, java.util.Map.class);
                        
                                    // Verifica se as coordenadas da base estão disponíveis
                                    if (latitudeBase != null && longitudeBase != null) {
                                        // Adiciona o cliente "BASE" no início do array de clientes
                                        var clientes = (java.util.List) jsonObject.get("clientes");
                                        clientes.add(0, java.util.Map.of(
                                            "cliente", "BASE",
                                            "lat", latitudeBase,
                                            "long", longitudeBase
                                        ));
                                    }
                        
                                    // Faz a requisição POST para a API
                                    HttpClient client = HttpClient.newHttpClient();
                                    HttpRequest request = HttpRequest.newBuilder()
                                        .uri(URI.create(url))
                                        .header("Content-Type", "application/json")
                                        .header("Authorization", token)
                                        .POST(HttpRequest.BodyPublishers.ofString(data))
                                        .build();
                        
                                    HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
                        
                                    // Verifica se a resposta da requisição foi bem-sucedida
                                    if (response.statusCode() != 200) {
                                        throw new IOException("Erro na requisição: " + response.statusCode());
                                    }
                        
                                    // Retorna os dados da resposta
                                    return response.body();
                        
                                } catch (IOException | InterruptedException error) {
                                    // Captura e trata qualquer erro que ocorra durante a requisição
                                    System.err.println("Erro ao enviar dados: " + error.getMessage());
                                    throw error; // Rejeita a exceção para que o erro possa ser tratado externamente
                                }
                            }
                        
                            public static void main(String[] args) throws IOException, InterruptedException {
                                // Exemplo de uso
                                // enviarDados(jsonData);
                            }
                        }
            

Roteirizador - Exemplos

Roteirizador Simples

Este é um exemplo de código HTML e JavaScript para o Roteirizador Simples:



<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>Mapa de Rotas</title>
    <link rel="stylesheet" href="https://iarotas.com.br/IArotas/IArotas.css" />
    <style>
        #map {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            z-index: 1;
            /* Mapa ficará em segundo plano */
        }

        #controls {
            position: absolute;
            top: 10px;
            left: 10px;
            z-index: 1000;
            background: white;
            padding: 10px;
            border-radius: 5px;
            box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
            text-align: center;
            cursor: move;
        }

        /* Estilo do indicador de loading */
        #loading {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background-color: rgba(0, 0, 0, 0.5);
            color: white;
            padding: 20px;
            border-radius: 5px;
            display: none;
            z-index: 1100;
        }

        /* Estilo do modal */
        .modal {
            display: none;
            /* Oculta o modal por padrão */
            position: fixed;
            z-index: 1000;
            left: 0;
            top: 0;
            width: 100%;
            height: 100%;
            overflow: auto;
            background-color: rgba(0, 0, 0, 0.5);
            /* Fundo escuro */
        }

        /* Conteúdo do modal */
        .modal-content {
            background-color: #fefefe;
            margin: 10% auto;
            padding: 20px;
            border: 1px solid #888;
            width: 80%;
            max-width: 600px;
            border-radius: 10px;
            position: relative;
        }

        /* Botão para fechar o modal */
        .close {
            color: #aaa;
            float: right;
            font-size: 28px;
            font-weight: bold;
            cursor: pointer;
        }

        .close:hover {
            color: #000;
        }

        /* Estilo comum para os conteúdos das abas */
        .tabcontent pre {
            white-space: pre-wrap;
            /* Mantém a formatação */
            word-wrap: break-word;
            font-family: monospace;
            background-color: #f9f9f9;
            padding: 10px;
            border: 1px solid #ddd;
            border-radius: 5px;
            max-height: 400px;
            overflow-y: auto;
            margin: 0;
            /* Remove margens padrão */
        }

        /* Estilo das abas */
        .tabs {
            display: flex;
            justify-content: space-around;
            margin-bottom: 10px;
        }

        .tablink {
            background-color: #f1f1f1;
            border: none;
            padding: 10px 20px;
            cursor: pointer;
            flex: 1;
            text-align: center;
        }

        .tablink:hover {
            background-color: #ddd;
        }

        .tabcontent {
            display: none;
            padding: 10px;
            border-top: 1px solid #ccc;
        }

        /* Mostra a aba ativa */
        .active {
            display: block;
        }

        .table {
            width: 100%;
            border-collapse: collapse;
            /* Garante que as bordas não fiquem duplicadas */
        }

        .th,
        .td {
            border: 1px solid black;
            /* Adiciona borda a todas as células */
            padding: 8px;
            text-align: left;
        }

        .th {
            background-color: #f2f2f2;
            /* Fundo para o cabeçalho */
        }
    </style>
</head>

<body>
    <div id="controls">
        <button id="importButton">Importar Arquivo</button>
        <button id="demoButton">Demo</button>
        <button id="layoutButton">Layout</button>
        <input id="fileInput" type="file" accept=".json,.xml,.csv,.xls,.xlsx" style="display: none;" />
        <div style="margin-top: 10px;">
            <input type="checkbox" id="downloadCheckbox" />
            <label for="downloadCheckbox">Download arquivo</label>
        </div>

        <div style="margin-top: 10px;">
            <input type="checkbox" id="routeComplete" />
            <label for="routeComplete">Rota completa para download</label>
        </div>

        <div style="display: flex; align-items: center; margin-bottom: 10px;">
            <!-- Caixa de texto para pesquisa -->
            <input type="text" id="addressInput" placeholder="Endereço Partida/Retorno:"
                style="flex: 1; margin-right: 5px; box-sizing: border-box; height: 20px;" />

            <!-- Botão de pesquisa -->
            <button id="searchButton" style="height: 20px;">Pesquisar</button>
        </div>

    </div>

    <!-- Modal -->
    <div id="jsonModal" class="modal">
        <div class="modal-content">
            <span class="close">&times;</span>
            <div class="tabs">
                <button class="tablink" onclick="openTab(event, 'jsonTab')">JSON</button>
                <button class="tablink" onclick="openTab(event, 'xmlTab')">XML</button>
                <button class="tablink" onclick="openTab(event, 'csvTab')">CSV</button>
                <button class="tablink" onclick="openTab(event, 'xlsTab')">XLS/XLSX</button> <!-- Nova aba -->
            </div>
            <div id="jsonTab" class="tabcontent">
                <pre id="jsonContent"></pre>
                </div>
                <div id="xmlTab" class="tabcontent">
                    <pre id="xmlContent"></pre>
                </div>
                <div id="csvTab" class="tabcontent">
                    <pre id="csvContent"></pre>
                </div>
                <div id="xlsTab" class="tabcontent">
                    <div id="xlsContent"></div> <!-- Conteúdo da nova aba -->
                </div>
            </div>
        </div>

        <div id="map"></div>
        <!-- Indicador de Loading -->
        <div id="loading">Carregando, por favor aguarde...</div>

        <script src="https://iarotas.com.br/IArotas/IArotas.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/blueimp-md5/2.19.0/js/md5.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.5.0/jszip.min.js"></script>

        <script>
            // Inicializa o mapa com a vista centralizada em [0, 0] e zoom nível 2
            var map = L.map('map').setView([0, 0], 2);

            // Adiciona uma camada de tiles ao mapa
            L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
                maxZoom: 19
            }).addTo(map);

            // Define a posição do controle de zoom no canto inferior direito do mapa
            map.zoomControl.setPosition('bottomright');

            const controls = document.getElementById('controls');
            let offsetXcontrols, offsetYcontrols;

            controls.addEventListener('mousedown', (e) => {
                offsetXcontrols = e.clientX - parseInt(window.getComputedStyle(controls).left);
                offsetYcontrols = e.clientY - parseInt(window.getComputedStyle(controls).top);
                document.addEventListener('mousemove', moveControls);
                document.addEventListener('mouseup', () => {
                    document.removeEventListener('mousemove', moveControls);
                });
            });

            function moveControls(e) {
                controls.style.left = `${e.clientX - offsetXcontrols}px`;
                controls.style.top = `${e.clientY - offsetYcontrols}px`;
            }

            function showLoading() {
                document.getElementById('loading').style.display = 'block';
            }

            function hideLoading() {
                document.getElementById('loading').style.display = 'none';
            }

            document.getElementById('importButton').addEventListener('click', function () {
                document.getElementById('fileInput').click();
            });

            // Adiciona um listener para o evento de change no input de arquivo
            document.getElementById('fileInput').addEventListener('change', function (event) {
                const file = event.target.files[0];
                if (file) {
                    const fileExtension = file.name.split('.').pop().toLowerCase();

                    const reader = new FileReader();
                    reader.onload = function (e) {
                        let jsonData;

                        try {
                            if (fileExtension === 'json') {
                                jsonData = JSON.parse(e.target.result);
                            } else if (fileExtension === 'xml') {
                                jsonData = parseXML(e.target.result); // Usa a função parseXML para arquivos XML
                            } else if (fileExtension === 'csv') {
                                jsonData = csvToJson(e.target.result);
                            } else if (fileExtension === 'xls' || fileExtension === 'xlsx') {
                                jsonData = xlsToJson(e.target.result); // Processa arquivos Excel
                            } else {
                                throw new Error('Formato de arquivo não suportado.');
                            }

                            console.log("JSON: ", jsonData);

                            enviarDados(jsonData, fileExtension); // Passa a extensão para ajustar o download
                        } catch (err) {
                            alert('Erro ao processar o arquivo: ' + err.message);
                        }
                    };

                    if (fileExtension === 'xls' || fileExtension === 'xlsx') {
                        reader.readAsArrayBuffer(file); // Necessário para arquivos Excel
                    } else {
                        reader.readAsText(file);
                    }
                }
            });

            // Adicionando evento de clique no botão
            document.getElementById('demoButton').addEventListener('click', function () {
                console.log("JSON Carregado: ", jsonData);
                enviarDados(jsonData, 'json');
            });

            // Seleciona o modal e o botão de fechar
            const modal = document.getElementById('jsonModal');
            const closeButton = document.querySelector('.close');
            const jsonContent = document.getElementById('jsonContent');


            // Função para abrir as abas
            function openTab(evt, tabName) {
                const tabcontent = document.getElementsByClassName("tabcontent");
                for (let i = 0; i < tabcontent.length; i++) {
                    tabcontent[i].style.display = "none";
                }

                const tablinks = document.getElementsByClassName("tablink");
                for (let i = 0; i < tablinks.length; i++) {
                    tablinks[i].className = tablinks[i].className.replace(" active", "");
                }

                document.getElementById(tabName).style.display = "block";
                evt.currentTarget.className += " active";
            }

            document.getElementById('layoutButton').addEventListener('click', function () {
                document.getElementById('jsonContent').textContent = JSON.stringify(jsonData, null, 2);
                document.getElementById('xmlContent').textContent = xmlData;
                document.getElementById('csvContent').textContent = csvData;

                // Exibir dados XLS/XLSX na nova aba como tabela
                const xlsContent = document.getElementById('xlsContent');

                let table = `<table style="border-collapse: collapse; width: 100%;">
                    <tr>
                        <th style="border: 1px solid black; padding: 8px;">Cliente</th>
                        <th style="border: 1px solid black; padding: 8px;">Latitude</th>
                        <th style="border: 1px solid black; padding: 8px;">Longitude</th>
                    </tr>`;

                jsonData.clientes.forEach(cliente => {
                    table += `<tr>
                    <td style="border: 1px solid black; padding: 8px;">${cliente.cliente}</td>
                    <td style="border: 1px solid black; padding: 8px;">${cliente.lat}</td>
                    <td style="border: 1px solid black; padding: 8px;">${cliente.long}</td>
                  </tr>`;
                });

                table += '</table>';
                xlsContent.innerHTML = table;

                // Abre a primeira aba por padrão
                document.getElementById('jsonTab').style.display = 'block';
                document.querySelector('.tablink').classList.add('active');

                modal.style.display = 'block';
            });


            // Fecha o modal ao clicar no botão de fechar
            closeButton.addEventListener('click', function () {
                modal.style.display = 'none';
            });

            // Fecha o modal ao clicar fora dele
            window.addEventListener('click', function (event) {
                if (event.target === modal) {
                    modal.style.display = 'none';
                }
            });

            // Função para converter XML para JSON
            function parseXML(xml) {
                const parser = new DOMParser();
                const xmlDoc = parser.parseFromString(xml, "application/xml");
                const clientesArray = [];
                const clientesNodes = xmlDoc.getElementsByTagName("clientes");

                for (let i = 0; i < clientesNodes.length; i++) {
                    const cliente = clientesNodes[i].getElementsByTagName("cliente")[0].textContent;
                    const lat = parseFloat(clientesNodes[i].getElementsByTagName("lat")[0].textContent);
                    const long = parseFloat(clientesNodes[i].getElementsByTagName("long")[0].textContent);
                    clientesArray.push({ cliente, lat, long });
                }

                return { clientes: clientesArray };
            }

            // Função para converter CSV para JSON
            function csvToJson(csvString) {
                const rows = csvString.split('\n').map(row => row.trim()).filter(row => row);
                const headers = rows[0].split(',');

                const clientesArray = rows.slice(1).map(row => {
                    const values = row.split(',');

                    return {
                        cliente: values[0].trim(),
                        lat: parseFloat(values[1].trim()),
                        long: parseFloat(values[2].trim())
                    };
                });

                return { clientes: clientesArray };
            }

            // Função para converter arquivos XLS e XLSX para JSON
            function xlsToJson(arrayBuffer) {
                const workbook = XLSX.read(arrayBuffer, { type: 'array' });
                const sheetName = workbook.SheetNames[0]; // Usando a primeira aba do Excel
                const worksheet = workbook.Sheets[sheetName];
                const data = XLSX.utils.sheet_to_json(worksheet, { header: ['cliente', 'lat', 'long'] });

                // Conversão para o formato esperado
                const clientesArray = data.slice(1).map(row => ({
                    cliente: String(row.cliente),
                    lat: parseFloat(row.lat),
                    long: parseFloat(row.long)
                }));

                return { clientes: clientesArray };
            }

            // Função para enviar dados para a API
            async function enviarDados(data, inputFileType) {
                const url = 'https://iarotas.com.br/api/routerv1';
                const token = gerarToken();

                showLoading(); // Adiciona o indicador de loading antes do início da requisição

                try {
                    // ** Adiciona a base ao data antes do envio **
                    if (latitudeBase !== null && longitudeBase !== null) {
                        data.clientes.unshift({
                            cliente: "BASE",
                            lat: latitudeBase,
                            long: longitudeBase
                        });
                    }

                    const response = await fetch(url, {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json',
                            'Authorization': token
                        },
                        body: JSON.stringify(data)
                    });

                    const responseData = await response.json();

                    plotarCoordenadas(responseData);

                    const isDownloadChecked = document.getElementById('downloadCheckbox').checked;
                    const routeComplete = document.getElementById('routeComplete').checked;

                    if (isDownloadChecked) {
                        let blob;
                        let fileName;

                        // Função para remover a variável 'route' de cada objeto cliente
                        function removeRouteIfNecessary(data) {
                            return data.map(obj => {
                                const newObj = { ...obj }; // Cria uma cópia do objeto
                                if (!routeComplete) {
                                    delete newObj.route; // Remove a chave 'route' se routeComplete for false
                                }
                                return newObj;
                            });
                        }

                        // Remove a variável 'route' dos dados, se necessário
                        const filteredData = removeRouteIfNecessary(responseData);

                        if (inputFileType === 'json') {
                            blob = new Blob([JSON.stringify(filteredData, null, 2)], { type: 'application/json' });
                            fileName = 'resposta.json';
                        } else if (inputFileType === 'xml') {
                            const xmlData = jsonToXml(filteredData);
                            blob = new Blob([xmlData], { type: 'application/xml' });
                            fileName = 'resposta.xml';
                        } else if (inputFileType === 'csv') {
                            const csvData = jsonToCsv(filteredData);
                            blob = new Blob([csvData], { type: 'text/csv' });
                            fileName = 'resposta.csv';
                        } else if (inputFileType === 'xls' || inputFileType === 'xlsx') {
                            const workbook = jsonToExcel(filteredData);
                            const excelBuffer = XLSX.write(workbook, { bookType: inputFileType, type: 'array' });
                            blob = new Blob([excelBuffer], { type: 'application/octet-stream' });
                            fileName = `resposta.${inputFileType}`;
                        }

                        // Crie um arquivo ZIP e adicione o arquivo
                        const zip = new JSZip();
                        zip.file(fileName, blob);

                        // Gera o ZIP e faz o download
                        zip.generateAsync({ type: 'blob' }).then((zipBlob) => {
                            const downloadLink = document.createElement('a');
                            downloadLink.href = URL.createObjectURL(zipBlob);
                            downloadLink.download = 'resposta.zip';
                            downloadLink.click();
                        });
                    }
                } catch (error) {
                    console.error('Erro na requisição:', error);
                } finally {
                    hideLoading(); // Remove o indicador de loading depois que a requisição é completada
                }
            }

            // Função para converter JSON para XML
            function jsonToXml(json) {
                function buildXml(obj, nodeName) {
                    let xml = '';
                    if (Array.isArray(obj)) {
                        // Trata a lista de clientes
                        if (nodeName === "clientes") {
                            obj.forEach((item) => {
                                xml += `<${nodeName}>${buildXml(item, "cliente")}</${nodeName}>`;
                            });
                        } else if (nodeName === "route") {
                            // Para a lista de rotas, converte cada coordenada em uma nova tag <route>
                            obj.forEach((coords) => {
                                xml += `<${nodeName}><lat>${coords[0]}</lat><long>${coords[1]}</long></${nodeName}>`;
                            });
                        }
                    } else if (typeof obj === 'object' && obj !== null) {
                        for (const key in obj) {
                            if (key === 'route') {
                                xml += buildXml(obj[key], key);
                            } else if (key === 'cliente') {
                                xml += `<${key}>${obj[key]}</${key}>`;
                            } else if (key === 'lat' || key === 'long') {
                                xml += `<${key}>${obj[key]}</${key}>`;
                            } else {
                                xml += `<${key}>${buildXml(obj[key], key)}</${key}>`;
                            }
                        }
                    } else {
                        xml += obj.toString();
                    }
                    return xml;
                }

                return `<root>${buildXml(json, "clientes")}</root>`;
            }

            // Função para converter JSON para CSV
            function jsonToCsv(jsonArray) {
                const headers = Object.keys(jsonArray[0]);
                const rows = jsonArray.map(obj => headers.map(header => obj[header] || '').join(','));
                return [headers.join(','), ...rows].join('\n');
            }

            function jsonToExcel(jsonArray) {
                // Função auxiliar para transformar os elementos da 'route' em uma única string
                function concatRoute(jsonArray) {
                    return jsonArray.map(obj => {
                        const newObj = { ...obj };
                        if (Array.isArray(obj.route)) {
                            newObj.route = obj.route.map(coords => coords.join(',')).join(',');
                        }
                        return newObj;
                    });
                }

                const concatenatedJsonArray = concatRoute(jsonArray);

                const worksheet = XLSX.utils.json_to_sheet(concatenatedJsonArray);
                const workbook = XLSX.utils.book_new();
                XLSX.utils.book_append_sheet(workbook, worksheet, 'Dados');
                return workbook;
            }

            // Função para plotar coordenadas no mapa
            function plotarCoordenadas(data) {
                let bounds = L.latLngBounds([]);
                let contadorPontos = 1; // Inicia o contador de pontos a partir de 1

                data.forEach(cliente => {
                    const lat = cliente.lat;
                    const long = cliente.long;

                    // Se for o cliente "BASE", apenas adiciona ao bounds e pula o restante
                    if (cliente.cliente === "BASE") {
                        bounds.extend([lat, long]);
                        return; // Não adiciona marcador
                    }

                    // Cria um ícone personalizado com número baseado no contador
                    const iconePersonalizado = L.divIcon({
                        className: 'custom-icon',
                        html: `<div style="background: white; border: 2px solid blue; border-radius: 50%; width: 24px; height: 24px; display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: bold;">${contadorPontos}</div>`,
                        iconSize: [24, 24],
                        iconAnchor: [12, 12]
                    });

                    // Plota a rota do cliente usando o array `route`
                    if (cliente.route && cliente.route.length > 0) {
                        const rota = cliente.route.map(coord => [coord[0], coord[1]]);
                        const linha = L.polyline(rota, { color: 'blue', weight: 4 }).addTo(map);
                        bounds.extend(linha.getBounds());
                    }

                    // Adiciona o marcador no mapa (exceto para o cliente BASE)
                    const marcador = L.marker([lat, long], { icon: iconePersonalizado }).addTo(map);
                    marcador.bindPopup(`<b>${contadorPontos}. Cliente:</b> ${cliente.cliente}`);

                    contadorPontos++; // Incrementa o contador apenas para clientes válidos
                });

                // Ajusta o zoom para incluir todos os elementos
                if (!bounds.isValid()) {
                    data.forEach(cliente => bounds.extend([cliente.lat, cliente.long]));
                }

                map.fitBounds(bounds);
                hideLoading();
            }


            let latitudeBase = null;
            let longitudeBase = null;

            document.getElementById('searchButton').addEventListener('click', function () {
                const address = document.getElementById('addressInput').value;
                if (address) {
                    const token = gerarToken();
                    // Faz a requisição para o endpoint
                    fetch('https://iarotas.com.br/api/address', {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json',
                            'Authorization': `Bearer ${token}`
                        },
                        body: JSON.stringify([{
                            "codigo": "001",
                            "endereco": address // Passa o endereço digitado
                        }])
                    })
                        .then(response => response.json())
                        .then(data => {
                            if (data && data.length > 0) {
                                // Acessando as coordenadas corretamente do objeto retornado
                                const { latitude, longitude } = data[0];

                                // Armazena as coordenadas nas variáveis globais
                                latitudeBase = parseFloat(latitude);
                                longitudeBase = parseFloat(longitude);

                                // Adiciona o marcador no mapa com as coordenadas retornadas
                                const latlngPartida = [latitudeBase, longitudeBase];

                                const iconUrl = 'https://cdn-icons-png.flaticon.com/512/2776/2776063.png'; // Substitua pelo seu ícone
                                addMarker(map, latlngPartida, iconUrl, `Endereço: ${address}`);
                                map.setView(latlngPartida, 13); // Ajusta o mapa para a nova localização
                            } else {
                                alert('Endereço não encontrado ou inválido.');
                            }
                        })
                        .catch(error => {
                            console.error('Erro na requisição:', error);
                            alert('Ocorreu um erro ao procurar o endereço.');
                        });
                } else {
                    alert('Por favor, insira um endereço.');
                }
            });

            // Função para adicionar um marcador no mapa
            function addMarker(map, latlng, iconUrl, popupText) {
                const icon = L.icon({
                    iconUrl: iconUrl,
                    iconSize: [25, 41], // Tamanho do ícone
                    iconAnchor: [12, 41], // Ponto de ancoragem
                    popupAnchor: [1, -34], // Ponto de ancoragem do popup
                    shadowSize: [41, 41] // Tamanho da sombra
                });
                const marker = L.marker(latlng, { icon: icon })
                    .addTo(map)
                    .bindPopup(popupText);
                return marker;
            }

            // Função para gerar um token de autenticação
            function gerarToken() {
                return chave;
            }
        </script>
</body>

</html>


Roteirização com Veículos

Este é um exemplo de código HTML e JavaScript para a Roteirização com Veículos:



<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>Mapa de Rotas</title>
    <link rel="stylesheet" href="https://iarotas.com.br/IArotas/IArotas.css" />
    <style>
        #map {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            z-index: 1;
            /* Mapa ficará em segundo plano */
        }

        #controls {
            position: absolute;
            top: 10px;
            left: 10px;
            z-index: 1000;
            background: white;
            padding: 10px;
            border-radius: 5px;
            box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
            text-align: center;
            cursor: move;
        }

        /* Estilo do indicador de loading */
        #loading {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background-color: rgba(0, 0, 0, 0.5);
            color: white;
            padding: 20px;
            border-radius: 5px;
            display: none;
            z-index: 1100;
        }

        /* Estilo do modal */
        .modal {
            display: none;
            /* Oculta o modal por padrão */
            position: fixed;
            z-index: 1000;
            left: 0;
            top: 0;
            width: 100%;
            height: 100%;
            overflow: auto;
            background-color: rgba(0, 0, 0, 0.5);
            /* Fundo escuro */
        }

        /* Conteúdo do modal */
        .modal-content {
            background-color: #fefefe;
            margin: 10% auto;
            padding: 20px;
            border: 1px solid #888;
            width: 80%;
            max-width: 600px;
            border-radius: 10px;
            position: relative;
        }

        /* Botão para fechar o modal */
        .close {
            color: #aaa;
            float: right;
            font-size: 28px;
            font-weight: bold;
            cursor: pointer;
        }

        .close:hover {
            color: #000;
        }

        /* Estilo comum para os conteúdos das abas */
        .tabcontent pre {
            white-space: pre-wrap;
            /* Mantém a formatação */
            word-wrap: break-word;
            font-family: monospace;
            background-color: #f9f9f9;
            padding: 10px;
            border: 1px solid #ddd;
            border-radius: 5px;
            max-height: 400px;
            overflow-y: auto;
            margin: 0;
            /* Remove margens padrão */
        }

        /* Estilo das abas */
        .tabs {
            display: flex;
            justify-content: space-around;
            margin-bottom: 10px;
        }

        .tablink {
            background-color: #f1f1f1;
            border: none;
            padding: 10px 20px;
            cursor: pointer;
            flex: 1;
            text-align: center;
        }

        .tablink:hover {
            background-color: #ddd;
        }

        .tabcontent {
            display: none;
            padding: 10px;
            border-top: 1px solid #ccc;
        }

        /* Mostra a aba ativa */
        .active {
            display: block;
        }

        .table {
            width: 100%;
            border-collapse: collapse;
            /* Garante que as bordas não fiquem duplicadas */
        }

        .th,
        .td {
            border: 1px solid black;
            /* Adiciona borda a todas as células */
            padding: 8px;
            text-align: left;
        }

        .th {
            background-color: #f2f2f2;
            /* Fundo para o cabeçalho */
        }
    </style>
</head>

<body>
    <div id="controls">
        <button id="importButton">Importar Arquivo</button>
        <button id="demoButton">Demo</button>
        <button id="layoutButton">Layout</button>
        <input id="fileInput" type="file" accept=".json,.xml,.csv,.xls,.xlsx" style="display: none;" />
        <div style="margin-top: 10px;">
            <input type="checkbox" id="downloadCheckbox" />
            <label for="downloadCheckbox">Download arquivo</label>
        </div>

        <div style="margin-top: 10px;">
            <input type="checkbox" id="routeComplete" />
            <label for="routeComplete">Rota completa para download</label>
        </div>

        <div style="display: flex; align-items: center; margin-bottom: 10px;">
            <!-- Caixa de texto para pesquisa -->
            <input type="text" id="addressInput" placeholder="Endereço Partida/Retorno:"
                style="flex: 1; margin-right: 5px; box-sizing: border-box; height: 20px;" />

            <!-- Botão de pesquisa -->
            <button id="searchButton" style="height: 20px;">Pesquisar</button>
        </div>

    </div>

    <!-- Modal -->
    <div id="jsonModal" class="modal">
        <div class="modal-content">
            <span class="close">&times;</span>
            <div class="tabs">
                <button class="tablink" onclick="openTab(event, 'jsonTab')">JSON</button>
                <button class="tablink" onclick="openTab(event, 'xmlTab')">XML</button>
                <button class="tablink" onclick="openTab(event, 'csvTab')">CSV</button>
                <button class="tablink" onclick="openTab(event, 'xlsTab')">XLS/XLSX</button> <!-- Nova aba -->
            </div>
            <div id="jsonTab" class="tabcontent">
                <pre id="jsonContent"></pre>
</div>
<div id="xmlTab" class="tabcontent">
    <pre id="xmlContent"></pre>
</div>
<div id="csvTab" class="tabcontent">
    <pre id="csvContent"></pre>
</div>
<div id="xlsTab" class="tabcontent">
    <div id="xlsContent"></div> <!-- Conteúdo da nova aba -->
</div>
</div>
</div>

<div id="map"></div>

<div id="infoTable"
    style="position: absolute; bottom: 10px; left: 10px; z-index: 1000; background: white; padding: 10px; border-radius: 5px; box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2); width: 300px; height: 200px; overflow-y: auto; display: none;">
    <h3 style="margin: 0 0 10px 0; font-size: 16px;">Informações</h3>
    <table id="clientTable" style="width: 100%; border-collapse: collapse;">
        <thead>
            <tr>
                <th style="border: 1px solid black; padding: 8px;">Cor</th>
                <th style="border: 1px solid black; padding: 8px;">Placa</th>
            </tr>
        </thead>
        <tbody>
            <!-- As linhas da tabela serão inseridas aqui dinamicamente -->
        </tbody>
    </table>
</div>

<!-- Indicador de Loading -->
<div id="loading">Carregando, por favor aguarde...</div>

<script src="https://iarotas.com.br/IArotas/IArotas.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/blueimp-md5/2.19.0/js/md5.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.5.0/jszip.min.js"></script>

<script>
    // Inicializa o mapa com a vista centralizada em [0, 0] e zoom nível 2
    var map = L.map('map').setView([0, 0], 2);

    // Adiciona uma camada de tiles ao mapa
    L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
        maxZoom: 19
    }).addTo(map);

    // Define a posição do controle de zoom no canto inferior direito do mapa
    map.zoomControl.setPosition('bottomright');

    const controls = document.getElementById('controls');
    let offsetXcontrols, offsetYcontrols;

    controls.addEventListener('mousedown', (e) => {
        offsetXcontrols = e.clientX - parseInt(window.getComputedStyle(controls).left);
        offsetYcontrols = e.clientY - parseInt(window.getComputedStyle(controls).top);
        document.addEventListener('mousemove', moveControls);
        document.addEventListener('mouseup', () => {
            document.removeEventListener('mousemove', moveControls);
        });
    });

    function moveControls(e) {
        controls.style.left = `${e.clientX - offsetXcontrols}px`;
        controls.style.top = `${e.clientY - offsetYcontrols}px`;
    }

    function showLoading() {
        document.getElementById('loading').style.display = 'block';
    }

    function hideLoading() {
        document.getElementById('loading').style.display = 'none';
    }

    document.getElementById('importButton').addEventListener('click', function () {
        document.getElementById('fileInput').click();
    });

    // Adiciona um listener para o evento de change no input de arquivo
    document.getElementById('fileInput').addEventListener('change', function (event) {
        const file = event.target.files[0];
        if (file) {
            const fileExtension = file.name.split('.').pop().toLowerCase();

            const reader = new FileReader();
            reader.onload = function (e) {
                let jsonData;

                try {
                    if (fileExtension === 'json') {
                        jsonData = JSON.parse(e.target.result);
                    } else if (fileExtension === 'xml') {
                        jsonData = parseXML(e.target.result); // Usa a função parseXML para arquivos XML
                    } else if (fileExtension === 'csv') {
                        jsonData = csvToJson(e.target.result);
                    } else if (fileExtension === 'xls' || fileExtension === 'xlsx') {
                        jsonData = xlsToJson(e.target.result); // Processa arquivos Excel
                    } else {
                        throw new Error('Formato de arquivo não suportado.');
                    }

                    console.log("JSON: ", jsonData);

                    enviarDados(jsonData, fileExtension); // Passa a extensão para ajustar o download
                } catch (err) {
                    alert('Erro ao processar o arquivo: ' + err.message);
                }
            };

            if (fileExtension === 'xls' || fileExtension === 'xlsx') {
                reader.readAsArrayBuffer(file); // Necessário para arquivos Excel
            } else {
                reader.readAsText(file);
            }
        }
    });

    document.getElementById('demoButton').addEventListener('click', function () {
        console.log("JSON Carregado: ", jsonData);
        enviarDados(jsonData, 'json');
    });


    // Seleciona o modal e o botão de fechar
    const modal = document.getElementById('jsonModal');
    const closeButton = document.querySelector('.close');
    const jsonContent = document.getElementById('jsonContent');


    // Função para abrir as abas
    function openTab(evt, tabName) {
        const tabcontent = document.getElementsByClassName("tabcontent");
        for (let i = 0; i < tabcontent.length; i++) {
            tabcontent[i].style.display = "none";
        }

        const tablinks = document.getElementsByClassName("tablink");
        for (let i = 0; i < tablinks.length; i++) {
            tablinks[i].className = tablinks[i].className.replace(" active", "");
        }

        document.getElementById(tabName).style.display = "block";
        evt.currentTarget.className += " active";
    }

    document.getElementById('layoutButton').addEventListener('click', function () {
        document.getElementById('jsonContent').textContent = JSON.stringify(jsonData, null, 2);
        document.getElementById('xmlContent').textContent = xmlData;
        document.getElementById('csvContent').textContent = csvData;

        // Exibir dados XLS/XLSX na nova aba como tabela
        const xlsContent = document.getElementById('xlsContent');

        let table = `<table style="border-collapse: collapse; width: 100%;">
                    <tr>
                        <th style="border: 1px solid black; padding: 8px;">Cliente</th>
                        <th style="border: 1px solid black; padding: 8px;">Latitude</th>
                        <th style="border: 1px solid black; padding: 8px;">Longitude</th>
                        <th style="border: 1px solid black; padding: 8px;">Placa</th>

                    </tr>`;

        jsonData.clientes.forEach(cliente => {
            table += `<tr>
                    <td style="border: 1px solid black; padding: 8px;">${cliente.cliente}</td>
                    <td style="border: 1px solid black; padding: 8px;">${cliente.lat}</td>
                    <td style="border: 1px solid black; padding: 8px;">${cliente.long}</td>
                    <td style="border: 1px solid black; padding: 8px;">${cliente.placa}</td>
                  </tr>`;
        });

        table += '</table>';
        xlsContent.innerHTML = table;

        // Abre a primeira aba por padrão
        document.getElementById('jsonTab').style.display = 'block';
        document.querySelector('.tablink').classList.add('active');

        modal.style.display = 'block';
    });

    // Fecha o modal ao clicar no botão de fechar
    closeButton.addEventListener('click', function () {
        modal.style.display = 'none';
    });

    // Fecha o modal ao clicar fora dele
    window.addEventListener('click', function (event) {
        if (event.target === modal) {
            modal.style.display = 'none';
        }
    });

    // Função para converter XML para JSON
    function parseXML(xml) {
        const parser = new DOMParser();
        const xmlDoc = parser.parseFromString(xml, "application/xml");
        const clientesArray = [];
        const clientesNodes = xmlDoc.getElementsByTagName("clientes");

        for (let i = 0; i < clientesNodes.length; i++) {
            const cliente = clientesNodes[i].getElementsByTagName("cliente")[0].textContent;
            const lat = parseFloat(clientesNodes[i].getElementsByTagName("lat")[0].textContent);
            const long = parseFloat(clientesNodes[i].getElementsByTagName("long")[0].textContent);
            const placa = clientesNodes[i].getElementsByTagName("placa")[0]?.textContent || 'N/A'; // Exemplo
            clientesArray.push({ cliente, lat, long, placa });
        }

        return { clientes: clientesArray };
    }


    // Função para converter CSV para JSON
    function csvToJson(csvString) {
        const rows = csvString.split('\n').map(row => row.trim()).filter(row => row);
        const headers = rows[0].split(',');

        const clientesArray = rows.slice(1).map(row => {
            const values = row.split(',');

            return {
                cliente: values[0].trim(),
                lat: parseFloat(values[1].trim()),
                long: parseFloat(values[2].trim()),
                placa: values[3]?.trim() || 'N/A' // Assume que a placa é o 4º campo no CSV
            };
        });

        return { clientes: clientesArray };
    }


    // Função para converter arquivos XLS e XLSX para JSON
    function xlsToJson(arrayBuffer) {
        const workbook = XLSX.read(arrayBuffer, { type: 'array' });
        const sheetName = workbook.SheetNames[0]; // Usando a primeira aba do Excel
        const worksheet = workbook.Sheets[sheetName];
        const data = XLSX.utils.sheet_to_json(worksheet, { header: ['cliente', 'lat', 'long', 'placa'] });

        // Conversão para o formato esperado
        const clientesArray = data.slice(1).map(row => ({
            cliente: String(row.cliente),
            lat: parseFloat(row.lat),
            long: parseFloat(row.long),
            placa: row.placa || 'N/A' // Assume que a coluna `placa` existe no Excel
        }));

        return { clientes: clientesArray };
    }

    // Função para enviar dados para a API
    async function enviarDados(data, inputFileType) {
        const url = 'https://iarotas.com.br/api/routerPlates';
        const token = gerarToken();

        showLoading(); // Adiciona o indicador de loading antes do início da requisição

        try {
            if (latitudeBase !== null && longitudeBase !== null) {
                data.clientes.unshift({
                    cliente: "BASE",
                    lat: latitudeBase,
                    long: longitudeBase
                });
            }

            const response = await fetch(url, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'Authorization': token
                },
                body: JSON.stringify(data)
            });

            const responseData = await response.json();

            plotarCoordenadas(responseData);

            const isDownloadChecked = document.getElementById('downloadCheckbox').checked;
            const routeComplete = document.getElementById('routeComplete').checked;

            if (isDownloadChecked) {
                let blob;
                let fileName;

                // Função para remover a variável 'route' de cada objeto cliente
                function removeRouteIfNecessary(data) {
                    return data.map(obj => {
                        const newObj = { ...obj }; // Cria uma cópia do objeto
                        if (!routeComplete) {
                            delete newObj.route; // Remove a chave 'route' se routeComplete for false
                        }
                        return newObj;
                    });
                }

                // Remove a variável 'route' dos dados, se necessário
                const filteredData = removeRouteIfNecessary(responseData);

                if (inputFileType === 'json') {
                    blob = new Blob([JSON.stringify(filteredData, null, 2)], { type: 'application/json' });
                    fileName = 'resposta.json';
                } else if (inputFileType === 'xml') {
                    const xmlData = jsonToXml(filteredData);
                    blob = new Blob([xmlData], { type: 'application/xml' });
                    fileName = 'resposta.xml';
                } else if (inputFileType === 'csv') {
                    const csvData = jsonToCsv(filteredData);
                    blob = new Blob([csvData], { type: 'text/csv' });
                    fileName = 'resposta.csv';
                } else if (inputFileType === 'xls' || inputFileType === 'xlsx') {
                    const workbook = jsonToExcel(filteredData);
                    const excelBuffer = XLSX.write(workbook, { bookType: inputFileType, type: 'array' });
                    blob = new Blob([excelBuffer], { type: 'application/octet-stream' });
                    fileName = `resposta.${inputFileType}`;
                }

                // Crie um arquivo ZIP e adicione o arquivo
                const zip = new JSZip();
                zip.file(fileName, blob);

                // Gera o ZIP e faz o download
                zip.generateAsync({ type: 'blob' }).then((zipBlob) => {
                    const downloadLink = document.createElement('a');
                    downloadLink.href = URL.createObjectURL(zipBlob);
                    downloadLink.download = 'resposta.zip';
                    downloadLink.click();
                });
            }
        } catch (error) {
            console.error('Erro na requisição:', error);
        } finally {
            hideLoading(); // Remove o indicador de loading depois que a requisição é completada
        }
    }

    // Função para converter JSON para XML
    function jsonToXml(json) {
        function buildXml(obj, nodeName) {
            let xml = '';
            if (Array.isArray(obj)) {
                if (nodeName === "clientes") {
                    obj.forEach((item) => {
                        xml += `<${nodeName}>${buildXml(item, "cliente")}</${nodeName}>`;
                    });
                } else if (nodeName === "route") {
                    obj.forEach((coords) => {
                        xml += `<${nodeName}><lat>${coords[0]}</lat><long>${coords[1]}</long></${nodeName}>`;
                    });
                }
            } else if (typeof obj === 'object' && obj !== null) {
                for (const key in obj) {
                    if (key === 'route') {
                        xml += buildXml(obj[key], key);
                    } else if (key === 'cliente' || key === 'lat' || key === 'long' || key === 'placa' || key === 'cor') {
                        xml += `<${key}>${obj[key]}</${key}>`;
                    } else {
                        xml += `<${key}>${buildXml(obj[key], key)}</${key}>`;
                    }
                }
            } else {
                xml += obj.toString();
            }
            return xml;
        }

        return `<root>${buildXml(json, "clientes")}</root>`;
    }

    // Função para converter JSON para CSV
    function jsonToCsv(jsonArray) {
        const headers = Object.keys(jsonArray[0]);
        const rows = jsonArray.map(obj =>
            headers.map(header => obj[header] || '').join(',')
        );
        return [headers.join(','), ...rows].join('\n');
    }


    function jsonToExcel(jsonArray) {
        function concatRoute(jsonArray) {
            return jsonArray.map(obj => {
                const newObj = { ...obj };
                if (Array.isArray(obj.route)) {
                    newObj.route = obj.route.map(coords => coords.join(',')).join(',');
                }
                return newObj;
            });
        }

        const concatenatedJsonArray = concatRoute(jsonArray);

        const worksheet = XLSX.utils.json_to_sheet(concatenatedJsonArray);
        const workbook = XLSX.utils.book_new();
        XLSX.utils.book_append_sheet(workbook, worksheet, 'Dados');
        return workbook;
    }

    // Função para plotar coordenadas no mapa
    function plotarCoordenadas(data) {
        // Cria um bounds vazio para acumular os limites de todas as rotas e marcadores
        let bounds = L.latLngBounds([]);

        // Seleciona o corpo da tabela
        const tableBody = document.querySelector('#clientTable tbody');
        tableBody.innerHTML = ''; // Limpa o conteúdo anterior da tabela

        // Objeto para agrupar clientes por placa
        const agrupadoPorPlaca = {};

        // Itera pelos dados para agrupar por placa
        data.forEach((cliente) => {
            const placa = cliente.placa;
            const cor = cliente.cor;

            if (!agrupadoPorPlaca[placa]) {
                agrupadoPorPlaca[placa] = { cor, placa };
            }
        });

        // Adiciona as informações agrupadas na tabela
        Object.values(agrupadoPorPlaca).forEach((item) => {
            const row = document.createElement('tr');
            row.innerHTML = `
            <td style="border: 1px solid black; padding: 8px; background-color: ${item.cor};"></td>
            <td style="border: 1px solid black; padding: 8px;">${item.placa}</td>
        `;
            tableBody.appendChild(row);
        });

        let contador = 1; // Contador separado para numerar os clientes ignorando a base

        // Itera pelos dados para adicionar marcadores e plota as rotas
        data.forEach((cliente) => {
            const lat = cliente.lat;
            const long = cliente.long;
            const placa = cliente.placa;
            const cor = cliente.cor; // Cor recebida do endpoint

            // Plota a rota do cliente usando o array `route`
            if (cliente.route && cliente.route.length > 0) {
                const rota = cliente.route.map(coord => [coord[0], coord[1]]);
                const linha = L.polyline(rota, { color: cor, weight: 4 }).addTo(map); // Usa a cor do cliente

                // Adiciona os limites da rota ao bounds total
                bounds.extend(linha.getBounds());
            }

            // Se for BASE, não adiciona marcador
            if (cliente.cliente === "BASE") return;

            // Cria um ícone personalizado para incluir o número, ajustando a borda com a cor
            const iconePersonalizado = L.divIcon({
                className: 'custom-icon',
                html: `
                <div style="
                    background: white; 
                    border: 2px solid ${cor}; 
                    border-radius: 50%; 
                    width: 24px; 
                    height: 24px; 
                    display: flex; 
                    align-items: center; 
                    justify-content: center; 
                    font-size: 12px; 
                    font-weight: bold; 
                    color: ${cor};">
                    ${contador}
                </div>`,
                iconSize: [24, 24],
                iconAnchor: [12, 12]
            });

            // Adiciona o marcador no mapa
            const marcador = L.marker([lat, long], { icon: iconePersonalizado }).addTo(map);
            marcador.bindPopup(`<b>${contador}. Cliente:</b> ${cliente.cliente}<br><b>Placa:</b> ${placa}`);

            // Adiciona as coordenadas do marcador ao bounds total
            bounds.extend([lat, long]);

            contador++; // Incrementa o contador
        });

        // Ajusta o zoom do mapa para incluir todas as rotas e marcadores de uma vez
        if (bounds.isValid()) {
            map.fitBounds(bounds);
        }

        var infoTable = document.getElementById('infoTable');
        infoTable.style.display = 'block'; // Torna a div visível

        hideLoading();
    }


    let latitudeBase = null;
    let longitudeBase = null;

    document.getElementById('searchButton').addEventListener('click', function () {
        const address = document.getElementById('addressInput').value;
        if (address) {
            const token = gerarToken();
            // Faz a requisição para o endpoint
            fetch('https://iarotas.com.br/api/address', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'Authorization': `Bearer ${token}`
                },
                body: JSON.stringify([{
                    "codigo": "001",
                    "endereco": address // Passa o endereço digitado
                }])
            })
                .then(response => response.json())
                .then(data => {
                    if (data && data.length > 0) {
                        // Acessando as coordenadas corretamente do objeto retornado
                        const { latitude, longitude } = data[0];

                        // Armazena as coordenadas nas variáveis globais
                        latitudeBase = parseFloat(latitude);
                        longitudeBase = parseFloat(longitude);

                        // Adiciona o marcador no mapa com as coordenadas retornadas
                        const latlngPartida = [latitudeBase, longitudeBase];

                        const iconUrl = 'https://cdn-icons-png.flaticon.com/512/2776/2776063.png'; // Substitua pelo seu ícone
                        addMarker(map, latlngPartida, iconUrl, `Endereço: ${address}`);
                        map.setView(latlngPartida, 13); // Ajusta o mapa para a nova localização
                    } else {
                        alert('Endereço não encontrado ou inválido.');
                    }
                })
                .catch(error => {
                    console.error('Erro na requisição:', error);
                    alert('Ocorreu um erro ao procurar o endereço.');
                });
        } else {
            alert('Por favor, insira um endereço.');
        }
    });

    // Função para adicionar um marcador no mapa
    function addMarker(map, latlng, iconUrl, popupText) {
        const icon = L.icon({
            iconUrl: iconUrl,
            iconSize: [25, 41], // Tamanho do ícone
            iconAnchor: [12, 41], // Ponto de ancoragem
            popupAnchor: [1, -34], // Ponto de ancoragem do popup
            shadowSize: [41, 41] // Tamanho da sombra
        });
        const marker = L.marker(latlng, { icon: icon })
            .addTo(map)
            .bindPopup(popupText);
        return marker;
    }

    // Função para gerar um token de autenticação
    function gerarToken() {
        return chave;
    }
</script>
</body>

</html>


Roteirização com Divisão de Carga

Este é um exemplo de código HTML e JavaScript para a Roteirização com Divisão de Carga:



<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>Mapa de Rotas</title>
    <link rel="stylesheet" href="https://iarotas.com.br/IArotas/IArotas.css" />
    <style>
        #map {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            z-index: 1;
            /* Mapa ficará em segundo plano */
        }

        #controls {
            position: absolute;
            top: 10px;
            left: 10px;
            z-index: 1000;
            background: white;
            padding: 10px;
            border-radius: 5px;
            box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
            text-align: center;
            cursor: move;
        }

        /* Estilo do indicador de loading */
        #loading {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background-color: rgba(0, 0, 0, 0.5);
            color: white;
            padding: 20px;
            border-radius: 5px;
            display: none;
            z-index: 1100;
        }

        /* Estilo do modal */
        .modal {
            display: none;
            /* Oculta o modal por padrão */
            position: fixed;
            z-index: 1000;
            left: 0;
            top: 0;
            width: 100%;
            height: 100%;
            overflow: auto;
            /* Fundo escuro */
            background-color: rgba(0, 0, 0, 0.5);
        }

        /* Conteúdo do modal */
        .modal-content {
            background-color: #fefefe;
            margin: 5% auto;
            padding: 20px;
            border: 1px solid #888;
            width: 80%;
            max-width: 1000px;
            /* Aumenta a largura máxima do modal */
            max-height: 80%;
            /* Limita a altura do modal */
            border-radius: 10px;
            position: relative;
            overflow-y: auto;
            /* Adiciona barra de rolagem vertical, se necessário */
        }

        /* Para o conteúdo da tabela */
        #xlsContent {
            max-height: 400px;
            /* Ajuste a altura da tabela conforme necessário */
            overflow-y: auto;
            /* Permite rolar se a tabela for muito grande */
        }


        /* Botão para fechar o modal */
        .close {
            color: #aaa;
            float: right;
            font-size: 28px;
            font-weight: bold;
            cursor: pointer;
        }

        .close:hover {
            color: #000;
        }

        /* Estilo comum para os conteúdos das abas */
        .tabcontent pre {
            white-space: pre-wrap;
            /* Mantém a formatação */
            word-wrap: break-word;
            font-family: monospace;
            background-color: #f9f9f9;
            padding: 10px;
            border: 1px solid #ddd;
            border-radius: 5px;
            max-height: 400px;
            overflow-y: auto;
            margin: 0;
            /* Remove margens padrão */
        }

        /* Estilo das abas */
        .tabs {
            display: flex;
            justify-content: space-around;
            margin-bottom: 10px;
        }

        .tablink {
            background-color: #f1f1f1;
            border: none;
            padding: 10px 20px;
            cursor: pointer;
            flex: 1;
            text-align: center;
        }

        .tablink:hover {
            background-color: #ddd;
        }

        .tabcontent {
            display: none;
            padding: 10px;
            border-top: 1px solid #ccc;
        }

        /* Mostra a aba ativa */
        .active {
            display: block;
        }

        .table {
            width: 100%;
            border-collapse: collapse;
            /* Garante que as bordas não fiquem duplicadas */
        }

        .th,
        .td {
            border: 1px solid black;
            /* Adiciona borda a todas as células */
            padding: 8px;
            text-align: left;
        }

        .th {
            background-color: #f2f2f2;
            /* Fundo para o cabeçalho */
        }
    </style>
</head>

<body>
    <div id="controls">
        <button id="importButton">Importar Arquivo</button>
        <button id="demoButton">Demo</button>
        <button id="layoutButton">Layout</button>
        <input id="fileInput" type="file" accept=".json,.xml,.csv,.xls,.xlsx" style="display: none;" />
        <div style="margin-top: 10px;">
            <input type="checkbox" id="downloadCheckbox" />
            <label for="downloadCheckbox">Download arquivo</label>
        </div>

        <div style="margin-top: 10px;">
            <input type="checkbox" id="routeComplete" />
            <label for="routeComplete">Rota completa para download</label>
        </div>


        <div style="display: flex; align-items: center; margin-bottom: 10px;">
            <!-- Caixa de texto para pesquisa -->
            <input type="text" id="addressInput" placeholder="Endereço Partida/Retorno:"
                style="flex: 1; margin-right: 5px; box-sizing: border-box; height: 20px;" />

            <!-- Botão de pesquisa -->
            <button id="searchButton" style="height: 20px;">Pesquisar</button>
        </div>

    </div>

    <!-- Modal -->
    <div id="jsonModal" class="modal">
        <div class="modal-content">
            <span class="close">&times;</span>
            <div class="tabs">
                <button class="tablink" onclick="openTab(event, 'jsonTab')">JSON</button>
                <button class="tablink" onclick="openTab(event, 'xmlTab')">XML</button>
                <button class="tablink" onclick="openTab(event, 'csvTab')">CSV</button>
                <button class="tablink" onclick="openTab(event, 'xlsTab')">XLS/XLSX</button> <!-- Nova aba -->
            </div>
            <div id="jsonTab" class="tabcontent">
                <pre id="jsonContent"></pre>
</div>
<div id="xmlTab" class="tabcontent">
    <pre id="xmlContent"></pre>
</div>
<div id="csvTab" class="tabcontent">
    <pre id="csvContent"></pre>
</div>
<div id="xlsTab" class="tabcontent">
    <div id="xlsContent"></div> <!-- Conteúdo da nova aba -->
</div>
</div>
</div>

<div id="map"></div>

<div id="infoTable"
    style="position: absolute; bottom: 10px; left: 10px; z-index: 1000; background: white; padding: 10px; border-radius: 5px; box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2); width: 300px; height: 200px; overflow-y: auto; display: none;">
    <h3 style="margin: 0 0 10px 0; font-size: 16px;">Informações</h3>
    <table id="clientTable" style="width: 100%; border-collapse: collapse;">
        <thead>
            <tr>
                <th style="border: 1px solid black; padding: 8px;">Cor</th>
                <th style="border: 1px solid black; padding: 8px;">Placa</th>
            </tr>
        </thead>
        <tbody>
            <!-- As linhas da tabela serão inseridas aqui dinamicamente -->
        </tbody>
    </table>
</div>

<!-- Indicador de Loading -->
<div id="loading">Carregando, por favor aguarde...</div>

<script src="https://iarotas.com.br/IArotas/IArotas.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/blueimp-md5/2.19.0/js/md5.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.5.0/jszip.min.js"></script>

<script>
    // Inicializa o mapa com a vista centralizada em [0, 0] e zoom nível 2
    var map = L.map('map').setView([0, 0], 2);

    // Adiciona uma camada de tiles ao mapa
    L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
        maxZoom: 19
    }).addTo(map);

    // Define a posição do controle de zoom no canto inferior direito do mapa
    map.zoomControl.setPosition('bottomright');

    const controls = document.getElementById('controls');
    let offsetXcontrols, offsetYcontrols;

    controls.addEventListener('mousedown', (e) => {
        offsetXcontrols = e.clientX - parseInt(window.getComputedStyle(controls).left);
        offsetYcontrols = e.clientY - parseInt(window.getComputedStyle(controls).top);
        document.addEventListener('mousemove', moveControls);
        document.addEventListener('mouseup', () => {
            document.removeEventListener('mousemove', moveControls);
        });
    });

    function moveControls(e) {
        controls.style.left = `${e.clientX - offsetXcontrols}px`;
        controls.style.top = `${e.clientY - offsetYcontrols}px`;
    }

    function showLoading() {
        document.getElementById('loading').style.display = 'block';
    }

    function hideLoading() {
        document.getElementById('loading').style.display = 'none';
    }

    document.getElementById('importButton').addEventListener('click', function () {
        document.getElementById('fileInput').click();
    });

    // Adiciona um listener para o evento de change no input de arquivo
    document.getElementById('fileInput').addEventListener('change', function (event) {
        const file = event.target.files[0];
        if (file) {
            const fileExtension = file.name.split('.').pop().toLowerCase();

            const reader = new FileReader();
            reader.onload = function (e) {
                let jsonData;

                try {
                    if (fileExtension === 'json') {
                        jsonData = JSON.parse(e.target.result);
                    } else if (fileExtension === 'xml') {
                        jsonData = parseXML(e.target.result); // Usa a função parseXML para arquivos XML
                    } else if (fileExtension === 'csv') {
                        jsonData = csvToJson(e.target.result);
                    } else if (fileExtension === 'xls' || fileExtension === 'xlsx') {
                        jsonData = xlsToJson(e.target.result); // Processa arquivos Excel
                    } else {
                        throw new Error('Formato de arquivo não suportado.');
                    }

                    console.log("JSON: ", jsonData);

                    enviarDados(jsonData, fileExtension); // Passa a extensão para ajustar o download
                } catch (err) {
                    alert('Erro ao processar o arquivo: ' + err.message);
                }
            };

            if (fileExtension === 'xls' || fileExtension === 'xlsx') {
                reader.readAsArrayBuffer(file); // Necessário para arquivos Excel
            } else {
                reader.readAsText(file);
            }
        }
    });

    document.getElementById('demoButton').addEventListener('click', function () {
        console.log("JSON Carregado: ", jsonData);
        enviarDados(jsonData, 'json');
    });


    // Seleciona o modal e o botão de fechar
    const modal = document.getElementById('jsonModal');
    const closeButton = document.querySelector('.close');
    const jsonContent = document.getElementById('jsonContent');


    // Função para abrir as abas
    function openTab(evt, tabName) {
        const tabcontent = document.getElementsByClassName("tabcontent");
        for (let i = 0; i < tabcontent.length; i++) {
            tabcontent[i].style.display = "none";
        }

        const tablinks = document.getElementsByClassName("tablink");
        for (let i = 0; i < tablinks.length; i++) {
            tablinks[i].className = tablinks[i].className.replace(" active", "");
        }

        document.getElementById(tabName).style.display = "block";
        evt.currentTarget.className += " active";
    }

    document.getElementById('layoutButton').addEventListener('click', function () {
        document.getElementById('jsonContent').textContent = JSON.stringify(jsonData, null, 2);
        document.getElementById('xmlContent').textContent = xmlData;
        document.getElementById('csvContent').textContent = csvData;

        // Exibir dados XLS/XLSX na nova aba como tabela
        const xlsContent = document.getElementById('xlsContent');

        // Montando a tabela unificada com todos os dados
        let table = `<table style="border-collapse: collapse; width: 100%;">
                    <tr>
                        <th style="border: 1px solid black; padding: 8px;">Tipo</th>
                        <th style="border: 1px solid black; padding: 8px;">Cliente</th>
                        <th style="border: 1px solid black; padding: 8px;">Nome Cliente</th>
                        <th style="border: 1px solid black; padding: 8px;">Latitude</th>
                        <th style="border: 1px solid black; padding: 8px;">Longitude</th>
                        <th style="border: 1px solid black; padding: 8px;">Placa</th>
                        <th style="border: 1px solid black; padding: 8px;">Capacidade</th>
                        <th style="border: 1px solid black; padding: 8px;">Peso</th>
                    </tr>`;

        // Adicionando clientes à tabela
        jsonData.clientes.forEach(cliente => {
            table += `<tr>
                    <td style="border: 1px solid black; padding: 8px;">Cliente</td>
                    <td style="border: 1px solid black; padding: 8px;">${cliente.cliente}</td>
                    <td style="border: 1px solid black; padding: 8px;">${cliente.nomeCliente}</td>
                    <td style="border: 1px solid black; padding: 8px;">${cliente.lat}</td>
                    <td style="border: 1px solid black; padding: 8px;">${cliente.long}</td>
                    <td style="border: 1px solid black; padding: 8px;"></td> <!-- Placa vazia para clientes -->
                    <td style="border: 1px solid black; padding: 8px;"></td> <!-- Capacidade vazia para clientes -->
                    <td style="border: 1px solid black; padding: 8px;"></td> <!-- Peso vazio para clientes -->
                  </tr>`;
        });

        // Adicionando veiculos à tabela
        jsonData.veiculos.forEach(veiculo => {
            table += `<tr>
                    <td style="border: 1px solid black; padding: 8px;">Veículo</td>
                    <td style="border: 1px solid black; padding: 8px;"></td> <!-- Cliente vazio para veiculos -->
                    <td style="border: 1px solid black; padding: 8px;"></td> <!-- Nome Cliente vazio para veiculos -->
                    <td style="border: 1px solid black; padding: 8px;"></td> <!-- Latitude vazia para veiculos -->
                    <td style="border: 1px solid black; padding: 8px;"></td> <!-- Longitude vazia para veiculos -->
                    <td style="border: 1px solid black; padding: 8px;">${veiculo.placa}</td>
                    <td style="border: 1px solid black; padding: 8px;">${veiculo.capacidade}</td>
                    <td style="border: 1px solid black; padding: 8px;"></td> <!-- Peso vazio para veiculos -->
                  </tr>`;
        });

        // Adicionando pedidos à tabela
        jsonData.pedidos.forEach(pedido => {
            table += `<tr>
                    <td style="border: 1px solid black; padding: 8px;">Pedido</td>
                    <td style="border: 1px solid black; padding: 8px;">${pedido.cliente}</td>
                    <td style="border: 1px solid black; padding: 8px;"></td> <!-- Nome Cliente vazio para pedidos -->
                    <td style="border: 1px solid black; padding: 8px;"></td> <!-- Latitude vazia para pedidos -->
                    <td style="border: 1px solid black; padding: 8px;"></td> <!-- Longitude vazia para pedidos -->
                    <td style="border: 1px solid black; padding: 8px;"></td> <!-- Placa vazia para pedidos -->
                    <td style="border: 1px solid black; padding: 8px;"></td> <!-- Capacidade vazia para pedidos -->
                    <td style="border: 1px solid black; padding: 8px;">${pedido.peso}</td>
                  </tr>`;
        });

        table += '</table>';
        xlsContent.innerHTML = table;

        // Abre a primeira aba por padrão
        document.getElementById('jsonTab').style.display = 'block';
        document.querySelector('.tablink').classList.add('active');

        modal.style.display = 'block';
    });


    // Fecha o modal ao clicar no botão de fechar
    closeButton.addEventListener('click', function () {
        modal.style.display = 'none';
    });

    // Fecha o modal ao clicar fora dele
    window.addEventListener('click', function (event) {
        if (event.target === modal) {
            modal.style.display = 'none';
        }
    });

    // Função para converter XML para JSON
    function parseXML(xml) {
        const parser = new DOMParser();
        const xmlDoc = parser.parseFromString(xml, "application/xml");

        // Parse 'clientes'
        const clientes = Array.from(xmlDoc.getElementsByTagName("clientes")).map(clientesNode => ({
            cliente: clientesNode.getElementsByTagName("cliente")[0]?.textContent || "",
            nomeCliente: clientesNode.getElementsByTagName("nomeCliente")[0]?.textContent || "",
            lat: parseFloat(clientesNode.getElementsByTagName("lat")[0]?.textContent || "0"),
            long: parseFloat(clientesNode.getElementsByTagName("long")[0]?.textContent || "0"),
        }));

        // Parse 'veiculos'
        const veiculos = Array.from(xmlDoc.getElementsByTagName("veiculos")).map(veiculosNode => ({
            placa: veiculosNode.getElementsByTagName("placa")[0]?.textContent || "",
            capacidade: veiculosNode.getElementsByTagName("capacidade")[0]?.textContent || "",
        }));

        // Parse 'pedidos'
        const pedidos = Array.from(xmlDoc.getElementsByTagName("pedidos")).map(pedidosNode => ({
            cliente: pedidosNode.getElementsByTagName("cliente")[0]?.textContent || "",
            peso: pedidosNode.getElementsByTagName("peso")[0]?.textContent || "",
        }));

        return { clientes, veiculos, pedidos };
    }


    // Função para converter CSV para JSON
    function csvToJson(csvString) {
        const rows = csvString.split('\n').map(row => row.trim()).filter(row => row);
        const headers = rows[0].split(',');

        const data = rows.slice(1).map(row => row.split(',').reduce((acc, value, index) => {
            acc[headers[index].trim()] = value.trim();
            return acc;
        }, {}));

        const clientes = data.filter(row => row.tipo === 'cliente').map(row => ({
            cliente: row.cliente,
            nomeCliente: row.nomeCliente,
            lat: parseFloat(row.lat),
            long: parseFloat(row.long),
        }));

        const veiculos = data.filter(row => row.tipo === 'veiculo').map(row => ({
            placa: row.placa,
            capacidade: row.capacidade,
        }));

        const pedidos = data.filter(row => row.tipo === 'pedido').map(row => ({
            cliente: row.cliente,
            peso: row.peso,
        }));

        return { clientes, veiculos, pedidos };
    }

    // Função para converter arquivos XLS e XLSX para JSON
    function xlsToJson(arrayBuffer) {
        const workbook = XLSX.read(arrayBuffer, { type: 'array' });
        const sheetName = workbook.SheetNames[0];
        const worksheet = workbook.Sheets[sheetName];
        const data = XLSX.utils.sheet_to_json(worksheet);

        const clientes = data
            .filter(row => row.tipo === 'cliente')
            .map(row => ({
                cliente: String(row.cliente), // Garantir que seja string
                nomeCliente: row.nomeCliente || "", // Nome do cliente como string
                lat: parseFloat(row.lat), // Latitude como número
                long: parseFloat(row.long), // Longitude como número
            }));

        const veiculos = data
            .filter(row => row.tipo === 'veiculo')
            .map(row => ({
                placa: String(row.placa), // Garantir que seja string
                capacidade: String(row.capacidade), // Garantir que seja string
            }));

        const pedidos = data
            .filter(row => row.tipo === 'pedido')
            .map(row => ({
                cliente: String(row.cliente), // Garantir que seja string
                peso: String(row.peso), // Garantir que seja string
            }));

        return { clientes, veiculos, pedidos };
    }

    // Função para enviar dados para a API
    async function enviarDados(data, inputFileType) {
        const url = 'https://iarotas.com.br/api/routerAndDistribute';
        const token = gerarToken();

        showLoading(); // Adiciona o indicador de loading antes do início da requisição

        try {
            if (latitudeBase !== null && longitudeBase !== null) {
                data.clientes.unshift({
                    cliente: "BASE",
                    lat: latitudeBase,
                    long: longitudeBase
                });
            }

            const response = await fetch(url, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'Authorization': token
                },
                body: JSON.stringify(data)
            });

            const responseData = await response.json();

            plotarCoordenadas(responseData);

            const isDownloadChecked = document.getElementById('downloadCheckbox').checked;
            const routeComplete = document.getElementById('routeComplete').checked;

            if (isDownloadChecked) {
                let blob;
                let fileName;

                // Função para remover a variável 'route' de cada objeto cliente
                function removeRouteIfNecessary(data) {
                    return data.map(obj => {
                        const newObj = { ...obj }; // Cria uma cópia do objeto
                        if (!routeComplete) {
                            delete newObj.route; // Remove a chave 'route' se routeComplete for false
                        }
                        return newObj;
                    });
                }

                // Remove a variável 'route' dos dados, se necessário
                const filteredData = removeRouteIfNecessary(responseData);

                if (inputFileType === 'json') {
                    blob = new Blob([JSON.stringify(filteredData, null, 2)], { type: 'application/json' });
                    fileName = 'resposta.json';
                } else if (inputFileType === 'xml') {
                    const xmlData = jsonToXml(filteredData);
                    blob = new Blob([xmlData], { type: 'application/xml' });
                    fileName = 'resposta.xml';
                } else if (inputFileType === 'csv') {
                    const csvData = jsonToCsv(filteredData);
                    blob = new Blob([csvData], { type: 'text/csv' });
                    fileName = 'resposta.csv';
                } else if (inputFileType === 'xls' || inputFileType === 'xlsx') {
                    const workbook = jsonToExcel(filteredData);
                    const excelBuffer = XLSX.write(workbook, { bookType: inputFileType, type: 'array' });
                    blob = new Blob([excelBuffer], { type: 'application/octet-stream' });
                    fileName = `resposta.${inputFileType}`;
                }

                // Crie um arquivo ZIP e adicione o arquivo
                const zip = new JSZip();
                zip.file(fileName, blob);

                // Gera o ZIP e faz o download
                zip.generateAsync({ type: 'blob' }).then((zipBlob) => {
                    const downloadLink = document.createElement('a');
                    downloadLink.href = URL.createObjectURL(zipBlob);
                    downloadLink.download = 'resposta.zip';
                    downloadLink.click();
                });
            }
        } catch (error) {
            console.error('Erro na requisição:', error);
        } finally {
            hideLoading(); // Remove o indicador de loading depois que a requisição é completada
        }
    }

    // Função para converter JSON para XML
    function jsonToXml(json) {
        function buildXml(obj, nodeName) {
            let xml = '';
            if (Array.isArray(obj)) {
                if (nodeName === "clientes") {
                    obj.forEach((item) => {
                        xml += `<${nodeName}>${buildXml(item, "cliente")}</${nodeName}>`;
                    });
                } else if (nodeName === "route") {
                    obj.forEach((coords) => {
                        xml += `<${nodeName}><lat>${coords[0]}</lat><long>${coords[1]}</long></${nodeName}>`;
                    });
                }
            } else if (typeof obj === 'object' && obj !== null) {
                for (const key in obj) {
                    if (key === 'route') {
                        xml += buildXml(obj[key], key);
                    } else if (key === 'cliente' || key === 'lat' || key === 'long' || key === 'placa' || key === 'cor') {
                        xml += `<${key}>${obj[key]}</${key}>`;
                    } else {
                        xml += `<${key}>${buildXml(obj[key], key)}</${key}>`;
                    }
                }
            } else {
                xml += obj.toString();
            }
            return xml;
        }

        return `<root>${buildXml(json, "clientes")}</root>`;
    }

    // Função para converter JSON para CSV
    function jsonToCsv(jsonArray) {
        const headers = Object.keys(jsonArray[0]);
        const rows = jsonArray.map(obj =>
            headers.map(header => obj[header] || '').join(',')
        );
        return [headers.join(','), ...rows].join('\n');
    }

    // Função para converter JSON para XLS/XLSX
    function jsonToExcel(jsonArray) {
        function concatRoute(jsonArray) {
            return jsonArray.map(obj => {
                const newObj = { ...obj };
                if (Array.isArray(obj.route)) {
                    newObj.route = obj.route.map(coords => coords.join(',')).join(',');
                }
                return newObj;
            });
        }

        const concatenatedJsonArray = concatRoute(jsonArray);

        const worksheet = XLSX.utils.json_to_sheet(concatenatedJsonArray);
        const workbook = XLSX.utils.book_new();
        XLSX.utils.book_append_sheet(workbook, worksheet, 'Dados');
        return workbook;
    }

    // Função para plotar coordenadas no mapa
    function plotarCoordenadas(data) {
        // Cria um bounds vazio para acumular os limites de todas as rotas e marcadores
        let bounds = L.latLngBounds([]);

        // Seleciona o corpo da tabela
        const tableBody = document.querySelector('#clientTable tbody');
        tableBody.innerHTML = ''; // Limpa o conteúdo anterior da tabela

        // Objeto para agrupar clientes por placa
        const agrupadoPorPlaca = {};

        // Itera pelos dados para agrupar por placa
        data.forEach((cliente) => {
            const placa = cliente.placa;
            const cor = cliente.cor;

            if (!agrupadoPorPlaca[placa]) {
                agrupadoPorPlaca[placa] = { cor, placa };
            }
        });

        // Adiciona as informações agrupadas na tabela
        Object.values(agrupadoPorPlaca).forEach((item) => {
            const row = document.createElement('tr');
            row.innerHTML = `
            <td style="border: 1px solid black; padding: 8px; background-color: ${item.cor};"></td>
            <td style="border: 1px solid black; padding: 8px;">${item.placa}</td>
        `;
            tableBody.appendChild(row);
        });

        let contador = 1; // Contador separado para numerar os clientes ignorando a base

        // Itera pelos dados para adicionar marcadores e plota as rotas
        data.forEach((cliente) => {
            const lat = cliente.lat;
            const long = cliente.long;
            const placa = cliente.placa;
            const cor = cliente.cor; // Cor recebida do endpoint

            // Plota a rota do cliente usando o array `route`
            if (cliente.route && cliente.route.length > 0) {
                const rota = cliente.route.map(coord => [coord[0], coord[1]]);
                const linha = L.polyline(rota, { color: cor, weight: 4 }).addTo(map); // Usa a cor do cliente

                // Adiciona os limites da rota ao bounds total
                bounds.extend(linha.getBounds());
            }

            // Se for BASE, não adiciona marcador
            if (cliente.cliente === "BASE") return;

            // Cria um ícone personalizado para incluir o número, ajustando a borda com a cor
            const iconePersonalizado = L.divIcon({
                className: 'custom-icon',
                html: `
                <div style="
                    background: white; 
                    border: 2px solid ${cor}; 
                    border-radius: 50%; 
                    width: 24px; 
                    height: 24px; 
                    display: flex; 
                    align-items: center; 
                    justify-content: center; 
                    font-size: 12px; 
                    font-weight: bold; 
                    color: ${cor};">
                    ${contador}
                </div>`,
                iconSize: [24, 24],
                iconAnchor: [12, 12]
            });

            // Adiciona o marcador no mapa
            const marcador = L.marker([lat, long], { icon: iconePersonalizado }).addTo(map);
            marcador.bindPopup(`<b>${contador}. Cliente:</b> ${cliente.cliente}<br><b>Placa:</b> ${placa}`);

            // Adiciona as coordenadas do marcador ao bounds total
            bounds.extend([lat, long]);

            contador++; // Incrementa o contador
        });

        // Ajusta o zoom do mapa para incluir todas as rotas e marcadores de uma vez
        if (bounds.isValid()) {
            map.fitBounds(bounds);
        }

        var infoTable = document.getElementById('infoTable');
        infoTable.style.display = 'block'; // Torna a div visível

        hideLoading();
    }


    let latitudeBase = null;
    let longitudeBase = null;

    document.getElementById('searchButton').addEventListener('click', function () {
        const address = document.getElementById('addressInput').value;
        if (address) {
            const token = gerarToken();
            // Faz a requisição para o endpoint
            fetch('https://iarotas.com.br/api/address', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'Authorization': `Bearer ${token}`
                },
                body: JSON.stringify([{
                    "codigo": "001",
                    "endereco": address // Passa o endereço digitado
                }])
            })
                .then(response => response.json())
                .then(data => {
                    if (data && data.length > 0) {
                        // Acessando as coordenadas corretamente do objeto retornado
                        const { latitude, longitude } = data[0];

                        // Armazena as coordenadas nas variáveis globais
                        latitudeBase = parseFloat(latitude);
                        longitudeBase = parseFloat(longitude);

                        // Adiciona o marcador no mapa com as coordenadas retornadas
                        const latlngPartida = [latitudeBase, longitudeBase];

                        const iconUrl = 'https://cdn-icons-png.flaticon.com/512/2776/2776063.png'; // Substitua pelo seu ícone
                        addMarker(map, latlngPartida, iconUrl, `Endereço: ${address}`);
                        map.setView(latlngPartida, 13); // Ajusta o mapa para a nova localização
                    } else {
                        alert('Endereço não encontrado ou inválido.');
                    }
                })
                .catch(error => {
                    console.error('Erro na requisição:', error);
                    alert('Ocorreu um erro ao procurar o endereço.');
                });
        } else {
            alert('Por favor, insira um endereço.');
        }
    });

    // Função para adicionar um marcador no mapa
    function addMarker(map, latlng, iconUrl, popupText) {
        const icon = L.icon({
            iconUrl: iconUrl,
            iconSize: [25, 41], // Tamanho do ícone
            iconAnchor: [12, 41], // Ponto de ancoragem
            popupAnchor: [1, -34], // Ponto de ancoragem do popup
            shadowSize: [41, 41] // Tamanho da sombra
        });
        const marker = L.marker(latlng, { icon: icon })
            .addTo(map)
            .bindPopup(popupText);
        return marker;
    }

    // Função para gerar um token de autenticação
    function gerarToken() {
        return chave;
    }

</script>
</body>

</html>