1# -*- coding: utf-8 -*-
2from natural.constant import NATO_ALPHABET, NATO_ALPHABET_PHONETIC
3from natural.constant import SPELL_ALPHABET, CODE_PRONOUNCIATION
4from natural.constant import CODE_ALPHABET_ARMY, CODE_ALPHABET_FAA
5from natural.constant import CODE_ALPHABET_ICAO, CODE_ALPHABET_MORSE
6from natural.constant import CODE_ALPHABET_WORD
7
8
9NATO_ALPHABET_KEYS = sorted(NATO_ALPHABET.keys())
10
11
12class Spelling(object):
13    def __call__(self, sentence, pad=u' '):
14        parts = []
15        for letter in sentence.lower():
16            letter = self.transform(letter)
17            if letter is not None:
18                parts.append(letter)
19        return pad.join(parts)
20
21    def transform(self, letter):
22        return None
23
24
25class Alphabet(Spelling):
26    '''
27    Helper class for (spelling) alphabets.
28    '''
29
30    def __init__(self, mapping):
31        self.mapping = mapping
32
33    @staticmethod
34    def from_pair(self, keys, values):
35        '''
36        Returns a new :func:`Alphabet` object for the translation items
37        specified in ``keys`` and ``values``.
38        '''
39        return Alphabet(dict(zip(keys, values)))
40
41    def transform(self, letter):
42        return self.mapping.get(letter)
43
44
45ALPHABET = dict(
46    code=dict(
47        army=Alphabet(CODE_ALPHABET_ARMY[1]),
48        faa=Alphabet(CODE_ALPHABET_FAA[1]),
49        icao=Alphabet(CODE_ALPHABET_ICAO[1]),
50        itu=Alphabet(CODE_ALPHABET_ICAO[1]),
51        morse=Alphabet(CODE_ALPHABET_MORSE[1]),
52        word=Alphabet(CODE_ALPHABET_WORD[1]),
53    ),
54    nato=dict(
55        telephony=Alphabet(NATO_ALPHABET),
56        phonetic=Alphabet(NATO_ALPHABET_PHONETIC),
57    ),
58    spell=Alphabet(SPELL_ALPHABET),
59    pronounce=Alphabet(CODE_PRONOUNCIATION),
60)
61CODE_PADDING = dict(
62    army=CODE_ALPHABET_ARMY[0],
63    faa=CODE_ALPHABET_FAA[0],
64    icao=CODE_ALPHABET_ICAO[0],
65    itu=CODE_ALPHABET_ICAO[0],
66    morse=CODE_ALPHABET_MORSE[0],
67    word=CODE_ALPHABET_WORD[0],
68)
69
70
71def code(sentence, pad=u'  ', format='army'):
72    '''
73    Transform a sentence using the code spelling alphabet, multiple
74    international code alphabets are supported.
75
76    ====== ====================================================================
77    format description
78    ====== ====================================================================
79    army   US (international) army code alphabet
80    faa    Federal Aviation Administration code alphabet, as described in "ICAO
81           Phonetics in the FAA ATC Manual, §2-4-16"
82    icao   International Civil Aviation Organization, as described in "Annex 10
83           to the Convention on International Civil Aviation, Volume II (Fifth
84           edition, 1995), Chapter 5, 38–40"
85    itu    International Telecommunication Union Roman alphabet, as described
86           in "ITU Phonetic Alphabet and Figure Code"
87    morse  International morse code, as described in "International Morse code
88           Recommendation ITU-R M.1677-1", http://itu.int/
89    word   International Civil Aviation Organization, as described in "Annex 10
90           to the Convention on International Civil Aviation, Volume II (Fifth
91           edition, 1995), Chapter 5, 38–40"
92    ====== ====================================================================
93
94    :param sentence: input sentence
95    :param pad: default ``None`` (reside to per-alphabet defaults)
96    :param format: default ``army``
97
98    >>> code('Python')
99    'PAH pah  YANG kee  TANG go  HO tell  OSS car  NOH vem ber'
100    >>> code('Python', format='faa')
101    'PAHPAH  YANGKEY  TANGGO  HOHTELL  OSSCAH  NOVEMBER'
102    >>> code('Python', format='icao')
103    'PAH PAH  YANG KEY  TANG GO  HOH TELL  OSS CAH  NO VEM BER'
104    >>> code('Python', format='itu')
105    'PAH PAH  YANG KEY  TANG GO  HOH TELL  OSS CAH  NO VEM BER'
106    >>> code('Python', format='morse')
107    '.--.  -.--  -  ....  ---  -.'
108    >>> code('Python', format='word')
109    'papa  yankee  tango  hotel  oscar  november'
110    '''
111    try:
112        return ALPHABET['code'][format](sentence, pad or CODE_PADDING[format])
113    except KeyError:
114        raise TypeError('Unsupported code alphabet "%s"' % (format,))
115
116
117def morse(sentence, pad=CODE_PADDING['morse']):
118    '''
119    Wrapper for :func:`code`.
120
121    >>> morse('Python')
122    '.--. -.-- - .... --- -.'
123    '''
124    return code(sentence, pad, 'morse')
125
126
127def nato(sentence, pad=' ', format='telephony'):
128    '''
129    Transform a sentence using the NATO spelling alphabet.
130
131    :param sentence: input sentence
132    :param pad: default ``u' '``
133    :param format: default ``telephony``, options ``telephony`` or ``phonetic``
134
135    >>> nato('Python')
136    'papa yankee tango hotel oscar november'
137    >>> nato('Python', format='phonetic')
138    'pah-pah yang-key tang-go hoh-tel oss-cah no-vem-ber'
139    '''
140    try:
141        return ALPHABET['nato'][format](sentence, pad)
142    except KeyError:
143        raise TypeError('Unsupported NATO alphabet "%s"' % (format,))
144
145
146def spell(sentence, pad='  '):
147    '''
148    Transform a sentence using the localised spelling alphabet.
149
150    :param sentence: input sentence
151    :param pad: default ``u'  '``
152
153    >>> spell('Python')
154    'Paris  Yokohama  Tripoli  Havanna  Oslo  New York'
155    '''
156    return ALPHABET['spell'](sentence, pad)
157
158
159def pronounce(sentence, pad=u' '):
160    '''
161    Transform a sentence using the pronounciations of the international code
162    spelling alphabet. This function is subject to change its behaviour to
163    support internationalised pronounciations of letters.
164
165    :param sentence: input sentence
166    :param pad: default ``u'  '``
167
168    >>> pronounce('abc')
169    'ælfɑ ˈbrɑːˈvo ˈtʃɑːli'
170
171    '''
172    return ALPHABET['pronounce'](sentence, pad)
173