Color-Encoded Information Protocol
Version 1.1
Table of Contents
- Introduction
- Objectives
- Rationale
- Color to Number Mapping
- Protocol Description
- Special Commands and Message Buffering
- Use Cases
- Future Work and Recommendations
1. Introduction
The Color-Encoded Information Protocol (CEIP) aims to provide a standardized way of representing digital information using LEGO bricks of specific colors. With the integration of 12 distinctive colors, this protocol offers a medium to encode and decode key/value pairs, where the key is an ASCII character, and the value is a number between 0 and 143.
2. Objectives
- Encode key/value pairs where the key is a printable ASCII character, and the value is a number between 0-143.
- Support a buffer for message data.
- Ensure the protocol is human-readable and interpretable.
- Allow the storage of various types of data, including game states and object attributes.
3. Rationale
3.1 Color Term Choices
The protocol utilizes 12 easily distinguishable colors that are universally recognizable and available in LEGO sets.
3.2 Ordering of Color Index
Colors are indexed from 0 to 11 in alphabetical order for ease of standardization and recollection.
3.3 Use of ASCII Characters for Keys
ASCII characters in the printable range (32-126) are used for the keys to ensure wide compatibility and ease of use. They are globally recognized and accommodate a rich variety of symbols and letters.
3.4 Use of Numbers for Values
The values range from 0 to 143. This is intentionally designed to match the 12×12 combinations that can be formed using the 12 unique colors (12 * 12 = 144, ranging from 0 to 143).
3.5 Key/Value Pair Representation
Each key/value pair is represented as a set of four LEGO bricks of specific colors. The first two bricks represent the ASCII character key, and the next two represent the value as a number between 0 and 143. This ensures each key/value pair can be consistently encoded and decoded using four LEGO bricks.
4. Color to Number Mapping
- “Aqua”: 0
- “Black”: 1
- “Blue”: 2
- “Brown”: 3
- “Gray”: 4
- “Green”: 5
- “Orange”: 6
- “Pink”: 7
- “Purple”: 8
- “Red”: 9
- “White”: 10
- “Yellow”: 11
5. Protocol Description
5.1 Encoding
Encoding of key/value pairs follows the predefined mappings, using four bricks per pair. The first two bricks encode the ASCII key, while the next two encode the value between 0 and 143.
5.2 Decoding
Decoding reverses the encoding process, translating each set of four bricks back into a key/value pair.
6. Special Commands and Message Buffering
If two bricks at the beginning of a row appear in sequence as Aqua followed by Blue (which decodes to the ASCII code point for ␂ or Start of Text), this signals the start of a message buffer. The buffer continues until another ␂ character is encountered or the row ends.
7. Use Cases
- Storing game states
- Embedding attributes in physical objects
- Encoding messages or notes
- Educational implementations
8. Future Work and Recommendations
- Validation and error-correction features
- Protocol optimizations
- Compatibility extensions
Python Implementation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ColorCode: | |
def __init__(self): | |
self.COLORS = { | |
"Aqua": 0, | |
"Black": 1, | |
"Blue": 2, | |
"Brown": 3, | |
"Gray": 4, | |
"Green": 5, | |
"Orange": 6, | |
"Pink": 7, | |
"Purple": 8, | |
"Red": 9, | |
"White": 10, | |
"Yellow": 11, | |
} | |
self.COLORS_INDEX = {v: k for k, v in self.COLORS.items()} | |
def text_encode(self, char): | |
if not 32 <= ord(char) <= 126: | |
raise ValueError("Character should be a printable ASCII character") | |
code_point = ord(char) | |
return self.number_encode(code_point) | |
def text_decode(self, color_list): | |
number = self.number_decode(color_list) | |
if not 32 <= number <= 126: | |
raise ValueError("Invalid color list for a single ASCII character") | |
return chr(number) | |
def number_encode(self, number): | |
if number < 0 or number > 144: | |
raise ValueError("Number should be in the range 0-143") | |
digit1, digit2 = divmod(number, 12) | |
color1 = self.COLORS_INDEX[digit1] | |
color2 = self.COLORS_INDEX[digit2] | |
return [color1, color2] | |
def number_decode(self, color_list): | |
if len(color_list) != 2: | |
raise ValueError("Invalid color list length for a single number") | |
digit1 = self.COLORS[color_list[0]] | |
digit2 = self.COLORS[color_list[1]] | |
return digit1 * 12 + digit2 | |
def encode(self, data): | |
if not all(isinstance(k, str) and len(k) == 1 and 32 <= ord(k) <= 126 for k in data.keys()): | |
raise ValueError("All keys should be single printable ASCII characters") | |
if not all(isinstance(v, int) and 0 <= v <= 143 for v in data.values()): | |
raise ValueError("All values should be integers between 0 and 143") | |
encoded_list = [] | |
for k, v in data.items(): | |
encoded_key = self.text_encode(k) | |
encoded_value = self.number_encode(v) | |
encoded_list.extend(encoded_key + encoded_value) | |
return encoded_list | |
def decode(self, encoded_list): | |
if len(encoded_list) % 4 != 0: | |
raise ValueError("Encoded list length should be a multiple of 4") | |
decoded_dict = {} | |
for i in range(0, len(encoded_list), 4): | |
decoded_key = self.text_decode(encoded_list[i:i + 2]) | |
decoded_value = self.number_decode(encoded_list[i + 2:i + 4]) | |
decoded_dict[decoded_key] = decoded_value | |
return decoded_dict | |
# Example usage | |
if __name__ == "__main__": | |
color_code = ColorCode() | |
STX = 2 # ASCII Start of Text character | |
STX_color = color_code.number_encode(STX) | |
print("Start of Text colors:", STX_color) | |
data = {'x': 30, 'y': 15, 'z': 101} | |
encoded_data = color_code.encode(data) | |
print("Encoded:", encoded_data) | |
decoded_only = color_code.decode(encoded_data) | |
print("Decoded:", decoded_only) |