What you are doing is creating array of all possible characters (finalCharacters) and taking randomly 12 characters of it.
What you need to do is to take at least one random character from each needed array (upperCharacters, numbers, symbols) and shuffle it.
Algorithm example:
- generating number of lowerCharacters, number of upperCharacters, number of numbers and number of symbols (i.e. 3 lower, 3 upper, 3 numbers, 3 symbols)
- push proper number of random characters from each array (
lowerCharacters, upperCharacters, ...) into array (i.e. passwordArray)
- shuffle
passwordArray
- join
passwordArray
First step may be:
noOfLowerCharacters = 0, noOfUpperCharacters = 0, noOfUpperCharacters = 0
- count number of needed types (
1, 2 or 3). Store it in variable noOfneededTypes.
- take random number from range from
1 to (passwordLength - noOfneededTypes). Store it in variable noOfLowerCharacters.
- create
usedTypeCounter. Set value to 1
- if
addUpper then take random number from range from 1 to (passwordLength - noOfneededTypes + usedTypeCounter - noOfLowerCharacters). Store it in variable noOfUpperCharacters. Increase usedTypeCounter
- if
addNumbers then take random number from range from 1 to (passwordLength - noOfneededTypes + usedTypeCounter - noOfLowerCharacters - noOfUpperCharacters). Store it in variable noOfNumbers.
- if
addSymbols then noOfSymbols = passwordLength - noOfLowerCharacters - noOfUpperCharacters - noOfNumbers
Example of implementation:
$scope.passwordLength = 12;
$scope.addUpper = true;
$scope.addNumbers = true;
$scope.addSymbols = true;
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
// shuffle function taken from http://stackoverflow.com/a/12646864/4989081
function shuffleArray(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
$scope.createPassword = function() {
var lowerCharacters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
var upperCharacters = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
var numbers = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
var symbols = ['!', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '^', '_', '`', '{', '|', '}', '~'];
var noOfLowerCharacters = 0,
noOfUpperCharacters = 0,
noOfNumbers = 0,
noOfSymbols = 0;
var noOfneededTypes = $scope.addUpper + $scope.addNumbers + $scope.addSymbols;
var noOfLowerCharacters = getRandomInt(1, $scope.passwordLength - noOfneededTypes);
var usedTypeCounter = 1;
if ($scope.addUpper) {
noOfUpperCharacters = getRandomInt(1, $scope.passwordLength - noOfneededTypes + usedTypeCounter - noOfLowerCharacters);
usedTypeCounter++;
}
if ($scope.addNumbers) {
noOfNumbers = getRandomInt(1, $scope.passwordLength - noOfneededTypes + usedTypeCounter - noOfLowerCharacters - noOfUpperCharacters);
usedTypeCounter++;
}
if ($scope.addSymbols) {
noOfSymbols = $scope.passwordLength - noOfLowerCharacters - noOfUpperCharacters - noOfNumbers;
}
var passwordArray = [];
for (var i = 0; i < noOfLowerCharacters; i++) {
passwordArray.push(lowerCharacters[getRandomInt(1, lowerCharacters.length - 1)]);
}
for (var i = 0; i < noOfUpperCharacters; i++) {
passwordArray.push(upperCharacters[getRandomInt(1, upperCharacters.length - 1)]);
}
for (var i = 0; i < noOfNumbers; i++) {
passwordArray.push(numbers[getRandomInt(1, numbers.length - 1)]);
}
for (var i = 0; i < noOfSymbols; i++) {
passwordArray.push(symbols[getRandomInt(1, symbols.length - 1)]);
}
passwordArray = shuffleArray(passwordArray);
return passwordArray.join("");
};
$scope.password = $scope.createPassword();
See working: http://jsfiddle.net/cmoqkkw8/