// Alternance de couleurs
for (let i = 0; i < cityRows.length; i++) {
const rowNumber = i + 2;
const color = i % 2 === 0 ? "#f8f9fa" : "#ffffff";
sheet.getRange(rowNumber, 1, 1, headers.length).setBackground(color);
}
}
// Ajuster la largeur des colonnes
sheet.autoResizeColumns(1, headers.length);
}
/**
* Créer/mettre à jour l'onglet de classement
*/
function updateRankingSheet(cityVotes) {
const ss = SpreadsheetApp.getActiveSpreadsheet();
let rankingSheet = ss.getSheetByName("📊 Classement");
if (!rankingSheet) {
rankingSheet = ss.insertSheet("📊 Classement", 0);
} else {
rankingSheet.clear();
}
// Récupérer les votes si non fournis
if (!cityVotes) {
const mainSheet = ss.getSheetByName(MAIN_SHEET_NAME);
const data = mainSheet.getDataRange().getValues();
const rows = data.slice(1);
cityVotes = {};
rows.forEach(row => {
const city = row[2];
if (city) {
cityVotes[city] = (cityVotes[city] || 0) + 1;
}
});
}
// Créer le classement
const ranking = Object.entries(cityVotes)
.map(([city, votes]) => ({ city, votes }))
.sort((a, b) => b.votes - a.votes);
// En-tête
rankingSheet.getRange("A1").setValue("🎸 CLASSEMENT DES VILLES - THE SUNVIZORS TOURNÉE 2025");
rankingSheet.getRange("A1:F1").merge()
.setBackground("#764ba2")
.setFontColor("#FFFFFF")
.setFontWeight("bold")
.setHorizontalAlignment("center")
.setFontSize(16);
// Statistiques globales
const totalVotes = ranking.reduce((sum, item) => sum + item.votes, 0);
const validatedCities = ranking.filter(item => item.votes >= THRESHOLD).length;
rankingSheet.getRange("A2").setValue("Total votes:");
rankingSheet.getRange("B2").setValue(totalVotes);
rankingSheet.getRange("C2").setValue("Villes en course:");
rankingSheet.getRange("D2").setValue(ranking.length);
rankingSheet.getRange("E2").setValue("Concerts validés:");
rankingSheet.getRange("F2").setValue(validatedCities);
rankingSheet.getRange("A2:F2")
.setBackground("#F8F9FA")
.setFontWeight("bold")
.setHorizontalAlignment("center");
// Ligne vide
rankingSheet.getRange("A3:F3").setBackground("#FFFFFF");
// En-têtes du classement
const headers = ["Position", "Ville", "Votes", "Progression", "Statut", "🔗 Lien feuille"];
rankingSheet.getRange(4, 1, 1, headers.length).setValues([headers]);
rankingSheet.getRange(4, 1, 1, headers.length)
.setBackground("#667eea")
.setFontColor("#FFFFFF")
.setFontWeight("bold")
.setHorizontalAlignment("center");
// Remplir le classement
ranking.forEach((item, index) => {
const row = index + 5;
const position = index + 1;
const percentage = Math.min((item.votes / THRESHOLD) * 100, 100).toFixed(1) + "%";
const isValidated = item.votes >= THRESHOLD;
const status = isValidated ? "✅ VALIDÉ" : `${THRESHOLD - item.votes} restants`;
// Créer un lien vers la feuille de la ville
const sheetLink = `=HYPERLINK("#gid=" & INDIRECT("'"&"${item.city}"&"'!A1";1); "📋 Voir détails")`;
const rowData = [
position,
item.city,
item.votes,
percentage,
status,
"" // Le lien sera ajouté séparément
];
rankingSheet.getRange(row, 1, 1, rowData.length).setValues([rowData]);
// Ajouter le lien hypertexte
try {
rankingSheet.getRange(row, 6).setFormula(sheetLink);
} catch (e) {
rankingSheet.getRange(row, 6).setValue("Voir " + item.city);
}
// Couleurs selon position
let bgColor = "#FFFFFF";
if (position === 1) bgColor = "#FFD700"; // Or
else if (position === 2) bgColor = "#C0C0C0"; // Argent
else if (position === 3) bgColor = "#CD7F32"; // Bronze
else if (isValidated) bgColor = "#D1FAE5"; // Vert validé
else if (index % 2 === 1) bgColor = "#F8F9FA"; // Alternance
rankingSheet.getRange(row, 1, 1, 6).setBackground(bgColor);
// Statut en couleur
if (isValidated) {
rankingSheet.getRange(row, 5)
.setFontWeight("bold")
.setFontColor("#10b981");
}
});
// Figer les lignes d'en-tête
rankingSheet.setFrozenRows(4);
// Ajuster les colonnes
rankingSheet.autoResizeColumns(1, headers.length);
}
/**
* Fonction pour mise à jour manuelle
*/
function manualUpdate() {
organizeData();
SpreadsheetApp.getUi().alert('✅ Classement mis à jour !');
}
/**
* Exporter le classement en JSON pour la carte
*/
function exportRankingJSON() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const mainSheet = ss.getSheetByName(MAIN_SHEET_NAME);
const data = mainSheet.getDataRange().getValues();
const rows = data.slice(1);
// Compter les votes par ville
const cityVotes = {};
rows.forEach(row => {
const city = row[2];
if (city) {
cityVotes[city] = (cityVotes[city] || 0) + 1;
}
});
// Créer le JSON
const json = JSON.stringify(cityVotes, null, 2);
// Afficher dans un popup
const ui = SpreadsheetApp.getUi();
ui.alert('Classement JSON', json, ui.ButtonSet.OK);
return cityVotes;
}
/**
* Créer un menu personnalisé
*/
function onOpen() {
const ui = SpreadsheetApp.getUi();
ui.createMenu('🎸 The Sunvizors')
.addItem('🔄 Mettre à jour le classement', 'manualUpdate')
.addItem('📊 Exporter en JSON', 'exportRankingJSON')
.addToUi();
}
/**
* Fonction pour nettoyer les données de test
*/
function clearTestData() {
const ui = SpreadsheetApp.getUi();
const response = ui.alert(
'Confirmation',
'⚠️ Voulez-vous vraiment supprimer TOUTES les données de test ?',
ui.ButtonSet.YES_NO
);
if (response == ui.Button.YES) {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const mainSheet = ss.getSheetByName(MAIN_SHEET_NAME);
if (mainSheet && mainSheet.getLastRow() > 1) {
mainSheet.getRange(2, 1, mainSheet.getLastRow() - 1, mainSheet.getLastColumn()).clearContent();
ui.alert('✅ Données effacées !');
}
}
}

