0

I'm trying to put a company name in front of a card number, this code here is what i'm attempting to make it print the name in front. The problem i'm having here is that each company has rules - conditions, i'm struggling to make these rules into conditions for an if statement.

I realise the if statement i'm doing is not a good way to handle this, but i'm just asking for an explanation on the best way to approach this.

AMEX card rules: - Length is 15 - Starts with '34' or '37'

Discover card rules: - Length is 16 - Starts with '6011'

MasterCard card rules: - Length is 16 - Starts with '51' or '55'

VISA card rules: - Starts with '13' or '16' or '4'

I'm reading numbers from another file seen in the code, i didn't think i'd have to include this but this is why i'm having trouble I'm not trying to skip an if statement just saying mine is impractical

This is my code:

import { createReadStream } from 'fs'
import { createInterface } from 'readline'

const lineReader = createInterface({
  input: createReadStream('data/input.txt')
})

lineReader.on('line', (creditCard: string) => {
  if ((creditCard.length === 15 && creditCard.substring(0, 1) === '37')) {
creditCard = '(AMEX) ' + creditCard + ' valid'
  } else {
return
  }
  console.log('Line from file: ', creditCard)
})
Aidan el Goste
  • 383
  • 1
  • 3
  • 23
  • I don't fully understand your problem. Are you asking for a way to simplify the logic beyond using a bunch of if statements? – YAHsaves Nov 20 '17 at 04:56
  • *if statement i'm doing is not a good way to handle* Why do you think that? – Rajesh Nov 20 '17 at 04:58
  • @Rajesh I think that because I will need to make one for each condition that changes – Aidan el Goste Nov 20 '17 at 05:00
  • @YAHsaves Yes i'm trying to make a small simple conditional to fit all of the rules of each respective card: if the conditions are met of a certain card it will append the Company name to the front of the creditCard which is a number read as a string from another file – Aidan el Goste Nov 20 '17 at 05:04
  • See my answer below – YAHsaves Nov 20 '17 at 05:04

4 Answers4

1

This is what i am doing to find credit/debit card type . But i m sure you can not skip if statement.

// declared all validators regex. 
var validators = {
      'american_express': /^3[47]/,
      'visa': /^4/,
      'mastercard': /^5[1-5]/,
      'discover': /^6011/,
      'amex_length': /^[0-9]{15}$/,
      'visa_length': /^[0-9]{16,16}$/,
      'cvv': /^[0-9]{3}$/,
      'amex_cvv': /^[0-9]{4}$/
};

// create a function to apply validations
function getCardType(cardNumber) {
     var result = "Unknown";
     if (validators.mastercard.test(cardNumber)) {
         result = "MasterCard";
     }else if (validators.visa.test(cardNumber)) {
         result = "Visa";
     }else if (validators.american_express.test(cardNumber)) {
         result = "Amex";
     }else if (validators.discover.test(cardNumber)) {
         result = "Discover";
     }
     return result;
}
Satendra
  • 6,755
  • 4
  • 26
  • 46
  • 1
    Just a pointer, instead of having hardcoded values, you can either update your `validators` object to return card type or have a new object that will have names. That way, you can make your code more generic and may even export to `DB/.json` file if you wish – Rajesh Nov 20 '17 at 05:29
  • I'm doing an exercise where i'm reading numbers from another folder and trying to get my code to figure out which company each number belongs to, just to clarify: creditCard is each line from a txt file being printed to the console. i'm trying to make my code read that file then append to the respective numbers – Aidan el Goste Nov 20 '17 at 05:44
  • just to add, this is what I would usually do under different circumstances this just doesn't work for what i'm doing – Aidan el Goste Nov 20 '17 at 05:49
  • @aidanhamilton code is to identify cards using javascript. in your case wherever you are getting cardnumber, either form text file or from any other external source you can identity its type by simply calling `getCardType()` function, also if you want to append card type before carnumber you can update the return statement of `getCardType()` i.e `return result+ " " + cardnumber` – Satendra Nov 20 '17 at 06:06
  • @Satendra I see, interesting i've actually figured it out for what i'm doing but I see why this is viable for what i'm doing – Aidan el Goste Nov 21 '17 at 02:10
  • @Satendra I won't mark it as accepted because I did something else that fixed my issue, I made an answer I can't accept it till tomorrow. I would up vote your answer but I don't have enough rep – Aidan el Goste Nov 21 '17 at 03:00
0

I'm not sure I fully understand your question, but the code below is the simplest way I can think of solving the above problem.

It uses if statements. Not sure why you'd want to avoid them.

    if(creditCard.substring(0, 1) === '13' || creditCard.substring(0, 1) === '16' || creditCard.substring(0, 1) === '4'){
      //Visa
    }else if(creditCard.length === 15){
      //AMEX
    }else if(creditCard.substring(0, 1) === '6011'){
      //Discover
    }else{
      //MasterCard
    }

If you can't see it at first, I've basically ordered the if statements in such a way that I get rid of the cards based on values specific to them.

Then I don't need to worry about comparing that card or that value down the road.

YAHsaves
  • 1,697
  • 12
  • 33
0

I also believe an if statement would be perfectly fine here, but here's an alternative way of writing it, that might be better suited if there are a large number of credit card types and you will want to extend the set of card types later.

It turns each card type into an object instance and uses an array of card types that is searched when a card number is encountered. This way, the logic determining the card type doesn't actually need to know what types are available (if this is a design goal).

class CreditCardType {
  constructor (
    public name: string,
    public validateNumber: (creditCardNumber) => boolean) {
  }
}

const CARDS: CreditCardType[] = [
  new CreditCardType('AMEX',
    (creditCardNumber) =>
      creditCardNumber.length === 15 && creditCardNumber.substring(0, 1) === '37'),
  new CreditCardType('Visa',
    (creditCardNumber) =>
      creditCardNumber.substring(0, 2) == '13')
]

So anytime you need to find out the card type for a card number you can do

function getCardType(creditCardNumber: string) {
    return CARDS.find(cardType => 
        cardType.validateNumber(creditCard)).name
)
ehrencrona
  • 6,102
  • 1
  • 18
  • 24
  • This won't work for me as i'm reading card numbers from another file: const lineReader = createInterface({ input: createReadStream('data/input.txt') }) lineReader.on('line', (creditCard: string) => { console.log('Line from file: ', creditCard) }) – Aidan el Goste Nov 20 '17 at 05:16
  • I doesn't really matter where you get the numbers from. I updated my answer to clarify this. – ehrencrona Nov 20 '17 at 05:21
  • I'm printing my numbers to the console using my initial code and i'm trying to append the company onto the code that prints into the console, this is just an exercise for practice and learning – Aidan el Goste Nov 20 '17 at 05:38
0

I have figured out my question for the most part, this will print the numbers and the numbers that fall under AMEX rules are appended (AMEX) First of all I declared a variable: company then I fixed the sub string, from creditCard.substring(0, 1) to creditCard.substring(0, 2) added in the || creditCard.substring(0, 2) === 34 then called the variable company we declared earlier company = (AMEX) ${creditCard} make sure to wrap (AMEX) ${creditCard} in back-ticks

Here is the full code-block:https://i.stack.imgur.com/Tu2FH.jpg (have to use imgur won't allow me to use back-ticks for code)

here is the console output: https://i.stack.imgur.com/k3yYk.jpg

Aidan el Goste
  • 383
  • 1
  • 3
  • 23