summaryrefslogtreecommitdiffstats
path: root/users/gourdo1
diff options
context:
space:
mode:
Diffstat (limited to 'users/gourdo1')
-rw-r--r--users/gourdo1/autocorrect/autocorrection.c182
-rw-r--r--users/gourdo1/autocorrect/autocorrection.h40
-rw-r--r--users/gourdo1/autocorrect/autocorrection_data.h722
-rw-r--r--users/gourdo1/autocorrect/autocorrection_data.h (large)722
-rw-r--r--users/gourdo1/autocorrect/autocorrection_data.h (small)152
-rw-r--r--users/gourdo1/autocorrect/autocorrection_dict.txt473
-rw-r--r--users/gourdo1/autocorrect/make_autocorrection_data.py303
-rw-r--r--users/gourdo1/custom_double_taps.h28
-rw-r--r--users/gourdo1/gourdo1.c121
-rw-r--r--users/gourdo1/gourdo1.h18
-rw-r--r--users/gourdo1/rules.mk2
11 files changed, 2693 insertions, 70 deletions
diff --git a/users/gourdo1/autocorrect/autocorrection.c b/users/gourdo1/autocorrect/autocorrection.c
new file mode 100644
index 0000000000..bc711016d9
--- /dev/null
+++ b/users/gourdo1/autocorrect/autocorrection.c
@@ -0,0 +1,182 @@
+// Copyright 2021-2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//
+// For full documentation, see
+// https://getreuer.info/posts/keyboards/autocorrection
+
+#include "autocorrection.h"
+
+#include <string.h>
+#include "autocorrection_data.h"
+
+#if AUTOCORRECTION_MIN_LENGTH < 4
+// Odd output or hard locks on the board have been observed when the min typo
+// length is 3 or lower (https://github.com/getreuer/qmk-keymap/issues/2).
+// Additionally, autocorrection entries for short typos are more likely to false
+// trigger, so it is suggested that typos be at least 5 characters.
+#error "Min typo length is less than 4. Autocorrection may behave poorly."
+#endif
+
+bool process_autocorrection(uint16_t keycode, keyrecord_t* record) {
+ if (user_config.autocorrect) {
+ static uint8_t typo_buffer[AUTOCORRECTION_MAX_LENGTH] = {0};
+ static uint8_t typo_buffer_size = 0;
+
+ // Ignore key release; we only process key presses.
+ if (!record->event.pressed) { return true; }
+
+ #ifndef NO_ACTION_ONESHOT
+ const uint8_t mods = get_mods() | get_oneshot_mods();
+ #else
+ const uint8_t mods = get_mods();
+ #endif // NO_ACTION_ONESHOT
+ // Disable autocorrection while a mod other than shift is active.
+ if ((mods & ~MOD_MASK_SHIFT) != 0) {
+ typo_buffer_size = 0;
+ return true;
+ }
+
+ // The following switch cases address various kinds of keycodes. This logic is
+ // split over two switches rather than merged into one. The first switch may
+ // extract a basic keycode which is then further handled by the second switch,
+ // e.g. a layer-tap key with Caps Lock `LT(layer, KC_CAPS)`.
+ switch (keycode) {
+ #ifndef NO_ACTION_TAPPING
+ case QK_MOD_TAP ... QK_MOD_TAP_MAX: // Tap-hold keys.
+ #ifndef NO_ACTION_LAYER
+ case QK_LAYER_TAP ... QK_LAYER_TAP_MAX:
+ #endif // NO_ACTION_LAYER
+ // Ignore when tap-hold keys are held.
+ if (record->tap.count == 0) { return true; }
+ // Otherwise when tapped, get the basic keycode.
+ // Fallthrough intended.
+ #endif // NO_ACTION_TAPPING
+
+ // Handle shifted keys, e.g. symbols like KC_EXLM = S(KC_1).
+ case QK_LSFT ... QK_LSFT + 255:
+ case QK_RSFT ... QK_RSFT + 255:
+ keycode &= 0xff; // Get the basic keycode.
+ break;
+
+ // NOTE: Space Cadet keys expose no info to check whether they are being
+ // tapped vs. held. This makes autocorrection ambiguous, e.g. KC_LCPO might
+ // be '(', which we would treat as a word break, or it might be shift, which
+ // we would treat as having no effect. To behave cautiously, we allow Space
+ // Cadet keycodes to fall to the logic below and clear autocorrection state.
+ }
+
+ switch (keycode) {
+ // Ignore shifts, Caps Lock, one-shot mods, and layer switch keys.
+ case KC_NO:
+ case KC_LSFT:
+ case KC_RSFT:
+ case KC_CAPS:
+ case QK_ONE_SHOT_MOD ... QK_ONE_SHOT_MOD_MAX:
+ case QK_TO ... QK_TO_MAX:
+ case QK_MOMENTARY ... QK_MOMENTARY_MAX:
+ case QK_DEF_LAYER ... QK_DEF_LAYER_MAX:
+ case QK_TOGGLE_LAYER ... QK_TOGGLE_LAYER_MAX:
+ case QK_ONE_SHOT_LAYER ... QK_ONE_SHOT_LAYER_MAX:
+ case QK_LAYER_TAP_TOGGLE ... QK_LAYER_TAP_TOGGLE_MAX:
+ case QK_LAYER_MOD ... QK_LAYER_MOD_MAX:
+ return true; // Ignore these keys.
+ }
+
+ if (keycode == KC_QUOT) {
+ // Treat " (shifted ') as a word boundary.
+ if ((mods & MOD_MASK_SHIFT) != 0) { keycode = KC_SPC; }
+ } else if (!(KC_A <= keycode && keycode <= KC_Z)) {
+ if (keycode == KC_BSPC) {
+ // Remove last character from the buffer.
+ if (typo_buffer_size > 0) { --typo_buffer_size; }
+ return true;
+ } else if (KC_1 <= keycode && keycode <= KC_SLSH && keycode != KC_ESC) {
+ // Set a word boundary if space, period, digit, etc. is pressed.
+ // Behave more conservatively for the enter key. Reset, so that enter
+ // can't be used on a word ending.
+ if (keycode == KC_ENT) { typo_buffer_size = 0; }
+ keycode = KC_SPC;
+ } else {
+ // Clear state if some other non-alpha key is pressed.
+ typo_buffer_size = 0;
+ return true;
+ }
+ }
+
+ // If the buffer is full, rotate it to discard the oldest character.
+ if (typo_buffer_size >= AUTOCORRECTION_MAX_LENGTH) {
+ memmove(typo_buffer, typo_buffer + 1, AUTOCORRECTION_MAX_LENGTH - 1);
+ typo_buffer_size = AUTOCORRECTION_MAX_LENGTH - 1;
+ }
+
+ // Append `keycode` to the buffer.
+ // NOTE: `keycode` must be a basic keycode (0-255) by this point.
+ typo_buffer[typo_buffer_size++] = (uint8_t) keycode;
+ // Early return if not many characters have been buffered so far.
+ if (typo_buffer_size < AUTOCORRECTION_MIN_LENGTH) { return true; }
+
+ // Check whether the buffer ends in a typo. This is done using a trie
+ // stored in `autocorrection_data`.
+ uint16_t state = 0;
+ uint8_t code = pgm_read_byte(autocorrection_data + state);
+ for (int i = typo_buffer_size - 1; i >= 0; --i) {
+ const uint8_t key_i = typo_buffer[i];
+
+ if (code & 64) { // Check for match in node with multiple children.
+ code &= 63;
+ for (; code != key_i;
+ code = pgm_read_byte(autocorrection_data + (state += 3))) {
+ if (!code) { return true; }
+ }
+
+ // Follow link to child node.
+ state = (uint16_t)(
+ (uint_fast16_t)pgm_read_byte(autocorrection_data + state + 1)
+ | (uint_fast16_t)pgm_read_byte(autocorrection_data + state + 2) << 8);
+ // Otherwise check for match in node with a single child.
+ } else if (code != key_i) {
+ return true;
+ } else if (!(code = pgm_read_byte(autocorrection_data + (++state)))) {
+ ++state;
+ }
+
+ // Stop if `state` becomes an invalid index. This should not normally
+ // happen, it is a safeguard in case of a bug, data corruption, etc.
+ if (state >= sizeof(autocorrection_data)) {
+ return true;
+ }
+
+ // Read first byte of the next node.
+ code = pgm_read_byte(autocorrection_data + state);
+
+ if (code & 128) { // A typo was found! Apply autocorrection.
+ const int backspaces = code & 63;
+ for (int i = 0; i < backspaces; ++i) { tap_code(KC_BSPC); }
+ send_string_P((char const*)(autocorrection_data + state + 1));
+
+ if (keycode == KC_SPC) {
+ typo_buffer[0] = KC_SPC;
+ typo_buffer_size = 1;
+ return true;
+ } else {
+ typo_buffer_size = 0;
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+ return true;
+}
diff --git a/users/gourdo1/autocorrect/autocorrection.h b/users/gourdo1/autocorrect/autocorrection.h
new file mode 100644
index 0000000000..d344a815f7
--- /dev/null
+++ b/users/gourdo1/autocorrect/autocorrection.h
@@ -0,0 +1,40 @@
+// Copyright 2021-2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//
+// Autocorrection on your keyboard.
+//
+// This library implements rudimentary autocorrection, automatically detecting
+// and fixing some misspellings. Beware that the autocorrection logic is
+// unaware of hotkey or mouse-based cursor movement.
+//
+// For full documentation, see
+// https://getreuer.info/posts/keyboards/autocorrection
+
+#pragma once
+
+#include "quantum.h"
+
+#include "gourdo1.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool process_autocorrection(uint16_t keycode, keyrecord_t* record);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/users/gourdo1/autocorrect/autocorrection_data.h b/users/gourdo1/autocorrect/autocorrection_data.h
new file mode 100644
index 0000000000..66518201e2
--- /dev/null
+++ b/users/gourdo1/autocorrect/autocorrection_data.h
@@ -0,0 +1,722 @@
+// Generated code.
+
+// Autocorrection dictionary (400 entries):
+// :acheiv -> achiev
+// :agian -> again
+// :agred -> agreed
+// :ajust -> adjust
+// :alot: -> a lot
+// :andteh -> and the
+// :andthe -> and the
+// :anual -> annual
+// :asign -> assign
+// :aslo: -> also
+// :asthe -> as the
+// :atthe -> at the
+// :casue -> cause
+// :choses -> chooses
+// :eveyr -> every
+// :foudn -> found
+// :gaurd -> guard
+// :goign -> going
+// :gonig -> going
+// :graet -> great
+// :grammer -> grammar
+// :guage -> gauge
+// :haev -> have
+// :hapen -> happen
+// :htere -> there
+// :htikn -> think
+// :htink -> think
+// :hwihc -> which
+// :hwile -> while
+// :idaes -> ideas
+// :jstu: -> just
+// :jsut: -> just
+// :knwo -> know
+// :konw -> know
+// :kwno -> know
+// :moeny -> money
+// :ocuntry -> country
+// :ocur -> occur
+// :olther -> other
+// :otehr -> other
+// :owudl -> would
+// :rference -> reference
+// :sicne -> since
+// :socre -> score
+// :szie -> size
+// :the:the: -> the
+// :theri -> their
+// :thier -> their
+// :thsoe -> those
+// :tothe -> to the
+// :ture -> true
+// :turth -> truth
+// :uesd: -> used
+// :usally -> usually
+// :yaers -> years
+// :yeasr -> years
+// abbout -> about
+// aberation -> aberration
+// abilties -> abilities
+// abilty -> ability
+// abotu -> about
+// abouta -> about a
+// aboutit -> about it
+// aboutthe -> about the
+// abvove -> above
+// accesories -> accessories
+// accomodate -> accommodate
+// accross -> across
+// acommodate -> accommodate
+// acomplish -> accomplish
+// actualy -> actually
+// acurate -> accurate
+// acutally -> actually
+// addtion -> addition
+// adviced -> advised
+// againnst -> against
+// aganist -> against
+// aggreed -> agreed
+// agianst -> against
+// ahppn -> happen
+// aledge -> allege
+// alledge -> allege
+// allign -> align
+// almsot -> almost
+// alomst -> almost
+// alwasy -> always
+// alwyas -> always
+// amature -> amateur
+// anohter -> another
+// anomolous -> anomalous
+// anomoly -> anomaly
+// anytying -> anything
+// aparent -> apparent
+// aparrent -> apparent
+// apparant -> apparent
+// apparrent -> apparent
+// aquire -> acquire
+// aroud -> around
+// arround -> around
+// arund -> around
+// asthetic -> aesthetic
+// auxilary -> auxiliary
+// auxillary -> auxiliary
+// auxilliary -> auxiliary
+// availabe -> available
+// availaible -> available
+// availalbe -> available
+// availble -> available
+// availiable -> available
+// avalable -> available
+// avaliable -> available
+// avilable -> available
+// baceause -> because
+// bandwith -> bandwidth
+// bankrupcy -> bankruptcy
+// baout -> about
+// beacuse -> because
+// becasue -> because
+// beccause -> because
+// becouse -> because
+// becuase -> because
+// bedore -> before
+// beeing -> being
+// befoer -> before
+// begginer -> beginner
+// beleif -> belief
+// beleive -> believe
+// belive -> believe
+// beteen -> between
+// beween -> between
+// bewteen -> between
+// breif -> brief
+// burried -> buried
+// busness -> business
+// bussiness -> business
+// cacheing -> caching
+// calander -> calendar
+// caluclate -> calculate
+// caluculate -> calculate
+// calulate -> calculate
+// catagory -> category
+// cauhgt -> caught
+// ceratin -> certain
+// certian -> certain
+// cheif -> chief
+// chekc -> check
+// childen -> children
+// chnage -> change
+// choosen -> chosen
+// cieling -> ceiling
+// circut -> circuit
+// claer -> clear
+// clasic -> classic
+// cmoputer -> computer
+// coform -> conform
+// cognizent -> cognizant
+// collegue -> colleague
+// comapny -> company
+// comittee -> committee
+// comming: -> coming
+// commitee -> committee
+// competance -> competence
+// competant -> competent
+// complier -> compiler
+// concensus -> consensus
+// considerd -> considered
+// contian -> contain
+// copywrite: -> copyright
+// cosnt -> const
+// coudl -> could
+// dervied -> derived
+// desicion -> decision
+// didnot -> did not
+// diferent -> different
+// diferrent -> different
+// differnt -> different
+// diffrent -> different
+// divison -> division
+// doulbe -> double
+// dyanmic -> dynamic
+// effecient -> efficient
+// elasped -> elapsed
+// eligable -> eligible
+// elpased -> elapsed
+// embarass -> embarrass
+// embeded -> embedded
+// encypt -> encrypt
+// excecut -> execut
+// excercise -> exercise
+// failse -> false
+// fales -> false
+// fasle -> false
+// feild -> field
+// finaly -> finally
+// firend -> friend
+// firts -> first
+// fitler -> filter
+// flase -> false
+// follwo -> follow
+// foriegn -> foreign
+// foward -> forward
+// fraciton -> fraction
+// freind -> friend
+// frequecy -> frequency
+// fromthe -> from the
+// fucntion -> function
+// fufill -> fulfill
+// fullfill -> fulfill
+// futher -> further
+// ganerate -> generate
+// garantee -> guarantee
+// gaurantee -> guarantee
+// generaly -> generally
+// govement -> government
+// govenment -> government
+// goverment -> government
+// governmnet -> government
+// govorment -> government
+// govornment -> government
+// greatful -> grateful
+// guaratee -> guarantee
+// heigher -> higher
+// heigth -> height
+// heirarchy -> hierarchy
+// higest -> highest
+// howver -> however
+// hydogen -> hydrogen
+// hygeine -> hygiene
+// hypocracy -> hypocrisy
+// hypocrasy -> hypocrisy
+// hypocricy -> hypocrisy
+// hypocrit: -> hypocrite
+// iamge -> image
+// importamt -> important
+// inclued -> include
+// indeces -> indices
+// indecies -> indices
+// indicies -> indices
+// inital -> initial
+// insted -> instead
+// interator -> iterator
+// intput -> input
+// intrest -> interest
+// invliad -> invalid
+// laguage -> language
+// largst -> largest
+// learnign -> learning
+// lenght -> length
+// levle -> level
+// liasion -> liaison
+// libary -> library
+// likly -> likely
+// lisense -> license
+// listner -> listener
+// littel -> little
+// looses: -> loses
+// looup -> lookup
+// macthing -> matching
+// maintence -> maintenance
+// manefist -> manifest
+// mesage -> message
+// morgage -> mortgage
+// mysefl -> myself
+// namesapce -> namespace
+// namespcae -> namespace
+// naturual -> natural
+// neccesary -> necessary
+// necesary -> necessary
+// nulltpr -> nullptr
+// occassion -> occasion
+// occured -> occurred
+// operaotr -> operator
+// ouptut -> output
+// ouput -> output
+// overide -> override
+// ovveride -> override
+// pallete -> palette
+// paralel -> parallel
+// parralel -> parallel
+// parrallel -> parallel
+// particualr -> particular
+// paticular -> particular
+// peaple -> people
+// peice -> piece
+// peolpe -> people
+// peopel -> people
+// perhasp -> perhaps
+// perheaps -> perhaps
+// perhpas -> perhaps
+// perphas -> perhaps
+// persue -> pursue
+// poeople -> people
+// poeple -> people
+// poitner -> pointer
+// posess -> possess
+// postion -> position
+// preiod -> period
+// primarly -> primarily
+// priviledge -> privilege
+// privte -> private
+// probablly -> probably
+// probaly -> probably
+// probelm -> problem
+// proccess -> process
+// proeprty -> property
+// prominant -> prominent
+// proove -> prove
+// propery -> property
+// propogate -> propagate
+// psuedo -> pseudo
+// raelly -> really
+// realtion -> relation
+// realy -> really
+// reasearch -> research
+// receiev -> receiv
+// recepient -> recipient
+// reciept -> receipt
+// reciev -> receiv
+// recipiant -> recipient
+// recrod -> record
+// recuring -> recurring
+// referece -> reference
+// refered -> referred
+// regluar -> regular
+// relaly -> really
+// releated -> related
+// relevent -> relevant
+// repitition -> repetition
+// reponse -> response
+// reprot -> report
+// resutl -> result
+// retrun -> return
+// retun -> return
+// reuslt -> result
+// reutrn -> return
+// reveiw -> review
+// saftey -> safety
+// safty -> safety
+// satisifed -> satisfied
+// scheduel -> schedule
+// seperat -> separat
+// sequnce -> sequence
+// shoudl -> should
+// similiar -> similar
+// simmilar -> similar
+// singed -> signed
+// singel -> single
+// slighly -> slightly
+// somehwat -> somewhat
+// spectogram -> spectrogram
+// statment -> statement
+// stirng -> string
+// stregth -> strength
+// strengh -> strength
+// strign -> string
+// succsess -> success
+// sucess -> success
+// sugest -> suggest
+// sumary -> summary
+// supress -> suppress
+// surpress -> suppress
+// swithc -> switch
+// swtich -> switch
+// symetric -> symmetric
+// teamplate -> template
+// tempalte -> template
+// theese -> these
+// therfore -> therefore
+// thign -> thing
+// thigsn -> things
+// thikn -> think
+// thiunk -> think
+// thnigs -> things
+// thresold -> threshold
+// throught -> thought
+// tihkn -> think
+// tkaes -> takes
+// todya -> today
+// toghether -> together
+// tolerence -> tolerance
+// tongiht -> tonight
+// tranpose -> transpose
+// typcial -> typical
+// udpate -> update
+// unkown -> unknown
+// unqiue -> unique
+// ususally -> usually
+// verticies -> vertices
+// virutal -> virtual
+// vitual -> virtual
+// whcih -> which
+// whereever -> wherever
+// wherre -> where
+// whihc -> which
+// whlch -> which
+// widht -> width
+// wierd -> weird
+// wihch -> which
+// woudl -> would
+// yeild -> yield
+
+#define AUTOCORRECTION_MIN_LENGTH 5 // "abotu"
+#define AUTOCORRECTION_MAX_LENGTH 10 // "auxilliary"
+
+static const uint8_t autocorrection_data[5967] PROGMEM = {108, 67, 0, 4, 212, 0,
+ 6, 236, 0, 7, 100, 1, 8, 15, 3, 9, 169, 8, 10, 204, 8, 11, 68, 9, 12, 246, 9,
+ 14, 0, 10, 15, 28, 10, 16, 79, 11, 17, 129, 11, 18, 175, 13, 19, 227, 13, 21,
+ 253, 13, 22, 194, 15, 23, 121, 17, 24, 201, 20, 25, 210, 20, 26, 8, 21, 28,
+ 34, 21, 0, 71, 89, 0, 8, 99, 0, 10, 130, 0, 18, 142, 0, 22, 152, 0, 23, 163,
+ 0, 24, 202, 0, 0, 22, 8, 24, 44, 0, 131, 115, 101, 100, 0, 75, 106, 0, 23,
+ 115, 0, 0, 23, 44, 8, 11, 23, 44, 0, 132, 0, 12, 21, 26, 28, 19, 18, 6, 0,
+ 133, 114, 105, 103, 104, 116, 0, 17, 12, 16, 16, 18, 6, 0, 132, 105, 110, 103,
+ 0, 15, 22, 4, 44, 0, 131, 108, 115, 111, 0, 8, 22, 18, 18, 15, 0, 132, 115,
+ 101, 115, 0, 76, 173, 0, 18, 183, 0, 24, 193, 0, 0, 21, 6, 18, 19, 28, 11, 0,
+ 128, 101, 0, 15, 4, 44, 0, 131, 32, 108, 111, 116, 0, 22, 13, 44, 0, 131, 117,
+ 115, 116, 0, 23, 22, 13, 44, 0, 131, 117, 115, 116, 0, 87, 219, 0, 28, 228, 0,
+ 0, 24, 18, 5, 4, 0, 128, 32, 97, 0, 7, 18, 23, 0, 129, 97, 121, 0, 75, 246, 0,
+ 12, 28, 1, 14, 92, 1, 0, 76, 253, 0, 23, 20, 1, 0, 75, 4, 1, 26, 10, 1, 0, 26,
+ 0, 129, 99, 104, 0, 11, 44, 0, 132, 119, 104, 105, 99, 104, 0, 12, 26, 22, 0,
+ 129, 99, 104, 0, 80, 41, 1, 21, 53, 1, 22, 67, 1, 23, 76, 1, 0, 17, 4, 28, 7,
+ 0, 132, 110, 97, 109, 105, 99, 0, 23, 8, 16, 28, 22, 0, 132, 109, 101, 116,
+ 114, 105, 99, 0, 4, 15, 6, 0, 129, 115, 105, 99, 0, 8, 11, 23, 22, 4, 0, 134,
+ 101, 115, 116, 104, 101, 116, 105, 99, 0, 8, 11, 6, 0, 129, 99, 107, 0, 68,
+ 122, 1, 8, 134, 1, 15, 84, 2, 17, 124, 2, 18, 180, 2, 21, 207, 2, 24, 7, 3, 0,
+ 12, 15, 25, 17, 12, 0, 131, 97, 108, 105, 100, 0, 70, 168, 1, 7, 178, 1, 8,
+ 188, 1, 9, 199, 1, 10, 212, 1, 12, 222, 1, 19, 248, 1, 21, 3, 2, 22, 38, 2,
+ 23, 50, 2, 24, 75, 2, 0, 12, 25, 7, 4, 0, 130, 115, 101, 100, 0, 8, 5, 16, 8,
+ 0, 129, 100, 101, 100, 0, 21, 10, 10, 4, 0, 132, 114, 101, 101, 100, 0, 12,
+ 22, 12, 23, 4, 22, 0, 131, 102, 105, 101, 100, 0, 17, 12, 22, 0, 131, 103,
+ 110, 101, 100, 0, 85, 229, 1, 25, 238, 1, 0, 21, 24, 5, 0, 131, 105, 101, 100,
+ 0, 21, 8, 7, 0, 131, 105, 118, 101, 100, 0, 22, 4, 15, 8, 0, 131, 112, 115,
+ 101, 100, 0, 72, 13, 2, 10, 22, 2, 24, 29, 2, 0, 9, 8, 21, 0, 129, 114, 101,
+ 100, 0, 4, 44, 0, 128, 101, 100, 0, 6, 6, 18, 0, 129, 114, 101, 100, 0, 4, 19,
+ 15, 8, 0, 132, 97, 112, 115, 101, 100, 0, 68, 57, 2, 22, 68, 2, 0, 8, 15, 8,
+ 21, 0, 132, 97, 116, 101, 100, 0, 17, 12, 0, 128, 97, 100, 0, 15, 6, 17, 12,
+ 0, 129, 100, 101, 0, 76, 91, 2, 18, 112, 2, 0, 8, 0, 73, 100, 2, 28, 106, 2,
+ 0, 131, 105, 101, 108, 100, 0, 131, 105, 101, 108, 100, 0, 22, 8, 21, 11, 23,
+ 0, 130, 104, 111, 108, 100, 0, 72, 134, 2, 12, 145, 2, 24, 155, 2, 0, 21, 12,
+ 9, 0, 132, 114, 105, 101, 110, 100, 0, 8, 21, 9, 0, 131, 105, 101, 110, 100,
+ 0, 82, 162, 2, 21, 172, 2, 0, 21, 21, 4, 0, 132, 111, 117, 110, 100, 0, 4, 0,
+ 130, 111, 117, 110, 100, 0, 76, 187, 2, 21, 198, 2, 0, 8, 21, 19, 0, 132, 101,
+ 114, 105, 111, 100, 0, 6, 8, 21, 0, 130, 111, 114, 100, 0, 68, 217, 2, 8, 228,
+ 2, 24, 253, 2, 0, 26, 18, 9, 0, 131, 114, 119, 97, 114, 100, 0, 71, 235, 2,
+ 12, 245, 2, 0, 12, 22, 17, 18, 6, 0, 128, 101, 100, 0, 26, 0, 131, 101, 105,
+ 114, 100, 0, 4, 10, 44, 0, 131, 117, 97, 114, 100, 0, 18, 21, 4, 0, 128, 110,
+ 100, 0, 68, 67, 3, 5, 80, 3, 6, 123, 3, 7, 251, 3, 8, 23, 4, 10, 107, 4, 11,
+ 227, 4, 12, 52, 5, 15, 61, 5, 17, 0, 6, 18, 27, 6, 19, 37, 6, 21, 47, 6, 22,
+ 156, 6, 23, 82, 7, 24, 45, 8, 25, 115, 8, 0, 6, 19, 22, 8, 16, 4, 17, 0, 130,
+ 97, 99, 101, 0, 68, 87, 3, 15, 97, 3, 0, 15, 12, 4, 25, 4, 0, 128, 108, 101,
+ 0, 68, 104, 3, 24, 115, 3, 0, 15, 12, 4, 25, 4, 0, 130, 98, 108, 101, 0, 18,
+ 7, 0, 130, 98, 108, 101, 0, 72, 136, 3, 12, 147, 3, 17, 156, 3, 19, 238, 3, 0,
+ 21, 8, 9, 8, 21, 0, 129, 110, 99, 101, 0, 8, 19, 0, 131, 105, 101, 99, 101, 0,
+ 68, 166, 3, 8, 179, 3, 24, 228, 3, 0, 23, 8, 19, 16, 18, 6, 0, 131, 101, 110,
+ 99, 101, 0, 85, 186, 3, 23, 217, 3, 0, 8, 0, 73, 195, 3, 15, 208, 3, 0, 21,
+ 44, 0, 134, 101, 102, 101, 114, 101, 110, 99, 101, 0, 18, 23, 0, 131, 97, 110,
+ 99, 101, 0, 17, 12, 4, 16, 0, 129, 97, 110, 99, 101, 0, 20, 8, 22, 0, 130,
+ 101, 110, 99, 101, 0, 4, 22, 8, 16, 4, 17, 0, 131, 112, 97, 99, 101, 0, 12,
+ 21, 8, 25, 0, 82, 7, 4, 25, 13, 4, 0, 130, 114, 105, 100, 101, 0, 18, 0, 133,
+ 101, 114, 114, 105, 100, 101, 0, 23, 0, 68, 38, 4, 12, 49, 4, 17, 59, 4, 23,
+ 94, 4, 0, 21, 4, 24, 10, 0, 130, 110, 116, 101, 101, 0, 16, 16, 18, 6, 0, 129,
+ 116, 101, 101, 0, 4, 21, 0, 68, 69, 4, 24, 81, 4, 0, 10, 0, 134, 117, 97, 114,
+ 97, 110, 116, 101, 101, 0, 4, 10, 0, 135, 117, 97, 114, 97, 110, 116, 101,
+ 101, 0, 12, 16, 18, 6, 0, 132, 109, 105, 116, 116, 101, 101, 0, 68, 117, 4, 7,
+ 184, 4, 16, 218, 4, 0, 74, 130, 4, 17, 141, 4, 22, 150, 4, 24, 159, 4, 0, 21,
+ 18, 16, 0, 131, 116, 103, 97, 103, 101, 0, 11, 6, 0, 131, 97, 110, 103, 101,
+ 0, 8, 16, 0, 130, 115, 97, 103, 101, 0, 10, 0, 108, 168, 4, 4, 174, 4, 0, 131,
+ 97, 117, 103, 101, 0, 15, 0, 132, 110, 103, 117, 97, 103, 101, 0, 8, 15, 0,
+ 68, 197, 4, 12, 203, 4, 15, 212, 4, 0, 131, 108, 101, 103, 101, 0, 25, 12, 21,
+ 19, 0, 130, 103, 101, 0, 4, 0, 130, 103, 101, 0, 4, 12, 0, 131, 109, 97, 103,
+ 101, 0, 23, 0, 71, 245, 4, 16, 255, 4, 18, 9, 5, 22, 18, 5, 23, 27, 5, 0, 17,
+ 4, 44, 0, 130, 32, 116, 104, 101, 0, 18, 21, 9, 0, 130, 32, 116, 104, 101, 0,
+ 23, 44, 0, 130, 32, 116, 104, 101, 0, 4, 44, 0, 130, 32, 116, 104, 101, 0, 68,
+ 34, 5, 24, 42, 5, 0, 44, 0, 130, 32, 116, 104, 101, 0, 18, 5, 4, 0, 130, 32,
+ 116, 104, 101, 0, 29, 22, 44, 0, 130, 105, 122, 101, 0, 69, 77, 5, 12, 190, 5,
+ 19, 201, 5, 22, 241, 5, 25, 249, 5, 0, 68, 87, 5, 12, 167, 5, 15, 179, 5, 0,
+ 74, 97, 5, 12, 107, 5, 15, 137, 5, 0, 12, 15, 8, 0, 131, 105, 98, 108, 101, 0,
+ 15, 0, 68, 116, 5, 12, 127, 5, 0, 25, 4, 0, 133, 105, 108, 97, 98, 108, 101,
+ 0, 4, 25, 4, 0, 132, 97, 98, 108, 101, 0, 68, 144, 5, 12, 155, 5, 0, 25, 4, 0,
+ 132, 105, 108, 97, 98, 108, 101, 0, 25, 4, 0, 133, 97, 105, 108, 97, 98, 108,
+ 101, 0, 4, 15, 12, 4, 25, 4, 0, 131, 98, 108, 101, 0, 12, 4, 25, 4, 0, 130,
+ 97, 98, 108, 101, 0, 26, 11, 44, 0, 132, 119, 104, 105, 108, 101, 0, 68, 211,
+ 5, 8, 220, 5, 18, 230, 5, 0, 8, 19, 0, 131, 111, 112, 108, 101, 0, 18, 19, 0,
+ 132, 101, 111, 112, 108, 101, 0, 8, 18, 19, 0, 133, 101, 111, 112, 108, 101,
+ 0, 4, 9, 0, 130, 108, 115, 101, 0, 8, 15, 0, 129, 101, 108, 0, 70, 7, 6, 12,
+ 16, 6, 0, 12, 22, 44, 0, 130, 110, 99, 101, 0, 8, 10, 28, 11, 0, 131, 105,
+ 101, 110, 101, 0, 22, 11, 23, 44, 0, 130, 111, 115, 101, 0, 15, 18, 8, 19, 0,
+ 130, 112, 108, 101, 0, 70, 66, 6, 8, 76, 6, 12, 87, 6, 18, 99, 6, 21, 127, 6,
+ 24, 134, 6, 0, 18, 22, 44, 0, 131, 99, 111, 114, 101, 0, 23, 11, 44, 0, 132,
+ 116, 104, 101, 114, 101, 0, 24, 20, 4, 0, 132, 99, 113, 117, 105, 114, 101, 0,
+ 71, 106, 6, 9, 115, 6, 0, 8, 5, 0, 131, 102, 111, 114, 101, 0, 21, 8, 11, 23,
+ 0, 131, 101, 102, 111, 114, 101, 0, 8, 11, 26, 0, 129, 101, 0, 23, 0, 108,
+ 143, 6, 4, 148, 6, 0, 130, 114, 117, 101, 0, 16, 4, 0, 130, 101, 117, 114, 0,
+ 68, 178, 6, 8, 203, 6, 12, 211, 6, 15, 226, 6, 17, 235, 6, 18, 9, 7, 24, 22,
+ 7, 0, 79, 185, 6, 24, 193, 6, 0, 9, 0, 131, 97, 108, 115, 101, 0, 6, 8, 5, 0,
+ 131, 97, 117, 115, 101, 0, 8, 11, 23, 0, 130, 115, 101, 0, 6, 21, 8, 6, 27, 8,
+ 0, 134, 101, 114, 99, 105, 115, 101, 0, 12, 4, 9, 0, 131, 108, 115, 101, 0,
+ 72, 242, 6, 18, 253, 6, 0, 22, 12, 15, 0, 132, 99, 101, 110, 115, 101, 0, 19,
+ 8, 21, 0, 132, 115, 112, 111, 110, 115, 101, 0, 19, 17, 4, 21, 23, 0, 131,
+ 115, 112, 111, 115, 101, 0, 68, 32, 7, 6, 61, 7, 18, 72, 7, 0, 70, 39, 7, 8,
+ 49, 7, 0, 6, 8, 5, 0, 132, 97, 117, 115, 101, 0, 6, 4, 5, 0, 134, 101, 99, 97,
+ 117, 115, 101, 0, 4, 8, 5, 0, 132, 99, 97, 117, 115, 101, 0, 6, 8, 5, 0, 131,
+ 97, 117, 115, 101, 0, 68, 95, 7, 8, 13, 8, 15, 24, 8, 25, 36, 8, 0, 71, 111,
+ 7, 10, 148, 7, 15, 161, 7, 19, 228, 7, 21, 238, 7, 0, 18, 16, 0, 80, 121, 7,
+ 18, 136, 7, 0, 18, 6, 4, 0, 135, 99, 111, 109, 109, 111, 100, 97, 116, 101, 0,
+ 6, 6, 4, 0, 132, 109, 111, 100, 97, 116, 101, 0, 18, 19, 18, 21, 19, 0, 132,
+ 97, 103, 97, 116, 101, 0, 70, 171, 7, 19, 184, 7, 24, 197, 7, 0, 24, 15, 4, 6,
+ 0, 133, 99, 117, 108, 97, 116, 101, 0, 16, 4, 8, 23, 0, 134, 109, 112, 108,
+ 97, 116, 101, 0, 70, 204, 7, 15, 217, 7, 0, 24, 15, 4, 6, 0, 134, 99, 117,
+ 108, 97, 116, 101, 0, 4, 6, 0, 132, 99, 117, 108, 97, 116, 101, 0, 7, 24, 0,
+ 132, 112, 100, 97, 116, 101, 0, 72, 245, 7, 24, 2, 8, 0, 17, 4, 10, 0, 134,
+ 101, 110, 101, 114, 97, 116, 101, 0, 6, 4, 0, 132, 99, 117, 114, 97, 116, 101,
+ 0, 15, 15, 4, 19, 0, 131, 101, 116, 116, 101, 0, 4, 19, 16, 8, 23, 0, 131,
+ 108, 97, 116, 101, 0, 12, 21, 19, 0, 129, 97, 116, 101, 0, 74, 55, 8, 12, 67,
+ 8, 22, 77, 8, 0, 8, 15, 15, 18, 6, 0, 130, 97, 103, 117, 101, 0, 20, 17, 24,
+ 0, 131, 105, 113, 117, 101, 0, 68, 84, 8, 21, 105, 8, 0, 6, 0, 108, 93, 8, 8,
+ 98, 8, 0, 130, 117, 115, 101, 0, 5, 0, 130, 117, 115, 101, 0, 8, 19, 0, 132,
+ 117, 114, 115, 117, 101, 0, 76, 122, 8, 18, 147, 8, 0, 72, 129, 8, 15, 139, 8,
+ 0, 15, 8, 5, 0, 131, 105, 101, 118, 101, 0, 8, 5, 0, 129, 101, 118, 101, 0,
+ 82, 154, 8, 25, 161, 8, 0, 21, 19, 0, 130, 118, 101, 0, 5, 4, 0, 131, 111,
+ 118, 101, 0, 12, 8, 0, 75, 182, 8, 15, 189, 8, 21, 197, 8, 0, 6, 0, 130, 105,
+ 101, 102, 0, 8, 5, 0, 130, 105, 101, 102, 0, 5, 0, 130, 105, 101, 102, 0, 76,
+ 211, 8, 17, 221, 8, 0, 17, 18, 10, 44, 0, 130, 105, 110, 103, 0, 76, 228, 8,
+ 21, 58, 9, 0, 72, 244, 8, 11, 11, 9, 15, 24, 9, 21, 36, 9, 28, 47, 9, 0, 72,
+ 251, 8, 11, 2, 9, 0, 5, 0, 131, 105, 110, 103, 0, 6, 4, 6, 0, 131, 105, 110,
+ 103, 0, 23, 6, 4, 16, 0, 133, 116, 99, 104, 105, 110, 103, 0, 8, 12, 6, 0,
+ 133, 101, 105, 108, 105, 110, 103, 0, 24, 6, 8, 21, 0, 130, 114, 105, 110,
+ 103, 0, 23, 28, 17, 4, 0, 131, 104, 105, 110, 103, 0, 12, 23, 22, 0, 131, 114,
+ 105, 110, 103, 0, 70, 87, 9, 8, 142, 9, 10, 154, 9, 12, 164, 9, 22, 173, 9,
+ 23, 191, 9, 0, 75, 100, 9, 12, 109, 9, 15, 119, 9, 21, 127, 9, 0, 12, 26, 0,
+ 131, 104, 105, 99, 104, 0, 23, 26, 22, 0, 131, 105, 116, 99, 104, 0, 11, 26,
+ 0, 130, 105, 99, 104, 0, 4, 8, 22, 4, 8, 21, 0, 134, 115, 101, 97, 114, 99,
+ 104, 0, 23, 7, 17, 4, 44, 0, 130, 32, 116, 104, 101, 0, 17, 8, 21, 23, 22, 0,
+ 128, 116, 104, 0, 6, 11, 26, 0, 130, 105, 99, 104, 0, 12, 15, 19, 16, 18, 6,
+ 4, 0, 134, 99, 111, 109, 112, 108, 105, 115, 104, 0, 74, 201, 9, 12, 225, 9,
+ 21, 236, 9, 0, 72, 208, 9, 12, 218, 9, 0, 21, 23, 22, 0, 130, 110, 103, 116,
+ 104, 0, 8, 11, 0, 129, 104, 116, 0, 26, 7, 17, 4, 5, 0, 129, 100, 116, 104, 0,
+ 24, 23, 44, 0, 131, 114, 117, 116, 104, 0, 21, 8, 11, 23, 44, 0, 129, 105,
+ 114, 0, 17, 0, 76, 9, 10, 24, 20, 10, 0, 23, 11, 44, 0, 132, 116, 104, 105,
+ 110, 107, 0, 12, 11, 23, 0, 130, 110, 107, 0, 68, 50, 10, 7, 134, 10, 8, 177,
+ 10, 9, 17, 11, 15, 26, 11, 23, 55, 11, 24, 64, 11, 0, 76, 60, 10, 23, 71, 10,
+ 24, 96, 10, 0, 6, 19, 28, 23, 0, 131, 105, 99, 97, 108, 0, 76, 78, 10, 24, 86,
+ 10, 0, 17, 12, 0, 129, 105, 97, 108, 0, 21, 12, 25, 0, 131, 116, 117, 97, 108,
+ 0, 81, 106, 10, 21, 115, 10, 23, 124, 10, 0, 4, 44, 0, 130, 110, 117, 97, 108,
+ 0, 24, 23, 4, 17, 0, 130, 97, 108, 0, 12, 25, 0, 131, 114, 116, 117, 97, 108,
+ 0, 24, 0, 82, 143, 10, 26, 167, 10, 0, 70, 153, 10, 11, 157, 10, 26, 163, 10,
+ 0, 129, 108, 100, 0, 22, 0, 129, 108, 100, 0, 129, 108, 100, 0, 18, 44, 0,
+ 132, 119, 111, 117, 108, 100, 0, 74, 193, 10, 15, 201, 10, 19, 247, 10, 23,
+ 255, 10, 24, 7, 11, 0, 17, 12, 22, 0, 129, 108, 101, 0, 68, 208, 10, 15, 234,
+ 10, 0, 21, 0, 68, 217, 10, 21, 224, 10, 0, 19, 0, 129, 108, 101, 108, 0, 4,
+ 19, 0, 132, 97, 108, 108, 101, 108, 0, 4, 21, 21, 4, 19, 0, 133, 97, 108, 108,
+ 101, 108, 0, 18, 8, 19, 0, 129, 108, 101, 0, 23, 12, 15, 0, 129, 108, 101, 0,
+ 7, 8, 11, 6, 22, 0, 129, 108, 101, 0, 8, 22, 28, 16, 0, 129, 108, 102, 0, 12,
+ 9, 0, 79, 36, 11, 24, 46, 11, 0, 15, 24, 9, 0, 132, 102, 105, 108, 108, 0, 9,
+ 0, 131, 108, 102, 105, 108, 108, 0, 24, 22, 8, 21, 0, 129, 108, 116, 0, 9, 23,
+ 4, 8, 21, 10, 0, 133, 97, 116, 101, 102, 117, 108, 0, 68, 89, 11, 15, 106, 11,
+ 21, 117, 11, 0, 21, 10, 18, 23, 6, 8, 19, 22, 0, 132, 114, 111, 103, 114, 97,
+ 109, 0, 8, 5, 18, 21, 19, 0, 130, 108, 101, 109, 0, 18, 9, 18, 6, 0, 131, 110,
+ 102, 111, 114, 109, 0, 68, 166, 11, 7, 206, 11, 8, 215, 11, 10, 58, 12, 12,
+ 141, 12, 14, 153, 12, 18, 192, 12, 19, 108, 13, 21, 120, 13, 22, 131, 13, 24,
+ 141, 13, 26, 164, 13, 0, 12, 0, 74, 175, 11, 23, 183, 11, 0, 4, 44, 0, 130,
+ 97, 105, 110, 0, 81, 190, 11, 21, 198, 11, 0, 18, 6, 0, 130, 97, 105, 110, 0,
+ 8, 6, 0, 130, 97, 105, 110, 0, 24, 18, 9, 44, 0, 129, 110, 100, 0, 71, 231,
+ 11, 8, 241, 11, 10, 27, 12, 19, 39, 12, 22, 48, 12, 0, 15, 12, 11, 6, 0, 129,
+ 114, 101, 110, 0, 87, 248, 11, 26, 17, 12, 0, 72, 255, 11, 26, 7, 12, 0, 5, 0,
+ 130, 119, 101, 101, 110, 0, 8, 5, 0, 132, 116, 119, 101, 101, 110, 0, 8, 5, 0,
+ 131, 116, 119, 101, 101, 110, 0, 18, 7, 28, 11, 0, 131, 114, 111, 103, 101,
+ 110, 0, 4, 11, 44, 0, 129, 112, 101, 110, 0, 18, 18, 11, 6, 0, 131, 115, 101,
+ 110, 0, 72, 65, 12, 12, 76, 12, 0, 12, 21, 18, 9, 0, 131, 101, 105, 103, 110,
+ 0, 75, 95, 12, 15, 101, 12, 17, 109, 12, 18, 118, 12, 21, 125, 12, 22, 132,
+ 12, 0, 23, 0, 129, 110, 103, 0, 15, 4, 0, 131, 105, 103, 110, 0, 21, 4, 8, 15,
+ 0, 129, 110, 103, 0, 10, 44, 0, 129, 110, 103, 0, 23, 22, 0, 129, 110, 103, 0,
+ 4, 44, 0, 130, 115, 105, 103, 110, 0, 23, 4, 21, 8, 6, 0, 131, 116, 97, 105,
+ 110, 0, 75, 160, 12, 12, 169, 12, 0, 12, 23, 0, 131, 104, 105, 110, 107, 0,
+ 75, 176, 12, 23, 182, 12, 0, 23, 0, 129, 110, 107, 0, 11, 44, 0, 132, 116,
+ 104, 105, 110, 107, 0, 76, 202, 12, 22, 86, 13, 23, 96, 13, 0, 70, 212, 12,
+ 22, 225, 12, 23, 251, 12, 0, 12, 22, 8, 7, 0, 133, 99, 105, 115, 105, 111,
+ 110, 0, 68, 232, 12, 22, 241, 12, 0, 12, 15, 0, 131, 105, 115, 111, 110, 0, 4,
+ 6, 6, 18, 0, 131, 105, 111, 110, 0, 68, 14, 13, 7, 27, 13, 12, 37, 13, 15, 52,
+ 13, 17, 64, 13, 22, 76, 13, 0, 21, 8, 5, 4, 0, 132, 114, 97, 116, 105, 111,
+ 110, 0, 7, 4, 0, 131, 105, 116, 105, 111, 110, 0, 23, 12, 19, 8, 21, 0, 134,
+ 101, 116, 105, 116, 105, 111, 110, 0, 4, 8, 21, 0, 133, 108, 97, 116, 105,
+ 111, 110, 0, 6, 24, 9, 0, 133, 110, 99, 116, 105, 111, 110, 0, 18, 19, 0, 131,
+ 105, 116, 105, 111, 110, 0, 12, 25, 12, 7, 0, 129, 105, 111, 110, 0, 12, 6, 4,
+ 21, 9, 0, 131, 116, 105, 111, 110, 0, 19, 11, 4, 0, 132, 104, 97, 112, 112,
+ 101, 110, 0, 23, 24, 8, 21, 0, 131, 116, 117, 114, 110, 0, 10, 12, 11, 23, 0,
+ 130, 110, 103, 115, 0, 85, 148, 13, 23, 157, 13, 0, 23, 8, 21, 0, 130, 117,
+ 114, 110, 0, 8, 21, 0, 128, 114, 110, 0, 18, 1