Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
f52dabb
feat: implement rendering with new renderer classes
dmccoystephenson May 28, 2025
dc6acba
refactor: improve environment loading logic
dmccoystephenson May 28, 2025
0d39f8a
refactor: rename functions for consistency and clarity
dmccoystephenson May 28, 2025
4549bc4
fix: save environments to file
dmccoystephenson May 30, 2025
18a7530
chore: update subproject commit reference
dmccoystephenson Jun 1, 2025
90c2bfa
chore: update subproject commit reference
dmccoystephenson Jun 1, 2025
a48ef7c
chore: update subproject commit reference
dmccoystephenson Jun 1, 2025
d06eceb
refactor: update `up.bat` to start program after spinning up dependen…
dmccoystephenson Jun 1, 2025
386300e
refactor: update `up.bat` to start program after spinning up dependen…
dmccoystephenson Jun 1, 2025
28bbc47
chore: update subproject commit reference
dmccoystephenson Jun 1, 2025
18ac187
feat: extract EnvironmentRenderer, GridRenderer, and LocationRenderer…
dmccoystephenson Jun 1, 2025
d8e2afc
refactor: remove unused grid_size parameter from EnvironmentRenderer
dmccoystephenson Jun 1, 2025
8104e2f
refactor: standardize variable naming for display dimensions and grid…
dmccoystephenson Jun 1, 2025
7030d56
refactor: add type hints for parameters in EnvironmentRenderer, GridR…
dmccoystephenson Jun 1, 2025
6679be6
fix: add delay in main loop to improve rendering performance
dmccoystephenson Jun 1, 2025
5e11d32
Merge pull request #7 from Preponderous-Software/refactor/modular-ren…
dmccoystephenson Jun 1, 2025
27fdf5a
Update gridRenderer.py
dmccoystephenson Sep 21, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Viron
19 changes: 19 additions & 0 deletions environmentRenderer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from Viron.src.main.python.preponderous.viron.models.environment import Environment
from Viron.src.main.python.preponderous.viron.services.gridService import GridService
from graphik import Graphik
from gridRenderer import GridRenderer


class EnvironmentRenderer:
def __init__(self, graphik: Graphik, url: str, port: int):
self.graphik = graphik
self.grid_service = GridService(url, port)
self.grid_renderer = GridRenderer(graphik, url, port)

def draw(self, environment: Environment):
grids = self.grid_service.get_grids_in_environment(environment.getEnvironmentId())
# assume one grid for now, can be extended later
if grids:
self.grid_renderer.draw(grids[0])
else:
self.graphik.drawText("No grids found in environment.", self.graphik.getGameDisplay().get_width()/2, self.graphik.getGameDisplay().get_height()/2, 20, "red")
23 changes: 23 additions & 0 deletions gridRenderer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from Viron.src.main.python.preponderous.viron.models.grid import Grid
from Viron.src.main.python.preponderous.viron.services.locationService import LocationService
from graphik import Graphik
from locationRenderer import LocationRenderer


class GridRenderer:
def __init__(self, graphik: Graphik, url: str, port: int):
self.graphik = graphik
self.location_service = LocationService(url, port)
self.location_renderer = LocationRenderer(graphik)
self.locations_cache = {}

def draw(self, grid: Grid):
grid_id = grid.get_grid_id()
if grid_id not in self.locations_cache:
self.locations_cache[grid_id] = self.location_service.get_locations_in_grid(grid_id)

locations = self.locations_cache[grid_id]
width = int(self.graphik.getGameDisplay().get_width() / grid.get_columns())
height = int(self.graphik.getGameDisplay().get_height() / grid.get_rows())
for location in locations:
self.location_renderer.draw(location, width, height)
21 changes: 21 additions & 0 deletions locationRenderer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import random

from Viron.src.main.python.preponderous.viron.models.location import Location
from graphik import Graphik


class LocationRenderer:
def __init__(self, graphik: Graphik):
self.graphik = graphik

def draw(self, location: Location, width: int, height: int):
x = location.get_x() * width
y = location.get_y() * height
color = self.get_random_color()
self.graphik.drawRectangle(x - 1, y - 1, width * 1.5, height * 1.5, color)

def get_random_color(self):
red = random.randrange(50, 200)
green = random.randrange(50, 200)
blue = random.randrange(50, 200)
return (red, green, blue)
121 changes: 62 additions & 59 deletions main.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import random
import pygame
from Viron.src.main.python.preponderous.viron.services.environmentService import EnvironmentService
from Viron.src.main.python.preponderous.viron.services.locationService import LocationService
from environmentRenderer import EnvironmentRenderer
from graphik import Graphik
import os
import json
Expand All @@ -12,115 +11,119 @@
black = (0,0,0)
white = (255,255,255)

displayWidth = 800
displayHeight = 800
display_width = 800
display_height = 800

def log(message):
print(message)

numGrids = 1
num_grids = 1
if len(sys.argv) > 1:
try:
gridSize = int(sys.argv[1])
grid_size = int(sys.argv[1])
except ValueError:
log("Invalid grid size argument, using default of 50.")
gridSize = 50
grid_size = 50
else:
gridSize = 50
grid_size = 50

url = "http://localhost"
port = 9999

locationService = LocationService(url, port)
environmentService = EnvironmentService(url, port)
exit_after_create = False
if len(sys.argv) > 2 and sys.argv[2] == "--exit-after-create":
exit_after_create = True
def drawEnvironment(locations, graphik, locationWidth, locationHeight):
for location in locations:
red = random.randrange(50, 200)
green = random.randrange(50, 200)
blue = random.randrange(50, 200)
x = location.get_x() * locationWidth
y = location.get_y() * locationHeight
graphik.drawRectangle(x - 1, y - 1, locationWidth * 1.5, locationHeight * 1.5, (red,green,blue))

def load_environments_file(env_file):
if os.path.exists(env_file):
log("Environments file exists, loading...")
with open(env_file, "r") as f:
return json.load(f)
else:
log("No existing environments found.")
return {}

def load_existing_environment(graphik, env_key, environments, environmentService):
Copy link

Copilot AI Sep 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function doesn't return a value when an exception occurs (lines 51-57), but the caller on line 90 expects a return value. Consider returning None or raising the exception instead of just logging and returning from the function.

Copilot uses AI. Check for mistakes.
graphik.drawText("Loading existing environment, please wait...", display_width/2, display_height/2, 20, "white")
env_id = environments[env_key]["environment_id"]
try:
return environmentService.get_environment_by_id(env_id)
except Exception as e:
log(f"Error loading existing environment: {e}")
graphik.drawText("Error loading environment, please check logs.", display_width/2, display_height/2 + 30, 20, "red")
pygame.display.update()
time.sleep(2)
pygame.quit()
return

def create_environment(graphik, num_grids, grid_size):
environmentService = EnvironmentService(url, port)
Comment on lines +59 to +60
Copy link

Copilot AI Sep 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The EnvironmentService is created inside this function but also created in main() on line 86. Consider passing the service as a parameter to avoid duplicate instantiation and improve consistency.

Suggested change
def create_environment(graphik, num_grids, grid_size):
environmentService = EnvironmentService(url, port)
def create_environment(graphik, num_grids, grid_size, environmentService):

Copilot uses AI. Check for mistakes.
graphik.drawText("Creating environment, please wait...", 400, 400, 20,"white")
pygame.display.update()
log("Creating environment with " + str(num_grids) + " grid(s) of size " + str(grid_size) + "x" + str(grid_size))
start_time = time.time()
environment = environmentService.create_environment("Test", num_grids, grid_size)
end_time = time.time()
log(f"Created new environment with id {environment.getEnvironmentId()} in {end_time - start_time:.2f} seconds.")

return environment, start_time, end_time

def main():
pygame.init()
gameDisplay = pygame.display.set_mode((displayWidth, displayHeight))
graphik = Graphik(gameDisplay)
game_display = pygame.display.set_mode((display_width, display_height))
graphik = Graphik(game_display)
pygame.display.set_caption("Visualizing Environment With Random Colors")

env_file = "environments.json"
environments = {}

# Load existing environments if file exists
if os.path.exists(env_file):
log("Environments file exists, loading...")
with open(env_file, "r") as f:
environments = json.load(f)
environments = load_environments_file(env_file)

# Create a unique key for the environment based on grid size and numGrids
env_key = f"{numGrids}x{gridSize}"
env_key = f"{num_grids}x{grid_size}"

environment_service = EnvironmentService(url, port)

if env_key in environments:
graphik.drawText("Loading existing environment, please wait...", displayWidth/2, displayHeight/2, 20, "white")
env_id = environments[env_key]["environment_id"]
try:
environment = environmentService.get_environment_by_id(env_id)
log(f"Loaded existing environment with id {env_id} and size {gridSize}x{gridSize} with {numGrids} grid(s).")
except Exception as e:
log(f"Error loading existing environment: {e}")
graphik.drawText("Error loading environment, please check logs.", displayWidth/2, displayHeight/2 + 30, 20, "red")
pygame.display.update()
time.sleep(2)
pygame.quit()
return
log(f"Environment with key {env_key} already exists, loading...")
environment = load_existing_environment(graphik, env_key, environments, environment_service)
else:
graphik.drawText("Creating environment, please wait...", 400, 400, 20,"white")
pygame.display.update()
log("Creating environment with " + str(numGrids) + " grid(s) of size " + str(gridSize) + "x" + str(gridSize))
start_time = time.time()
environment = environmentService.create_environment("Test", numGrids, gridSize)
end_time = time.time()
log(f"No existing environment found with key {env_key}, creating new one.")
environment, start_time, end_time = create_environment(graphik, num_grids, grid_size)

environments[env_key] = {
"environment_id": environment.getEnvironmentId(),
"grid_size": gridSize,
"num_grids": numGrids,
"grid_size": grid_size,
"num_grids": num_grids,
"creation_time_seconds": end_time - start_time
}
with open(env_file, "w") as f:
json.dump(environments, f, indent=2)
log(f"Created new environment with id {environment.getEnvironmentId()} in {end_time - start_time:.2f} seconds.")

if exit_after_create:
log("Exiting after environment creation.")
locations = locationService.get_locations_in_environment(environment.getEnvironmentId())
drawEnvironment(locations, graphik, displayWidth/gridSize, displayHeight/gridSize)
environment_renderer = EnvironmentRenderer(graphik, url, port)
environment_renderer.draw(environment)
pygame.display.update()
time.sleep(2)
pygame.quit()
return

locationWidth = displayWidth/gridSize
locationHeight = displayHeight/gridSize

locationsCache = {}

running = True

environment_renderer = EnvironmentRenderer(graphik, url, port)

while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()

if locationsCache == {}:
log("Fetching locations from service...")
locationsCache = locationService.get_locations_in_environment(environment.getEnvironmentId())

gameDisplay.fill(white)
drawEnvironment(locationsCache, graphik, locationWidth, locationHeight)
game_display.fill(white)
environment_renderer.draw(environment)
pygame.display.update()

time.sleep(0.1)

main()
6 changes: 2 additions & 4 deletions up.bat
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# This script is used to start the Docker containers defined in the Docker Compose file.

docker compose -f .\viron\compose.yml up -d --build
REM The -d flag runs the containers in detached mode, allowing them to run in the background.
REM The --build flag forces a rebuild of the images before starting the containers.

python main.py