Skip to content

Commit

Permalink
chore: Update project structure and add initial code
Browse files Browse the repository at this point in the history
  • Loading branch information
gabriel-logan committed Jul 10, 2024
1 parent a27cd0d commit 204a44b
Show file tree
Hide file tree
Showing 53 changed files with 1,358 additions and 6 deletions.
14 changes: 14 additions & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# These are supported funding model platforms

github: [gabriel-logan] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
polar: # Replace with a single Polar username
buy_me_a_coffee: gabriellogan
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
25 changes: 25 additions & 0 deletions .github/workflows/kotlin-pr-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: Kotlin Pull Request Check
# With maven

on:
pull_request:
branches:
- main

workflow_dispatch:

jobs:
checking-pr:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up JDK 11
uses: actions/setup-java@v2
with:
distribution: 'adopt'
java-version: '11'
- name: Build with Maven
run: mvn -B package --file pom.xml
- name: Run tests
run: mvn test
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 21 additions & 1 deletion .idea/sonarlint/issuestore/index.pb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
22 changes: 21 additions & 1 deletion .idea/sonarlint/securityhotspotstore/index.pb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

70 changes: 70 additions & 0 deletions .idea/workspace.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,20 @@
<artifactId>kotlin-stdlib</artifactId>
<version>1.9.23</version>
</dependency>
<!-- JUnit Jupiter API -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.7.0</version>
<scope>test</scope>
</dependency>
<!-- JUnit Jupiter Engine -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.7.0</version>
<scope>test</scope>
</dependency>
</dependencies>

</project>
66 changes: 66 additions & 0 deletions src/main/kotlin/CnpjValidator.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import java.util.*

class CnpjValidator private constructor() {
init {
throw IllegalStateException("Utility class")
}

companion object {
private fun calculateFirstVerifier(cnpjBase: IntArray): Int {
val weight = intArrayOf(5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2)
var sum = 0

for (i in 0..11) {
sum += cnpjBase[i] * weight[i]
}
val remainder = sum % 11

return if (remainder < 2) 0 else 11 - remainder
}

private fun calculateSecondVerifier(cnpjBase: IntArray, firstVerifier: Int): Int {
val weight = intArrayOf(6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2)
var sum = 0

for (i in 0..11) {
sum += cnpjBase[i] * weight[i]
}
sum += firstVerifier * weight[12]

val remainder = sum % 11

return if (remainder < 2) 0 else 11 - remainder
}

@JvmStatic
fun cnpjIsValid(cnpj: String?): Boolean {
if (cnpj.isNullOrEmpty()) {
throw NullPointerException("CNPJ cannot be null or empty")
}

val cnpjClean = cnpj.replace("\\D".toRegex(), "")

if (cnpjClean.isEmpty()) {
return false
}

if (cnpjClean.length != 14) {
return false
}

// Convert the string to an array of integers
val cnpjArray = cnpjClean.chars().map { codePoint: Int -> Character.getNumericValue(codePoint) }.toArray()

// Calculate the first verifier and second verifier
val cnpjBase = Arrays.copyOfRange(cnpjArray, 0, 12)
val firstVerifier = calculateFirstVerifier(cnpjBase)

val cnpjBaseWithFirstVerifier = cnpjBase.copyOf(cnpjBase.size + 1)
cnpjBaseWithFirstVerifier[cnpjBaseWithFirstVerifier.size - 1] = firstVerifier

val secondVerifier = calculateSecondVerifier(cnpjBaseWithFirstVerifier, firstVerifier)

return cnpjArray[12] == firstVerifier && cnpjArray[13] == secondVerifier
}
}
}
40 changes: 40 additions & 0 deletions src/main/kotlin/CpfValidator.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import java.util.regex.Pattern
import java.util.stream.IntStream

class CpfValidator private constructor() {
init {
throw IllegalStateException("Utility class")
}

companion object {
@JvmStatic
fun cpfIsValid(cpf: String?): Boolean {
if (cpf.isNullOrEmpty()) {
throw NullPointerException("CPF cannot be null or empty")
}

val cpfClean = cpf.replace("\\D".toRegex(), "")

if (cpfClean.length != 11) {
return false
}

val pattern = Pattern.compile("(\\d)\\1{10}")
val matcher = pattern.matcher(cpfClean)

if (matcher.find()) {
return false
}

val cpfArray = cpfClean.chars().map { codePoint: Int -> Character.getNumericValue(codePoint) }.toArray()

val sum1 = IntStream.range(0, 9).map { i: Int -> cpfArray[i] * (10 - i) }.sum()
val sum2 = IntStream.range(0, 10).map { i: Int -> cpfArray[i] * (11 - i) }.sum()

val validator1 = if (sum1 % 11 < 2) 0 else 11 - (sum1 % 11)
val validator2 = if (sum2 % 11 < 2) 0 else 11 - (sum2 % 11)

return cpfArray[9] == validator1 && cpfArray[10] == validator2
}
}
}
66 changes: 66 additions & 0 deletions src/main/kotlin/CreditCardValidator.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
class CreditCardValidator private constructor() {
init {
throw IllegalStateException("Utility class")
}

companion object {
private const val INPUT_VALUE_CANNOT_BE_EMPTY = "Input value cannot be empty."

@JvmStatic
fun isCreditCardValid(creditCard: String?): Boolean {
require(!creditCard.isNullOrEmpty()) { INPUT_VALUE_CANNOT_BE_EMPTY }

val creditCardString = creditCard.replace("\\D".toRegex(), "")

if (creditCardString.length < 13 || creditCardString.length > 19) {
return false
}

var sum = 0
var alternate = false

for (i in creditCardString.length - 1 downTo 0) {
var n = creditCardString.substring(i, i + 1).toInt()

if (alternate) {
n *= 2

if (n > 9) {
n = (n % 10) + 1
}
}

sum += n
alternate = !alternate
}

return sum % 10 == 0
}

@JvmStatic
fun identifyFlagCard(cardNumber: String?): String {
require(!cardNumber.isNullOrEmpty()) { "The input should be a string." }

val flags = arrayOf(
arrayOf("Visa", "^4[0-9]{12}(?:[0-9]{3})?$"),
arrayOf("Mastercard", "^5[1-5][0-9]{14}$"),
arrayOf("American Express", "^3[47][0-9]{13}$"),
arrayOf("Discover", "^6(?:011|5[0-9]{2})[0-9]{12}$"),
arrayOf("JCB", "^(?:2131|1800|35[0-9]{3})[0-9]{11}$"),
arrayOf("Diners Club", "^3(?:0[0-5]|[68][0-9])[0-9]{11}$"),
arrayOf("Maestro", "^(?:5[0678][0-9]{2}|6304|6390|67[0-9]{2})[0-9]{12,15}$"),
arrayOf("UnionPay", "^(62|88)[0-9]{14,17}$"),
arrayOf("Elo", "^63[789][0-9]{13}$"),
arrayOf("Hipercard", "^(3841[0-9]{12}|60[0-9]{14})$")
)

for (flag in flags) {
if (cardNumber.matches(flag[1].toRegex())) {
return flag[0]
}
}

return "Unknown"
}
}
}
Loading

0 comments on commit 204a44b

Please sign in to comment.