<!DOCTYPE html>

<html lang="it">

<head>

    <meta charset="UTF-8">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>Divisore di Gruppi Dinamico</title>

    <!-- Carica Tailwind CSS per uno stile moderno e responsive -->

    <script src="https://cdn.tailwindcss.com"></script>

    <style>

        /* Stili personalizzati per la tipografia e l'aspetto generale */

        body {

            font-family: 'Inter', sans-serif;

            background-color: #f7f9fb;

        }

        .group-card {

            min-height: 150px;

            box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.06);

            transition: transform 0.2s, box-shadow 0.2s;

        }

        .group-card:hover {

            box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.05);

            transform: translateY(-2px);

        }

    </style>

</head>

<body class="p-4 sm:p-8">


    <div class="max-w-4xl mx-auto">

        <h1 class="text-3xl sm:text-4xl font-extrabold text-gray-800 mb-2">Generatore di Gruppi per Lezioni</h1>

        <p class="text-gray-600 mb-6 sm:mb-8">

            Gestisci la lista dei partecipanti, segna le presenze e genera i gruppi casuali con un clic.

        </p>


        <!-- Sezione di configurazione -->

        <div class="bg-white p-6 rounded-xl shadow-lg mb-8 border border-gray-200">

            <h2 class="text-2xl font-bold text-gray-700 mb-4 border-b pb-2">Configurazione Lezione</h2>

            

            <div class="grid grid-cols-1 lg:grid-cols-3 gap-6">

                

                <!-- Colonna 1: Numero di Gruppi -->

                <div class="col-span-1">

                    <label for="numGroupsInput" class="block text-sm font-medium text-gray-700 mb-2">Numero di Gruppi Desiderato</label>

                    <input type="number" id="numGroupsInput" min="1" value="4"

                        class="w-full p-2 border border-gray-300 rounded-lg focus:ring-indigo-500 focus:border-indigo-500 shadow-sm"

                        onchange="saveSettings()">

                </div>


                <!-- Colonna 2 & 3: Lista Master e Nomi Gruppi -->

                <div class="col-span-2 grid grid-cols-1 sm:grid-cols-2 gap-4">

                     <div>

                        <label for="groupNamesInput" class="block text-sm font-medium text-gray-700 mb-2">Nomi dei Gruppi (separati da virgola)</label>

                        <input type="text" id="groupNamesInput" 

                            class="w-full p-2 border border-gray-300 rounded-lg focus:ring-indigo-500 focus:border-indigo-500 shadow-sm"

                            value="Squadra Alfa, I Pionieri, Le Sentinelle, Gruppo Zenith"

                            onchange="saveSettings()">

                        <p class="text-xs text-gray-500 mt-1">Se ci sono più gruppi che nomi, verranno usati i numeri.</p>

                    </div>

                    

                    <div>

                        <label for="masterListArea" class="block text-sm font-medium text-gray-700 mb-2">Lista Master (un nome per riga)</label>

                        <textarea id="masterListArea" rows="4"

                            class="w-full p-2 border border-gray-300 rounded-lg focus:ring-indigo-500 focus:border-indigo-500 shadow-sm"

                            onchange="updateAttendanceAndSave()">Aurora

Fulvia

Eleonora

Lucia B.

Edoardo

Giorgia

Esra

Giovanni

Andrea

Mattia

Riccardo

Jacopo

Kamela

Lucioa Lol.

Fabio

Donatella

Rachid

Alessandra

Dimitri

Marta

Laura

Filippo</textarea>

                    </div>

                </div>

            </div>

            

            <!-- Sezione Presenze -->

            <div class="mt-6 border-t pt-4">

                <h3 class="text-lg font-bold text-gray-700 mb-3">Segna Presenze (<span id="attendeeCount">0</span> persone presenti)</h3>

                <div id="attendanceContainer" class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6 gap-3">

                    <!-- Checkbox delle presenze verranno inserite qui dal JS -->

                </div>

            </div>

        </div>



        <!-- Pulsante di generazione -->

        <button id="shuffleButton"

            class="w-full sm:w-auto px-8 py-3 bg-indigo-600 text-white font-bold text-lg rounded-xl hover:bg-indigo-700 transition duration-150 transform hover:scale-[1.01] focus:outline-none focus:ring-4 focus:ring-indigo-500 focus:ring-opacity-50 active:bg-indigo-800 shadow-lg mb-8">

            <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 inline-block mr-2 align-text-bottom" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">

                <path stroke-linecap="round" stroke-linejoin="round" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />

            </svg>

            Mescola e Genera Gruppi

        </button>

        

        <!-- Area di visualizzazione dei gruppi -->

        <div id="groupsContainer" class="grid grid-cols-1 md:grid-cols-2 gap-6">

            <!-- I risultati dei gruppi saranno inseriti qui -->

        </div>


        <div id="statusMessage" class="mt-6 text-center text-gray-500 italic">

            Configura la lista e il numero di gruppi, quindi clicca sul pulsante.

        </div>

    </div>


    <script type="text/javascript">

        // Costanti per le chiavi di localStorage

        const STORAGE_KEY_PEOPLE = 'group_shuffler_people';

        const STORAGE_KEY_GROUP_NAMES = 'group_shuffler_group_names';

        const STORAGE_KEY_NUM_GROUPS = 'group_shuffler_num_groups';

        

        const button = document.getElementById('shuffleButton');

        const groupsContainer = document.getElementById('groupsContainer');

        const statusMessage = document.getElementById('statusMessage');

        const masterListArea = document.getElementById('masterListArea');

        const numGroupsInput = document.getElementById('numGroupsInput');

        const groupNamesInput = document.getElementById('groupNamesInput');

        const attendanceContainer = document.getElementById('attendanceContainer');

        const attendeeCountSpan = document.getElementById('attendeeCount');



        /**

         * Salva le impostazioni correnti (lista master, nomi gruppi, numero gruppi) in localStorage.

         */

        function saveSettings() {

            // Salva la lista master (un nome per riga)

            localStorage.setItem(STORAGE_KEY_PEOPLE, masterListArea.value);

            // Salva i nomi dei gruppi

            localStorage.setItem(STORAGE_KEY_GROUP_NAMES, groupNamesInput.value);

            // Salva il numero di gruppi

            localStorage.setItem(STORAGE_KEY_NUM_GROUPS, numGroupsInput.value);

        }


        /**

         * Carica le impostazioni da localStorage all'avvio.

         */

        function loadSettings() {

            const savedPeople = localStorage.getItem(STORAGE_KEY_PEOPLE);

            const savedGroupNames = localStorage.getItem(STORAGE_KEY_GROUP_NAMES);

            const savedNumGroups = localStorage.getItem(STORAGE_KEY_NUM_GROUPS);


            if (savedPeople) {

                masterListArea.value = savedPeople;

            }

            if (savedGroupNames) {

                groupNamesInput.value = savedGroupNames;

            }

            if (savedNumGroups) {

                numGroupsInput.value = savedNumGroups;

            }

            

            // Renderizza la lista delle presenze dopo aver caricato la lista master

            renderAttendanceList();

        }


        /**

         * Renderizza la lista di checkbox per segnare le presenze.

         */

        function renderAttendanceList() {

            const people = getMasterList();

            attendanceContainer.innerHTML = '';

            

            if (people.length === 0) {

                attendanceContainer.innerHTML = '<p class="text-sm text-gray-500 italic col-span-full">Inserisci i nomi nella lista master per segnare le presenze.</p>';

                attendeeCountSpan.textContent = '0';

                return;

            }


            people.forEach(person => {

                const isChecked = true; // Di default, tutti sono presenti all'inizio

                const html = `

                    <div class="flex items-center">

                        <input id="person-${person}" type="checkbox" value="${person}" ${isChecked ? 'checked' : ''}

                               class="h-4 w-4 text-indigo-600 border-gray-300 rounded cursor-pointer"

                               onchange="updateAttendeeCount()">

                        <label for="person-${person}" class="ml-2 text-sm text-gray-700 whitespace-nowrap overflow-hidden text-ellipsis cursor-pointer" title="${person}">

                            ${person}

                        </label>

                    </div>

                `;

                attendanceContainer.insertAdjacentHTML('beforeend', html);

            });

            updateAttendeeCount();

        }

        

        /**

         * Aggiorna il conteggio delle persone presenti.

         */

        function updateAttendeeCount() {

            const attendees = getAttendees();

            attendeeCountSpan.textContent = attendees.length.toString();

        }


        /**

         * Funzione di utility per estrarre la lista master dall'area di testo.

         * @returns {Array<string>} La lista dei nomi senza righe vuote.

         */

        function getMasterList() {

            return masterListArea.value

                .split('\n')

                .map(name => name.trim())

                .filter(name => name.length > 0);

        }


        /**

         * Aggiorna la lista di presenze e salva le impostazioni. Chiamata su cambio della Master List.

         */

        function updateAttendanceAndSave() {

            saveSettings();

            renderAttendanceList();

        }


        /**

         * Ottiene l'elenco dei partecipanti selezionati dalle checkbox.

         * @returns {Array<string>} I nomi delle persone presenti.

         */

        function getAttendees() {

            const checkboxes = attendanceContainer.querySelectorAll('input[type="checkbox"]:checked');

            return Array.from(checkboxes).map(checkbox => checkbox.value);

        }


        /**

         * Ottiene l'elenco dei nomi dei gruppi.

         * @returns {Array<string>} La lista dei nomi dei gruppi.

         */

        function getGroupNames() {

            return groupNamesInput.value

                .split(',')

                .map(name => name.trim())

                .filter(name => name.length > 0);

        }


        /**

         * Implementa l'algoritmo Fisher-Yates per mescolare un array in modo casuale.

         * @param {Array<string>} array L'array da mescolare.

         * @returns {Array<string>} L'array mescolato.

         */

        function shuffleArray(array) {

            const shuffled = [...array];

            for (let i = shuffled.length - 1; i > 0; i--) {

                const j = Math.floor(Math.random() * (i + 1));

                [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];

            }

            return shuffled;

        }


        /**

         * Divide un array mescolato in un numero flessibile di gruppi, cercando l'equilibrio.

         * @param {Array<string>} shuffledPeople L'array di persone mescolate.

         * @param {number} numGroups Il numero di gruppi desiderato.

         * @returns {Array<Array<string>>} Un array contenente i gruppi.

         */

        function divideIntoGroups(shuffledPeople, numGroups) {

            const P = shuffledPeople.length; // Persone

            const G = numGroups; // Gruppi

            

            if (P === 0 || G <= 0) return [];


            // Calcolo la dimensione base del gruppo (parte intera)

            const S = Math.floor(P / G);

            // Calcolo il resto (numero di gruppi che avranno S+1 persone)

            const R = P % G;


            const groups = [];

            let currentIndex = 0;


            for (let i = 0; i < G; i++) {

                // Se i < R, il gruppo avrà dimensione S+1, altrimenti S

                const size = i < R ? S + 1 : S; 

                

                if (size > 0) {

                    const group = shuffledPeople.slice(currentIndex, currentIndex + size);

                    groups.push(group);

                    currentIndex += size;

                }

            }


            return groups;

        }


        /**

         * Genera e visualizza i gruppi.

         */

        function generateAndDisplayGroups() {

            const attendees = getAttendees();

            const numGroups = parseInt(numGroupsInput.value, 10);

            const groupNames = getGroupNames();

            

            groupsContainer.innerHTML = '';

            

            if (attendees.length < numGroups) {

                 groupsContainer.innerHTML = `<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded-xl col-span-full" role="alert"><p class="font-bold">Attenzione!</p><p class="text-sm">Il numero di persone presenti (${attendees.length}) è inferiore al numero di gruppi desiderato (${numGroups}). Riduci il numero di gruppi o aggiungi persone.</p></div>`;

                 statusMessage.classList.add('hidden');

                 return;

            }

            if (numGroups <= 0) {

                 groupsContainer.innerHTML = `<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded-xl col-span-full" role="alert"><p class="font-bold">Errore!</p><p class="text-sm">Il numero di gruppi deve essere maggiore di zero.</p></div>`;

                 statusMessage.classList.add('hidden');

                 return;

            }


            // 1. Mescola le persone presenti

            const shuffledPeople = shuffleArray(attendees);


            // 2. Dividi nei gruppi

            const groups = divideIntoGroups(shuffledPeople, numGroups);


            // 3. Mescola i nomi dei gruppi (per assegnarli in modo casuale)

            const shuffledNames = shuffleArray(groupNames);


            // 4. Pulisci il contenitore e mostra i risultati

            statusMessage.classList.add('hidden');


            groups.forEach((group, index) => {

                let groupName = `Gruppo ${index + 1}`;

                

                // Assegna un nome casuale se disponibile

                if (shuffledNames[index]) {

                    groupName = shuffledNames[index];

                }

                

                const membersList = group.map(person =>

                    // Stile per ogni membro

                    `<span class="inline-block bg-indigo-100 text-indigo-800 text-sm font-medium mr-2 mb-2 px-3 py-1 rounded-full border border-indigo-200 whitespace-nowrap">${person}</span>`

                ).join('');


                // Crea la card HTML per il gruppo

                const groupCardHtml = `

                    <div class="group-card bg-white p-5 rounded-xl border border-gray-200">

                        <h2 class="text-xl font-bold text-indigo-700 mb-3">${groupName}</h2>

                        <p class="text-sm font-medium text-gray-500 mb-3">Membri: ${group.length} persone</p>

                        <div>

                            ${membersList}

                        </div>

                    </div>

                `;

                groupsContainer.insertAdjacentHTML('beforeend', groupCardHtml);

            });

        }


        // --- Inizializzazione ---

        

        // Aggiungi il listener al pulsante

        button.addEventListener('click', generateAndDisplayGroups);


        // Carica le impostazioni e renderizza la lista di presenze all'avvio

        document.addEventListener('DOMContentLoaded', () => {

            loadSettings();

            generateAndDisplayGroups(); // Genera una prima divisione all'avvio

        });

        

    </script>

</body>

</html>