Sosiaaliturvatunnuksen tarkistus Angular-direktiivillä

Jep, tuli tarpeeseen ihmetellä Angularin direktiivejä ja validointia – miten sosiaaliturvatunnuksen oikeellisuus validoidaan? Tähän ei löytynyt pikaisella haulla valmista ratkaisua joten ei muuta kuin tekemään oma.

Suomalaista sosiaaliturvatunnusta kun ihmetellään, niin osan tarkistuksista voi hoitaa ihan olemassaolevilla direktiiveillä. Esim. pituus tasan 11 merkkiä, aina. Tunnuksen muodon osalta voi olettaa siinä olevan numeroita ensin kuusi, sitten välimerkki jossa on muuutamia mahdollisuuksia, sitten kolme numeroa, ja tarkistuskoodi joka voi olla numero tai kirjain tietystä valikoimasta. Tämä hoituu komeasti esim. Angularin regex-patternilla.

Mutta syy miksi kirjoitan tätä blogia itselleni muistiin on nimenomaan tuon viimeisen merkin tarkistussumman laskeminen, ja oman custom validation direktiivin teko. Se menee nimittäin näin:

(function() {
  angular.module('app').directive('validSsn', validSSN);

  validSSN.$inject = ['$log'];

  function validSSN($log) {
    var checksumChars = 'abcdefhjklmnprstuvwxy';

    var validateSSN = function(value) {
      if (value === undefined || value.length != 11) {
        return false;
      }
      var datePart = value.substr(0, 6);
      var individualNumber = value.substr(7, 3);
      var checkSumCharacter = value.substr(10).toLowerCase();
      var dividedValueModulo = parseInt(
          String(datePart) + String(individualNumber)) % 31;
      var expected;
      if (dividedValueModulo < 10) {
        expected = String(dividedValueModulo);
      } else {
        expected = checksumChars.charAt(dividedValueModulo - 10);
      }
      if (checkSumCharacter === expected) {
        return true;
      } else {
        $log.debug('Expected checksum ', expected,
          ', got checksum ', checkSumCharacter);
        return false;
      }
    };

    return {
      restrict: 'A',
      require: 'ngModel',
      link: function(scope, elem, attr, ctrl) {
        ctrl.$parsers.unshift(function(value) {
          var valid = validateSSN(value);
          ctrl.$setValidity('valid-ssn', valid);
          return value;
        });

        ctrl.$formatters.unshift(function(value) {
          var valid = validateSSN(value);
          ctrl.$setValidity('valid-ssn', valid);
          return value;
        });

      }
    };
  }
}());

No niin, tuossa on vielä paljonkin siistittävää ja optimoitavaa, mutta jätetään se itsekunkin omaksi harjoitukseksi. Idea käy silti ilmi. Katsotaan ensin että arvo on olemassa ja oikean mittainen – ellei, se automaattisti ei läpäise validointia. Jos mitta on oikea, otetaan kaikki data-osan numerot, 9 kappaletta, merkkijonona, ja jaetaan alkuluvulla 31. Jakojäännös kiinnostaa – jos se on alle 10 se on suoraan tarkistuskoodi, jos se on 10 tai yli, verrataan kirjaintaulukkoon josta on muutama kirjain selvyyden vuoksi poistettu.

Sitä voi testata esim. näin:

it('should pass validation with valid ssn', function() {

  var element =
        $compile(
          '<form name="form">' +
            '<input valid-ssn name="ssn" ng-model="value" />' +
          '</form>')($rootScope);
  var form = $rootScope.form;

  $rootScope.value = '140785-940X';
  $rootScope.$digest();
  expect(form.ssn.$valid).toBeTruthy();

  $rootScope.value = '140785-940x';
  $rootScope.$digest();
  expect(form.ssn.$valid).toBeTruthy();

  $rootScope.value = '140785-9143';
  $rootScope.$digest();
  expect(form.ssn.$valid).toBeTruthy();

});

Tällaista tällä kertaa. Jos hommaa haluaisi vielä kehittää. voi toki tarkistaa että päivämäärä on oikea, sukupuoli vastaa muualla annettua tietoa, if any, jne.

Mainokset

IoT: Go home PI, you’re drunk!

Internet of Things on kiehtonut omaa mieltä jo pitkään ennen kuin termi edes keksittiin: Se on pääosin se asia joka nykypäivän communicator/mobile device kategorian laitteissa ja älypuettavissakin kiehtoo. Älykkäiden verkottuneiden laitteiden mahdollisuudet ja uhat. Nyt tuli sitten aika pistää äly pyörille.

2015-07-05 17.27.22

Nykypäivänä on helpompaa kuin koskaan näperrellä ja prototypoida näiden parissa: Raspberry Pi tietokoneet ovat halpoja ja niihin saa kiinnitettyä oikeastaan mitä vain mielikuvitus loihtii. Olen itse rakennellut niihin aiemmin kokeilumielessä full stack raskasta Java EE ratkaisua, milloin MySQL kannan, milloin MongoDB:n kera ohjaamaan kodin automaatiota. Tuli kokeiltua sekin miten Glassfish sovelluspalvelin pyörähtää käyntiin: Ihan hienosti, jopa ihan ykkösgeneraation Raspissa.

Tällä kertaa halusin kokeilla jotain uutta. Muutama vuosi takaperin JavaOne seminaarissa osallistuin autokilpailuun jossa koodailtiin autoihin algoritmia jolla ne ajaisivat lujaa mutta pysyisivät radalla. Siitä jäi ajatus itämään. Hiljattain tutkin Lego Mindstorm EVO paketteja, mutta ne tuntuivat rajoittuneilta, ja kalliilta kokeiluun nähden. Niihinkin löytyy toki nykyään BrickPi-laajennus jolla voi laittaa Raspberryn käskemään EVO kontrollereita ja sensoreita. Mutta itselleni haaviin jäi GoPiGo-alusta. Moottorit, pieni kontrolleri joka kytkeytyy suoraan Pin kylkeen, virtapaketti joka toimii pattereilla ja irrottaa laitteen virtapiuhan tyranniasta. Go, Pi, Go, feel the wind in your electronic hairs! 😉

2015-07-05 17.27.05

Eli tilaukseen napsahti, ja ei kun testailemaan. GoPiGo web sitelta sai latailla valmiin imagen joka pohjautui jo tuttuun Raspbianiin, ja toimi ihan ok, kunhan viritin sen langattomaan kotiverkkoon ja kävin läpi alustusrutiinit. Sieltä löyty esimerkkejä mm. Pythonilla, Javalla, ja testailin niiden avulla että olin koonnut kaiken oikein ja piuhat olivat paikallaan. Mutta kuten sanottua, tällä kertaa oli tarkoitus tehdä jotain uutta.

Joten päädyin viritykseen, jossa ytimen muodostaa node.js palvelin. Viritin sen automaattikäynnistymään Raspin myötä. Automaattikäynnistys tapahtuu ihan init.d scripteillä, ja apuna käyttelin forever + nodemon yhdistelmää, jotta prosessi päivittää itsensä kun koodeja päivitetään, ja myös jos se sattuisi kaatumaan.

Palvelin initialisoi GoPiGo osan, ja kiinnittää pari tapahtumankuuntelijaa, mm. varoittamaan jos virta käy vähiin pattereissa. Ja lataa html-sivun jonka kautta raspia voi ohjailla. Tuossa vähän maistiaista miltä sen pään koodi näyttää:

socket.on('status', function(msg){
  $('#messages').append($('<li>').text(msg));
});
$('#forward').click(function() {
  socket.emit('command','move forward');
});
$('#backward').click(function() {
  socket.emit('command','move backward');
});

Halusin rivakkuutta ohjaukseen joten websocketeilla mennään. Tarkemmin, socket.io nykyisellä inkarnaatiolla. Käyttöliittymä on tässä kohtaa karu – pelkkää html:ää ja jquerya. Vähän kutkuttaisi päästää Aurelia irti tässä kohtaa. Käytännössä siis websocket kanavalla liikkuu kahteen suuntaan tavaraa: status viestit menevät ’status’ kanavalle, ja näytetään ’client’ päässä. Komennot lähetetään ’commands’ kanavalle, ja voivat olla esim. mene eteenpäin, pysähdy, käänny, laita ledejä päälle, jne.

Ja sehän toimii. Hienosti. Jopa ihan Android kännykästä käsin. Sillä oli kiva kiusata kissoja ja koiraa 😉

2015-07-05 17.33.55

2015-07-01 22.21.13

Mitähän hittoa tällä sitten tekee? No ei yhtikäs mitään. Mutta mielenkiintoinen harjoite taas keveiden pikku älylaitteiden maailmassa, nodejs tuntuisi olevan mukavan keveä ratkaisu tämäntapaiseen hommaan, ja Raspberry Pi tuntuu Noden kanssa tarjoavan kaikki tarpeelliset palaset että prosessin saa pyörimään luotettavasti ja itsenäisesti.

Seuraavia askelia:

– pistä UI päähän jotain fiksumpaa ja helpompaa kehitysframeworkia, esim. Aurelia.

– Kiinnitä pakkaan sensoreita, esim. mikroaaltotutka, kamera, servoja.

– Opeta robotille Asimovin kolme periaatetta ettei käy kuin Volkswagenin tehtailla

– Laita laite tuomaan kylmä olut kun se aistii sille tarpeen.

– Ja ampumaan raketteja devaajan päähän joka taas /&%/&% rikkoi sen buildin! Tässä voidaan vähän joustaa Asimov-periaatteiden kanssa.

http://www.dexterindustries.com/GoPiGo/projects/python-examples-for-the-raspberry-pi/raspberry-pi-controlled-office-cannon/

ES6: It’s a better monster!

Kirjailin taannoin Aurelia-nimisestä Javascript sovelluskehyksestä joka teki vaikutuksen. Yksi suurimpia osia miksi se kiinnosti oli helppo kyvykkyys alkaa heti käyttämään JavaScriptin/ECMAScriptin versiota 6. Se taas kiinnosti kahdesta syystä: Ensimmäinen on halu pitää nokka aina menosuuntaan: muuten putoaa helposti rattailta. Toinen on, että ES6 tarjoaa lukuisia sovelluskehittäjälle oikeasti laatua parantavia tekijöitä jahka se vain saadaan laajemmin käyttöön. Ja näin inspiroiduin kirjoittamaan vähän sen nykytilasta.

Nykyisellään selaimissa käytetään yleisimmin ECMAScript versiota 5 – tai 5.1 – ja versio 6 on ollut työnimellä Harmony työstettävänä jo jonkin aikaa. ES6 saatiin spesifikaationa viimein valmiiksi tämän vuoden toukokuussa.

Selaintuki on aina määräävä tekijä: Tätä artikkelia kirjoittaessa parhaiten ES6:sta tukee Firefox versio 40 – hurjalla 63% ominaisuustuella. Pienenä yllätyksenä kakkossijan jakavat Firefoxin versio 39 – ja Microsoftin tuleva Edge/Spartan selain joka tulee syrjäyttämään jo tammikuusta alkaen IE8-11 versiot joiden tuki lakkautetaan. Chrome ei ole ihan vielä näissä ajan tasalla – ominaisuuksia on tuettu n. 45% hujakoilla. Safarilta ja IE10/11 versioilta saati sitten vanhemmilta ei kannata näistä edes kysellä – tulee turhaan paha mieli. Ja mobiililaitteiden selaintuki on toki ihan oma lukunsa.

Onneksi on myös Babel/6to5 transpiler jota myös Aurelia käyttää – se osaa tarvittaessa kääntää ES6 syntaksia ES5 yhteensopivaksi jotta piirteet toimivat myös vanhoissa selaimissa – jep, aina pahamaiseiseen IE9:ään asti. Tämän avulla uusia piirteitä voi alkaa jo käyttelemään projekteissa joissa on tarpeen tukea laajaa selainkirjoa.

Mitä sieltä sitten löytyy? Miksi kannattaisi alkaa käyttämään ES6:sta? No siitä taidan tehdä ihan toisen artikkelin, sen verran mehukas aihe. Mutta tuossa itselle muistilistaa:

  • Vakiot (tai siis immutable muuttujat…)
  • Scope käyttö
  • Nuolifunktio (lambda syntaksi)
  • Parannukset this-avainsanaan
  • Tuki moduuleille, import/export
  • Parannukset luokkiin/objekteihin
  • Promise/Rinnakkaisuusmekanismit
  • Iteraattorit
  • Kokoelmaparannukset

Pysykäähän kuulolla…

Linkkejä:

http://www.ecma-international.org/ecma-262/6.0/ECMA-262.pdf

https://kangax.github.io/compat-table/es6/