sernatur/lib/rut.vala
2019-01-05 00:28:18 -03:00

141 lines
3.4 KiB
Vala

namespace LibSernatur {
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 {
// Add the '0' to convert from int to unichar
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;
}
}
}
}
}