Skip to content

Commit

Permalink
feat/pronounce_digits (MycroftAI#21)
Browse files Browse the repository at this point in the history
Co-authored-by: jarbasal <jarbasai@mailfence.com>
  • Loading branch information
JarbasAl and JarbasAl authored May 9, 2021
1 parent cfbbd19 commit 2812840
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 7 deletions.
29 changes: 23 additions & 6 deletions lingua_nostra/format.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
from warnings import warn
from os.path import join


from lingua_nostra.bracket_expansion import SentenceTreeParser
from lingua_nostra.internal import localized_function, \
populate_localized_function_dict, get_active_langs, \
Expand All @@ -30,10 +29,10 @@
UnsupportedLanguageError, NoneLangWarning, InvalidLangWarning, \
FunctionNotLocalizedError


_REGISTERED_FUNCTIONS = ("nice_number",
"nice_time",
"pronounce_number",
"pronounce_digits",
"nice_response",
"nice_duration")

Expand Down Expand Up @@ -119,12 +118,12 @@ def _number_strings(self, number, lang):
str(int(number % 100 / 10))) or str(int(number % 100 / 10))
x0 = (self.lang_config[lang]['number'].get(
str(int(number % 100 / 10) * 10)) or
str(int(number % 100 / 10) * 10))
str(int(number % 100 / 10) * 10))
xxx = (self.lang_config[lang]['number'].get(str(number % 1000)) or
str(number % 1000))
x00 = (self.lang_config[lang]['number'].get(str(int(
number % 1000 / 100) * 100)) or
str(int(number % 1000 / 100) * 100))
str(int(number % 1000 / 100) * 100))
x_in_x00 = self.lang_config[lang]['number'].get(str(int(
number % 1000 / 100))) or str(int(number % 1000 / 100))
xx00 = self.lang_config[lang]['number'].get(str(int(
Expand All @@ -134,11 +133,12 @@ def _number_strings(self, number, lang):
number % 10000 / 100))) or str(int(number % 10000 / 100))
x000 = (self.lang_config[lang]['number'].get(str(int(
number % 10000 / 1000) * 1000)) or
str(int(number % 10000 / 1000) * 1000))
str(int(number % 10000 / 1000) * 1000))
x_in_x000 = self.lang_config[lang]['number'].get(str(int(
number % 10000 / 1000))) or str(int(number % 10000 / 1000))
x0_in_x000 = self.lang_config[lang]['number'].get(str(int(
number % 10000 / 1000) * 10)) or str(int(number % 10000 / 1000) * 10)
number % 10000 / 1000) * 10)) or str(
int(number % 10000 / 1000) * 10)
x_in_0x00 = self.lang_config[lang]['number'].get(str(int(
number % 1000 / 100)) or str(int(number % 1000 / 100)))

Expand Down Expand Up @@ -305,6 +305,23 @@ def pronounce_number(number, lang='', places=2, short_scale=True,
"""


@localized_function()
def pronounce_digits(number, lang=None, places=2, all_digits=False):
"""
Pronounce a number's digits, either colloquially or in full
In English, the colloquial way is usually to read two digits at a time,
treating each pair as a single number.
Examples:
>>> pronounce_number(127, all_digits=False)
'one twenty seven'
>>> pronounce_number(127, all_digits=True)
'one two seven'
Args:
number (int|float)
all_digits (bool): read every digit, rather than two digits at a time
"""


def nice_date(dt, lang='', now=None):
"""
Format a datetime to a pronounceable date
Expand Down
38 changes: 37 additions & 1 deletion lingua_nostra/lang/format_en.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#

from math import modf
from lingua_nostra.lang.format_common import convert_to_mixed_fraction
from lingua_nostra.lang.common_data_en import _NUM_STRING_EN, \
_FRACTION_STRING_EN, _LONG_SCALE_EN, _SHORT_SCALE_EN, _SHORT_ORDINAL_EN, _LONG_ORDINAL_EN
Expand Down Expand Up @@ -65,6 +65,42 @@ def nice_number_en(number, speech=True, denominators=range(1, 21)):
return return_string


def pronounce_digits_en(number, places=2, all_digits=False):
if isinstance(number, str):
op_val = number
decimal_part = ""
if "." in number:
op_val, decimal_part = number.split(".")
if all_digits:
op_val = " ".join([pronounce_number_en(int(ch))
for ch in op_val])
else:

op_val = pronounce_number_en(int(op_val))
if decimal_part:
decimal_part = " ".join([pronounce_number_en(int(ch))
for ch in decimal_part[:places]])
return op_val + " point " + decimal_part
return op_val

if "." in str(number):
op_val, decimal_part = str(number).split(".")
decimal_part = " ".join([pronounce_number_en(int(ch))
for ch in decimal_part[:places]])
else:
op_val = str(number)
decimal_part = ""

if all_digits:
op_val = " ".join([pronounce_number_en(int(ch))
for ch in op_val])
else:
op_val = pronounce_number_en(int(op_val))
if decimal_part:
return op_val + " point " + decimal_part
return op_val


def pronounce_number_en(number, places=2, short_scale=True, scientific=False,
ordinals=False):
"""
Expand Down
50 changes: 50 additions & 0 deletions test/test_format.py → test/test_format_en.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
from lingua_nostra.format import date_time_format
from lingua_nostra.format import join_list
from lingua_nostra.format import nice_bytes
from lingua_nostra.format import pronounce_digits


def setUpModule():
Expand Down Expand Up @@ -131,6 +132,55 @@ def bypass_warning():


class TestPronounceNumber(unittest.TestCase):
def test_pronounce_digits_float(self):
self.assertEqual(pronounce_digits(0.5), "zero point five")
self.assertEqual(pronounce_digits(1.1235), "one point one two")
self.assertEqual(pronounce_digits(10.999999), "ten point nine nine")
self.assertEqual(pronounce_digits(10.999999, places=0), "ten")
self.assertEqual(pronounce_digits(15.0), "fifteen point zero")
self.assertEqual(pronounce_digits(20.0001, places=99),
"twenty point zero zero zero one")
self.assertEqual(pronounce_digits(27.23467875, places=4),
"twenty seven point two three four six")
self.assertEqual(pronounce_digits(0.5, all_digits=True),
"zero point five")
self.assertEqual(pronounce_digits(012345.5, all_digits=True),
"one two three four five point five")
self.assertEqual(pronounce_digits(27.23467875, all_digits=True),
"two seven point two three")
self.assertEqual(pronounce_digits(199.9990, places=5),
"one hundred and ninety nine point nine nine nine")
self.assertEqual(pronounce_digits(199.9990, places=5, all_digits=True),
"one nine nine point nine nine nine")

def test_pronounce_digits_int(self):
self.assertEqual(pronounce_digits(0), "zero")
self.assertEqual(pronounce_digits(1), "one")
self.assertEqual(pronounce_digits(199999, all_digits=True),
"one nine nine nine nine nine")
self.assertEqual(pronounce_digits(10999999, all_digits=True),
"one zero nine nine nine nine nine nine")
self.assertEqual(pronounce_digits(150, all_digits=True),
"one five zero")
self.assertEqual(pronounce_digits(200001, all_digits=True),
"two zero zero zero zero one")

def test_pronounce_digits_str(self):
self.assertEqual(pronounce_digits("0"), "zero")
self.assertEqual(pronounce_digits("01"), "one")
self.assertEqual(pronounce_digits("01", all_digits=True),
"zero one")
self.assertEqual(pronounce_digits("199999", all_digits=True),
"one nine nine nine nine nine")
self.assertEqual(pronounce_digits("199.999", all_digits=True),
"one nine nine point nine nine")
self.assertEqual(pronounce_digits("199.999", places=5,
all_digits=True),
"one nine nine point nine nine nine")
self.assertEqual(pronounce_digits("199.9990", places=5,
all_digits=True),
"one nine nine point nine nine nine zero")

def test_convert_int(self):
self.assertEqual(pronounce_number(0), "zero")
self.assertEqual(pronounce_number(1), "one")
Expand Down
File renamed without changes.

0 comments on commit 2812840

Please sign in to comment.