thai_id_utils 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: d9194c3362b9038193a979c13e0d7723bb0c6f0c3ce41ff17523086ef8a04672
4
+ data.tar.gz: dac42ef970424a31999019dc4c3d8d1fa5c5739c55427440906e118d4c2cecba
5
+ SHA512:
6
+ metadata.gz: c3f92740ba6ac0700b5cddb7abdc23a74cdc759a822a14936a1a36acbd43e021ad42f395889ec09d4db5cf3ed1f641599d454d1b8eb4cc17756365f26f853ab9
7
+ data.tar.gz: 49bbfa319256583fd8156cea558995d2d555e17352b0391830046ff78cdb90034306c9cf5cb0d5eacf13195380d61c3196e14d7d7d27f38b266195b04c67240c
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gemspec
data/README.md ADDED
@@ -0,0 +1,33 @@
1
+ # Thai ID Utils
2
+
3
+ Thai ID Utils is a zero-dependency Ruby gem for validating and decoding Thai national ID numbers. It provides a simple API to check the official modulus-11 checksum, extract the embedded components (category, office code, district code, sequence), and get a human-readable description of the category code.
4
+
5
+ Thai ID Utils เป็น Ruby gem ที่ไม่ต้องพึ่งพาไลบรารีเสริม สำหรับตรวจสอบความถูกต้องและถอดรหัสหมายเลขบัตรประชาชนไทย โดยมี API ที่ใช้งานง่ายสำหรับตรวจสอบ checksum ตามมาตรฐาน modulus-11 ดึงส่วนประกอบต่างๆ (ประเภทผู้ลงทะเบียน รหัสหน่วยงาน รหัสอำเภอ และหมายเลขลำดับ) และแสดงคำอธิบายของรหัสประเภทในรูปแบบอ่านง่าย
6
+
7
+ ## Usage / วิธีใช้งาน
8
+
9
+ ```ruby
10
+ require "thai_id_utils"
11
+
12
+ id = "3012304567082"
13
+
14
+ # ✅ Validate checksum
15
+ if ThaiIdUtils.valid?(id)
16
+ puts "Valid!"
17
+ else
18
+ puts "Invalid ID"
19
+ end
20
+
21
+ # 🔍 Decode components
22
+ info = ThaiIdUtils.decode(id)
23
+ # => { category: 1, office_code: "6099", district_code: "99", sequence: "00257" }
24
+ puts info.inspect
25
+
26
+ # 🏷️ Get category description
27
+ desc = ThaiIdUtils.category_description(info[:category])
28
+ # => "Thai nationals who were born after 1 January 1984 and had their birth notified within the given deadline (15 days)."
29
+ puts desc
30
+
31
+ # 🎲 Generate a new random valid ID
32
+ new_id = ThaiIdUtils.generate
33
+ puts new_id # => e.g. "3601205234518"
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rake/testtask'
4
+
5
+ Rake::TestTask.new do |t|
6
+ t.libs << 'test'
7
+ end
8
+
9
+ task default: :test
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ThaiIdUtils
4
+ VERSION = '0.1.1'
5
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ # ThaiIdUtils: Validate and decode Thai national ID numbers,
4
+ # providing checksum validation, component decoding, ID generation,
5
+ # and human-readable category descriptions.
6
+ module ThaiIdUtils
7
+ class InvalidIDError < StandardError; end
8
+
9
+ # ----------------------------------------------------------------------------
10
+ # Mapping of category codes to their descriptions
11
+ # ----------------------------------------------------------------------------
12
+ # rubocop:disable Layout/LineLength
13
+ CATEGORY_DESCRIPTIONS = {
14
+ 0 => '(Not found on cards of Thai nationals but may be found in the other issued identity cards below)',
15
+ 1 => 'Thai nationals who were born after 1 January 1984 and had their birth notified within the given deadline (15 days).',
16
+ 2 => 'Thai nationals who were born after 1 January 1984 but failed to have their birth notified in time.',
17
+ 3 => 'Thai nationals or foreign nationals with identification cards who were born and whose names were included in a house registration book before 1 January 1984',
18
+ 4 => 'Thai nationals who were born before 1 January 1984 but were not included in a house registration book at that time, for example due to moving residences',
19
+ 5 => 'Thai nationals who missed the official census or other special cases, for instance those of dual nationality',
20
+ 6 => 'Foreign nationals who are living in Thailand temporarily and illegal migrants',
21
+ 7 => 'Children of people of category 6 who were born in Thailand',
22
+ 8 => 'Foreign nationals who are living in Thailand permanently or Thai nationals by naturalization'
23
+ }.freeze
24
+ # rubocop:enable Layout/LineLength
25
+
26
+ # Public: Validate checksum using Thailand’s modulus-11 algorithm
27
+ def self.valid?(id)
28
+ digits = id.to_s.chars.map(&:to_i)
29
+ return false unless digits.size == 13
30
+
31
+ sum = digits[0..11].each_with_index.sum { |d, i| d * (13 - i) }
32
+ ((11 - (sum % 11)) % 10) == digits.last
33
+ rescue StandardError
34
+ false
35
+ end
36
+
37
+ # Public: Decode components present in a Thai ID
38
+ # Returns a hash with keys:
39
+ # :category => Integer
40
+ # :office_code => String (4-digit registrar)
41
+ # :district_code => String (last 2 of office_code)
42
+ # :sequence => String (5-digit personal sequence)
43
+ def self.decode(id)
44
+ raise InvalidIDError, 'Invalid ID' unless valid?(id)
45
+
46
+ d = id.to_s.chars
47
+
48
+ {
49
+ category: d[0].to_i,
50
+ office_code: d[1..4].join,
51
+ district_code: d[3..4].join,
52
+ sequence: d[5..9].join
53
+ }
54
+ end
55
+
56
+ # Public: Generate a random, valid 13-digit Thai national ID.
57
+ # You can override any component or let it be randomized.
58
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
59
+ def self.generate(category: rand(1..6),
60
+ office_code: nil,
61
+ district_code: nil,
62
+ sequence: nil)
63
+ # Build and override office_code/district_code
64
+ office_code = format('%04d', office_code || rand(1..9_999))
65
+ office_code[2..3] = district_code.to_s.rjust(2, '0') if district_code
66
+
67
+ # Sequence (5 digits) and classification (2 digits)
68
+ sequence = format('%05d', sequence || rand(0..99_999))
69
+ classification = format('%02d', rand(0..99))
70
+
71
+ # First 12 digits: category + office_code + sequence + classification
72
+ digits = [category.to_i] +
73
+ office_code.chars.map(&:to_i) +
74
+ sequence.chars.map(&:to_i) +
75
+ classification.chars.map(&:to_i)
76
+
77
+ # Checksum
78
+ sum = digits.each_with_index.sum { |d, i| d * (13 - i) }
79
+ check = (11 - (sum % 11)) % 10
80
+
81
+ (digits + [check]).join
82
+ end
83
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
84
+
85
+ # Public: Return a human-readable description for a category code
86
+ def self.category_description(category)
87
+ CATEGORY_DESCRIPTIONS[category.to_i] || 'Unknown category'
88
+ end
89
+ end
metadata ADDED
@@ -0,0 +1,67 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: thai_id_utils
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Chayut Orapinpatipat
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2025-06-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: minitest
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '5.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '5.0'
27
+ description: |
28
+ Zero-dependency Ruby utilities for:
29
+ • checksum validation (modulus-11),
30
+ • component decoding (category, office_code, district_code, sequence),
31
+ • random valid ID generation,
32
+ • human-readable category descriptions.
33
+ email:
34
+ - chayut_o@hotmail.com
35
+ executables: []
36
+ extensions: []
37
+ extra_rdoc_files: []
38
+ files:
39
+ - Gemfile
40
+ - README.md
41
+ - Rakefile
42
+ - lib/thai_id_utils.rb
43
+ - lib/thai_id_utils/version.rb
44
+ homepage: https://github.com/chayuto/thai-id-utils
45
+ licenses:
46
+ - MIT
47
+ metadata: {}
48
+ post_install_message:
49
+ rdoc_options: []
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: '2.7'
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ requirements: []
63
+ rubygems_version: 3.5.11
64
+ signing_key:
65
+ specification_version: 4
66
+ summary: Validate and decode Thai national ID numbers
67
+ test_files: []