Credit Card Checker

Hey all! First post here on the forum. :slight_smile: I’m going through the Credit Card Checker project right now and I’m running into a snag with my findInvalidCards() function. I’m expecting it to push a nested array depending on the result, but right now it’s pushing the values directly. For the life of me I can’t figure out why.

My code below. Excuse the excessive console logs, I’ve been in debugging mode for a few hours trying to figure out where this is going wrong.

// All valid credit card numbers
const valid1 = [4, 5, 3, 9, 6, 7, 7, 9, 0, 8, 0, 1, 6, 8, 0, 8];
const valid2 = [5, 5, 3, 5, 7, 6, 6, 7, 6, 8, 7, 5, 1, 4, 3, 9];
const valid3 = [3, 7, 1, 6, 1, 2, 0, 1, 9, 9, 8, 5, 2, 3, 6];
const valid4 = [6, 0, 1, 1, 1, 4, 4, 3, 4, 0, 6, 8, 2, 9, 0, 5];
const valid5 = [4, 5, 3, 9, 4, 0, 4, 9, 6, 7, 8, 6, 9, 6, 6, 6];

// All invalid credit card numbers
const invalid1 = [4, 5, 3, 2, 7, 7, 8, 7, 7, 1, 0, 9, 1, 7, 9, 5];
const invalid2 = [5, 7, 9, 5, 5, 9, 3, 3, 9, 2, 1, 3, 4, 6, 4, 3];
const invalid3 = [3, 7, 5, 7, 9, 6, 0, 8, 4, 4, 5, 9, 9, 1, 4];
const invalid4 = [6, 0, 1, 1, 1, 2, 7, 9, 6, 1, 7, 7, 7, 9, 3, 5];
const invalid5 = [5, 3, 8, 2, 0, 1, 9, 7, 7, 2, 8, 8, 3, 8, 5, 4];

// Can be either valid or invalid
const mystery1 = [3, 4, 4, 8, 0, 1, 9, 6, 8, 3, 0, 5, 4, 1, 4];
const mystery2 = [5, 4, 6, 6, 1, 0, 0, 8, 6, 1, 6, 2, 0, 2, 3, 9];
const mystery3 = [6, 0, 1, 1, 3, 7, 7, 0, 2, 0, 9, 6, 2, 6, 5, 6, 2, 0, 3];
const mystery4 = [4, 9, 2, 9, 8, 7, 7, 1, 6, 9, 2, 1, 7, 0, 9, 3];
const mystery5 = [4, 5, 3, 9, 6, 8, 9, 8, 8, 7, 7, 0, 5, 7, 9, 8];

// An array of all the arrays above
const batch = [valid1, valid2, valid3, valid4, valid5, invalid1, invalid2, invalid3, invalid4, invalid5, mystery1, mystery2, mystery3, mystery4, mystery5];


// Add your functions below:
// Copy #, Remove Digit, Reverse
const validateCred = array => {
  let holdArray = [];
  holdArray = array.slice();
  holdArray.pop();
  holdArray.reverse()
// Multiply every other number by two. If the result is over 9, subtract 9, reinstating the originally popped number.
  for (let i = 0; i < holdArray.length; i += 2) {
    holdArray[i] *= 2;
  };
  for (let i = 0; i < holdArray.length; i++) {
    if (holdArray[i] > 9) {
      holdArray[i] -= 9;
    }
  };
  holdArray.push(array[array.length-1]);
  //Calculating Total and testing validity
  let sumTotal = holdArray.reduce((acc, curVal) => acc + curVal);
  if (sumTotal % 10 === 0) {
    console.log(`Total: ${sumTotal}. Valid.`)
    return true;
  }
    console.log(`Total: ${sumTotal}. Invalid.`)
    return false;
};
// Take in an array
const findInvalidCards = array => {
  let invalidCards = [];
  let validCards = [];
  // create function that passes array to validateCred 
  const validChecker = array => validateCred(array);
  //for each card in array, console log the card you're checking, run it through validateCred (via validChecker), nest the card in the appropriate array.
  for(let card in array){
    console.log(array[card])
  if(validChecker(array[card]) === true){
    console.log(`Card ${array[card]} is true.`)
    validCards.unshift(array[card])//expected to nest the array
  } else{
    invalidCards.push(card);//expected to nest the card #
    }
}
// Testing outputs.
console.log(`Valid Cards: ${validCards}`);
console.log(`Invalid Cards: ${invalidCards}`)
}
findInvalidCards(batch)

Hi @py6107642942
Welcome to the forum!
Nice job adding many consoles to your functions. That shows that you have already done a lot to trace the error and understand your functions. And you’re almost there.

push and unshift basically do the same. Push adds the item at the end of an array. Unshift at the beginning. Therefore I wonder why you don’t use the same logic for the valid and the invalid cards?

Hey!

It’s due to how you’re logging your array within a template literal. You’ll just want to console.log(validCards);

Also you won’t need to do if(validChecker(array[card]) === true)

You can just do if(validChecker(array[card])).

Here is a solution if that’s what you’re going for:

console.log(Valid Cards:)
console.log(validCards)
console.log(Invalid Cards:)
console.log(invalidCards)

Maybe mess with some line breaks, but it’s because you’re inserting it as a string which is just a bunch of comma separated values in the end.

Also is there any reason you call a function to pass the array to validateCred? I believe you can throw validateCred straight into the if statement and have the same functionality without the extra line of code :slight_smile:

2 Likes

That was leftover from some experimenting changing variables between the two card sets to see how those changes impacted the code. I didn’t even notice the discrepancy there. Thanks!

1 Like

To tell you I spent HOURS trying to figure out what wasn’t working. The function was doing its job correctly, I was just asking it in the wrong way. :man_facepalming: Glass half full I guess.

There is not, and you are correct. :sweat_smile:

Thanks for the help!

1 Like

Better to have functionality working as intended! Syntax errors can be a PAIN and I know even from my development team at work that they go through things like this occasionally.

For example:

if(a = b){
}
Will still run through your code, but if you’re actually trying to do a strict equal you’d want to do if(a ===b){}, you can imagine that that is hard to spot and can really give you some unintended results.

Keep chugging along! I’m only maybe 1.5 months ahead of you and if you really apply yourself (especially to your portfolio projects(i did a web app rather than a website)) you’ll learn SO much.

I’ve been putting finishing touches on this long enough I should probably quit while I’m ahead and everything appears to be working almost as expected. :sweat_smile: I’m having fun messing around with conditional operators and seeing how they can really simplify the readability of code.

I spent far longer than necessary trying to figure out why my testOneCard function wasn’t working when I entered a long card number as a number instead of string. After some digging, I discovered it was because of how javascript handles numbers over 16 characters long and I’m content letting that be my stopping point.

Final code below :slight_smile:

// All valid credit card numbers
const valid1 = [4, 5, 3, 9, 6, 7, 7, 9, 0, 8, 0, 1, 6, 8, 0, 8];
const valid2 = [5, 5, 3, 5, 7, 6, 6, 7, 6, 8, 7, 5, 1, 4, 3, 9];
const valid3 = [3, 7, 1, 6, 1, 2, 0, 1, 9, 9, 8, 5, 2, 3, 6];
const valid4 = [6, 0, 1, 1, 1, 4, 4, 3, 4, 0, 6, 8, 2, 9, 0, 5];
const valid5 = [4, 5, 3, 9, 4, 0, 4, 9, 6, 7, 8, 6, 9, 6, 6, 6];

// All invalid credit card numbers
const invalid1 = [4, 5, 3, 2, 7, 7, 8, 7, 7, 1, 0, 9, 1, 7, 9, 5];
const invalid2 = [5, 7, 9, 5, 5, 9, 3, 3, 9, 2, 1, 3, 4, 6, 4, 3];
const invalid3 = [3, 7, 5, 7, 9, 6, 0, 8, 4, 4, 5, 9, 9, 1, 4];
const invalid4 = [6, 0, 1, 1, 1, 2, 7, 9, 6, 1, 7, 7, 7, 9, 3, 5];
const invalid5 = [5, 3, 8, 2, 0, 1, 9, 7, 7, 2, 8, 8, 3, 8, 5, 4];

// Can be either valid or invalid
const mystery1 = [3, 4, 4, 8, 0, 1, 9, 6, 8, 3, 0, 5, 4, 1, 4];
const mystery2 = [5, 4, 6, 6, 1, 0, 0, 8, 6, 1, 6, 2, 0, 2, 3, 9];
const mystery3 = [6, 0, 1, 1, 3, 7, 7, 0, 2, 0, 9, 6, 2, 6, 5, 6, 2, 0, 3];
const mystery4 = [4, 9, 2, 9, 8, 7, 7, 1, 6, 9, 2, 1, 7, 0, 9, 3];
const mystery5 = [4, 5, 3, 9, 6, 8, 9, 8, 8, 7, 7, 0, 5, 7, 9, 8];

// An array of all the arrays above
const batch = [valid1, valid2, valid3, valid4, valid5, invalid1, invalid2, invalid3, invalid4, invalid5, mystery1, mystery2, mystery3, mystery4, mystery5]; // expected return 2 invalid cards per company.


// Add your functions below:
// Determines whether a card (entered as array) is valid.
const validateCred = array => {
  // Copy #, Remove Digit, Reverse
  let holdArray = [];
  holdArray = array.slice();
  holdArray.pop();
  holdArray.reverse();
  // Multiply every other number by two. If the result is over 9, subtract 9, reinstating the originally popped number.
  for (let i = 0; i < holdArray.length; i += 2) {
    holdArray[i] *= 2;
  };
  for (let i = 0; i < holdArray.length; i++) {
    if (holdArray[i] > 9) {
      holdArray[i] -= 9;
    }
  };
  holdArray.push(array[array.length-1]);
  //Calculating Total and testing validity
  let sumTotal = holdArray.reduce((acc, curVal) => acc + curVal);
  if (sumTotal % 10 === 0) {
    return true;
  }
    return false;
};
// For each card in array, run through validateCred and return new array with all invalid cards.
const findInvalidCards = arr => {
  let invalidCards = [];
  for(let card in arr){
  if(!validateCred(arr[card])){
    invalidCards.push(arr[card]);
    }
    }
    return invalidCards;
};
//determine invalidCards, separate based on company, and notify which companies need to be contacted
const idInvalidCardCompanies = list => {
  let companiesToContact = [];
  let invalidCards = findInvalidCards(list);
  //each array filters through the first value and pushes to the appropriate
  let badVisas = invalidCards.filter(card => card[0] === 4);
  console.log('Invalid Visas:');
  console.log(badVisas);
  let badAmexes = invalidCards.filter(card => card[0] === 3);
  console.log('Invalid Amexes:');
  console.log(badAmexes);
  let badMasters = invalidCards.filter(card => card[0] === 5);
  console.log('Invalid Mastercards:');
  console.log(badMasters);
  let badDiscovers = invalidCards.filter(card => card[0] === 6);
  console.log('Invalid Discovers:');
  console.log(badDiscovers);
  //If there's a card there, push the company to companiesToContact
  badAmexes.length === 0 ?  null : companiesToContact.push(`Amex: ${badAmexes.length} cards`);
  badVisas.length === 0 ?  null : companiesToContact.push(`Visa: ${badVisas.length} cards`);
  badMasters.length === 0 ?  null : companiesToContact.push(`Mastercard: ${badMasters.length} cards`);
  badDiscovers.length === 0 ?  null : companiesToContact.push(`Discover: ${badDiscovers.length} cards`);
  invalidCards.length === 0 ? companiesToContact.push('None!') : null;
// Console log which companies we should contact and how many invalid cards they have.
console.log(`Companies to Contact: ${companiesToContact.join(', ')}`);
};
// Convert String of Numbers to Array and checks it against validateCred
const testOneCard = num => {
  let sumTotal
  let stringToNum = num => parseInt(num, 10);
  let finalArray = Array.from(String(num), stringToNum);
  validateCred(finalArray);
    console.log('Card number ' + finalArray.join('') + ' is ' + (validateCred(finalArray) ? 'valid.' : 'invalid.'))
};
testOneCard('379589973721009')
idInvalidCardCompanies(batch)

This topic was automatically closed 41 days after the last reply. New replies are no longer allowed.