Re: I'm struggling with a function, and hoping for some insight -- not strictly Perl
by smls (Friar) on May 18, 2014 at 11:20 UTC
|
Your function considers an input string as valid, if (after sanitizing) it either matches a certain regex, or passes a certain check digit algorithm.
There are many standardized check digit algorithms in use; if you need to find out which one you're dealing with here, maybe this Wikipedia page can help.
Edit: As it turns out, it's the Luhn algorithm.
Anyway, here is a more or less literal translation of your code to to Perl with many explanatory comments (keeping in mind that I had to make an educated guess about the non-standard function discussed in a separate answer above):
#!/usr/bin/perl
use strict;
use warnings;
use feature 'say';
sub validate_serial_number {
my $v = shift;
$v =~ s/\s//g; # remove whitespace
$v = uc $v; # convert to uppercase
# 1) Try regex:
return 0 if !length $v;
return 1 if $v =~ /^JM-\d+-\S{4}[1-9Zz]{6}$/;
# 2) Initialize the %map hash with (A=>0, B=>1, C=>2, ...):
my $dv = 0;
my %map = map { $_ => $dv++ }
qw(A B C D E F G H J K L M N P Q R T U V W Y 3 4 6 7 8 9);
# 3) Extract significant character data, for example:
# 'FOOBAR123ABCDE' -> chars: qw(D C B A 3 R A B F)
# check: 'E'
my @chars = reverse split '', $v;
my $check = shift @chars;
@chars = grep { exists $map{$_} } @chars;
# 4) Sanity check:
return 0 if @chars != 9;
# 5) Perform check digit algorithm:
my $totalVal = 0;
# Loop over the reversed array of input characters:
for my $i (0..$#chars) {
# Map the character to a unique numeric value:
my $posVal = $map{$chars[$i]};
# Double the value, but only for every second character:
$posVal *= 2 if !($i % 2);
# Add the sum of the digits of $posVal to $totalVal:
while($posVal){
$totalVal += $posVal % 10;
$posVal = int($posVal / 10);
}
}
# Substract the last digit of $totalVal from 10, and take the
# last digit of *that* to get the check digit:
return ( $check eq ( 10 - $totalVal % 10 ) % 10 );
}
for ('Foo abr 123 ABCD6',
'Foo bar 123 ABCD6') {
say "'$_' is " . (validate_serial_number($_) ? "valid" : "invalid");
}
Output:
'Foo abr 123 ABCD6' is invalid
'Foo bar 123 ABCD6' is valid
| [reply] [d/l] [select] |
|
|
Hello, smls, and thank you VERY much for an over-the-top reply!
The Points Fairy thought so too. :)
In all fairness to anyone looking to respond; I should have probably noted in the OP, that I think my difficulty in following the logic, or flow, seemed to be with my apparent lack of knowledge with the map function. The use of split in the code here, might also be a factor. But, where split is concerned, may well be related to my lack of experience with map, or because this is in JavaScript, not Perl.
Thanks again, smls, for such an informative reply!
--Chris
¡λɐp ʇɑəɹ⅁ ɐ əʌɐɥ puɐ ʻꜱdləɥ ꜱᴉɥʇ ədoH
| [reply] |
Re: I'm struggling with a function, and hoping for some insight -- not strictly Perl
by smls (Friar) on May 18, 2014 at 09:14 UTC
|
$w('A B C D E F G H J K L M N P Q R T U V W Y 3 4 6 7 8 9').each(
function(d){ map[d] = dv++; }
);
^^ This looks very similar to jQuery syntax for looping over DOM elements. For example you could loop over all "div" elements of a web page, and do something with each of them, using this jQuery syntax:
$( "div" ).each(function(i) {
// in here, 'this' can be used to refer to the current DOM
// element, whereas 'i' contains the loop index
});
$ is not a sigil, it is the name of a function defined by the jQuery library.
In your code, a similar-behaving function called $w is used. It will probably help your reverse-engineering effort if you could find out where that function is defined, and what exactly it does.
Update: Looks like it may be simply doing what Perl's qw(...) quote-like operator does...
Edit: Moved Perl translation and high-level discussion to a separate answer.
| [reply] [d/l] [select] |
Re: I'm struggling with a function, and hoping for some insight -- not strictly Perl
by boftx (Deacon) on May 18, 2014 at 08:15 UTC
|
What part of it is giving you trouble? I don't quite understand all of it myself, but I can see right off the top that the missing letters from the $w array(?) correspond to the the missing numerals in that 'I', 'O', 'S' and 'Z' could be confused for the numerals '1', '0', '5' and '2'.
This leads me to think this is some form of CAPTCHA field.
It helps to remember that the primary goal is to drain the swamp even when you are hip-deep in alligators.
| [reply] |
|
|
Hello, boftx!
How's the weather down in TX?
Hey. Your answer makes me feel better, that I can't quite follow it. :)
Good guess. But not quite. It's actually a number validation; which you pretty much guessed. But it's not for CAPTCHA, it's a SERIAL number. :) No. I'm NOT attempting to thwart some PAY-FOR application. I found a link to an application I thought I'd (and others might) like to use. Problem was, the site, and application had apparently been abandoned. So, after much detective work. I was able to get ahold of the author, and inquired as to what it would take to continue development on the application. He said I could have it, but on the condition that it was AS-IS, and WITHOUT ANY support from him.
Apparently he'd used it for income, but got a real mucky-muck job, and position in a big mucky-muck firm. So had no more interest, or time for it.
Well I accepted his offer, and have been working with it since.
I simply nuked the serial function(s). But they seemed so clever (to me, anyway) that I thought it'd be well worth the effort to understand it better.
So here I am, asking/begging. :)
Thanks for the reply, boftx!
--Chris
¡λɐp ʇɑəɹ⅁ ɐ əʌɐɥ puɐ ʻꜱdləɥ ꜱᴉɥʇ ədoH
| [reply] |
|
|
More on topic, I'm not a big fan of having validation like that on the client side (assuming it is client-side since it is js.) I'd much rather see it done server-side through an AJAX call if you don't want to cycle through a page reload. Can you move it there and write it in Perl? (For those who are picky, "Perl" is the language, "perl" is the program.)
It helps to remember that the primary goal is to drain the swamp even when you are hip-deep in alligators.
| [reply] |
|
|
Sorry I couldn't help more, maybe a couple more shots of Scotch will help me.
BTW, I'm back in Vegas. Apparently $work thinks I'm good enough that they want me to be happy and will let me work remote from home. :)
It helps to remember that the primary goal is to drain the swamp even when you are hip-deep in alligators.
| [reply] |
|
|
|
|
Re: I'm struggling with a function, and hoping for some insight -- not strictly Perl
by Anonymous Monk on May 18, 2014 at 10:33 UTC
|
might help me better understand it. For what purpose? I would study the documentation first :)
It seems quite clever Also seems like junk not coping with scoping very well and poor variable names ... and incomplete, no wonder understanding it is hard
JSHint, a JavaScript Code Quality Tool
| [reply] |
Re: I'm struggling with a function, and hoping for some insight -- not strictly Perl
by Anonymous Monk on May 18, 2014 at 15:07 UTC
|
JavaScript logic is always hard to follow because it usually doesn't have comments or many blank lines ... even when it isn't "min-ized." Sometimes the logic is obfuscatory, maybe because someone thought it was faster and maybe it was. If there are particular portions of the logic that you're looking at -- say, regexes, or "each()" -- these would certainly qualify as legitimate Perl-ish questions and we can help. Target your questions . . . | [reply] |