unit SlownieFn;
(*
	SŁOWNIE - moduł konwersji kwoty na tekst
	----------------------------------------
	(c) 2011 michal@glebowski.pl, e-storm.pl
		licencja: freeware / GNU GPL 2.1
		autor nie ponosi odpowiedzialności za szkody wyrządzone przez kod
*)
interface
  function slownie(x: Extended): String;
  procedure test();

implementation

uses SysUtils;
const zerogroszy = True;

procedure test();
begin
  WriteLn(slownie(0.01));
  WriteLn(slownie(1.00));
  WriteLn(slownie(-1000.00));
  WriteLn(slownie(1234567890.12));
  ReadLn;
end;

function Ad(s1, s2: String): String;
begin
  if (s1 <> '') and (s2 <> '') then Result := s1 + ' ' + s2
                               else Result := s1 + s2;
end;

function liczba(w: Integer; s: String): String;
const
  d1 : array[0..9] of String = ('', 'jeden', 'dwa', 'trzy', 'cztery', 'pięć', 'sześć', 'siedem', 'osiem', 'dziewięć');
  d2 : array[0..9] of String = ('', 'dziesięć', 'dwadzieścia', 'trzydzieści', 'czterdzieści', 'pięćdziesiąt', 'sześćdziesiąt', 'siedemdziesiąt', 'osiemdziesiąt', 'dziewięćdziesiąt');
  d3 : array[0..9] of String = ('', 'sto', 'dwieście', 'trzysta', 'czterysta', 'pięćset', 'sześćset', 'siedemset', 'osiemset', 'dziewięćset');
  dx : array[0..9] of String = ('dziesięć', 'jedenaście', 'dwanaście', 'trzynaście', 'czternaście', 'piętnaście', 'szesnaście', 'siednaście', 'osiemnście', 'dziewiętnaście');
begin
  Result := d3[StrToInt(s[1])];
  if StrToInt(s[2]) = 1 then Result := Ad(Result, dx[StrToInt(s[3])])
                        else Result := Ad(Ad(Result, d2[StrToInt(s[2])]), d1[StrToInt(s[3])]);
  if (w > 0) and (Result = d1[1]) then Result := '';
end;

function slowo(w: Integer; s: String): String;
const
  w1 : array[0..2] of String = ('tysiąc',  'tysiące',   'tysięcy');
  w2 : array[0..2] of String = ('milion',  'miliony',   'milionów');
  w3 : array[0..2] of String = ('miliard', 'miliardy',  'miliardów');
  w4 : array[0..2] of String = ('bilion',  'biliony',   'bilionów');
  wz : array[0..2] of String = ('złoty',   'złote',     'złotych');
  wg : array[0..2] of String = ('grosz',   'grosze',    'groszy');
var
  n, j, k: Int64;
begin
  j := StrToInt64(s);
  if j = 1 then n := 0 else n := 2;
  j := StrToInt(s[length(s)]);
  k := StrToInt(s[length(s)-1]);
  if (j > 1) and (j < 5) and (k <> 1) then n := 1;
  if w =  0 then Result := ''    else
  if w =  1 then Result := w1[n] else
  if w =  2 then Result := w2[n] else
  if w =  3 then Result := w3[n] else
  if w =  4 then Result := w4[n] else
  if w = 20 then Result := wz[n] else
  if w = 21 then Result := wg[n];
end;

function slownie(x: Extended): String;
var
  p : Int64;    // get tens xxxx or decimals yy ( xxxx,yy )
  s : String;   // string representation of xxxx or yy
  w : Integer;  // triple counter iterator
  c : String;   // current triple value
  m : Boolean;
begin
  Result := '';
  m := x < 0;
  if m then x := -x;
  p := Trunc(x);    // 123456789012
  s := IntToStr(p); // "123456789012" (123-456-789-012)
  while length(s) mod 3 <> 0 do s := '0' + s;
  for w := 0 to 4 do
    if length(s)>w*3 then begin
      c      := copy(s, length(s)-w*3-2, 3); // i=0 => "012", i=1 => "789"
      if c <> '000' then // 2015-06-15 FIX!!!      
        Result := Ad(Ad(liczba(w, c), slowo(w, c)), Result);
    end;
  if Result = '' then Result := 'zero';
  Result := Ad(Result, slowo(20, s));

  p := Round((x - p) * 100);
  if p > 0 then begin
    s      := IntToStr(p);
    while length(s) mod 3 <> 0 do s := '0' + s;
    Result := Ad(Result, Ad(liczba(0, s), slowo(0, s)));
    Result := Ad(Result, slowo(21, s));
  end else
    if zerogroszy then Result := Ad(Result, 'zero groszy');

  if m then Result := Ad('minus', Result);
end;

end.