forked from nus-cs2103-AY1819S1/addressbook-level4
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into change-tag-colour
- Loading branch information
Showing
2 changed files
with
134 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
package seedu.address.model.loan; | ||
|
||
import static java.util.Objects.requireNonNull; | ||
import static seedu.address.commons.util.AppUtil.checkArgument; | ||
|
||
/** | ||
* Class that stores the NRIC of a person. | ||
*/ | ||
public class Nric { | ||
|
||
public static final String MESSAGE_NRIC_CONSTRAINTS = | ||
"NRIC should be Singapore issued. It may be blank. "; | ||
|
||
public static final String NRIC_VALIDATION_REGEX = "^[ST]\\d{7}[A-JZ]|[FG]\\d{7}[K-NPQRTUWX]$"; | ||
|
||
public final String nric; | ||
|
||
/** | ||
* Constructs a {@code Nric}. | ||
* | ||
* @param ic A valid nric. | ||
*/ | ||
public Nric(String ic) { | ||
requireNonNull(ic); | ||
ic = ic.toUpperCase(); | ||
checkArgument(isValidNric(ic), MESSAGE_NRIC_CONSTRAINTS); | ||
nric = ic; | ||
} | ||
|
||
/** | ||
* Returns true if a given string is a valid nric. | ||
* Precondition: test is not null. | ||
*/ | ||
public static boolean isValidNric(String test) { | ||
String ic = test.toUpperCase(); | ||
|
||
if (!ic.matches(NRIC_VALIDATION_REGEX)) { | ||
return false; | ||
} | ||
|
||
String prefix = String.valueOf(ic.charAt(0)); | ||
String checksum = String.valueOf(ic.charAt(8)); | ||
String digits = ic.substring(1, 8); | ||
|
||
int[] weights = {2, 7, 6, 5, 4, 3, 2}; | ||
int sum = 0; | ||
|
||
// Generate checksum | ||
for (int i = 0; i < digits.length(); i++) { | ||
sum += Integer.parseInt(String.valueOf(digits.charAt(i))) * weights[i]; | ||
} | ||
|
||
// Add 4 to IC issued in 21th century. This rule was designed by the Singapore government. | ||
if ("G".equals(prefix) || "T".equals(prefix)) { | ||
sum += 4; | ||
} | ||
|
||
if ("S".equals(prefix) || "T".equals(prefix)) { | ||
String[] nricCheckDigits = {"J", "Z", "I", "H", "G", "F", "E", "D", "C", "B", "A"}; | ||
return nricCheckDigits[sum % 11].equals(checksum); | ||
} else { | ||
String[] finCheckDigits = {"X", "W", "U", "T", "R", "Q", "P", "N", "M", "L", "K"}; | ||
return finCheckDigits[sum % 11].equals(checksum); | ||
} | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return nric; | ||
} | ||
|
||
@Override | ||
public boolean equals(Object other) { | ||
return other == this // short circuit if same object | ||
|| (other instanceof Nric // instanceof handles nulls | ||
&& nric.equals(((Nric) other).nric)); // state check | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return nric.hashCode(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package seedu.address.model.loan; | ||
|
||
import static org.junit.Assert.assertFalse; | ||
import static org.junit.Assert.assertTrue; | ||
|
||
import org.junit.Test; | ||
|
||
import seedu.address.testutil.Assert; | ||
|
||
public class NricTest { | ||
@Test | ||
public void constructor_null_throwsNullPointerException() { | ||
Assert.assertThrows(NullPointerException.class, () -> new Nric(null)); | ||
} | ||
|
||
@Test | ||
public void constructor_invalidNric_throwsIllegalArgumentException() { | ||
String invalidNric = ""; | ||
Assert.assertThrows(IllegalArgumentException.class, () -> new Nric(invalidNric)); | ||
} | ||
|
||
@Test | ||
public void isValidNric() { | ||
// null nric | ||
Assert.assertThrows(NullPointerException.class, () -> Nric.isValidNric(null)); | ||
|
||
// invalid nric | ||
assertFalse(Nric.isValidNric("")); // empty string | ||
assertFalse(Nric.isValidNric(" ")); // spaces only | ||
assertFalse(Nric.isValidNric("^")); // only non-alphanumeric characters | ||
assertFalse(Nric.isValidNric("njkakjsdnfa")); // contains random alphanumeric characters | ||
|
||
// Wrong checksum | ||
assertFalse(Nric.isValidNric("S1234567Z")); | ||
assertFalse(Nric.isValidNric("T1234567Z")); | ||
assertFalse(Nric.isValidNric("F1234567Z")); | ||
assertFalse(Nric.isValidNric("G1234567Z")); | ||
|
||
// valid nric | ||
assertTrue(Nric.isValidNric("S1234567D")); // IC for citizens born in 20th century | ||
assertTrue(Nric.isValidNric("T1234567J")); // IC for citizens born in 21th century | ||
assertTrue(Nric.isValidNric("F1234567N")); // Foreign IC F | ||
assertTrue(Nric.isValidNric("G1234567X")); // Foreign IC G | ||
|
||
// Inconsistant case | ||
assertTrue(Nric.isValidNric("s1234567d")); | ||
assertTrue(Nric.isValidNric("t1234567j")); | ||
assertTrue(Nric.isValidNric("f1234567N")); | ||
assertTrue(Nric.isValidNric("G1234567x")); | ||
} | ||
} |