# -*- coding: utf-8 -*- """ Created on Mon Apr 24 14:26:02 2023 @author: Edward Middleton-Smith Braille 3D Model Product Creation Braille Dictionary Conversion / Creation Plaintext message translation into Braille for 3D modelling """ # CLASSES # ATTRIBUTE DECLARATION # METHODS # FUNCTION # ARGUMENTS # ARGUMENT VALIDATION # ATTRIBUTE + VARIABLE INSTANTIATION # METHODS # RETURNS # NORMAL METHODS # FUNCTION # ARGUMENTS # ARGUMENT VALIDATION # VARIABLE INSTANTIATION # METHODS # RETURNS import pandas as pd from typing import Optional from enum import Enum import argument_validation as av import sys class difficulty(Enum): ALPHABETPUNCTUATION = 1 SIMPLEWORDGROUPSIGNS = 2 LOWERCONTRACTIONS = 3 def mini(): # FUNCTION # Get minimum value in enumerator # RETURNS return min([e.value for e in difficulty]) def maxi(): # FUNCTION # Get maximum value in enumerator # RETURNS return max([e.value for e in difficulty]) class braille_trans(): # ATTRIBUTE DECLARATION key: str # search key in input messages for Braille translation - includes additional characters for literal processing level: difficulty # stage of learning at which this translation is discovered braille: list # list[list[int]] # Braille translation of plaintext plaintext: str # English plaintext key # METHODS # def argvalinit(key: str, level: difficulty, braille: list, plaintext: Optional[str] = None): # # run before instantiating braille_trans # # av.val_list(braille, 'list')= # # _m = 'braille_trans.argvalinit' # # if not av.val_str(key, 'key', method, min_len = -1, max_len = -1, suppress_errors = False, suppress_console_outputs = False, v_arg_type = 'argument') # if not (av.val_str(key) and (str(type(level)) == "" or av.val_int(level, difficulty.mini(), difficulty.maxi())) and av.val_list(braille, "") and (av.val_str(plaintext, -1, -1, True) or plaintext == None)): # print(f'Invalid braille_trans instantiation. key = {key}, level = {level}, braille = {braille}, plaintext = {plaintext}') # return None # return braille_trans(key, level, braille, plaintext) def __new__(cls, key: str, level: difficulty, braille: list, plaintext: Optional[str] = None): # FUNCTION # Initialise class object # ARGUMENTS # str key # difficulty level # list[list[int]] braille # optional str plaintext # VARIABLE DECLARATION _m = 'braille_trans.__new__' v_arg_type = 'class attribute' # ARGUMENT VALIDATION av.val_str(key, 'key', _m, 1, -1, v_arg_type = v_arg_type) av.val_type(level, "", 'level', _m, v_arg_type = v_arg_type) av.val_nested_list(braille, 0, 1, 'braille', _m, "", -1, [-1, 6], -1, [-1, 6], v_arg_type = v_arg_type) if not (av.val_str(plaintext, 'plaintext', _m, -1, -1, True, True, v_arg_type) or str(type(plaintext)) == ""): raise ValueError(av.error_msg_str(_m, 'plaintext', plaintext, "", v_arg_type = v_arg_type)) # if not av.val_str(key): # raise ValueError(av.error_msg_str('braille_trans.__new__', 'key', key, 'attribute')) # if not av.val_type(level, ""): # raise ValueError(av.error_msg_str('braille_trans.__new__', 'level', level, 'attribute')) # if not av.val_nested_list(braille, 0, 2, "", 6, [1, 6], 6, [-1, 6]): # raise ValueError(av.error_msg_str('braille_trans.__new__', 'braille', braille, 'attribute')) # if not (av.val_str(plaintext) or str(type(plaintext)) == ""): # raise ValueError(av.error_msg_str('braille_trans.__new__', 'plaintext', plaintext, 'attribute')) # RETURNS return super(braille_trans, cls).__new__(cls) def __init__(self, key: str, level: difficulty, braille: list, plaintext: Optional[str] = None): # FUNCTION # Construct class object # ARGUMENTS # str key # difficulty level # list[list[int]] braille # optional str plaintext # ARGUMENT VALIDATION # see __new__() # ATTRIBUTE + VARIABLE INSTANTIATION self.key = key self.level = level self.braille = braille self.plaintext = self.key if (plaintext is None) else plaintext def __repr__(self): return f"key = {self.key}, level = {self.level}, braille = {self.braille}, plaintext = {self.plaintext}" # def query_lvl(self): # return ' & '.join(["{}=='{}'".format(key, value) # for key, value in self.__dict__.items() # if not value is None]) def as_dict(self): return {'key': self.key, 'level': self.level, 'braille': self.braille, 'plaintext': self.plaintext} class product(): # ATTRIBUTE DECLARATION name: str line_length: int # number of Braille characters per line on keyboard msg: str # pre-translated English (with necessary modifications for input to this programme e.g. splitting up undesired translations with hidden delimiter character @?NOTHING) msg_prefix: str # additional pre-translated str as above to pre-append to product for adding header to creation of product messages from dictionary queries filename: str # filename - name without spaces # METHODS # def argvalinit(name: str, line_length: int, msg: str, msg_prefix: Optional[str] = ''): # # run before instantiating product # if not (av.val_str(name) and av.val_int(line_length, 0) and av.val_str(msg) and av.val_str(msg_prefix)): # print(f'Invalid product instantiation. name = {name}, line_length = {line_length}, msg = {msg}, msg_prefix = {msg_prefix}') # return None # return product(name, line_length, msg, msg_prefix) def __new__(cls, name, line_length, msg, msg_prefix = ''): # FUNCTION # Initialise class object # ARGUMENTS # str name # int line_length # str msg # str msg_prefix # ARGUMENT VALIDATION _m = 'product.__new__' v_arg_type = 'class attribute' av.val_str(name, 'name', _m, 1, -1, v_arg_type = v_arg_type) av.val_int(line_length, 'line_length', _m, 1, v_arg_type = v_arg_type) av.val_str(msg, 'msg', _m, -1, -1, v_arg_type = v_arg_type) av.val_str(msg_prefix, 'msg_prefix', _m, -1, -1, v_arg_type = v_arg_type) # if not av.val_str(name): # raise ValueError(av.error_msg_str('product.__new__', 'name', name, 'attribute')) # if not av.val_int(line_length, 1): # raise ValueError(av.error_msg_str('product.__new__', 'line_length', line_length, 'attribute')) # if not av.val_str(msg): # raise ValueError(av.error_msg_str('product.__new__', 'msg', msg, 'attribute')) # if not av.val_str(msg_prefix): # raise ValueError(av.error_msg_str('product.__new__', 'msg_prefix', msg_prefix, 'attribute')) # RETURNS return super(product, cls).__new__(cls) def __init__(self, name: str, line_length: int, msg: str, msg_prefix: Optional[str] = ''): # FUNCTION # Construct class object # ARGUMENTS # str name # int line_length # str msg # str msg_prefix # ARGUMENT VALIDATION # see __new__() # ATTRIBUTE + VARIABLE INSTANTIATION self.name = name self.line_length = line_length self.msg = msg self.msg_prefix = msg_prefix # for procedurally-generated messages from difficulty selection self.filename = name.replace(' ', '_') def __repr__(self): return f"name = {self.name}, line_length = {self.line_length}, msg = {self.msg}, msg_prefix = {self.msg_prefix}, filename = {self.filename}" def get_braille_translations(): # FUNCTION # return list of braille translations # longer keys get priority in translation # VARIABLE INSTANTIATION temp_dict = [braille_trans("A", difficulty(1), [[1, 0, 0, 0, 0, 0]]), braille_trans("B", difficulty(1), [[1, 1, 0, 0, 0, 0]]), braille_trans("C", difficulty(1), [[1, 0, 0, 1, 0, 0]]), braille_trans("D", difficulty(1), [[1, 0, 0, 1, 1, 0]]), braille_trans("E", difficulty(1), [[1, 0, 0, 0, 1, 0]]), braille_trans("F", difficulty(1), [[1, 1, 0, 1, 0, 0]]), braille_trans("G", difficulty(1), [[1, 1, 0, 1, 1, 0]]), braille_trans("H", difficulty(1), [[1, 1, 0, 0, 1, 0]]), braille_trans("I", difficulty(1), [[0, 1, 0, 1, 0, 0]]), braille_trans("J", difficulty(1), [[0, 1, 0, 1, 1, 0]]), braille_trans("K", difficulty(1), [[1, 0, 1, 0, 0, 0]]), braille_trans("L", difficulty(1), [[1, 1, 1, 0, 0, 0]]), braille_trans("M", difficulty(1), [[1, 0, 1, 1, 0, 0]]), braille_trans("N", difficulty(1), [[1, 0, 1, 1, 1, 0]]), braille_trans("O", difficulty(1), [[1, 0, 1, 0, 1, 0]]), braille_trans("P", difficulty(1), [[1, 1, 1, 1, 0, 0]]), braille_trans("Q", difficulty(1), [[1, 1, 1, 1, 1, 0]]), braille_trans("R", difficulty(1), [[1, 1, 1, 0, 1, 0]]), braille_trans("S", difficulty(1), [[0, 1, 1, 1, 0, 0]]), braille_trans("T", difficulty(1), [[0, 1, 1, 1, 1, 0]]), braille_trans("U", difficulty(1), [[1, 0, 1, 0, 0, 1]]), braille_trans("V", difficulty(1), [[1, 1, 1, 0, 0, 1]]), braille_trans("W", difficulty(1), [[0, 1, 0, 1, 1, 1]]), braille_trans("X", difficulty(1), [[1, 0, 1, 1, 0, 1]]), braille_trans("Y", difficulty(1), [[1, 0, 1, 1, 1, 1]]), braille_trans("Z", difficulty(1), [[1, 0, 1, 0, 1, 1]]), braille_trans("@?NUM", difficulty(1), [[0, 0, 1, 1, 1, 1]], 'NUMBER'), #" ", difficulty(1), [[0, 0, 0, 0, 0, 0]]), braille_trans(",", difficulty(1), [[0, 1, 0, 0, 0, 0]]), braille_trans(";", difficulty(1), [[0, 1, 1, 0, 0, 0]]), braille_trans(":", difficulty(1), [[0, 1, 0, 0, 1, 0]]), braille_trans(".", difficulty(1), [[0, 1, 0, 0, 1, 1]]), braille_trans("!", difficulty(1), [[0, 1, 1, 0, 1, 0]]), braille_trans("(", difficulty(1), [[0, 1, 1, 0, 1, 1]]), braille_trans(")", difficulty(1), [[0, 1, 1, 0, 1, 1]]), braille_trans("?", difficulty(1), [[0, 1, 1, 0, 0, 1]]), braille_trans('"@?BO', difficulty(1), [[0, 1, 1, 0, 0, 1]], '"'), braille_trans('"@?BC', difficulty(1), [[0, 0, 1, 0, 1, 1]], '"'), braille_trans("'", difficulty(1), [[0, 0, 1, 0, 0, 0]]), braille_trans("@?ABBREV1", difficulty(1), [[0, 0, 0, 1, 0, 0]], "ABBREV"), braille_trans("@?ABBREV2", difficulty(1), [[0, 0, 0, 1, 1, 0]], "ABBREV"), braille_trans("@?ABBREV3", difficulty(1), [[0, 0, 0, 1, 1, 1]], "ABBREV"), braille_trans("@?ABBREV4", difficulty(1), [[0, 0, 0, 0, 1, 0]], "ABBREV"), braille_trans("...", difficulty(1), [[0, 0, 1, 0, 0, 0], [0, 0, 1, 0, 0, 0], [0, 0, 1, 0, 0, 0]]), braille_trans("-", difficulty(1), [[0, 0, 1, 0, 0, 1]]), braille_trans("-@?S", difficulty(1), [[0, 0, 1, 0, 0, 1], [0, 0, 1, 0, 0, 1]], "-"), braille_trans("-@?L", difficulty(1), [[0, 0, 1, 0, 0, 1], [0, 0, 1, 0, 0, 1], [0, 0, 1, 0, 0, 1], [0, 0, 1, 0, 0, 1]], "-"), braille_trans("/@?B", difficulty(1), [[0, 0, 0, 1, 0, 0], [0, 1, 1, 0, 1, 1]], "/"), braille_trans("\@?B", difficulty(1), [[0, 0, 0, 1, 0, 0], [0, 1, 1, 0, 1, 1]], "\\"), braille_trans("[@?BPH", difficulty(1), [[0, 0, 0, 1, 1, 0], [0, 1, 1, 0, 1, 1]], "["), braille_trans("]@?BPH", difficulty(1), [[0, 0, 0, 1, 1, 0], [0, 1, 1, 0, 1, 1]], "]"), braille_trans("<", difficulty(1), [[0, 0, 0, 1, 1, 1], [0, 1, 1, 0, 1, 1]]), braille_trans(">", difficulty(1), [[0, 0, 0, 1, 1, 1], [0, 1, 1, 0, 1, 1]]), braille_trans("/", difficulty(1), [[0, 0, 0, 1, 1, 1], [0, 0, 1, 1, 0, 0]]), braille_trans("{", difficulty(1), [[0, 0, 0, 1, 0, 1], [0, 1, 1, 0, 1, 1]]), braille_trans("}", difficulty(1), [[0, 0, 0, 1, 0, 1], [0, 1, 1, 0, 1, 1]]), braille_trans("[@?BSQ", difficulty(1), [[0, 0, 0, 0, 0, 1], [0, 1, 1, 0, 1, 1]], "["), braille_trans("]@?BSQ", difficulty(1), [[0, 1, 1, 0, 1, 1], [0, 0, 0, 0, 0, 1]], "]"), braille_trans("'@?BO", difficulty(1), [[0, 0, 0, 0, 0, 1], [0, 1, 1, 0, 0, 1]], "'"), braille_trans("'@?BC", difficulty(1), [[0, 1, 1, 0, 0, 1], [0, 0, 0, 0, 0, 1]], "'"), # oldbrailledict_2 = { # Simple Upper Wordsigns braille_trans("BUT", difficulty(2), [[1, 1, 0, 0, 0, 0]]), braille_trans("CAN", difficulty(2), [[1, 0, 0, 1, 0, 0]]), braille_trans("DO", difficulty(2), [[1, 0, 0, 1, 1, 0]]), braille_trans("EVERY", difficulty(2), [[1, 0, 0, 0, 1, 0]]), braille_trans("FROM", difficulty(2), [[1, 1, 0, 1, 0, 0]]), braille_trans("GO", difficulty(2), [[1, 1, 0, 1, 1, 0]]), braille_trans("HAVE", difficulty(2), [[1, 1, 0, 0, 1, 0]]), braille_trans("JUST", difficulty(2), [[0, 1, 0, 1, 1, 0]]), braille_trans("KNOWLEDGE", difficulty(2), [[1, 0, 1, 0, 0, 0]]), braille_trans("LIKE", difficulty(2), [[1, 1, 1, 0, 0, 0]]), braille_trans("MORE", difficulty(2), [[1, 0, 1, 1, 0, 0]]), braille_trans("NOT", difficulty(2), [[1, 0, 1, 1, 1, 0]]), braille_trans("PEOPLE", difficulty(2), [[1, 1, 1, 1, 0, 0]]), braille_trans("QUITE", difficulty(2), [[1, 1, 1, 1, 1, 0]]), braille_trans("RATHER", difficulty(2), [[1, 1, 1, 0, 1, 0]]), braille_trans("SO", difficulty(2), [[0, 1, 1, 1, 0, 0]]), braille_trans("THAT", difficulty(2), [[0, 1, 1, 1, 1, 0]]), braille_trans("US", difficulty(2), [[1, 0, 1, 0, 0, 1]]), braille_trans("VERY", difficulty(2), [[1, 1, 1, 0, 0, 1]]), braille_trans("WILL", difficulty(2), [[0, 1, 0, 1, 1, 1]]), braille_trans("IT", difficulty(2), [[1, 0, 1, 1, 0, 1]]), braille_trans("YOU", difficulty(2), [[1, 0, 1, 1, 1, 1]]), braille_trans("AS", difficulty(2), [[1, 0, 1, 0, 1, 1]]), braille_trans("CHILD", difficulty(2), [[1, 0, 0, 0, 0, 1]]), braille_trans("SHALL", difficulty(2), [[1, 0, 0, 1, 0, 1]]), braille_trans("THIS", difficulty(2), [[1, 0, 0, 1, 1, 1]]), braille_trans("WHICH", difficulty(2), [[1, 0, 0, 0, 1, 1]]), braille_trans("OUT", difficulty(2), [[1, 1, 0, 0, 1, 1]]), braille_trans("STILL", difficulty(2), [[0, 0, 1, 1, 0, 0]]), # Simple Upper Groupsigns braille_trans("AND", difficulty(2), [[1, 1, 1, 1, 0, 1]]), braille_trans("FOR", difficulty(2), [[1, 1, 1, 1, 1, 1]]), braille_trans("OF", difficulty(2), [[1, 1, 1, 0, 1, 1]]), braille_trans("THE", difficulty(2), [[0, 1, 1, 1, 0, 1]]), braille_trans("WITH", difficulty(2), [[0, 1, 1, 1, 1, 1]]), braille_trans("CH", difficulty(2), [[1, 0, 0, 0, 0, 1]]), braille_trans("GH", difficulty(2), [[1, 1, 0, 0, 0, 1]]), braille_trans("SH", difficulty(2), [[1, 0, 0, 1, 0, 1]]), braille_trans("TH", difficulty(2), [[1, 0, 0, 1, 1, 1]]), braille_trans("WH", difficulty(2), [[1, 0, 0, 0, 1, 1]]), braille_trans("ED", difficulty(2), [[1, 1, 0, 1, 0, 1]]), braille_trans("ER", difficulty(2), [[1, 1, 0, 1, 1, 1]]), braille_trans("OU", difficulty(2), [[1, 1, 0, 0, 1, 1]]), braille_trans("OW", difficulty(2), [[0, 1, 0, 1, 0, 1]]), braille_trans("ST", difficulty(2), [[0, 0, 1, 1, 0, 0]]), braille_trans("AR", difficulty(2), [[0, 0, 1, 1, 1, 0]]), braille_trans("ING", difficulty(2), [[0, 0, 1, 1, 0, 1]]), braille_trans("BLE", difficulty(2), [[0, 0, 1, 1, 1, 1]]), # oldbrailledict_3 = { # Lower Contractions # Initial Groupsigns braille_trans("BE", difficulty(3), [[0, 1, 1, 0, 0, 0]]), braille_trans("COM", difficulty(3), [[0, 0, 1, 0, 0, 1]]), braille_trans("CON", difficulty(3), [[0, 1, 0, 0, 1, 0]]), braille_trans("DIS", difficulty(3), [[0, 1, 0, 0, 1, 1]]), # Initial-Medial-Terminal Groupsigns braille_trans("EN", difficulty(3), [[0, 1, 0, 0, 0, 1]]), braille_trans("IN", difficulty(3), [[0, 0, 1, 0, 1, 0]]), # Medial Groupsigns braille_trans("EA", difficulty(3), [[0, 1, 0, 0, 0, 0]]), braille_trans("BB", difficulty(3), [[0, 1, 1, 0, 0, 0]]), braille_trans("CC", difficulty(3), [[0, 1, 0, 0, 1, 0]]), braille_trans("DD", difficulty(3), [[0, 1, 0, 0, 1, 1]]), braille_trans("FF", difficulty(3), [[0, 1, 1, 0, 1, 0]]), braille_trans("GG", difficulty(3), [[0, 1, 1, 0, 1, 1]]), # Wordsigns braille_trans("ENOUGH", difficulty(3), [[0, 1, 0, 0, 0, 1]]), braille_trans("TO", difficulty(3), [[0, 1, 1, 0, 1, 0]]), braille_trans("WERE", difficulty(3), [[0, 1, 1, 0 , 1, 1]]), braille_trans("HIS", difficulty(3), [[0, 1, 1, 0, 0, 1]]), braille_trans("INTO", difficulty(3), [[0, 0, 1, 0, 1, 0], [0, 1, 1, 0, 1, 0]]), #(sequenced) braille_trans("BY", difficulty(3), [[0, 0, 1, 0, 1, 1]]), #(sequenced) braille_trans("WAS", difficulty(3), [[0, 0 , 1, 0 , 1, 1]]), # Modifiers braille_trans("@?LET", difficulty(3), [[0, 0, 0, 0, 1, 1]], "LET"), braille_trans("@?CAPS", difficulty(3), [[0, 0, 0, 0, 0, 1]], "CAPS"), braille_trans("@?EMPH", difficulty(3), [[0, 0, 0, 1, 0, 1]], "EMPH"), ] # remove None 's - rejected inputs valid = False while not valid: try: temp_dict.remove(None) except: valid = True braille_dict = pd.DataFrame([x.as_dict() for x in temp_dict]) # , columns=['key', 'level', 'msg', 'msg_prefix']) # RETURNS # print('Braille Dictionary Creation') # print(f"type(temp_dict) = {type(temp_dict)}") # print("temp_dict = ") # for i in range(len(temp_dict)): # print(f"{temp_dict[i]}") # print('') # print(f"type(braille_dict) = {type(braille_dict)}") # print(f"braille_dict = {braille_dict}") return braille_dict # temp_dict # braille_dict def get_delimiters(): # FUNCTION # delimiters and special character codes for plaintext message before braille translation # VARIABLE INSTANTIATION txtdict = {"@?NUM" : "NUMBER", "@?NOTHING" : "", #" " : "", '"@?BO' : '"', '"@?BC' : '"', "-@?S" : "-", "-@?L" : "-", "/@?B" : "/", "[@?BPH" : "[", "]@?BPH" : "]", "[@?BSQ" : "[", "]@?BSQ" : "]", "'@?BO" : "'", "'@?BC" : "'", "@?LET" : "LET", "@?CAPS" : "CAPS", "@?EMPH" : "EMPH", "@?ABBREV1" : "ABBREV", "@?ABBREV2" : "ABBREV", "@?ABBREV3" : "ABBREV", "@?ABBREV4" : "ABBREV", } # RETURNS return txtdict def gen_difficulty_msgstr(braille_dict, level: difficulty = difficulty(1)): # FUNCTION # generate keyboard message for specified difficulty # ARGUMENTS # list[braille_trans] braille_dict # difficulty level # ARGUMENT VALIDATION _m = 'gen_difficulty_msgstr' av.val_type(braille_dict, "", 'braille_dict', _m) av.val_type(level, "", 'level', _m) # VARIABLE INSTANTIATION str_out = '' # n = len(braille_dict) # METHODS # print(f"len(braille_dict) = {n}") # print(f"braille_dict.columns =") # for i in braille_dict.columns: # print(braille_dict.columns[i]) # temp_dict = braille_dict['key'] dict_iterator = braille_dict[braille_dict['level'] == level] print(f"dict_iterator.index = {dict_iterator.index}") for bd_i in range(len(dict_iterator.index)): bd_n = dict_iterator['key'][dict_iterator.index[bd_i]] # print(f"bd_i = {bd_i}") # print(f"bd_n = {bd_n}") str_out += "@?NOTHING" + bd_n # for i in range(n): # bd_i = braille_dict.loc[i][0] # # print(f"bd_i = {bd_i}") # # print(f"type(bd_i) = {str(type(bd_i))}") # if (bd_i.level == difficulty): # str_out += "@?NOTHING" + bd_i.key # RETURNS return str_out # def get_braille_by_key(braille_dict: pd.DataFrame, key: str): # # FUNCTION # # Find key in braille dictionary # return None # # ARGUMENTS # # ARGUMENT VALIDATION # # VARIABLE INSTANTIATION # # METHODS # # RETURNS def input_product(braille_dict, products, my_option: Optional[int] = -1, my_select: Optional[str] = ''): # FUNCTION # Get product input from user - repeat until valid input received # ARGUMENTS # list[braille_trans] braile_dict # list[product] products # optional int my_option - if option provided in code # ARGUMENT VALIDATION _m = 'input_product' av.val_type(braille_dict, "", 'braille_dict', _m) av.val_list(products, 'products', _m, "", 1) av.val_int(my_option, 'my_option', _m) # VARIABLE INSTANTIATION N = len(products) select_i = my_option valid = (my_option > 0 and my_option <= N) # temp_dict = braille_dict['key'] # METHODS if valid: if my_option == N: temp = braille_dict[braille_dict['key'] == my_select] if len(temp.index) == 1: products[N - 1].msg_prefix = my_select else: valid = False while not valid: print() print('Welcome to your 3D Braille Model Generator') print("At any time, answer the following error code to exit (excl. speech marks): '#!ERRORCODE!#'") print() print('Braille Products:') for i in range(N): print(f"{i + 1}. {products[i].name}") print() select_i = av.input_int(input(f"Please enter your selection (1 - {N}) from the products above\n"), 1, N) if select_i == '#!ERRORCODE!#': sys.exit valid = not (str(type(select_i)) == "") if valid and select_i == N: valid = False while not valid: select_A = input("Please enter a character selection for your Scrabble tile\n") if select_A == '#!ERRORCODE!#': sys.exit temp = braille_dict[braille_dict['key'] == select_A].index if not len(temp) == 1: print(f"temp = {temp}") valid = False else: valid = True products[N - 1].msg_prefix = select_A # RETURNS return products[select_i - 1] def append_ifnotNone(v_list, v_item): # FUNCTION # append v_item to v_list if v_item is not None # ARGUMENTS # list v_list # v_item # ARGUMENT VALIDATION if (not av.val_list(v_list, 'v_list', 'append_ifnotNone', suppress_errors = True)) or v_item == None: # RETURNS return v_list v_list.append(v_item) return v_list#.append(v_item) def gen_product_inputs(braille_dict): # FUNCTION # Generate product inputs # ARGUMENTS # [pandas.DataFrame] braille_dict - braille dictionary # VARIABLE INSTANTIATION products = [] # ARGUMENT VALIDATION av.val_type(braille_dict, "", 'braille_dict', 'gen_product_inputs') # METHODS products.append(product("Extended Alphabet", 10, "abcdefg@?NOTHINGhijKLMNOPQRS@?NOTHINGTUVXYZANDFOROFTHEWITHCHGHSHTHWHEDEROUOWWEABBCCDDENFF?GGINBY")) products.append(product("Upper Groupsigns", 10, "uppe@?nothingr GRO@?NOTHINGUPSIGNsand:a@?nothingn@?nothingd for:fo@?nothingr of:o@?nothingf the:t@?nothingh@?nothinge with:wi@?nothingt@?nothingh "+"@?NEWLINECH:C@?NOTHINGH " + "GH:G@?NOTHINGH " + "SH:S@?NOTHINGH " + "TH:T@?NOTHINGH " + "WH:W@?NOTHINGH " + "ED:E@?NOTHINGD " + "ER:E@?NOTHINGR " + "OU:O@?NOTHINGU " + "OW:O@?NOTHINGW "+"st:s@?nothingt ar:a@?nothingr ble:bl@?nothinge ing:i@?nothingng")) products.append(product("Upper Wordsigns", 24, gen_difficulty_msgstr(braille_dict, difficulty(3)))) products.append(product("Alphabet", 10, "ABCDEFG@?NOTHINGHIJKLMNOPQRSTUVWXYZ")) products.append(product("Travel", 5, "ABCDEFG@?NOTHINGHIJ")) products.append(product("Scrabble Alphabet of Tiles", 1, '')) products.append(product("Scrabble Character Tile", 1, '')) # RETURNS return products def gen_braille_inputs_4_openscad(msgin, line_length, brailledict): # , hyphenate = False # FUNCTION # Convert message to Braille for openSCAD generation # ARGUMENTS # str msgin - partially translated message containing only brailledict keys and blankspace # int line_length - number of Braille characters per row on keyboard # pandas.DataFrame brailledict - Braille translations with diffculty # # bool hyphenate - hyphenate words that cross lines or start on new line # ARGUMENT VALIDATION _m = 'gen_braille_inputs_4_openscad' av.val_str(msgin, 'msgin', _m, 1) av.val_int(line_length, 'line_length', _m) av.val_type(brailledict, "", 'brailledict', _m) # VARIABLE INSTANTIATION # dict txtdict - delimiters for Braille translation msgin = msgin.upper() braille = [] letters = ["", ] n_rows = 1 start_of_word = 0 # position within cum numbers = [] cum = [0] # 0-based cumulative starting position of Braille translation of message segments #lmsg = [0] * len(msgin) # length of braille message last_is_num = False new_word = True iter_lim = len(msgin) print(f"iteration limit = {iter_lim}") #len(msgin)) msg_i_0 = -1 maxstrlen = max_key_len(brailledict) # METHODS print(f"msgin = {msgin}") while (msg_i_0 < iter_lim): msg_i_0 = msg_i_0 + 1 found = False print(f"msg_i_0 = {msg_i_0}") for phrase_len in range(min(len(msgin) - msg_i_0, maxstrlen), 0, -1): if found: continue phrase = msgin[msg_i_0 : msg_i_0 + phrase_len] # message segment to search for in Braille translation keys print(f'phrase = {phrase}') # generate braille if a code has been found if (phrase_len == 0): if (ord(phrase) >= 48 and ord(phrase) <= 57): # numbers b_num_pre = brailledict[brailledict['key'] == "@?NUM"]['braille'].values[0] b_num = brailledict[brailledict['key'] == ("J" if (ord(phrase) == 48) else chr(ord(phrase)+16))]['braille'].values[0] if last_is_num == True: braille[len(braille) - 1].append(b_num[0]) new_cum = 1 # temp = temp2 else: braille.append([b_num_pre[0], b_num[0]]) new_cum = 2 # temp = [temp1[0], temp2[0]] print('braille(numeric phrase) = ', braille[len(braille) - 1]) last_is_num = True else: # new_cum = len(brailledict[brailledict['key'] == phrase].index) found = (len(brailledict[brailledict['key'] == phrase].index) == 1) if found: last_is_num = False # temp = brailledict.get(phrase) else: # new_cum = len(brailledict[brailledict['key'] == phrase].index) found = (len(brailledict[brailledict['key'] == phrase].index) == 1) if found: last_is_num = False # temp = brailledict.get(phrase) #print("tempsearch = ", temp) # organise placement of braille phrase onto end of whole message if found or last_is_num: # (temp != None): # # found = True # last_is_num = False new_num = [-1] if (len(phrase) == 1): if (ord(phrase) >= 65 and ord(phrase) <= 90): # letters new_num = [ord(phrase) - 64] elif (ord(phrase) >= 48 and ord(phrase) <= 57): # numbers new_num = [ord(phrase) - 48] # last_is_num = True if found: braille.append(brailledict[brailledict['key'] == phrase]['braille'].values[0]) new_cum = len(braille[len(braille) - 1]) numbers.append(new_num) new_cum = cum[len(cum) - 1] + new_cum cum.append(new_cum) n_rows_0 = n_lines_at_pos(start_of_word, line_length) n_rows_next = n_lines_at_pos(new_cum, line_length) if (n_rows_0 < n_rows_next and not n_rows_0 % line_length == 0): delta_cum_new_line = n_rows_next * line_length + 1 - cum[start_of_word] for msg_j in range(len(cum) - start_of_word - 1): cum[start_of_word + msg_j] += delta_cum_new_line #if (cum[len(cum)-1] % line_length > 0): # cum[len(cum)-1] = cum[len(cum)-1] + line_length - (1+(cum[len(cum)-1]-1) % line_length) # print("clean_rows",cum[len(cum)-1]) # print("phrase_len=",phrase_len) msg_i_0 += phrase_len - 1 letters.append(brailledict[brailledict['key'] == phrase]['plaintext'].values[0]) # temptxt = txtdict.get(phrase) # if temptxt == None: # letters.append(phrase) # else: # letters.append(temptxt) elif phrase == "@?NOTHING": msg_i_0 += 8 # 9 print('found nothing') found = True elif phrase == "@?NEWLINE": msg_i_0 += 8 # 9 print('forced newline') cum[len(cum) - 1] += line_length - 1 - ((cum[len(cum) - 1] - 1) % line_length) found = True start_of_word = True elif phrase == " ": # and (cum[len(cum)-1] % line_length > 0)): # no space at start of line # or letters[len(cum)-1] == " " or msgin[ni+1] == " ") # msg_i_0 += 1 cum[len(cum)-1] = cum[len(cum)-1] + 1 print('space') start_of_word = True # word start position if new_word: start_of_word = len(cum) - 1 # position within cum # unfound character?? if phrase_len == 0 and not (found or (ord(phrase) >= 48 and ord(phrase) <= 57)): print(f"Unfound phrase: {phrase}") # OUTPUTS # console output n_keys = max(cum) letters = letters[1:len(letters)] # why does element 0 exist? # print(f"message length b = {n_keys}") # print(f"braille = {braille}") # print(f"cum = {cum}") # print(f"numbers = {numbers}") # print(f"letters = {letters}") ## file output f = open('Braille.txt','a') f.truncate() f.write(f'cum = {str(cum)};\n') f.write('msgstr = [') for i in range(len(letters)): f.write('"') f.write(str(letters[i])) if i < len(letters) - 1: f.write('", ') f.write('"];\n') f.write('numbers = [') for i in range(len(numbers)): #f.write('"') f.write(str(numbers[i])) if i < len(numbers) - 1: f.write(', ') f.write('];\n') f.write(f"inA = {str(braille)};\n") f.write(f"lmsg = {str(len(braille))};\n") f.write(f"N = {str(n_keys)};\n") f.write(f"nln = {str(min(line_length, n_keys))};\n") f.write(f"maxln = {str(n_rows)};\n") f.close() # RETURNS return cum, letters, numbers, braille, n_keys, n_rows def n_lines_at_pos(position, line_length): # FUNCTION # calculate number of rows of keyboard required for message of length (in Braille keys) position # ARGUMENTS # int position - quantity of Braille keys in message up to (+ incl.) position # int line_length - number of Braille keys per line / row # ARGUMENT VALIDATION _m = 'n_lines_at_pos' av.val_int(position, 'position', _m, 0) av.val_int(line_length, 'line_length', _m, 1) # RETURNS return 1 + (position // line_length) def max_key_len(mydict: pd.DataFrame, min_dict_len: Optional[int] = 1): # FUNCTION # find maximum key length in braille dictionary # ARGUMENTS # pandas.DataFrame mydict # ARGUMENT VALIDATION _m = 'max_key_len' av.val_int(min_dict_len, 'min_dict_len', _m) av.val_type(mydict, "", 'mydict', _m) # VARIABLE INSTANTIATION n = len(mydict.index) max_len = 0 # METHODS for i in range(n): max_len = max(max_len, len(mydict.iloc[i]['key'])) if max_len < min_dict_len: return -1 # RETURNS return max_len # ToDo: Finish this! # def remove_words_in_word(word, maxstrlen=9): # ln = len(word) # minmax = min(ln, maxstrlen) # fix = False # skip = False # for length in np.arange(minmax, 1, -1): # for start in range(ln-length): # tempstr = word[start:start+length] # if (tempstr == "@?NOTHING"): # skip = True # if skip: # continue # tempfind = brailledict.get(tempstr) # if not (tempbool == None): # tempword = word[:start] # for li in range(length): # ## add "@?NOTHING" # def get_translated_input(my_option: Optional[int] = -1): # REDUNDANT # # FUNCTION # # Get product selection input from user + convert to Braille # # VARIABLE INSTANTIATION # braille_translations = get_braille_translations() # products = gen_product_inputs(braille_translations) # delimiters = get_delimiters() # # METHODS # my_product = input_product(braille_translations, products, my_option) # # cum, letters, numbers, braille, ltmsg, n_rows = gen_braille_inputs_4_openscad(my_product.msg, my_product.line_length, braille_translations, max_key_len(braille_translations), delimiters) # # RETURNS # return my_product, braille_translations, max_key_len(braille_translations), delimiters # get_translated_input() ' requires translate_msg_2_braille is replaced by __main__ in type validation strings # def process_old_dict(old_dict, difficulty): # # FUNCTION # # create new list of braille_trans dataclass items # # ARGUMENTS # # old_dict - old dictionary of keys, values # # difficulty - level field of dataclass # # ARGUMENT VALIDATION # print(f"type(old_dict) = {type(old_dict)}") # print(f"type(difficulty) = {type(difficulty)}") # # VARIABLE INSTANTIATION # new_dict = [] # # METHODS # for i in range(len(old_dict)): # temp_key, temp_value = old_dict.popitem() # new_dict.append(braille_trans(temp_key, difficulty, temp_value)) # # RETURNS # return new_dict # class braille_dictionary(): # def __init__(self, keys, hardnesses, braille_translations): # return self.push(keys, hardnesses, braille_translations) # def push(self, keys, hardnesses, braille_translations): # N_in = len(keys) # if not (N_in == len(hardnesses) == len(braille_translations)): # return False # for i in range(N_in - 1): # for j in range(i + 1): # if (keys[i + 1] == keys[j]): # return False # for i in range(N_in): # self.keys.append(keys[i]) # self.hards.append(hardnesses[i]) # self.brailles.append(braille_translations[i]) # return True # def exists_key(self, key): # try: # i = self.keys.index(key) # except ValueError: # return True # else: # return False # def get_key_index(self, key): # if self.exists_key(key): # return self.keys.index(key) # else: # return -1