diff --git a/.gitignore b/.gitignore index 990e906..cda55c9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,31 +1,80 @@ +!*.xcodeproj/project.pbxproj +!*.xcodeproj/project.xcworkspace/ +!*.xcodeproj/xcshareddata/ +!*.xcworkspace/contents.xcworkspacedata !/gradle/wrapper/gradle-wrapper.jar +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 +$RECYCLE.BIN/ +**/xcshareddata/WorkspaceSettings.xcsettings *.aab *.ap_ *.apk +*.cab *.class *.ctxt +*.dSYM +*.dSYM.zip *.dex *.ear +*.hmap *.hprof +*.icloud *.iml +*.ipa *.ipr *.iws *.jar *.jks *.keystore +*.lnk *.log +*.mode1v3 +*.mode2v3 +*.moved-aside +*.msi +*.msix +*.msm +*.msp *.nar +*.pbxuser +*.perspectivev3 *.rar +*.stackdump *.swp *.tar.gz *.war +*.xccheckout +*.xcodeproj/* +*.xcscmblueprint *.zip *~ +.AppleDB +.AppleDesktop +.AppleDouble +.DS_Store +.DocumentRevisions-V100 +.LSOverride +.Spotlight-V100 +.TemporaryItems +.Trash-* +.Trashes +.VolumeIcon.icns +._* +.accio/ +.apdisk +.build/ .classpath +.com.apple.timemachine.donotpresent .cproject .cxx/ +.directory .externalNativeBuild .externalNativeBuild/ +.fseventsd +.fuse_hidden* .gradle .gradle/ .idea/ @@ -86,15 +135,26 @@ .idea_modules/ .mtj.tmp/ .navigation/ +.nfs* .project .settings/ .signing/ +/*.gcno /*/*/build /*/*/production /*/build/ /*/local.properties /*/out /out/ +Carthage/Build/ +Dependencies/ +DerivedData/ +Icon +Network Trash Folder +Temporary Items +Thumbs.db +Thumbs.db:encryptable +[Dd]esktop.ini atlassian-ide-plugin.xml bin/ build/ @@ -104,16 +164,26 @@ com_crashlytics_export_strings.xml crashlytics-build.properties crashlytics.properties deploymentTargetDropDown.xml +ehthumbs.db +ehthumbs_vista.db fabric.properties +fastlane/Preview.html +fastlane/report.xml +fastlane/screenshots/**/*.png +fastlane/test_output gen-external-apklibs gen/ google-services.json hs_err_pid* +iOSInjectionProject/ local.properties misc.xml obj/ out/ output.json +playground.xcworkspace proguard/ render.experimental.xml -replay_pid* \ No newline at end of file +replay_pid* +timeline.xctimeline +xcuserdata/ \ No newline at end of file diff --git a/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/.library-appleMain.cinteropLibraries b/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/.library-appleMain.cinteropLibraries new file mode 100644 index 0000000..e69de29 diff --git a/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/.library-appleTest.cinteropLibraries b/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/.library-appleTest.cinteropLibraries new file mode 100644 index 0000000..e69de29 diff --git a/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/.library-iosMain.cinteropLibraries b/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/.library-iosMain.cinteropLibraries new file mode 100644 index 0000000..e69de29 diff --git a/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/.library-iosTest.cinteropLibraries b/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/.library-iosTest.cinteropLibraries new file mode 100644 index 0000000..e69de29 diff --git a/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/.library-nativeMain.cinteropLibraries b/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/.library-nativeMain.cinteropLibraries new file mode 100644 index 0000000..e69de29 diff --git a/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/.library-nativeTest.cinteropLibraries b/.kotlin/metadata/kotlinTransformedCInteropMetadataLibraries/.library-nativeTest.cinteropLibraries new file mode 100644 index 0000000..e69de29 diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlin-kotlin-stdlib-2.0.0-commonMain-2bbUHA.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlin-kotlin-stdlib-2.0.0-commonMain-2bbUHA.klib new file mode 100644 index 0000000..b467275 Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlin-kotlin-stdlib-2.0.0-commonMain-2bbUHA.klib differ diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlin-kotlin-test-2.0.0-annotationsCommonMain-24eTFQ.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlin-kotlin-test-2.0.0-annotationsCommonMain-24eTFQ.klib new file mode 100644 index 0000000..bd208c2 Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlin-kotlin-test-2.0.0-annotationsCommonMain-24eTFQ.klib differ diff --git a/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlin-kotlin-test-2.0.0-assertionsCommonMain-24eTFQ.klib b/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlin-kotlin-test-2.0.0-assertionsCommonMain-24eTFQ.klib new file mode 100644 index 0000000..8470a47 Binary files /dev/null and b/.kotlin/metadata/kotlinTransformedMetadataLibraries/org.jetbrains.kotlin-kotlin-test-2.0.0-assertionsCommonMain-24eTFQ.klib differ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..fc73b50 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2023 JetBrains s.r.o. and and respective authors and developers. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..544e7a8 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,6 @@ +plugins { + id("root.publication") + //trick: for the same plugin versions in all sub-modules + alias(libs.plugins.androidLibrary).apply(false) + alias(libs.plugins.kotlinMultiplatform).apply(false) +} diff --git a/convention-plugins/build.gradle.kts b/convention-plugins/build.gradle.kts new file mode 100644 index 0000000..5e77211 --- /dev/null +++ b/convention-plugins/build.gradle.kts @@ -0,0 +1,7 @@ +plugins { + `kotlin-dsl` +} + +dependencies { + implementation(libs.nexus.publish) +} \ No newline at end of file diff --git a/convention-plugins/settings.gradle.kts b/convention-plugins/settings.gradle.kts new file mode 100644 index 0000000..ffb42e8 --- /dev/null +++ b/convention-plugins/settings.gradle.kts @@ -0,0 +1,21 @@ +pluginManagement { + repositories { + google() + gradlePluginPortal() + mavenCentral() + } +} + +dependencyResolutionManagement { + repositories { + google() + gradlePluginPortal() + mavenCentral() + } + + versionCatalogs { + create("libs") { + from(files("../gradle/libs.versions.toml")) + } + } +} \ No newline at end of file diff --git a/convention-plugins/src/main/kotlin/module.publication.gradle.kts b/convention-plugins/src/main/kotlin/module.publication.gradle.kts new file mode 100644 index 0000000..e18c9f1 --- /dev/null +++ b/convention-plugins/src/main/kotlin/module.publication.gradle.kts @@ -0,0 +1,51 @@ +import org.gradle.api.publish.maven.MavenPublication +import org.gradle.api.tasks.bundling.Jar +import org.gradle.kotlin.dsl.`maven-publish` + +plugins { + `maven-publish` + signing +} + +publishing { + // Configure all publications + publications.withType { + // Stub javadoc.jar artifact + artifact(tasks.register("${name}JavadocJar", Jar::class) { + archiveClassifier.set("javadoc") + archiveAppendix.set(this@withType.name) + }) + + // Provide artifacts information required by Maven Central + pom { + name.set("Kotlin Multiplatform library template") + description.set("Dummy library to test deployment to Maven Central") + url.set("https://github.com/Kotlin/multiplatform-library-template") + + licenses { + license { + name.set("MIT") + url.set("https://opensource.org/licenses/MIT") + } + } + developers { + developer { + id.set("JetBrains") + name.set("JetBrains Team") + organization.set("JetBrains") + organizationUrl.set("https://www.jetbrains.com") + } + } + scm { + url.set("https://github.com/Kotlin/multiplatform-library-template") + } + } + } +} + +signing { + if (project.hasProperty("signing.gnupg.keyName")) { + useGpgCmd() + sign(publishing.publications) + } +} diff --git a/convention-plugins/src/main/kotlin/root.publication.gradle.kts b/convention-plugins/src/main/kotlin/root.publication.gradle.kts new file mode 100644 index 0000000..12e295f --- /dev/null +++ b/convention-plugins/src/main/kotlin/root.publication.gradle.kts @@ -0,0 +1,19 @@ +plugins { + id("io.github.gradle-nexus.publish-plugin") +} + +allprojects { + group = "org.jetbrains.kotlinx.multiplatform-library-template" + version = "0.0.1" +} + +nexusPublishing { + // Configure maven central repository + // https://github.com/gradle-nexus/publish-plugin#publishing-to-maven-central-via-sonatype-ossrh + repositories { + sonatype { //only for users registered in Sonatype after 24 Feb 2021 + nexusUrl.set(uri("https://s01.oss.sonatype.org/service/local/")) + snapshotRepositoryUrl.set(uri("https://s01.oss.sonatype.org/content/repositories/snapshots/")) + } + } +} diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..5e4d56d --- /dev/null +++ b/gradle.properties @@ -0,0 +1,12 @@ +#Gradle +org.gradle.jvmargs=-Xmx2048M -Dfile.encoding=UTF-8 -Dkotlin.daemon.jvm.options\="-Xmx2048M" +org.gradle.caching=true +org.gradle.configuration-cache=true +#Kotlin +kotlin.code.style=official +kotlin.js.compiler=ir +#MPP +kotlin.mpp.enableCInteropCommonization=true +#Android +android.useAndroidX=true +android.nonTransitiveRClass=true diff --git a/library/build.gradle.kts b/library/build.gradle.kts new file mode 100644 index 0000000..cbbd9cb --- /dev/null +++ b/library/build.gradle.kts @@ -0,0 +1,44 @@ +import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + +plugins { + alias(libs.plugins.kotlinMultiplatform) + alias(libs.plugins.androidLibrary) + id("module.publication") +} + +kotlin { + jvm() + androidTarget { + publishLibraryVariants("release") + @OptIn(ExperimentalKotlinGradlePluginApi::class) + compilerOptions { + jvmTarget.set(JvmTarget.JVM_1_8) + } + } + iosX64() + iosArm64() + iosSimulatorArm64() + linuxX64() + + sourceSets { + val commonMain by getting { + dependencies { + //put your multiplatform dependencies here + } + } + val commonTest by getting { + dependencies { + implementation(libs.kotlin.test) + } + } + } +} + +android { + namespace = "org.jetbrains.kotlinx.multiplatform.library.template" + compileSdk = libs.versions.android.compileSdk.get().toInt() + defaultConfig { + minSdk = libs.versions.android.minSdk.get().toInt() + } +} diff --git a/library/src/androidMain/kotlin/fibiprops.android.kt b/library/src/androidMain/kotlin/fibiprops.android.kt new file mode 100644 index 0000000..9561333 --- /dev/null +++ b/library/src/androidMain/kotlin/fibiprops.android.kt @@ -0,0 +1,2 @@ +actual val firstElement: Int = 1 +actual val secondElement: Int = 2 \ No newline at end of file diff --git a/library/src/androidUnitTest/kotlin/AndroidFibiTest.kt b/library/src/androidUnitTest/kotlin/AndroidFibiTest.kt new file mode 100644 index 0000000..481af37 --- /dev/null +++ b/library/src/androidUnitTest/kotlin/AndroidFibiTest.kt @@ -0,0 +1,10 @@ +import kotlin.test.Test +import kotlin.test.assertEquals + +class AndroidFibiTest { + + @Test + fun `test 3rd element`() { + assertEquals(3, fibi.take(3).last()) + } +} \ No newline at end of file diff --git a/library/src/commonMain/kotlin/io/github/kabirnayeem99/viminfo/VinInfo.kt b/library/src/commonMain/kotlin/io/github/kabirnayeem99/viminfo/VinInfo.kt new file mode 100644 index 0000000..4d55aac --- /dev/null +++ b/library/src/commonMain/kotlin/io/github/kabirnayeem99/viminfo/VinInfo.kt @@ -0,0 +1,11 @@ +package io.github.kabirnayeem99.viminfo + +class VinInfo { + fun someLibraryMethod(): Boolean { + return true + } +} + +fun main() { + println(VinInfo().someLibraryMethod()) +} \ No newline at end of file diff --git a/library/src/commonMain/kotlin/io/github/kabirnayeem99/viminfo/data/Manufacturers.kt b/library/src/commonMain/kotlin/io/github/kabirnayeem99/viminfo/data/Manufacturers.kt new file mode 100644 index 0000000..19f72b3 --- /dev/null +++ b/library/src/commonMain/kotlin/io/github/kabirnayeem99/viminfo/data/Manufacturers.kt @@ -0,0 +1,486 @@ +package io.github.kabirnayeem99.viminfo.data + +val manufacturers = mapOf( + "AAV" to "Volkswagen", + "AC5" to "Hyundai", + "ADD" to "Hyundai", + "AFA" to "Ford", + "AHT" to "Toyota", + "JA3" to "Mitsubishi", + "JA4" to "Mitsubishi", + "JA" to "Isuzu", + "JD" to "Daihatsu", + "JF" to "Fuji Heavy Industries (Subaru)", + "JH" to "Honda", + "JK" to "Kawasaki (motorcycles)", + "JL5" to "Mitsubishi Fuso", + "JMB" to "Mitsubishi Motors", + "JMY" to "Mitsubishi Motors", + "JMZ" to "Mazda", + "JN" to "Nissan", + "JS" to "Suzuki", + "JS0" to "Suzuki", + "JS1" to "Suzuki", + "JS8" to "Suzuki", + "JT" to "Toyota", + "JY" to "Yamaha (motorcycles)", + "KL" to "Daewoo General Motors", + "KM" to "Hyundai", + "KMY" to "Daelim (motorcycles)", + "KM1" to "Hyosung (motorcycles)", + "KN" to "Kia", + "KNM" to "Renault Samsung", + "KPA" to "SsangYong", + "KPT" to "SsangYong", + "LAE" to "Jinan Qingqi Motorcycle", + "LAN" to "Changzhou Yamasaki Motorcycle", + "LBB" to "Zhejiang Qianjiang Motorcycle (Keeway/Generic)", + "LBE" to "Beijing Hyundai", + "LBM" to "Zongshen Piaggio", + "LBP" to "Chongqing Jainshe Yamaha (motorcycles)", + "LB2" to "Geely Motorcycles", + "LCE" to "Hangzhou Chunfeng Motorcycles (CFMOTO)", + "LDC" to "Dong Feng Peugeot Citroen (DPCA)", + "LDD" to "Dandong Huanghai Automobile", + "LDN" to "SouEast Motor", + "LDY" to "Zhongtong Coach", + "LET" to "Jiangling-Isuzu Motors", + "LE4" to "Beijing Benz", + "LFB" to "FAW (busses)", + "LFG" to "Taizhou Chuanl Motorcycle Manufacturing", + "LFP" to "FAW (passenger vehicles)", + "LFT" to "FAW (trailers)", + "LFV" to "FAW-Volkswagen", + "LFW" to "FAW JieFang", + "LFY" to "Changshu Light Motorcycle Factory", + "LGB" to "Dong Feng (DFM)", + "LGH" to "Qoros (formerly Dong Feng (DFM))", + "LGX" to "BYD Auto", + "LHB" to "Beijing Automotive Industry Holding", + "LH1" to "FAW-Haima", + "LJC" to "JAC", + "LJ1" to "JAC", + "LKL" to "Suzhou King Long", + "LL6" to "Hunan Changfeng Manufacture Joint-Stock", + "LL8" to "Linhai (ATV)", + "LMC" to "Suzuki Hong Kong (motorcycles)", + "LPR" to "Yamaha Hong Kong (motorcycles)", + "LSG" to "SAIC General Motors", + "LSJ" to "SAIC MG", + "LSV" to "SAIC Volkswagen", + "LSY" to "Brilliance Zhonghua", + "LTV" to "Toyota Tian Jin", + "LUC" to "Guangqi Honda", + "LVS" to "Ford Chang An", + "LVV" to "Chery", + "LVZ" to "Dong Feng Sokon Motor Company (DFSK)", + "LZM" to "MAN", + "LZE" to "Isuzu Guangzhou", + "LZG" to "Shaanxi Automobile Group", + "LZP" to "Zhongshan Guochi Motorcycle (Baotian)", + "LZY" to "Yutong Zhengzhou", + "LZZ" to "Chongqing Shuangzing Mech & Elec (Howo)", + "L4B" to "Xingyue Group (motorcycles)", + "L5C" to "KangDi (ATV)", + "L5K" to "Zhejiang Yongkang Easy Vehicle", + "L5N" to "Zhejiang Taotao (ATV & motorcycles)", + "L5Y" to "Merato Motorcycle Taizhou Zhongneng", + "L85" to "Zhejiang Yongkang Huabao Electric Appliance", + "L8X" to "Zhejiang Summit Huawin Motorcycle", + "MAB" to "Mahindra & Mahindra", + "MAC" to "Mahindra & Mahindra", + "MAJ" to "Ford", + "MAK" to "Honda Siel Cars", + "MAL" to "Hyundai", + "MAT" to "Tata Motors", + "MA1" to "Mahindra & Mahindra", + "MA3" to "Suzuki (Maruti)", + "MA6" to "GM", + "MA7" to "Mitsubishi (formerly Honda)", + "MBH" to "Suzuki (Maruti)", + "MBJ" to "Toyota", + "MBR" to "Mercedes-Benz", + "MB1" to "Ashok Leyland", + "MCA" to "Fiat", + "MCB" to "GM", + "MC2" to "Volvo Eicher commercial vehicles limited.", + "MDH" to "Nissan", + "MD2" to "Bajaj Auto", + "MD9" to "Shuttle Cars", + "MEE" to "Renault", + "MEX" to "Volkswagen", + "MHF" to "Toyota", + "MHR" to "Honda", + "MLC" to "Suzuki", + "MLH" to "Honda", + "MMB" to "Mitsubishi", + "MMC" to "Mitsubishi", + "MMM" to "Chevrolet", + "MMS" to "Suzuki", + "MMT" to "Mitsubishi", + "MM8" to "Mazda", + "MNB" to "Ford", + "MNT" to "Nissan", + "MPA" to "Isuzu", + "MP1" to "Isuzu", + "MRH" to "Honda", + "MR0" to "Toyota", + "MS0" to "KIA", + "MS3" to "Suzuki Motor Co., Ltd.", + "NLA" to "Honda", + "NLE" to "Mercedes-Benz Truck", + "NLH" to "Hyundai Assan", + "NLT" to "TEMSA", + "NMB" to "Mercedes-Benz Buses", + "NMC" to "BMC", + "NM0" to "Ford", + "NM4" to "Tofaş", + "NMT" to "Toyota", + "NNA" to "Isuzu", + "PE1" to "Ford", + "PE3" to "Mazda", + "PL1" to "Proton", + "PNA" to "NAZA (Peugeot)", + "RA1" to "Steyr Trucks International FZE", + "RFB" to "Kymco", + "RFG" to "Sanyang SYM", + "RFL" to "Adly", + "RFT" to "CPI", + "RF3" to "Aeon Motor", + "SAD" to "Jaguar (F-Pace)", + "SAL" to "Land Rover", + "SAJ" to "Jaguar", + "SAR" to "Rover", + "SB1" to "Toyota", + "SBM" to "McLaren", + "SCA" to "Rolls Royce", + "SCB" to "Bentley", + "SCC" to "Lotus Cars", + "SCE" to "DeLorean Motor Cars N. Ireland", + "SCF" to "Aston", + "SDB" to "Peugeot (formerly Talbot)", + "SED" to "General Motors Luton Plant", + "SEY" to "LDV", + "SFA" to "Ford", + "SFD" to "Alexander Dennis", + "SHH" to "Honda", + "SHS" to "Honda", + "SJN" to "Nissan", + "SKF" to "Vauxhall", + "SLP" to "JCB Research", + "SMT" to "Triumph Motorcycles", + "SUF" to "Fiat Auto", + "SUL" to "FSC", + "SUP" to "FSO-Daewoo", + "SUU" to "Solaris Bus & Coach", + "SWV" to "TA-NO", + "TCC" to "Micro Compact Car AG (smart 1998-1999)", + "TDM" to "QUANTYA Swiss Electric Movement", + "TK9" to "SOR buses", + "TMA" to "Hyundai Motor Manufacturing", + "TMB" to "Škoda", + "TMK" to "Karosa", + "TMP" to "Škoda trolleybuses", + "TMT" to "Tatra", + "TM9" to "Škoda trolleybuses", + "TNE" to "TAZ", + "TN9" to "Karosa", + "TRA" to "Ikarus Bus", + "TRU" to "Audi", + "TSE" to "Ikarus Egyedi Autobuszgyar", + "TSM" to "Suzuki", + "TW1" to "Toyota Caetano", + "TYA" to "Mitsubishi Trucks", + "TYB" to "Mitsubishi Trucks", + "UU1" to "Renault Dacia", + "UU3" to "ARO", + "UU6" to "Daewoo", + "U5Y" to "Kia Motors", + "U6Y" to "Kia Motors", + "VAG" to "Magna Steyr Puch", + "VAN" to "MAN", + "VBK" to "KTM (Motorcycles)", + "VF1" to "Renault", + "VF2" to "Renault", + "VF3" to "Peugeot", + "VF4" to "Talbot", + "VF6" to "Renault (Trucks & Buses)", + "VF7" to "Citroën", + "VF8" to "Matra", + "VF9" to "Bugatti", + "795" to "Bugatti", + "VG5" to "MBK (motorcycles)", + "VLU" to "Scania", + "VN1" to "SOVAB", + "VNE" to "Irisbus", + "VNK" to "Toyota", + "VNV" to "Renault-Nissan", + "VSA" to "Mercedes-Benz", + "VSE" to "Suzuki (Santana Motors)", + "VSK" to "Nissan", + "VSS" to "SEAT", + "VSX" to "Opel", + "VS6" to "Ford", + "VS7" to "Citroën", + "VS9" to "Carrocerias Ayats", + "VTH" to "Derbi (motorcycles)", + "VTL" to "Yamaha (motorcycles)", + "VTT" to "Suzuki (motorcycles)", + "VV9" to "TAURO", + "VWA" to "Nissan", + "VWV" to "Volkswagen", + "VX1" to "Zastava / Yugo Serbia", + "WAG" to "Neoplan", + "WAU" to "Audi", + "WA1" to "Audi SUV", + "WBA" to "BMW", + "WBS" to "BMW M", + "WBW" to "BMW", + "WBY" to "BMW", + "WDA" to "Daimler", + "WDB" to "Mercedes-Benz", + "WDC" to "DaimlerChrysler", + "WDD" to "Mercedes-Benz", + "WDF" to "Mercedes-Benz (commercial vehicles)", + "WEB" to "Evobus GmbH (Mercedes-Bus)", + "WJM" to "Iveco Magirus", + "WF0" to "Ford", + "WKE" to "Fahrzeugwerk Bernard Krone GmbH & Co. KG", + "WKK" to "Kässbohrer/Setra", + "WMA" to "MAN", + "WME" to "smart", + "WMW" to "MINI", + "WMX" to "Mercedes-AMG", + "WP0" to "Porsche", + "WP1" to "Porsche SUV", + "W09" to "RUF", + "W0L" to "Opel", + "W0V" to "Opel", + "WUA" to "quattro GmbH", + "WVG" to "Volkswagen MPV/SUV", + "WVW" to "Volkswagen", + "WV1" to "Volkswagen Commercial Vehicles", + "WV2" to "Volkswagen Bus/Van", + "WV3" to "Volkswagen Trucks", + "XLB" to "Volvo (NedCar)", + "XLE" to "Scania", + "XLR" to "DAF (trucks)", + "XL9" to "Spyker", + "363" to "Spyker", + "XMC" to "Mitsubishi (NedCar)", + "XTA" to "Lada/AvtoVAZ", + "XTC" to "KAMAZ", + "XTH" to "GAZ", + "XTT" to "UAZ/Sollers", + "XTY" to "LiAZ", + "XUF" to "General Motors", + "XUU" to "AvtoTor (General Motors SKD)", + "XW8" to "Volkswagen Group", + "XWB" to "UZ-Daewoo", + "XWE" to "AvtoTor (Hyundai-Kia SKD)", + "X1M" to "PAZ", + "X4X" to "AvtoTor (BMW SKD)", + "X7L" to "Renault AvtoFramos", + "X7M" to "Hyundai TagAZ", + "YBW" to "Volkswagen", + "YB1" to "Volvo Trucks", + "YCM" to "Mazda", + "YE2" to "Van Hool (buses)", + "YH2" to "BRP (Lynx snowmobiles)", + "YK1" to "Saab-Valmet", + "YS2" to "Scania AB", + "YS3" to "Saab", + "YS4" to "Scania Bus", + "YTN" to "Saab NEVS", + "YT9" to "Koenigsegg", + "007" to "Koenigsegg", + "034" to "Carvia", + "YU7" to "Husaberg (motorcycles)", + "YV1" to "Volvo Cars", + "YV4" to "Volvo Cars", + "YV2" to "Volvo Trucks", + "YV3" to "Volvo Buses", + "Y3M" to "MAZ", + "Y6D" to "Zaporozhets/AvtoZAZ", + "ZAA" to "Autobianchi", + "ZAM" to "Maserati", + "ZAP" to "Piaggio/Vespa/Gilera", + "ZAR" to "Alfa Romeo", + "ZBN" to "Benelli", + "ZCG" to "Cagiva SpA / MV Agusta", + "ZCF" to "Iveco", + "ZDM" to "Ducati Motor Holdings SpA", + "ZDF" to "Ferrari Dino", + "ZD0" to "Yamaha", + "ZD3" to "Beta Motor", + "ZD4" to "Aprilia", + "ZFA" to "Fiat", + "ZFC" to "Fiat V.I.", + "ZFF" to "Ferrari", + "ZGU" to "Moto Guzzi", + "ZHW" to "Lamborghini", + "ZJM" to "Malaguti", + "ZJN" to "Innocenti", + "ZKH" to "Husqvarna Motorcycles", + "ZLA" to "Lancia", + "ZOM" to "OM", + "Z8M" to "Marussia", + "1B3" to "Dodge", + "1C3" to "Chrysler", + "1C4" to "Chrysler", + "1C6" to "Chrysler", + "1D3" to "Dodge", + "1FA" to "Ford Motor Company", + "1FB" to "Ford Motor Company", + "1FC" to "Ford Motor Company", + "1FD" to "Ford Motor Company", + "1FM" to "Ford Motor Company", + "1FT" to "Ford Motor Company", + "1FU" to "Freightliner", + "1FV" to "Freightliner", + "1F9" to "FWD Corp.", + "1G" to "General Motors", + "1GC" to "Chevrolet Truck", + "1GT" to "GMC Truck", + "1G1" to "Chevrolet", + "1G2" to "Pontiac", + "1G3" to "Oldsmobile", + "1G4" to "Buick", + "1G6" to "Cadillac", + "1G8" to "Saturn", + "1GM" to "Pontiac", + "1GY" to "Cadillac", + "1H" to "Honda", + "1HD" to "Harley-Davidson", + "1J4" to "Jeep", + "1J8" to "Jeep", + "1L" to "Lincoln", + "1ME" to "Mercury", + "1M1" to "Mack Truck", + "1M2" to "Mack Truck", + "1M3" to "Mack Truck", + "1M4" to "Mack Truck", + "1M9" to "Mynatt Truck & Equipment", + "1N" to "Nissan", + "1NX" to "NUMMI", + "1P3" to "Plymouth", + "1R9" to "Roadrunner Hay Squeeze", + "1VW" to "Volkswagen", + "1XK" to "Kenworth", + "1XP" to "Peterbilt", + "1YV" to "Mazda (AutoAlliance International)", + "1ZV" to "Ford (AutoAlliance International)", + "2A4" to "Chrysler", + "2BP" to "Bombardier Recreational Products", + "2B3" to "Dodge", + "2B7" to "Dodge", + "2C3" to "Chrysler", + "2CN" to "CAMI", + "2D3" to "Dodge", + "2FA" to "Ford Motor Company", + "2FB" to "Ford Motor Company", + "2FC" to "Ford Motor Company", + "2FM" to "Ford Motor Company", + "2FT" to "Ford Motor Company", + "2FU" to "Freightliner", + "2FV" to "Freightliner", + "2FZ" to "Sterling", + "2Gx" to "General Motors", + "2G1" to "Chevrolet", + "2G2" to "Pontiac", + "2G3" to "Oldsmobile", + "2G4" to "Buick", + "2G9" to "Gnome Homes", + "2HG" to "Honda", + "2HK" to "Honda", + "2HJ" to "Honda", + "2HM" to "Hyundai", + "2M" to "Mercury", + "2NV" to "Nova Bus", + "2P3" to "Plymouth", + "2T" to "Toyota", + "2TP" to "Triple E LTD", + "2V4" to "Volkswagen", + "2V8" to "Volkswagen", + "2WK" to "Western Star", + "2WL" to "Western Star", + "2WM" to "Western Star", + "3C4" to "Chrysler", + "3D3" to "Dodge", + "3D4" to "Dodge", + "3FA" to "Ford Motor Company", + "3FE" to "Ford Motor Company", + "3G" to "General Motors", + "3H" to "Honda", + "3JB" to "BRP (all-terrain vehicles)", + "3MD" to "Mazda", + "3MZ" to "Mazda", + "3N" to "Nissan", + "3P3" to "Plymouth", + "3VW" to "Volkswagen", + "4F" to "Mazda", + "4JG" to "Mercedes-Benz", + "4M" to "Mercury", + "4RK" to "Nova Bus", + "4S" to "Subaru-Isuzu Automotive", + "4T" to "Toyota", + "4T9" to "Lumen Motors", + "4UF" to "Arctic Cat Inc.", + "4US" to "BMW", + "4UZ" to "Frt-Thomas Bus", + "4V1" to "Volvo", + "4V2" to "Volvo", + "4V3" to "Volvo", + "4V4" to "Volvo", + "4V5" to "Volvo", + "4V6" to "Volvo", + "4VL" to "Volvo", + "4VM" to "Volvo", + "4VZ" to "Volvo", + "538" to "Zero Motorcycles", + "5F" to "Honda Alabama", + "5J" to "Honda Ohio", + "5L" to "Lincoln", + "5N1" to "Nissan", + "5NP" to "Hyundai", + "5T" to "Toyota - trucks", + "5YJ" to "Tesla, Inc.", + "6AB" to "MAN", + "6F4" to "Nissan Motor Company", + "6F5" to "Kenworth", + "6FP" to "Ford Motor Company", + "6G1" to "General Motors-Holden (post Nov 2002)", + "6G2" to "Pontiac (GTO & G8)", + "6H8" to "General Motors-Holden (pre Nov 2002)", + "6MM" to "Mitsubishi Motors", + "6T1" to "Toyota Motor Corporation", + "6U9" to "Privately Imported car", + "8AD" to "Peugeot", + "8AF" to "Ford Motor Company", + "8AG" to "Chevrolet", + "8AJ" to "Toyota", + "8AK" to "Suzuki", + "8AP" to "Fiat", + "8AW" to "Volkswagen", + "8A1" to "Renault", + "8GD" to "Peugeot", + "8GG" to "Chevrolet", + "935" to "Citroën", + "936" to "Peugeot", + "93H" to "Honda", + "93R" to "Toyota", + "93U" to "Audi", + "93V" to "Audi", + "93X" to "Mitsubishi Motors", + "93Y" to "Renault", + "94D" to "Nissan", + "9BD" to "Fiat", + "9BF" to "Ford Motor Company", + "9BG" to "Chevrolet", + "9BM" to "Mercedes-Benz", + "9BR" to "Toyota", + "9BS" to "Scania", + "9BW" to "Volkswagen", + "9FB" to "Renault", + "WB1" to "BMW Motorrad of North America", +) \ No newline at end of file diff --git a/library/src/commonMain/kotlin/io/github/kabirnayeem99/viminfo/data/Years.kt b/library/src/commonMain/kotlin/io/github/kabirnayeem99/viminfo/data/Years.kt new file mode 100644 index 0000000..61f4408 --- /dev/null +++ b/library/src/commonMain/kotlin/io/github/kabirnayeem99/viminfo/data/Years.kt @@ -0,0 +1,34 @@ +package io.github.kabirnayeem99.viminfo.data + +val years = mapOf( + 'N' to 1992, + 'P' to 1993, + 'R' to 1994, + 'S' to 1995, + 'T' to 1996, + 'V' to 1997, + 'W' to 1998, + 'X' to 1999, + 'Y' to 2000, + '1' to 2001, + '2' to 2002, + '3' to 2003, + '4' to 2004, + '5' to 2005, + '6' to 2006, + '7' to 2007, + '8' to 2008, + '9' to 2009, + 'A' to 2010, + 'B' to 2011, + 'C' to 2012, + 'D' to 2013, + 'E' to 2014, + 'F' to 2015, + 'G' to 2016, + 'H' to 2017, + 'J' to 2018, + 'K' to 2019, + 'L' to 2020, + 'M' to 2021, +) \ No newline at end of file diff --git a/library/src/commonMain/kotlin/io/github/kabirnayeem99/viminfo/entities/Vin.kt b/library/src/commonMain/kotlin/io/github/kabirnayeem99/viminfo/entities/Vin.kt new file mode 100644 index 0000000..22392de --- /dev/null +++ b/library/src/commonMain/kotlin/io/github/kabirnayeem99/viminfo/entities/Vin.kt @@ -0,0 +1,132 @@ +package io.github.kabirnayeem99.viminfo.entities + +import io.github.kabirnayeem99.viminfo.data.manufacturers +import io.github.kabirnayeem99.viminfo.data.years +import io.github.kabirnayeem99.viminfo.exceptions.InvalidVinLengthException +import io.github.kabirnayeem99.viminfo.exceptions.InvalidVinRegionCharException +import io.github.kabirnayeem99.viminfo.exceptions.InvalidVinYearException + +data class Vin( + val number: String, + private val normalizedNumber: String, + val wmi: String, + val vds: String, + val vis: String, + val isExtended: Boolean, + private var vehicleInfo: Map = emptyMap(), +) { + + private val validVinRegex = "^[a-zA-Z0-9]+$".toRegex() + + val isValid: Boolean + get() = validVinRegex.matches(normalizedNumber) && normalizedNumber.length == 17 + + + val year: Int + get() = years[yearCharacter] ?: throw InvalidVinYearException(yearCharacter) + + val region: String + get() { + val regionId = + normalizedNumber.getOrNull(0)?.toString() ?: throw InvalidVinLengthException( + normalizedNumber + ) + + val regexAF = Regex("[A-H]", RegexOption.IGNORE_CASE) + val regexAS = Regex("[J-R]", RegexOption.IGNORE_CASE) + val regexEU = Regex("[S-Z]", RegexOption.IGNORE_CASE) + val regexNA = Regex("[1-5]", RegexOption.IGNORE_CASE) + val regexOC = Regex("[6-7]", RegexOption.IGNORE_CASE) + val regexSA = Regex("[8-9]", RegexOption.IGNORE_CASE) + + return when { + regexAF.containsMatchIn(regionId) -> "AF" + regexAS.containsMatchIn(regionId) -> "AS" + regexEU.containsMatchIn(regionId) -> "EU" + regexNA.containsMatchIn(regionId) -> "NA" + regexOC.containsMatchIn(regionId) -> "OC" + regexSA.containsMatchIn(regionId) -> "SA" + else -> throw InvalidVinRegionCharException(regionId) + } + } + + val manufacturer: String + get() { + if (wmi.isBlank()) throw InvalidVinLengthException(normalizedNumber) + return if (manufacturers.containsKey(this.wmi)) { + manufacturers[this.wmi] + ?: throw Exception("Unknown World Manufacturer Identifier (WMI): ${this.wmi.uppercase()}") + } else { + val alternativeWmiId = this.wmi.substring(0, 2) + if (manufacturers.containsKey(alternativeWmiId)) { + manufacturers[alternativeWmiId] + ?: throw Exception("Unknown World Manufacturer Identifier (WMI): ${alternativeWmiId.uppercase()}") + } else { + throw Exception("Unknown World Manufacturer Identifier (WMI): ${this.wmi.uppercase()}") + } + } + + } + + val checksum: Char + get() = if (region != "EU") normalizedNumber[8] else throw Exception("No CheckSum for the Europe region.") + + val assemblyPlant: Char + get() = normalizedNumber.getOrNull(10) + ?: throw Exception("Wrong VIN Number length: ${normalizedNumber.length}") + + val serialNumber: String + get() = normalizedNumber.substring(12, 17) + +// suspend fun + // Future _fetchExtendedVehicleInfo() async { + // if (this._vehicleInfo.isEmpty && extended == true) { + // this._vehicleInfo = await NHTSA.decodeVinValues(this.number); + // } + // } + // + // /// Get the Make of the vehicle from the NHTSA database if [extended] mode + // /// is enabled. + // Future getMakeAsync() async { + // await _fetchExtendedVehicleInfo(); + // return this._vehicleInfo['Make']; + // } + // + // /// Get the Model of the vehicle from the NHTSA database if [extended] mode + // /// is enabled. + // Future getModelAsync() async { + // await _fetchExtendedVehicleInfo(); + // return this._vehicleInfo['Model']; + // } + // + // /// Get the Vehicle Type from the NHTSA database if [extended] mode is + // /// enabled. + // Future getVehicleTypeAsync() async { + // await _fetchExtendedVehicleInfo(); + // return this._vehicleInfo['VehicleType']; + // } + + + private val yearCharacter: Char + get() = normalizedNumber.getOrNull(9) ?: throw Exception("Invalid VIN Length") + + + override fun toString() = this.wmi + this.vds + this.vis + + companion object { + + private fun String.normalize() = uppercase().replaceAfter("-", "") + + fun fromNumber(number: String, isExtended: Boolean = false): Vin { + val normalizedNumber = number.normalize() + return Vin( + number = number, + isExtended = isExtended, + normalizedNumber = normalizedNumber, + wmi = if (number.length >= 3) normalizedNumber.substring(0, 3) else "", + vds = if (number.length >= 9) normalizedNumber.substring(3, 9) else "", + vis = if (number.length >= 17) normalizedNumber.substring(9, 17) else "", + ) + } + } +} \ No newline at end of file diff --git a/library/src/commonMain/kotlin/io/github/kabirnayeem99/viminfo/exceptions/InvalidVinLengthException.kt b/library/src/commonMain/kotlin/io/github/kabirnayeem99/viminfo/exceptions/InvalidVinLengthException.kt new file mode 100644 index 0000000..b208ae9 --- /dev/null +++ b/library/src/commonMain/kotlin/io/github/kabirnayeem99/viminfo/exceptions/InvalidVinLengthException.kt @@ -0,0 +1,7 @@ +package io.github.kabirnayeem99.viminfo.exceptions + +import java.lang.Exception + +class InvalidVinLengthException(vin: String) : + Exception("Invalid VIN length: ${vin.length}. Expected length is 17 characters. Ensure that the VIN is 17 characters long, which is the standard length for VINs. Please check the VIN and try again.") { +} \ No newline at end of file diff --git a/library/src/commonMain/kotlin/io/github/kabirnayeem99/viminfo/exceptions/InvalidVinRegionCharException.kt b/library/src/commonMain/kotlin/io/github/kabirnayeem99/viminfo/exceptions/InvalidVinRegionCharException.kt new file mode 100644 index 0000000..3e3e979 --- /dev/null +++ b/library/src/commonMain/kotlin/io/github/kabirnayeem99/viminfo/exceptions/InvalidVinRegionCharException.kt @@ -0,0 +1,4 @@ +package io.github.kabirnayeem99.viminfo.exceptions + +class InvalidVinRegionCharException(regionChar: String) : + Exception("Invalid region ID: '$regionChar'. The first character of the VIN should be within the ranges A-H, J-R, S-Z, or 1-9 to indicate a valid region. Please check the VIN and try again.") diff --git a/library/src/commonMain/kotlin/io/github/kabirnayeem99/viminfo/exceptions/InvalidVinYearException.kt b/library/src/commonMain/kotlin/io/github/kabirnayeem99/viminfo/exceptions/InvalidVinYearException.kt new file mode 100644 index 0000000..2f2a978 --- /dev/null +++ b/library/src/commonMain/kotlin/io/github/kabirnayeem99/viminfo/exceptions/InvalidVinYearException.kt @@ -0,0 +1,4 @@ +package io.github.kabirnayeem99.viminfo.exceptions + +class InvalidVinYearException(yearChar: Char) : + Exception("Invalid model year character: '$yearChar'. Expected a valid year character within the allowed range. Please check the VIN and try again.") \ No newline at end of file diff --git a/library/src/commonMain/kotlin/io/github/kabirnayeem99/viminfo/network/NhtsaUsaApi.kt b/library/src/commonMain/kotlin/io/github/kabirnayeem99/viminfo/network/NhtsaUsaApi.kt new file mode 100644 index 0000000..3c9f9e2 --- /dev/null +++ b/library/src/commonMain/kotlin/io/github/kabirnayeem99/viminfo/network/NhtsaUsaApi.kt @@ -0,0 +1,4 @@ +package io.github.kabirnayeem99.viminfo.network + +class NhtsaUsaApi { +} \ No newline at end of file diff --git a/library/src/commonTest/kotlin/FibiTest.kt b/library/src/commonTest/kotlin/FibiTest.kt new file mode 100644 index 0000000..1b0c5db --- /dev/null +++ b/library/src/commonTest/kotlin/FibiTest.kt @@ -0,0 +1,10 @@ +import kotlin.test.Test +import kotlin.test.assertEquals + +class FibiTest { + + @Test + fun `test 3rd element`() { + assertEquals(firstElement + secondElement, fibi.take(3).last()) + } +} \ No newline at end of file diff --git a/library/src/iosMain/kotlin/fibiprops.ios.kt b/library/src/iosMain/kotlin/fibiprops.ios.kt new file mode 100644 index 0000000..8fb1aa0 --- /dev/null +++ b/library/src/iosMain/kotlin/fibiprops.ios.kt @@ -0,0 +1,2 @@ +actual val firstElement: Int = 3 +actual val secondElement: Int = 4 \ No newline at end of file diff --git a/library/src/iosTest/kotlin/IosFibiTest.kt b/library/src/iosTest/kotlin/IosFibiTest.kt new file mode 100644 index 0000000..778d22a --- /dev/null +++ b/library/src/iosTest/kotlin/IosFibiTest.kt @@ -0,0 +1,10 @@ +import kotlin.test.Test +import kotlin.test.assertEquals + +class IosFibiTest { + + @Test + fun `test 3rd element`() { + assertEquals(7, fibi.take(3).last()) + } +} \ No newline at end of file diff --git a/library/src/jvmMain/kotlin/fibiprops.jvm.kt b/library/src/jvmMain/kotlin/fibiprops.jvm.kt new file mode 100644 index 0000000..b1d5404 --- /dev/null +++ b/library/src/jvmMain/kotlin/fibiprops.jvm.kt @@ -0,0 +1,2 @@ +actual val firstElement: Int = 2 +actual val secondElement: Int = 3 \ No newline at end of file diff --git a/library/src/jvmTest/kotlin/JvmFibiTest.kt b/library/src/jvmTest/kotlin/JvmFibiTest.kt new file mode 100644 index 0000000..09dedb1 --- /dev/null +++ b/library/src/jvmTest/kotlin/JvmFibiTest.kt @@ -0,0 +1,10 @@ +import kotlin.test.Test +import kotlin.test.assertEquals + +class JvmFibiTest { + + @Test + fun `test 3rd element`() { + assertEquals(5, fibi.take(3).last()) + } +} \ No newline at end of file diff --git a/library/src/linuxX64Main/kotlin/fibiprops.linuxX64.kt b/library/src/linuxX64Main/kotlin/fibiprops.linuxX64.kt new file mode 100644 index 0000000..9c84ba4 --- /dev/null +++ b/library/src/linuxX64Main/kotlin/fibiprops.linuxX64.kt @@ -0,0 +1,2 @@ +actual val firstElement: Int = 3 +actual val secondElement: Int = 5 \ No newline at end of file diff --git a/library/src/linuxX64Test/kotlin/LinuxFibiTest.kt b/library/src/linuxX64Test/kotlin/LinuxFibiTest.kt new file mode 100644 index 0000000..b08b96c --- /dev/null +++ b/library/src/linuxX64Test/kotlin/LinuxFibiTest.kt @@ -0,0 +1,10 @@ +import kotlin.test.Test +import kotlin.test.assertEquals + +class LinuxFibiTest { + + @Test + fun `test 3rd element`() { + assertEquals(8, fibi.take(3).last()) + } +} diff --git a/src/main/kotlin/io/github/kabirnayeem99/viminfo/VinInfo.kt b/src/main/kotlin/io/github/kabirnayeem99/viminfo/VinInfo.kt new file mode 100644 index 0000000..4d55aac --- /dev/null +++ b/src/main/kotlin/io/github/kabirnayeem99/viminfo/VinInfo.kt @@ -0,0 +1,11 @@ +package io.github.kabirnayeem99.viminfo + +class VinInfo { + fun someLibraryMethod(): Boolean { + return true + } +} + +fun main() { + println(VinInfo().someLibraryMethod()) +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/kabirnayeem99/viminfo/data/Manufacturers.kt b/src/main/kotlin/io/github/kabirnayeem99/viminfo/data/Manufacturers.kt new file mode 100644 index 0000000..19f72b3 --- /dev/null +++ b/src/main/kotlin/io/github/kabirnayeem99/viminfo/data/Manufacturers.kt @@ -0,0 +1,486 @@ +package io.github.kabirnayeem99.viminfo.data + +val manufacturers = mapOf( + "AAV" to "Volkswagen", + "AC5" to "Hyundai", + "ADD" to "Hyundai", + "AFA" to "Ford", + "AHT" to "Toyota", + "JA3" to "Mitsubishi", + "JA4" to "Mitsubishi", + "JA" to "Isuzu", + "JD" to "Daihatsu", + "JF" to "Fuji Heavy Industries (Subaru)", + "JH" to "Honda", + "JK" to "Kawasaki (motorcycles)", + "JL5" to "Mitsubishi Fuso", + "JMB" to "Mitsubishi Motors", + "JMY" to "Mitsubishi Motors", + "JMZ" to "Mazda", + "JN" to "Nissan", + "JS" to "Suzuki", + "JS0" to "Suzuki", + "JS1" to "Suzuki", + "JS8" to "Suzuki", + "JT" to "Toyota", + "JY" to "Yamaha (motorcycles)", + "KL" to "Daewoo General Motors", + "KM" to "Hyundai", + "KMY" to "Daelim (motorcycles)", + "KM1" to "Hyosung (motorcycles)", + "KN" to "Kia", + "KNM" to "Renault Samsung", + "KPA" to "SsangYong", + "KPT" to "SsangYong", + "LAE" to "Jinan Qingqi Motorcycle", + "LAN" to "Changzhou Yamasaki Motorcycle", + "LBB" to "Zhejiang Qianjiang Motorcycle (Keeway/Generic)", + "LBE" to "Beijing Hyundai", + "LBM" to "Zongshen Piaggio", + "LBP" to "Chongqing Jainshe Yamaha (motorcycles)", + "LB2" to "Geely Motorcycles", + "LCE" to "Hangzhou Chunfeng Motorcycles (CFMOTO)", + "LDC" to "Dong Feng Peugeot Citroen (DPCA)", + "LDD" to "Dandong Huanghai Automobile", + "LDN" to "SouEast Motor", + "LDY" to "Zhongtong Coach", + "LET" to "Jiangling-Isuzu Motors", + "LE4" to "Beijing Benz", + "LFB" to "FAW (busses)", + "LFG" to "Taizhou Chuanl Motorcycle Manufacturing", + "LFP" to "FAW (passenger vehicles)", + "LFT" to "FAW (trailers)", + "LFV" to "FAW-Volkswagen", + "LFW" to "FAW JieFang", + "LFY" to "Changshu Light Motorcycle Factory", + "LGB" to "Dong Feng (DFM)", + "LGH" to "Qoros (formerly Dong Feng (DFM))", + "LGX" to "BYD Auto", + "LHB" to "Beijing Automotive Industry Holding", + "LH1" to "FAW-Haima", + "LJC" to "JAC", + "LJ1" to "JAC", + "LKL" to "Suzhou King Long", + "LL6" to "Hunan Changfeng Manufacture Joint-Stock", + "LL8" to "Linhai (ATV)", + "LMC" to "Suzuki Hong Kong (motorcycles)", + "LPR" to "Yamaha Hong Kong (motorcycles)", + "LSG" to "SAIC General Motors", + "LSJ" to "SAIC MG", + "LSV" to "SAIC Volkswagen", + "LSY" to "Brilliance Zhonghua", + "LTV" to "Toyota Tian Jin", + "LUC" to "Guangqi Honda", + "LVS" to "Ford Chang An", + "LVV" to "Chery", + "LVZ" to "Dong Feng Sokon Motor Company (DFSK)", + "LZM" to "MAN", + "LZE" to "Isuzu Guangzhou", + "LZG" to "Shaanxi Automobile Group", + "LZP" to "Zhongshan Guochi Motorcycle (Baotian)", + "LZY" to "Yutong Zhengzhou", + "LZZ" to "Chongqing Shuangzing Mech & Elec (Howo)", + "L4B" to "Xingyue Group (motorcycles)", + "L5C" to "KangDi (ATV)", + "L5K" to "Zhejiang Yongkang Easy Vehicle", + "L5N" to "Zhejiang Taotao (ATV & motorcycles)", + "L5Y" to "Merato Motorcycle Taizhou Zhongneng", + "L85" to "Zhejiang Yongkang Huabao Electric Appliance", + "L8X" to "Zhejiang Summit Huawin Motorcycle", + "MAB" to "Mahindra & Mahindra", + "MAC" to "Mahindra & Mahindra", + "MAJ" to "Ford", + "MAK" to "Honda Siel Cars", + "MAL" to "Hyundai", + "MAT" to "Tata Motors", + "MA1" to "Mahindra & Mahindra", + "MA3" to "Suzuki (Maruti)", + "MA6" to "GM", + "MA7" to "Mitsubishi (formerly Honda)", + "MBH" to "Suzuki (Maruti)", + "MBJ" to "Toyota", + "MBR" to "Mercedes-Benz", + "MB1" to "Ashok Leyland", + "MCA" to "Fiat", + "MCB" to "GM", + "MC2" to "Volvo Eicher commercial vehicles limited.", + "MDH" to "Nissan", + "MD2" to "Bajaj Auto", + "MD9" to "Shuttle Cars", + "MEE" to "Renault", + "MEX" to "Volkswagen", + "MHF" to "Toyota", + "MHR" to "Honda", + "MLC" to "Suzuki", + "MLH" to "Honda", + "MMB" to "Mitsubishi", + "MMC" to "Mitsubishi", + "MMM" to "Chevrolet", + "MMS" to "Suzuki", + "MMT" to "Mitsubishi", + "MM8" to "Mazda", + "MNB" to "Ford", + "MNT" to "Nissan", + "MPA" to "Isuzu", + "MP1" to "Isuzu", + "MRH" to "Honda", + "MR0" to "Toyota", + "MS0" to "KIA", + "MS3" to "Suzuki Motor Co., Ltd.", + "NLA" to "Honda", + "NLE" to "Mercedes-Benz Truck", + "NLH" to "Hyundai Assan", + "NLT" to "TEMSA", + "NMB" to "Mercedes-Benz Buses", + "NMC" to "BMC", + "NM0" to "Ford", + "NM4" to "Tofaş", + "NMT" to "Toyota", + "NNA" to "Isuzu", + "PE1" to "Ford", + "PE3" to "Mazda", + "PL1" to "Proton", + "PNA" to "NAZA (Peugeot)", + "RA1" to "Steyr Trucks International FZE", + "RFB" to "Kymco", + "RFG" to "Sanyang SYM", + "RFL" to "Adly", + "RFT" to "CPI", + "RF3" to "Aeon Motor", + "SAD" to "Jaguar (F-Pace)", + "SAL" to "Land Rover", + "SAJ" to "Jaguar", + "SAR" to "Rover", + "SB1" to "Toyota", + "SBM" to "McLaren", + "SCA" to "Rolls Royce", + "SCB" to "Bentley", + "SCC" to "Lotus Cars", + "SCE" to "DeLorean Motor Cars N. Ireland", + "SCF" to "Aston", + "SDB" to "Peugeot (formerly Talbot)", + "SED" to "General Motors Luton Plant", + "SEY" to "LDV", + "SFA" to "Ford", + "SFD" to "Alexander Dennis", + "SHH" to "Honda", + "SHS" to "Honda", + "SJN" to "Nissan", + "SKF" to "Vauxhall", + "SLP" to "JCB Research", + "SMT" to "Triumph Motorcycles", + "SUF" to "Fiat Auto", + "SUL" to "FSC", + "SUP" to "FSO-Daewoo", + "SUU" to "Solaris Bus & Coach", + "SWV" to "TA-NO", + "TCC" to "Micro Compact Car AG (smart 1998-1999)", + "TDM" to "QUANTYA Swiss Electric Movement", + "TK9" to "SOR buses", + "TMA" to "Hyundai Motor Manufacturing", + "TMB" to "Škoda", + "TMK" to "Karosa", + "TMP" to "Škoda trolleybuses", + "TMT" to "Tatra", + "TM9" to "Škoda trolleybuses", + "TNE" to "TAZ", + "TN9" to "Karosa", + "TRA" to "Ikarus Bus", + "TRU" to "Audi", + "TSE" to "Ikarus Egyedi Autobuszgyar", + "TSM" to "Suzuki", + "TW1" to "Toyota Caetano", + "TYA" to "Mitsubishi Trucks", + "TYB" to "Mitsubishi Trucks", + "UU1" to "Renault Dacia", + "UU3" to "ARO", + "UU6" to "Daewoo", + "U5Y" to "Kia Motors", + "U6Y" to "Kia Motors", + "VAG" to "Magna Steyr Puch", + "VAN" to "MAN", + "VBK" to "KTM (Motorcycles)", + "VF1" to "Renault", + "VF2" to "Renault", + "VF3" to "Peugeot", + "VF4" to "Talbot", + "VF6" to "Renault (Trucks & Buses)", + "VF7" to "Citroën", + "VF8" to "Matra", + "VF9" to "Bugatti", + "795" to "Bugatti", + "VG5" to "MBK (motorcycles)", + "VLU" to "Scania", + "VN1" to "SOVAB", + "VNE" to "Irisbus", + "VNK" to "Toyota", + "VNV" to "Renault-Nissan", + "VSA" to "Mercedes-Benz", + "VSE" to "Suzuki (Santana Motors)", + "VSK" to "Nissan", + "VSS" to "SEAT", + "VSX" to "Opel", + "VS6" to "Ford", + "VS7" to "Citroën", + "VS9" to "Carrocerias Ayats", + "VTH" to "Derbi (motorcycles)", + "VTL" to "Yamaha (motorcycles)", + "VTT" to "Suzuki (motorcycles)", + "VV9" to "TAURO", + "VWA" to "Nissan", + "VWV" to "Volkswagen", + "VX1" to "Zastava / Yugo Serbia", + "WAG" to "Neoplan", + "WAU" to "Audi", + "WA1" to "Audi SUV", + "WBA" to "BMW", + "WBS" to "BMW M", + "WBW" to "BMW", + "WBY" to "BMW", + "WDA" to "Daimler", + "WDB" to "Mercedes-Benz", + "WDC" to "DaimlerChrysler", + "WDD" to "Mercedes-Benz", + "WDF" to "Mercedes-Benz (commercial vehicles)", + "WEB" to "Evobus GmbH (Mercedes-Bus)", + "WJM" to "Iveco Magirus", + "WF0" to "Ford", + "WKE" to "Fahrzeugwerk Bernard Krone GmbH & Co. KG", + "WKK" to "Kässbohrer/Setra", + "WMA" to "MAN", + "WME" to "smart", + "WMW" to "MINI", + "WMX" to "Mercedes-AMG", + "WP0" to "Porsche", + "WP1" to "Porsche SUV", + "W09" to "RUF", + "W0L" to "Opel", + "W0V" to "Opel", + "WUA" to "quattro GmbH", + "WVG" to "Volkswagen MPV/SUV", + "WVW" to "Volkswagen", + "WV1" to "Volkswagen Commercial Vehicles", + "WV2" to "Volkswagen Bus/Van", + "WV3" to "Volkswagen Trucks", + "XLB" to "Volvo (NedCar)", + "XLE" to "Scania", + "XLR" to "DAF (trucks)", + "XL9" to "Spyker", + "363" to "Spyker", + "XMC" to "Mitsubishi (NedCar)", + "XTA" to "Lada/AvtoVAZ", + "XTC" to "KAMAZ", + "XTH" to "GAZ", + "XTT" to "UAZ/Sollers", + "XTY" to "LiAZ", + "XUF" to "General Motors", + "XUU" to "AvtoTor (General Motors SKD)", + "XW8" to "Volkswagen Group", + "XWB" to "UZ-Daewoo", + "XWE" to "AvtoTor (Hyundai-Kia SKD)", + "X1M" to "PAZ", + "X4X" to "AvtoTor (BMW SKD)", + "X7L" to "Renault AvtoFramos", + "X7M" to "Hyundai TagAZ", + "YBW" to "Volkswagen", + "YB1" to "Volvo Trucks", + "YCM" to "Mazda", + "YE2" to "Van Hool (buses)", + "YH2" to "BRP (Lynx snowmobiles)", + "YK1" to "Saab-Valmet", + "YS2" to "Scania AB", + "YS3" to "Saab", + "YS4" to "Scania Bus", + "YTN" to "Saab NEVS", + "YT9" to "Koenigsegg", + "007" to "Koenigsegg", + "034" to "Carvia", + "YU7" to "Husaberg (motorcycles)", + "YV1" to "Volvo Cars", + "YV4" to "Volvo Cars", + "YV2" to "Volvo Trucks", + "YV3" to "Volvo Buses", + "Y3M" to "MAZ", + "Y6D" to "Zaporozhets/AvtoZAZ", + "ZAA" to "Autobianchi", + "ZAM" to "Maserati", + "ZAP" to "Piaggio/Vespa/Gilera", + "ZAR" to "Alfa Romeo", + "ZBN" to "Benelli", + "ZCG" to "Cagiva SpA / MV Agusta", + "ZCF" to "Iveco", + "ZDM" to "Ducati Motor Holdings SpA", + "ZDF" to "Ferrari Dino", + "ZD0" to "Yamaha", + "ZD3" to "Beta Motor", + "ZD4" to "Aprilia", + "ZFA" to "Fiat", + "ZFC" to "Fiat V.I.", + "ZFF" to "Ferrari", + "ZGU" to "Moto Guzzi", + "ZHW" to "Lamborghini", + "ZJM" to "Malaguti", + "ZJN" to "Innocenti", + "ZKH" to "Husqvarna Motorcycles", + "ZLA" to "Lancia", + "ZOM" to "OM", + "Z8M" to "Marussia", + "1B3" to "Dodge", + "1C3" to "Chrysler", + "1C4" to "Chrysler", + "1C6" to "Chrysler", + "1D3" to "Dodge", + "1FA" to "Ford Motor Company", + "1FB" to "Ford Motor Company", + "1FC" to "Ford Motor Company", + "1FD" to "Ford Motor Company", + "1FM" to "Ford Motor Company", + "1FT" to "Ford Motor Company", + "1FU" to "Freightliner", + "1FV" to "Freightliner", + "1F9" to "FWD Corp.", + "1G" to "General Motors", + "1GC" to "Chevrolet Truck", + "1GT" to "GMC Truck", + "1G1" to "Chevrolet", + "1G2" to "Pontiac", + "1G3" to "Oldsmobile", + "1G4" to "Buick", + "1G6" to "Cadillac", + "1G8" to "Saturn", + "1GM" to "Pontiac", + "1GY" to "Cadillac", + "1H" to "Honda", + "1HD" to "Harley-Davidson", + "1J4" to "Jeep", + "1J8" to "Jeep", + "1L" to "Lincoln", + "1ME" to "Mercury", + "1M1" to "Mack Truck", + "1M2" to "Mack Truck", + "1M3" to "Mack Truck", + "1M4" to "Mack Truck", + "1M9" to "Mynatt Truck & Equipment", + "1N" to "Nissan", + "1NX" to "NUMMI", + "1P3" to "Plymouth", + "1R9" to "Roadrunner Hay Squeeze", + "1VW" to "Volkswagen", + "1XK" to "Kenworth", + "1XP" to "Peterbilt", + "1YV" to "Mazda (AutoAlliance International)", + "1ZV" to "Ford (AutoAlliance International)", + "2A4" to "Chrysler", + "2BP" to "Bombardier Recreational Products", + "2B3" to "Dodge", + "2B7" to "Dodge", + "2C3" to "Chrysler", + "2CN" to "CAMI", + "2D3" to "Dodge", + "2FA" to "Ford Motor Company", + "2FB" to "Ford Motor Company", + "2FC" to "Ford Motor Company", + "2FM" to "Ford Motor Company", + "2FT" to "Ford Motor Company", + "2FU" to "Freightliner", + "2FV" to "Freightliner", + "2FZ" to "Sterling", + "2Gx" to "General Motors", + "2G1" to "Chevrolet", + "2G2" to "Pontiac", + "2G3" to "Oldsmobile", + "2G4" to "Buick", + "2G9" to "Gnome Homes", + "2HG" to "Honda", + "2HK" to "Honda", + "2HJ" to "Honda", + "2HM" to "Hyundai", + "2M" to "Mercury", + "2NV" to "Nova Bus", + "2P3" to "Plymouth", + "2T" to "Toyota", + "2TP" to "Triple E LTD", + "2V4" to "Volkswagen", + "2V8" to "Volkswagen", + "2WK" to "Western Star", + "2WL" to "Western Star", + "2WM" to "Western Star", + "3C4" to "Chrysler", + "3D3" to "Dodge", + "3D4" to "Dodge", + "3FA" to "Ford Motor Company", + "3FE" to "Ford Motor Company", + "3G" to "General Motors", + "3H" to "Honda", + "3JB" to "BRP (all-terrain vehicles)", + "3MD" to "Mazda", + "3MZ" to "Mazda", + "3N" to "Nissan", + "3P3" to "Plymouth", + "3VW" to "Volkswagen", + "4F" to "Mazda", + "4JG" to "Mercedes-Benz", + "4M" to "Mercury", + "4RK" to "Nova Bus", + "4S" to "Subaru-Isuzu Automotive", + "4T" to "Toyota", + "4T9" to "Lumen Motors", + "4UF" to "Arctic Cat Inc.", + "4US" to "BMW", + "4UZ" to "Frt-Thomas Bus", + "4V1" to "Volvo", + "4V2" to "Volvo", + "4V3" to "Volvo", + "4V4" to "Volvo", + "4V5" to "Volvo", + "4V6" to "Volvo", + "4VL" to "Volvo", + "4VM" to "Volvo", + "4VZ" to "Volvo", + "538" to "Zero Motorcycles", + "5F" to "Honda Alabama", + "5J" to "Honda Ohio", + "5L" to "Lincoln", + "5N1" to "Nissan", + "5NP" to "Hyundai", + "5T" to "Toyota - trucks", + "5YJ" to "Tesla, Inc.", + "6AB" to "MAN", + "6F4" to "Nissan Motor Company", + "6F5" to "Kenworth", + "6FP" to "Ford Motor Company", + "6G1" to "General Motors-Holden (post Nov 2002)", + "6G2" to "Pontiac (GTO & G8)", + "6H8" to "General Motors-Holden (pre Nov 2002)", + "6MM" to "Mitsubishi Motors", + "6T1" to "Toyota Motor Corporation", + "6U9" to "Privately Imported car", + "8AD" to "Peugeot", + "8AF" to "Ford Motor Company", + "8AG" to "Chevrolet", + "8AJ" to "Toyota", + "8AK" to "Suzuki", + "8AP" to "Fiat", + "8AW" to "Volkswagen", + "8A1" to "Renault", + "8GD" to "Peugeot", + "8GG" to "Chevrolet", + "935" to "Citroën", + "936" to "Peugeot", + "93H" to "Honda", + "93R" to "Toyota", + "93U" to "Audi", + "93V" to "Audi", + "93X" to "Mitsubishi Motors", + "93Y" to "Renault", + "94D" to "Nissan", + "9BD" to "Fiat", + "9BF" to "Ford Motor Company", + "9BG" to "Chevrolet", + "9BM" to "Mercedes-Benz", + "9BR" to "Toyota", + "9BS" to "Scania", + "9BW" to "Volkswagen", + "9FB" to "Renault", + "WB1" to "BMW Motorrad of North America", +) \ No newline at end of file diff --git a/src/main/kotlin/io/github/kabirnayeem99/viminfo/data/Years.kt b/src/main/kotlin/io/github/kabirnayeem99/viminfo/data/Years.kt new file mode 100644 index 0000000..61f4408 --- /dev/null +++ b/src/main/kotlin/io/github/kabirnayeem99/viminfo/data/Years.kt @@ -0,0 +1,34 @@ +package io.github.kabirnayeem99.viminfo.data + +val years = mapOf( + 'N' to 1992, + 'P' to 1993, + 'R' to 1994, + 'S' to 1995, + 'T' to 1996, + 'V' to 1997, + 'W' to 1998, + 'X' to 1999, + 'Y' to 2000, + '1' to 2001, + '2' to 2002, + '3' to 2003, + '4' to 2004, + '5' to 2005, + '6' to 2006, + '7' to 2007, + '8' to 2008, + '9' to 2009, + 'A' to 2010, + 'B' to 2011, + 'C' to 2012, + 'D' to 2013, + 'E' to 2014, + 'F' to 2015, + 'G' to 2016, + 'H' to 2017, + 'J' to 2018, + 'K' to 2019, + 'L' to 2020, + 'M' to 2021, +) \ No newline at end of file diff --git a/src/main/kotlin/io/github/kabirnayeem99/viminfo/entities/Vin.kt b/src/main/kotlin/io/github/kabirnayeem99/viminfo/entities/Vin.kt new file mode 100644 index 0000000..22392de --- /dev/null +++ b/src/main/kotlin/io/github/kabirnayeem99/viminfo/entities/Vin.kt @@ -0,0 +1,132 @@ +package io.github.kabirnayeem99.viminfo.entities + +import io.github.kabirnayeem99.viminfo.data.manufacturers +import io.github.kabirnayeem99.viminfo.data.years +import io.github.kabirnayeem99.viminfo.exceptions.InvalidVinLengthException +import io.github.kabirnayeem99.viminfo.exceptions.InvalidVinRegionCharException +import io.github.kabirnayeem99.viminfo.exceptions.InvalidVinYearException + +data class Vin( + val number: String, + private val normalizedNumber: String, + val wmi: String, + val vds: String, + val vis: String, + val isExtended: Boolean, + private var vehicleInfo: Map = emptyMap(), +) { + + private val validVinRegex = "^[a-zA-Z0-9]+$".toRegex() + + val isValid: Boolean + get() = validVinRegex.matches(normalizedNumber) && normalizedNumber.length == 17 + + + val year: Int + get() = years[yearCharacter] ?: throw InvalidVinYearException(yearCharacter) + + val region: String + get() { + val regionId = + normalizedNumber.getOrNull(0)?.toString() ?: throw InvalidVinLengthException( + normalizedNumber + ) + + val regexAF = Regex("[A-H]", RegexOption.IGNORE_CASE) + val regexAS = Regex("[J-R]", RegexOption.IGNORE_CASE) + val regexEU = Regex("[S-Z]", RegexOption.IGNORE_CASE) + val regexNA = Regex("[1-5]", RegexOption.IGNORE_CASE) + val regexOC = Regex("[6-7]", RegexOption.IGNORE_CASE) + val regexSA = Regex("[8-9]", RegexOption.IGNORE_CASE) + + return when { + regexAF.containsMatchIn(regionId) -> "AF" + regexAS.containsMatchIn(regionId) -> "AS" + regexEU.containsMatchIn(regionId) -> "EU" + regexNA.containsMatchIn(regionId) -> "NA" + regexOC.containsMatchIn(regionId) -> "OC" + regexSA.containsMatchIn(regionId) -> "SA" + else -> throw InvalidVinRegionCharException(regionId) + } + } + + val manufacturer: String + get() { + if (wmi.isBlank()) throw InvalidVinLengthException(normalizedNumber) + return if (manufacturers.containsKey(this.wmi)) { + manufacturers[this.wmi] + ?: throw Exception("Unknown World Manufacturer Identifier (WMI): ${this.wmi.uppercase()}") + } else { + val alternativeWmiId = this.wmi.substring(0, 2) + if (manufacturers.containsKey(alternativeWmiId)) { + manufacturers[alternativeWmiId] + ?: throw Exception("Unknown World Manufacturer Identifier (WMI): ${alternativeWmiId.uppercase()}") + } else { + throw Exception("Unknown World Manufacturer Identifier (WMI): ${this.wmi.uppercase()}") + } + } + + } + + val checksum: Char + get() = if (region != "EU") normalizedNumber[8] else throw Exception("No CheckSum for the Europe region.") + + val assemblyPlant: Char + get() = normalizedNumber.getOrNull(10) + ?: throw Exception("Wrong VIN Number length: ${normalizedNumber.length}") + + val serialNumber: String + get() = normalizedNumber.substring(12, 17) + +// suspend fun + // Future _fetchExtendedVehicleInfo() async { + // if (this._vehicleInfo.isEmpty && extended == true) { + // this._vehicleInfo = await NHTSA.decodeVinValues(this.number); + // } + // } + // + // /// Get the Make of the vehicle from the NHTSA database if [extended] mode + // /// is enabled. + // Future getMakeAsync() async { + // await _fetchExtendedVehicleInfo(); + // return this._vehicleInfo['Make']; + // } + // + // /// Get the Model of the vehicle from the NHTSA database if [extended] mode + // /// is enabled. + // Future getModelAsync() async { + // await _fetchExtendedVehicleInfo(); + // return this._vehicleInfo['Model']; + // } + // + // /// Get the Vehicle Type from the NHTSA database if [extended] mode is + // /// enabled. + // Future getVehicleTypeAsync() async { + // await _fetchExtendedVehicleInfo(); + // return this._vehicleInfo['VehicleType']; + // } + + + private val yearCharacter: Char + get() = normalizedNumber.getOrNull(9) ?: throw Exception("Invalid VIN Length") + + + override fun toString() = this.wmi + this.vds + this.vis + + companion object { + + private fun String.normalize() = uppercase().replaceAfter("-", "") + + fun fromNumber(number: String, isExtended: Boolean = false): Vin { + val normalizedNumber = number.normalize() + return Vin( + number = number, + isExtended = isExtended, + normalizedNumber = normalizedNumber, + wmi = if (number.length >= 3) normalizedNumber.substring(0, 3) else "", + vds = if (number.length >= 9) normalizedNumber.substring(3, 9) else "", + vis = if (number.length >= 17) normalizedNumber.substring(9, 17) else "", + ) + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/kabirnayeem99/viminfo/exceptions/InvalidVinLengthException.kt b/src/main/kotlin/io/github/kabirnayeem99/viminfo/exceptions/InvalidVinLengthException.kt new file mode 100644 index 0000000..b208ae9 --- /dev/null +++ b/src/main/kotlin/io/github/kabirnayeem99/viminfo/exceptions/InvalidVinLengthException.kt @@ -0,0 +1,7 @@ +package io.github.kabirnayeem99.viminfo.exceptions + +import java.lang.Exception + +class InvalidVinLengthException(vin: String) : + Exception("Invalid VIN length: ${vin.length}. Expected length is 17 characters. Ensure that the VIN is 17 characters long, which is the standard length for VINs. Please check the VIN and try again.") { +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/kabirnayeem99/viminfo/exceptions/InvalidVinRegionCharException.kt b/src/main/kotlin/io/github/kabirnayeem99/viminfo/exceptions/InvalidVinRegionCharException.kt new file mode 100644 index 0000000..3e3e979 --- /dev/null +++ b/src/main/kotlin/io/github/kabirnayeem99/viminfo/exceptions/InvalidVinRegionCharException.kt @@ -0,0 +1,4 @@ +package io.github.kabirnayeem99.viminfo.exceptions + +class InvalidVinRegionCharException(regionChar: String) : + Exception("Invalid region ID: '$regionChar'. The first character of the VIN should be within the ranges A-H, J-R, S-Z, or 1-9 to indicate a valid region. Please check the VIN and try again.") diff --git a/src/main/kotlin/io/github/kabirnayeem99/viminfo/exceptions/InvalidVinYearException.kt b/src/main/kotlin/io/github/kabirnayeem99/viminfo/exceptions/InvalidVinYearException.kt new file mode 100644 index 0000000..2f2a978 --- /dev/null +++ b/src/main/kotlin/io/github/kabirnayeem99/viminfo/exceptions/InvalidVinYearException.kt @@ -0,0 +1,4 @@ +package io.github.kabirnayeem99.viminfo.exceptions + +class InvalidVinYearException(yearChar: Char) : + Exception("Invalid model year character: '$yearChar'. Expected a valid year character within the allowed range. Please check the VIN and try again.") \ No newline at end of file diff --git a/src/main/kotlin/io/github/kabirnayeem99/viminfo/network/NhtsaUsaApi.kt b/src/main/kotlin/io/github/kabirnayeem99/viminfo/network/NhtsaUsaApi.kt new file mode 100644 index 0000000..3c9f9e2 --- /dev/null +++ b/src/main/kotlin/io/github/kabirnayeem99/viminfo/network/NhtsaUsaApi.kt @@ -0,0 +1,4 @@ +package io.github.kabirnayeem99.viminfo.network + +class NhtsaUsaApi { +} \ No newline at end of file diff --git a/src/test/kotlin/io/github/kabirnayeem99/viminfo/VinInfoTest.kt b/src/test/kotlin/io/github/kabirnayeem99/viminfo/VinInfoTest.kt new file mode 100644 index 0000000..6d82f8c --- /dev/null +++ b/src/test/kotlin/io/github/kabirnayeem99/viminfo/VinInfoTest.kt @@ -0,0 +1,96 @@ +package io.github.kabirnayeem99.viminfo + +import io.github.kabirnayeem99.viminfo.entities.Vin +import io.github.kabirnayeem99.viminfo.exceptions.InvalidVinLengthException +import io.github.kabirnayeem99.viminfo.exceptions.InvalidVinYearException +import kotlin.test.AfterTest +import kotlin.test.BeforeTest +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertFailsWith +import kotlin.test.assertFalse +import kotlin.test.assertTrue + +private const val VALID_VIN = "1HGCM82635A123456" + +class VinInfoTest { + + lateinit var vin: Vin + + @BeforeTest + fun setUp() { + vin = Vin.fromNumber(VALID_VIN) + } + + @AfterTest + fun tearDown() { + vin = Vin.fromNumber("") + } + + @Test + fun `VIN should be VALID`() { + assertTrue(vin.isValid, "$VALID_VIN should be a valid vin.") + } + + @Test + fun `VIN with less than 17 characters should be invalid`() { + vin = Vin.fromNumber("1HGCM82635A12345") + assertFalse( + vin.isValid, + "1HGCM82635A12345 should be invalid, as the number of characters are less than 17." + ) + } + + @Test + fun `VIN with more than 17 characters should be invalid`() { + vin = Vin.fromNumber("1HGCM82635A1234567") + assertFalse( + vin.isValid, + "1HGCM82635A1234567 should be invalid, as the number of characters are more than 17." + ) + } + + + @Test + fun `VIN with invalid characters should be invalid`() { + vin = Vin.fromNumber("1HGCM82633A!2345&") + assertFalse( + vin.isValid, "2345 should be invalid, as it contains invalid characters like ! and &" + ) + } + + @Test + fun `VIN should return correct year`() { + vin = Vin.fromNumber(VALID_VIN) + assertEquals(2005, vin.year, "The valid year should be 2005.") + } + + @Test + fun `VIN with wrong year should throw invalid year exception`() { + vin = Vin.fromNumber("1HGCM8263?A123456") + assertFailsWith( + InvalidVinYearException::class, "This should throw a wrong year exception." + ) { + vin.year + } + } + + @Test + fun `VIN region should be NA (North America)`() { + vin = Vin.fromNumber(VALID_VIN) + assertEquals("NA", vin.region) + } + + @Test + fun `VIN region should throw InvalidVinLengthException with empty VIN if asked for region`() { + vin = Vin.fromNumber("") + assertFailsWith(InvalidVinLengthException::class) { + vin.region + } + } + + @Test + fun `VIN region should throw InvalidVinRegionCharException`() { + } + +}