# Quansheng UV-K5 driver (c) 2024 Giorgio (IU0QWJ) for the Fagci R3b0rn firmware
#
# based on template.py Copyright 2012 Dan Smith <dsmith@danplanet.com>
# based on Copyright 2023 Jacek Lipkowski <sq5bpf@lipkowski.org>
#
# This is a preliminary version of a driver for the UV-K5
# It is based on my reverse engineering effort described here:
# https://github.com/sq5bpf/uvk5-reverse-engineering
#
# Warning: this driver is experimental, it may brick your radio,
# eat your lunch and mess up your configuration.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
# Made From Giorgio (IU0QWJ) for the Fagci R3b0rn firmware
# https://github.com/gpillon
# https://github.com/fagci/uvk5-fagci-reborn
#
# Many Thanks to:
# - IJV
# - Julian Lilov (LZ1JDL)
# - Francesco IK8JHL,
# for their work :)
# and...THANKS FAGCI FOR THE FIRMWARE!


# Known Bugs (Fixes Needed - Help is Appreciated)
# - Custom mode names differ from those on the radio (might require a pull request to CHIRP)

import math

import struct
import logging
import re
import wx

# noinspection PyUnresolvedReferences
from chirp import chirp_common, directory, bitwise, memmap, errors, util
# noinspection PyUnresolvedReferences
from chirp.settings import RadioSetting, RadioSettingGroup, \
    RadioSettingValueBoolean, RadioSettingValueList, \
    RadioSettingValueInteger, RadioSettingValueString, \
    RadioSettings, RadioSettingSubGroup

LOG = logging.getLogger(__name__)

# Define the allowed characters
ALLOWED_CHARS = ''.join(chirp_common.CHARSET_ASCII)

# Create a regex pattern to match any character not in the allowed list
ALLOWED_CHARS_PATTERN = f'[^{re.escape(ALLOWED_CHARS)}]'

# Show the obfuscated version of commands. Not needed normally, but
# might be useful for someone who is debugging a similar radio
DEBUG_SHOW_OBFUSCATED_COMMANDS = True

# Show the memory being written/received. Not needed normally, because
# this is the same information as in the packet hexdumps, but
# might be useful for someone debugging some obscure memory issue
DEBUG_SHOW_MEMORY_ACTIONS = True

MEM_BLOCK = 0x80  # largest block of memory that we can reliably write

OFFSET_SIZE = 0  # size of the offset in the memory map

RAW_PATCH_DATA = [21, 0, 15, 224, 242, 115, 118, 47, 22, 111, 38, 30, 0, 75, 44, 88, 22, 163, 116, 15, 224, 76, 54, 228,
              22, 10, 224, 248, 205, 243, 135, 218, 22, 46, 161, 223, 110, 235, 53, 156, 22, 159, 26, 9, 238, 185,
              181, 69, 22, 163, 92, 15, 162, 193, 63, 174, 22, 133, 82, 68, 119, 49, 234, 132, 22, 79, 253, 12, 84,
              127, 69, 207, 22, 249, 39, 2, 78, 9, 162, 104, 22, 127, 156, 248, 207, 51, 57, 45, 22, 86, 142, 194,
              52, 248, 115, 118, 22, 185, 94, 92, 74, 253, 97, 0, 22, 102, 81, 133, 209, 85, 48, 52, 22, 80, 121, 71,
              36, 192, 25, 102, 22, 212, 88, 128, 91, 207, 134, 113, 22, 109, 120, 38, 162, 137, 71, 111, 22, 27,
              222, 15, 35, 178, 91, 101, 22, 13, 102, 130, 147, 18, 198, 46, 22, 88, 69, 244, 163, 132, 32, 101, 22,
              7, 219, 34, 48, 54, 96, 155, 22, 146, 104, 196, 119, 241, 124, 152, 22, 116, 163, 213, 214, 231, 254,
              226, 22, 100, 148, 24, 78, 122, 191, 77, 22, 180, 113, 171, 11, 45, 154, 53, 22, 53, 159, 254, 7, 237,
              14, 220, 22, 174, 205, 197, 45, 83, 142, 214, 22, 22, 196, 16, 16, 61, 9, 64, 22, 192, 154, 118, 232,
              11, 18, 63, 22, 184, 73, 225, 79, 185, 108, 87, 22, 3, 49, 34, 165, 65, 200, 198, 22, 146, 72, 100,
              144, 60, 122, 163, 22, 65, 46, 44, 72, 76, 218, 217, 22, 243, 248, 17, 162, 51, 84, 47, 22, 55, 172,
              27, 168, 48, 3, 203, 22, 111, 47, 198, 232, 55, 29, 182, 22, 116, 173, 90, 7, 57, 53, 243, 22, 85, 111,
              219, 195, 36, 254, 151, 22, 137, 249, 42, 24, 156, 238, 123, 22, 239, 126, 83, 90, 234, 178, 102, 22,
              11, 168, 234, 137, 86, 121, 161, 22, 10, 159, 239, 100, 241, 182, 230, 22, 88, 199, 149, 45, 163, 114,
              164, 22, 108, 239, 27, 166, 212, 141, 219, 22, 227, 16, 67, 188, 39, 166, 212, 22, 185, 73, 218, 14,
              118, 20, 189, 22, 76, 114, 148, 118, 202, 221, 86, 22, 143, 52, 41, 89, 164, 60, 221, 22, 135, 202,
              193, 147, 158, 214, 243, 22, 82, 194, 128, 197, 38, 181, 33, 22, 206, 224, 112, 27, 181, 44, 230, 22,
              75, 198, 65, 232, 56, 31, 240, 22, 26, 101, 167, 100, 11, 23, 212, 22, 105, 57, 8, 11, 84, 25, 71, 22,
              50, 22, 109, 110, 201, 141, 75, 22, 38, 37, 193, 179, 223, 223, 185, 22, 52, 51, 218, 45, 142, 39, 111,
              22, 185, 130, 111, 192, 20, 32, 20, 22, 57, 86, 227, 51, 99, 18, 223, 22, 4, 51, 88, 227, 158, 226, 55,
              22, 94, 126, 48, 68, 74, 145, 107, 22, 240, 18, 105, 89, 135, 106, 241, 22, 107, 204, 27, 83, 237, 255,
              221, 22, 15, 235, 94, 86, 64, 105, 242, 22, 96, 193, 165, 121, 121, 198, 198, 22, 129, 127, 241, 175,
              85, 79, 19, 22, 219, 223, 239, 154, 65, 87, 57, 22, 205, 250, 144, 203, 24, 17, 111, 22, 222, 116, 19,
              243, 94, 90, 203, 22, 117, 50, 40, 60, 238, 132, 118, 22, 247, 9, 227, 215, 90, 179, 122, 22, 71, 159,
              128, 190, 154, 162, 225, 22, 19, 227, 45, 199, 213, 17, 64, 22, 4, 105, 195, 222, 81, 172, 247, 22,
              155, 2, 224, 198, 135, 230, 33, 22, 42, 240, 182, 79, 96, 53, 63, 22, 229, 248, 157, 196, 237, 133,
              209, 22, 79, 133, 93, 179, 105, 50, 38, 22, 98, 95, 224, 213, 125, 117, 221, 22, 223, 122, 54, 204,
              227, 75, 51, 22, 226, 138, 69, 110, 73, 117, 1, 22, 23, 20, 149, 167, 8, 235, 113, 22, 48, 251, 110,
              83, 216, 219, 62, 22, 238, 130, 188, 235, 226, 47, 191, 22, 14, 77, 21, 111, 200, 186, 2, 22, 152, 35,
              159, 196, 224, 64, 242, 22, 162, 83, 205, 204, 211, 224, 126, 22, 246, 13, 119, 78, 35, 6, 92, 22, 214,
              77, 227, 180, 250, 35, 203, 22, 108, 102, 131, 1, 121, 141, 141, 22, 208, 3, 43, 184, 136, 147, 27, 22,
              132, 63, 124, 164, 155, 190, 173, 22, 210, 71, 197, 127, 156, 242, 218, 22, 155, 26, 218, 187, 92, 147,
              88, 22, 160, 86, 167, 163, 146, 193, 35, 22, 85, 94, 108, 237, 152, 189, 199, 22, 224, 243, 3, 251, 43,
              244, 159, 22, 95, 41, 67, 94, 246, 67, 137, 22, 214, 121, 136, 26, 188, 226, 14, 22, 160, 189, 8, 61,
              185, 155, 245, 22, 14, 245, 169, 251, 38, 23, 8, 22, 150, 2, 24, 232, 88, 180, 111, 22, 61, 70, 54, 15,
              211, 135, 103, 22, 172, 209, 180, 54, 227, 232, 218, 22, 234, 147, 166, 236, 142, 45, 52, 22, 49, 240,
              116, 184, 137, 216, 109, 22, 237, 66, 94, 147, 59, 71, 208, 22, 9, 96, 175, 57, 91, 124, 34, 22, 127,
              33, 209, 253, 3, 86, 224, 22, 196, 248, 135, 253, 194, 15, 7, 22, 58, 170, 140, 154, 96, 112, 35, 22,
              113, 129, 119, 62, 83, 15, 245, 22, 225, 77, 70, 105, 206, 169, 6, 22, 193, 253, 152, 218, 237, 157,
              52, 22, 162, 239, 108, 248, 124, 80, 180, 22, 237, 231, 181, 29, 93, 125, 108, 22, 249, 159, 118, 208,
              9, 71, 50, 22, 240, 174, 186, 105, 214, 190, 26, 22, 75, 103, 44, 124, 107, 88, 62, 22, 5, 16, 179,
              107, 95, 57, 246, 22, 197, 61, 228, 108, 15, 250, 110, 22, 104, 162, 116, 163, 228, 205, 42, 22, 193,
              31, 188, 59, 243, 206, 214, 22, 202, 135, 116, 190, 37, 72, 196, 22, 63, 170, 51, 76, 21, 102, 175, 22,
              244, 84, 30, 34, 198, 82, 234, 22, 135, 254, 216, 174, 91, 134, 63, 22, 140, 252, 212, 68, 176, 64,
              100, 22, 19, 234, 65, 237, 114, 247, 157, 22, 54, 89, 231, 182, 64, 35, 229, 22, 197, 253, 131, 208,
              98, 130, 17, 22, 254, 60, 17, 125, 64, 232, 23, 22, 192, 126, 235, 209, 193, 1, 223, 22, 210, 212, 114,
              26, 84, 190, 199, 22, 25, 241, 197, 91, 227, 19, 43, 22, 109, 228, 67, 238, 142, 78, 253, 22, 248, 182,
              131, 68, 38, 142, 56, 22, 166, 227, 233, 27, 91, 20, 32, 22, 159, 117, 229, 153, 181, 163, 129, 22, 54,
              184, 216, 247, 181, 122, 97, 22, 218, 196, 173, 62, 39, 87, 227, 22, 201, 195, 82, 133, 28, 158, 108,
              22, 159, 23, 4, 9, 32, 176, 119, 22, 206, 24, 237, 29, 174, 161, 0, 22, 219, 165, 176, 123, 117, 128,
              11, 22, 18, 58, 218, 245, 5, 238, 165, 22, 16, 28, 120, 202, 102, 191, 205, 22, 242, 164, 186, 40, 28,
              129, 237, 22, 68, 51, 42, 108, 78, 87, 170, 22, 212, 235, 69, 173, 186, 133, 62, 22, 219, 84, 26, 221,
              8, 175, 183, 22, 199, 221, 16, 145, 242, 180, 31, 22, 39, 51, 72, 139, 89, 227, 59, 22, 226, 223, 32,
              97, 45, 105, 216, 22, 120, 253, 61, 119, 232, 63, 12, 22, 169, 165, 164, 188, 106, 197, 83, 22, 246,
              207, 174, 66, 142, 159, 6, 22, 36, 254, 8, 236, 78, 68, 69, 22, 63, 104, 134, 189, 159, 180, 136, 22,
              24, 235, 33, 251, 218, 234, 96, 22, 157, 33, 162, 105, 154, 179, 189, 22, 214, 91, 225, 94, 225, 186,
              95, 22, 246, 236, 140, 40, 129, 143, 244, 22, 69, 175, 2, 75, 223, 73, 215, 22, 140, 37, 238, 249, 86,
              33, 65, 22, 217, 250, 241, 56, 115, 48, 141, 22, 79, 219, 5, 198, 206, 88, 0, 22, 172, 68, 138, 238,
              152, 229, 75, 22, 199, 211, 76, 15, 138, 76, 13, 22, 207, 17, 77, 147, 166, 186, 146, 22, 237, 222, 6,
              189, 67, 48, 199, 22, 205, 162, 95, 177, 19, 249, 217, 22, 26, 168, 8, 107, 195, 52, 6, 22, 119, 60,
              72, 204, 189, 155, 200, 22, 58, 36, 92, 36, 8, 194, 212, 22, 169, 39, 244, 223, 27, 102, 71, 22, 110,
              82, 142, 12, 134, 92, 65, 22, 234, 250, 148, 77, 224, 60, 149, 22, 35, 11, 214, 28, 184, 95, 19, 22,
              74, 41, 13, 41, 124, 204, 216, 22, 240, 128, 12, 25, 138, 115, 130, 22, 121, 1, 64, 155, 174, 10, 25,
              22, 249, 200, 77, 96, 197, 208, 129, 22, 14, 207, 200, 230, 2, 161, 11, 22, 149, 81, 199, 189, 148,
              126, 248, 22, 73, 167, 159, 231, 233, 63, 240, 22, 81, 49, 136, 236, 248, 0, 68, 22, 180, 20, 101, 236,
              118, 97, 69, 22, 238, 186, 88, 135, 237, 237, 16, 22, 2, 118, 74, 144, 61, 152, 21, 22, 193, 31, 123,
              250, 204, 62, 29, 22, 5, 173, 34, 228, 114, 124, 110, 22, 171, 215, 162, 37, 58, 165, 230, 22, 240,
              175, 123, 212, 114, 96, 188, 22, 84, 254, 96, 220, 207, 129, 52, 22, 227, 212, 174, 165, 144, 212, 0,
              22, 74, 163, 83, 29, 111, 147, 127, 22, 93, 252, 121, 159, 81, 14, 53, 22, 12, 166, 33, 4, 129, 130, 7,
              22, 36, 246, 196, 180, 180, 37, 254, 22, 195, 102, 216, 114, 21, 138, 106, 22, 35, 186, 153, 119, 80,
              168, 241, 22, 46, 206, 31, 99, 127, 168, 189, 22, 34, 81, 218, 47, 253, 250, 99, 22, 83, 200, 222, 63,
              176, 56, 69, 22, 183, 134, 9, 23, 137, 91, 174, 22, 15, 85, 106, 215, 22, 208, 33, 22, 249, 61, 157,
              163, 239, 107, 197, 22, 131, 195, 186, 75, 64, 103, 55, 22, 138, 198, 14, 225, 172, 241, 66, 22, 146,
              254, 123, 39, 106, 91, 19, 22, 10, 143, 253, 54, 254, 155, 143, 22, 17, 229, 192, 105, 52, 209, 125,
              22, 155, 223, 203, 183, 49, 255, 234, 22, 84, 214, 54, 170, 117, 71, 240, 22, 169, 145, 166, 19, 236,
              214, 13, 22, 98, 75, 135, 205, 27, 163, 119, 22, 11, 231, 35, 87, 192, 90, 254, 22, 84, 242, 74, 13,
              12, 86, 172, 22, 8, 226, 239, 212, 204, 120, 148, 22, 169, 242, 93, 91, 27, 173, 10, 22, 181, 185, 70,
              17, 98, 2, 113, 22, 103, 96, 235, 41, 207, 103, 178, 22, 121, 73, 4, 51, 51, 78, 25, 22, 96, 224, 49,
              226, 31, 95, 63, 22, 210, 19, 175, 105, 57, 42, 109, 22, 162, 225, 197, 116, 84, 252, 186, 22, 51, 206,
              100, 75, 211, 144, 212, 22, 12, 121, 17, 48, 163, 81, 44, 22, 30, 173, 101, 166, 176, 135, 175, 22, 84,
              8, 61, 37, 181, 203, 217, 22, 210, 125, 70, 146, 162, 125, 184, 22, 121, 167, 33, 170, 236, 14, 146,
              22, 249, 111, 146, 255, 99, 144, 229, 22, 180, 143, 55, 131, 20, 56, 182, 22, 134, 0, 214, 106, 10,
              150, 27, 22, 85, 218, 227, 245, 215, 49, 59, 22, 53, 12, 195, 29, 207, 108, 128, 22, 22, 162, 252, 68,
              45, 216, 75, 22, 71, 191, 185, 37, 250, 29, 111, 22, 46, 89, 187, 168, 174, 0, 36, 22, 103, 129, 75,
              231, 82, 197, 216, 22, 190, 15, 164, 250, 83, 191, 221, 22, 2, 106, 144, 17, 98, 32, 47, 22, 13, 123,
              129, 158, 204, 229, 255, 22, 34, 125, 210, 247, 225, 36, 126, 22, 99, 161, 32, 79, 83, 141, 57, 22,
              241, 100, 91, 188, 80, 96, 176, 22, 73, 23, 184, 216, 124, 89, 21, 22, 193, 53, 47, 32, 152, 43, 90,
              22, 124, 82, 28, 71, 222, 170, 28, 22, 36, 198, 163, 0, 48, 19, 38, 22, 73, 136, 195, 158, 205, 203,
              169, 22, 183, 154, 178, 123, 205, 21, 34, 22, 133, 16, 95, 23, 12, 54, 197, 22, 43, 13, 249, 46, 74,
              240, 198, 22, 160, 6, 37, 47, 212, 92, 53, 22, 140, 96, 83, 41, 105, 211, 195, 22, 184, 69, 115, 229,
              29, 199, 252, 22, 166, 12, 68, 15, 100, 180, 255, 22, 245, 5, 129, 164, 113, 31, 74, 22, 173, 246, 240,
              239, 204, 253, 76, 22, 226, 160, 23, 169, 163, 42, 125, 22, 71, 183, 244, 146, 11, 185, 104, 22, 38,
              145, 129, 28, 210, 186, 250, 22, 153, 54, 20, 11, 213, 38, 25, 22, 224, 234, 3, 236, 39, 52, 57, 22,
              228, 38, 84, 132, 139, 116, 34, 22, 28, 30, 189, 5, 211, 243, 192, 22, 190, 244, 70, 212, 160, 117,
              136, 22, 154, 194, 250, 127, 125, 230, 181, 22, 167, 135, 0, 102, 236, 215, 241, 22, 81, 19, 20, 209,
              161, 18, 150, 22, 167, 206, 63, 0, 15, 29, 230, 22, 20, 125, 132, 94, 26, 233, 222, 22, 37, 107, 53,
              222, 168, 42, 239, 22, 194, 181, 26, 68, 171, 173, 80, 22, 238, 194, 215, 99, 8, 138, 155, 22, 240,
              217, 155, 150, 38, 164, 57, 22, 126, 163, 166, 134, 145, 3, 157, 22, 244, 176, 24, 123, 179, 9, 106,
              22, 26, 239, 4, 82, 211, 130, 39, 22, 226, 189, 220, 176, 239, 44, 153, 22, 106, 172, 223, 119, 58,
              135, 49, 22, 64, 104, 41, 220, 29, 56, 185, 22, 80, 208, 200, 246, 238, 156, 2, 22, 76, 26, 223, 8, 59,
              63, 163, 22, 90, 185, 77, 251, 66, 28, 186, 22, 70, 119, 152, 233, 234, 247, 189, 22, 140, 144, 207,
              251, 209, 20, 229, 22, 202, 179, 5, 163, 65, 82, 162, 22, 147, 120, 170, 47, 252, 252, 100, 22, 59,
              168, 147, 154, 136, 212, 202, 22, 7, 185, 64, 224, 103, 14, 148, 22, 84, 104, 164, 174, 39, 69, 131,
              22, 114, 98, 110, 110, 211, 153, 73, 22, 150, 77, 13, 138, 128, 149, 228, 22, 216, 150, 125, 208, 124,
              244, 158, 22, 32, 181, 95, 46, 127, 245, 238, 22, 162, 80, 168, 99, 66, 231, 240, 22, 155, 57, 101,
              248, 161, 27, 73, 22, 180, 158, 220, 242, 27, 27, 138, 22, 65, 53, 236, 78, 251, 202, 255, 22, 132, 2,
              175, 82, 20, 43, 108, 22, 61, 221, 164, 163, 154, 72, 222, 22, 139, 168, 132, 60, 100, 219, 157, 22,
              162, 59, 69, 87, 254, 212, 121, 22, 203, 57, 228, 47, 216, 144, 133, 22, 33, 128, 204, 136, 154, 185,
              218, 22, 94, 2, 49, 131, 61, 76, 158, 22, 99, 13, 185, 139, 14, 62, 4, 22, 191, 21, 214, 72, 196, 109,
              146, 22, 37, 63, 214, 120, 179, 128, 129, 22, 126, 35, 130, 87, 255, 130, 147, 22, 196, 97, 45, 216,
              156, 53, 162, 22, 86, 210, 201, 31, 220, 70, 210, 22, 118, 30, 64, 149, 201, 162, 177, 22, 185, 71,
              246, 254, 2, 64, 139, 22, 176, 77, 3, 170, 59, 182, 229, 22, 187, 154, 32, 175, 170, 234, 247, 22, 123,
              110, 40, 145, 177, 239, 250, 22, 19, 212, 86, 238, 66, 73, 242, 22, 56, 171, 204, 221, 200, 174, 106,
              22, 253, 223, 94, 226, 184, 184, 100, 22, 245, 177, 36, 128, 97, 136, 213, 22, 146, 220, 16, 176, 120,
              25, 113, 22, 21, 180, 219, 94, 127, 120, 104, 22, 38, 8, 64, 223, 155, 72, 71, 22, 171, 255, 84, 190,
              154, 176, 60, 22, 221, 115, 135, 191, 177, 229, 180, 22, 234, 61, 75, 198, 101, 75, 158, 22, 153, 61,
              206, 235, 50, 124, 125, 22, 170, 78, 89, 195, 197, 170, 76, 22, 183, 10, 233, 149, 172, 92, 104, 22,
              190, 206, 27, 67, 47, 133, 27, 22, 238, 140, 94, 201, 125, 254, 52, 22, 124, 114, 30, 113, 222, 181,
              157, 22, 18, 223, 80, 140, 108, 71, 162, 22, 2, 112, 123, 176, 159, 153, 139, 22, 120, 75, 249, 184,
              213, 126, 50, 22, 78, 52, 177, 155, 34, 45, 172, 22, 33, 41, 168, 74, 68, 236, 166, 22, 207, 186, 93,
              80, 134, 249, 164, 22, 216, 137, 201, 107, 139, 185, 159, 22, 0, 124, 136, 117, 202, 23, 24, 22, 3,
              203, 130, 210, 220, 106, 118, 22, 8, 24, 124, 8, 42, 58, 225, 22, 185, 64, 0, 94, 187, 225, 178, 22,
              96, 176, 176, 96, 212, 181, 13, 22, 90, 157, 148, 242, 57, 248, 235, 22, 83, 133, 69, 208, 148, 75, 50,
              22, 191, 3, 57, 109, 3, 190, 224, 22, 97, 178, 137, 235, 3, 175, 34, 22, 81, 83, 222, 19, 120, 247,
              113, 22, 244, 86, 121, 65, 92, 206, 180, 22, 122, 171, 56, 83, 157, 96, 185, 22, 33, 215, 124, 209,
              244, 81, 246, 22, 251, 86, 161, 213, 28, 194, 106, 22, 252, 212, 181, 114, 226, 7, 225, 22, 45, 134,
              227, 154, 70, 240, 6, 22, 18, 123, 143, 236, 209, 61, 67, 22, 73, 47, 205, 177, 235, 40, 227, 22, 29,
              182, 221, 193, 192, 148, 190, 22, 77, 0, 12, 142, 120, 22, 232, 22, 223, 62, 238, 205, 100, 220, 23,
              22, 141, 112, 236, 131, 170, 64, 50, 22, 6, 95, 102, 57, 4, 205, 76, 22, 248, 27, 240, 12, 64, 82, 134,
              22, 7, 107, 99, 77, 135, 48, 33, 22, 159, 52, 93, 83, 43, 247, 180, 22, 238, 121, 158, 149, 43, 90, 30,
              22, 190, 82, 170, 158, 51, 131, 184, 22, 163, 20, 241, 17, 168, 104, 80, 22, 241, 66, 158, 40, 156, 5,
              66, 22, 16, 148, 126, 122, 167, 84, 120, 22, 187, 158, 250, 208, 78, 254, 17, 22, 20, 64, 144, 60, 144,
              83, 158, 22, 74, 69, 20, 53, 200, 208, 203, 22, 192, 55, 132, 144, 155, 177, 117, 22, 225, 178, 112,
              241, 76, 188, 195, 22, 116, 241, 26, 150, 89, 135, 96, 22, 102, 68, 124, 34, 26, 39, 35, 22, 21, 145,
              215, 28, 215, 244, 174, 22, 79, 164, 35, 161, 158, 60, 146, 22, 29, 255, 104, 250, 171, 146, 9, 22,
              134, 230, 205, 201, 162, 225, 172, 22, 27, 11, 139, 91, 10, 190, 218, 22, 159, 25, 37, 166, 158, 123,
              194, 22, 242, 54, 242, 144, 243, 92, 40, 22, 42, 11, 52, 186, 37, 95, 1, 22, 172, 87, 222, 11, 238, 19,
              123, 22, 209, 8, 22, 40, 74, 247, 17, 22, 185, 17, 223, 208, 233, 73, 66, 22, 187, 94, 107, 164, 129,
              241, 155, 22, 91, 145, 96, 87, 34, 44, 35, 22, 98, 175, 55, 159, 193, 116, 126, 22, 140, 72, 100, 142,
              109, 42, 21, 22, 187, 36, 56, 161, 221, 91, 170, 22, 231, 72, 134, 164, 218, 50, 116, 22, 136, 74, 198,
              160, 117, 98, 8, 22, 42, 145, 77, 237, 1, 90, 77, 22, 78, 167, 201, 27, 29, 232, 136, 22, 26, 93, 125,
              219, 103, 92, 243, 22, 201, 163, 193, 8, 62, 94, 73, 22, 50, 101, 90, 107, 44, 197, 120, 22, 32, 254,
              136, 246, 63, 65, 70, 22, 151, 41, 249, 199, 216, 247, 49, 22, 162, 232, 51, 78, 155, 222, 100, 22, 56,
              41, 176, 60, 134, 99, 47, 22, 67, 137, 97, 88, 131, 222, 77, 22, 56, 9, 159, 119, 218, 218, 34, 22, 22,
              113, 36, 222, 54, 27, 100, 22, 214, 34, 72, 115, 34, 196, 72, 22, 123, 226, 230, 16, 107, 113, 227, 22,
              172, 30, 229, 131, 88, 237, 52, 22, 169, 249, 149, 55, 65, 56, 5, 22, 176, 122, 123, 72, 224, 146, 82,
              22, 137, 108, 145, 6, 111, 90, 54, 22, 167, 254, 176, 189, 202, 144, 59, 22, 173, 187, 241, 141, 112,
              125, 61, 22, 157, 220, 12, 134, 216, 228, 11, 22, 73, 49, 104, 165, 226, 255, 132, 22, 251, 72, 30,
              163, 81, 122, 170, 22, 187, 53, 144, 227, 35, 18, 229, 22, 109, 231, 148, 66, 54, 67, 127, 22, 32, 218,
              67, 244, 108, 70, 231, 22, 34, 174, 114, 216, 103, 78, 115, 22, 34, 177, 145, 15, 114, 86, 63, 22, 83,
              193, 119, 78, 88, 2, 191, 22, 18, 51, 229, 139, 179, 143, 255, 22, 254, 34, 214, 103, 152, 187, 202,
              22, 150, 246, 153, 14, 192, 196, 171, 22, 255, 3, 39, 103, 182, 212, 205, 22, 175, 233, 0, 202, 195,
              37, 198, 22, 170, 141, 11, 146, 126, 164, 115, 22, 57, 143, 11, 30, 163, 66, 165, 22, 233, 109, 251,
              75, 185, 214, 30, 22, 179, 119, 55, 200, 162, 164, 151, 22, 227, 8, 132, 162, 210, 22, 251, 22, 176,
              131, 135, 181, 109, 130, 243, 22, 135, 91, 235, 9, 151, 96, 43, 22, 149, 141, 178, 103, 137, 128, 66,
              22, 3, 31, 209, 209, 81, 94, 3, 22, 120, 33, 31, 237, 30, 121, 207, 22, 117, 176, 83, 145, 17, 36, 155,
              22, 223, 117, 69, 16, 68, 124, 164, 22, 130, 117, 109, 211, 91, 190, 142, 22, 237, 44, 102, 128, 253,
              152, 199, 22, 249, 71, 254, 78, 29, 81, 187, 22, 170, 6, 238, 15, 35, 85, 112, 22, 30, 59, 213, 73,
              100, 212, 149, 22, 60, 220, 113, 68, 139, 82, 240, 22, 192, 17, 210, 189, 228, 22, 28, 22, 113, 28,
              178, 221, 14, 230, 114, 22, 173, 110, 2, 13, 56, 8, 189, 22, 151, 98, 103, 6, 127, 19, 116, 22, 52, 4,
              122, 114, 215, 177, 139, 22, 244, 225, 181, 64, 173, 10, 248, 22, 246, 63, 2, 28, 8, 34, 64, 22, 211,
              171, 250, 105, 138, 74, 151, 22, 238, 29, 59, 122, 197, 72, 201, 22, 75, 28, 41, 157, 229, 26, 172, 22,
              242, 91, 39, 127, 41, 50, 251, 22, 36, 18, 115, 178, 167, 112, 224, 22, 193, 5, 199, 197, 92, 80, 189,
              22, 9, 47, 24, 185, 136, 245, 119, 22, 165, 48, 86, 161, 245, 112, 61, 22, 0, 121, 155, 52, 199, 3, 46,
              22, 41, 232, 160, 48, 85, 106, 128, 22, 216, 152, 224, 222, 84, 253, 3, 22, 12, 225, 35, 43, 0, 93, 85,
              22, 95, 116, 201, 62, 112, 210, 187, 22, 14, 152, 24, 137, 238, 228, 94, 22, 6, 177, 202, 207, 137,
              251, 175, 22, 253, 206, 147, 38, 122, 51, 164, 22, 116, 174, 96, 194, 86, 54, 207, 22, 130, 62, 132,
              149, 232, 109, 135, 22, 81, 109, 153, 206, 38, 62, 73, 22, 153, 81, 246, 36, 83, 48, 162, 22, 81, 149,
              31, 50, 97, 182, 158, 22, 41, 22, 36, 52, 186, 1, 93, 22, 168, 73, 95, 67, 126, 149, 169, 22, 155, 247,
              164, 52, 49, 147, 230, 22, 208, 133, 155, 177, 98, 200, 245, 22, 225, 48, 84, 39, 155, 70, 43, 22, 159,
              91, 139, 79, 152, 127, 237, 22, 130, 127, 241, 45, 245, 172, 171, 22, 40, 70, 13, 239, 15, 112, 59, 22,
              191, 85, 69, 149, 62, 179, 75, 22, 26, 61, 128, 208, 132, 98, 170, 22, 239, 139, 207, 133, 234, 29,
              131, 22, 180, 11, 104, 233, 113, 64, 49, 22, 42, 132, 117, 69, 242, 247, 37, 22, 62, 163, 1, 104, 82,
              35, 25, 22, 158, 54, 6, 122, 234, 199, 122, 22, 72, 190, 81, 24, 22, 118, 93, 22, 234, 186, 218, 191,
              248, 33, 88, 22, 14, 30, 131, 182, 232, 36, 215, 22, 218, 210, 122, 63, 1, 160, 88, 22, 177, 180, 173,
              196, 95, 154, 48, 22, 117, 19, 166, 34, 166, 233, 41, 22, 60, 207, 232, 228, 152, 0, 23, 22, 52, 44,
              210, 146, 89, 187, 181, 22, 61, 16, 173, 215, 190, 178, 178, 22, 29, 130, 35, 9, 201, 35, 248, 22, 54,
              202, 66, 3, 173, 157, 85, 22, 201, 253, 213, 126, 190, 222, 189, 22, 62, 32, 6, 62, 254, 28, 1, 22, 18,
              53, 211, 95, 240, 84, 204, 22, 9, 200, 185, 36, 76, 242, 180, 22, 183, 109, 222, 116, 168, 144, 47, 22,
              17, 118, 15, 52, 209, 144, 192, 22, 108, 61, 81, 88, 39, 110, 123, 22, 177, 121, 36, 16, 41, 52, 30,
              22, 77, 194, 50, 138, 13, 14, 94, 22, 196, 93, 145, 17, 172, 79, 221, 22, 213, 188, 190, 162, 34, 147,
              97, 22, 83, 22, 147, 52, 171, 155, 7, 22, 32, 11, 184, 234, 135, 254, 20, 22, 139, 115, 228, 174, 149,
              123, 161, 22, 76, 222, 109, 223, 142, 254, 239, 22, 225, 60, 211, 156, 208, 198, 172, 22, 75, 98, 24,
              73, 134, 227, 16, 22, 83, 163, 224, 78, 75, 0, 196, 22, 100, 129, 106, 0, 41, 218, 63, 22, 65, 202,
              188, 115, 173, 228, 152, 22, 49, 39, 142, 2, 242, 70, 57, 22, 54, 116, 154, 123, 184, 77, 114, 22, 243,
              37, 81, 104, 109, 113, 156, 22, 196, 77, 195, 162, 145, 210, 51, 22, 99, 177, 84, 227, 255, 72, 72, 22,
              234, 165, 135, 148, 83, 148, 116, 22, 72, 226, 132, 209, 216, 57, 43, 22, 210, 205, 9, 139, 78, 241,
              50, 22, 96, 137, 38, 124, 11, 100, 148, 22, 88, 171, 205, 46, 169, 189, 58, 22, 21, 194, 141, 146, 201,
              115, 34, 22, 107, 146, 7, 18, 23, 163, 228, 22, 154, 68, 210, 84, 85, 223, 28, 22, 17, 12, 236, 13,
              237, 42, 147, 22, 230, 233, 241, 182, 148, 250, 232, 22, 122, 140, 200, 208, 207, 176, 33, 22, 195, 76,
              65, 133, 208, 49, 168, 22, 174, 155, 166, 81, 28, 150, 255, 22, 200, 237, 153, 207, 135, 79, 34, 22,
              165, 177, 157, 236, 35, 171, 45, 22, 207, 245, 201, 71, 184, 247, 101, 22, 201, 84, 26, 172, 33, 207,
              162, 22, 11, 200, 192, 53, 77, 50, 71, 22, 144, 152, 70, 81, 176, 30, 118, 22, 255, 6, 214, 184, 10,
              162, 136, 22, 191, 141, 130, 242, 51, 155, 120, 22, 103, 53, 6, 3, 51, 172, 254, 22, 161, 123, 115, 9,
              180, 113, 16, 22, 85, 37, 100, 182, 255, 91, 184, 22, 97, 168, 180, 63, 75, 252, 2, 22, 63, 147, 151,
              148, 190, 236, 129, 22, 25, 185, 245, 53, 128, 161, 144, 22, 198, 55, 191, 184, 211, 9, 93, 22, 175,
              85, 44, 205, 22, 235, 207, 22, 24, 184, 34, 252, 167, 202, 166, 22, 105, 85, 206, 158, 173, 57, 6, 22,
              186, 103, 163, 40, 180, 3, 30, 22, 58, 215, 13, 36, 146, 26, 212, 22, 170, 141, 137, 105, 225, 101,
              156, 22, 247, 150, 185, 220, 129, 160, 20, 22, 23, 208, 184, 101, 71, 89, 168, 22, 228, 166, 75, 137,
              187, 221, 231, 22, 130, 113, 35, 219, 241, 74, 138, 22, 245, 7, 190, 198, 45, 227, 99, 22, 239, 227,
              12, 254, 91, 124, 124, 22, 14, 33, 97, 135, 108, 46, 167, 22, 148, 201, 211, 207, 242, 140, 139, 22,
              150, 180, 41, 61, 1, 243, 137, 22, 236, 95, 157, 68, 144, 84, 141, 22, 25, 115, 74, 160, 76, 24, 52,
              22, 53, 177, 137, 239, 66, 18, 142, 22, 129, 82, 39, 61, 219, 241, 240, 22, 102, 211, 80, 118, 173, 50,
              209, 22, 8, 2, 78, 55, 177, 151, 234, 22, 169, 97, 101, 207, 81, 232, 12, 22, 138, 1, 13, 64, 0, 0, 0,
              21, 0, 2, 0, 43, 159, 142, 130, 22, 225, 94, 128, 215, 151, 50, 175, 22, 126, 2, 165, 154, 93, 78, 177,
              22, 34, 17, 111, 160, 44, 63, 231, 22, 52, 134, 51, 82, 28, 95, 16, 22, 79, 94, 183, 208, 39, 206, 85,
              22, 36, 233, 125, 124, 138, 157, 179, 22, 106, 162, 167, 77, 45, 143, 67, 22, 215, 159, 241, 233, 207,
              198, 26, 22, 31, 154, 2, 35, 29, 133, 105, 22, 41, 189, 151, 222, 209, 204, 39, 22, 160, 83, 1, 33, 4,
              108, 223, 22, 94, 95, 60, 170, 171, 191, 250, 22, 13, 216, 129, 217, 188, 178, 161, 22, 96, 229, 188,
              32, 226, 190, 27, 22, 3, 69, 15, 143, 147, 236, 49, 22, 71, 151, 133, 110, 80, 8, 35, 22, 254, 45, 251,
              156, 84, 193, 126, 22, 21, 78, 90, 102, 247, 123, 249, 22, 126, 221, 231, 119, 173, 69, 100, 22, 88,
              251, 229, 112, 118, 110, 7, 22, 78, 170, 42, 43, 250, 218, 139, 22, 223, 162, 136, 2, 157, 122, 71, 22,
              204, 122, 223, 211, 243, 180, 183, 22, 254, 222, 140, 34, 59, 38, 15, 22, 72, 252, 181, 213, 47, 115,
              209, 22, 199, 200, 188, 15, 97, 28, 47, 22, 76, 184, 193, 97, 202, 19, 171, 22, 12, 35, 35, 83, 241,
              184, 164, 22, 6, 166, 231, 178, 188, 169, 157, 22, 201, 201, 147, 149, 238, 79, 154, 22, 71, 11, 15,
              155, 23, 196, 97, 22, 43, 192, 84, 37, 65, 233, 175, 22, 8, 246, 76, 84, 145, 119, 250, 22, 47, 10,
              130, 239, 19, 65, 154, 22, 67, 162, 62, 219, 176, 165, 193, 22, 77, 227, 69, 20, 76, 255, 85, 22, 60,
              153, 108, 87, 198, 51, 173, 22, 9, 181, 97, 6, 52, 216, 12, 22, 176, 0, 179, 239, 0, 171, 167, 22, 141,
              116, 85, 84, 162, 178, 152, 22, 132, 92, 130, 165, 31, 201, 241, 22, 46, 131, 183, 239, 126, 193, 75,
              22, 234, 97, 209, 31, 253, 22, 39, 22, 2, 234, 207, 136, 100, 226, 98, 22, 100, 227, 93, 173, 137, 119,
              249, 22, 3, 65, 20, 48, 136, 224, 59, 22, 152, 18, 160, 197, 95, 19, 107, 22, 90, 200, 221, 126, 78,
              72, 14, 22, 89, 75, 75, 14, 49, 151, 224, 22, 121, 232, 53, 160, 36, 47, 106, 22, 189, 45, 138, 144,
              48, 246, 77, 22, 85, 204, 113, 244, 54, 79, 96, 22, 58, 120, 79, 5, 207, 209, 73, 22, 65, 255, 124,
              144, 94, 78, 231, 22, 45, 63, 202, 144, 145, 180, 26, 22, 64, 26, 92, 190, 110, 56, 222, 22, 70, 8, 7,
              84, 104, 18, 182, 22, 146, 197, 188, 136, 8, 177, 154, 22, 229, 144, 126, 109, 54, 41, 22, 22, 224, 92,
              136, 43, 23, 110, 198, 22, 213, 179, 153, 200, 166, 206, 127, 22, 17, 239, 88, 211, 202, 221, 165, 22,
              163, 92, 188, 225, 124, 143, 69, 22, 97, 183, 106, 109, 81, 40, 230, 22, 34, 93, 211, 241, 180, 142,
              224, 22, 68, 188, 204, 79, 117, 249, 31, 22, 209, 22, 109, 209, 145, 182, 217, 22, 25, 164, 238, 111,
              114, 248, 161, 22, 98, 17, 7, 97, 68, 158, 217, 22, 160, 5, 84, 196, 117, 225, 163, 22, 152, 204, 113,
              113, 85, 96, 146, 22, 186, 195, 71, 233, 239, 209, 92, 22, 211, 71, 223, 174, 154, 213, 188, 22, 113,
              0, 0, 0, 0, 0, 0, 21, 0, 16, 0, 182, 170, 115, 217, 22, 84, 134, 207, 216, 4, 144, 175, 22, 157, 55,
              124, 54, 42, 248, 230, 22, 124, 82, 79, 88, 132, 8, 67, 22, 22, 49, 17, 65, 86, 233, 83, 22, 10, 145,
              24, 51, 241, 86, 217, 22, 180, 15, 26, 155, 36, 196, 161, 22, 18, 148, 5, 226, 85, 50, 204, 22, 146,
              148, 135, 242, 41, 81, 163, 22, 172, 232, 161, 104, 31, 112, 102, 22, 131, 162, 130, 217, 31, 40, 37,
              22, 214, 63, 222, 72, 224, 160, 141, 22, 253, 199, 170, 45, 48, 98, 153, 22, 170, 87, 109, 171, 126,
              195, 254, 22, 48, 23, 222, 34, 201, 232, 58, 22, 87, 4, 20, 7, 135, 43, 26, 22, 195, 16, 61, 46, 220,
              189, 137, 22, 214, 166, 36, 168, 49, 52, 91, 22, 99, 218, 63, 225, 104, 250, 224, 22, 42, 119, 57, 218,
              65, 245, 162, 22, 144, 232, 109, 72, 129, 74, 244, 22, 150, 214, 29, 211, 177, 135, 197, 22, 6, 138,
              251, 37, 253, 28, 189, 22, 50, 186, 14, 104, 42, 217, 155, 22, 125, 4, 129, 206, 40, 236, 151, 22, 192,
              114, 103, 51, 62, 235, 7, 22, 124, 219, 90, 161, 201, 159, 73, 22, 144, 43, 30, 238, 39, 46, 86, 22,
              177, 95, 226, 244, 170, 35, 212, 22, 139, 215, 113, 48, 159, 244, 123, 22, 243, 42, 228, 23, 14, 132,
              25, 22, 156, 229, 179, 44, 83, 254, 95, 22, 197, 101, 23, 45, 11, 255, 2, 22, 89, 202, 81, 73, 191,
              155, 191, 22, 106, 0, 85, 14, 180, 92, 171, 22, 170, 250, 180, 142, 19, 174, 131, 22, 22, 232, 209, 71,
              16, 5, 46, 22, 236, 255, 41, 65, 253, 132, 14, 22, 120, 7, 190, 113, 162, 98, 32, 22, 99, 94, 79, 184,
              77, 196, 148, 22, 102, 39, 13, 187, 15, 93, 66, 22, 1, 249, 100, 112, 39, 73, 205, 22, 176, 110, 179,
              106, 140, 122, 49, 22, 159, 186, 248, 206, 82, 123, 57, 22, 139, 247, 254, 171, 165, 13, 98, 22, 73,
              122, 231, 248, 191, 5, 133, 22, 255, 150, 216, 1, 183, 223, 219, 22, 91, 184, 112, 150, 100, 167, 87,
              22, 12, 88, 248, 114, 17, 192, 228, 22, 203, 72, 148, 144, 232, 191, 12, 22, 94, 94, 95, 83, 237, 55,
              27, 22, 175, 123, 21, 75, 251, 78, 173, 22, 55, 141, 109, 228, 116, 204, 228, 22, 6, 202, 235, 107,
              108, 91, 168, 22, 192, 0, 75, 57, 99, 25, 22, 22, 78, 54, 24, 126, 7, 172, 82, 22, 15, 201, 182, 131,
              44, 13, 66, 22, 188, 1, 255, 87, 177, 94, 69, 22, 164, 240, 24, 196, 246, 107, 141, 22, 30, 228, 203,
              6, 116, 177, 47, 22, 17, 148, 131, 118, 9, 155, 141, 22, 151, 55, 173, 182, 18, 170, 220, 22, 93, 3,
              93, 29, 178, 217, 185, 22, 160, 169, 36, 94, 166, 112, 93, 22, 105, 15, 103, 89, 248, 35, 141, 22, 193,
              61, 96, 149, 183, 129, 83, 22, 225, 92, 77, 197, 64, 106, 19, 22, 1, 82, 60, 100, 32, 149, 9, 22, 1,
              177, 31, 139, 101, 67, 220, 22, 60, 34, 118, 82, 168, 36, 219, 22, 213, 220, 40, 60, 235, 128, 1, 22,
              129, 135, 222, 224, 176, 241, 225, 22, 193, 245, 53, 61, 218, 17, 20, 22, 50, 133, 76, 151, 189, 235,
              82, 22, 86, 150, 227, 206, 246, 167, 214, 22, 153, 57, 56, 158, 85, 98, 214, 22, 254, 53, 202, 136, 76,
              104, 155, 22, 198, 190, 227, 145, 1, 99, 153, 22, 244, 154, 31, 187, 180, 211, 190, 22, 10, 217, 228,
              153, 97, 175, 85, 22, 231, 29, 64, 87, 46, 116, 1, 22, 14, 51, 27, 124, 52, 36, 154, 22, 0, 203, 239,
              15, 121, 138, 65, 22, 17, 35, 209, 250, 146, 85, 125, 22, 9, 210, 13, 162, 155, 96, 135, 22, 230, 14,
              213, 206, 199, 198, 80, 22, 155, 43, 61, 145, 244, 204, 116, 22, 12, 124, 56, 141, 35, 118, 36, 22,
              220, 27, 137, 85, 103, 121, 135, 22, 209, 184, 253, 253, 108, 245, 239, 22, 40, 209, 148, 235, 200,
              206, 61, 22, 133, 168, 131, 42, 133, 117, 218, 22, 12, 3, 165, 77, 65, 84, 89, 22, 103, 191, 236, 157,
              76, 164, 70, 22, 150, 65, 51, 74, 180, 216, 121, 22, 126, 53, 74, 217, 21, 121, 39, 22, 25, 43, 69,
              196, 99, 192, 108, 22, 74, 216, 100, 121, 246, 201, 242, 22, 232, 233, 60, 128, 149, 85, 60, 22, 10,
              249, 166, 251, 24, 63, 27, 22, 86, 108, 226, 126, 1, 15, 235, 22, 243, 21, 63, 60, 245, 146, 174, 22,
              46, 192, 145, 237, 100, 187, 248, 22, 87, 190, 26, 1, 127, 169, 135, 22, 184, 19, 168, 4, 18, 118, 218,
              22, 104, 107, 50, 250, 163, 83, 226, 22, 139, 81, 154, 44, 187, 9, 127, 22, 165, 201, 181, 243, 92,
              146, 217, 22, 98, 15, 2, 244, 229, 106, 189, 22, 146, 199, 28, 67, 231, 31, 237, 22, 42, 65, 27, 139,
              246, 154, 30, 22, 192, 62, 22, 21, 10, 3, 255, 22, 181, 112, 244, 89, 41, 249, 173, 22, 184, 144, 59,
              30, 78, 162, 171, 22, 50, 200, 193, 91, 222, 126, 119, 22, 1, 176, 104, 59, 216, 29, 142, 22, 45, 21,
              106, 79, 206, 77, 253, 22, 165, 39, 80, 133, 173, 220, 170, 22, 12, 241, 194, 97, 153, 200, 76, 22,
              174, 30, 238, 237, 187, 121, 95, 22, 239, 211, 12, 138, 95, 225, 91, 22, 247, 246, 66, 9, 248, 175, 97,
              22, 5, 18, 196, 83, 197, 52, 61, 22, 168, 40, 189, 135, 236, 84, 124, 22, 71, 226, 74, 129, 254, 82,
              168, 22, 172, 253, 81, 41, 163, 239, 177, 22, 201, 127, 217, 250, 249, 138, 87, 22, 228, 245, 51, 135,
              47, 190, 159, 22, 86, 236, 152, 247, 96, 114, 6, 22, 148, 227, 60, 155, 5, 82, 74, 22, 72, 33, 253, 16,
              49, 161, 112, 22, 95, 37, 206, 224, 3, 179, 9, 22, 200, 43, 193, 132, 10, 245, 19, 22, 166, 52, 71, 49,
              112, 85, 120, 22, 18, 159, 74, 206, 161, 5, 240, 22, 127, 244, 11, 103, 117, 199, 119, 22, 140, 168,
              87, 199, 7, 39, 166, 22, 242, 107, 167, 174, 132, 217, 179, 22, 215, 172, 87, 106, 38, 194, 165, 22,
              38, 235, 40, 5, 181, 169, 173, 22, 227, 99, 124, 182, 7, 65, 202, 22, 159, 252, 65, 51, 96, 245, 147,
              22, 237, 112, 167, 73, 199, 110, 193, 22, 59, 173, 101, 158, 127, 149, 186, 22, 213, 68, 124, 68, 230,
              51, 239, 22, 135, 25, 173, 64, 35, 205, 79, 22, 248, 81, 157, 131, 90, 35, 57, 22, 253, 6, 182, 156,
              243, 113, 27, 22, 213, 244, 9, 14, 231, 104, 236, 22, 198, 36, 143, 6, 17, 125, 20, 22, 90, 229, 139,
              126, 38, 106, 214, 22, 177, 237, 185, 149, 29, 51, 223, 22, 135, 216, 199, 159, 240, 63, 173, 22, 235,
              238, 242, 131, 167, 38, 138, 22, 123, 130, 190, 241, 70, 57, 243, 22, 188, 109, 209, 175, 50, 6, 4, 22,
              192, 113, 221, 63, 99, 64, 224, 22, 128, 247, 114, 203, 45, 200, 60, 22, 193, 149, 15, 194, 208, 229,
              79, 22, 69, 178, 34, 18, 145, 45, 37, 22, 168, 112, 172, 39, 230, 18, 236, 22, 18, 28, 126, 208, 52,
              204, 185, 22, 36, 20, 29, 8, 159, 184, 215, 22, 126, 242, 75, 0, 128, 105, 54, 22, 178, 34, 180, 167,
              30, 235, 125, 22, 198, 239, 39, 76, 85, 170, 183, 22, 165, 174, 117, 195, 127, 237, 173, 22, 136, 49,
              159, 76, 73, 161, 48, 22, 218, 142, 134, 121, 127, 1, 238, 22, 17, 150, 197, 82, 246, 103, 164, 22,
              202, 205, 186, 230, 165, 130, 87, 22, 12, 130, 40, 252, 165, 44, 106, 22, 150, 200, 170, 102, 177, 87,
              166, 22, 147, 148, 145, 179, 147, 169, 174, 22, 141, 152, 114, 124, 160, 121, 58, 22, 40, 11, 113, 167,
              97, 217, 55, 22, 148, 147, 76, 230, 144, 130, 174, 22, 193, 221, 102, 253, 97, 102, 239, 22, 172, 167,
              132, 172, 89, 8, 1, 22, 30, 161, 93, 170, 5, 180, 166, 22, 112, 232, 125, 105, 215, 238, 3, 22, 15, 87,
              112, 5, 97, 207, 51, 22, 119, 174, 64, 44, 251, 219, 185, 22, 98, 59, 140, 200, 135, 0, 165, 22, 100,
              134, 155, 251, 33, 236, 181, 22, 146, 68, 83, 177, 127, 7, 141, 22, 12, 243, 82, 98, 41, 44, 96, 22,
              239, 37, 152, 53, 150, 82, 45, 22, 111, 134, 160, 127, 82, 182, 15, 22, 246, 236, 58, 63, 59, 237, 84,
              22, 12, 179, 74, 92, 201, 76, 216, 22, 219, 200, 26, 150, 95, 46, 57, 22, 235, 231, 97, 218, 49, 161,
              153, 22, 20, 74, 60, 115, 59, 135, 83, 22, 117, 131, 57, 143, 210, 203, 22, 22, 231, 194, 107, 146,
              159, 176, 142, 22, 156, 114, 213, 20, 154, 135, 75, 22, 47, 218, 141, 37, 211, 45, 29, 22, 39, 90, 106,
              229, 228, 47, 179, 22, 121, 61, 57, 182, 27, 83, 171, 22, 53, 217, 92, 106, 57, 191, 145, 22, 29, 217,
              81, 148, 111, 74, 142, 22, 244, 153, 135, 213, 34, 10, 50, 22, 64, 24, 23, 61, 253, 1, 126, 22, 101,
              201, 111, 62, 223, 48, 97, 22, 143, 70, 123, 78, 61, 147, 181, 22, 18, 239, 209, 43, 65, 235, 130, 22,
              155, 204, 154, 111, 68, 221, 153, 22, 220, 248, 76, 205, 45, 175, 218, 22, 215, 91, 43, 121, 131, 176,
              98, 22, 241, 38, 105, 214, 168, 130, 209, 22, 123, 83, 124, 168, 128, 136, 29, 22, 43, 71, 223, 152,
              54, 84, 34, 22, 134, 182, 53, 183, 35, 6, 141, 22, 147, 254, 86, 54, 76, 178, 158, 22, 138, 80, 111,
              86, 61, 125, 108, 22, 170, 100, 161, 100, 195, 144, 49, 22, 2, 174, 70, 246, 139, 149, 33, 22, 253,
              115, 82, 196, 126, 209, 168, 22, 219, 38, 19, 154, 164, 17, 210, 22, 144, 48, 148, 70, 217, 11, 184,
              22, 179, 139, 119, 188, 95, 28, 48, 22, 129, 87, 101, 199, 49, 156, 49, 22, 17, 200, 14, 77, 30, 96,
              141, 22, 177, 170, 214, 152, 192, 15, 212, 22, 105, 162, 192, 119, 54, 44, 85, 22, 163, 179, 217, 142,
              91, 88, 130, 22, 76, 183, 175, 193, 196, 228, 140, 22, 91, 128, 153, 105, 197, 246, 53, 22, 202, 193,
              134, 14, 96, 228, 146, 22, 36, 21, 247, 74, 22, 160, 108, 22, 146, 67, 57, 46, 176, 180, 214, 22, 28,
              188, 82, 82, 112, 15, 216, 22, 201, 255, 44, 40, 213, 122, 50, 22, 131, 6, 1, 62, 255, 5, 6, 22, 36,
              70, 231, 222, 236, 128, 178, 22, 106, 64, 6, 240, 222, 8, 74, 22, 235, 66, 195, 113, 245, 89, 200, 22,
              13, 211, 158, 89, 252, 138, 83, 22, 225, 141, 122, 167, 40, 203, 176, 22, 46, 156, 200, 113, 188, 227,
              45, 22, 11, 77, 223, 77, 99, 72, 191, 22, 116, 139, 89, 110, 12, 233, 80, 22, 163, 81, 1, 129, 6, 244,
              166, 22, 217, 252, 142, 142, 194, 195, 111, 22, 29, 54, 214, 180, 135, 172, 117, 22, 58, 162, 56, 46,
              83, 113, 166, 22, 22, 182, 41, 127, 58, 72, 67, 22, 105, 141, 121, 151, 36, 203, 29, 22, 13, 103, 189,
              77, 134, 82, 101, 22, 168, 147, 25, 47, 177, 228, 25, 22, 228, 239, 100, 27, 52, 165, 209, 22, 146, 41,
              108, 252, 203, 72, 41, 22, 42, 9, 5, 46, 11, 164, 25, 22, 215, 255, 202, 238, 165, 84, 152, 22, 125,
              206, 165, 100, 44, 159, 136, 22, 123, 1, 232, 148, 247, 135, 222, 22, 203, 88, 45, 195, 88, 137, 217,
              22, 1, 220, 105, 198, 245, 126, 161, 22, 86, 53, 7, 1, 161, 13, 58, 22, 21, 2, 53, 55, 43, 225, 155,
              22, 166, 109, 99, 110, 101, 154, 36, 22, 135, 250, 128, 240, 76, 247, 88, 22, 167, 219, 15, 67, 103,
              50, 240, 22, 194, 251, 191, 11, 137, 162, 237, 22, 215, 239, 71, 234, 47, 130, 174, 22, 191, 168, 230,
              3, 3, 239, 229, 22, 44, 72, 49, 130, 124, 94, 68, 22, 106, 73, 164, 148, 33, 131, 215, 22, 120, 109,
              108, 26, 254, 191, 206, 22, 84, 92, 75, 100, 141, 171, 37, 22, 183, 160, 125, 247, 152, 120, 32, 22,
              30, 205, 72, 176, 157, 60, 98, 22, 94, 195, 176, 122, 120, 83, 169, 22, 111, 185, 166, 20, 198, 2, 145,
              22, 168, 253, 119, 221, 225, 7, 228, 22, 1, 250, 57, 178, 205, 208, 255, 22, 36, 3, 6, 216, 145, 147,
              23, 22, 85, 186, 182, 22, 11, 139, 39, 22, 63, 204, 81, 118, 186, 61, 132, 22, 143, 81, 176, 167, 129,
              238, 216, 22, 24, 201, 230, 77, 91, 91, 194, 22, 95, 12, 13, 176, 99, 148, 181, 22, 49, 172, 246, 226,
              231, 38, 135, 22, 31, 200, 228, 236, 198, 42, 101, 22, 83, 59, 133, 116, 30, 251, 254, 22, 51, 37, 134,
              246, 251, 78, 100, 22, 230, 85, 87, 198, 77, 140, 154, 22, 16, 6, 130, 71, 139, 69, 102, 22, 236, 162,
              229, 33, 135, 87, 94, 22, 164, 93, 43, 22, 244, 103, 138, 22, 226, 255, 212, 247, 112, 92, 102, 22,
              122, 165, 62, 165, 170, 209, 95, 22, 173, 36, 50, 169, 242, 43, 219, 22, 97, 163, 2, 170, 250, 135,
              160, 22, 212, 20, 57, 117, 189, 251, 245, 22, 228, 100, 41, 15, 131, 67, 117, 22, 225, 91, 180, 124,
              214, 44, 228, 22, 156, 243, 206, 191, 54, 250, 83, 22, 252, 9, 161, 177, 120, 143, 239, 22, 204, 158,
              81, 221, 143, 182, 191, 22, 56, 241, 199, 247, 160, 151, 107, 22, 109, 111, 95, 113, 115, 175, 77, 22,
              2, 197, 102, 81, 92, 118, 51, 22, 239, 160, 7, 121, 231, 49, 99, 22, 183, 145, 4, 46, 141, 153, 139,
              22, 213, 92, 151, 190, 96, 183, 236, 22, 176, 222, 70, 74, 31, 146, 47, 22, 53, 9, 22, 34, 167, 131,
              62, 22, 169, 150, 204, 168, 4, 137, 163, 22, 230, 121, 45, 167, 193, 254, 69, 22, 194, 50, 53, 38, 83,
              19, 211, 22, 192, 145, 31, 252, 253, 241, 114, 22, 148, 50, 160, 108, 199, 68, 133, 22, 151, 127, 127,
              147, 62, 38, 227, 22, 208, 114, 103, 169, 67, 191, 15, 22, 62, 12, 228, 78, 35, 155, 36, 22, 252, 219,
              241, 4, 74, 236, 183, 22, 25, 58, 16, 77, 11, 142, 239, 22, 115, 77, 120, 186, 109, 92, 226, 22, 64,
              117, 56, 28, 205, 88, 76, 22, 122, 212, 16, 214, 53, 225, 208, 22, 235, 191, 29, 211, 18, 240, 42, 22,
              69, 196, 18, 46, 233, 16, 68, 22, 149, 229, 17, 204, 76, 140, 120, 22, 69, 134, 95, 184, 82, 197, 141,
              22, 117, 219, 236, 254, 145, 82, 86, 22, 113, 132, 161, 62, 154, 142, 248, 22, 245, 179, 130, 215, 89,
              224, 97, 22, 109, 144, 252, 34, 35, 26, 255, 22, 78, 204, 193, 209, 175, 21, 89, 22, 29, 239, 91, 204,
              182, 192, 19, 22, 249, 232, 255, 3, 174, 252, 26, 22, 85, 129, 107, 236, 8, 0, 137, 22, 5, 10, 20, 175,
              182, 75, 178, 22, 128, 232, 221, 133, 90, 216, 159, 22, 196, 87, 197, 30, 177, 244, 73, 22, 12, 221,
              35, 177, 155, 156, 155, 22, 63, 196, 245, 214, 23, 194, 221, 22, 15, 126, 63, 68, 254, 92, 146, 22,
              195, 242, 216, 62, 184, 10, 103, 22, 4, 14, 28, 75, 165, 69, 143, 22, 60, 250, 49, 57, 236, 120, 103,
              22, 179, 127, 111, 26, 3, 109, 108, 22, 224, 245, 4, 213, 21, 188, 93, 22, 47, 188, 125, 13, 2, 132,
              253, 22, 219, 205, 35, 59, 162, 64, 128, 22, 108, 214, 209, 7, 183, 150, 239, 22, 89, 78, 223, 224, 61,
              194, 51, 22, 246, 106, 254, 11, 21, 52, 19, 22, 201, 140, 186, 180, 197, 132, 171, 22, 204, 25, 242,
              240, 108, 8, 57, 22, 77, 64, 185, 0, 200, 205, 193, 22, 149, 223, 69, 192, 192, 27, 228, 22, 242, 166,
              168, 104, 156, 91, 225, 22, 254, 11, 99, 184, 89, 144, 4, 22, 151, 105, 148, 77, 250, 222, 156, 22,
              196, 213, 150, 28, 147, 130, 103, 22, 73, 74, 121, 171, 133, 221, 45, 22, 167, 106, 77, 252, 60, 181,
              172, 22, 245, 139, 200, 214, 64, 82, 25, 22, 103, 100, 81, 161, 112, 192, 147, 22, 52, 253, 23, 158,
              169, 191, 94, 22, 64, 204, 241, 82, 58, 77, 80, 22, 147, 201, 157, 106, 34, 147, 133, 22, 214, 127, 17,
              11, 66, 144, 183, 22, 153, 59, 132, 74, 18, 137, 255, 22, 243, 197, 19, 40, 116, 232, 8, 22, 240, 207,
              61, 117, 92, 126, 209, 22, 107, 7, 232, 216, 48, 165, 163, 22, 170, 110, 229, 32, 200, 175, 177, 22,
              247, 159, 233, 161, 187, 132, 242, 22, 169, 174, 204, 163, 98, 173, 176, 22, 56, 219, 216, 33, 154,
              123, 96, 22, 20, 179, 21, 241, 253, 71, 164, 22, 208, 30, 119, 127, 143, 249, 231, 22, 74, 33, 191, 84,
              134, 103, 191, 22, 161, 204, 10, 23, 81, 72, 150, 22, 118, 169, 100, 126, 166, 204, 137, 22, 117, 131,
              181, 78, 251, 190, 180, 22, 11, 0, 205, 255, 36, 245, 142, 22, 135, 133, 227, 43, 253, 87, 215, 22,
              235, 225, 219, 121, 17, 152, 108, 22, 38, 170, 128, 193, 114, 162, 119, 22, 238, 150, 135, 236, 213,
              10, 246, 22, 54, 176, 48, 39, 123, 132, 105, 22, 42, 231, 87, 198, 77, 88, 139, 22, 237, 223, 67, 18,
              109, 192, 148, 22, 79, 44, 183, 202, 16, 57, 100, 22, 206, 194, 104, 179, 230, 43, 180, 22, 23, 203,
              252, 14, 111, 167, 184, 22, 34, 141, 184, 23, 161, 109, 168, 22, 147, 174, 219, 142, 58, 248, 235, 22,
              253, 36, 160, 255, 32, 107, 225, 22, 51, 119, 240, 14, 36, 131, 213, 22, 146, 90, 165, 49, 163, 168,
              131, 22, 7, 115, 43, 235, 194, 127, 40, 22, 30, 84, 164, 34, 201, 141, 127, 22, 6, 76, 104, 14, 119,
              55, 208, 22, 245, 188, 201, 216, 240, 82, 239, 22, 5, 247, 161, 56, 233, 84, 200, 22, 124, 194, 230,
              205, 178, 74, 253, 22, 55, 116, 207, 48, 219, 124, 210, 22, 86, 215, 18, 75, 157, 224, 24, 22, 237,
              115, 102, 229, 63, 138, 80, 22, 67, 11, 43, 216, 83, 137, 52, 22, 194, 21, 10, 165, 91, 220, 203, 22,
              165, 95, 32, 37, 229, 53, 132, 22, 38, 9, 132, 138, 191, 230, 101, 22, 106, 125, 176, 165, 214, 222,
              200, 22, 141, 124, 104, 215, 204, 229, 84, 22, 26, 96, 110, 182, 200, 3, 232, 22, 233, 229, 52, 138,
              221, 17, 77, 22, 140, 163, 2, 219, 255, 213, 35, 22, 85, 5, 169, 35, 241, 205, 59, 22, 202, 198, 145,
              185, 83, 97, 46, 22, 236, 162, 162, 175, 216, 167, 235, 22, 101, 177, 29, 212, 38, 171, 195, 22, 130,
              253, 162, 83, 162, 46, 215, 22, 9, 232, 89, 69, 181, 83, 185, 22, 42, 131, 77, 213, 38, 74, 45, 22,
              204, 36, 140, 148, 108, 237, 63, 22, 206, 176, 129, 82, 209, 155, 44, 22, 76, 52, 70, 87, 230, 63, 1,
              22, 166, 176, 5, 176, 149, 113, 185, 22, 6, 16, 7, 39, 182, 127, 53, 22, 185, 66, 155, 48, 68, 83, 71,
              22, 123, 53, 169, 153, 109, 242, 173, 22, 112, 224, 178, 92, 248, 100, 94, 22, 169, 57, 8, 252, 234,
              21, 123, 22, 40, 74, 28, 245, 81, 94, 169, 22, 143, 200, 122, 33, 129, 74, 135, 22, 6, 94, 232, 88,
              146, 254, 107, 22, 142, 159, 40, 160, 206, 184, 195, 22, 83, 200, 240, 186, 58, 114, 179, 22, 246, 159,
              108, 249, 66, 28, 217, 22, 180, 174, 140, 111, 167, 237, 186, 22, 7, 198, 72, 197, 141, 242, 97, 22,
              194, 54, 147, 68, 201, 199, 152, 22, 126, 76, 81, 171, 63, 20, 125, 22, 101, 165, 237, 203, 187, 105,
              76, 22, 140, 69, 94, 42, 179, 33, 241, 22, 62, 169, 188, 82, 21, 108, 26, 22, 89, 3, 12, 91, 134, 181,
              153, 22, 25, 236, 169, 158, 87, 200, 29, 22, 65, 175, 99, 82, 133, 119, 151, 22, 14, 122, 236, 151,
              169, 156, 104, 22, 233, 206, 248, 197, 235, 159, 174, 22, 4, 181, 152, 82, 152, 218, 33, 22, 234, 190,
              36, 250, 56, 156, 93, 22, 88, 170, 121, 237, 238, 210, 118, 22, 71, 145, 23, 9, 253, 243, 195, 22, 55,
              214, 197, 164, 215, 111, 103, 22, 188, 92, 4, 90, 147, 53, 103, 22, 44, 226, 79, 149, 20, 250, 186, 22,
              92, 121, 99, 250, 218, 0, 236, 22, 127, 75, 134, 120, 228, 65, 254, 22, 93, 232, 209, 65, 38, 217, 175,
              22, 241, 222, 19, 148, 12, 130, 110, 22, 95, 1, 247, 253, 74, 215, 154, 22, 88, 167, 193, 231, 234,
              250, 150, 22, 56, 52, 10, 61, 130, 81, 157, 22, 127, 110, 103, 243, 21, 172, 125, 22, 37, 119, 246,
              244, 29, 33, 183, 22, 113, 13, 7, 199, 140, 57, 130, 22, 176, 100, 65, 150, 162, 104, 105, 22, 77, 134,
              222, 76, 83, 72, 58, 22, 34, 118, 176, 232, 20, 220, 62, 22, 226, 51, 134, 158, 116, 164, 35, 22, 146,
              136, 78, 207, 94, 42, 182, 22, 113, 128, 18, 86, 5, 30, 155, 22, 129, 36, 16, 54, 52, 42, 64, 22, 132,
              52, 177, 242, 182, 90, 87, 22, 149, 39, 81, 96, 234, 254, 21, 22, 161, 164, 224, 113, 94, 126, 94, 22,
              74, 219, 57, 187, 154, 154, 242, 22, 85, 2, 156, 170, 153, 226, 123, 22, 7, 50, 205, 67, 56, 34, 224,
              22, 94, 96, 26, 119, 67, 221, 94, 22, 225, 60, 234, 12, 158, 99, 228, 22, 202, 188, 0, 200, 219, 27,
              91, 22, 197, 65, 83, 150, 33, 152, 90, 22, 32, 202, 117, 173, 80, 3, 24, 22, 222, 122, 1, 123, 106, 22,
              34, 22, 195, 65, 196, 87, 37, 92, 45, 22, 123, 42, 16, 246, 180, 153, 157, 22, 43, 137, 224, 192, 164,
              20, 148, 22, 119, 86, 81, 204, 77, 154, 148, 22, 35, 144, 189, 190, 162, 34, 221, 22, 240, 9, 218, 200,
              76, 170, 141, 22, 62, 126, 192, 138, 9, 119, 57, 22, 169, 178, 210, 211, 127, 168, 106, 22, 59, 80,
              181, 46, 48, 116, 19, 22, 251, 89, 209, 126, 111, 237, 157, 22, 6, 8, 254, 74, 91, 14, 68, 22, 150,
              112, 204, 125, 185, 111, 95, 22, 62, 156, 5, 148, 125, 101, 24, 22, 192, 251, 214, 19, 146, 201, 4, 22,
              96, 184, 98, 134, 125, 38, 47, 22, 48, 157, 9, 239, 102, 217, 84, 22, 17, 245, 17, 219, 61, 193, 175,
              22, 75, 30, 119, 104, 38, 219, 134, 22, 122, 21, 181, 96, 140, 88, 157, 22, 82, 160, 219, 179, 107,
              246, 20, 22, 81, 1, 132, 99, 58, 152, 19, 22, 145, 213, 169, 47, 249, 161, 55, 22, 178, 26, 95, 241,
              211, 8, 68, 22, 235, 89, 151, 184, 51, 92, 51, 22, 15, 59, 124, 62, 217, 116, 163, 22, 229, 139, 116,
              3, 51, 240, 90, 22, 119, 82, 159, 155, 201, 125, 85, 22, 124, 49, 61, 132, 70, 64, 85, 22, 110, 201,
              25, 194, 238, 196, 81, 22, 223, 22, 142, 110, 75, 190, 163, 22, 78, 225, 113, 163, 211, 146, 122, 22,
              158, 147, 179, 133, 32, 93, 54, 22, 161, 163, 83, 147, 156, 52, 56, 22, 121, 207, 47, 23, 4, 113, 247,
              22, 145, 157, 28, 205, 112, 160, 151, 22, 141, 3, 245, 253, 112, 193, 231, 22, 109, 29, 10, 198, 53,
              66, 21, 22, 15, 74, 237, 22, 70, 237, 178, 22, 53, 15, 161, 189, 188, 169, 7, 22, 46, 182, 58, 204,
              128, 132, 149, 22, 175, 239, 165, 77, 214, 215, 185, 22, 69, 23, 99, 242, 170, 60, 87, 22, 161, 63, 87,
              148, 229, 239, 186, 22, 6, 147, 143, 143, 41, 108, 198, 22, 47, 229, 42, 84, 129, 76, 138, 22, 18, 249,
              250, 5, 111, 248, 147, 22, 253, 123, 39, 95, 108, 24, 152, 22, 31, 54, 128, 19, 149, 240, 200, 22, 236,
              128, 16, 90, 175, 79, 237, 22, 70, 158, 238, 175, 36, 208, 237, 22, 11, 209, 193, 218, 17, 188, 118,
              22, 160, 118, 104, 224, 112, 103, 113, 22, 175, 171, 185, 146, 48, 17, 182, 22, 10, 223, 39, 183, 54,
              42, 58, 22, 41, 195, 246, 226, 83, 53, 159, 22, 73, 169, 118, 247, 178, 92, 16, 22, 181, 125, 198, 167,
              67, 42, 131, 22, 2, 48, 128, 26, 241, 124, 180, 22, 201, 143, 109, 15, 231, 202, 42, 22, 86, 241, 10,
              39, 137, 127, 231, 22, 32, 164, 190, 248, 255, 198, 92, 22, 29, 118, 143, 31, 98, 28, 205, 22, 154, 37,
              250, 247, 201, 159, 114, 22, 171, 105, 59, 244, 115, 170, 80, 22, 233, 119, 15, 43, 193, 71, 13, 22,
              123, 26, 122, 199, 145, 225, 66, 22, 226, 1, 173, 85, 160, 192, 112, 22, 217, 227, 179, 39, 156, 75, 3,
              22, 75, 180, 52, 114, 79, 4, 24, 22, 178, 24, 189, 227, 208, 199, 168, 22, 132, 58, 204, 130, 60, 50,
              205, 22, 172, 250, 117, 77, 241, 94, 42, 22, 113, 146, 125, 166, 149, 47, 133, 22, 185, 53, 102, 194,
              44, 43, 153, 22, 87, 215, 206, 155, 173, 104, 97, 22, 116, 179, 152, 73, 61, 250, 156, 22, 177, 40,
              226, 181, 162, 140, 212, 22, 191, 147, 44, 105, 252, 57, 203, 22, 248, 136, 200, 104, 118, 17, 21, 22,
              92, 55, 33, 122, 61, 178, 41, 22, 33, 233, 98, 207, 78, 176, 201, 22, 122, 131, 33, 9, 54, 25, 213, 22,
              94, 253, 61, 221, 44, 184, 126, 22, 18, 239, 124, 173, 75, 173, 196, 22, 37, 133, 214, 202, 6, 160, 6,
              22, 154, 56, 96, 249, 86, 183, 78, 22, 70, 54, 234, 198, 133, 98, 66, 22, 240, 114, 225, 4, 251, 149,
              107, 22, 223, 44, 176, 250, 233, 58, 192, 22, 154, 218, 176, 230, 231, 37, 38, 22, 63, 197, 21, 150,
              34, 56, 177, 22, 57, 168, 105, 49, 45, 155, 228, 22, 0, 95, 26, 172, 143, 59, 59, 22, 222, 204, 79, 70,
              67, 138, 130, 22, 139, 236, 29, 217, 70, 107, 189, 22, 159, 180, 138, 128, 48, 139, 116, 22, 33, 13,
              62, 0, 21, 93, 177, 22, 69, 68, 220, 48, 248, 180, 11, 22, 126, 134, 143, 224, 130, 177, 166, 22, 92,
              108, 163, 165, 174, 208, 222, 22, 62, 198, 94, 115, 38, 226, 234, 22, 51, 66, 181, 156, 14, 196, 74,
              22, 96, 0, 0, 0, 0, 0, 0, 21, 0, 12, 0, 6, 186, 213, 174, 22, 49, 165, 214, 80, 102, 88, 235, 22, 19,
              118, 18, 33, 179, 175, 87, 22, 70, 36, 164, 249, 94, 176, 135, 22, 51, 144, 99, 86, 252, 112, 79, 22,
              206, 13, 155, 4, 97, 105, 64, 22, 199, 169, 193, 40, 215, 204, 201, 22, 112, 66, 246, 186, 172, 197,
              170, 22, 247, 247, 254, 221, 28, 121, 254, 22, 223, 240, 167, 139, 199, 93, 17, 22, 114, 29, 61, 24,
              82, 69, 73, 22, 115, 234, 185, 227, 125, 129, 148, 22, 161, 56, 90, 93, 146, 188, 112, 22, 165, 134,
              31, 48, 217, 251, 226, 22, 210, 121, 92, 97, 5, 58, 179, 22, 151, 73, 3, 14, 22, 109, 230, 22, 4, 18,
              66, 52, 34, 255, 214, 22, 159, 68, 11, 254, 201, 185, 174, 22, 67, 96, 116, 226, 190, 178, 189, 22,
              226, 38, 84, 178, 181, 208, 189, 22, 80, 145, 229, 156, 6, 226, 131, 22, 99, 113, 30, 236, 45, 233, 85,
              22, 91, 198, 252, 115, 209, 192, 246, 22, 123, 133, 101, 140, 44, 230, 78, 22, 243, 4, 250, 105, 231,
              31, 64, 22, 254, 155, 110, 211, 82, 120, 202, 22, 0, 141, 241, 93, 111, 46, 245, 22, 94, 108, 42, 122,
              75, 207, 249, 22, 14, 246, 154, 53, 246, 108, 233, 22, 122, 51, 107, 198, 110, 192, 174, 22, 50, 244,
              44, 55, 104, 248, 249, 22, 12, 0, 120, 181, 192, 83, 42, 22, 175, 75, 69, 69, 108, 166, 114, 22, 224,
              171, 147, 56, 16, 139, 23, 22, 167, 111, 138, 61, 198, 164, 98, 22, 191, 146, 18, 128, 22, 62, 209, 22,
              234, 86, 124, 186, 161, 229, 157, 22, 15, 26, 141, 137, 191, 194, 14, 22, 35, 75, 234, 161, 163, 82,
              156, 22, 80, 225, 177, 144, 40, 229, 102, 22, 88, 112, 246, 4, 12, 101, 98, 22, 230, 158, 160, 60, 100,
              150, 105, 22, 151, 40, 246, 54, 124, 168, 232, 22, 69, 202, 162, 224, 218, 100, 131, 22, 235, 184, 79,
              117, 28, 29, 98, 22, 223, 203, 153, 82, 236, 223, 83, 22, 57, 226, 176, 115, 46, 97, 63, 22, 213, 110,
              92, 106, 114, 65, 70, 22, 21, 242, 194, 243, 208, 255, 197, 22, 156, 135, 225, 27, 34, 202, 61, 22, 47,
              208, 119, 67, 3, 251, 240, 22, 87, 34, 175, 249, 232, 100, 31, 22, 192, 55, 180, 226, 6, 3, 128, 22,
              108, 83, 221, 128, 106, 134, 196, 22, 197, 35, 208, 157, 70, 210, 180, 22, 156, 232, 108, 251, 101,
              146, 240, 22, 154, 118, 69, 68, 74, 243, 236, 22, 97, 140, 88, 16, 175, 42, 24, 22, 248, 38, 66, 180,
              162, 187, 206, 22, 72, 153, 110, 249, 168, 95, 56, 22, 17, 251, 0, 139, 222, 0, 4, 22, 203, 238, 78,
              155, 155, 44, 121, 22, 44, 200, 105, 13, 173, 200, 23, 22, 91, 225, 7, 81, 91, 208, 210, 22, 235, 1,
              48, 187, 225, 159, 196, 22, 175, 57, 123, 236, 155, 76, 126, 22, 33, 110, 120, 70, 86, 58, 187, 22, 63,
              163, 39, 106, 143, 121, 127, 22, 106, 157, 61, 103, 71, 238, 61, 22, 174, 183, 212, 12, 202, 248, 89,
              22, 196, 23, 150, 65, 151, 132, 220, 22, 98, 45, 73, 86, 97, 5, 179, 22, 229, 157, 205, 127, 139, 249,
              3, 22, 2, 134, 7, 235, 65, 59, 254, 22, 103, 156, 136, 132, 162, 51, 4, 22, 68, 19, 37, 217, 166, 67,
              111, 22, 172, 107, 220, 126, 194, 75, 141, 22, 112, 19, 235, 63, 169, 59, 182, 22, 177, 19, 33, 62,
              156, 201, 127, 22, 1, 205, 225, 222, 110, 66, 121, 22, 98, 55, 76, 24, 110, 65, 251, 22, 56, 157, 135,
              24, 242, 217, 243, 22, 53, 214, 229, 64, 220, 163, 255, 22, 168, 153, 208, 216, 50, 180, 116, 22, 6,
              22, 39, 76, 129, 219, 134, 22, 244, 55, 224, 79, 216, 219, 183, 22, 10, 156, 238, 158, 31, 143, 70, 22,
              235, 19, 236, 154, 61, 227, 63, 22, 203, 89, 106, 23, 163, 150, 199, 22, 5, 190, 210, 39, 111, 63, 212,
              22, 46, 251, 172, 152, 195, 19, 26, 22, 182, 172, 155, 242, 244, 216, 207, 22, 106, 185, 48, 25, 230,
              210, 65, 22, 128, 168, 5, 38, 95, 58, 92, 22, 241, 52, 117, 30, 207, 100, 103, 22, 135, 88, 233, 72,
              55, 184, 208, 22, 66, 27, 29, 176, 6, 121, 240, 22, 138, 139, 82, 169, 230, 27, 249, 22, 93, 188, 189,
              59, 169, 171, 205, 22, 185, 3, 76, 246, 181, 186, 168, 22, 25, 238, 94, 86, 90, 114, 27, 22, 154, 212,
              71, 8, 157, 172, 15, 22, 63, 193, 243, 15, 54, 46, 50, 22, 219, 92, 41, 137, 192, 16, 69, 22, 232, 20,
              75, 132, 102, 219, 173, 22, 129, 228, 129, 21, 241, 182, 71, 22, 113, 151, 29, 226, 253, 212, 97, 22,
              207, 36, 121, 238, 133, 235, 127, 22, 191, 205, 13, 61, 102, 75, 40, 22, 40, 246, 167, 26, 10, 71, 105,
              22, 48, 146, 36, 18, 57, 183, 162, 22, 136, 218, 14, 77, 232, 174, 38, 22, 40, 189, 32, 144, 161, 48,
              20, 22, 234, 242, 117, 12, 192, 193, 42, 22, 37, 181, 98, 247, 242, 1, 210, 22, 176, 67, 77, 22, 56,
              75, 131, 22, 202, 101, 129, 121, 142, 152, 164, 22, 240, 184, 243, 31, 149, 62, 38, 22, 218, 239, 77,
              195, 17, 30, 125, 22, 214, 196, 90, 51, 32, 210, 201, 22, 62, 94, 35, 139, 183, 192, 69, 22, 68, 92,
              163, 72, 102, 206, 168, 22, 15, 219, 221, 52, 19, 231, 173, 22, 36, 66, 41, 136, 160, 8, 10, 22, 210,
              151, 54, 187, 77, 38, 255, 22, 243, 123, 196, 136, 236, 137, 198, 22, 95, 114, 43, 192, 161, 224, 213,
              22, 138, 148, 57, 82, 170, 126, 230, 22, 170, 134, 33, 233, 185, 98, 204, 22, 54, 250, 84, 66, 6, 235,
              190, 22, 113, 17, 105, 99, 20, 178, 94, 22, 51, 33, 84, 71, 94, 138, 220, 22, 124, 75, 172, 160, 34,
              152, 133, 22, 141, 83, 118, 129, 188, 60, 199, 22, 114, 71, 131, 175, 24, 94, 36, 22, 121, 5, 156, 103,
              95, 79, 83, 22, 204, 151, 241, 43, 173, 10, 250, 22, 63, 121, 139, 68, 126, 87, 242, 22, 154, 106, 233,
              131, 32, 231, 124, 22, 125, 55, 150, 147, 222, 102, 189, 22, 46, 113, 100, 225, 76, 1, 106, 22, 208,
              15, 217, 225, 127, 60, 125, 22, 45, 106, 201, 76, 126, 243, 16, 22, 219, 128, 221, 254, 224, 12, 43,
              22, 154, 7, 69, 119, 5, 249, 121, 22, 60, 98, 78, 39, 219, 148, 187, 22, 102, 79, 235, 67, 31, 242,
              245, 22, 32, 136, 151, 95, 99, 251, 200, 22, 116, 119, 163, 68, 131, 27, 153, 22, 224, 156, 180, 158,
              10, 254, 80, 22, 225, 107, 152, 52, 84, 47, 20, 22, 78, 171, 244, 17, 157, 233, 221, 22, 253, 120, 152,
              232, 63, 231, 215, 22, 145, 70, 49, 220, 43, 78, 107, 22, 241, 103, 174, 226, 45, 98, 246, 22, 63, 168,
              223, 255, 247, 79, 54, 22, 13, 148, 146, 132, 164, 95, 65, 22, 12, 238, 216, 21, 149, 178, 209, 22,
              141, 40, 17, 234, 18, 78, 236, 22, 250, 110, 156, 82, 195, 241, 55, 22, 134, 79, 204, 169, 31, 135, 39,
              22, 76, 143, 160, 250, 163, 98, 48, 22, 137, 168, 214, 78, 28, 92, 239, 22, 82, 39, 95, 165, 211, 30,
              100, 22, 185, 117, 155, 36, 253, 194, 24, 22, 1, 187, 188, 4, 163, 230, 24, 22, 109, 20, 165, 145, 115,
              59, 198, 22, 79, 101, 148, 72, 43, 207, 224, 22, 108, 54, 189, 3, 230, 31, 234, 22, 153, 219, 46, 189,
              80, 246, 220, 22, 34, 41, 137, 20, 225, 107, 123, 22, 225, 69, 189, 190, 173, 117, 78, 22, 181, 152,
              108, 8, 209, 197, 90, 22, 159, 164, 77, 48, 54, 16, 44, 22, 198, 149, 12, 169, 35, 250, 108, 22, 39,
              161, 98, 214, 170, 236, 236, 22, 249, 251, 139, 194, 220, 137, 67, 22, 242, 211, 37, 204, 221, 150,
              115, 22, 101, 141, 200, 133, 122, 133, 67, 22, 79, 47, 130, 215, 209, 21, 196, 22, 246, 38, 195, 58,
              158, 35, 242, 22, 54, 111, 134, 82, 138, 25, 217, 22, 33, 189, 116, 132, 163, 46, 165, 22, 92, 100, 90,
              124, 32, 36, 60, 22, 70, 110, 60, 223, 151, 134, 227, 22, 18, 238, 31, 166, 74, 134, 57, 22, 241, 242,
              63, 231, 206, 100, 229, 22, 243, 90, 43, 135, 56, 33, 19, 22, 89, 187, 51, 63, 104, 215, 63, 22, 251,
              133, 136, 79, 193, 100, 193, 22, 69, 59, 179, 203, 135, 175, 192, 22, 88, 160, 145, 201, 151, 145, 81,
              22, 85, 105, 89, 232, 214, 253, 180, 22, 45, 126, 140, 108, 11, 3, 56, 22, 205, 215, 140, 214, 215,
              248, 169, 22, 50, 129, 76, 195, 234, 160, 144, 22, 164, 201, 187, 95, 24, 242, 132, 22, 176, 19, 27,
              153, 133, 5, 222, 22, 205, 77, 231, 56, 4, 67, 116, 22, 79, 118, 38, 228, 53, 230, 12, 22, 113, 123,
              205, 61, 77, 195, 71, 22, 69, 156, 0, 156, 228, 130, 101, 22, 160, 53, 156, 182, 51, 191, 185, 22, 180,
              123, 218, 51, 232, 8, 90, 22, 83, 84, 66, 152, 179, 111, 78, 22, 253, 2, 173, 139, 187, 127, 87, 22,
              175, 183, 63, 82, 21, 104, 70, 22, 49, 24, 85, 164, 23, 244, 185, 22, 212, 242, 205, 222, 186, 143, 16,
              22, 148, 128, 82, 106, 167, 101, 50, 22, 152, 162, 72, 163, 33, 79, 51, 22, 3, 135, 134, 193, 137, 109,
              206, 22, 65, 190, 36, 206, 173, 104, 96, 22, 65, 180, 207, 141, 206, 37, 33, 22, 221, 139, 214, 183,
              98, 51, 203, 22, 221, 7, 153, 174, 216, 242, 17, 22, 203, 167, 115, 102, 147, 65, 5, 22, 142, 12, 58,
              206, 218, 212, 54, 22, 236, 104, 208, 136, 108, 253, 177, 22, 85, 193, 25, 119, 156, 194, 191, 22, 19,
              88, 14, 145, 49, 99, 177, 22, 143, 125, 125, 195, 21, 248, 40, 22, 118, 233, 224, 194, 64, 44, 76, 22,
              17, 253, 148, 203, 133, 104, 188, 22, 203, 158, 115, 22, 178, 45, 228, 22, 49, 92, 244, 11, 154, 83,
              143, 22, 4, 93, 159, 189, 151, 21, 162, 22, 245, 162, 187, 241, 121, 140, 248, 22, 134, 151, 33, 161,
              61, 183, 184, 22, 248, 136, 185, 171, 105, 242, 125, 22, 109, 10, 211, 85, 28, 32, 212, 22, 236, 140,
              84, 103, 179, 169, 225, 22, 142, 112, 228, 94, 110, 254, 104, 22, 33, 128, 116, 212, 97, 176, 38, 22,
              148, 252, 73, 155, 47, 215, 87, 22, 238, 153, 134, 78, 151, 219, 133, 22, 26, 71, 109, 176, 15, 244,
              44, 22, 161, 172, 200, 134, 178, 197, 19, 22, 33, 111, 166, 74, 219, 253, 88, 22, 177, 138, 228, 251,
              16, 6, 24, 22, 112, 26, 226, 31, 7, 223, 86, 22, 174, 54, 110, 16, 171, 20, 46, 22, 61, 251, 202, 113,
              1, 98, 233, 22, 165, 179, 105, 170, 6, 60, 54, 22, 222, 123, 253, 205, 208, 113, 47, 22, 236, 126, 60,
              61, 79, 169, 214, 22, 202, 164, 137, 250, 237, 139, 161, 22, 70, 101, 38, 139, 0, 157, 55, 22, 174,
              221, 195, 185, 41, 109, 212, 22, 48, 117, 95, 154, 118, 206, 70, 22, 9, 169, 52, 228, 80, 109, 202, 22,
              246, 74, 71, 64, 69, 41, 184, 22, 119, 115, 33, 34, 23, 91, 4, 22, 112, 29, 73, 217, 233, 242, 52, 22,
              254, 149, 73, 186, 183, 181, 60, 22, 192, 102, 202, 21, 89, 94, 175, 22, 81, 147, 0, 166, 21, 170, 108,
              22, 17, 76, 242, 89, 49, 193, 110, 22, 50, 7, 187, 146, 10, 27, 194, 22, 189, 128, 171, 132, 242, 139,
              45, 22, 72, 106, 129, 185, 178, 101, 46, 22, 73, 212, 6, 116, 60, 25, 75, 22, 180, 17, 177, 131, 38,
              245, 112, 22, 46, 14, 60, 34, 4, 98, 181, 22, 182, 205, 131, 183, 114, 30, 70, 22, 143, 223, 143, 78,
              142, 150, 223, 22, 218, 46, 140, 178, 214, 94, 137, 22, 81, 43, 122, 172, 53, 1, 166, 22, 161, 84, 165,
              137, 231, 100, 227, 22, 242, 151, 5, 77, 104, 211, 184, 22, 77, 98, 52, 113, 203, 41, 42, 22, 209, 172,
              161, 123, 91, 22, 188, 22, 89, 205, 248, 138, 183, 174, 127, 22, 56, 7, 80, 150, 249, 159, 71, 22, 154,
              253, 9, 136, 154, 14, 80, 22, 111, 212, 237, 191, 194, 54, 237, 22, 48, 185, 8, 119, 110, 158, 175, 22,
              150, 246, 72, 129, 206, 162, 243, 22, 28, 78, 174, 105, 230, 241, 124, 22, 142, 111, 80, 206, 130, 235,
              172, 22, 73, 150, 228, 194, 242, 85, 135, 22, 88, 23, 233, 185, 35, 43, 146, 22, 135, 166, 170, 155,
              144, 14, 176, 22, 164, 223, 48, 126, 53, 230, 48, 22, 223, 21, 238, 193, 58, 140, 190, 22, 57, 156, 14,
              231, 4, 18, 34, 22, 224, 155, 58, 231, 201, 65, 21, 22, 156, 83, 37, 23, 13, 229, 242, 22, 202, 251,
              67, 237, 243, 129, 145, 22, 151, 219, 211, 144, 202, 162, 235, 22, 11, 123, 158, 21, 98, 124, 195, 22,
              38, 74, 104, 141, 131, 220, 40, 22, 5, 91, 206, 191, 67, 64, 248, 22, 154, 87, 52, 195, 178, 229, 79,
              22, 230, 29, 134, 111, 246, 216, 32, 22, 104, 239, 196, 23, 226, 28, 131, 22, 231, 36, 3, 179, 217,
              212, 67, 22, 66, 8, 106, 77, 219, 75, 64, 22, 240, 188, 112, 102, 209, 100, 228, 22, 253, 169, 184,
              212, 62, 178, 197, 22, 15, 99, 71, 144, 228, 118, 114, 22, 135, 195, 161, 144, 81, 61, 57, 22, 120,
              137, 66, 100, 188, 124, 242, 22, 177, 56, 29, 185, 154, 52, 226, 22, 146, 106, 38, 165, 26, 218, 212,
              22, 209, 65, 69, 247, 253, 90, 169, 22, 157, 189, 40, 148, 253, 134, 215, 22, 105, 21, 183, 170, 64,
              33, 217, 22, 201, 236, 164, 42, 62, 234, 147, 22, 87, 63, 18, 8, 121, 231, 146, 22, 121, 150, 209, 152,
              22, 250, 234, 22, 203, 147, 155, 168, 20, 252, 107, 22, 40, 48, 142, 137, 115, 212, 87, 22, 203, 237,
              42, 238, 82, 50, 34, 22, 2, 107, 216, 100, 222, 17, 255, 22, 61, 218, 172, 208, 71, 30, 137, 22, 145,
              92, 180, 225, 80, 89, 110, 22, 1, 166, 108, 211, 181, 47, 118, 22, 239, 176, 212, 30, 177, 180, 254,
              22, 95, 175, 148, 31, 73, 97, 137, 22, 60, 45, 152, 135, 61, 160, 70, 22, 22, 187, 116, 23, 192, 178,
              88, 22, 175, 213, 209, 58, 181, 13, 1, 22, 52, 9, 165, 103, 193, 180, 113, 22, 176, 98, 217, 109, 208,
              80, 219, 22, 201, 63, 44, 183, 56, 40, 71, 22, 4, 191, 91, 70, 160, 85, 240, 22, 148, 43, 127, 247,
              166, 241, 151, 22, 6, 53, 206, 122, 194, 77, 180, 22, 87, 75, 2, 118, 114, 241, 200, 22, 122, 29, 142,
              82, 238, 163, 205, 22, 5, 209, 166, 84, 12, 129, 228, 22, 188, 170, 167, 49, 108, 147, 55, 22, 58, 179,
              58, 101, 126, 1, 231, 22, 170, 172, 44, 160, 192, 170, 26, 22, 60, 252, 201, 28, 221, 39, 216, 22, 49,
              171, 200, 165, 190, 217, 170, 22, 164, 219, 35, 193, 13, 124, 106, 22, 202, 67, 57, 55, 58, 224, 169,
              22, 185, 50, 70, 185, 5, 95, 82, 22, 252, 212, 57, 232, 44, 1, 128, 22, 204, 140, 25, 102, 61, 151,
              104, 22, 60, 155, 12, 33, 246, 172, 160, 22, 2, 205, 32, 101, 248, 182, 42, 22, 14, 242, 136, 30, 56,
              99, 102, 22, 14, 195, 215, 109, 15, 228, 239, 22, 37, 241, 215, 152, 5, 148, 94, 22, 10, 97, 110, 143,
              208, 115, 237, 22, 211, 32, 115, 93, 114, 255, 118, 22, 206, 94, 28, 105, 77, 94, 253, 22, 20, 174,
              197, 42, 219, 247, 41, 22, 253, 111, 5, 181, 122, 230, 9, 22, 7, 175, 186, 56, 81, 75, 129, 22, 92,
              255, 179, 125, 245, 198, 105, 22, 132, 78, 49, 233, 227, 131, 159, 22, 171, 120, 76, 239, 176, 131, 61,
              22, 77, 12, 104, 194, 15, 246, 26, 22, 5, 124, 64, 61, 19, 11, 113, 22, 93, 142, 145, 18, 113, 106,
              172, 22, 22, 60, 65, 50, 9, 63, 76, 22, 235, 113, 145, 227, 70, 206, 91, 22, 27, 33, 111, 75, 17, 181,
              29, 22, 12, 205, 147, 35, 45, 255, 113, 22, 242, 24, 247, 70, 116, 179, 18, 22, 58, 206, 12, 50, 39,
              100, 97, 22, 79, 120, 182, 206, 165, 103, 225, 22, 32, 101, 169, 187, 236, 14, 218, 22, 140, 149, 64,
              26, 6, 5, 177, 22, 157, 203, 236, 100, 29, 82, 134, 22, 27, 166, 190, 216, 82, 21, 110, 22, 231, 148,
              162, 107, 205, 212, 33, 22, 217, 243, 171, 247, 49, 149, 65, 22, 118, 147, 110, 189, 56, 140, 211, 22,
              56, 126, 40, 36, 58, 78, 85, 22, 28, 207, 20, 70, 97, 187, 99, 22, 45, 64, 201, 195, 30, 246, 84, 22,
              213, 91, 60, 32, 241, 200, 184, 22, 96, 95, 131, 235, 10, 160, 206, 22, 84, 105, 19, 226, 143, 58, 87,
              22, 181, 1, 50, 209, 253, 206, 71, 22, 182, 202, 125, 168, 45, 158, 180, 22, 253, 86, 195, 48, 196,
              137, 88, 22, 198, 109, 206, 191, 22, 46, 196, 22, 91, 188, 237, 57, 148, 222, 59, 22, 182, 20, 186,
              225, 224, 68, 57, 22, 232, 31, 42, 230, 243, 34, 11, 22, 235, 105, 35, 150, 159, 49, 245, 22, 246, 122,
              116, 223, 140, 167, 125, 22, 224, 83, 241, 9, 64, 238, 209, 22, 160, 110, 85, 188, 116, 160, 73, 22,
              14, 6, 132, 175, 192, 202, 54, 22, 89, 55, 109, 137, 147, 60, 20, 22, 147, 40, 145, 87, 95, 9, 73, 22,
              121, 114, 223, 168, 162, 103, 175, 22, 168, 68, 190, 33, 119, 220, 45, 22, 44, 70, 117, 236, 248, 149,
              50, 22, 69, 199, 123, 178, 201, 197, 187, 22, 118, 250, 173, 45, 191, 153, 130, 22, 14, 9, 138, 153,
              101, 179, 200, 22, 98, 244, 225, 67, 205, 101, 50, 22, 34, 169, 148, 16, 131, 241, 91, 22, 236, 120,
              96, 163, 127, 151, 145, 22, 212, 9, 173, 13, 252, 214, 8, 22, 222, 236, 248, 201, 217, 97, 166, 22,
              193, 109, 46, 204, 181, 148, 69, 22, 167, 203, 166, 156, 154, 104, 163, 22, 121, 59, 195, 175, 31, 129,
              140, 22, 53, 48, 89, 163, 114, 221, 156, 22, 24, 174, 136, 111, 106, 103, 6, 22, 43, 42, 3, 76, 245,
              17, 231, 22, 135, 85, 27, 69, 103, 203, 95, 22, 40, 27, 191, 167, 189, 21, 183, 22, 94, 124, 18, 19,
              172, 157, 162, 22, 231, 134, 214, 54, 62, 89, 106, 22, 102, 174, 100, 52, 91, 76, 254, 22, 98, 81, 199,
              1, 204, 114, 227, 22, 43, 119, 135, 60, 129, 150, 252, 22, 229, 219, 189, 106, 237, 187, 81, 22, 70,
              136, 140, 16, 108, 15, 131, 22, 25, 252, 247, 88, 236, 85, 1, 22, 57, 124, 213, 48, 108, 22, 91, 22,
              219, 162, 245, 166, 78, 219, 56, 22, 213, 151, 33, 250, 12, 38, 190, 22, 196, 85, 227, 250, 160, 252,
              182, 22, 87, 44, 125, 85, 203, 140, 51, 22, 145, 107, 143, 244, 82, 109, 243, 22, 67, 233, 223, 54, 31,
              118, 79, 22, 98, 229, 175, 68, 37, 241, 71, 22, 230, 89, 197, 87, 69, 73, 13, 22, 208, 223, 48, 220,
              59, 72, 117, 22, 138, 128, 250, 52, 135, 15, 83, 22, 77, 19, 112, 95, 241, 51, 247, 22, 167, 182, 191,
              211, 145, 123, 194, 22, 48, 114, 8, 189, 50, 215, 183, 22, 57, 255, 122, 89, 91, 88, 61, 22, 60, 130,
              116, 171, 22, 152, 162, 22, 206, 27, 219, 124, 68, 180, 210, 22, 194, 183, 241, 105, 31, 60, 229, 22,
              185, 115, 81, 248, 80, 80, 173, 22, 27, 188, 72, 46, 29, 219, 0, 21, 0, 8, 0, 139, 100, 76, 135, 22,
              16, 48, 139, 221, 153, 168, 125, 22, 187, 99, 20, 7, 58, 192, 183, 22, 155, 223, 49, 142, 24, 245, 227,
              22, 6, 161, 193, 87, 83, 93, 119, 22, 116, 154, 202, 169, 71, 168, 101, 22, 110, 186, 56, 177, 25, 80,
              221, 22, 132, 16, 204, 68, 100, 218, 36, 22, 13, 113, 3, 99, 224, 141, 11, 22, 125, 9, 221, 48, 74,
              208, 156, 22, 218, 224, 1, 177, 188, 194, 223, 22, 233, 93, 3, 59, 148, 154, 106, 22, 132, 15, 90, 232,
              197, 62, 183, 22, 207, 111, 252, 247, 142, 189, 255, 22, 173, 237, 135, 158, 34, 62, 115, 22, 96, 20,
              119, 174, 225, 2, 34, 22, 126, 93, 133, 158, 124, 201, 28, 22, 65, 96, 66, 97, 242, 31, 1, 22, 111,
              135, 135, 41, 162, 9, 29, 22, 49, 72, 196, 233, 218, 253, 96, 22, 125, 29, 167, 4, 39, 236, 95, 22,
              232, 176, 238, 165, 244, 83, 103, 22, 190, 89, 119, 83, 253, 46, 124, 22, 208, 219, 191, 88, 16, 169,
              151, 22, 206, 253, 210, 251, 92, 101, 1, 22, 39, 153, 62, 188, 245, 92, 234, 22, 48, 213, 229, 124, 49,
              184, 11, 22, 6, 131, 83, 113, 185, 51, 192, 22, 159, 207, 148, 211, 92, 80, 92, 22, 101, 135, 59, 51,
              83, 210, 221, 22, 113, 152, 167, 249, 43, 211, 143, 22, 255, 232, 181, 152, 59, 27, 194, 22, 27, 208,
              47, 56, 237, 99, 125, 22, 219, 88, 16, 153, 22, 78, 172, 22, 230, 131, 143, 112, 60, 77, 239, 22, 66,
              21, 254, 5, 102, 72, 18, 22, 118, 134, 130, 182, 192, 113, 134, 22, 174, 75, 228, 47, 158, 80, 226, 22,
              88, 135, 3, 104, 68, 121, 143, 22, 186, 147, 25, 249, 249, 156, 5, 22, 100, 109, 45, 42, 151, 158, 69,
              22, 222, 97, 241, 154, 69, 3, 44, 22, 121, 96, 115, 142, 27, 189, 190, 22, 18, 93, 52, 142, 73, 152,
              228, 22, 169, 63, 87, 90, 97, 54, 20, 22, 129, 30, 41, 68, 93, 81, 129, 22, 226, 215, 10, 236, 40, 77,
              70, 22, 119, 39, 78, 254, 74, 62, 158, 22, 22, 130, 49, 33, 167, 219, 44, 22, 235, 232, 21, 29, 53,
              238, 6, 22, 144, 58, 151, 163, 44, 7, 29, 22, 236, 25, 120, 94, 93, 166, 37, 22, 83, 243, 187, 173, 79,
              171, 169, 22, 190, 188, 180, 28, 183, 116, 150, 22, 141, 53, 44, 74, 66, 201, 50, 22, 231, 101, 116,
              52, 20, 218, 244, 22, 175, 68, 245, 13, 84, 144, 129, 22, 222, 91, 201, 138, 193, 149, 204, 22, 115,
              38, 5, 217, 53, 131, 14, 22, 240, 10, 127, 82, 55, 163, 167, 22, 226, 230, 238, 15, 226, 123, 243, 22,
              199, 239, 24, 212, 5, 234, 14, 22, 87, 250, 77, 88, 132, 165, 122, 22, 80, 216, 7, 96, 239, 141, 111,
              22, 251, 197, 243, 129, 84, 157, 210, 22, 153, 125, 45, 42, 214, 67, 242, 22, 97, 223, 146, 43, 10,
              226, 223, 22, 238, 93, 240, 144, 103, 243, 83, 22, 153, 83, 113, 46, 137, 233, 155, 22, 27, 135, 253,
              177, 37, 3, 18, 22, 133, 30, 157, 117, 175, 148, 221, 22, 223, 18, 19, 164, 153, 229, 94, 22, 96, 246,
              16, 8, 142, 237, 128, 22, 183, 117, 154, 79, 166, 5, 170, 22, 232, 70, 80, 161, 94, 5, 102, 22, 168,
              238, 12, 23, 6, 66, 33, 22, 213, 242, 117, 35, 65, 10, 217, 22, 179, 58, 116, 137, 232, 78, 84, 22,
              111, 160, 106, 78, 109, 152, 93, 22, 166, 9, 215, 72, 5, 228, 31, 22, 225, 86, 27, 138, 151, 132, 217,
              22, 235, 12, 170, 123, 91, 214, 111, 22, 72, 145, 227, 107, 202, 75, 31, 22, 106, 121, 73, 233, 3, 134,
              47, 22, 33, 190, 168, 110, 72, 15, 239, 22, 199, 201, 76, 26, 41, 255, 13, 22, 162, 56, 116, 43, 56,
              52, 188, 22, 11, 197, 206, 157, 48, 220, 254, 22, 253, 39, 3, 108, 250, 72, 111, 22, 195, 160, 115, 17,
              176, 218, 11, 22, 50, 149, 163, 37, 85, 150, 98, 22, 148, 17, 90, 186, 118, 248, 248, 22, 162, 119, 91,
              51, 178, 121, 96, 22, 199, 183, 137, 223, 219, 202, 234, 22, 70, 134, 177, 17, 204, 26, 167, 22, 61,
              128, 79, 247, 149, 213, 255, 22, 181, 149, 222, 177, 9, 11, 235, 22, 72, 119, 23, 128, 190, 35, 79, 22,
              107, 229, 189, 19, 189, 171, 188, 22, 129, 47, 182, 185, 16, 149, 122, 22, 183, 108, 31, 24, 28, 37,
              209, 22, 113, 100, 203, 240, 101, 175, 32, 22, 163, 130, 223, 2, 182, 239, 49, 22, 185, 28, 67, 48,
              213, 66, 203, 22, 222, 199, 12, 10, 16, 97, 117, 22, 94, 130, 174, 72, 9, 168, 32, 22, 227, 209, 108,
              119, 231, 90, 159, 22, 14, 56, 41, 181, 176, 254, 120, 22, 204, 22, 186, 26, 16, 66, 77, 22, 162, 92,
              10, 55, 39, 12, 134, 22, 128, 154, 202, 112, 250, 51, 181, 22, 170, 183, 241, 2, 232, 151, 68, 22, 202,
              72, 219, 198, 247, 202, 157, 22, 192, 44, 13, 133, 184, 170, 48, 22, 146, 109, 212, 146, 106, 236, 216,
              22, 149, 61, 30, 91, 126, 173, 171, 22, 212, 49, 203, 181, 32, 148, 181, 22, 210, 39, 225, 129, 93,
              220, 66, 22, 207, 71, 46, 206, 139, 144, 18, 22, 23, 7, 165, 248, 134, 146, 227, 22, 171, 68, 125, 110,
              112, 2, 83, 22, 1, 69, 33, 65, 20, 132, 29, 22, 80, 8, 182, 26, 254, 205, 136, 22, 227, 190, 195, 194,
              191, 75, 82, 22, 165, 248, 55, 101, 17, 227, 64, 22, 35, 183, 45, 80, 42, 144, 24, 22, 51, 55, 99, 187,
              198, 23, 167, 22, 254, 26, 79, 106, 194, 149, 148, 22, 14, 40, 253, 3, 253, 97, 216, 22, 138, 153, 53,
              200, 72, 76, 12, 22, 89, 231, 227, 199, 193, 203, 20, 22, 40, 234, 76, 29, 206, 86, 48, 22, 78, 213,
              81, 207, 217, 53, 122, 22, 19, 162, 182, 96, 69, 164, 49, 22, 99, 2, 139, 45, 94, 188, 20, 22, 70, 203,
              130, 68, 239, 110, 90, 22, 187, 173, 219, 230, 91, 198, 196, 22, 35, 47, 233, 56, 75, 64, 131, 22, 17,
              211, 22, 68, 16, 116, 81, 22, 1, 41, 218, 13, 220, 120, 245, 22, 22, 27, 73, 235, 143, 168, 17, 22, 59,
              51, 48, 97, 10, 162, 39, 22, 185, 111, 22, 249, 36, 67, 152, 22, 189, 89, 190, 122, 244, 73, 64, 22,
              228, 157, 54, 2, 234, 168, 191, 22, 119, 51, 66, 41, 13, 177, 250, 22, 183, 35, 230, 55, 59, 235, 31,
              22, 108, 33, 150, 255, 102, 43, 129, 22, 140, 240, 82, 222, 99, 62, 118, 22, 135, 243, 112, 9, 216, 80,
              36, 22, 191, 245, 235, 61, 239, 71, 103, 22, 171, 135, 48, 27, 4, 119, 191, 22, 220, 9, 244, 149, 59,
              75, 192, 22, 166, 192, 231, 230, 96, 115, 158, 22, 240, 136, 248, 61, 47, 3, 241, 22, 102, 2, 131, 31,
              214, 78, 158, 22, 140, 152, 96, 64, 44, 34, 250, 22, 144, 50, 168, 6, 2, 144, 181, 22, 240, 153, 110,
              69, 206, 11, 98, 22, 200, 217, 102, 142, 63, 12, 230, 22, 120, 36, 115, 73, 121, 245, 17, 22, 3, 67,
              69, 6, 38, 247, 232, 22, 125, 8, 36, 245, 250, 209, 151, 22, 122, 25, 233, 68, 172, 71, 171, 22, 42,
              200, 113, 180, 52, 177, 37, 22, 165, 178, 128, 186, 254, 32, 235, 22, 162, 33, 130, 151, 236, 184, 108,
              22, 219, 105, 178, 201, 194, 78, 232, 22, 94, 199, 0, 12, 68, 76, 194, 22, 131, 236, 65, 186, 188, 16,
              246, 22, 247, 71, 139, 171, 163, 223, 241, 22, 154, 104, 233, 144, 60, 148, 210, 22, 228, 108, 222,
              154, 235, 232, 198, 22, 83, 89, 70, 9, 235, 203, 29, 22, 54, 42, 251, 75, 124, 74, 131, 22, 99, 210,
              66, 22, 152, 87, 93, 22, 46, 82, 22, 189, 216, 11, 141, 22, 148, 1, 191, 168, 63, 100, 172, 22, 252,
              28, 81, 211, 201, 28, 173, 22, 162, 115, 227, 241, 104, 64, 161, 22, 68, 137, 169, 36, 222, 63, 198,
              22, 169, 76, 252, 255, 37, 229, 122, 22, 153, 238, 232, 176, 10, 244, 100, 22, 121, 136, 26, 157, 175,
              230, 176, 22, 28, 239, 165, 109, 16, 6, 247, 22, 241, 20, 93, 35, 130, 206, 191, 22, 3, 218, 191, 207,
              159, 59, 78, 22, 168, 41, 3, 132, 161, 34, 159, 22, 9, 84, 207, 4, 3, 30, 239, 22, 212, 184, 194, 247,
              158, 168, 227, 22, 107, 247, 26, 181, 219, 159, 87, 22, 95, 17, 87, 114, 123, 45, 37, 22, 187, 123, 84,
              112, 168, 3, 48, 22, 166, 53, 124, 104, 92, 126, 126, 22, 178, 185, 123, 55, 168, 110, 121, 22, 168,
              48, 40, 254, 57, 243, 192, 22, 103, 4, 71, 1, 175, 208, 186, 22, 4, 153, 189, 178, 141, 87, 117, 22,
              111, 33, 172, 202, 133, 173, 32, 22, 201, 208, 243, 175, 179, 145, 150, 22, 123, 175, 65, 225, 116,
              230, 179, 22, 228, 54, 247, 144, 229, 122, 213, 22, 63, 84, 192, 177, 121, 148, 186, 22, 37, 221, 61,
              80, 104, 81, 32, 22, 64, 178, 112, 3, 69, 23, 68, 22, 238, 35, 15, 40, 48, 189, 88, 22, 80, 77, 57, 24,
              71, 66, 93, 22, 50, 223, 255, 121, 51, 239, 210, 22, 199, 230, 206, 139, 235, 38, 49, 22, 202, 10, 234,
              85, 177, 96, 111, 22, 47, 131, 200, 255, 248, 126, 242, 22, 210, 227, 129, 156, 222, 76, 45, 22, 119,
              47, 217, 190, 159, 191, 84, 22, 159, 3, 193, 73, 226, 241, 43, 22, 180, 9, 130, 7, 136, 235, 170, 22,
              107, 208, 173, 231, 154, 234, 49, 22, 136, 17, 26, 207, 244, 255, 36, 22, 254, 86, 47, 230, 12, 132, 8,
              22, 114, 251, 49, 195, 230, 196, 186, 22, 236, 240, 51, 89, 48, 134, 107, 22, 73, 181, 216, 99, 55,
              152, 94, 22, 42, 123, 171, 65, 5, 149, 25, 22, 120, 220, 87, 255, 21, 98, 238, 22, 95, 201, 58, 106,
              71, 60, 244, 22, 250, 235, 103, 147, 191, 106, 159, 22, 243, 199, 2, 251, 65, 165, 132, 22, 61, 164,
              122, 128, 31, 47, 157, 22, 85, 55, 65, 197, 158, 124, 148, 22, 161, 54, 25, 203, 15, 149, 95, 22, 68,
              216, 169, 119, 207, 160, 39, 22, 163, 38, 217, 131, 96, 157, 77, 22, 189, 129, 236, 74, 125, 173, 66,
              22, 37, 172, 96, 237, 124, 156, 121, 22, 98, 78, 211, 238, 92, 8, 173, 22, 83, 5, 165, 18, 140, 107,
              216, 22, 226, 29, 241, 253, 70, 218, 51, 22, 198, 55, 154, 34, 12, 26, 143, 22, 48, 76, 98, 221, 252,
              99, 185, 22, 103, 246, 11, 118, 34, 253, 188, 22, 138, 224, 235, 95, 28, 202, 212, 22, 10, 160, 238,
              245, 211, 71, 35, 22, 192, 120, 153, 68, 53, 189, 46, 22, 214, 75, 232, 151, 239, 5, 79, 22, 239, 12,
              153, 54, 225, 215, 242, 22, 160, 153, 128, 1, 204, 30, 104, 22, 232, 41, 104, 63, 118, 84, 10, 22, 253,
              111, 64, 184, 114, 70, 127, 22, 153, 210, 235, 184, 122, 144, 91, 22, 218, 27, 224, 131, 196, 103, 72,
              22, 129, 121, 140, 231, 4, 106, 190, 22, 43, 66, 49, 111, 194, 198, 160, 22, 9, 191, 154, 70, 147, 1,
              223, 22, 44, 14, 68, 46, 224, 182, 26, 22, 104, 47, 139, 206, 60, 198, 225, 22, 179, 156, 27, 90, 27,
              168, 129, 22, 60, 144, 65, 201, 120, 220, 10, 22, 193, 159, 180, 195, 188, 167, 230, 22, 64, 78, 232,
              34, 215, 158, 114, 22, 155, 122, 238, 251, 17, 248, 8, 22, 190, 63, 121, 106, 182, 86, 15, 22, 159,
              131, 193, 162, 223, 100, 206, 22, 123, 96, 239, 147, 21, 43, 137, 22, 176, 10, 8, 212, 73, 250, 227,
              22, 222, 99, 216, 239, 224, 196, 43, 22, 11, 255, 121, 137, 155, 184, 82, 22, 183, 215, 242, 78, 88,
              160, 247, 22, 119, 25, 11, 193, 232, 118, 251, 22, 63, 176, 149, 236, 218, 5, 34, 22, 227, 253, 195,
              72, 56, 9, 122, 22, 170, 56, 61, 63, 69, 174, 241, 22, 88, 163, 64, 193, 24, 23, 194, 22, 41, 181, 113,
              69, 47, 225, 136, 22, 249, 215, 153, 74, 45, 181, 49, 22, 128, 87, 178, 12, 98, 237, 36, 22, 244, 162,
              92, 25, 73, 116, 239, 22, 241, 244, 78, 179, 101, 38, 138, 22, 195, 225, 251, 53, 5, 41, 27, 22, 83,
              107, 237, 240, 152, 132, 114, 22, 175, 214, 154, 60, 101, 207, 181, 22, 30, 227, 4, 11, 149, 24, 218,
              22, 140, 145, 248, 58, 143, 223, 123, 22, 79, 163, 77, 5, 177, 58, 21, 22, 60, 83, 218, 239, 249, 185,
              131, 22, 188, 215, 196, 88, 122, 255, 4, 22, 227, 210, 51, 43, 174, 198, 244, 22, 98, 65, 153, 110,
              101, 197, 156, 22, 243, 193, 172, 186, 132, 23, 163, 22, 163, 187, 149, 27, 234, 188, 241, 22, 41, 164,
              206, 94, 225, 248, 141, 22, 212, 45, 31, 172, 222, 157, 185, 22, 168, 142, 162, 61, 235, 13, 63, 22,
              18, 239, 47, 250, 67, 229, 120, 22, 59, 29, 74, 236, 54, 40, 183, 22, 0, 58, 71, 55, 0, 0, 0, 21, 0, 0,
              0, 0, 0, 157, 41]

##################
# SRT Fagci Reborn
##################

CHAN_MAX = 1024
READ_WRITE_CHANNELS = CHAN_MAX  # This val should be; CHAN_MAX For debbunging purposes,
# this value can be changed to 10 for faster testing (? STILL TRUE??)

SETTINGS_SIZE = 0x001b

PATCH_SIZE = 15832

PATCH_BLOCKS = 1979
# PATCH_SIZE / PATCH_BLOCKS must be an integer!

CH_SIZE = 23

EEPROM_SIZES = [
    8192,  # 000
    8192,  # 001
    8192,  # 010
    16384,  # 011
    32768,  # 100
    65536,  # 101
    131072,  # 110
    262144,  # 111
]

RADIO_LIST = [
    "BK4819",
    "BK1080",
    "SI4732",
    "Preset",
]

BANDWIDTH_LIST = ["25k", "12.5k", "6.25k"]

MODULATION_LIST = ["FM", "AM", "LSB", "USB",
                   "BYP", "RAW", "WFM", "Preset"]

MODULATION_LIST_MAP = ["FM", "AM", "LSB", "USB",
                       "DV", "CW", "WFM", "Auto"]

STEP_NAMES = [
    "0.01kHz",
    "0.1kHz",
    "0.5kHz",
    "1.0kHz",
    "2.5kHz",
    "5.0kHz",
    "6.25kHz",
    "8.33kHz",
    "10.0kHz",
    "12.5kHz",
    "25.0kHz",
    "50.0kHz",
    "100.0kHz",
    "125.0kHz",
    "200.0kHz"
]

UPCONVERTER_TYPES = [
    "UPCONVERTER_OFF",
    "UPCONVERTER_50M",
    "UPCONVERTER_125M"
]

OFFSET_DIRECTION = [
    "NONE",
    "+",
    "-"
]

BACKLIGHT_ON_SQUELCH_MODE = [
    "BL_SQL_OFF",
    "BL_SQL_ON",
    "BL_SQL_OPEN"
]

BATTERY_TYPE = [
    "BAT_1600",
    "BAT_2200",
    "BAT_3500"
]

BATTERY_STYLE = [
    "BAT_CLEAN",
    "BAT_PERCENT",
    "BAT_VOLTAGE"
]

TX_OUTPUT_POWER = [
    "TX_POW_ULOW",
    "TX_POW_LOW",
    "TX_POW_MID",
    "TX_POW_HIGH"
]

RADIO = [
    "RADIO_BK4819",
    "RADIO_BK1080",
    "RADIO_SI4732",
    "RADIO_UNKNOWN"
]

SCAN_TIMEOUT = [
    "0",
    "500ms",
    "1s",
    "3s",
    "5s",
    "10s",
    "30s",
    "1min",
    "2min",
    "5min",
    "NONE"
]

EEPROM_TYPE = [
    "EEPROM_A",
    "EEPROM_B",
    "EEPROM_BL24C64",
    "EEPROM_BL24C128",
    "EEPROM_BL24C256",
    "EEPROM_BL24C512",
    "EEPROM_BL24C1024",
    "EEPROM_M24M02"
]

BL_TIME_VALUES = [0, 5, 10, 20, 60, 120, 255]
BL_TIME_NAMES = ["Off", "5s", "10s", "20s", "1min", "2min", "On"]
BL_TIME_MAP = list(zip(BL_TIME_NAMES, BL_TIME_VALUES))

BL_SQL_MODE_NAMES = ["Off", "On", "Open"]
TX_POWER_NAMES = ["ULow", "Low", "Mid", "High"]
TX_OFFSET_NAMES = ["Unset", "+", "-"]

TX_CODE_TYPES = RX_CODE_TYPES = ["None", "CTCSS", "DCS", "-DCS"]

EEPROM_TYPE_NAMES = [
    "none 1",  # 000
    "none 2",  # 001
    "BL24C64 (stock)",  # 010
    "BL24C128",  # 011
    "BL24C256",  # 100
    "BL24C512",  # 101
    "BL24C1024",  # 110
    "M24M02 (x1)",  # 111
]

APP_LIST = [
    "None",
    "EEPROM view",
    "Spectrum band",
    "Spectrum analyzer",
    "CH Scan",
    "Channels",
    "1 VFO pro",
    "Frequency input",
    "Run app",
    "Loot",
    "Presets",
    "Reset",
    "Text input",
    "VFO config",
    "Preset config",
    "Settings",
    "1 VFO",
    "2 VFO",
    "ABOUT"
]

BATTERY_TYPE_NAMES = ["1600mAh", "2200mAh", "3500mAh"]
BATTERY_STYLE_NAMES = ["Plain", "Percent", "Voltage"]

SCAN_TIMEOUT_NAMES = [
    "0", "500ms", "1s", "3s", "5s", "10s",
    "30s", "1min", "2min", "5min", "None"
]

BOUND_240_280_NAMES = ["Bound 240", "Bound 280"]
VFOs = ["VFO A", "VFO B"]

SQUELCH_TYPE_LIST = ["RNG", "RG", "RN", "R"]

SQL_CLOSE_NAMES = [f"{i}ms" for i in range(0, 15, 5)]

SQL_OPEN_NAMES = [f"{i}ms" for i in range(0, 35, 5)]

# power
UVK5_POWER_LEVELS = [chirp_common.PowerLevel("ULow", watts=0.01),
                     chirp_common.PowerLevel("Low", watts=0.50),
                     chirp_common.PowerLevel("Med", watts=2.00),
                     chirp_common.PowerLevel("High", watts=5.00)]

BANDS = {
    0: [0.153, 10.000],  # for the SI4732
    1: [10.0, 660.0000],
    2: [840.0000, 1340.0000],
    # 2: [137.0, 173.9990],
    # 3: [174.0, 229.9999],
    # 4: [230.0, 319.9999],
    # 5: [320.0, 399.9999],
    # 6: [400.0, 433.0749],
    # 7: [433.0750, 434.7999],
    # 8: [434.8000, 446.00625],
    # 9: [446.00625, 446.19375],
    # 10: [446.2000, 462.5624],
    # 11: [462.5625, 462.7374],
    # 12: [462.7375, 467.5624],
    # 13: [467.5625, 467.7499],
    # 14: [467.7500, 469.9999],
    # 15: [470.0, 620.0],
    # 16: [840.0, 862.9999],
    # 17: [863.0, 869.9999],
    # 18: [870.0, 889.9999],
    # 19: [890.0, 959.9999],
    # 20: [960.0, 1259.9999],
    # 21: [1260.0, 1299.9999],
    # 22: [1260.0, 1340.0]
}

# DEFAULT_BAND_NAMES = [
#     "15-30",
#     "30-64",
#     "64-88",
#     "Bcast FM",
#     "108-118",
#     "Air",
#     "135-144",
#     "2m HAM",
#     "148-174",
#     "174-230",
#     "230-320",
#     "320-400",
#     "400-433",
#     "LPD",
#     "435-446",
#     "PMR",
#     "446-462",
#     "FRS/G462",
#     "462-467",
#     "FRS/G467",
#     "468-470",
#     "470-620",
#     "840-863",
#     "LORA",
#     "870-890",
#     "GSM-900",
#     "960-1260",
#     "23cm HAM",
#     "1.3-1.34",
#     "160m HAM",
#     "80m HAM",
#     "60m HAM",
#     "40m HAM",
#     "20m HAM",
#     "17m HAM",
#     "15m HAM",
#     "12m HAM",
#     "10m HAM"
# ]

TMODES = [None, "Tone", "DTCS", "DTCS"]
ROGER_NAMES = ["None", "Moto", "Tiny", "Call"]

CTCSS_TONES = [
    67.0, 69.3, 71.9, 74.4, 77.0, 79.7, 82.5, 85.4,
    88.5, 91.5, 94.8, 97.4, 100.0, 103.5, 107.2, 110.9,
    114.8, 118.8, 123.0, 127.3, 131.8, 136.5, 141.3, 146.2,
    151.4, 156.7, 159.8, 162.2, 165.5, 167.9, 171.3, 173.8,
    177.3, 179.9, 183.5, 186.2, 189.9, 192.8, 196.6, 199.5,
    203.5, 206.5, 210.7, 218.1, 225.7, 229.1, 233.6, 241.8,
    250.3, 254.1,
]

CTCSS_TONES_NAMES = list(map(str, CTCSS_TONES))

DTCS_CODES = [
    23, 25, 26, 31, 32, 36, 43, 47, 51, 53, 54,
    65, 71, 72, 73, 74, 114, 115, 116, 122, 125, 131,
    132, 134, 143, 145, 152, 155, 156, 162, 165, 172, 174,
    205, 212, 223, 225, 226, 243, 244, 245, 246, 251, 252,
    255, 261, 263, 265, 266, 271, 274, 306, 311, 315, 325,
    331, 332, 343, 346, 351, 356, 364, 365, 371, 411, 412,
    413, 423, 431, 432, 445, 446, 452, 454, 455, 462, 464,
    465, 466, 503, 506, 516, 523, 526, 532, 546, 565, 606,
    612, 624, 627, 631, 632, 654, 662, 664, 703, 712, 723,
    731, 732, 734, 743, 754
]

DTCS_CODES_NAMES = list(map(str, DTCS_CODES))

TXPOWER_LIST = ["ULow", "Low", "Mid", "High"]

MIN_FREQ = 153000
MAX_FREQ = 1399999990

## SETTINGS_VF0_PRESET_SIZE = 0x3d1  #  TERRIBLE hardcoding; should get sizeof(MEM_SETTINGS) ## add 20hex / Preset ##
SETTINGS_VF0_PRESET_SIZE = 0x411  #  TERRIBLE hardcoding; should get sizeof(MEM_SETTINGS)
MEMORY_START_LOWER_LIMIT = SETTINGS_VF0_PRESET_SIZE

BIT_MASK_NAMES = ["--------"]

# Generate elements from "1--------" to "-------8"
for i in range(1, 9):
    BIT_MASK_NAMES.append('-' * (i - 1) + str(i) + '-' * (8 - i))

# Append additional elements
BIT_MASK_NAMES.append("12345678")

BIT_MASK_NAMES.append("Custom")

SSB_PATCHES = ["None", "SSB V1", "Unknown Patch"]

##################
# END Fagci Reborn
##################

READ_SMALL_OFFSET = False

##################
# SRT Memory Map
##################

MEM_SETTINGS = """
struct {
  u8 checkbyte : 5,
     eepromType : 3;
  u8 scrambler : 4, 
     squelch : 4;
  u8 vox : 4,
     batsave : 4;
  u8 txTime : 4,
     backlight : 4;
  u8 currentScanlist : 4,
     micGain  : 4;
  u8 chDisplayMode : 2,
     scanmode : 2,
     roger : 2,
     upconverter : 2;
  u8 dtmfdecode : 1,
     repeaterSte : 1,
     ste : 1,
     busyChannelTxLock : 1,
     keylock : 1,
     beep : 1,
     crossBand : 1,
     dw : 1;
  u8 contrast : 4,
     brightness : 4;
  u8 mainApp : 8;
  u8 presetsCount : 8;
  u8 activePreset : 8;
  ul16 batteryStyle : 2,
       batteryType : 2,
       batteryCalibration: 12;
  u8 sqClosedTimeout : 4,
     sqOpenedTimeout : 4;
  u8 backlightOnSquelch : 2,
     reserved2 : 3,
     si4732PowerOff: 1,
     noListen : 1,
     bound_240_280 : 1;
  u8 scanTimeout : 8;
  u8 activeVFO : 2,
     skipGarbageFrequencies : 1,
     sqlCloseTime : 2,
     sqlOpenTime : 3;
  char nickName[10];
} Settings;
"""

MEM_VF0 = """
struct {
  struct {
    ul32 unused : 1,
      codeType : 4,
      f: 27;
    u8 code;
  } rx;
  struct {
    ul32 unused : 1,
      codeType : 4,
      f: 27;
    u8 code;
  } tx;
  il16  channel;
  u8 radio : 2,
     power : 2,
     modulation : 4;
} VFO[2];
"""

MEM_PRESET = """
struct {
  struct {
    u8 s : 8;
    u8 m : 8;
    u8 e : 8;
  } PowerCalibration;
  ul32 lastUsedFreq_tx_lsb: 5,
       lastUsedFreq_rx: 27;
  ul24 unused: 2,
     lastUsedFreq_tx_msb: 22;
  struct {
    struct {
      ul32 end_lsb: 5,
           start: 27;
      ul24 unused: 2,
         end_msb: 22;
    } FRange;
    char name[10];
    u8 modulation : 4,
       step : 4;
    u8 squelch : 4,
       squelchType : 2,
       bw : 2;
    u8 reserved1 : 3,
       gainIndex : 5;
  } Band;
  u8 memoryBanks : 8;
  u8 unused: 1,
     allowTx : 1,
     radio : 2,
     offsetDir : 2,
     power : 2;
} Preset[33];
"""

MEM_CH = """struct {
  struct {
    ul32 unused : 1,
      codeType : 4,
      f: 27;
    u8 code;
  } rx;
  struct {
    ul32 unused : 1,
      codeType : 4,
      f: 27;
    u8 code;
  } tx;
  char name[10];
  u8 memoryBanks;
  u8 power : 2,
      bw : 2,
      modulation : 4;
  u8  unused: 6,
      radio : 2;
} CH[""" + f"{CHAN_MAX}" + "];\n"


##  NOTE 
##  THIS SHOULD MATCH WITH MEM_PATCH Object Size
PATCH_BLOCK_SIZE, SINGLE_PATCH_VAL = 4, 0xffffffff # patch_data = ul32
#PATCH_BLOCK_SIZE, SINGLE_PATCH_VAL = 2, 0xffff # patch_data = ul16
#PATCH_BLOCK_SIZE, SINGLE_PATCH_VAL = 1, 0xff # patch_data = ul8

PATCH_DATA_BLOCKS_IN_PATCH_BLOCK = int(PATCH_SIZE / PATCH_BLOCKS / PATCH_BLOCK_SIZE)

MEM_PATCH = """struct {
  u32 patch_data[""" + f"{PATCH_DATA_BLOCKS_IN_PATCH_BLOCK}" + """];
} Patch[""" + f"{PATCH_BLOCKS}" + """];
"""

PATCH_DATA_BLOCK_SIZE = int(PATCH_SIZE / PATCH_BLOCKS)

MEM_FORMAT = MEM_SETTINGS + MEM_VF0 + MEM_PRESET

##################
# END Memory Map
##################

ERROR_TIP = ("\n\nPlease ensure that the radio is **NOT** tuned to a frequency that is receiving a signal,"
             " as this can interrupt the upload / download process.\n\nCheck the cable is connected to the radio and"
             " try again. If everything is ok, just try again, sometimes it requires a few tries")

def empty_patch():
    a = {"Patch": []}
    for _ in (range(PATCH_BLOCKS)):
        b = {"patch_data" : []}
        for _ in range(PATCH_DATA_BLOCKS_IN_PATCH_BLOCK):
            b["patch_data"].append(SINGLE_PATCH_VAL)
        a["Patch"].append(b)
    return a
    #return {"Patch": [{"patch_data": [SINGLE_PATCH_VAL] * PATCH_DATA_BLOCKS_IN_PATCH_BLOCK}] * PATCH_BLOCKS}

def transform_to_8bit(num):
    # Initialize an empty list to store the 8-bit integers
    uint8_list = []

    # Loop through each integer in the input list
    for i in range(PATCH_BLOCK_SIZE):
        shift_amount = (PATCH_BLOCK_SIZE - 1 - i) * 8
        uint8_list.append((num >> shift_amount) & 0xFF)

    return uint8_list

def copy_patch(src, dest):
    for i in range(len(src["Patch"])):
        for j in range(len(src["Patch"][i]["patch_data"])):
            patch_block = transform_to_8bit(src["Patch"][i]["patch_data"][j])
            curr_patch_data_block_val = 0
            for k in range(PATCH_BLOCK_SIZE):
                curr_patch_data_block_val |= patch_block[k] << (8 * (PATCH_BLOCK_SIZE - k - 1))
            dest["Patch"][i]["patch_data"][j] = curr_patch_data_block_val

def assign_patch(dest):
    for i in range(len(dest["Patch"])):
        for j in range(len(dest["Patch"][i]["patch_data"])):
            curr_patch_data_ptr = i * PATCH_DATA_BLOCK_SIZE + j * PATCH_BLOCK_SIZE
            curr_patch_data_block_val = 0
            for k in range(PATCH_BLOCK_SIZE):
                curr_patch_data_block_val |= RAW_PATCH_DATA[curr_patch_data_ptr + k] << (8 * (PATCH_BLOCK_SIZE - k - 1))
            # LOG.debug("i=%d, j=%d, p=%d, v=%x" % (i,j,curr_patch_data_ptr,curr_patch_data_block_val))
            dest["Patch"][i]["patch_data"][j] = curr_patch_data_block_val

EMPTY_PATCH_VALUE = empty_patch()
OLD_PATCH_VALUE =  empty_patch()
SSB_V1_PATCH_DATA_VALUE =  empty_patch()
assign_patch(SSB_V1_PATCH_DATA_VALUE)
LOG.debug( SSB_V1_PATCH_DATA_VALUE)
USER_SELECTION_PATCH = {
    "Clear": False,
    "Update" : False
}

def sanitize_str(val):
    """)
    Sanitize the nickname to ensure it contains only allowed characters.
    """
    sanitized_name = re.sub(ALLOWED_CHARS_PATTERN, '', str(val)).strip("\x00\xff\x20") + "\x00"
    return sanitized_name


# function to get only first 9 chars of a string and set the 10th char to string terminator
def sanitize_str_10(val):
    """
     Get only the first 9 characters of a string and set the 10th character to string terminator.
     """
    return val[:9] + '\x00'


def min_max_def(value, min_val, max_val, default):
    """returns value if in bounds or default otherwise"""
    if min_val is not None and value < min_val:
        return default
    if max_val is not None and value > max_val:
        return default
    return value


# --------------------------------------------------------------------------------
# nibble to ascii
def hexasc(data):
    res = data
    if res <= 9:
        return chr(res + 48)
    elif data == 0xA:
        return "A"
    elif data == 0xB:
        return "B"
    elif data == 0xC:
        return "C"
    elif data == 0xD:
        return "D"
    elif data == 0xF:
        return "F"
    else:
        return " "


# --------------------------------------------------------------------------------
# nibble to ascii
def ascdec(data):
    if data == "0":
        return 0
    elif data == "1":
        return 1
    elif data == "2":
        return 2
    elif data == "3":
        return 3
    elif data == "4":
        return 4
    elif data == "5":
        return 5
    elif data == "6":
        return 6
    elif data == "7":
        return 7
    elif data == "8":
        return 8
    elif data == "9":
        return 9
    elif data == "A":
        return 10
    elif data == "B":
        return 11
    elif data == "C":
        return 12
    elif data == "D":
        return 13
    elif data == "F":
        return 15
    else:
        return 14


# --------------------------------------------------------------------------------
# the communication is obfuscated using this fine mechanism
def xorarr(data: bytes):
    tbl = [22, 108, 20, 230, 46, 145, 13, 64, 33, 53, 213, 64, 19, 3, 233, 128]
    x = b""
    r = 0
    for byte in data:
        x += bytes([byte ^ tbl[r]])
        r = (r + 1) % len(tbl)
    return x


# --------------------------------------------------------------------------------
# if this crc was used for communication to AND from the radio, then it
# would be a measure to increase reliability.
# but it's only used towards the radio, so it's for further obfuscation
def calculate_crc16_xmodem(data: bytes):
    poly = 0x1021
    crc = 0x0
    for byte in data:
        crc = crc ^ (byte << 8)
        for i in range(8):
            crc = crc << 1
            if (crc & 0x10000):
                crc = (crc ^ poly) & 0xFFFF
    return crc & 0xFFFF


# --------------------------------------------------------------------------------
def _send_command(serport, data: bytes):
    """Send a command to UV-K5 radio"""
    LOG.debug("Sending command (unobfuscated) len=0x%4.4x:\n%s" %
              (len(data), util.hexprint(data)))

    crc = calculate_crc16_xmodem(data)
    data2 = data + struct.pack("<H", crc)

    command = struct.pack(">HBB", 0xabcd, len(data), 0) + \
              xorarr(data2) + \
              struct.pack(">H", 0xdcba)
    if DEBUG_SHOW_OBFUSCATED_COMMANDS:
        LOG.debug("Sending command (obfuscated):\n%s" % util.hexprint(command))
    try:
        result = serport.write(command)
    except Exception:
        raise errors.RadioError("Error writing data to radio{}".format(ERROR_TIP))
    return result


# --------------------------------------------------------------------------------
def _receive_reply(serport):
    header = serport.read(4)
    if len(header) != 4:
        LOG.warning("Header short read: [%s] len=%i" %
                    (util.hexprint(header), len(header)))
        b = serport.read(400)
        LOG.warning("res: \n\n%s\n\n len=%i" % (util.hexprint(b), len(b)))
        raise errors.RadioError("Header short read{}".format(ERROR_TIP))
    if header[0] != 0xAB or header[1] != 0xCD or header[3] != 0x00:
        b = serport.read(400)
        LOG.warning("res: \n\n%s\n\n len=%i" % (util.hexprint(b), len(b)))
        LOG.warning("Bad response header: %s len=%i" %
                    (util.hexprint(header), len(header)))
        raise errors.RadioError("Bad response header{}".format(ERROR_TIP))

    cmd = serport.read(int(header[2]))
    if len(cmd) != int(header[2]):
        LOG.warning("Body short read: [%s] len=%i" %
                    (util.hexprint(cmd), len(cmd)))
        raise errors.RadioError("Command body short read{}".format(ERROR_TIP))

    footer = serport.read(4)

    if len(footer) != 4:
        LOG.warning("Footer short read: [%s] len=%i" %
                    (util.hexprint(footer), len(footer)))
        raise errors.RadioError("Footer short read{}".format(ERROR_TIP))

    if footer[2] != 0xDC or footer[3] != 0xBA:
        LOG.debug(
            "Reply before bad response footer (obfuscated)"
            "len=0x%4.4x:\n%s" % (len(cmd), util.hexprint(cmd)))
        LOG.warning("Bad response footer: %s len=%i" %
                    (util.hexprint(footer), len(footer)))
        raise errors.RadioError("Bad response footer{}".format(ERROR_TIP))

    if DEBUG_SHOW_OBFUSCATED_COMMANDS:
        LOG.debug("Received reply (obfuscated) len=0x%4.4x:\n%s" %
                  (len(cmd), util.hexprint(cmd)))

    cmd2 = xorarr(cmd)

    LOG.debug("Received reply (unobfuscated) len=0x%4.4x:\n%s" %
              (len(cmd2), util.hexprint(cmd2)))

    return cmd2


# --------------------------------------------------------------------------------
def _getstring(data: bytes, begin, maxlen):
    tmplen = min(maxlen + 1, len(data))
    s = [data[i] for i in range(begin, tmplen)]
    for key, val in enumerate(s):
        if val < ord(' ') or val > ord('~'):
            break
    return ''.join(chr(x) for x in s[0:key])


# --------------------------------------------------------------------------------
def _sayhello(serport):
    hellopacket = b"\x14\x05\x04\x00\x6a\x39\x57\x64"

    tries = 5
    while True:
        LOG.debug("Sending hello packet")
        _send_command(serport, hellopacket)
        o = _receive_reply(serport)
        if (o):
            break
        tries -= 1
        if tries == 0:
            LOG.warning("Failed to initialise radio")
            raise errors.RadioError("Failed to initialize radio{}".format(ERROR_TIP))
    firmware = _getstring(o, 4, 16)
    LOG.info("Found firmware: %s" % firmware)
    return firmware


# --------------------------------------------------------------------------------

def _get_offset(serport, offset, length):
    global OFFSET_SIZE
    if OFFSET_SIZE == 0:
        a = [1]
        while len(a) > 0:
            a = serport.read(512)  # flush the serial port
        readmem = b"\x1b\x05\x08\x00" + \
                  struct.pack("<HBB", 0, MEM_BLOCK, 0) + \
                  b"\x6a\x39\x57\x64"
        _send_command(serport, readmem)
        header = serport.read(4)
        serport.read(512)  # flush the rest of the header
        if len(header) == 4:
            OFFSET_SIZE = 2
            return OFFSET_SIZE
        else:
            readmem = b"\x1b\x05\x0A\x00" + \
                      struct.pack("<IBBBB", 0, MEM_BLOCK, 0, 0, 0) + \
                      b"\x6a\x39\x57\x64"
            _send_command(serport, readmem)
            header = serport.read(4)
            serport.read(512)  # flush the rest of the header
            if len(header) == 4:
                OFFSET_SIZE = 4
                return OFFSET_SIZE
            else:
                raise errors.RadioError("Unable to determine offset size{}".format(ERROR_TIP))
    else:
        return OFFSET_SIZE


def _readmem(serport, offset, length):
    current_offset = _get_offset(serport, 0, 0)
    LOG.debug("Offset_len: %d" % current_offset)

    if current_offset == 2:
        LOG.debug("Sending readmem offset=0x%8.4x len=0x%4.4x" % (offset, length))
        readmem = b"\x1b\x05\x08\x00" + \
                  struct.pack("<HBB", offset, length, 0) + \
                  b"\x6a\x39\x57\x64"
    else:
        LOG.debug("Sending readmem offset=0x%4.4x len=0x%4.4x" % (offset, length))
        readmem = b"\x1b\x05\x0A\x00" + \
                  struct.pack("<IBBBB", offset, length, 0, 0, 0) + \
                  b"\x6a\x39\x57\x64"
    _send_command(serport, readmem)
    o = _receive_reply(serport)
    if DEBUG_SHOW_MEMORY_ACTIONS:
        LOG.debug("readmem Received data len=0x%4.4x:\n%s" %
                  (len(o), util.hexprint(o)))
    if OFFSET_SIZE == 2:
        return o[8:]
    else:
        return o[12:]


# --------------------------------------------------------------------------------
def _writemem(serport, data, offset):
    current_offset = _get_offset(serport, 0, 0)

    LOG.debug("Sending writemem offset=0x%4.4x len=0x%4.4x" %
              (offset, len(data)))

    if DEBUG_SHOW_MEMORY_ACTIONS:
        LOG.debug("writemem sent data offset=0x%4.4x len=0x%4.4x:\n%s" %
                  (offset, len(data), util.hexprint(data)))

    dlen = len(data)
    if current_offset == 2:
        writemem = b"\x1d\x05" + \
                   struct.pack("<BBHBB", dlen + 10, 0, offset, dlen, 0) + \
                   b"\x6a\x39\x57\x64" + data
    else:
        writemem = b"\x1d\x05" + \
                   struct.pack("<BBIBBBB", dlen + 10, 0, offset, dlen, 0, 0, 1) + \
                   b"\x6a\x39\x57\x64" + data

    _send_command(serport, writemem)
    o = _receive_reply(serport)

    LOG.debug("writemem Received data: %s len=%i" % (util.hexprint(o), len(o)))

    if (o[0] == 0x1e
            and
            o[4] == (offset & 0xff)
            and
            o[5] == (offset >> 8) & 0xff):
        return True
    else:
        LOG.warning("Bad data from writemem")
        raise errors.RadioError("Bad response to writemem{}".format(ERROR_TIP))


# --------------------------------------------------------------------------------
def _resetradio(serport):
    resetpacket = b"\xdd\x05\x00\x00"
    _send_command(serport, resetpacket)


def set_mem_struct_from_settings(memory_size):
    (ch_memory_start, ch_memory_end, has_patch, _) = get_mem_addrs_and_meta(memory_size)
    LOG.debug("Memory start: %d, Memory end: %d, has_patch : %d" % (ch_memory_start, ch_memory_end, has_patch))

    global MEM_FORMAT
    mem_ch_with_offset = f"\n#seekto {hex(max(SETTINGS_VF0_PRESET_SIZE, ch_memory_start))};\n" + MEM_CH
    MEM_FORMAT = MEM_SETTINGS + MEM_VF0 + MEM_PRESET + mem_ch_with_offset

    if has_patch:
        mem_patch = f"\n#seekto {hex(ch_memory_end)};\n" + MEM_PATCH
        MEM_FORMAT = MEM_FORMAT + mem_patch
        LOG.debug("Memory format with patch: %s" % MEM_FORMAT)


def get_mem_addrs_and_meta(memory_size):
    has_patch = True
    ch_memory_end = memory_size - PATCH_SIZE  # Determine IF PATCH_SIZE is needed
    ch_memory_start = ch_memory_end - (CH_SIZE * CHAN_MAX)
    max_channels = (ch_memory_end - ch_memory_start) // CH_SIZE

    LOG.debug("Memory size: %d, Memory start: %d, Memory end: %d, has_patch : %d" %
              (memory_size, ch_memory_start, ch_memory_end, has_patch))

    if ch_memory_start <= MEMORY_START_LOWER_LIMIT:  # channels.c# 23
        # Not enough memory for all channels, so we need to adjust the memory, unable to fit Patch
        ch_memory_end = memory_size
        ch_memory_start = ch_memory_end - (CH_SIZE * CHAN_MAX)
        has_patch = False

    if ch_memory_start < SETTINGS_VF0_PRESET_SIZE:
        # Not enough memory for all channels, so we need to adjust the memory, unable to fit Patch
        while ch_memory_start < SETTINGS_VF0_PRESET_SIZE:
            ch_memory_start += CH_SIZE
            max_channels -= 1
        # global CHAN_MAX = READ_WRITE_CHANNELS = max_channels
    LOG.debug("Memory size: %d, Memory start: %d, Memory end: %d, has_patch : %d, max_channels = %d" %
              (memory_size, ch_memory_start, ch_memory_end, has_patch, max_channels))

    return ch_memory_start, ch_memory_end, has_patch, max_channels


# ------------------------------READ Eeprom--------------------------------------------------

def map_values(value, left_min, left_max, right_min, right_max):
    # Figure out how 'wide' each range is
    left_span = left_max - left_min
    right_span = right_max - right_min

    # Convert the left range into a 0-1 range (float)
    value_scaled = float(value - left_min) / float(left_span)

    # Convert the 0-1 range into a value in the right range.
    return right_min + (value_scaled * right_span)


def do_download(radio):
    serport = radio.pipe
    serport.timeout = 0.5
    status = chirp_common.Status()
    status.cur = 0
    status.max = SETTINGS_SIZE
    status.msg = "Getting Firmware Version"
    radio.status_fn(status)

    eeprom = b""
    settings = b""
    f = _sayhello(serport)
    if f:
        radio.FIRMWARE_VERSION = f
    else:
        raise errors.RadioError('Unable to determine firmware version')

    sett = 0

    while sett < SETTINGS_SIZE:
        o = _readmem(serport, sett, MEM_BLOCK)
        status.cur = sett
        radio.status_fn(status)

        if o and len(o) == MEM_BLOCK:
            settings += o
            sett += MEM_BLOCK
        else:
            raise errors.RadioError("Memory download incomplete")

    status.msg = "Downloading Settings from radio"
    settings_mmap = memmap.MemoryMapBytes(settings)
    settings_parsed = bitwise.parse(MEM_SETTINGS, settings_mmap)
    eeprom_type = settings_parsed["Settings"]['eepromType']
    memory_size = EEPROM_SIZES[eeprom_type]
    LOG.debug(settings_parsed)

    (ch_memory_start, ch_memory_end, has_patch, max_channels) = get_mem_addrs_and_meta(memory_size)

    LOG.debug("EEPROM type: %d, memory size: %d, memory start: %d, memory end: %d" % (
        eeprom_type, memory_size, ch_memory_start, ch_memory_end))
    set_mem_struct_from_settings(memory_size)

    addr = 0
    status.cur = 0
    status.max = memory_size
    status.msg = f"Downloading Config from radio"

    current_offset = _get_offset(serport, 0, 0)
    if current_offset == 2 and memory_size > 65536:
        raise errors.RadioError(
            "Radio's UART driver has 4 byte offset but memory size is bigger than 512kb\n\nPlease update the firmware (it will be released after 12/08/2024)\n\nMeanwhile just set a smaller memory in the radio (max 512kb)")
    LOG.debug("current_offset: %d, memory_size: %d" % (current_offset, memory_size))

    while addr < SETTINGS_VF0_PRESET_SIZE:
        o = _readmem(serport, addr, MEM_BLOCK)
        status.cur = addr
        radio.status_fn(status)

        if o and len(o) == MEM_BLOCK:
            eeprom += o
            addr += MEM_BLOCK
        else:
            raise errors.RadioError("Config download incomplete")

    status.msg = f"Skipping Empty Bytes"

    while addr < ch_memory_end - (CH_SIZE * READ_WRITE_CHANNELS + MEM_BLOCK):  # WWHHYHYYYY + MEM_BLOCK ?!?!?!?!!?!?!
        o = bytes([0] * MEM_BLOCK)
        status.cur = addr
        radio.status_fn(status)

        if o and len(o) == MEM_BLOCK:
            eeprom += o
            addr += MEM_BLOCK
        else:
            raise errors.RadioError("Empty bytes download incomplete.. WTF??")

    status.msg = f"Downloading Channels from radio"
    while addr < ch_memory_end:
        o = _readmem(serport, addr, MEM_BLOCK)
        status.cur = addr

        status.msg = f"Downloading Channels ({max(0, int(map_values(addr, ch_memory_start, ch_memory_end, 0, max_channels)))} / {max_channels})"
        radio.status_fn(status)
        if o and len(o) == MEM_BLOCK:
            eeprom += o
            addr += MEM_BLOCK
        else:
            raise errors.RadioError("Memory download incomplete")

    status.msg = f"Downloading Patch from radio"
    if has_patch:
        while addr < EEPROM_SIZES[eeprom_type]:
            o = _readmem(serport, addr, MEM_BLOCK)
            status.cur = addr
            status.msg = f"Downloading Patch ({addr - ch_memory_end} / {PATCH_SIZE})"
            radio.status_fn(status)

            if o and len(o) == MEM_BLOCK:
                eeprom += o
                addr += MEM_BLOCK
            else:
                raise errors.RadioError("Patch download incomplete")

    return memmap.MemoryMapBytes(eeprom)


# -------------------------------WRITE EEprom-------------------------------------------------
def do_upload(radio):
    serport = radio.pipe
    serport.timeout = 0.5
    status = chirp_common.Status()
    status.cur = 0
    memory_size = EEPROM_SIZES[radio._memobj.Settings.eepromType]
    (ch_memory_start, ch_memory_end, has_patch, max_channels) = get_mem_addrs_and_meta(memory_size)
    status.max = memory_size

    status.msg = "Uploading VFO Setting to radio"
    radio.status_fn(status)

    current_offset = _get_offset(serport, 0, 0)
    if current_offset == 2 and memory_size > 65536:
        raise errors.RadioError(
            "Radio's UART driver has 4 byte offset but memory size is bigger than 512kb\n\nPlease update the firmware (it will be released after 12/08/2024)\n\nMeanwhile just set a smaller memory in the radio (max 512kb)")
    LOG.debug("current_offset: %d, memory_size: %d" % (current_offset, memory_size))

    f = _sayhello(serport)
    if f:
        radio.FIRMWARE_VERSION = f
    else:
        return False
    # ---------------Write setting
    addr = 0
    status.msg = "Uploading Settings, VFO, Presets to radio"
    while addr < SETTINGS_VF0_PRESET_SIZE:
        o = radio.get_mmap()[addr:addr + MEM_BLOCK]
        _writemem(serport, o, addr)
        status.cur = addr
        radio.status_fn(status)
        if o:
            addr += MEM_BLOCK
        else:
            raise errors.RadioError("Upload Settings, VFO, Presets incomplete")

    # ----------------Empty, just for a nice scrollbar :)
    status.msg = ":) 73s from IU0QWJ :)"
    while addr < ch_memory_start - MEM_BLOCK:  # WWWWWWWWHY - MEM_BLOCK ?!?!?!?!!?!?!
        o = radio.get_mmap()[addr:addr + MEM_BLOCK]
        #  _writemem(serport, o, addr)
        status.cur = addr
        radio.status_fn(status)
        if o:
            addr += MEM_BLOCK
        else:
            raise errors.RadioError("Change your PC, this is not possible; ")

    # ----------------Write Mems
    status.msg = "Uploading Channels (0)"

    while addr < ch_memory_end:
        o = radio.get_mmap()[addr:addr + MEM_BLOCK]
        _writemem(serport, o, addr)
        status.cur = addr
        radio.status_fn(status)
        status.msg = f"Uploading Channels ({max(0, int(map_values(addr, ch_memory_start, ch_memory_end, 0, max_channels)))} / {max_channels})"
        if o:
            addr += MEM_BLOCK
        else:
            raise errors.RadioError("Memory upload incomplete")

    # ----------------Write Patch
    if has_patch:
        status.msg = "Uploading Patch"

        while addr < memory_size:
            o = radio.get_mmap()[addr:addr + MEM_BLOCK]
            _writemem(serport, o, addr)
            status.cur = addr
            radio.status_fn(status)
            status.msg = f"Uploading Patch ({addr - ch_memory_end} / {PATCH_SIZE})"
            if o:
                addr += MEM_BLOCK
            else:
                raise errors.RadioError("Memory upload incomplete")

    status.msg = "Upload OK"

    _resetradio(serport)

    return True


# --------------------------------------------------------------------------------
def _find_band(hz):
    mhz = hz / 1000000.0

    B = BANDS

    for a in B:
        if mhz >= B[a][0] and mhz <= B[a][1]:
            return a

    return False


def bit_loc(bitnum):
    """
    return the ndx and mask for a bit location
    """
    return (bitnum // 8, 1 << (bitnum & 7))


def store_bit(ch, bank, val):
    """
    store a bit in a bankmem. Store 0 or 1 for False or True
    """
    banknum = bank.index
    ndx, mask = bit_loc(banknum)
    if val:
        ch.memoryBanks |= mask
    else:
        ch.memoryBanks &= ~mask
    return


def retrieve_bit(ch, bank):
    """
    return True or False for a bit in a bankmem
    """
    banknum = bank.index
    ndx, mask = bit_loc(banknum)
    return (ch.memoryBanks & mask) != 0


class FagciBankModel(chirp_common.BankModel):

    def get_num_mappings(self):
        return 8

    def get_mappings(self):
        banks = []
        for i in range(1, 1 + self.get_num_mappings()):
            bank = chirp_common.Bank(self, "%i" % i, "Scan List ")
            bank.index = i - 1
            banks.append(bank)
        return banks

    def add_memory_to_mapping(self, memory, bank):
        chan_max = self._radio.get_features().memory_bounds[1]
        store_bit(self._radio._memobj.CH[chan_max - memory.number], bank, True)
        LOG.debug("Memory %i added to %s." % (memory.number, memory))
        LOG.debug(memory)
        _mem = self._radio._memobj.CH[chan_max - memory.number]
        memory_banks = self._radio._match_memory_banks(_mem.memoryBanks)
        memory.extra.memoryBanks = memory_banks

    def remove_memory_from_mapping(self, memory, bank):
        chan_max = self._radio.get_features().memory_bounds[1]
        if not retrieve_bit(self._radio._memobj.CH[chan_max - memory.number], bank):
            raise Exception("Memory %i is not in %s." % (memory.number, bank))

        store_bit(self._radio._memobj.CH[chan_max - memory.number], bank, False)
        self._radio.get_memory(chan_max - memory.number)
        _mem = self._radio._memobj.CH[chan_max - memory.number]
        memory_banks = self._radio._match_memory_banks(_mem.memoryBanks)
        memory.extra.memoryBanks = memory_banks

    # return a list of slots in a bank
    def get_mapping_memories(self, bank):
        memories = []
        chan_max = self._radio.get_features().memory_bounds[1]
        for i in range(*self._radio.get_features().memory_bounds):
            if retrieve_bit(self._radio._memobj.CH[chan_max - i - 1], bank):
                memories.append(self._radio.get_memory(chan_max - i - 1))
        return memories

    # return a list of banks a slot is a member of
    def get_memory_mappings(self, memory):
        chan_max = self._radio.get_features().memory_bounds[1]
        banks = []
        # LOG.debug(self._radio._memobj.CH[chan_max - memory.number].memoryBanks)
        for bank in self.get_mappings():
            if retrieve_bit(self._radio._memobj.CH[chan_max - memory.number], bank):
                banks.append(bank)
        return banks


def set_tx_code(_mem, curr_vfo, i, v):
    # tx_code
    key_name = f"vfo{i}_tx_code"
    tx_code = int(curr_vfo.tx.code)
    tx_codeType = int(_mem.VFO[i].tx.codeType)
    if (key_name in v):
        del v[key_name]
    if TX_CODE_TYPES[tx_codeType] == "CTCSS":
        if tx_code >= len(CTCSS_TONES):
            tx_code = 0
        v.append(RadioSetting(key_name, "TX Code",
                              RadioSettingValueList(CTCSS_TONES_NAMES, CTCSS_TONES_NAMES[tx_code]))
                 )
    elif TX_CODE_TYPES[tx_codeType] == "DCS" or TX_CODE_TYPES[tx_codeType] == "-DCS":
        if tx_code >= len(DTCS_CODES):
            tx_code = 0
        v.append(RadioSetting(key_name, "TX Code",
                              RadioSettingValueList(DTCS_CODES_NAMES, DTCS_CODES_NAMES[tx_code]))
                 )
    else:
        rs = RadioSettingValueString(0, 0, "")
        rs.set_mutable(False)
        v.append(RadioSetting(key_name, "TX Code", rs))


def set_rx_code(_mem, curr_vfo, i, v):
    # rx_code
    key_name = f"vfo{i}_rx_code"
    rx_code = int(curr_vfo.rx.code)
    rx_code_type = int(_mem.VFO[i].rx.codeType)
    if RX_CODE_TYPES[rx_code_type] == "CTCSS":
        if rx_code >= len(CTCSS_TONES):
            rx_code = 0
        v.append(RadioSetting(key_name, "RX Code",
                              RadioSettingValueList(CTCSS_TONES_NAMES, CTCSS_TONES_NAMES[rx_code]))
                 )
    elif RX_CODE_TYPES[rx_code_type] == "DCS" or RX_CODE_TYPES[rx_code_type] == "-DCS":
        if rx_code >= len(DTCS_CODES):
            rx_code = 0
        v.append(RadioSetting(key_name, "RX Code",
                              RadioSettingValueList(DTCS_CODES_NAMES, DTCS_CODES_NAMES[rx_code]))
                 )
    else:
        rs = RadioSettingValueString(0, 0, "")
        rs.set_mutable(False)
        v.append(RadioSetting(key_name, "RX Code", rs))


@directory.register
class UVK5Radio(chirp_common.CloneModeRadio):
    """Quansheng UV-K5"""
    VENDOR = "Quansheng"
    MODEL = "UV-K5"
    VARIANT = "FAGCI-REBORN"
    BAUD_RATE = 38400
    NEEDS_COMPAT_SERIAL = False
    FIRMWARE_VERSION = "300"
    _expanded_limits = True

    def get_bank_model(self):
        return FagciBankModel(self)

    # --------------------------------------------------------------------------------
    def get_prompts(x=None):
        rp = chirp_common.RadioPrompts()
        rp.experimental = _(
            'This is an experimental driver for the Quansheng UV-K5. '
            'It may harm your radio, or worse. Use at your own risk.\n\n'
            'Before attempting to do any changes please download '
            'the memory image from the radio with chirp '
            'and keep it. This can be later used to recover the '
            'original settings. \n\n'
            'some details are not yet implemented')
        rp.pre_download = _(
            "1. Turn radio on.\n"
            "2. Connect cable to mic/spkr connector.\n"
            "3. Make sure connector is firmly connected.\n"
            "4. Click OK to download image from device.\n\n"
            "It will may not work if you turn on the radio "
            "with the cable already attached\n")
        rp.pre_upload = _(
            "1. Turn radio on.\n"
            "2. Connect cable to mic/spkr connector.\n"
            "3. Make sure connector is firmly connected.\n"
            "4. Click OK to upload the image to device.\n\n"
            "It will may not work if you turn on the radio "
            "with the cable already attached")
        return rp

    # --------------------------------------------------------------------------------
    # Return information about this radio's features, including
    # how many memories it has, what bands it supports, etc
    def get_features(self):
        rf = chirp_common.RadioFeatures()
        rf.has_bank = True
        rf.has_bank_index = True
        rf.has_rx_dtcs = True
        rf.has_ctone = True
        rf.has_settings = True
        rf.has_comment = True
        rf.has_nostep_tuning = True
        rf.has_tuning_step = False
        rf.valid_dtcs_codes = DTCS_CODES
        rf.valid_name_length = 10
        rf.valid_power_levels = UVK5_POWER_LEVELS
        #rf.valid_duplexes = ["", "off", "-", "+"]
        #rf.valid_tuning_steps = STEPS
        rf.valid_tmodes = ["", "Tone", "TSQL", "DTCS", "Cross"]
        rf.valid_cross_modes = ["Tone->Tone", "Tone->DTCS", "DTCS->Tone", "->Tone", "->DTCS", "DTCS->", "DTCS->DTCS"]
        rf.valid_characters = chirp_common.CHARSET_ASCII
        rf.valid_modes = MODULATION_LIST_MAP
        rf.valid_tuning_steps = []

        # rf.valid_skips = ["", "S"]
        rf.valid_skips = []
        rf._expanded_limits = True
        rf.memory_bounds = (1, self.max_channels)

        for a in BANDS:
            rf.valid_bands.append(
                (
                    int(BANDS[a][0] * 1000000),
                    int(BANDS[a][1] * 1000000)
                )
            )
        return rf

    # --------------------------------------------------------------------------------
    # Do a download of the radio from the serial port
    def sync_in(self):
        self._mmap = do_download(self)
        self.process_mmap()
        

    # --------------------------------------------------------------------------------
    # Do an upload of the radio to the serial port
    def sync_out(self):
        do_upload(self)

    # --------------------------------------------------------------------------------
    # Convert the raw byte array into a memory object structure
    def process_mmap(self):

        settings_parsed = bitwise.parse(MEM_SETTINGS, self._mmap)
        eeprom_type = settings_parsed["Settings"]['eepromType']
        memory_size = EEPROM_SIZES[eeprom_type]
        set_mem_struct_from_settings(memory_size)
        self._memobj = bitwise.parse(MEM_FORMAT, self._mmap)
        (_, _, has_patch, max_channels) = get_mem_addrs_and_meta(memory_size)
        self.max_channels = max_channels
        if has_patch:
            copy_patch(self._memobj, OLD_PATCH_VALUE)
        # # This code works, But is what we want?
        # real_bands = [(10.0000, 660.0000), (840.0000, 1340.0000)]
        # for i in range(0, len(self._memobj.Preset)):
        #     curr_pr = self._memobj.Preset[i]
        #     start_freq = curr_pr.Band.FRange.start * 10
        #     end_freq = curr_pr.Band.FRange.end_msb << 5 | curr_pr.Band.FRange.end_lsb * 10
        #     real_bands = (start_freq/ 1000 / 1000, end_freq / 1000 / 1000)
        # chirp_common.RadioFeatures().valid_bands = real_bands

    # --------------------------------------------------------------------------------
    # Return a raw representation of the memory object, which
    # is very helpful for development
    def get_raw_memory(self, number):
        return repr(self._memobj.CH[number - 1])

    # --------------------------------------------------------------------------------
    def validate_memory(self, mem):
        msgs = super().validate_memory(mem)

        if mem.name == "" or mem.name == "<new>":
            mem.name = f"{(mem.freq / 1000 / 1000):.4f}"
            self._memobj.CH[self.max_channels - mem.number].memoryBanks = 0x00

        if mem.duplex not in ['', "-", "+"]:
            msgs.append(chirp_common.ValidationError("Invalid duplex setting: %s" % mem.duplex))

        # find tx frequency
        if mem.duplex == '-':
            txfreq = mem.freq - mem.offset
        elif mem.duplex == '+':
            txfreq = mem.freq + mem.offset
        else:
            txfreq = mem.freq

        # find band
        band = _find_band(txfreq)
        if band is False:
            msg = "Transmit frequency %.4f MHz is not supported by this radio" % (txfreq / 1000000.0)
            msgs.append(chirp_common.ValidationError(msg))

        band = _find_band(mem.freq)
        if band is False:
            msg = "The frequency %.4f MHz is not supported by this radio" % (mem.freq / 1000000.0)
            msgs.append(chirp_common.ValidationError(msg))

        return msgs

    # --------------------------------------------------------------------------------
    def _set_tone(self, mem, _mem):
        ((txmode, txtone, txpol),
         (rxmode, rxtone, rxpol)) = chirp_common.split_tone_encode(mem)

        if txmode == "Tone":
            txmoval = TX_CODE_TYPES.index("CTCSS")
            txtoval = CTCSS_TONES.index(txtone)
        elif txmode == "DTCS":
            txmoval = txpol == "R" and TX_CODE_TYPES.index("-DCS") or TX_CODE_TYPES.index("DCS")
            txtoval = DTCS_CODES.index(txtone)
        else:
            txmoval = TX_CODE_TYPES.index("None")
            txtoval = 0

        if rxmode == "Tone":
            rxmoval = RX_CODE_TYPES.index("CTCSS")
            rxtoval = CTCSS_TONES.index(rxtone)
        elif rxmode == "DTCS":
            rxmoval = rxpol == "R" and RX_CODE_TYPES.index("-DCS") or RX_CODE_TYPES.index("DCS")
            rxtoval = DTCS_CODES.index(rxtone)
        else:
            rxmoval = RX_CODE_TYPES.index("None")
            rxtoval = 0

        _mem.rx.codeType = rxmoval
        _mem.tx.codeType = txmoval
        _mem.rx.code = rxtoval
        _mem.tx.code = txtoval

    # --------------------------------------------------------------------------------
    def _get_tone(self, mem, _mem):
        rx_pol = None
        tx_pol = None

        rxtype = _mem.rx.codeType
        txtype = _mem.tx.codeType

        if rxtype >= len(TMODES):
            rxtype = 0
        rx_tmode = TMODES[rxtype]

        if txtype >= len(TMODES):
            txtype = 0
        tx_tmode = TMODES[txtype]

        rx_tone = tx_tone = "None"

        if tx_tmode == "Tone":
            if _mem.tx.code < len(CTCSS_TONES):
                tx_tone = CTCSS_TONES[_mem.tx.code]
            else:
                tx_tone = 0
        elif tx_tmode == "DTCS":
            if _mem.tx.code < len(DTCS_CODES):
                tx_tone = DTCS_CODES[_mem.tx.code]
                tx_pol = TX_CODE_TYPES[txtype] == "DCS" and "N" or "R"
            else:
                tx_tone = 0

        if rx_tmode == "Tone":
            if _mem.rx.code < len(CTCSS_TONES):
                rx_tone = CTCSS_TONES[_mem.rx.code]
            else:
                rx_tone = 0
        elif rx_tmode == "DTCS":
            if _mem.rx.code < len(DTCS_CODES):
                rx_tone = DTCS_CODES[_mem.rx.code]
                rx_pol = RX_CODE_TYPES[rxtype] == "DCS" and "N" or "R"
            else:
                rx_tone = 0

        tx_tmode = TMODES[txtype]
        rx_tmode = TMODES[rxtype]

        chirp_common.split_tone_decode(mem, (tx_tmode, tx_tone, tx_pol), (rx_tmode, rx_tone, rx_pol))

    def _match_memory_banks(self, memory_banks):
        if memory_banks == 0:
            return "--------"
        elif memory_banks == 0xFF:
            return "12345678"
        elif bin(memory_banks).count('1') == 1:
            result = []
            for i in range(8):
                if memory_banks & (1 << i):
                    result.append(str(i + 1))
                else:
                    result.append('-')
            return ''.join(result)
        else:
            return "Custom"

    def set_bits_from_string(self, bit_string, value):
        if bit_string == "Custom":
            return value
        else:
            value = 0

        if bit_string == "--------":
            return 0
        elif bit_string == "12345678":
            return 0xFF
        else:
            for i, char in enumerate(bit_string):
                if char != '-':
                    value |= (1 << (i))
        return value

    # --------------------------------------------------------------------------------
    # Extract a high-level memory object from the low-level memory map
    # This is called to populate a memory in the UI
    def get_memory(self, number2):

        _mem = self._memobj
        mem = chirp_common.Memory()
        number = self.max_channels - number2
        mem.number = self.max_channels - number
        _mem = self._memobj.CH[number]

        # if number > (self.max_channels - 1):
        #     mem.immutable = ["name", "scanlists"]
        # else:
        for char in _mem.name:
            if str(char) == "\xFF" or str(char) == "\x00":
                break
            mem.name += str(char)

        tag = mem.name.strip()
        mem.name = tag

        is_empty = False
        # We'll consider any blank (i.e. 0 MHz frequency) to be empty
        if (_mem.rx.f == 0xffffffff) or (_mem.rx.f == 0) or (_mem.rx.f == 0x7FFFFFF) or mem.name == "":
            is_empty = True

        if is_empty:
            mem.empty = True
            # set some sane defaults:
            mem.power = UVK5_POWER_LEVELS[0]
            mem.extra = RadioSettingGroup("Extra", "extra")

            rs = RadioSetting("radio", "Radio", RadioSettingValueList(RADIO_LIST, RADIO_LIST[0]))
            mem.extra.append(rs)

            rs = RadioSetting("bandwidth", "Bandwidth", RadioSettingValueList(BANDWIDTH_LIST, BANDWIDTH_LIST[1]))
            mem.extra.append(rs)

            mem.duplex = ""
            mem.mode = MODULATION_LIST_MAP[0]
            mem.offset = 0

            return mem

        # Convert your low-level frequency to Hertz
        mem.freq = int(_mem.rx.f) * 10
        freq_tx = int(_mem.tx.f) * 10
        offset = 0 if freq_tx == 0 or (_mem.tx.f == 0x7FFFFFF) else int(freq_tx - mem.freq)

        # LOG.debug(f"name: {mem.name}, mem.freq: {mem.freq}, freq_tx: {freq_tx}, mem.offset: {mem.offset}")

        if offset == 0:
            mem.duplex = ''
        elif offset < 0:
            mem.duplex = '-'
        else:
            mem.duplex = '+'

        mem.offset = abs(offset)
        # tone data
        self._get_tone(mem, _mem)

        # mode
        if _mem.modulation >= len(MODULATION_LIST_MAP):
            mem.mode = MODULATION_LIST_MAP[0]
        else:
            mem.mode = MODULATION_LIST_MAP[_mem.modulation]

        # power
        if _mem.power >= len(UVK5_POWER_LEVELS):
            mem.power = UVK5_POWER_LEVELS[0]
        else:
            mem.power = UVK5_POWER_LEVELS[_mem.power]

        # We'll consider any blank (i.e. 0 MHz frequency) to be empty
        if (_mem.rx.f == 0xffffffff) or (_mem.rx.f == 0) or (_mem.rx.f == 0x7fffffff) or mem.name == "":
            mem.empty = True
        else:
            mem.empty = False

        mem.extra = RadioSettingGroup("Extra", "extra")

        # bandwidth
        bwidth = _mem.bw
        if bwidth >= len(BANDWIDTH_LIST):
            bwidth = 0
        rs = RadioSetting("bandwidth", "Bandwidth", RadioSettingValueList(BANDWIDTH_LIST, BANDWIDTH_LIST[bwidth]))
        mem.extra.append(rs)

        radio = _mem.radio
        rs = RadioSetting("radio", "Radio", RadioSettingValueList(RADIO_LIST, RADIO_LIST[radio]))
        mem.extra.append(rs)

        memory_banks = self._match_memory_banks(_mem.memoryBanks)
        memory_banks_idx = BIT_MASK_NAMES.index(memory_banks)
        rs = RadioSetting("memoryBanks", "Memory Banks",
                          RadioSettingValueList(BIT_MASK_NAMES, BIT_MASK_NAMES[memory_banks_idx]))
        mem.extra.append(rs)

        #LOG.debug("Setting memory #%d banks to %s" % (number, memory_banks))

        return mem

    # --------------------------------------------------------------------------------
    # Store details about a high-level memory to the memory map
    # This is called when a user edits a memory in the UI
    def set_memory(self, mem):

        number = self.max_channels - mem.number

        if number > self.max_channels:
            return mem

        # Get a low-level memory object mapped to the image
        _mem = self._memobj.CH[number]

        old_rx_freq = _mem.rx.f
        # frequency/offset
        _mem.rx.f = int(mem.freq / 10)
        rx_delta = old_rx_freq - _mem.rx.f
        # _mem.tx.f = mem.freq / 10
        # _mem.offset = mem.offset / 10

        LOG.debug(
            f"mem.freq: {mem.freq}, _mem.rx.f: {int(_mem.rx.f)} mem.duplex: {mem.duplex}, "
            f"_mem.tx.f: {int(_mem.tx.f)}, mem.offset: {mem.offset}"
        )

        if mem.duplex == '-':
            _mem.tx.f = int(_mem.rx.f - mem.offset / 10)
            # _mem.tx.f += rx_delta  # FIXME: this is a hack to keep the offset the same, but it's not working
        elif mem.duplex == '+':
            _mem.tx.f = int(_mem.rx.f + mem.offset / 10)
            # _mem.tx.f += rx_delta  # FIXME: this is a hack to keep the offset the same, but it's not working
        elif mem.duplex == '':
            _mem.tx.f = 0

        _mem.tx.f += rx_delta

        LOG.debug(
            f"mem.freq: {mem.freq}, _mem.rx.f: {int(_mem.rx.f)} mem.duplex: {mem.duplex}, "
            f"_mem.tx.f: {int(_mem.tx.f)},  mem.offset: {mem.offset}"
        )

        # name
        tag = mem.name.ljust(10)
        if mem.freq == 0:
            _mem.name = b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
            return mem
        _mem.name = sanitize_str_10(tag)

        # tone data
        self._set_tone(mem, _mem)

        # tx power
        if str(mem.power) == str(UVK5_POWER_LEVELS[3]):
            _mem.power = TXPOWER_LIST.index("High")
        elif str(mem.power) == str(UVK5_POWER_LEVELS[2]):
            _mem.power = TXPOWER_LIST.index("Mid")
        elif str(mem.power) == str(UVK5_POWER_LEVELS[1]):
            _mem.power = TXPOWER_LIST.index("Low")
        else:
            _mem.power = TXPOWER_LIST.index("ULow")
        _mem.modulation = MODULATION_LIST_MAP.index(mem.mode)

        for setting in mem.extra:
            sname = setting.get_name()
            svalue = setting.value.get_value()

            # LOG.debug(f"---------------------\n-------------------\n------------------\nSetting: {sname} Value: {svalue}\n-----------------\n---------------------\n-----------------")

            if sname == "bandwidth":
                _mem.bw = BANDWIDTH_LIST.index(svalue)

            if sname == "radio":
                _mem.radio = RADIO_LIST.index(svalue)

            if sname == "memoryBanks":
                _mem.memoryBanks = self.set_bits_from_string(svalue, _mem.memoryBanks)
        LOG.debug("--------------end of set_memory-----------------")
        return mem

    # --------------------------------------------------------------------------------
    def get_settings(self):
        _mem = self._memobj
        (_, _, has_patch, _) = get_mem_addrs_and_meta(EEPROM_SIZES[_mem.Settings.eepromType])

        basic = RadioSettingGroup("basic", "Basic Settings")
        radio_settings = RadioSettingGroup("radio_settings", "Radio")
        display_battery = RadioSettingGroup("display_battery", "Display & Battery")
        sql = RadioSettingGroup("sql", "SQL")
        patch = RadioSettingGroup("patches", "Patches")

        # --------------------------------------------------------------------------------
        # helper function
        def append_label(radio_setting, label, descr=""):
            if not hasattr(append_label, 'idx'):
                append_label.idx = 0

            append_label_val = RadioSettingValueString(len(descr), len(descr), descr)
            append_label_val.set_mutable(False)
            append_label_rs = RadioSetting("label" + str(append_label.idx), label, append_label_val)
            append_label.idx += 1
            radio_setting.append(append_label_rs)

        # readonly info
        # Firmware
        #firmware = self.metadata.get('uvk5_firmware', 'UNKNOWN')
        firmware = self.FIRMWARE_VERSION

        val = RadioSettingValueString(0, 128, firmware)
        val.set_mutable(False)
        rs = RadioSetting("fw_ver", "Firmware Version", val)
        basic.append(rs)

        # append_label(basic, f"Last Used Freq Offset 1: {_mem.lastUsedFreq_offset_2}")
        # append_label(basic, f"Last Used Freq Offset 2: {_mem.lastUsedFreq_offset_2}")

        ############
        #   VFO    #
        ############
        vfo = []
        for i in range(len(_mem.VFO)):
            curr_vfo = _mem.VFO[i]
            v = RadioSettingGroup(f"vfo{i}", f"VFO {i + 1}")

            #tx_f
            tx = int(curr_vfo.tx.f)
            v.append(
                RadioSetting(f"vfo{i}_tx_f", "TX Frequency", RadioSettingValueInteger(0, MAX_FREQ, tx * 10)))

            #tx_codeType
            tx_codeType = int(curr_vfo.tx.codeType)
            if tx_codeType >= len(TX_CODE_TYPES):
                tx_codeType = 0
            v.append(RadioSetting(f"vfo{i}_tx_codeType", "TX Code Type",
                                  RadioSettingValueList(TX_CODE_TYPES, TX_CODE_TYPES[tx_codeType])))

            set_tx_code(_mem, curr_vfo, i, v)

            #rx_f
            rx = int(curr_vfo.rx.f)
            v.append(
                RadioSetting(f"vfo{i}_rx_f", "RX Frequency", RadioSettingValueInteger(MIN_FREQ, MAX_FREQ, rx * 10)))

            #rx_codeType
            rx_codeType = int(curr_vfo.rx.codeType)
            if rx_codeType >= len(RX_CODE_TYPES):
                rx_codeType = 0
            v.append(RadioSetting(f"vfo{i}_rx_codeType", "RX Code Type",
                                  RadioSettingValueList(RX_CODE_TYPES, RX_CODE_TYPES[rx_codeType])))

            set_rx_code(_mem, curr_vfo, i, v)

            #channel
            channel = curr_vfo.channel
            if channel >= len(_mem.CH) or channel < -1:
                channel = 0
            v.append(RadioSetting(f"vfo{i}_channel", "VFO Channel",
                                  RadioSettingValueInteger(0, self.max_channels, channel + 1)))

            #modulation
            modulation = int(curr_vfo.modulation)
            if modulation >= len(MODULATION_LIST_MAP):
                modulation = 0
            v.append(RadioSetting(f"vfo{i}_modulation", "VFO Modulation",
                                  RadioSettingValueList(MODULATION_LIST_MAP, MODULATION_LIST_MAP[modulation])))

            #power
            power = curr_vfo.power
            if power >= len(UVK5_POWER_LEVELS):
                power = 0
            v.append(RadioSetting(f"vfo{i}_power", "VFO Power",
                                  RadioSettingValueList(TXPOWER_LIST, TXPOWER_LIST[power])))

            #radio
            radio = curr_vfo.radio
            if radio >= len(RADIO_LIST):
                radio = 0
            v.append(RadioSetting(f"vfo{i}_radio", "Radio", RadioSettingValueList(RADIO_LIST, RADIO_LIST[radio])))

            vfo.append(v)
       
        ############
        #  PRESET  #
        ############
        presets = []
        for i in range(len(_mem.Preset)):

            curr_pr = _mem.Preset[i]
            band = curr_pr.Band
            name = sanitize_str(band.name)
            n = str(name).strip("\x20\x00\xff")
            pr = RadioSettingGroup(f"preset{i}", f"Preset {i + 1} ({n})")

            # LOG.debug(f"Processing preset {i}")
            # LOG.debug(f"Current preset: {curr_pr}")

            # PowerCalibration.s
            pr.append(RadioSetting(f"preset{i}_PowerCalibration_s", "Power Calibration S",
                                   RadioSettingValueInteger(0, 255, curr_pr.PowerCalibration.s)))

            # PowerCalibration.m
            pr.append(RadioSetting(f"preset{i}_PowerCalibration_m", "Power Calibration M",
                                   RadioSettingValueInteger(0, 255, curr_pr.PowerCalibration.m)))

            # PowerCalibration.e
            pr.append(RadioSetting(f"preset{i}_PowerCalibration_e", "Power Calibration E",
                                   RadioSettingValueInteger(0, 255, curr_pr.PowerCalibration.e)))

            # start
            start_freq = curr_pr.Band.FRange.start
            start_freq_rs = RadioSettingValueInteger(0, MAX_FREQ, start_freq * 10)
            pr.append(RadioSetting(f"preset{i}_band_start", "Start Frequency", start_freq_rs))

            # end
            end_freq = curr_pr.Band.FRange.end_msb << 5 | curr_pr.Band.FRange.end_lsb
            end_freq_rs = RadioSettingValueInteger(0, MAX_FREQ, end_freq * 10)
            pr.append(RadioSetting(f"preset{i}_band_end", "End Frequency", end_freq_rs))

            # lastUsedFreq_offset_1
            freq1 = curr_pr.lastUsedFreq_rx
            lastUsedFreq_offset_1 = RadioSettingValueInteger(0, MAX_FREQ, freq1 * 10)
            lastUsedFreq_offset_1.set_mutable(False)
            pr.append(RadioSetting(f"preset{i}_lastUsedFreq_rx", "Last Used Freq Rx", lastUsedFreq_offset_1))

            # lastUsedFreq_offset_2
            freq2 = curr_pr.lastUsedFreq_tx_msb << 5 | curr_pr.lastUsedFreq_tx_lsb
            lastUsedFreq_offset_2 = RadioSettingValueInteger(0, MAX_FREQ, freq2 * 10)
            lastUsedFreq_offset_2.set_mutable(False)
            pr.append(RadioSetting(f"preset{i}_lastUsedFreq_tx", "Last Used Freq Tx", lastUsedFreq_offset_2))

            # name
            pr.append(RadioSetting(f"preset{i}_band_name", "Band Name", RadioSettingValueString(0, 9, n)))

            # modulation
            modulation = band.modulation
            if modulation >= len(MODULATION_LIST_MAP):
                modulation = 0
            pr.append(RadioSetting(f"preset{i}_band_modulation", "Band Modulation",
                                   RadioSettingValueList(MODULATION_LIST_MAP, MODULATION_LIST_MAP[modulation])))

            # step
            step = band.step
            if step >= len(STEP_NAMES):
                step = 0
            pr.append(
                RadioSetting(f"preset{i}_band_step", "Band Step", RadioSettingValueList(STEP_NAMES, STEP_NAMES[step])))

            # bw
            bw = band.bw
            if bw >= len(BANDWIDTH_LIST):
                bw = 0
            pr.append(RadioSetting(f"preset{i}_band_bw", "Band Bandwidth",
                                   RadioSettingValueList(BANDWIDTH_LIST, BANDWIDTH_LIST[bw])))

            # squelch Type
            squelch_type = band.squelchType
            if squelch_type >= len(SQUELCH_TYPE_LIST):
                squelch_type = 0
            pr.append(RadioSetting(f"preset{i}_band_squelch_type", "Band Squelch Type",
                                   RadioSettingValueList(SQUELCH_TYPE_LIST, SQUELCH_TYPE_LIST[squelch_type])))

            # sql
            pr.append(RadioSetting(f"preset{i}_band_squelch", "SQL",
                                   RadioSettingValueInteger(0, 15, band.squelch)))

            #gainIndex
            pr.append(RadioSetting(f"preset{i}_band_gainIndex", "Gain Index",
                                   RadioSettingValueInteger(0, math.pow(2, 5) - 1, band.gainIndex)))

            # #reserved1
            # pr.append(RadioSetting("band_reserved1", "Reserved 1",
            #                        RadioSettingValueInteger(0, 255, band.reserved1)))

            #Memory Bank
            pr.append(RadioSetting(f"preset{i}_memoryBanks", "Memory Bank",
                                   RadioSettingValueInteger(0, 255, curr_pr.memoryBanks)))

            #radio
            radio = curr_pr.radio
            if radio >= len(RADIO_LIST):
                radio = 0
            pr.append(RadioSetting(f"preset{i}_radio", "Radio", RadioSettingValueList(RADIO_LIST, RADIO_LIST[radio])))

            #offset dir
            offsetDir = curr_pr.offsetDir
            if offsetDir >= len(OFFSET_DIRECTION):
                offsetDir = 0
            pr.append(RadioSetting(f"preset{i}_offsetDir", "Offset Direction",
                                   RadioSettingValueList(OFFSET_DIRECTION, OFFSET_DIRECTION[offsetDir])))

            #allow Tx
            tmpval = curr_pr.allowTx
            rs = RadioSetting(f"preset{i}_allowTx", "Allow Tx", RadioSettingValueBoolean(bool(tmpval)))
            pr.append(rs)

            #power
            power = curr_pr.power
            if power >= len(TXPOWER_LIST):
                power = 0
            pr.append(
                RadioSetting(f"preset{i}_power", "Power", RadioSettingValueList(TXPOWER_LIST, TXPOWER_LIST[power])))

            presets.append(pr)

        ############
        #  PATCH   #
        ############


        ssb_patch_idx = 2
        
        if has_patch:
            if self.is_none_patched(_mem):
                ssb_patch_idx = 0
            elif self.is_ssb_v1_patched(_mem):
                ssb_patch_idx = 1
          
        val = RadioSettingValueList(SSB_PATCHES, SSB_PATCHES[ssb_patch_idx])
        val.set_mutable(has_patch)
        rs = RadioSetting("ssb_patch", "SSB Patch", val)
        patch.append(rs)

        tmpval = _mem.Settings.checkbyte
        rs = RadioSetting("checkbyte", "Check Byte", RadioSettingValueInteger(0, 31, tmpval))
        basic.append(rs)

        tmpval = _mem.Settings.eepromType
        val = RadioSettingValueList(EEPROM_TYPE, EEPROM_TYPE[tmpval])
        val.set_mutable(False)
        rs = RadioSetting("eepromType", "EPPROM Type", val)
        basic.append(rs)

        tmpval = _mem.Settings.squelch
        rs = RadioSetting("squelch", "Squelch", RadioSettingValueInteger(0, 15, tmpval))
        sql.append(rs)

        tmpval = _mem.Settings.vox
        rs = RadioSetting("vox", "Vox", RadioSettingValueInteger(0, 15, tmpval))
        basic.append(rs)

        tmpval = _mem.Settings.batsave
        rs = RadioSetting("battsave", "Battery Save", RadioSettingValueInteger(0, 15, tmpval))
        display_battery.append(rs)

        tmpval = _mem.Settings.txTime
        rs = RadioSetting("txTime", "Tx Time", RadioSettingValueInteger(0, 15, tmpval))
        radio_settings.append(rs)

        tmpval = _mem.Settings.scrambler
        rs = RadioSetting("scrambler", "Scrambler", RadioSettingValueInteger(0, 15, tmpval))
        radio_settings.append(rs)

        tmpval = _mem.Settings.backlight
        rs = RadioSetting("backlight", "BLmode (TX/RX)",
                          RadioSettingValueList(BL_TIME_NAMES, BL_TIME_NAMES[tmpval])) 
        display_battery.append(rs)

        tmpval = _mem.Settings.currentScanlist
        if tmpval >= 8:
            tmpval = 0
        rs = RadioSetting("currentScanlist", "Current Scan List", RadioSettingValueInteger(1, 8, tmpval + 1))
        basic.append(rs)

        tmpval = _mem.Settings.chDisplayMode
        rs = RadioSetting("chDisplayMode", "Channel Display Mode", RadioSettingValueInteger(0, 3, tmpval))
        basic.append(rs)

        tmpval = _mem.Settings.micGain
        rs = RadioSetting("micGain", "Mic Gain", RadioSettingValueInteger(0, 15, tmpval))
        basic.append(rs)

        tmpval = _mem.Settings.scanmode
        rs = RadioSetting("scanmode", "Scan Mode", RadioSettingValueInteger(0, 3, tmpval))
        basic.append(rs)

        tmpval = _mem.Settings.roger
        rs = RadioSetting("roger", "Roger", RadioSettingValueList(ROGER_NAMES, ROGER_NAMES[tmpval]))
        radio_settings.append(rs)

        tmpval = _mem.Settings.upconverter
        rs = RadioSetting("upconverter", "Upconverter",
                          RadioSettingValueList(UPCONVERTER_TYPES, UPCONVERTER_TYPES[tmpval]))
        radio_settings.append(rs)

        tmpval = _mem.Settings.dtmfdecode
        rs = RadioSetting("dtmfdecode", "DTMF Decode", RadioSettingValueBoolean(bool(tmpval)))
        radio_settings.append(rs)

        tmpval = _mem.Settings.repeaterSte
        rs = RadioSetting("repeaterSte", "RP-STE (Repeater Squelch Tail Eliminator)",
                          RadioSettingValueBoolean(bool(tmpval)))
        radio_settings.append(rs)

        tmpval = _mem.Settings.ste
        rs = RadioSetting("ste", "STE (Squelch Tail Eliminator)", RadioSettingValueBoolean(bool(tmpval)))
        radio_settings.append(rs)

        tmpval = _mem.Settings.busyChannelTxLock
        rs = RadioSetting("busyChannelTxLock", "Busy Channel Lock", RadioSettingValueBoolean(bool(tmpval)))
        radio_settings.append(rs)

        tmpval = _mem.Settings.keylock
        rs = RadioSetting("keylock", "Keylock", RadioSettingValueBoolean(bool(tmpval)))
        basic.append(rs)

        tmpval = _mem.Settings.beep
        rs = RadioSetting("beep", "Beep", RadioSettingValueBoolean(bool(tmpval)))
        basic.append(rs)

        tmpval = _mem.Settings.crossBand
        rs = RadioSetting("crossBand", "CrossBand", RadioSettingValueBoolean(bool(tmpval)))
        radio_settings.append(rs)

        tmpval = _mem.Settings.dw
        rs = RadioSetting("dw", "Dual Watch", RadioSettingValueBoolean(bool(tmpval)))
        radio_settings.append(rs)

        tmpval = _mem.Settings.contrast - 8
        rs = RadioSetting("contrast", "Contrast", RadioSettingValueInteger(-8, 7, tmpval))
        display_battery.append(rs)

        tmpval = _mem.Settings.brightness
        rs = RadioSetting("brightness", "Brightness", RadioSettingValueInteger(0, 15, tmpval))
        display_battery.append(rs)

        tmpval = _mem.Settings.mainApp
        rs = RadioSetting("mainApp", "Main App", RadioSettingValueList(APP_LIST, APP_LIST[tmpval]))
        basic.append(rs)

        tmpval = _mem.Settings.activePreset
        PRESET_NAMES = [re.sub(ALLOWED_CHARS_PATTERN, ' ', str(preset.Band.name)).strip() + "\x00" for preset in
                        _mem.Preset]
        # LOG.debug(f"PRESET_NAMES: {PRESET_NAMES}, activePreset: {tmpval}")
        rs = RadioSetting("activePreset", "Active Preset", RadioSettingValueList(PRESET_NAMES, PRESET_NAMES[tmpval]))
        basic.append(rs)

        tmpval = _mem.Settings.presetsCount
        val = RadioSettingValueInteger(0, 255, tmpval)
        val.set_mutable(False)
        rs = RadioSetting("presetsCount", "Preset Count", val)
        basic.append(rs)

        #Battery
        tmpval = _mem.Settings.batteryStyle
        rs = RadioSetting("batteryStyle", "Battery Style Name",
                          RadioSettingValueList(BATTERY_STYLE_NAMES, BATTERY_STYLE_NAMES[tmpval]))
        display_battery.append(rs)

        tmpval = _mem.Settings.batteryType
        rs = RadioSetting("batteryType", "Battery Type",
                          RadioSettingValueList(BATTERY_TYPE_NAMES, BATTERY_TYPE_NAMES[tmpval]))
        display_battery.append(rs)

        tmpval = _mem.Settings.batteryCalibration
        rs = RadioSetting("batteryCalibration", "Battery Calibration",
                          RadioSettingValueInteger(0, math.pow(2, 12) - 1, tmpval))
        display_battery.append(rs)

        tmpval = _mem.Settings.sqOpenedTimeout
        rs = RadioSetting("sqOpenedTimeout", "SCAN listen time",
                          RadioSettingValueList(SCAN_TIMEOUT_NAMES, SCAN_TIMEOUT_NAMES[tmpval]))
        sql.append(rs)

        tmpval = _mem.Settings.sqClosedTimeout
        rs = RadioSetting("sqClosedTimeout", "SCAN after close timex",
                          RadioSettingValueList(SCAN_TIMEOUT_NAMES, SCAN_TIMEOUT_NAMES[tmpval]))
        sql.append(rs)

        tmpval = _mem.Settings.backlightOnSquelch
        rs = RadioSetting("backlightOnSquelch", "Backlight On Squelch",
                          RadioSettingValueList(BL_SQL_MODE_NAMES, BL_SQL_MODE_NAMES[tmpval]))
        display_battery.append(rs)

        tmpval = _mem.Settings.noListen
        rs = RadioSetting("noListen", "No Listen", RadioSettingValueBoolean(bool(tmpval)))
        basic.append(rs)

        tmpval = _mem.Settings.si4732PowerOff
        rs = RadioSetting("si4732PowerOff", "SI4732 Power Off", RadioSettingValueBoolean(bool(tmpval)))
        basic.append(rs)

        tmpval = _mem.Settings.bound_240_280
        rs = RadioSetting("bound_240_280", "Bound 240 / 280",
                          RadioSettingValueList(BOUND_240_280_NAMES, BOUND_240_280_NAMES[tmpval]))
        radio_settings.append(rs)

        tmpval = _mem.Settings.scanTimeout
        rs = RadioSetting("scanTimeout", "SCAN single freq Time", RadioSettingValueInteger(0, 255, tmpval))
        radio_settings.append(rs)

        tmpval = _mem.Settings.activeVFO
        rs = RadioSetting("activeVFO", "Active VFO", RadioSettingValueList(VFOs, VFOs[tmpval]))
        basic.append(rs)

        tmpval = _mem.Settings.skipGarbageFrequencies
        rs = RadioSetting("skipGarbageFrequencies", "Skip Garbage Frequencies", RadioSettingValueBoolean(bool(tmpval)))
        radio_settings.append(rs)

        tmpval = _mem.Settings.sqlOpenTime
        if tmpval >= len(SQL_OPEN_NAMES):
            tmpval = 0
        rs = RadioSetting("sqlOpenTime", "SQL open time",
                          RadioSettingValueList(SQL_OPEN_NAMES, SQL_OPEN_NAMES[tmpval]))
        sql.append(rs)

        tmpval = _mem.Settings.sqlCloseTime
        if tmpval >= len(SQL_CLOSE_NAMES):
            tmpval = 0
        rs = RadioSetting("sqlCloseTime", "SQL close time",
                          RadioSettingValueList(SQL_CLOSE_NAMES, SQL_CLOSE_NAMES[tmpval]))
        sql.append(rs)

        tmpval = sanitize_str(_mem.Settings.nickName)
        rs = RadioSetting("nickName", "Nick Name", RadioSettingValueString(0, 10, str(tmpval).strip("\x20\x00\xff")))
        basic.append(rs)

        top = RadioSettings(basic, radio_settings, display_battery, sql, patch, *vfo, *presets)
        return top

    # --------------------------------------------------------------------------------

    def is_ssb_v1_patched(self, _mem):
        for i in range(len(_mem.Patch)):
            curr_patch_blocks = _mem.Patch[i].patch_data
            for j in range(len(curr_patch_blocks)):
                test = 0
                curr_patch_data_ptr = i * PATCH_DATA_BLOCK_SIZE + j * PATCH_BLOCK_SIZE
                for k in range(PATCH_BLOCK_SIZE):
                    test |= RAW_PATCH_DATA[curr_patch_data_ptr + k] << (8 * (PATCH_BLOCK_SIZE - k - 1))
                LOG.debug("curr_patch_blocks[j] = %x, test=%x" % (curr_patch_blocks[j],test ))
                if curr_patch_blocks[j] != test:
                    return False
        return True
    
    def is_none_patched(self, _mem):
        for i in range(len(_mem.Patch)):
            curr_patch_blocks = _mem.Patch[i].patch_data
            for j in range(len(curr_patch_blocks)):
                test = 0
                for k in range(PATCH_BLOCK_SIZE):
                    test |= (0xff << (k * 8))
                if curr_patch_blocks[j] != test:
                    return False
        return True

    # --------------------------------------------------------------------------------
    def set_settings(self, settings):

        _mem = self._memobj
        for element in settings:
            if not isinstance(element, RadioSetting):
                self.set_settings(element)
                continue

            if element.get_name() == "checkbyte":
                _mem.Settings.checkbyte = int(element.value)

            if element.get_name() == "eepromType":
                _mem.Settings.eepromType = EEPROM_TYPE.index(element.value)

            if element.get_name() == "squelch":
                _mem.Settings.squelch = int(element.value)

            if element.get_name() == "vox":
                _mem.Settings.vox = int(element.value)

            if element.get_name() == "batsave":
                _mem.Settings.batsave = int(element.value)

            if element.get_name() == "txTime":
                _mem.Settings.txTime = int(element.value)
                
            if element.get_name() == "scrambler":
                _mem.Settings.scrambler = int(element.value)

            if element.get_name() == "backlight":
                _mem.Settings.backlight = BL_TIME_NAMES.index(element.value)

            if element.get_name() == "currentScanlist":
                _mem.Settings.currentScanlist = int(element.value) - 1

            if element.get_name() == "micGain":
                _mem.Settings.micGain = int(element.value)

            if element.get_name() == "chDisplayMode":
                _mem.Settings.chDisplayMode = int(element.value)

            if element.get_name() == "scanmode":
                _mem.Settings.scanmode = int(element.value)

            if element.get_name() == "roger":
                _mem.Settings.roger = ROGER_NAMES.index(element.value)

            if element.get_name() == "upconverter":
                _mem.Settings.upconverter = UPCONVERTER_TYPES.index(element.value)

            if element.get_name() == "dtmfdecode":
                _mem.Settings.dtmfdecode = element.value and 1 or 0

            if element.get_name() == "repeaterSte":
                _mem.Settings.repeaterSte = element.value and 1 or 0

            if element.get_name() == "ste":
                _mem.Settings.ste = element.value and 1 or 0

            if element.get_name() == "busyChannelTxLock":
                _mem.Settings.busyChannelTxLock = element.value and 1 or 0

            if element.get_name() == "keylock":
                _mem.Settings.keylock = element.value and 1 or 0

            if element.get_name() == "beep":
                _mem.Settings.beep = element.value and 1 or 0

            if element.get_name() == "crossBand":
                _mem.Settings.crossBand = element.value and 1 or 0

            if element.get_name() == "dw":
                _mem.Settings.dw = element.value and 1 or 0

            if element.get_name() == "contrast":
                _mem.Settings.contrast = int(element.value) + 8

            if element.get_name() == "brightness":
                _mem.Settings.brightness = int(element.value)

            if element.get_name() == "mainApp":
                _mem.Settings.mainApp = APP_LIST.index(element.value)

            if element.get_name() == "activePreset":
                # Probably this is not the best way to do it; but it works if not changning the preset.Band.name
                PRESET_NAMES = [re.sub(ALLOWED_CHARS_PATTERN, ' ', str(preset.Band.name)).strip() + "\x00" for preset in
                                _mem.Preset]

                _mem.Settings.activePreset = PRESET_NAMES.index(element.value)

            if element.get_name() == "batteryStyle":
                _mem.Settings.batteryStyle = BATTERY_STYLE_NAMES.index(element.value)

            if element.get_name() == "batteryType":
                _mem.Settings.batteryType = BATTERY_TYPE_NAMES.index(element.value)

            if element.get_name() == "batteryCalibration":
                _mem.Settings.batteryCalibration = int(element.value)

            if element.get_name() == "sqClosedTimeout":
                _mem.Settings.sqClosedTimeout = SCAN_TIMEOUT_NAMES.index(element.value)

            if element.get_name() == "sqOpenedTimeout":
                _mem.Settings.sqOpenedTimeout = SCAN_TIMEOUT_NAMES.index(element.value)

            if element.get_name() == "backlightOnSquelch":
                _mem.Settings.backlightOnSquelch = BL_SQL_MODE_NAMES.index(element.value)

            if element.get_name() == "noListen":
                _mem.Settings.noListen = element.value and 1 or 0

            if element.get_name() == "si4732PowerOff":
                _mem.Settings.si4732PowerOff = element.value and 1 or 0

            if element.get_name() == "bound_240_280":
                _mem.Settings.bound_240_280 = BOUND_240_280_NAMES.index(element.value)

            if element.get_name() == "scanTimeout":
                _mem.Settings.scanTimeout = int(element.value)

            if element.get_name() == "activeVFO":
                _mem.Settings.activeVFO = VFOs.index(element.value)

            if element.get_name() == "skipGarbageFrequencies":
                _mem.Settings.skipGarbageFrequencies = element.value and 1 or 0

            if element.get_name() == "sqlCloseTime":
                _mem.Settings.sqlCloseTime = SQL_CLOSE_NAMES.index(element.value)

            if element.get_name() == "sqlOpenTime":
                _mem.Settings.sqlOpenTime = SQL_OPEN_NAMES.index(element.value)

            if element.get_name() == "nickName":
                _mem.Settings.nickName = element.value

            # VFO
            reg_patt = "^vfo(([0-9]){1,2})_"
            if re.search(reg_patt, element.get_name()):
                vfo_idx = int(re.search(reg_patt, element.get_name()).group(1))
                base_vfo_name = f"vfo{vfo_idx}"

                if element.get_name() == f"{base_vfo_name}_tx_f":
                    _mem.VFO[vfo_idx].tx.f = int(element.value) / 10

                if element.get_name() == f"{base_vfo_name}_tx_codeType":
                    #  Needed some logic to update the settings list values
                    _mem.VFO[vfo_idx].tx.codeType = TX_CODE_TYPES.index(element.value)

                if element.get_name() == f"{base_vfo_name}_tx_code":
                    _mem.VFO[vfo_idx].tx.code = int(element.value)

                if element.get_name() == f"{base_vfo_name}_rx_f":
                    _mem.VFO[vfo_idx].rx.f = int(element.value) / 10

                if element.get_name() == f"{base_vfo_name}_rx_codeType":
                    _mem.VFO[vfo_idx].rx.codeType = RX_CODE_TYPES.index(element.value)

                if element.get_name() == f"{base_vfo_name}_rx_code":
                    _mem.VFO[vfo_idx].rx.code = int(element.value)
                    set_rx_code(_mem, _mem.VFO[vfo_idx], vfo_idx, element)

                if element.get_name() == f"{base_vfo_name}_channel":
                    _mem.VFO[vfo_idx].channel = int(element.value) - 1

                if element.get_name() == f"{base_vfo_name}_modulation":
                    _mem.VFO[vfo_idx].modulation = MODULATION_LIST_MAP.index(element.value)

                if element.get_name() == f"{base_vfo_name}_power":
                    _mem.VFO[vfo_idx].power = TX_POWER_NAMES.index(element.value)

                if element.get_name() == f"{base_vfo_name}_radio":
                    _mem.VFO[vfo_idx].radio = RADIO_LIST.index(element.value)

            # Preset
            reg_patt = "^preset(([0-9]){1,2})_"
            if re.search(reg_patt, element.get_name()):
                pr_idx = int(re.search(reg_patt, element.get_name()).group(1))
                base_pr_name = f"preset{pr_idx}"

                if element.get_name() == f"{base_pr_name}_PowerCalibration_s":
                    _mem.Preset[pr_idx].PowerCalibration.s = int(element.value)

                if element.get_name() == f"{base_pr_name}_PowerCalibration_m":
                    _mem.Preset[pr_idx].PowerCalibration.m = int(element.value)

                if element.get_name() == f"{base_pr_name}_PowerCalibration_e":
                    _mem.Preset[pr_idx].PowerCalibration.e = int(element.value)

                if element.get_name() == f"{base_pr_name}_band_start":
                    _mem.Preset[pr_idx].Band.FRange.start = int(element.value) / 10

                if element.get_name() == f"{base_pr_name}_band_end":
                    end = int(int(element.value) / 10)
                    _mem.Preset[pr_idx].Band.FRange.end_msb = (end >> 5) & 0x3FFFFF
                    _mem.Preset[pr_idx].Band.FRange.end_lsb = end & 0x1FF

                    # LOG.debug(
                    #     f"end: {end}, _mem.Preset[pr_idx].Band.FRange.end_msb: {_mem.Preset[pr_idx].Band.FRange.end_msb}, _mem.Preset[pr_idx].Band.FRange.end_lsb: {_mem.Preset[pr_idx].Band.FRange.end_lsb}")

                if element.get_name() == f"{base_pr_name}_band_name":
                    _mem.Preset[pr_idx].Band.name = sanitize_str_10(element.value)

                if element.get_name() == f"{base_pr_name}_band_modulation":
                    _mem.Preset[pr_idx].Band.modulation = MODULATION_LIST_MAP.index(element.value)

                if element.get_name() == f"{base_pr_name}_band_step":
                    _mem.Preset[pr_idx].Band.step = STEP_NAMES.index(element.value)

                if element.get_name() == f"{base_pr_name}_band_bw":
                    _mem.Preset[pr_idx].Band.bw = BANDWIDTH_LIST.index(element.value)

                if element.get_name() == f"{base_pr_name}_band_squelch_type":
                    _mem.Preset[pr_idx].Band.squelchType = SQUELCH_TYPE_LIST.index(element.value)

                if element.get_name() == f"{base_pr_name}_band_squelch":
                    _mem.Preset[pr_idx].Band.squelch = int(element.value)

                if element.get_name() == f"{base_pr_name}_band_gainIndex":
                    _mem.Preset[pr_idx].Band.gainIndex = int(element.value)

                if element.get_name() == f"{base_pr_name}_memoryBanks":
                    _mem.Preset[pr_idx].memoryBanks = int(element.value)

                if element.get_name() == f"{base_pr_name}_radio":
                    _mem.Preset[pr_idx].radio = RADIO_LIST.index(element.value)

                if element.get_name() == f"{base_pr_name}_offsetDir":
                    _mem.Preset[pr_idx].offsetDir = OFFSET_DIRECTION.index(element.value)

                if element.get_name() == f"{base_pr_name}_allowTx":
                    _mem.Preset[pr_idx].allowTx = element.value and 1 or 0

                if element.get_name() == f"{base_pr_name}_power":
                    _mem.Preset[pr_idx].power = TXPOWER_LIST.index(element.value)

            if element.get_name() == f"ssb_patch":
                if (element.value == "SSB V1"):
                    copy_patch(SSB_V1_PATCH_DATA_VALUE, _mem)
                elif (element.value == "None"):
                    copy_patch(EMPTY_PATCH_VALUE, _mem)
                else: 
                    copy_patch(OLD_PATCH_VALUE, _mem)