diff options
Diffstat (limited to 'lulua')
-rw-r--r-- | lulua/data/report/index.html | 77 | ||||
-rw-r--r-- | lulua/data/report/style.css | 8 | ||||
-rw-r--r-- | lulua/report.py | 7 | ||||
-rw-r--r-- | lulua/stats.py | 25 |
4 files changed, 110 insertions, 7 deletions
diff --git a/lulua/data/report/index.html b/lulua/data/report/index.html index a18dcb7..cae6024 100644 --- a/lulua/data/report/index.html +++ b/lulua/data/report/index.html @@ -268,13 +268,18 @@ $$a = \frac{b_{left}}{b_{total}} - \frac{b_{right}}{b_{total}}$$ <p> - The layout proposed uses four layers and assumes a 102/105 key ISO - keyboard common in Europe to accomodate the shift keys necessary. + The layout proposed uses four shift layers in a way inspired by <a + href="https://neo-layout.org/">Neo2</a>. + <!-- --> + Thus it assumes a <a + href="https://en.wikipedia.org/wiki/IBM_PC_keyboard#Keyboard_layouts">102/105 + key ISO keyboard</a> common in Europe – but also available in Arab + countries – to accommodate for the necessary shift keys. <!-- --> These are in order: <span class="layer second">Shift on the left and right</span>, <span class="layer third">caps lock on the left and the rightmost key in the middle row</span>, <span class="layer fourth">the - key right of the left shift key and the key labeled <em>Alt Gr</em> to + key right to the left shift key and the key labeled <em>Alt Gr</em> to the right of the spacebar</span>. <!-- --> Symbols are assigned to the four layers by their function: <span @@ -282,6 +287,15 @@ second">punctuation</span>, <span class="layer third">diacritics</span>, <span class="layer fourth">other</span>. </p> + <details class="remarks"> + <summary></summary> + <p>Apple, for instance, provides an <a + href="https://www.apple.com/shop/product/MLA22AC/A/magic-keyboard-arabic">Arabic + hardware keyboard</a> with this physical layout. But both variants, + 101/104 key and 102/105 key devices, seem to exist in the Arab + world.</p> + </details> + <p> The first layer was optimized using an extended reimplementation of <a href="http://mkweb.bcgsc.ca/carpalx/?typing_effort">carpalx</a>. @@ -299,10 +313,10 @@ </p> <details class="remarks"> <summary></summary> - <p>(This is <a + <p>This is <a href="https://github.com/mw8/white_keyboard_layout/blob/master/README.md#finding-the-optimal-layout">a common way</a> of arranging brackets, because most algorithms ignore - human desire for symmetry.)</p> + human desire for symmetry.</p> </details> <p> @@ -317,6 +331,59 @@ typing load, but naturally the left middle finger is used more frequently due to its assignment to the letter alif. </p> + + <p> + The layout targets Quaranic and Modern Standard Arabic (MSA), also called Fusha + (<bdo lang="ar">الفصحى</bdo>), only. + <!-- --> + Dialectical Arabic (<bdo lang="ar">العامية</bdo>) is mainly a spoken + language, although with the rise of social media sites like Twitter and + Facebook this is changing. + <!-- --> + For now however it’s not an optimization target due to the lack of a + good, representative corpus. + </p> + + <p> + Designing the layout to be compose-based has both benefits and + disadvantages. + <!-- --> + Compose-based mainly means the hamza <bdo lang="ar" dir="ltr">ء</bdo> + is treated like an optional diacritic for Alef, Waw and Yah instead of + viewing Alef-Hamza, Waw-Hamza and Yah-Hamza as precombined, atomic + units. + <!-- --> + Although <bdo lang="ar" dir="ltr">أ</bdo> and <bdo lang="ar" + dir="ltr">ا</bdo> are not the same, the hamza can be dropped if the + writer’s intention is unambigiously inferable from context. + <!-- --> + Thus it makes sense to provide hamza as a combining character on the + keyboard. + <!-- --> + Additionally it uses two keys less than precombining it with its stems, + allowing the entire alphabet plus hamza diacritic to fit on a single + keyboard layer. + <!-- --> + However, there is a cost to this approach: + All hamza variants account for {{ + '%.1f'|format(layoutstats['ar-osx'].hamzaImpact*100) }}% of button + combinations. + <!-- --> + Splitting hamza and from its stem means doubling the total number of + button combinations and thus button presses, decreasing scores like + words per minute (WPM) slightly. + <!-- --> + Splitting Alef and Alef-Hamza could also reduce pressure on left middle + finger and allow for more even distribution, since {{ + layoutstats['ar-osx'].hamzaOnAlef|fraction }}<sup>th</sup> of all Alef + uses are with Hamza. + </p> + <details class="remarks"> + <summary></summary> + <p>See for example section 3.3 of <a + href="https://doi.org/10.1007/978-1-4020-6046-5_3">Buckwalter’s <em>Issues in Arabic Morphological Analysis</em></a>. + </p> + </details> </div> </div> </div> diff --git a/lulua/data/report/style.css b/lulua/data/report/style.css index f62fcef..ed0d32d 100644 --- a/lulua/data/report/style.css +++ b/lulua/data/report/style.css @@ -240,6 +240,12 @@ details[open].remarks { margin-bottom: 1em; } details.remarks summary { - list-style-type: "+"; + list-style-type: "↳ Remarks"; cursor: pointer; + opacity: 0.4; } + +details.remarks p { + margin-top: 0; +} + diff --git a/lulua/report.py b/lulua/report.py index 8a50681..b25201d 100644 --- a/lulua/report.py +++ b/lulua/report.py @@ -21,6 +21,7 @@ import sys, argparse, logging, pickle, math from gettext import GNUTranslations, NullTranslations from decimal import Decimal +from fractions import Fraction import yaml from jinja2 import Environment, PackageLoader @@ -40,6 +41,11 @@ def approx (i, lang='en'): units.pop (0) return round (i, 1), units[0] +def fraction (n, maxdenom=10): + """ Turn floating number n into a human-digestable fraction """ + f = Fraction (n).limit_denominator (maxdenom) + return f'{f.numerator}\u2044{f.denominator}' + def numspace (s): """ Replace ordinary spaces with unicode FIGURE SPACE """ return s.replace (' ', '\u2007') @@ -83,6 +89,7 @@ def render (): env.filters['numspace'] = numspace env.filters['arabnum'] = arabnum env.filters['blendn'] = blendn + env.filters['fraction'] = fraction corpus = [] for x in args.corpus: diff --git a/lulua/stats.py b/lulua/stats.py index 9c11d10..1d051b3 100644 --- a/lulua/stats.py +++ b/lulua/stats.py @@ -360,7 +360,7 @@ from .text import mapChars, charMap def layoutstats (args): """ - Statistics for the report + Various statistics for the report """ stats = pickle.load (sys.stdin.buffer) @@ -384,6 +384,27 @@ def layoutstats (args): ] sentences = [sentenceStats (keyboard, layout, mapChars (s, charMap).replace ('\r\n', '\n')) for s in sentences] + # Impact of hamza + yah = '\u064a' + waw = '\u0648' + alef = 'ا' + hamzaAbove = '\u0654' + hamzaBelow = '\u0655' + # list of combination counts for each match + combPerGroup = defaultdict (int) + combStats = stats['simple'].combinations + letterWithHamza = [alef+hamzaAbove, alef+hamzaBelow, yah+hamzaAbove, waw+hamzaAbove] + for letter in [alef] + letterWithHamza: + match, combinations = layout (letter) + if match != letter: + # not a single key or single combination + continue + combPerGroup[letter] += sum (map (lambda x: combStats[x], combinations)) + combinations = sum (stats['simple'].combinations.values ()) + hamzaImpact = sum (map (lambda x: combPerGroup[x], letterWithHamza))/combinations + x = combPerGroup[alef+hamzaAbove] + combPerGroup[alef+hamzaBelow] + hamzaOnAlef = x/(x+combPerGroup[alef]) + pickle.dump (dict ( layout=args.layout, hands=dict (hands), @@ -391,6 +412,8 @@ def layoutstats (args): buttonPresses=buttonPresses, asymmetry=asymmetry, sentences=sentences, + hamzaImpact=hamzaImpact, + hamzaOnAlef=hamzaOnAlef, ), sys.stdout.buffer) def latinImeDict (args): |