From fc6bfdb113cd67f3270ab0a34b30d702911c49be Mon Sep 17 00:00:00 2001 From: Nemo Date: Sat, 1 Jul 2023 20:00:02 +0530 Subject: [PATCH] Lots of changes for v2 Mainly, add a search method to find all valid pincodes See #3 Create a single unified regex. Update some dependencies However, this breaks on PHP,so I need to fix something for that. --- .gitignore | 2 ++ HACKING.md | 6 ++--- README.md | 8 ++++-- composer.json | 2 +- package.json | 3 ++- phpunit.xml | 2 +- pincode-validator.gemspec | 2 +- src/Validator.php | 31 +++++++++++++++++------ src/generate.js | 6 ++--- src/index.js | 29 ++++++++++------------ src/pincode_validator.rb | 18 ++++++++------ tests/SimpleTest.php | 7 ++++++ tests/validate.js | 52 ++++++++++++++++++++++++++++----------- tests/validate_spec.rb | 8 ++++++ 14 files changed, 117 insertions(+), 59 deletions(-) diff --git a/.gitignore b/.gitignore index eac44e4..f227bf1 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,5 @@ Gemfile.lock .pdm.toml __pypackages__/ src/pincode.egg-info/ +.phpunit.*cache +*.bak diff --git a/HACKING.md b/HACKING.md index 2ec61f8..d3bbcf2 100644 --- a/HACKING.md +++ b/HACKING.md @@ -1,10 +1,8 @@ # Generating the regex 1. Download the latest CSV file from . -2. Copy all the pincodes to a pincodes.txt file -3. Generate all unique pincodes by running `sort -u pincodes.txt > /tmp/pin.txt` -4. `npm install` -5. `node src/generate.js /tmp/pin.txt > regex.txt` +2. Copy all the pincodes to a pincodes.csv file +3. Generate all unique pincodes by running `npm run build` # Generating the browser-version diff --git a/README.md b/README.md index 26fd766..e527024 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,11 @@ To use the package: ```js const P = require('pincode-validator'); P.validate('110011'); // returns true +P.search('my pincode is 560029'); // returns ['560029'] + +// or directly use the regex in your code +P.exactRegex.match('560029') +"address with pincode (560029)".matchAll(P.regex) ```` ## Ruby @@ -63,13 +68,12 @@ Pincode.validate("560029"); // returns true ``` -Since there is no hotline/CDN for this yet, please watch to repo to get notified of new releases. +You can use githack for directly using this in your code: (Make sure you use the latest version). Please watch the repo to get notified of new releases. ## Code of Conduct Everyone interacting in the this project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/captn3m0/outliner/blob/master/CODE_OF_CONDUCT.md). - ## Contributing - See [`HACKING.md`](HACKING.md) for some development details. diff --git a/composer.json b/composer.json index fba34e3..0c9b9ec 100644 --- a/composer.json +++ b/composer.json @@ -16,6 +16,6 @@ }, "require": {}, "require-dev": { - "phpunit/phpunit": "^9.0 || ^8.0" + "phpunit/phpunit": "^9.0 || ^8.0 || ^10.0" } } diff --git a/package.json b/package.json index d5d41d3..f6070ce 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ }, "scripts": { "test": "node tests/validate.js", + "build": "node src/generate.js <(sort -u pincodes.csv) > regex.txt", "browserify": "browserify --transform brfs --outfile pincode-regex.js -s Pincode src/index.js" }, "repository": { @@ -29,7 +30,7 @@ "homepage": "https://github.com/captn3m0/india-pincode-regex#readme", "devDependencies": { "brfs": "^2.0.2", - "browserify": "^16.5.1", + "browserify": "^17.0.0", "regexgen": "^1.3.0" }, "dependencies": {} diff --git a/phpunit.xml b/phpunit.xml index 7fa640c..1f7c73b 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -22,4 +22,4 @@ - \ No newline at end of file + diff --git a/pincode-validator.gemspec b/pincode-validator.gemspec index edc6a21..0f9d660 100644 --- a/pincode-validator.gemspec +++ b/pincode-validator.gemspec @@ -25,5 +25,5 @@ Gem::Specification.new do |spec| spec.license = 'MIT' spec.require_paths = ["src"] spec.add_development_dependency 'rake', '~> 13.0' - spec.add_development_dependency 'rspec', '~> 3.8' + spec.add_development_dependency 'rspec', '~> 3.12' end diff --git a/src/Validator.php b/src/Validator.php index 9bf9a41..65013a0 100644 --- a/src/Validator.php +++ b/src/Validator.php @@ -3,19 +3,34 @@ namespace PIN; class Validator { - static $regexes; + static $regex; + static $exactRegex; + + public static function init(){ + if(!self::$regex) { + self::$regex = "/" . trim(file_get_contents('regex.txt')) . "/"; + self::$exactRegex = "/^" . trim(file_get_contents('regex.txt')) . "$/"; + } + } public static function validate(string $pin) { - if(!self::$regexes) { - self::$regexes = array_filter(file('regex.txt')); - } + self::init(); - foreach (self::$regexes as $regex) { - if (strlen($pin) === 6 and preg_match($regex, $pin) === 1) { - return true; - } + fwrite(STDERR, var_dump(self::$exactRegex, TRUE)); + + if (strlen($pin) === 6 and preg_match(self::$exactRegex, $pin) === 1) { + return true; } return false; } + + public static function search(string $address) { + self::init(); + preg_match_all(self::$regex, $address, $matches); + + return array_map(function($match) { + return $match[0]; + }, $matches); + } } diff --git a/src/generate.js b/src/generate.js index fdc2ee2..220b2cf 100644 --- a/src/generate.js +++ b/src/generate.js @@ -26,13 +26,11 @@ readInterface.on("line", function (line) { let areaCode = parseInt(line.charAt(0), 10); if (areaCode < 9 && areaCode > 0) { let areaCodeIndex = areaCode - 1; - regexes[areaCodeIndex].add(line); + regexes[areaCodeIndex].add(line.trim()); } } }); readInterface.on("close", function () { - for (i in regexes) { - console.log(regexes[i].toRegExp()); - } + console.log("(" + regexes.join('|') + ")"); }); diff --git a/src/index.js b/src/index.js index 704d223..0264bc6 100644 --- a/src/index.js +++ b/src/index.js @@ -1,25 +1,22 @@ const readline = require("readline"); const fs = require("fs"); -const regexes = fs - .readFileSync(__dirname + "/../regex.txt", "utf8") - .split("\n") - // Remove empty lines - .filter(function(r) { - return r.length > 1; - }) - // Remove the opening and closing slashes - .map(function(r) { - return new RegExp("^" + r.slice(1, -1) + "$"); - }); +let contents = fs.readFileSync(__dirname + "/../regex.txt", "utf8").trim() +const regex = new RegExp(contents, "gm"); +const exactRegex = new RegExp("^" + contents + "$"); module.exports = { + // Validates an exact 6 digit string as a valid pincode validate: function(pin) { - for (let i in regexes) { - if (regexes[i].test(pin)) { - return true; - } + if (exactRegex.test(pin)) { + return true; } return false; - } + }, + // Returns all valid PIN codes for a given address + search: function(address) { + return Array.from(address.matchAll(regex), (x) => x[0]) + }, + regex: regex, + exactRegex: exactRegex }; diff --git a/src/pincode_validator.rb b/src/pincode_validator.rb index 88060fa..84e5ca4 100644 --- a/src/pincode_validator.rb +++ b/src/pincode_validator.rb @@ -1,5 +1,5 @@ module PincodeValidator - VERSION = "1.0.3" + VERSION = "1.0.4" FILENAME='regex.txt' class Error < StandardError; end @@ -8,14 +8,18 @@ module PincodeValidator File.dirname __dir__ end - @@regexes ||= IO.readlines(File.join root, FILENAME).map do |line| - Regexp.new("^#{line.strip[1...-1]}$") - end + @@regex ||= + Regexp.new(File.read(File.join root, FILENAME).strip) + + @@exactRegex ||= + Regexp.new("^#{File.read(File.join root, FILENAME).strip}$") def self.valid?(pincode) - @@regexes.each do |r| - return true if r.match? pincode - end + return true if @@exactRegex.match? pincode false end + + def self.search?(address) + address.scan(@@regex).map(&:first).map(&:strip) + end end diff --git a/tests/SimpleTest.php b/tests/SimpleTest.php index ba99cba..4504f5e 100644 --- a/tests/SimpleTest.php +++ b/tests/SimpleTest.php @@ -17,4 +17,11 @@ class SimpleTest extends TestCase { $this->assertFalse(P::validate($pin), "$pin should be invalid"); } } + + // public function testSearch() { + // $this->assertSame(P::search("my pincode is 560029"), ["560029"]); + // $this->assertSame(P::search("560029"), ["560029"]); + // $this->assertSame(P::search("560029 244713"), ["560029", "244713"]); + // $this->assertSame(P::search("address 560038 bangalore"), ["560038"]); + // } } diff --git a/tests/validate.js b/tests/validate.js index 3ccad7c..538ae54 100644 --- a/tests/validate.js +++ b/tests/validate.js @@ -1,19 +1,43 @@ -const pincode = require('../src/index'); +const P = require('../src/index'); const assert = require('assert'); // A few correct ones - -assert.strictEqual(pincode.validate('110011'), true, '110011'); -assert.strictEqual(pincode.validate('244713'), true, '244713'); -assert.strictEqual(pincode.validate('560029'), true, '560029'); -assert.strictEqual(pincode.validate('560030'), true, '560030'); +assert.strictEqual(P.validate('110011'), true, '110011'); +assert.strictEqual(P.validate('244713'), true, '244713'); +assert.strictEqual(P.validate('560029'), true, '560029'); +assert.strictEqual(P.validate('560030'), true, '560030'); // Incorrect -assert.strictEqual(pincode.validate('1100111'), false, '1100111'); -assert.strictEqual(pincode.validate('111111'), false, '111111'); -assert.strictEqual(pincode.validate('999999'), false, '999999'); -assert.strictEqual(pincode.validate('99999'), false, '99999'); -assert.strictEqual(pincode.validate('9999'), false, '9999'); -assert.strictEqual(pincode.validate('999'), false, '999'); -assert.strictEqual(pincode.validate('99'), false, '99'); -assert.strictEqual(pincode.validate('9'), false, '9'); +assert.strictEqual(P.validate('address 560030'), false, 'address 560030 should fail'); +assert.strictEqual(P.validate('1100111'), false, '1100111'); +assert.strictEqual(P.validate('111111'), false, '111111'); +assert.strictEqual(P.validate('999999'), false, '999999'); +assert.strictEqual(P.validate('99999'), false, '99999'); +assert.strictEqual(P.validate('9999'), false, '9999'); +assert.strictEqual(P.validate('999'), false, '999'); +assert.strictEqual(P.validate('99'), false, '99'); +assert.strictEqual(P.validate('9'), false, '9'); + +// Validate search method +assert.deepEqual(P.search('bangalore 560038 244713'), ['560038', '244713']) +assert.deepEqual(P.search('bangalore 560038'), ['560038']) +assert.deepEqual(P.search('560038 BENGALURU'), ['560038']) +assert.deepEqual(P.search('560038'), ['560038']) +assert.deepEqual(P.search('my pincode is 244713'), ['244713']) +assert.deepEqual(P.search('560029 pin'), ['560029']) + +// Validate direct regex exports +assert(P.regex instanceof RegExp) +assert(P.exactRegex instanceof RegExp) + +// exact regex only works with 6 digit strings +assert(P.exactRegex.test('560029')) +assert.match('560029', P.exactRegex) +assert.doesNotMatch('111111', P.exactRegex) +assert.doesNotMatch('address is 560029', P.exactRegex) + +// Normal regex works with long addresses +assert.match('560029', P.regex) +assert.match('address is 560029', P.regex) +assert.doesNotMatch('address is 111111', P.regex) +assert.doesNotMatch('111111', P.regex) diff --git a/tests/validate_spec.rb b/tests/validate_spec.rb index 247eab7..e2ce155 100644 --- a/tests/validate_spec.rb +++ b/tests/validate_spec.rb @@ -12,4 +12,12 @@ describe PincodeValidator do expect(described_class::valid? pin).to eq(false), "#{pin} should be invalid" end end + + it 'should search pincodes' do + expect(described_class::search? '560029').to eq(['560029']) + expect(described_class::search? '560029, 560030').to eq(['560029', '560030']) + expect(described_class::search? '560029, 560030, 110011').to eq(['560029', '560030', '110011']) + expect(described_class::search? 'bangalore 560029').to eq(['560029']) + expect(described_class::search? 'bangalore 1').to eq([]) + end end