Skip to content

Commit 204a44b

Browse files
committed
chore: Update project structure and add initial code
1 parent a27cd0d commit 204a44b

File tree

53 files changed

+1358
-6
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+1358
-6
lines changed

.github/FUNDING.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# These are supported funding model platforms
2+
3+
github: [gabriel-logan] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4+
patreon: # Replace with a single Patreon username
5+
open_collective: # Replace with a single Open Collective username
6+
ko_fi: # Replace with a single Ko-fi username
7+
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8+
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9+
liberapay: # Replace with a single Liberapay username
10+
issuehunt: # Replace with a single IssueHunt username
11+
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
12+
polar: # Replace with a single Polar username
13+
buy_me_a_coffee: gabriellogan
14+
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

.github/workflows/kotlin-pr-check.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
name: Kotlin Pull Request Check
2+
# With maven
3+
4+
on:
5+
pull_request:
6+
branches:
7+
- main
8+
9+
workflow_dispatch:
10+
11+
jobs:
12+
checking-pr:
13+
runs-on: ubuntu-latest
14+
steps:
15+
- name: Checkout
16+
uses: actions/checkout@v2
17+
- name: Set up JDK 11
18+
uses: actions/setup-java@v2
19+
with:
20+
distribution: 'adopt'
21+
java-version: '11'
22+
- name: Build with Maven
23+
run: mvn -B package --file pom.xml
24+
- name: Run tests
25+
run: mvn test

.idea/sonarlint/issuestore/2/6/26a9a7c88872e994049900d0e758aea6deca4683

Whitespace-only changes.

.idea/sonarlint/issuestore/4/7/47099d604f5454a9f826c9bd7f6ad9311bbeb9b4

Whitespace-only changes.

.idea/sonarlint/issuestore/5/e/5e7ed05eb20df30a215289817543113eb0e8a750

Whitespace-only changes.

.idea/sonarlint/issuestore/7/e/7eb9a2b3314ef6c5ca43eccb6bc245d429b27d58

Whitespace-only changes.

.idea/sonarlint/issuestore/8/5/85cf9a1203932e1143b33e76ccceb93161ac03f0

Whitespace-only changes.

.idea/sonarlint/issuestore/b/9/b99ee3f4f26e65147657407346d01d34e468b2a3

Whitespace-only changes.

.idea/sonarlint/issuestore/c/f/cfc168c7e69bb8c84ff7d20fde0480e8a9cb85cb

Whitespace-only changes.

.idea/sonarlint/issuestore/d/6/d68bda52a2bca6a82fda6c0e6a14aa002c2b14d7

Whitespace-only changes.

.idea/sonarlint/issuestore/d/9/d962f1a1a7755aa2dd7a17dfcea05123b89ea233

Whitespace-only changes.

.idea/sonarlint/issuestore/e/8/e8b83630bafecb98399d3c08e721173b4a16b529

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/sonarlint/issuestore/index.pb

Lines changed: 21 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/sonarlint/securityhotspotstore/2/6/26a9a7c88872e994049900d0e758aea6deca4683

Whitespace-only changes.

.idea/sonarlint/securityhotspotstore/4/7/47099d604f5454a9f826c9bd7f6ad9311bbeb9b4

Whitespace-only changes.

.idea/sonarlint/securityhotspotstore/5/e/5e7ed05eb20df30a215289817543113eb0e8a750

Whitespace-only changes.

.idea/sonarlint/securityhotspotstore/7/e/7eb9a2b3314ef6c5ca43eccb6bc245d429b27d58

Whitespace-only changes.

.idea/sonarlint/securityhotspotstore/8/5/85cf9a1203932e1143b33e76ccceb93161ac03f0

Whitespace-only changes.

.idea/sonarlint/securityhotspotstore/b/9/b99ee3f4f26e65147657407346d01d34e468b2a3

Whitespace-only changes.

.idea/sonarlint/securityhotspotstore/c/f/cfc168c7e69bb8c84ff7d20fde0480e8a9cb85cb

Whitespace-only changes.

.idea/sonarlint/securityhotspotstore/d/6/d68bda52a2bca6a82fda6c0e6a14aa002c2b14d7

Whitespace-only changes.

.idea/sonarlint/securityhotspotstore/d/9/d962f1a1a7755aa2dd7a17dfcea05123b89ea233

Whitespace-only changes.

.idea/sonarlint/securityhotspotstore/e/8/e8b83630bafecb98399d3c08e721173b4a16b529

Whitespace-only changes.

.idea/sonarlint/securityhotspotstore/index.pb

Lines changed: 21 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/workspace.xml

Lines changed: 70 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pom.xml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,20 @@
8383
<artifactId>kotlin-stdlib</artifactId>
8484
<version>1.9.23</version>
8585
</dependency>
86+
<!-- JUnit Jupiter API -->
87+
<dependency>
88+
<groupId>org.junit.jupiter</groupId>
89+
<artifactId>junit-jupiter-api</artifactId>
90+
<version>5.7.0</version>
91+
<scope>test</scope>
92+
</dependency>
93+
<!-- JUnit Jupiter Engine -->
94+
<dependency>
95+
<groupId>org.junit.jupiter</groupId>
96+
<artifactId>junit-jupiter-engine</artifactId>
97+
<version>5.7.0</version>
98+
<scope>test</scope>
99+
</dependency>
86100
</dependencies>
87101

88102
</project>

src/main/kotlin/CnpjValidator.kt

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import java.util.*
2+
3+
class CnpjValidator private constructor() {
4+
init {
5+
throw IllegalStateException("Utility class")
6+
}
7+
8+
companion object {
9+
private fun calculateFirstVerifier(cnpjBase: IntArray): Int {
10+
val weight = intArrayOf(5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2)
11+
var sum = 0
12+
13+
for (i in 0..11) {
14+
sum += cnpjBase[i] * weight[i]
15+
}
16+
val remainder = sum % 11
17+
18+
return if (remainder < 2) 0 else 11 - remainder
19+
}
20+
21+
private fun calculateSecondVerifier(cnpjBase: IntArray, firstVerifier: Int): Int {
22+
val weight = intArrayOf(6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2)
23+
var sum = 0
24+
25+
for (i in 0..11) {
26+
sum += cnpjBase[i] * weight[i]
27+
}
28+
sum += firstVerifier * weight[12]
29+
30+
val remainder = sum % 11
31+
32+
return if (remainder < 2) 0 else 11 - remainder
33+
}
34+
35+
@JvmStatic
36+
fun cnpjIsValid(cnpj: String?): Boolean {
37+
if (cnpj.isNullOrEmpty()) {
38+
throw NullPointerException("CNPJ cannot be null or empty")
39+
}
40+
41+
val cnpjClean = cnpj.replace("\\D".toRegex(), "")
42+
43+
if (cnpjClean.isEmpty()) {
44+
return false
45+
}
46+
47+
if (cnpjClean.length != 14) {
48+
return false
49+
}
50+
51+
// Convert the string to an array of integers
52+
val cnpjArray = cnpjClean.chars().map { codePoint: Int -> Character.getNumericValue(codePoint) }.toArray()
53+
54+
// Calculate the first verifier and second verifier
55+
val cnpjBase = Arrays.copyOfRange(cnpjArray, 0, 12)
56+
val firstVerifier = calculateFirstVerifier(cnpjBase)
57+
58+
val cnpjBaseWithFirstVerifier = cnpjBase.copyOf(cnpjBase.size + 1)
59+
cnpjBaseWithFirstVerifier[cnpjBaseWithFirstVerifier.size - 1] = firstVerifier
60+
61+
val secondVerifier = calculateSecondVerifier(cnpjBaseWithFirstVerifier, firstVerifier)
62+
63+
return cnpjArray[12] == firstVerifier && cnpjArray[13] == secondVerifier
64+
}
65+
}
66+
}

src/main/kotlin/CpfValidator.kt

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import java.util.regex.Pattern
2+
import java.util.stream.IntStream
3+
4+
class CpfValidator private constructor() {
5+
init {
6+
throw IllegalStateException("Utility class")
7+
}
8+
9+
companion object {
10+
@JvmStatic
11+
fun cpfIsValid(cpf: String?): Boolean {
12+
if (cpf.isNullOrEmpty()) {
13+
throw NullPointerException("CPF cannot be null or empty")
14+
}
15+
16+
val cpfClean = cpf.replace("\\D".toRegex(), "")
17+
18+
if (cpfClean.length != 11) {
19+
return false
20+
}
21+
22+
val pattern = Pattern.compile("(\\d)\\1{10}")
23+
val matcher = pattern.matcher(cpfClean)
24+
25+
if (matcher.find()) {
26+
return false
27+
}
28+
29+
val cpfArray = cpfClean.chars().map { codePoint: Int -> Character.getNumericValue(codePoint) }.toArray()
30+
31+
val sum1 = IntStream.range(0, 9).map { i: Int -> cpfArray[i] * (10 - i) }.sum()
32+
val sum2 = IntStream.range(0, 10).map { i: Int -> cpfArray[i] * (11 - i) }.sum()
33+
34+
val validator1 = if (sum1 % 11 < 2) 0 else 11 - (sum1 % 11)
35+
val validator2 = if (sum2 % 11 < 2) 0 else 11 - (sum2 % 11)
36+
37+
return cpfArray[9] == validator1 && cpfArray[10] == validator2
38+
}
39+
}
40+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
class CreditCardValidator private constructor() {
2+
init {
3+
throw IllegalStateException("Utility class")
4+
}
5+
6+
companion object {
7+
private const val INPUT_VALUE_CANNOT_BE_EMPTY = "Input value cannot be empty."
8+
9+
@JvmStatic
10+
fun isCreditCardValid(creditCard: String?): Boolean {
11+
require(!creditCard.isNullOrEmpty()) { INPUT_VALUE_CANNOT_BE_EMPTY }
12+
13+
val creditCardString = creditCard.replace("\\D".toRegex(), "")
14+
15+
if (creditCardString.length < 13 || creditCardString.length > 19) {
16+
return false
17+
}
18+
19+
var sum = 0
20+
var alternate = false
21+
22+
for (i in creditCardString.length - 1 downTo 0) {
23+
var n = creditCardString.substring(i, i + 1).toInt()
24+
25+
if (alternate) {
26+
n *= 2
27+
28+
if (n > 9) {
29+
n = (n % 10) + 1
30+
}
31+
}
32+
33+
sum += n
34+
alternate = !alternate
35+
}
36+
37+
return sum % 10 == 0
38+
}
39+
40+
@JvmStatic
41+
fun identifyFlagCard(cardNumber: String?): String {
42+
require(!cardNumber.isNullOrEmpty()) { "The input should be a string." }
43+
44+
val flags = arrayOf(
45+
arrayOf("Visa", "^4[0-9]{12}(?:[0-9]{3})?$"),
46+
arrayOf("Mastercard", "^5[1-5][0-9]{14}$"),
47+
arrayOf("American Express", "^3[47][0-9]{13}$"),
48+
arrayOf("Discover", "^6(?:011|5[0-9]{2})[0-9]{12}$"),
49+
arrayOf("JCB", "^(?:2131|1800|35[0-9]{3})[0-9]{11}$"),
50+
arrayOf("Diners Club", "^3(?:0[0-5]|[68][0-9])[0-9]{11}$"),
51+
arrayOf("Maestro", "^(?:5[0678][0-9]{2}|6304|6390|67[0-9]{2})[0-9]{12,15}$"),
52+
arrayOf("UnionPay", "^(62|88)[0-9]{14,17}$"),
53+
arrayOf("Elo", "^63[789][0-9]{13}$"),
54+
arrayOf("Hipercard", "^(3841[0-9]{12}|60[0-9]{14})$")
55+
)
56+
57+
for (flag in flags) {
58+
if (cardNumber.matches(flag[1].toRegex())) {
59+
return flag[0]
60+
}
61+
}
62+
63+
return "Unknown"
64+
}
65+
}
66+
}

0 commit comments

Comments
 (0)