File Coverage

blib/lib/Lingua/THA/Num2Word.pm
Criterion Covered Total %
statement 27 71 38.0
branch 2 42 4.7
condition 4 42 9.5
subroutine 9 12 75.0
pod 3 3 100.0
total 45 170 26.4


line stmt bran cond sub pod time code
1             # For Emacs: -*- mode:cperl; eval: (folding-mode 1); coding:utf-8 -*-
2              
3             package Lingua::THA::Num2Word;
4             # ABSTRACT: Number to word conversion in Thai
5              
6 1     1   86564 use 5.16.0;
  1         3  
7 1     1   4 use utf8;
  1         1  
  1         11  
8 1     1   20 use warnings;
  1         1  
  1         54  
9              
10             # {{{ use block
11              
12 1     1   5 use Carp;
  1         2  
  1         67  
13 1     1   538 use Export::Attrs;
  1         9469  
  1         6  
14 1     1   766 use Readonly;
  1         3267  
  1         563  
15              
16             # }}}
17             # {{{ variable declarations
18              
19             my Readonly::Scalar $COPY = 'Copyright (c) PetaMem, s.r.o. 2002-present';
20             our $VERSION = '0.2603300';
21              
22             # }}}
23              
24             # {{{ num2tha_cardinal convert number to text
25              
26             sub num2tha_cardinal :Export {
27 2     2 1 139453 my $positive = shift;
28              
29 2 50 33     25 croak 'You should specify a number from interval [0, 999_999_999]'
      33        
      33        
30             if !defined $positive
31             || $positive !~ m{\A\d+\z}xms
32             || $positive < 0
33             || $positive > 999_999_999;
34              
35 2         11 my @units = qw(ศูนย์ หนึ่ง สอง สาม สี่ ห้า หก เจ็ด แปด เก้า);
36              
37 2 50 33     12 return $units[$positive] if ($positive >= 0 && $positive <= 9);
38 0 0         return 'สิบ' if ($positive == 10);
39              
40 0           my $out = '';
41 0           my $remain;
42              
43             # Helper: append remainder, substituting เอ็ด for bare หนึ่ง in compounds.
44             # In Thai, the digit 1 in the units position of any compound number
45             # is always เอ็ด (et), never หนึ่ง (nueng).
46             my $append_remain = sub {
47 0     0     my ($so_far, $r) = @_;
48 0 0         if ($r == 1) {
49 0           return $so_far . 'เอ็ด';
50             }
51 0           return $so_far . num2tha_cardinal($r);
52 0           };
53              
54 0 0 0       if ($positive > 10 && $positive < 20) { # 11 .. 19
    0 0        
    0 0        
    0 0        
    0 0        
    0 0        
    0 0        
55 0           $remain = $positive % 10;
56 0           $out = 'สิบ';
57 0 0         $out .= $remain == 1 ? 'เอ็ด' : $units[$remain];
58             }
59             elsif ($positive >= 20 && $positive < 100) { # 20 .. 99
60 0           my $tens = int($positive / 10);
61 0           $remain = $positive % 10;
62              
63 0 0         $out = $tens == 2 ? 'ยี่' : $units[$tens];
64 0           $out .= 'สิบ';
65 0 0         if ($remain) {
66 0 0         $out .= $remain == 1 ? 'เอ็ด' : $units[$remain];
67             }
68             }
69             elsif ($positive >= 100 && $positive < 1000) { # 100 .. 999
70 0           my $hundreds = int($positive / 100);
71 0           $remain = $positive % 100;
72              
73 0           $out = $units[$hundreds] . 'ร้อย';
74 0 0         $out = $append_remain->($out, $remain) if $remain;
75             }
76             elsif ($positive >= 1000 && $positive < 10_000) { # 1_000 .. 9_999
77 0           my $thousands = int($positive / 1000);
78 0           $remain = $positive % 1000;
79              
80 0           $out = $units[$thousands] . 'พัน';
81 0 0         $out = $append_remain->($out, $remain) if $remain;
82             }
83             elsif ($positive >= 10_000 && $positive < 100_000) { # 10_000 .. 99_999
84 0           my $ten_thousands = int($positive / 10000);
85 0           $remain = $positive % 10000;
86              
87 0           $out = $units[$ten_thousands] . 'หมื่น';
88 0 0         $out = $append_remain->($out, $remain) if $remain;
89             }
90             elsif ($positive >= 100_000 && $positive < 1_000_000) { # 100_000 .. 999_999
91 0           my $hundred_thousands = int($positive / 100000);
92 0           $remain = $positive % 100000;
93              
94 0           $out = $units[$hundred_thousands] . 'แสน';
95 0 0         $out = $append_remain->($out, $remain) if $remain;
96             }
97             elsif ($positive >= 1_000_000 && $positive < 1_000_000_000) { # 1_000_000 .. 999_999_999
98 0           my $millions = int($positive / 1_000_000);
99 0           $remain = $positive % 1_000_000;
100              
101 0           $out = num2tha_cardinal($millions) . 'ล้าน';
102 0 0         $out = $append_remain->($out, $remain) if $remain;
103             }
104              
105 0           return $out;
106 1     1   8 }
  1         1  
  1         8  
107              
108             # }}}
109              
110              
111             # {{{ num2tha_ordinal convert number to ordinal text
112              
113             sub num2tha_ordinal :Export {
114 0     0 1   my $number = shift;
115              
116 0 0 0       croak 'You should specify a number from interval [1, 999_999_999]'
      0        
      0        
117             if !defined $number
118             || $number !~ m{\A\d+\z}xms
119             || $number < 1
120             || $number > 999_999_999;
121              
122             # Thai ordinals: ที่ (thi) + cardinal
123 0           my $cardinal = num2tha_cardinal($number);
124              
125 0           return 'ที่' . $cardinal;
126 1     1   396 }
  1         5  
  1         7  
127              
128             # }}}
129              
130             # {{{ capabilities declare supported features
131              
132             sub capabilities {
133             return {
134 0     0 1   cardinal => 1,
135             ordinal => 1,
136             };
137             }
138              
139             # }}}
140             1;
141              
142             __END__