master
  1/**
  2 * Assignment 2, COMP268 Class: CreditCard.java
  3 *
  4 * @description Provides an implementation of Luhn's algorithm
  5 * @author: mo khan Student ID: 3431709
  6 * @date Jun 9, 2019
  7 * @version 1.0
  8 */
  9package Q3;
 10
 11import java.util.*;
 12
 13public class CreditCard {
 14  private int evenSum = 0;
 15  private int oddSum = 0;
 16  private int sum = 0;
 17  private String ccNumber;
 18  private String company;
 19
 20  public CreditCard(String num) {
 21    this.ccNumber = num;
 22    this.company = this.identifyCompany(num);
 23    this.calculateSums(num);
 24  }
 25
 26  /**
 27   * Returns the sum of the even digits
 28   *
 29   * @return the sum of the even digits
 30   */
 31  public int getEvenSum() {
 32    return evenSum;
 33  }
 34
 35  /**
 36   * Returns the sum of the odd digits
 37   *
 38   * @return the sum of the odd digits
 39   */
 40  public int getOddSum() {
 41    return oddSum;
 42  }
 43
 44  /**
 45   * Returns the sum of all the digits
 46   *
 47   * @return the sum of the even and odd digits.
 48   */
 49  public int getSum() {
 50    return sum;
 51  }
 52
 53  /**
 54   * Return the credit card number
 55   *
 56   * @return the credit card number.
 57   */
 58  public String getCcNumber() {
 59    return this.ccNumber;
 60  }
 61
 62  /**
 63   * Return the company that issues this credit card number.
 64   *
 65   * @return the name of the company that owns this credit card number.
 66   */
 67  public String getCompany() {
 68    return this.company;
 69  }
 70
 71  /** @return true if the credit card # is valid, otherwise returns false. */
 72  public boolean isValid() {
 73    return this.validateCompany()
 74        && this.validateLength()
 75        && this.validateNumber()
 76        && this.validateSums()
 77        && this.isDivisibleBy10();
 78  }
 79
 80  /** @return true if the total sum is divisible by 10, otherwise returns false. */
 81  public boolean isDivisibleBy10() {
 82    return ((this.getSum()) % 10) == 0;
 83  }
 84
 85  /**
 86   * Validates the company that the credit card number belongs to.
 87   *
 88   * @return true if the card belongs to one of the described credit card company, otherwise false.
 89   */
 90  public boolean validateCompany() {
 91    return this.ccNumber.startsWith("4")
 92        || this.ccNumber.startsWith("5")
 93        || this.ccNumber.startsWith("37")
 94        || this.ccNumber.startsWith("6");
 95  }
 96
 97  /** @return true if the length of the card number is valid. */
 98  public boolean validateLength() {
 99    return this.ccNumber.length() >= 13 && this.ccNumber.length() <= 16;
100  }
101
102  /** @return true if each character in the credit card number is a digit. */
103  public boolean validateNumber() {
104    for (int i = 0; i < this.ccNumber.length(); i++)
105      if (!Character.isDigit(this.ccNumber.charAt(i))) return false;
106    return true;
107  }
108
109  /** @return true if the sum is greater than 0; */
110  public boolean validateSums() {
111    return this.evenSum > 0 && this.oddSum > 0;
112  }
113
114  private String identifyCompany(String number) {
115    if (validateCompany())
116      switch (number.charAt(0)) {
117        case '3':
118          return "American Express";
119        case '4':
120          return "Visa";
121        case '5':
122          return "MasterCard";
123        case '6':
124          return "Discover";
125      }
126
127    return "Unknown";
128  }
129
130  private void calculateSums(String number) {
131    if (!validateNumber()) return;
132
133    String reversed = this.reverseString(number);
134    for (int i = 0; i < reversed.length(); i++) {
135      int digit = this.digitFrom(reversed, i);
136      if (this.isOdd(i + 1)) this.oddSum += digit;
137      else {
138        String value = String.valueOf(digit * 2);
139        for (int j = 0; j < value.length(); j++) this.evenSum += this.digitFrom(value, j);
140      }
141    }
142
143    this.sum = this.oddSum + this.evenSum;
144  }
145
146  private String reverseString(String value) {
147    return new StringBuilder(value).reverse().toString();
148  }
149
150  private boolean isEven(int number) {
151    return number % 2 == 0;
152  }
153
154  private boolean isOdd(int number) {
155    return !this.isEven(number);
156  }
157
158  private int digitFrom(String input, int index) {
159    return Character.getNumericValue(input.charAt(index));
160  }
161
162  /**
163   * The entry point to the console application.
164   *
165   * @param args the argument vector provided to the console application.
166   */
167  public static void main(String[] args) {
168    Scanner in = new Scanner(System.in);
169    System.out.println("Enter credit card #:");
170    CreditCard creditCard = new CreditCard(in.next());
171    if (creditCard.isValid())
172      System.out.println(
173          String.format("%s is offerred by %s", creditCard.getCcNumber(), creditCard.getCompany()));
174    else System.out.println(String.format("%s in invalid", creditCard.getCcNumber()));
175  }
176}