Development Artifact Cleanup: ✅ BROTHER_NODE REORGANIZATION: Moved development test node to appropriate location - dev/test-nodes/brother_node/: Moved from root directory for better organization - Contains development configuration, test logs, and test chain data - No impact on production systems - purely development/testing artifact ✅ DEVELOPMENT ARTIFACTS IDENTIFIED: - Chain ID: aitbc-brother-chain (test/development chain) - Ports: 8010 (P2P) and 8011 (RPC) - different from production - Environment: .env file with test configuration - Logs: rpc.log and node.log from development testing session (March 15, 2026) ✅ ROOT DIRECTORY CLEANUP: Removed development clutter from production directory - brother_node/ moved to dev/test-nodes/brother_node/ - Root directory now contains only production-ready components - Development artifacts properly organized in dev/ subdirectory DIRECTORY STRUCTURE IMPROVEMENT: 📁 dev/test-nodes/: Development and testing node configurations 🏗️ Root Directory: Clean production structure with only essential components 🧪 Development Isolation: Test environments separated from production BENEFITS: ✅ Clean Production Directory: No development artifacts in root ✅ Better Organization: Development nodes grouped in dev/ subdirectory ✅ Clear Separation: Production vs development environments clearly distinguished ✅ Maintainability: Easier to identify and manage development components RESULT: Successfully moved brother_node development artifact to dev/test-nodes/ subdirectory, cleaning up the root directory while preserving development testing environment for future use.
101 lines
3.2 KiB
Python
Executable File
101 lines
3.2 KiB
Python
Executable File
from math import sqrt
|
|
from functools import lru_cache
|
|
from typing import Sequence, Tuple, TYPE_CHECKING
|
|
|
|
from .color_triplet import ColorTriplet
|
|
|
|
if TYPE_CHECKING:
|
|
from rich.table import Table
|
|
|
|
|
|
class Palette:
|
|
"""A palette of available colors."""
|
|
|
|
def __init__(self, colors: Sequence[Tuple[int, int, int]]):
|
|
self._colors = colors
|
|
|
|
def __getitem__(self, number: int) -> ColorTriplet:
|
|
return ColorTriplet(*self._colors[number])
|
|
|
|
def __rich__(self) -> "Table":
|
|
from rich.color import Color
|
|
from rich.style import Style
|
|
from rich.text import Text
|
|
from rich.table import Table
|
|
|
|
table = Table(
|
|
"index",
|
|
"RGB",
|
|
"Color",
|
|
title="Palette",
|
|
caption=f"{len(self._colors)} colors",
|
|
highlight=True,
|
|
caption_justify="right",
|
|
)
|
|
for index, color in enumerate(self._colors):
|
|
table.add_row(
|
|
str(index),
|
|
repr(color),
|
|
Text(" " * 16, style=Style(bgcolor=Color.from_rgb(*color))),
|
|
)
|
|
return table
|
|
|
|
# This is somewhat inefficient and needs caching
|
|
@lru_cache(maxsize=1024)
|
|
def match(self, color: Tuple[int, int, int]) -> int:
|
|
"""Find a color from a palette that most closely matches a given color.
|
|
|
|
Args:
|
|
color (Tuple[int, int, int]): RGB components in range 0 > 255.
|
|
|
|
Returns:
|
|
int: Index of closes matching color.
|
|
"""
|
|
red1, green1, blue1 = color
|
|
_sqrt = sqrt
|
|
get_color = self._colors.__getitem__
|
|
|
|
def get_color_distance(index: int) -> float:
|
|
"""Get the distance to a color."""
|
|
red2, green2, blue2 = get_color(index)
|
|
red_mean = (red1 + red2) // 2
|
|
red = red1 - red2
|
|
green = green1 - green2
|
|
blue = blue1 - blue2
|
|
return _sqrt(
|
|
(((512 + red_mean) * red * red) >> 8)
|
|
+ 4 * green * green
|
|
+ (((767 - red_mean) * blue * blue) >> 8)
|
|
)
|
|
|
|
min_index = min(range(len(self._colors)), key=get_color_distance)
|
|
return min_index
|
|
|
|
|
|
if __name__ == "__main__": # pragma: no cover
|
|
import colorsys
|
|
from typing import Iterable
|
|
from rich.color import Color
|
|
from rich.console import Console, ConsoleOptions
|
|
from rich.segment import Segment
|
|
from rich.style import Style
|
|
|
|
class ColorBox:
|
|
def __rich_console__(
|
|
self, console: Console, options: ConsoleOptions
|
|
) -> Iterable[Segment]:
|
|
height = console.size.height - 3
|
|
for y in range(0, height):
|
|
for x in range(options.max_width):
|
|
h = x / options.max_width
|
|
l = y / (height + 1)
|
|
r1, g1, b1 = colorsys.hls_to_rgb(h, l, 1.0)
|
|
r2, g2, b2 = colorsys.hls_to_rgb(h, l + (1 / height / 2), 1.0)
|
|
bgcolor = Color.from_rgb(r1 * 255, g1 * 255, b1 * 255)
|
|
color = Color.from_rgb(r2 * 255, g2 * 255, b2 * 255)
|
|
yield Segment("▄", Style(color=color, bgcolor=bgcolor))
|
|
yield Segment.line()
|
|
|
|
console = Console()
|
|
console.print(ColorBox())
|