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; } } } } }