140 lines
3.3 KiB
Vala
140 lines
3.3 KiB
Vala
namespace Sernatur {
|
|
namespace Person {
|
|
|
|
public errordomain InvalidRut {
|
|
INVALID,
|
|
TOOLARGE,
|
|
INVALIDVERIFIER
|
|
}
|
|
|
|
public class Rut : GLib.Object {
|
|
private string clean_rut;
|
|
private string pretty_rut;
|
|
private unichar verifier;
|
|
|
|
public enum Type {
|
|
RUN,
|
|
RUT
|
|
}
|
|
|
|
public Rut (string rut) throws InvalidRut {
|
|
parse (rut);
|
|
}
|
|
|
|
private void parse (string rut) throws InvalidRut {
|
|
try {
|
|
var regex = new Regex ("^[ ]*([0-9.]{0,11}[\\-]?[0-9kK])?[ ]*$");
|
|
if (!regex.match (rut)) {
|
|
throw new InvalidRut.INVALID (dgettext (null, "The RUT %s has an invalid character!"), rut);
|
|
}
|
|
}
|
|
catch (Error e) {
|
|
#if DEBUG
|
|
error (e.message);
|
|
#else
|
|
warning (e.message);
|
|
#endif
|
|
}
|
|
try {
|
|
var regex = new Regex ("([.-])");
|
|
string new_rut = rut.up ();
|
|
new_rut = new_rut.strip ();
|
|
rut = regex.replace (new_rut, new_rut.length, 0, "");
|
|
if (int.parse (rut.substring (0, rut.length - 1)) > 100000000) {
|
|
throw new InvalidRut.TOOLARGE (dgettext (null, "The RUT %s is too big!"), rut);
|
|
}
|
|
this.verifier = rut.get_char (rut.length - 1);
|
|
this.clean_rut = rut.substring (0, rut.length - 1);
|
|
if (generate_verfifier (this.clean_rut) != this.verifier) {
|
|
throw new InvalidRut.INVALIDVERIFIER (dgettext (null, "The verifier %C is invalid!"), this.verifier);
|
|
}
|
|
pretty();
|
|
}
|
|
catch (Error e) {
|
|
#if DEBUG
|
|
error (e.message);
|
|
#else
|
|
warning (e.message);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
private void pretty () {
|
|
string new_rut = "";
|
|
string temp_rut = this.clean_rut.reverse ();
|
|
int rut_length = this.clean_rut.length;
|
|
for (int i = 0; i < rut_length; i++) {
|
|
new_rut = new_rut + temp_rut.get_char(i).to_string ();
|
|
if ((i + 1) % 3 == 0) {
|
|
new_rut = new_rut + ".";
|
|
}
|
|
}
|
|
new_rut = new_rut.reverse ();
|
|
this.pretty_rut = new_rut + "-" + this.verifier.to_string ();
|
|
}
|
|
|
|
private unichar generate_verfifier (string rut) {
|
|
/**
|
|
* 1. Multiply each digit of the RUT by 2, 3, ..., 7, 2, 3, ... from the end of the RUT moving forward.
|
|
* 2. Add the partial multiplications.
|
|
* 3. Calculate the remainder of the division by 11.
|
|
* 4. The verifier is 11 minus the previous result. If the result is 10, change it to K.
|
|
*/
|
|
int multiplier = 2;
|
|
int sum = 0;
|
|
int remainder;
|
|
int division;
|
|
int rut_length = rut.length;
|
|
|
|
// Steps 1 and 2
|
|
for (int i = rut_length - 1; i >= 0; i--) {
|
|
sum = sum + (int.parse (rut.substring(i, 1)) * multiplier);
|
|
multiplier++;
|
|
if (multiplier == 8) {
|
|
multiplier = 2;
|
|
}
|
|
}
|
|
|
|
// Step 3
|
|
division = sum / 11;
|
|
division = division * 11;
|
|
remainder = sum - division;
|
|
|
|
// Step 4
|
|
if (remainder != 0) {
|
|
remainder = 11 - remainder;
|
|
}
|
|
|
|
// Let's return their verifier
|
|
if (remainder == 10) {
|
|
// Their verifier is 10 so let's return K.
|
|
return 'K';
|
|
}
|
|
else {
|
|
return (unichar) remainder + '0';
|
|
}
|
|
}
|
|
|
|
public string get_clean_rut () {
|
|
return this.clean_rut + this.verifier.to_string ();
|
|
}
|
|
|
|
public string get_rut () {
|
|
return this.pretty_rut;
|
|
}
|
|
|
|
public Type type () {
|
|
uint rut = int.parse (this.clean_rut);
|
|
if (rut < 100000000 && rut > 50000000) {
|
|
// Company
|
|
return Type.RUT;
|
|
}
|
|
else {
|
|
// Person
|
|
return Type.RUN;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|