MediaWiki:Script/Calculator.js : Différence entre versions

(Page créée avec « var weaponData = {'Poings': [['warrior', 'ninja', 'sura', 'shamane', 'lycan'], [0, 0, 0, 0], []],'Épée': [['warrior', 'ninja', 'sura'], [15, 19, 13, 15], [0, 7, 14, 21,... »)
 
Ligne 20 : Ligne 20 :
 
     var option = document.createElement("option");
 
     var option = document.createElement("option");
 
     option.textContent = weapon;
 
     option.textContent = weapon;
 +
    option.value = weapon;
 
     if (weaponData[weapon][0].indexOf("warrior") === -1) {
 
     if (weaponData[weapon][0].indexOf("warrior") === -1) {
 
       hideElement(option);
 
       hideElement(option);
Ligne 76 : Ligne 77 :
  
 
function filterUpgrade(weaponUpgrade, labelWeaponUpgrade, weaponName, randomAttackValue) {
 
function filterUpgrade(weaponUpgrade, labelWeaponUpgrade, weaponName, randomAttackValue) {
 
+
 
 
   if (weaponName.indexOf('serpent') !== -1) {
 
   if (weaponName.indexOf('serpent') !== -1) {
 
     showElement(randomAttackValue);
 
     showElement(randomAttackValue);
Ligne 207 : Ligne 208 :
  
  
function characterCreationListener(character, battle) {
+
function saveButtonGreen(characters, animation) {
 +
  if (animation) {
 +
    characters.saveBar.style.animation = characters.saveButton.dataset.animation;
 +
  } else {
 +
    characters.saveBar.style.animation = "";
 +
    characters.saveBar.style.backgroundColor = "lightgreen";
 +
  }
 +
}
 +
 
 +
 
 +
function saveButtonOrange(characters) {
 +
  characters.saveBar.style.animation = "";
 +
  characters.saveBar.style.backgroundColor = "#ffdd40";
 +
}
 +
 
 +
 
 +
function characterCreationListener(characters, battle) {
  
   character.characterCreation.addEventListener("submit", function(event) {
+
   characters.characterCreation.addEventListener("submit", function(event) {
 
     event.preventDefault();
 
     event.preventDefault();
     saveCharacter(character.savedCharacters, character.characterCreation, battle);
+
 
    character.unsavedChanges = false;
+
     if (characters.unsavedChanges) {
 +
      saveCharacter(characters.savedCharacters, characters.characterCreation, battle);
 +
      saveButtonGreen(characters, true);
 +
      characters.unsavedChanges = false;
 +
    }
 
   });
 
   });
 
}
 
}
Ligne 280 : Ligne 301 :
  
  
function deleteCharacter(characters, pseudo, element, battle) {
+
function deleteCharacter(characters, pseudo, displayedPseudo, element, battle) {
   delete characters[pseudo];
+
 
 +
   delete characters.savedCharacters[pseudo];
 +
 
 +
  var charactersPseudo = Object.keys(characters.savedCharacters);
 +
 
 
   element.remove();
 
   element.remove();
   updateSavedCharactersPseudo(Object.keys(characters));
+
 
 +
   updateSavedCharactersPseudo(charactersPseudo);
 
   removeBattleChoice(battle, pseudo);
 
   removeBattleChoice(battle, pseudo);
 +
 
 +
  if (!charactersPseudo.length || characters.characterCreation.name.value === pseudo) {
 +
    saveButtonGreen(characters);
 +
    characters.unsavedChanges = false;
 +
    hideElement(characters.characterCreation);
 +
  }
 
}
 
}
  
Ligne 290 : Ligne 322 :
  
 
function updateForm(formData, characterCreation) {
 
function updateForm(formData, characterCreation) {
 +
 
 
   characterCreation.reset();
 
   characterCreation.reset();
 +
 
 
   for (var [name, value] of Object.entries(formData)) {
 
   for (var [name, value] of Object.entries(formData)) {
     var field = characterCreation.querySelector('[name="' + name + '"]');
+
     var formElement = characterCreation[name];
     if (field) {
+
     if (formElement) {
       field.value = value;
+
       formElement.value = value;
 
     }
 
     }
 
   }
 
   }
Ligne 300 : Ligne 334 :
  
  
function handleClickOnSvg(event, characters, battle) {
+
function handleClickOnCharacter(target, characters, battle, edition) {
 
    
 
    
   var target = event.target;
+
   var displayedPseudo = characters.characterCreation.name.value;
 
    
 
    
   if (target.tagName === "path") {
+
   if (edition) {
     target = target.parentElement;
+
   
  }
+
    var pseudo = target.querySelector("span.input").textContent;
 
+
   
  var pseudo = target.parentElement.dataset.pseudo;
+
     showElement(characters.characterCreation);
 
+
 
  switch (target.dataset.icon) {
+
    if (!characters.unsavedChanges) {
        
+
      updateForm(characters.savedCharacters[pseudo], characters.characterCreation);
     case 'edition':
+
 
       showElement(characters.characterCreation);
+
    } else if (displayedPseudo === pseudo) {
     
+
       // pass
       if (!characters.unsavedChanges) {
+
 
 +
     } else {
 +
       var result = confirm("Voulez-vous continuer ? Les dernières modifications ne seront pas sauvegardées.");
 +
 
 +
       if (result) {
 
         updateForm(characters.savedCharacters[pseudo], characters.characterCreation);
 
         updateForm(characters.savedCharacters[pseudo], characters.characterCreation);
 +
        saveButtonGreen(characters);
 +
        characters.unsavedChanges = false;
 +
      }
 +
    }
 +
  } else {
 +
   
 +
    var pseudo = target.parentElement.dataset.pseudo;
 +
   
 +
    if (target.tagName === "path") {
 +
      target = target.parentElement;
 +
    }
 +
   
 +
    switch (target.dataset.icon) {
 +
 +
      case 'duplicate':
 +
 +
        if (!characters.unsavedChanges) {
 +
          addNewCharacter(characters, characters.newCharacterTemplate, characters.charactersContainer, battle, pseudo);
 +
 +
        } else {
 +
          var result = confirm("Voulez-vous continuer ? Les dernières modifications ne seront pas sauvegardées.");
  
      } else {
+
          if (result) {
        var result = confirm("Voulez-vous continuer ? Les dernières modifications ne seront pas sauvegardées.");
+
            addNewCharacter(characters, characters.newCharacterTemplate, characters.charactersContainer, battle, pseudo);
       
+
            saveButtonGreen(characters);
        if (result) {
+
            characters.unsavedChanges = false;
          updateForm(characters.savedCharacters[pseudo], characters.characterCreation);
+
          }
          characters.unsavedChanges = false;
 
 
         }
 
         }
      }
+
        break;
      break;
 
     
 
    case 'duplicate':
 
     
 
      if (!characters.unsavedChanges) {
 
        addNewCharacter(characters, characters.newCharacterTemplate, characters.charactersContainer, battle, pseudo);
 
  
       } else {
+
       case 'download':
         var result = confirm("Voulez-vous continuer ? Les dernières modifications ne seront pas sauvegardées.");
+
         downloadCharacter(characters.savedCharacters[pseudo]);
 +
        break;
  
 +
      case 'delete':
 +
        var result = confirm("Voulez-vous vraiment supprimer définitivement le personnage " + pseudo + " ?");
 
         if (result) {
 
         if (result) {
           addNewCharacter(characters, characters.newCharacterTemplate, characters.charactersContainer, battle, pseudo);
+
           deleteCharacter(characters, pseudo, displayedPseudo, target.parentElement.parentElement, battle);
          characters.unsavedChanges = false;
 
 
         }
 
         }
      }
+
        break;
      break;
+
     }
     
 
     case 'download':
 
      downloadCharacter(characters.savedCharacters[pseudo]);
 
      break;
 
     
 
    case 'delete':
 
      var result = confirm("Voulez-vous vraiment supprimer définitivement le personnage " + pseudo + " ?");
 
      if (result) {
 
        deleteCharacter(characters.savedCharacters, pseudo, target.parentElement.parentElement, battle);
 
        hideElement(characters.characterCreation);
 
      }
 
      break;
 
 
   }
 
   }
 
}
 
}
Ligne 362 : Ligne 404 :
 
   var spanInput = newCharacterTemplate.querySelector("span.input");
 
   var spanInput = newCharacterTemplate.querySelector("span.input");
 
   var svgContainer = newCharacterTemplate.querySelector("div.svg-container");
 
   var svgContainer = newCharacterTemplate.querySelector("div.svg-container");
 
+
 
 +
  newCharacterTemplate.setAttribute("tabindex", "0");
 
   charactersContainer.appendChild(newCharacterTemplate);
 
   charactersContainer.appendChild(newCharacterTemplate);
 
    
 
    
Ligne 369 : Ligne 412 :
 
     svgContainer.setAttribute("data-pseudo", pseudo);
 
     svgContainer.setAttribute("data-pseudo", pseudo);
 
   }
 
   }
 
+
 
   svgContainer.addEventListener("click", function(event) {
+
   newCharacterTemplate.addEventListener("click", function(event) {
     handleClickOnSvg(event, characters, battle);
+
     var currentTarget = event.currentTarget;
 +
    var target = event.target;
 +
   
 +
    if (target.tagName === "path" || target.tagName === "svg") {
 +
      handleClickOnCharacter(target, characters, battle);
 +
    } else {
 +
      handleClickOnCharacter(currentTarget, characters, battle, true);
 +
    }
 
   });
 
   });
 
    
 
    
Ligne 379 : Ligne 429 :
  
 
function validPseudo(pseudo) {
 
function validPseudo(pseudo) {
   var newPseudo = pseudo.replace(/[^A-Za-z0-9]+/g, "")
+
 
 +
   var newPseudo = pseudo.replace(/[^A-Za-z0-9]+/g, "");
 +
 
 
   if (!newPseudo) {
 
   if (!newPseudo) {
 
     return "Pseudo"
 
     return "Pseudo"
 
   }
 
   }
 +
 
 
   return newPseudo;
 
   return newPseudo;
 
}
 
}
Ligne 473 : Ligne 526 :
 
       if (result) {
 
       if (result) {
 
         addNewCharacter(characters, characterTemplate, charactersContainer, battle);
 
         addNewCharacter(characters, characterTemplate, charactersContainer, battle);
 +
        saveButtonGreen(characters);
 
         characters.unsavedChanges = false;
 
         characters.unsavedChanges = false;
 
       }
 
       }
Ligne 483 : Ligne 537 :
 
    
 
    
 
   characters.characterCreation.addEventListener("change", function() {
 
   characters.characterCreation.addEventListener("change", function() {
 +
    saveButtonOrange(characters)
 
     characters.unsavedChanges = true;
 
     characters.unsavedChanges = true;
 
   })
 
   })
Ligne 519 : Ligne 574 :
 
     var option = document.createElement("option");
 
     var option = document.createElement("option");
 
     option.textContent = text;
 
     option.textContent = text;
 +
    option.value = text;
 
     return option;
 
     return option;
 
   }
 
   }
Ligne 713 : Ligne 769 :
 
     uploadCharacter: document.getElementById("upload-character"),
 
     uploadCharacter: document.getElementById("upload-character"),
 
     newCharacterTemplate: document.getElementById("new-character-template").children[0],
 
     newCharacterTemplate: document.getElementById("new-character-template").children[0],
     charactersContainer: document.getElementById("characters-container")
+
     charactersContainer: document.getElementById("characters-container"),
 +
    saveButton: document.getElementById("save-button"),
 +
    saveBar: document.getElementById("save-bar")
 
   }
 
   }
 
   var savedCharactersPseudo = getSavedCharactersPseudo();
 
   var savedCharactersPseudo = getSavedCharactersPseudo();

Version du 1 octobre 2023 à 18:36

var weaponData = {'Poings': [['warrior', 'ninja', 'sura', 'shamane', 'lycan'], [0, 0, 0, 0], []],'Épée': [['warrior', 'ninja', 'sura'], [15, 19, 13, 15], [0, 7, 14, 21, 28, 35, 42, 49, 56, 63]], 'Épée longue': [['warrior', 'ninja', 'sura'], [13, 15, 15, 19], [0, 7, 14, 21, 28, 35, 42, 49, 56, 63]], 'Lame courbe': [['warrior', 'ninja', 'sura'], [20, 24, 20, 24], [0, 7, 14, 21, 28, 35, 42, 49, 56, 63]], 'Canne Épée': [['warrior', 'ninja', 'sura'], [25, 35, 22, 26], [0, 7, 14, 21, 28, 35, 42, 49, 56, 63]], 'Épée large': [['warrior', 'ninja', 'sura'], [20, 28, 25, 35], [0, 7, 14, 21, 28, 35, 42, 49, 56, 63]], 'Épée en argent': [['warrior', 'ninja', 'sura'], [38, 52, 36, 46], [0, 6, 12, 18, 24, 32, 41, 51, 62, 74]], 'Épée aux orchidées': [['warrior', 'ninja', 'sura'], [36, 46, 38, 52], [0, 6, 12, 18, 24, 32, 41, 51, 62, 74]], 'Épée bâtarde': [['warrior', 'ninja', 'sura'], [52, 68, 48, 58], [0, 6, 12, 18, 24, 32, 41, 51, 62, 74]], 'Glaive barbare': [['warrior', 'ninja', 'sura'], [48, 58, 52, 68], [0, 6, 12, 18, 24, 32, 41, 51, 62, 74]], 'Épée sanglante': [['warrior', 'ninja', 'sura'], [69, 91, 65, 87], [0, 5, 10, 15, 20, 27, 35, 44, 54, 65]], 'Grande Épée': [['warrior', 'ninja', 'sura'], [65, 87, 69, 91], [0, 5, 10, 15, 20, 27, 35, 44, 54, 65]], 'Épée du magic. volant': [['warrior', 'ninja', 'sura'], [72, 108, 74, 100], [0, 5, 10, 15, 20, 27, 35, 44, 54, 65]], 'Épée de demi-lune': [['warrior', 'ninja', 'sura'], [74, 100, 72, 108], [0, 5, 10, 15, 20, 27, 35, 44, 54, 65]], 'Épée de bataille': [['warrior', 'ninja', 'sura'], [65, 87, 100, 140], [0, 8, 17, 27, 38, 50, 63, 77, 102, 137]], 'Lame de croc fantôme': [['sura'], [90, 110, 77, 105], [0, 8, 17, 27, 38, 50, 63, 77, 102, 137]], 'Épée de nymphe': [['warrior', 'ninja', 'sura'], [69, 81, 102, 138], [0, 6, 13, 21, 30, 40, 51, 63, 76, 90]], 'Épée de piqûre': [['warrior', 'ninja', 'sura'], [69, 81, 102, 138], [0, 6, 13, 21, 30, 40, 51, 63, 76, 90]], 'Épée empoisonnée': [['warrior', 'ninja', 'sura'], [0, 0, 100, 140], [0, 8, 17, 27, 38, 50, 63, 77, 102, 137]], 'Épée du lion': [['sura'], [77, 105, 90, 110], [0, 6, 13, 21, 30, 40, 51, 63, 76, 90]], 'Lame tranchante': [['sura'], [68, 90, 92, 135], [100, 111, 170, 170, 170, 180, 190, 190, 200, 210]], "Épée d'exorcisme": [['sura'], [74, 98, 98, 142], [0, 6, 13, 21, 30, 40, 51, 63, 76, 90]], 'Lame démoniaque': [['sura'], [90, 110, 77, 105], [0, 6, 13, 21, 30, 40, 51, 63, 76, 90]], 'Épée de Triton': [['warrior', 'ninja', 'sura'], [18, 40, 100, 140], [137, 138, 140, 144, 149, 155, 162, 170, 180, 190]], 'Épée sacrée': [['sura'], [90, 110, 5, 70], [140, 132, 142, 150, 150, 160, 170, 180, 190, 200]], 'Épée de la lune pleine': [['warrior', 'ninja', 'sura'], [62, 88, 57, 73], [0, 6, 11, 17, 22, 30, 38, 48, 58, 70]], 'Lame du zodiaque': [['sura'], [149, 211, 116, 164], [0, 10, 14, 22, 33, 50, 74, 111, 167, 250]], 'Épée du zodiaque': [['warrior', 'ninja', 'sura'], [0, 0, 149, 211], [0, 8, 11, 17, 26, 40, 59, 88, 133, 200]], 'Épée du dragon obscur': [['warrior', 'ninja', 'sura'], [0, 0, 135, 214], [0, 13, 17, 24, 34, 45, 70, 112, 137, 209, 224, 239, 254, 269, 284, 314]], 'Stylet du dragon obs.': [['sura'], [136, 217, 111, 162], [0, 15, 20, 33, 42, 64, 92, 111, 169, 234, 270, 285, 300, 315, 340, 370]], 'Épée serpent': [['warrior', 'ninja', 'sura'], [0, 0, 175, 193], [0, 15, 25, 35, 46, 60, 92, 147, 179, 273, 293, 313, 335, 355, 375, 413]], 'Lame serpent': [['sura'], [177, 300, 144, 230], [0, 22, 28, 45, 57, 86, 122, 147, 222, 306, 353, 373, 393, 412, 444, 485]], 'Épée runique': [['warrior', 'ninja', 'sura'], [119, 161, 153, 207], [0, 10, 14, 22, 33, 50, 74, 111, 167, 250]], 'Lame dent de dragon': [['sura'], [149, 211, 116, 164], [0, 10, 14, 22, 33, 50, 74, 111, 167, 250]], 'Épée de kyanite': [['sura'], [149, 211, 87, 137], [140, 160, 170, 170, 180, 190, 210, 230, 240, 250]], 'Dague': [['ninja'], [0, 0, 8, 11], [0, 4, 8, 12, 16, 20, 24, 28, 32, 36]], 'Dague cobra': [['ninja'], [0, 0, 13, 15], [0, 4, 8, 12, 16, 20, 24, 28, 32, 36]], 'Dagues ciseaux': [['ninja'], [0, 0, 15, 19], [0, 4, 8, 12, 16, 20, 24, 28, 32, 36]], 'Couteau porte-bonheur': [['ninja'], [0, 0, 30, 36], [0, 3, 6, 9, 12, 17, 23, 30, 38, 47]], 'Cout. Morsure de Chat': [['ninja'], [0, 0, 33, 37], [0, 3, 6, 9, 12, 17, 23, 30, 38, 47]], 'Poig. Visage de Diable': [['ninja'], [0, 0, 36, 40], [0, 3, 6, 9, 12, 17, 23, 30, 38, 47]], 'Dague du poing diab.': [['ninja'], [0, 0, 47, 51], [0, 2, 4, 6, 8, 12, 17, 23, 30, 38]], 'Dague sanglante': [['ninja'], [0, 0, 48, 56], [0, 2, 4, 6, 8, 12, 17, 23, 30, 38]], 'Couteau de Nervure': [['ninja'], [0, 0, 49, 59], [0, 2, 4, 6, 8, 12, 17, 23, 30, 38]], 'Chakram': [['ninja'], [0, 0, 53, 65], [0, 2, 4, 6, 8, 12, 17, 23, 30, 38]], 'Couteau du dragon': [['ninja'], [0, 0, 74, 86], [0, 8, 17, 27, 38, 50, 63, 77, 102, 137]], "Couteau d'éclairs": [['ninja'], [0, 0, 74, 86], [0, 6, 13, 21, 30, 40, 51, 63, 76, 90]], 'Couteau siamois': [['ninja'], [0, 0, 74, 86], [0, 6, 13, 21, 30, 40, 51, 63, 76, 90]], 'Chakram aile du diable': [['ninja'], [0, 0, 83, 92], [0, 8, 17, 27, 38, 50, 63, 77, 101, 137]], 'Dague de feuille noire': [['ninja'], [0, 0, 40, 44], [0, 3, 5, 8, 10, 15, 20, 27, 34, 43]], 'Dague du zodiaque': [['ninja'], [0, 0, 116, 136], [0, 12, 17, 27, 41, 63, 93, 139, 210, 315]], 'Dague du dragon obsc.': [['ninja'], [0, 0, 112, 139], [0, 16, 21, 31, 45, 67, 97, 143, 204, 305, 340, 355, 370, 385, 400, 430]], 'Dague serpent': [['ninja'], [0, 0, 145, 198], [0, 24, 32, 45, 62, 89, 129, 188, 270, 400, 445, 465, 485, 505, 525, 562]], 'Lame des cinq éléments': [['ninja'], [0, 0, 116, 136], [0, 12, 17, 27, 41, 63, 93, 139, 210, 315]], 'Dague de kyanite': [['ninja'], [0, 0, 87, 109], [140, 160, 170, 170, 180, 190, 210, 230, 240, 250]], 'Arc court': [['ninja'], [0, 0, 7, 29], [0, 8, 16, 24, 32, 40, 48, 56, 64, 72]], 'Arc long': [['ninja'], [0, 0, 15, 51], [0, 8, 16, 24, 32, 40, 48, 56, 64, 72]], 'Arc composite': [['ninja'], [0, 0, 19, 57], [0, 8, 16, 24, 32, 40, 48, 56, 64, 72]], 'Arc de bataille': [['ninja'], [0, 0, 26, 70], [0, 8, 16, 24, 32, 40, 48, 56, 64, 72]], 'Arc long de cavalerie': [['ninja'], [0, 0, 40, 88], [0, 8, 16, 24, 32, 40, 48, 56, 64, 72]], 'Arc de bat. cavalerie': [['ninja'], [0, 0, 50, 118], [0, 7, 14, 21, 28, 37, 47, 58, 70, 83]], 'Arc cuivré': [['ninja'], [0, 0, 62, 128], [0, 7, 14, 21, 28, 37, 47, 58, 70, 83]], 'Arc de ruine noire': [['ninja'], [0, 0, 64, 150], [0, 7, 14, 21, 28, 37, 47, 58, 70, 83]], "Arc d'oeil rouge": [['ninja'], [0, 0, 65, 194], [0, 7, 14, 21, 28, 37, 47, 58, 70, 83]], 'Arc de feuilles épin.': [['ninja'], [0, 0, 106, 206], [0, 6, 12, 18, 24, 32, 41, 51, 62, 74]], 'Arc cornes de taureau': [['ninja'], [0, 0, 116, 216], [0, 6, 12, 18, 24, 32, 41, 51, 62, 74]], 'Arc de licorne': [['ninja'], [0, 0, 139, 213], [0, 6, 12, 18, 24, 32, 41, 51, 62, 74]], "Arc d'aile géante": [['ninja'], [0, 0, 135, 251], [0, 6, 12, 18, 24, 32, 41, 51, 62, 74]], "Arc d'abricot divin": [['ninja'], [0, 0, 190, 290], [0, 6, 13, 21, 30, 40, 51, 63, 76, 90]], 'Arc géant drag. jaune': [['ninja'], [0, 0, 187, 293], [0, 8, 17, 27, 38, 50, 63, 77, 102, 137]], 'Arc à cornes': [['ninja'], [0, 0, 85, 178], [0, 7, 13, 20, 26, 35, 44, 55, 66, 79]], 'Arc diabolique géant': [['ninja'], [0, 0, 187, 293], [138, 143, 149, 156, 164, 173, 183, 194, 206, 223]], "Arc de corbeau d'acier": [['ninja'], [0, 0, 190, 290], [0, 6, 13, 21, 30, 40, 51, 63, 76, 90]], 'Arc du dragon bleu': [['ninja'], [0, 0, 187, 293], [0, 6, 13, 21, 30, 40, 51, 63, 76, 90]], 'Arc du zodiaque': [['ninja'], [0, 0, 237, 436], [0, 10, 14, 22, 33, 50, 74, 111, 167, 250]], 'Arc du dragon obscur': [['ninja'], [0, 0, 233, 439], [0, 13, 17, 25, 36, 53, 77, 114, 160, 243, 268, 283, 298, 313, 328, 358]], 'Arc serpent': [['ninja'], [0, 0, 303, 594], [0, 19, 25, 35, 49, 71, 103, 152, 211, 318, 351, 370, 390, 410, 430, 468]], 'Arc du phénix': [['ninja'], [0, 0, 237, 436], [0, 10, 14, 22, 33, 50, 74, 111, 167, 250]], 'Arc de kyanite': [['ninja'], [0, 0, 208, 409], [140, 160, 170, 170, 180, 190, 210, 230, 240, 250]], 'Glaive': [['warrior'], [0, 0, 14, 22], [0, 8, 16, 24, 32, 40, 48, 56, 64, 72]], 'Lance': [['warrior'], [0, 0, 23, 33], [0, 8, 16, 24, 32, 40, 48, 56, 64, 72]], 'Lame guillotine': [['warrior'], [0, 0, 24, 42], [0, 8, 16, 24, 32, 40, 48, 56, 64, 72]], 'Lance araignée': [['warrior'], [0, 0, 30, 44], [0, 8, 16, 24, 32, 40, 48, 56, 64, 72]], 'Gisarme': [['warrior'], [0, 0, 34, 52], [0, 8, 16, 24, 32, 40, 48, 56, 64, 72]], 'Faux de guerre': [['warrior'], [0, 0, 52, 86], [0, 6, 12, 18, 24, 32, 41, 51, 62, 74]], 'Fourche Militaire': [['warrior'], [0, 0, 58, 88], [0, 6, 12, 18, 24, 32, 41, 51, 62, 74]], 'Hallebarde': [['warrior'], [0, 0, 60, 96], [0, 6, 12, 18, 24, 32, 41, 51, 62, 74]], 'Grand hache': [['warrior'], [0, 0, 69, 103], [0, 6, 12, 18, 24, 32, 41, 51, 62, 74]], 'Pique de glace': [['warrior'], [0, 0, 84, 122], [0, 5, 10, 15, 20, 27, 35, 44, 54, 65]], 'Épée des douze Esprits': [['warrior'], [0, 0, 85, 139], [0, 5, 10, 15, 20, 27, 35, 44, 54, 65]], 'Lame du salut': [['warrior'], [0, 0, 86, 154], [0, 5, 10, 15, 20, 27, 35, 44, 54, 65]], 'Tueuse de lion': [['warrior'], [0, 0, 102, 156], [0, 5, 10, 15, 20, 27, 35, 44, 54, 65]], 'Partisan': [['warrior'], [0, 0, 136, 184], [0, 8, 17, 27, 38, 50, 63, 77, 102, 137]], 'Lame électromagnétique': [['warrior'], [0, 0, 126, 194], [0, 6, 13, 21, 30, 40, 51, 63, 76, 90]], "Lame voleuse d'âme": [['warrior'], [0, 0, 126, 194], [0, 6, 13, 27, 38, 50, 63, 77, 102, 137]], 'Épée de rancune': [['warrior'], [0, 0, 136, 184], [0, 6, 13, 21, 30, 40, 51, 63, 76, 90]], 'Lame solaire': [['warrior'], [0, 0, 230, 311], [0, 7, 10, 16, 24, 37, 55, 83, 125, 187]], 'Lame de fer rouge': [['warrior'], [0, 0, 72, 109], [0, 6, 11, 17, 22, 30, 38, 48, 58, 70]], 'Glaive du zodiaque': [['warrior'], [0, 0, 230, 311], [0, 7, 10, 16, 24, 37, 55, 83, 125, 187]], 'Lame du dragon obscur': [['warrior'], [0, 0, 226, 314], [0, 10, 13, 19, 27, 40, 58, 86, 118, 180, 210, 225, 240, 255, 270, 300]], 'Grande épée serpent': [['warrior'], [0, 0, 293, 429], [0, 13, 23, 26, 43, 55, 85, 115, 155, 220, 280, 300, 320, 340, 365, 405]], 'Lame de kyanite': [['warrior'], [0, 0, 201, 284], [140, 160, 170, 170, 180, 190, 210, 230, 240, 250]], 'Amija': [['ninja'], [0, 0, 12, 14], [0, 4, 8, 12, 16, 20, 24, 28, 32, 36]], 'Neuf Lames': [['ninja'], [0, 0, 14, 16], [0, 4, 8, 12, 16, 20, 24, 28, 32, 36]], 'Couteau court': [['ninja'], [0, 0, 28, 32], [0, 3, 6, 9, 12, 17, 23, 30, 38, 47]], 'Poig. Jumeau Lunaire': [['ninja'], [0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], 'Couteau sans âme': [['ninja'], [0, 0, 74, 84], [151, 153, 155, 158, 161, 165, 171, 179, 189, 201]], 'Gong de cuivre': [['shaman'], [10, 18, 13, 15], [0, 7, 14, 21, 28, 35, 42, 49, 56, 63]], "Gong d'argent": [['shaman'], [4, 30, 20, 26], [0, 7, 14, 21, 28, 35, 42, 49, 56, 63]], "Gong d'or": [['shaman'], [19, 27, 25, 35], [0, 7, 14, 21, 28, 35, 42, 49, 56, 63]], 'Gong de jade': [['shaman'], [30, 38, 29, 39], [0, 6, 12, 18, 24, 32, 41, 51, 62, 74]], 'Gong de fontaine': [['shaman'], [26, 52, 41, 51], [0, 6, 12, 18, 24, 32, 41, 51, 62, 74]], 'Gong abricot': [['shaman'], [42, 48, 42, 60], [0, 6, 12, 18, 24, 32, 41, 51, 62, 74]], 'Gong magique': [['shaman'], [43, 67, 59, 89], [0, 5, 10, 15, 20, 27, 35, 44, 54, 65]], "Gong d'insecte d'or": [['shaman'], [47, 77, 68, 90], [0, 5, 10, 15, 20, 27, 35, 44, 54, 65]], "Gong d'insecte d'acier": [['shaman'], [65, 75, 76, 104], [0, 5, 10, 15, 20, 27, 35, 44, 54, 65]], 'Gong oiseau tonnerre': [['shaman'], [47, 77, 91, 129], [0, 8, 17, 27, 38, 50, 63, 77, 102, 137]], 'Gong terre et ciel': [['shaman'], [65, 75, 72, 108], [0, 6, 13, 21, 30, 40, 51, 63, 76, 90]], 'Gong antique': [['shaman'], [35, 60, 50, 70], [0, 6, 11, 17, 22, 30, 38, 48, 58, 70]], 'Gong de bambou': [['shaman'], [70, 80, 72, 108], [0, 8, 17, 27, 38, 50, 63, 77, 102, 137]], 'Gong sinistre évent.': [['shaman'], [47, 77, 91, 129], [0, 8, 17, 27, 38, 50, 63, 77, 102, 137]], 'Gong du dragon': [['shaman'], [65, 75, 72, 108], [0, 6, 13, 21, 30, 40, 51, 63, 76, 90]], "Gong de l'hibiscus": [['shaman'], [47, 77, 91, 129], [0, 8, 17, 27, 38, 50, 63, 77, 102, 137]], 'Cloche du zodiaque': [['shaman'], [84, 116, 166, 194], [0, 9, 12, 19, 29, 45, 66, 99, 150, 225]], 'Gong du dragon obscur': [['shaman'], [81, 120, 162, 197], [0, 9, 12, 19, 29, 45, 66, 99, 130, 219, 242, 255, 269, 283, 298, 335]], 'Cloche serpent': [['shaman'], [105, 172, 211, 273], [0, 15, 19, 28, 39, 61, 89, 132, 172, 288, 318, 335, 353, 373, 390, 438]], 'Gong Gueule de Dragon': [['shaman'], [60, 70, 70, 100], [100, 110, 110, 120, 130, 140, 150, 160, 170, 180]], "Cloche d'esprit dragon": [['shaman'], [84, 116, 166, 194], [0, 9, 12, 19, 29, 45, 66, 99, 150, 225]], 'Gong de kyanite': [['shaman'], [84, 116, 137, 167], [140, 160, 170, 170, 180, 190, 210, 230, 240, 250]], "Flambeau d'acier": [['lycan'], [15, 19, 13, 15], [0, 7, 14, 21, 28, 35, 42, 49, 56, 63]], 'Lance de phoenix': [['lycan'], [0, 0, 40, 44], [0, 3, 5, 8, 10, 15, 20, 27, 34, 43]], 'Griffe de fer': [['lycan'], [0, 0, 57, 73], [0, 3, 5, 8, 10, 15, 20, 27, 34, 43]], "Griffe d'acier": [['lycan'], [0, 0, 69, 91], [0, 5, 10, 15, 20, 27, 35, 44, 54, 65]], 'Griffe prédatrice': [['lycan'], [0, 0, 72, 108], [0, 5, 10, 15, 20, 27, 35, 44, 54, 65]], 'Griffe de scarabée': [['lycan'], [0, 0, 74, 100], [0, 5, 10, 15, 20, 27, 35, 44, 54, 65]], 'Griffe de faucon': [['lycan'], [0, 0, 80, 112], [0, 8, 17, 27, 38, 50, 63, 77, 102, 137]], 'Griffe épineuse': [['lycan'], [0, 0, 81, 110], [0, 6, 13, 21, 30, 40, 51, 63, 76, 90]], 'Croc de loup vert': [['lycan'], [0, 0, 92, 145], [100, 111, 170, 170, 170, 180, 190, 190, 200, 210]], 'Seigneur des dragons': [['lycan'], [0, 0, 122, 165], [0, 10, 14, 22, 33, 50, 74, 111, 167, 250]], 'Griffe du zodiaque': [['lycan'], [0, 0, 122, 165], [0, 10, 14, 22, 33, 50, 74, 111, 167, 250]], 'Griffe du dragon obs.': [['lycan'], [0, 0, 115, 172], [0, 10, 14, 22, 33, 50, 74, 111, 157, 240, 263, 277, 291, 305, 320, 350]], 'Griffe de serpent': [['lycan'], [0, 0, 150, 242], [0, 15, 20, 32, 45, 68, 98, 146, 206, 313, 344, 362, 380, 399, 418, 457]], 'Griffe de kyanite': [['lycan'], [0, 0, 93, 138], [140, 160, 170, 170, 180, 190, 210, 230, 240, 250]], 'Éventail': [['shaman'], [13, 15, 11, 15], [0, 7, 14, 21, 28, 35, 42, 49, 56, 63]], 'Éventail de fer': [['shaman'], [14, 22, 11, 17], [0, 7, 14, 21, 28, 35, 42, 49, 56, 63]], 'Éventail du tigre noir': [['shaman'], [18, 28, 13, 19], [0, 7, 14, 21, 28, 35, 42, 49, 56, 63]], 'Éventail aile de grue': [['shaman'], [24, 32, 17, 21], [0, 7, 14, 21, 28, 35, 42, 49, 56, 63]], 'Éventail du paon': [['shaman'], [29, 33, 18, 24], [0, 7, 14, 21, 28, 35, 42, 49, 56, 63]], 'Éventail aquatique': [['shaman'], [29, 39, 27, 41], [0, 6, 12, 18, 24, 32, 41, 51, 62, 74]], 'Éventail de pierre': [['shaman'], [33, 47, 30, 46], [0, 6, 12, 18, 24, 32, 41, 51, 62, 74]], "Éventail de l'océan": [['shaman'], [30, 62, 35, 45], [0, 6, 12, 18, 24, 32, 41, 51, 62, 74]], 'Éventail de piqûre': [['shaman'], [42, 60, 37, 53], [0, 6, 12, 18, 24, 32, 41, 51, 62, 74]], 'Éventail du phoenix': [['shaman'], [59, 89, 50, 64], [0, 5, 10, 15, 20, 27, 35, 44, 54, 65]], 'Éventail triple': [['shaman'], [68, 90, 49, 73], [0, 5, 10, 15, 20, 27, 35, 44, 54, 65]], 'Éventails de cils': [['shaman'], [70, 100, 52, 78], [0, 5, 10, 15, 20, 27, 35, 44, 54, 65]], 'Éventail soleil noir': [['shaman'], [83, 97, 55, 83], [0, 5, 10, 15, 20, 27, 35, 44, 54, 65]], 'Event. oiseau céleste': [['shaman'], [83, 97, 64, 96], [0, 8, 17, 27, 38, 50, 63, 77, 102, 137]], 'Éventail du salut': [['shaman'], [95, 115, 69, 91], [0, 6, 13, 21, 30, 40, 51, 63, 76, 90]], "Éventail d'extase": [['shaman'], [95, 115, 69, 91], [0, 6, 13, 21, 30, 40, 51, 63, 76, 90]], "Éventail vent d'autom.": [['shaman'], [45, 76, 43, 55], [0, 6, 11, 17, 22, 30, 38, 48, 58, 70]], 'Éventail démoniaque': [['shaman'], [90, 115, 65, 85], [100, 100, 100, 100, 150, 150, 150, 150, 200, 200]], 'Éventail du zodiaque': [['shaman'], [160, 240, 115, 173], [0, 8, 11, 17, 26, 40, 59, 88, 133, 200]], 'Évent. dragon obscur': [['shaman'], [157, 243, 119, 176], [0, 8, 11, 17, 26, 40, 59, 88, 123, 192, 218, 231, 245, 259, 274, 304]], 'Éventail serpent': [['shaman'], [204, 337, 155, 244], [0, 13, 17, 25, 35, 55, 80, 117, 163, 256, 290, 306, 325, 343, 363, 402]], 'Éventail de kyanite': [['shaman'], [160, 240, 86, 146], [140, 160, 170, 170, 180, 190, 210, 230, 240, 250]]}

//level, str, dex, ht, int, mindamage, maxdamage, def, ResistFist	ResistSword	ResistTwoHanded	ResistDagger	ResistBell	ResistFan	ResistBow	ResistClaw	ResistFire	ResistElect	ResistMagic	ResistWind AttElec	AttFire	AttIce	AttWind	AttEarth	AttDark	ResistDark	ResistIce	ResistEarth	DamMultiply

var monsterData = {'Chien errant': [1, 3, 6, 5, 2, 20, 24, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.0]}


function showElement(element) {
  element.classList.remove("tabber-noactive");
}


function hideElement(element) {
  element.classList.add("tabber-noactive");
}


function addWeapon(weaponChoice) {
  for (var weapon in weaponData) {
    var option = document.createElement("option");
    option.textContent = weapon;
    option.value = weapon;
    if (weaponData[weapon][0].indexOf("warrior") === -1) {
      hideElement(option);
    }
    weaponChoice.appendChild(option);
  }
}


function filterClass(selectedRace, classChoice, labelClassChoice) {
  
  if (selectedRace == 'lycan') {
      
    hideElement(classChoice);
    hideElement(labelClassChoice);

  } else {

    var selectValueIsChanged = false;

    showElement(classChoice);
    showElement(labelClassChoice);

    for (var option of classChoice.options) {
      if (option.getAttribute('data-race') === selectedRace) {
        if (!selectValueIsChanged) {
          classChoice.value = option.value;
          selectValueIsChanged = true;
        }
        showElement(option);
      } else {
        hideElement(option);
      }
    }
  }
}


function filterWeapon(selectedRace, weaponChoice) {
  
  var selectValueIsChanged = false;
  
  for (var option of weaponChoice.options) {
    if (weaponData[option.value][0].indexOf(selectedRace) !== -1) {
      if (!selectValueIsChanged) {
        weaponChoice.value = option.value;
        selectValueIsChanged = true;
      }
      showElement(option);
    } else {
      hideElement(option);
    }
  }
}


function filterUpgrade(weaponUpgrade, labelWeaponUpgrade, weaponName, randomAttackValue) {

  if (weaponName.indexOf('serpent') !== -1) {
    showElement(randomAttackValue);
  } else {
    hideElement(randomAttackValue);
  }
    
  var upgradeNumber = weaponData[weaponName][2].length;
  
  if (!upgradeNumber) {
    
    hideElement(weaponUpgrade);
    hideElement(labelWeaponUpgrade);
    
  } else {
    
    showElement(weaponUpgrade);
    showElement(labelWeaponUpgrade);
    weaponUpgrade.innerHTML = "";

    for (var upgrade = 0; upgrade < upgradeNumber; upgrade++) {
   
      var option = document.createElement("option");
      option.value = upgrade;
      option.textContent = "+" + upgrade;
      weaponUpgrade.appendChild(option);
    }
    option.selected = true;
  }
}


function filterForm() {
  
  var raceChoice = document.getElementById("race-choice");
  var classChoice = document.getElementById("class-choice");
  var labelClassChoice = document.getElementById("class-choice-label");
  var weaponChoice = document.getElementById("weapon-choice");
  var weaponUpgrade = document.getElementById("upgrade-choice");
  var labelWeaponUpgrade = document.getElementById("upgrade-choice-label");
  var randomAttackValue = document.getElementById("random-attack-value");
  
  addWeapon(weaponChoice);
  
  raceChoice.addEventListener("change", function(event) {
    
    var selectedRace = event.target.value
    
    filterClass(selectedRace, classChoice, labelClassChoice);
    filterWeapon(selectedRace, weaponChoice);
    
  });
  
  weaponChoice.addEventListener("change", function(event) {
    
    var weaponName = event.target.value;
    
    filterUpgrade(weaponUpgrade, labelWeaponUpgrade, weaponName, randomAttackValue);
    
  });
}


function getCharacter(pseudo) {
  return localStorage.getItem(pseudo);
}


function getSavedCharactersPseudo() {
  var savedCharactersPseudo = localStorage.getItem("savedCharactersPseudo");

  if (savedCharactersPseudo) {
    return JSON.parse(savedCharactersPseudo);
  }
  return [];
}


function parseCharacter(characterString) {
  return JSON.parse(characterString);
}


function addUniquePseudo(characterDataObject, savedCharactersPseudo) {

  var characterPseudo = characterDataObject.name;
  var originalPseudo = characterPseudo;
  var count = 0;
  
  while (savedCharactersPseudo.indexOf(characterPseudo) !== -1) {
    characterPseudo = originalPseudo + count;
    count++;
  }
  
  characterDataObject.name = characterPseudo;
  return [characterDataObject, characterPseudo]
}


function convertToNumber(value) {
  var valueNumber = Number(value);
  return isNaN(valueNumber) ? value : valueNumber;
}


function updateSavedCharactersPseudo(charactersPseudo) {
  localStorage.setItem("savedCharactersPseudo", JSON.stringify(charactersPseudo));
}


function saveCharacter(savedCharacters, characterCreation, battle, newCharacter, characterDataObject) {
  
  if (!characterDataObject) {
    var characterData = new FormData(characterCreation);
    var characterDataObject = {};

    characterData.forEach(function(value, key) {
      characterDataObject[key] = convertToNumber(value);
    });
  }

  savedCharacters[characterDataObject.name] = characterDataObject;
  localStorage.setItem(characterDataObject.name, JSON.stringify(characterDataObject));
  
  if (newCharacter) {
    updateSavedCharactersPseudo(Object.keys(savedCharacters));
    addBattleChoice(battle, characterDataObject.name);
  }
}


function saveButtonGreen(characters, animation) {
  if (animation) {
    characters.saveBar.style.animation = characters.saveButton.dataset.animation;
  } else {
    characters.saveBar.style.animation = "";
    characters.saveBar.style.backgroundColor = "lightgreen";
  }
}


function saveButtonOrange(characters) {
  characters.saveBar.style.animation = "";
  characters.saveBar.style.backgroundColor = "#ffdd40";
}


function characterCreationListener(characters, battle) {

  characters.characterCreation.addEventListener("submit", function(event) {
    event.preventDefault();

    if (characters.unsavedChanges) {
      saveCharacter(characters.savedCharacters, characters.characterCreation, battle);
      saveButtonGreen(characters, true);
      characters.unsavedChanges = false;
    }
  });
}


function downloadCharacter(character) {
  
  var content = JSON.stringify(character);
  var link = document.createElement("a");
  var blob = new Blob([content], {type: "text/plain"});
  var blobURL = URL.createObjectURL(blob);

  link.href = blobURL;
  link.download = character.name + ".txt";
  link.click();
  URL.revokeObjectURL(blobURL);
}


function uploadCharacter(characters, characterTemplate, charactersContainer, battle) {
  
  var fileInput = document.createElement("input");
  
  fileInput.type = "file";
  fileInput.accept = ".txt";
  fileInput.multiple = true;
  fileInput.click();
  
  fileInput.addEventListener("change", function(event) {
    var selectedFiles = event.target.files;
    var selectFilesLength = selectedFiles.length;
    
    hideElement(characters.characterCreation);

    for (var fileIndex = 0; fileIndex < selectFilesLength; fileIndex++) {
      var selectedFile = selectedFiles[fileIndex];
      
      if (selectedFile.type === "text/plain") {
        var reader = new FileReader();
        reader.onload = function(e) {
          var fileContent = e.target.result;
          try {
            var characterDataObject = JSON.parse(fileContent);
            var characterPseudo = characterDataObject.name;
            
            if (characterPseudo) {
              characterPseudo = validPseudo(characterPseudo);
              [characterDataObject, characterPseudo] = addUniquePseudo(characterDataObject, Object.keys(characters.savedCharacters));
              handleNewCharacter(characters, characterTemplate, charactersContainer, battle, characterPseudo);
              
              if (selectFilesLength === 1) {
                showElement(characters.characterCreation);
                updateForm(characterDataObject, characters.characterCreation);
              }

              saveCharacter(characters.savedCharacters, characters.characterCreation, battle, true, characterDataObject);
            }
          } catch (error) {
            // pass
          }
        };
        reader.readAsText(selectedFile);
      }
    }
});
}


function deleteCharacter(characters, pseudo, displayedPseudo, element, battle) {
  
  delete characters.savedCharacters[pseudo];
  
  var charactersPseudo = Object.keys(characters.savedCharacters);
  
  element.remove();
  
  updateSavedCharactersPseudo(charactersPseudo);
  removeBattleChoice(battle, pseudo);
  
  if (!charactersPseudo.length || characters.characterCreation.name.value === pseudo) {
    saveButtonGreen(characters);
    characters.unsavedChanges = false;
    hideElement(characters.characterCreation);
  }
}



function updateForm(formData, characterCreation) {
  
  characterCreation.reset();
  
  for (var [name, value] of Object.entries(formData)) {
    var formElement = characterCreation[name];
    if (formElement) {
      formElement.value = value;
    }
  }
}


function handleClickOnCharacter(target, characters, battle, edition) {
  
  var displayedPseudo = characters.characterCreation.name.value;
  
  if (edition) {
    
    var pseudo = target.querySelector("span.input").textContent;
    
    showElement(characters.characterCreation);

    if (!characters.unsavedChanges) {
      updateForm(characters.savedCharacters[pseudo], characters.characterCreation);

    } else if (displayedPseudo === pseudo) {
      // pass

    } else {
      var result = confirm("Voulez-vous continuer ? Les dernières modifications ne seront pas sauvegardées.");

      if (result) {
        updateForm(characters.savedCharacters[pseudo], characters.characterCreation);
        saveButtonGreen(characters);
        characters.unsavedChanges = false;
      }
    }
  } else {
    
    var pseudo = target.parentElement.dataset.pseudo;
    
    if (target.tagName === "path") {
      target = target.parentElement;
    }
    
    switch (target.dataset.icon) {

      case 'duplicate':

        if (!characters.unsavedChanges) {
          addNewCharacter(characters, characters.newCharacterTemplate, characters.charactersContainer, battle, pseudo);

        } else {
          var result = confirm("Voulez-vous continuer ? Les dernières modifications ne seront pas sauvegardées.");

          if (result) {
            addNewCharacter(characters, characters.newCharacterTemplate, characters.charactersContainer, battle, pseudo);
            saveButtonGreen(characters);
            characters.unsavedChanges = false;
          }
        }
        break;

      case 'download':
        downloadCharacter(characters.savedCharacters[pseudo]);
        break;

      case 'delete':
        var result = confirm("Voulez-vous vraiment supprimer définitivement le personnage " + pseudo + " ?");
        if (result) {
          deleteCharacter(characters, pseudo, displayedPseudo, target.parentElement.parentElement, battle);
        }
        break;
    }
  }
}


function handleNewCharacter(characters, characterTemplate, charactersContainer, battle, pseudo) {
  var newCharacterTemplate = characterTemplate.cloneNode(true);
  var spanInput = newCharacterTemplate.querySelector("span.input");
  var svgContainer = newCharacterTemplate.querySelector("div.svg-container");
  
  newCharacterTemplate.setAttribute("tabindex", "0");
  charactersContainer.appendChild(newCharacterTemplate);
  
  if (pseudo) {
    spanInput.textContent = pseudo;
    svgContainer.setAttribute("data-pseudo", pseudo);
  }
  
  newCharacterTemplate.addEventListener("click", function(event) {
    var currentTarget = event.currentTarget;
    var target = event.target;
    
    if (target.tagName === "path" || target.tagName === "svg") {
      handleClickOnCharacter(target, characters, battle);
    } else {
      handleClickOnCharacter(currentTarget, characters, battle, true);
    }
  });
  
  return [spanInput, svgContainer];
}


function validPseudo(pseudo) {
  
  var newPseudo = pseudo.replace(/[^A-Za-z0-9]+/g, "");
  
  if (!newPseudo) {
    return "Pseudo"
  }
  
  return newPseudo;
}


function addNewCharacter(characters, characterTemplate, charactersContainer, battle, pseudoToDuplicate) {

  function editAndSetCharacterPseudoInput(spanInput, svgContainer) {
  
    var selection = window.getSelection();
    var range = document.createRange();
    
    if (pseudoToDuplicate) {
      spanInput.textContent = pseudoToDuplicate;
    }
    
    spanInput.contentEditable = true;
    spanInput.focus();
    range.selectNodeContents(spanInput);
    selection.removeAllRanges();
    selection.addRange(range);
    
    function pseudoValidation() {
      
      var characterPseudo = validPseudo(spanInput.textContent);
      var characterDataObject = {name: characterPseudo};
      
      if (pseudoToDuplicate) {
        characterDataObject = characters.savedCharacters[pseudoToDuplicate];
        characterDataObject.name = characterPseudo;
      }
      
      [characterDataObject, characterPseudo] = addUniquePseudo(characterDataObject, Object.keys(characters.savedCharacters));
      
      svgContainer.setAttribute("data-pseudo", characterPseudo);
      selection.removeAllRanges();
      spanInput.contentEditable = false;
      spanInput.textContent = characterPseudo;

      showElement(characters.characterCreation);
      updateForm(characterDataObject, characters.characterCreation);
      saveCharacter(characters.savedCharacters, characters.characterCreation, battle, true);
    }

    function handleBlur() {
      spanInput.removeEventListener("blur", handleBlur);
      pseudoValidation();
    }
    
    function handleKeyDown(event) {

      if (event.key === "Enter") {
        
        event.preventDefault();
        
        spanInput.removeEventListener("keydown", handleKeyDown);
        spanInput.removeEventListener("blur", handleBlur);
        
        pseudoValidation();
      }
    }

    spanInput.addEventListener("keydown", handleKeyDown);
    spanInput.addEventListener("blur", handleBlur);
  }
  
  hideElement(characters.characterCreation);
  var [spanInput, svgContainer] = handleNewCharacter(characters, characterTemplate, charactersContainer, battle);

  editAndSetCharacterPseudoInput(spanInput, svgContainer);
}


function characterManagement(characters, battle) {
  
  var characterTemplate = characters.newCharacterTemplate;
  var charactersContainer = characters.charactersContainer;
  
  Object.keys(characters.savedCharacters).forEach(function(pseudo) {
    handleNewCharacter(characters, characterTemplate, charactersContainer, battle, pseudo);
  });

  characters.addNewCharacterButton.addEventListener("click", function(event) {
    if (!characters.unsavedChanges) {
      addNewCharacter(characters, characterTemplate, charactersContainer, battle);
      
    } else {
      var result = confirm("Voulez-vous continuer ? Les dernières modifications ne seront pas sauvegardées.");
      
      if (result) {
        addNewCharacter(characters, characterTemplate, charactersContainer, battle);
        saveButtonGreen(characters);
        characters.unsavedChanges = false;
      }
    }
  });
  
  characters.uploadCharacter.addEventListener("click", function(event) {
    uploadCharacter(characters, characterTemplate, charactersContainer, battle);
  });
  
  characters.characterCreation.addEventListener("change", function() {
    saveButtonOrange(characters)
    characters.unsavedChanges = true;
  })
  
  filterForm();
  characterCreationListener(characters, battle);
  
  window.addEventListener('beforeunload', function(event) {
    if (characters.unsavedChanges) {
      event.preventDefault();
      event.returnValue = '';
      return '';
    }
  });
}


function removeBattleChoice(battle, name) {
  
  var battleSelects = [battle.attackerSelection, battle.victimSelection];
  
  battleSelects.forEach(function(battleSelect) {
    for (var optionIndex = 0; optionIndex < battleSelect.options.length; optionIndex++) {
      if (battleSelect.options[optionIndex].value === name) {
        battleSelect.remove(optionIndex);
        break;
      }
    }
  });
}


function addBattleChoice(battle, name) {
  
  function createOption(text) {
    var option = document.createElement("option");
    option.textContent = text;
    option.value = text;
    return option;
  }
  
  battle.attackerSelection.appendChild(createOption(name));
  battle.victimSelection.appendChild(createOption(name));
}


function updateBattleChoice(savedCharacters, battle) {
  
  addBattleChoice(battle, "Chien errant");

  Object.keys(savedCharacters).forEach(function(pseudo) {
    addBattleChoice(battle, pseudo);
  });
}


function calcAttackFactor(attacker, victim) {

  function calcCoeffK(dex, level) {
    return Math.min(90, Math.floor((2 * dex + level) / 3))
  }

  var K1 = calcCoeffK(attacker.dex, attacker.level);
  var K2 = calcCoeffK(victim.dex, attacker.level);
  
  var AR = (K1 + 210) / 300;
  var ER = (2 * K2 + 5) / (K2 + 95) * 3 / 10;
  
  return AR - ER
}


function calcMainAttackValue(character, characterWeapon) {
  
  var rawWeaponAttackValue = characterWeapon[2][character.upgrade];
  
  if (!rawWeaponAttackValue) {
    rawWeaponAttackValue = 0;
  }

  return 2 * (character.level + rawWeaponAttackValue) + character.leadership
}


function calcStatAttackValue(character) {
  
  switch (character.race) {
    case 'warrior':
    case 'sura':
      return 2 * character.str
    case 'ninja':
      return parseInt(1 / 4 * (character.str + 7 * character.dex))
    case 'shaman':
      return parseInt(1 / 3 * (5 * character.int + character.dex))
    case 'lycan':
      return character.vit + 2 * character.dex;
    default:
      return 2 * character.str
  }
}


function calcSecondaryAttackValue(character, characterWeapon) {
  
  var statAttackValue = calcStatAttackValue(character);
  var attackValues = [];
  
  if (character.weapon.indexOf("serpent") === -1) {
    
    var minWeaponAttackValue = characterWeapon[1][2];
    var maxWeaponAttackValue = characterWeapon[1][3];
    
  } else {
    
    var rawAttackValue = characterWeapon[2][character.upgrade]
    var minWeaponAttackValue = character.randomAttackValueMin - rawAttackValue;
    var maxWeaponAttackValue = Math.max(minWeaponAttackValue, character.randomAttackValueMax  - rawAttackValue);
    
  }
  
  minWeaponAttackValue += character.slashMin;
  maxWeaponAttackValue += character.slashMax;
  
  var secondaryAttackValue = statAttackValue + character.attackValue
  
  for (var attackValue = minWeaponAttackValue; attackValue <= maxWeaponAttackValue; attackValue++) {
    attackValues.push(2 * attackValue + secondaryAttackValue);
  }
  
  return attackValues
}


function calcDamageWithBonuses(attacker, victim, attackFactor, mainAttackValue, secondaryAttackValue) {
  var damages = mainAttackValue + parseInt(attackFactor * secondaryAttackValue);
  damages -= victim.defense
  return damages
}


function calcBattleDamage(attacker, victim) {
  
  var sumDamages = 0;
 
  var attackerWeapon = weaponData[attacker.weapon];

  var attackFactor = calcAttackFactor(attacker, victim);
  var mainAttackValue = calcMainAttackValue(attacker, attackerWeapon);
  var secondaryAttackValues = calcSecondaryAttackValue(attacker, attackerWeapon);
  var damageLength = secondaryAttackValues.length;
  
  for (var damageIndex = 0; damageIndex < damageLength; damageIndex++) {
    var secondaryAttackValue = secondaryAttackValues[damageIndex]
    sumDamages += calcDamageWithBonuses(attacker, victim, attackFactor, mainAttackValue, secondaryAttackValue);
  }
  
  return sumDamages / damageLength
}


function damageFormat(damage, precision) {
  return Math.max(0, Math.round((damage) * 10**precision) / 10**precision);
}


function createMonster(name) {
  
  var data = monsterData[name];

  var monster = {
    "name": name,
    "level": data[0],
    "race": "monster",
    "vit": data[3],
    "int": data[4],
    "str": data[1],
    "dex": data[2],
    "weapon": "Poings",
    "randomAttackValueMin": data[5],
    "randomAttackValueMax": data[6],
    "slashMin": 0,
    "slashMax": 0,
    "attackValue": 0,
    "leadership": 0,
    "defense": data[7] + data[0] + data[3]
  }
  
  return monster;
}


function createBattle(characters, battle) {
  
  battle.battleForm.addEventListener("submit", function(event) {
    
    event.preventDefault();
    
    var battleInfo = new FormData(event.target)
    var attackerName = battleInfo.get("attacker");
    var victimName = battleInfo.get("victim");
    
    if (attackerName === 'Chien errant') {
      var attacker = createMonster('Chien errant');
      
    } else {
      var attacker = characters.savedCharacters[attackerName];
    }
    
    if (victimName === 'Chien errant') {
      var victim = createMonster('Chien errant');
      
    } else {
      var victim = characters.savedCharacters[victimName];
    }

    var meanDamages = calcBattleDamage(attacker, victim);

    battle.damageResult.textContent = attacker.name + " inflige " + damageFormat(meanDamages, 1) + " dégâts en moyenne à " + victim.name + ".";
  })
  
}


function createDamageCalculatorInformation() {
  
  var characters = {
    unsavedChanges: false,
    savedCharacters: {},
    characterCreation: document.getElementById("character-creation"),
    addNewCharacterButton: document.getElementById("add-new-character"),
    uploadCharacter: document.getElementById("upload-character"),
    newCharacterTemplate: document.getElementById("new-character-template").children[0],
    charactersContainer: document.getElementById("characters-container"),
    saveButton: document.getElementById("save-button"),
    saveBar: document.getElementById("save-bar")
  }
  var savedCharactersPseudo = getSavedCharactersPseudo();

  savedCharactersPseudo.forEach(function(pseudo) {
    var characterData = getCharacter(pseudo);
    characterData = parseCharacter(characterData);
    characters.savedCharacters[pseudo] = characterData;
  });
  
  var battle = {
    battleForm: document.getElementById("create-battle"),
    attackerSelection: document.getElementById("attacker-selection"),
    victimSelection: document.getElementById("victim-selection"),
    damageResult: document.getElementById("result-damage")
  }

  return [characters, battle];
}


(function(){

  var [characters, battle] = createDamageCalculatorInformation();

  characterManagement(characters, battle);
  
  updateBattleChoice(characters.savedCharacters, battle);
  createBattle(characters, battle);

})();