Modifying Luhn checker function to check for Laser cards - javascript

I use the following script to validate the card details entered in a form. I would like to add a function to this so that a visitor using a Laser card is alerted that we don't accept them.
The start digits of the Laser are 6304, 6706, 6771 & 6709
function Calculate(Luhn)
{
var sum = 0;
for (i=0; i<Luhn.length; i++ )
{
sum += parseInt(Luhn.substring(i,i+1));
}
var delta = new Array (0,1,2,3,4,-4,-3,-2,-1,0);
for (i=Luhn.length-1; i>=0; i-=2 )
{
var deltaIndex = parseInt(Luhn.substring(i,i+1));
var deltaValue = delta[deltaIndex];
sum += deltaValue;
}
var mod10 = sum % 10;
mod10 = 10 - mod10;
if (mod10==10)
{
mod10=0;
}
return mod10;
}
function Validate(Luhn)
{
var LuhnDigit = parseInt(Luhn.substring(Luhn.length-1,Luhn.length));
var LuhnLess = Luhn.substring(0,Luhn.length-1);
if (Calculate(LuhnLess)==parseInt(LuhnDigit))
{
return true;
}
alert("\n\nError with your card number! \nPlease check and correct.\n\n")
return false;

I wouldn't modify these functions to check the card type - they have a specific goal. If you change the Validate(Luhn) function so that it fails a card that passes its Luhn check but that has specific starting digits, you're making trouble for yourself later. Instead, add a new function, something like this:
function checkCardType(CardNumber) {
var CardStart = CardNumber.substring(0, 4);
if ((CardStart == '6304') || (CardStart == '6706') || (CardStart == '6771') || (CardStart == '6709')) {
alert('We do not accept Laser cards.');
return false;
} else {
return true;
}
}

Could you just keep a blacklist? You'd need to have a process to keep it up-to-date (e.g. load it from a database, manage it there - keeping it in the source is more hassle in the long term), but for such a small number of items, it would be useful:
function LoadBlacklist() {
// this is the simplest example; you may want to load the array dynamically
var bad_prefixes = [ "6304", "6706", "6771", "6709" ];
return bad_prefixes;
}
function Validate(Luhn)
{
var blacklist = LoadBlacklist();
var luhn_prefix = Luhn.substring(0,4); // only check the first 4 characters
for (var bl_pos = blacklist.length - 1; bl_pos >= 0; bl_pos--) {
if (blacklist[bl_pos] == luhn_prefix) {
// this card matches one of the blacklist prefixes
return false;
}
}
// if we're here, no match was found
// go on with validation...
}

Related

How to generate a random 5 letter code and give filters

I want to generate a random 5 letter code and give filters that the code will not same to the filters. I also want filters to be in an array. If there are too many filters that the code can't generated, it will make new character in the code. Like in YouTube, in a video, a random letter of 9 characters is generated and it has given filters to not generate the same.
The generation function and the filter generate function (90%) are created but only one problem is written in the code:
var l = `abcdefghijklmnopqrstuvwxyz${"abcdefghijklmnopqrstuvwxyz".toUpperCase()}0123456789`;
function generateCode(c) {
var t = "";
for (var i = 0; i < c; i++) {
t += l.split("")[randomNumber(0, l.length)];
}
return t;
}
function filtersPreventGenerate(generated, minCharacters) {
/*
generated: array
minCharacters: number
*/
var t = "";
var characters = minCharacters;
t = generateCode(characters);
while (generated.indexOf(t) > -1) {
t = generateCode(c);
// i can't tell what is the code to check there are too many items in the generated argument that 5 letter can't generated. what will be the code?
}
return t;
}
function randomNumber(min, max) {
return Math.floor(Math.random() * max) + min;
}
Help will be appreciated.
Here is a snippet that you can use as a 5-letter code generator
function generate(len = 5){
let charset = "1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM!##$%^&*()"
let result = ""
for(let i = 0; i<len;i++ ){
let charsetlength = charset.length
result+=charset.charAt(Math.floor(Math.random() * charsetlength))
}
return result;
}
And below snippet is responsible to assign the random as a "code" variable, based on it you can create filter inside the function
$(document).on("click", ".generate", function(){
let code = generate()
// your filters here
})

Find duplicates in array JavaScript

So I'm working on a simple JavaScript web-based game. The goal is to guess a X digit random number. This means the random number can be 4, 5 digits up to whatever you want. You can actually play the game at www.juegodescifralo.com , (it's in Spanish, sorry about that).
The user inputs a number that is stored as an array. The random number is also generated as an array. Individual numbers in both arrays can be repeated.
There are three types of possible "values/numbers": the "good" ones are the numbers you chose that are in the same position as the ones in the random array. So for example:
Random array is: 1457
User input is: 6851
Number 5 is a "good" number, since it's in the same position. Then there are the second type of "values", which are "regular". This means they are inside the random number but not in the same position. In this example, number 1 would be a "regular" value. And the third type is the "bad" ones, which are not even inside the random array.
The function I've developed is as follows:
function checkNumbers(randomArray, myArray, good, regular, bad) {
for (var x = 0; x < randomArray.length; x++) {
var posRepetido = randomArray.indexOf(myArray[x]); //Is current number inside random array?
if (posRepetido == -1) { //It's not inside
console.log("number " + myArray[x] + "is not inside");
bad++;
} else { //It's inside
regular++;
if (myArray[x] == randomArray[x]) { //If it's the same number...
console.log("number " + myArray[x] + "is in the correct position");
good++;
regular--;
} else { //If it's not the same number
if (randomArray[posRepetido] != myArray[posRepetido]) {
console.log("number " + myArray[x] + "is inside but not in the same position");
} else {
console.log("number " + myArray[x] + "is not inside");
}
}
}
}
var obj = { //Return object for accessing later, to show feedback to the user.
good: good,
regular: regular,
bad: bad
};
return obj;
}
The code is a bit buggy. When there are duplicates in the random array, and one of them is marked as good, then the other one (even if it exists in user input) will be set as bad, not as regular as it should.
The thing becomes even more complicated since you should be able to play against any amount of digits. So I should be able to guess a 20 digit number without "problems".
You can play by yourself at www.juegodescifralo.com
How can I go about this? Any ideas how can I access array data more easily? Thank you very much!
Rather than indexOf comparisons against -1 and checks of myArray[x], it would probably be a lot easier to use includes and array methods such as forEach for better abstraction. All you really need is an if, an else if, and an else. For example:
function checkNumbers(randomArray, userArray, good=0, regular=0, bad=0) {
userArray.forEach((guess, i) => {
if (guess === randomArray[i]) good++;
else if (randomArray.includes(guess)) regular++;
else bad++;
});
return { good, regular, bad };
}
// 4 good
console.log(checkNumbers(
'1234'.split(''),
'1234'.split(''),
));
// 4 good, 2 bad
console.log(checkNumbers(
'1234'.split(''),
'123456'.split(''),
));
// 4 good, 2 regular
console.log(checkNumbers(
'1234'.split(''),
'123412'.split(''),
));
// all regular:
console.log(checkNumbers(
'123456789123456789'.split(''),
'912345678912345678'.split(''),
));
i think it is easier to loop thru it twice like this
function checkNumbers(randomArray, guessArray) {
var clone = randomArray.slice(0);
var good = 0;
var regular = 0;
var bad = 0;
var visited = [];
guessArray.forEach(function(guess, index) {
if (guess === clone[index]) { // the guess is in right position
good++;
clone[index] = "x"; // strike it out so it cannot be used later
visited.push(index);
} else if (clone.indexOf(guess) === -1) {
bad++;
visited.push(index);
}
});
guessArray.forEach(function(guess, index) {
if (!visited.includes(index)) {
var match = clone.indexOf(guess);
if (match !== -1) {
regular++;
clone[match] = "x"; // strike it out so it cannot be used later
}
}
});
return {
good: good,
bad: bad,
regular: regular
}
}
first loop is to check the good and bad. and strikeout the value it is good so it cannot be used again.
second loop to check for the regular and strikeout the value it is used so it cannot be used again.
This should work.
function guessNumber (numUser, numRandom) {
if (typeof numUser == 'number') {
numUser = numUser.toString().split('');
}
if (typeof numRandom == 'number') {
numRandom = numRandom.toString().split('');
}
if (typeof numRandom != 'object' || typeof numUser != 'object') {
return false;
}
if (numRandom == numUser) {
return true;
}
var numRegular = {},
numBuenos = {},
numMalos = {},
numRepeat = {};
for(var i = 0; i < numRandom.length; i++) {
if (!numRepeat[numRandom[i]]) {
numRepeat[numRandom[i]] = 0;
}
numRegular[numRandom[i]] = 0;
numRepeat[numRandom[i]]++;
}
for (var i = 0; i < numUser.length; i++) {
if (numUser[i] == numRandom[i]) {
numBuenos[numUser[i]] = numUser[i];
}else if ($.inArray(numUser[i], numRandom)) {
if (!numRegular[numUser[i]]) {
numRegular[numUser[i]] = 0;
}
if (numRegular[numUser[i]] < numRepeat[numUser[i]]) {
numRegular[numUser[i]]++;
} else {
numMalos[numUser[i]] = numUser[i];
}
} else {
numMalos[numUser[i]] = numUser[i];
}
}
return {
regular: Object.values(numRegular).reduce((a, b) => a + b),
buenos: Object.keys(numBuenos).length,
malos: Object.keys(numMalos).length
};
}
console.log(guessNumber(8365, 8512));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

JS function to validate input name not working correctly

The objective of this code is to check the name the user inputs. If the value contains something other than -abcdefghijklmnopqrstuvwxyz'ABCDEFGHIJKLMNOPQRSTUVWXYZ the function will throw an error.
I am unable to get this to work, and I'm not allowed to use Regular expressions. I've also tried String1.indexOf(usr.substr(i,1)) > -1) but that doesn't seem to work neither.
function nameValidation(username) {
var usr = document.getElementById("username").value;
usr = usr.trim();
var alpha = "-abcdefghijklmnopqrstuvwxyz'ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var ok = 1;
for (var i = 0; i < usr.length; i++) {
if (!isNaN(usr[i])) {
ok = 0;
break;
} else {
ok = 1;
document.getElementById("fnerror").innerHTML = "";
document.getElementById("username").style.borderColor = "lightgrey";
return true;
}
}
if (ok == 0) {
document.getElementById("fnerror").innerHTML = "X Enter Upper and lower case letters, hypen, apostrohe only please";
return false;
}
return true;
}
Something like this, maybe:
function isValidUsername(username) {
var alpha = "-'ABCDEFGHIJKLMNOPQRSTUVWXYZ";
username = username.toUpperCase();
for (var i = 0, l = username.length; i < l; i++) {
if (alpha.indexOf(username[i]) === -1) return false;
}
return true;
}
Cheaper to upper-case the string and therefore have a shorter set of characters to test against (though probably marginal at best because there's a cost to even native-uppercasing..)
You can do it in a more "functional way", by using every method, which allow us to break a loop instead of foreach.
The every method executes the provided callback function once for each element present in the array until it finds one where callback returns a falsy value (a value that becomes false when converted to a Boolean). If such an element is found, the every method immediately returns false. Otherwise, if callback returned a true value for all elements, every will return true. callback is invoked only for indexes of the array which have assigned values; it is not invoked for indexes which have been deleted or which have never been assigned values.
Array.proototype.every
So :
function check(){
//Get value input and transform it into array
var value = document.querySelector('#username').value.split('');
var alpha = "-abcdefghijklmnopqrstuvwxyz'ABCDEFGHIJKLMNOPQRSTUVWXYZ";
//If there is an error, stop the loop and return result
return value.every(function(elm){
//check if elm is an alpha string
return alpha.indexOf(elm) > -1;
});
}
The easiest (to understand at least) solution (that doesn't use regex), would be to loop through your string character by character and check .indexOf against your list of allowed characters, something like:
for (var i = 0; i < input.length; i++) {
if (alpha.indexOf(input[i])==-1) {
console.log("ERROR");
break;
}
}
EDITED: I read the question wrong and thought you wanted to return true if there's a letter. It will now make sure that each character is within the ASCII values of A and z.
text = "ABCDEFzzxasd1";
valid = true;
for( i = 0; i < text.length; i++ ) {
if ( text.charCodeAt(i) < 65 || text.charCodeAt(i) > 122 ) {
alert("Woah, that's not a letter!");
valid = false;
break;
}
}
Begin with
var alpha = "-abcdefghijklmnopqrstuvwxyz'ABCDEFGHIJKLMNOPQRSTUVWXYZ".split('');
function duplicates( element, index, array ){
return array.indexOf(element) == index;
}
function isNameFormatCorrect( userName ){
return ( alpha.concat(username.split(''))
.filter( duplicates ).length === alpha.length );
}
Then
var username = "YourUserNameHere-"
isNameFormatCorrect( username ); => true;
var username = "YourUserNameHere-**"
isNameFormatCorrect( username ); => false;

Textarea input length check in JavaScript

I'd like to create an SMS gateway which alerts the user each time when 160 chars are written (or pasted). I need to store a variable n containing number of message parts of 160 chars. The code will be like this, just the n needs to be stored globally. Is there any better way than e. g. storing it into a hidden form field?
Note: an assumption that less than 160 chars will be pasted at once is safe in this particular case.
window.onload = function() {
var n=1;
var t=document.getElementById('msg');
t.addEventListener('input', function() {
var l=t.value.length;
if(l>n*160){
n++;
alert('Message will be split into '+n+' parts');
}
}, false);
}
As mentioned in my comment, it depends on what you want to do with n ultimately.
If you just want it to show the user a message, you can update the DOM once you've calculated this value.
Your current example doesn't allow the user to delete text after they've typed/pasted it in. A better example would be stateless, i.e. don't compare n to itself, as in my example below:
var t = document.getElementById('msg');
var splitSize = 10;
var n = 1;
t.addEventListener('input', function() {
var nextN = 1;
if (t.value.length > 0) {
nextN = Math.ceil(t.value.length / splitSize);
}
if (n !== nextN) {
n = nextN;
var label = document.getElementById('label');
if (n === 1) {
label.innerHTML = '';
} else {
label.innerHTML = 'The message will be split into ' + n + ' parts';
}
}
});
<p id="label"></p>
<textarea id="msg"></textarea>

Counting the frequency of elements in an array in JavaScript

how do I count the frequency of the elements in the array, I'm new to Javascript and completely lost, I have looked at other answers here but can't get them to work for me. Any help is much appreciated.
function getText() {
var userText;
userText = document.InputForm.MyTextBox.value; //get text as string
alphaOnly(userText);
}
function alphaOnly(userText) {
var nuText = userText;
//result = nuText.split("");
var alphaCheck = /[a-zA-Z]/g; //using RegExp create variable to have only alphabetic characters
var alphaResult = nuText.match(alphaCheck); //get object with only alphabetic matches from original string
alphaResult.sort();
var result = freqLet(alphaResult);
document.write(countlist);
}
function freqLet(alphaResult) {
count = 0;
countlist = {
alphaResult: count
};
for (i = 0; i < alphaResult.length; i++) {
if (alphaResult[i] in alphaResult)
count[i] ++;
}
return countlist;
}
To count frequencies you should use an object which properties correspond to the letters occurring in your input string.
Also before incrementing the value of the property you should previously check whether this property exists or not.
function freqLet (alphaResult) {
var count = {};
countlist = {alphaResult:count};
for (i = 0; i < alphaResult.length; i++) {
var character = alphaResult.charAt(i);
if (count[character]) {
count[character]++;
} else {
count[character] = 1;
}
}
return countlist;
}
If you can use a third party library, underscore.js provides a function "countBy" that does pretty much exactly what you want.
_.countBy(userText, function(character) {
return character;
});
This should return an associative array of characters in the collection mapped to a count.
Then you could filter the keys of that object to the limited character set you need, again, using underscore or whatever method you like.
Do as below:
var __arr = [6,7,1,2,3,3,4,5,5,5]
function __freq(__arr){
var a = [], b = [], prev
__arr.sort((a,b)=>{return a- b} )
for(let i = 0; i<__arr.length; i++){
if(__arr[i] !== prev){
a.push(__arr[i])
b.push(1)
}else{
b[b.length - 1]++
}
prev = __arr[i]
}
return [a , b]
}

Categories

Resources