diff --git a/15_melodic_rpg_chiptunes_mid/rpgchip03_town.mid b/15_melodic_rpg_chiptunes_mid/rpgchip03_town.mid deleted file mode 100644 index 6cf11a3..0000000 Binary files a/15_melodic_rpg_chiptunes_mid/rpgchip03_town.mid and /dev/null differ diff --git a/README.md b/README.md index 688b42a..b390961 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,79 @@ +````markdown # Mice! Mice! is a strategic game where players must kill rats with bombs before they reproduce and become too numerous. The game is a clone of the classic game Rats! for Windows 95. ## Compatibility -*It's developed in Python 3.11, please use it* +*Developed and tested with Python 3.11+* ## Features -- **Maze Generation**: Randomly generated mazes using Depth First Search (DFS) algorithm. -- **Units**: Different types of units such as rats, bombs, and points with specific behaviors. -- **Graphics**: Custom graphics for maze tiles, units, and effects. -- **Sound Effects**: Audio feedback for various game events. -- **Scoring**: Points system to track player progress. +- **Maze Generation**: Randomly generated mazes using Depth First Search (DFS) algorithm +- **Multiple Unit Types**: Rats, bombs, mines, gas, and collectible points with unique behaviors +- **User Profile System**: Track scores, achievements, and game statistics +- **Graphics**: Custom graphics for maze tiles, units, and effects +- **Sound Effects**: Audio feedback for various game events +- **Scoring**: Points system with leaderboards and profile integration +- **Dual Rendering Engines**: Support for both SDL2 and Pygame + +## Rendering Engine Options + +The game now supports **two rendering backends** with identical interfaces: + +### 1. SDL2 Backend (`engine/sdl2_layer.py`) +- **Original implementation** using PySDL2 +- Hardware-accelerated rendering via SDL2 +- Optimized for performance on Linux systems +- Direct access to low-level graphics features + +### 2. Pygame Backend (`engine/pygame_layer.py`) ⭐ **NEW** +- **Drop-in replacement** for SDL2 backend +- More portable and easier to set up +- Better cross-platform support (Windows, macOS, Linux) +- Simplified dependency management +- Identical API - no game code changes needed + +### Switching Between Rendering Engines + +To switch from SDL2 to Pygame, simply change the import in `rats.py`: + +```python +# Using SDL2 (original) +from engine import maze, controls, graphics, sdl2_layer as engine, unit_manager, scoring + +# Using Pygame (new) +from engine import maze, controls, graphics, pygame_layer as engine, unit_manager, scoring +``` + +That's it! No other code changes are required thanks to the compatible interface design. + +## Browser / Pyodide Support (experimental) + +- The project includes an experimental browser build that runs the game in WebAssembly using Pyodide and a bundled pygame-ce build. This supports running the game inside modern browsers (desktop only) and is intended for demos and lightweight testing. +- Key points: + - `index.html` contains the Pyodide bootstrap, asset loader and a JS-driven game loop that calls into the Python game tick function so the UI stays responsive. + - The browser integration includes a small profile sync mechanism so profiles saved by the Python code (inside Pyodide's virtual FS) are synchronized back to browser `localStorage`. + - A tiny utility `tools/create_favicon.py` generates `favicon.ico` from the game's `assets` if you want a browser favicon for local hosting. + +Use the browser demo for quick sharing and testing, but prefer the native Python + SDL2/pygame backends for actual play and development. + +## Cleanup notes + +This repository contains some auxiliary files used during development and for old/demo flows. If you want me to remove unused items, I can safely delete them in a single branch/commit after you confirm. Suggested candidates are listed in the developer checklist below. + +### Developer cleanup checklist (proposed deletions) + +These files look like auxiliary or duplicate/demo artifacts and can be removed to reduce noise. I'll only delete them if you confirm. + +- `BROWSER_GAME_README.md` — duplicate/demo readme for browser build +- `BROWSER_SETUP_QUICK_START.md` — quick-start for browser demo +- `PYGAME_BACKEND_GUIDE.md` — documentation duplicate +- `pyodide-guide.html` — local demo HTML (we already ship `index.html`) +- `browser-game-setup.sh` and `play.sh` — demo scripts not used in CI +- `assets/asset-manifest.json`, `assets/sound-manifest.json` — generated manifests (can be regenerated) +- `engine/pygame_layer.py` and `engine/sdl2_layer.py` — ensure you want to keep one backend; if you prefer only SDL2 or only Pygame, remove the other + +If you'd like me to proceed, reply with "delete these files" and I will create a branch, remove them, and push the change. ## Engine Architecture @@ -19,58 +81,80 @@ The Mice! game engine is built on a modular architecture designed for flexibilit ### Core Engine Components -#### 1. **Rendering System** (`engine/sdl2.py`) -- **GameWindow Class**: Central rendering manager using SDL2 +#### 1. **Rendering System** (`engine/sdl2_layer.py` or `engine/pygame_layer.py`) +- **GameWindow Class**: Central rendering manager - **Features**: - - Hardware-accelerated rendering via SDL2 + - Hardware-accelerated rendering - Texture management and caching - Sprite rendering with transparency support - Text rendering with custom fonts - Resolution-independent scaling - Fullscreen/windowed mode switching + - Dynamic blood splatter effects + - White flash screen effects - **Implementation**: - - Uses SDL2 renderer for efficient GPU-accelerated drawing - - Implements double buffering for smooth animation - - Manages texture atlas for optimized memory usage - - Handles viewport transformations for different screen resolutions + - Double buffering for smooth animation + - Texture atlas for optimized memory usage + - Viewport transformations for different screen resolutions + - Alpha blending for transparency effects #### 2. **Input System** (`engine/controls.py`) - **KeyBindings Class**: Handles all user input - **Features**: - Keyboard input mapping and handling - Joystick/gamepad support - - Configurable key bindings - - Input state management + - Configurable key bindings via YAML/JSON + - Context-sensitive input (menu vs. gameplay) - **Implementation**: - Event-driven input processing - - Key state buffering for smooth movement - Support for multiple input devices simultaneously - - Customizable control schemes + - Dynamic key binding system with action mapping #### 3. **Map System** (`engine/maze.py`) - **Map Class**: Manages the game world structure - **Features**: - - Maze data loading and parsing + - Maze data loading from JSON - Collision detection system - Tile-based world representation - Pathfinding support for AI units - **Implementation**: - Grid-based coordinate system - - Efficient collision detection using spatial partitioning - - Support for different tile types (walls, floors, special tiles) - - Integration with maze generation algorithms + - Efficient collision detection + - Support for walls and floor tiles + - Integration with procedural maze generation #### 4. **Audio System** - **Sound Management**: Handles all audio playback - **Features**: - - Sound effect playback + - Sound effect playback with multiple channels - Background music support - Volume control - - Multiple audio channels + - Per-channel audio mixing +- **Implementation**: + - SDL2 backend: Native SDL2 audio system + - Pygame backend: pygame.mixer module + - Support for WAV format audio files + - Multiple simultaneous sound channels (base, effects, music) + +#### 5. **Unit Management System** (`engine/unit_manager.py`) +- **UnitManager Class**: Manages all game entities +- **Features**: + - Dynamic unit spawning and removal + - Position tracking for collision detection + - Resource management (ammo, items) - **Implementation**: - - Uses subprocess module for audio playback - - Asynchronous sound loading and playing - - Audio file format support (WAV, MP3, OGG) + - UUID-based unique identifiers + - Efficient lookup structures + - Automatic cleanup on unit death + +#### 6. **User Profile System** (`engine/user_profile_integration.py`) +- **UserProfileIntegration Class**: Manages player profiles +- **Features**: + - Multiple user profile support + - Score tracking and leaderboards + - Game statistics (games played, wins, best score) + - Device-specific profiles + - Global leaderboard integration ### Game Loop Architecture @@ -78,98 +162,515 @@ The main game loop follows the standard pattern: 1. **Input Processing**: Capture and process user input 2. **Update Phase**: Update game state, unit logic, and physics 3. **Render Phase**: Draw all game objects to the screen -4. **Timing Control**: Maintain consistent frame rate +4. **Timing Control**: Maintain consistent frame rate (target 60 FPS) ``` Input → Update → Render → Present → Repeat ``` + ## Units Implementation The game uses an object-oriented approach for all game entities. Each unit type inherits from a base unit class and implements specific behaviors. -### Base Unit Architecture +### Base Unit Architecture (`units/unit.py`) + +All units share common properties and methods defined in the abstract `Unit` class: + +**Common Attributes**: +- `id` (UUID): Unique identifier for each unit +- `position` (tuple): Current (x, y) grid coordinates +- `position_before` (tuple): Previous position for smooth movement +- `age` (int): Time alive in game ticks +- `speed` (float): Movement speed multiplier +- `partial_move` (float): Sub-cell movement progress (0.0 to 1.0) +- `bbox` (tuple): Bounding box for collision detection +- `stop` (int): Remaining ticks of immobilization + +**Abstract Methods** (must be implemented by subclasses): +- `move()`: Update unit position and state each frame +- `draw()`: Render the unit on screen -All units share common properties and methods: -- **Position and Movement**: 2D coordinates with movement capabilities -- **Unique Identification**: UUID-based unique identifiers -- **Collision Detection**: Bounding box collision system -- **State Management**: Current state tracking (alive, dead, exploding, etc.) -- **Rendering**: Sprite-based visual representation +**Concrete Methods**: +- `collisions()`: Handle interactions with other units +- `die(score=None)`: Remove unit from game and handle cleanup ### Unit Types Implementation #### 1. **Rat Units** (`units/rat.py`) **Base Rat Class**: -- **AI Behavior**: Implements pathfinding using A* algorithm -- **Movement**: Grid-based movement with smooth interpolation -- **State Machine**: Multiple states (wandering, fleeing, reproducing) +- **AI Behavior**: Pathfinding with direction memory to avoid backtracking +- **Movement**: Smooth interpolated movement between grid cells +- **Lifecycle**: Age-based behavior changes (baby → adult → elder) +- **Gas Vulnerability**: Can be killed by poison gas **Male Rat Class**: -- **Reproduction Logic**: Seeks female rats for mating -- **Territorial Behavior**: Defends territory from other males -- **Lifespan Management**: Age-based death system +- **Reproduction**: Seeks female rats for mating +- **Fighting**: Territorial combat with other males +- **Adult Threshold**: Becomes fertile after 200 game ticks **Female Rat Class**: -- **Pregnancy System**: Gestation period simulation -- **Offspring Generation**: Creates new rat units -- **Maternal Behavior**: Protects offspring from threats +- **Pregnancy System**: 500-tick gestation period +- **Offspring Generation**: Spawns baby rats at intervals +- **Maternal Behavior**: Protects territory from threats **Implementation Details**: ```python -# Simplified rat behavior structure -class Rat: - def update(self): - self.process_ai() # Decision making - self.handle_movement() # Position updates - self.check_collisions() # Collision detection - self.update_state() # State transitions +class Rat(Unit): + def move(self): + self.age += 1 + if self.gassed > 35: + self.choked() # Death by gas + if self.age == AGE_THRESHOLD: + self.speed *= SPEED_REDUCTION # Slow down with age + self.partial_move += self.speed + if self.partial_move >= 1: + self.position = self.find_next_position() + self.partial_move = 0 ``` #### 2. **Bomb Units** (`units/bomb.py`) -**Bomb Class**: -- **Timer System**: Countdown mechanism before explosion -- **Placement Logic**: Player-controlled positioning -- **Damage Calculation**: Blast radius and damage computation +**Timer Bomb Class**: +- **Countdown System**: Visual timer (4 stages) before explosion +- **Chain Reactions**: Triggers nearby bombs +- **Directional Blast**: Explodes in 4 cardinal directions until hitting walls + +**Nuclear Bomb Class**: +- **Instant Kill**: Destroys all rats on the map +- **White Flash Effect**: Screen flash on detonation +- **Single Use**: Limited to 1 per game **Explosion Class**: -- **Visual Effects**: Animated explosion graphics -- **Damage Dealing**: Affects units within blast radius -- **Temporary Entity**: Self-destructs after animation +- **Temporary Effect**: Short-lived visual and damage entity +- **Kill Radius**: Destroys all rats in the same cell +- **Score Bonus**: Awards points for each rat killed **Implementation Details**: -- **State Machine**: Armed → Countdown → Exploding → Cleanup -- **Collision System**: Different collision behaviors per state -- **Effect Propagation**: Chain reaction support for multiple bombs +```python +class Timer(Bomb): + def move(self): + self.age += 1 + if self.age > 160: # 160 ticks = explosion + self.die(unit=self, score=10) + + def die(self, unit=None, score=None): + # Create explosion and propagate in 4 directions + for direction in ["N", "S", "E", "W"]: + # Spread until wall + while not self.game.map.is_wall(x, y): + self.game.spawn_unit(Explosion, (x, y)) +``` -#### 3. **Point Units** (`units/points.py`) +#### 3. **Mine Units** (`units/mine.py`) + +**Mine Class**: +- **Arming Delay**: Becomes active after placement delay +- **Contact Trigger**: Detonates when rat steps on it +- **Gas Release**: Creates poison gas clouds on detonation +- **Limited Supply**: Max 4 mines at a time + +#### 4. **Gas Units** (`units/gas.py`) + +**Gas Cloud Class**: +- **Lingering Effect**: Stays in place for duration +- **Poison Damage**: Accumulates damage on rats over time +- **Chaining**: Can spawn additional gas clouds +- **Visual Effect**: Semi-transparent gas sprite + +#### 5. **Point Units** (`units/points.py`) **Point Class**: -- **Collection Mechanics**: Player interaction system -- **Value System**: Different point values for different achievements -- **Visual Feedback**: Pickup animations and effects +- **Collection Mechanics**: Auto-collected by player cursor +- **Value System**: Different point values (5, 10, 25, 50, 100) +- **Timed Existence**: Disappears after ~5 seconds +- **Score Tracking**: Updates player score on collection ### Unit Interaction System Units interact through a centralized collision and event system: -1. **Collision Detection**: - - Grid-based broad phase for efficiency - - Precise bounding box narrow phase - - Custom collision responses per unit type pair - -2. **Event System**: - - Unit death events - - Reproduction events - - Explosion events - - Point collection events - -3. **AI Communication**: - - Shared pathfinding data - - Pheromone trail system for rat behavior - - Danger awareness (bombs, explosions) +#### Collision Detection +- **Spatial Hashing**: Grid-based lookup for nearby units +- **Bounding Box**: Precise pixel-perfect collision detection +- **Overlap Tolerance**: Small margin to prevent jittering +- **Bi-directional**: Both units check for collisions + +#### Event System +- **Death Events**: Spawn points, trigger explosions, update score +- **Reproduction Events**: Create new rat units +- **Explosion Events**: Chain reactions, area damage +- **Collection Events**: Point pickup, ammo refill + +#### AI Communication +- **Position Tracking**: `unit_positions` dictionary for fast lookup +- **Shared Pathfinding**: Avoid blocked cells +- **Danger Awareness**: Rats flee from explosions + +## Technical Details + +### Language & Core Libraries +- **Python**: 3.11+ (recommended) +- **Rendering**: + - `pysdl2` - SDL2 bindings for graphics (original backend) + - `pygame` - Pygame library for graphics (new backend) +- **Image Processing**: `Pillow` - For image loading and manipulation +- **Configuration**: `pyaml` - YAML config file parsing +- **Standard Library**: `uuid`, `random`, `os`, `json` + +### Performance Optimizations +- **Spatial Partitioning**: Grid-based collision detection reduces O(n²) to O(n) +- **Texture Caching**: Pre-loaded assets prevent repeated disk I/O +- **Background Rendering**: Static maze rendered once, cached as texture +- **Delta Time**: Frame-rate independent updates using `partial_move` +- **Efficient Drawing**: Only draw units in visible viewport area + +### Memory Management +- **Automatic Cleanup**: Dead units removed from `units` dictionary +- **Surface Reuse**: Blood stains combined into background texture +- **Lazy Loading**: Assets loaded on demand +- **Reference Counting**: Python GC handles most cleanup + +### Architecture Patterns +- **Multiple Inheritance**: Game class combines Controls, Graphics, UnitManager, Scoring +- **Abstract Base Classes**: `Unit` defines interface for all game entities +- **Factory Pattern**: `spawn_unit()` method for dynamic unit creation +- **Observer Pattern**: Event-driven input system with callbacks +- **Strategy Pattern**: Different AI behaviors for rat types + +## Environment Variables + +Configure the game behavior using environment variables: + +- `SDL_VIDEODRIVER`: Video driver selection (x11, wayland, etc.) +- `RESOLUTION`: Screen resolution in format `WIDTHxHEIGHT` (default: 640x480) +- `FULLSCREEN`: Enable fullscreen mode (true/false) +- `SOUND_ENABLED`: Enable/disable sound effects (true/false) + +Example: +```bash +RESOLUTION=1920x1080 FULLSCREEN=true python rats.py +``` + +## Installation + +### Prerequisites +- Python 3.11 or higher +- pip package manager + +### Step-by-Step Installation + +1. **Clone the repository**: + ```bash + git clone https://github.com/yourusername/mice-maze-game.git + cd mice-maze-game + ``` + +2. **Create a virtual environment** (recommended): + ```bash + python3 -m venv venv + source venv/bin/activate # On Windows: venv\Scripts\activate + ``` + +3. **Install dependencies**: + + For **Pygame backend** (recommended for beginners): + ```bash + pip install pygame Pillow pyaml + ``` + + For **SDL2 backend** (advanced users): + ```bash + pip install pysdl2 Pillow pyaml + ``` + + Or install all dependencies: + ```bash + pip install -r requirements.txt + ``` + +4. **Run the game**: + ```bash + python rats.py + ``` + +### Platform-Specific Notes + +#### Linux +- SDL2 backend requires `libsdl2-dev` package +- Install via: `sudo apt-get install libsdl2-dev libsdl2-ttf-dev libsdl2-mixer-dev` + +#### macOS +- Install SDL2 via Homebrew: `brew install sdl2 sdl2_ttf sdl2_mixer` +- Pygame backend works out of the box + +#### Windows +- Pygame backend recommended (easiest setup) +- SDL2 backend requires manual SDL2 DLL installation + +## Project Structure + +``` +mice/ +├── engine/ # Core engine components +│ ├── controls.py # Input handling system +│ ├── graphics.py # Graphics and rendering helpers +│ ├── maze.py # Map and collision system +│ ├── sdl2_layer.py # SDL2 rendering backend +│ ├── pygame_layer.py # Pygame rendering backend ⭐ NEW +│ ├── unit_manager.py # Entity spawning and management +│ ├── scoring.py # Score tracking system +│ ├── user_profile_integration.py # User profile system +│ └── score_api_client.py # API client for global leaderboard +├── units/ # Game entity implementations +│ ├── __init__.py # Unit package exports +│ ├── unit.py # Abstract base class for all units +│ ├── rat.py # Rat AI and behavior (Male/Female) +│ ├── bomb.py # Bombs, timers, and explosions +│ ├── mine.py # Mine traps +│ ├── gas.py # Poison gas clouds +│ └── points.py # Collectible point items +├── profile_manager/ # Profile management system +│ ├── profile_manager.py # Profile CRUD operations +│ ├── profile_data.py # Profile data models +│ ├── ui_components.py # UI helpers +│ └── screens/ # Profile management screens +│ ├── screen_manager.py # Screen navigation +│ ├── main_menu_screen.py +│ ├── profile_list_screen.py +│ ├── create_profile_screen.py +│ ├── edit_profile_screen.py +│ ├── profile_stats_screen.py +│ └── leaderboard_screen.py +├── assets/ # Game resources +│ ├── Rat/ # Sprite images +│ │ ├── BMP_*.png # Various game sprites +│ └── decterm.ttf # Font file +├── sound/ # Audio files +│ ├── converted/ # Converted audio format +│ └── *.WAV # Sound effects +├── conf/ # Configuration files +│ ├── keybindings.yaml # Key mapping configuration +│ ├── keybindings_*.yaml # Device-specific bindings +│ └── keybindings.json # JSON format bindings +├── tools/ # Utility scripts +│ ├── convert_audio.py # Audio format converter +│ ├── resize_assets.py # Image resizing tool +│ └── colorize_assets.py # Asset colorization +├── rats.py # Main game entry point +├── maze.json # Maze layout data +├── user_profiles.json # User profile storage +├── requirements.txt # Python dependencies +├── README.md # This documentation +├── README_PROFILE_MANAGER.md # Profile system documentation +└── UNIT_ARCHITECTURE_GUIDE.md # Unit system guide +``` + +## Game Files Details + +### Core Game Files +- **`rats.py`**: Main game controller, entry point, and game loop +- **`maze.json`**: Maze layout definition (grid of walls and paths) +- **`key.py`**: Additional key handling utilities + +### Engine Modules +- **`engine/controls.py`**: Input abstraction with configurable bindings +- **`engine/graphics.py`**: Graphics helpers (asset loading, background generation) +- **`engine/maze.py`**: World representation with collision detection +- **`engine/sdl2_layer.py`**: Low-level SDL2 graphics interface +- **`engine/pygame_layer.py`**: Pygame graphics interface (new) +- **`engine/unit_manager.py`**: Unit spawning and lifecycle management +- **`engine/scoring.py`**: Score calculation and persistence + +### Unit Implementations +- **`units/unit.py`**: Abstract base class defining unit interface +- **`units/rat.py`**: Rat AI with pathfinding and reproduction +- **`units/bomb.py`**: Explosive units with timer and blast mechanics +- **`units/mine.py`**: Trap units with proximity trigger +- **`units/gas.py`**: Poison gas clouds with area effect +- **`units/points.py`**: Collectible scoring items + +### Data Files +- **`user_profiles.json`**: Persistent user profile data +- **`scores.txt`**: Traditional high score storage (legacy) +- **`maze.json`**: Level layout definition + +### Configuration +- **`conf/keybindings.yaml`**: Key mapping for different game states +- **Device-specific configs**: Optimized bindings for different devices + +## How to Play + +### Objective +Eliminate all rats before they reproduce and overwhelm the maze. Collect points by killing rats with bombs, mines, and gas. + +### Controls + +#### Default Keyboard Controls +- **Arrow Keys**: Move cursor +- **Space**: Place bomb at cursor position +- **M**: Place mine at cursor position +- **G**: Release poison gas at cursor position +- **N**: Deploy nuclear bomb (one-time use) +- **P**: Pause game +- **F**: Toggle fullscreen +- **S**: Toggle sound +- **ESC**: Quit game + +#### Gamepad Support +- **D-Pad**: Move cursor +- **Button A**: Place bomb +- **Button B**: Place mine +- **Button X**: Release gas +- **Start**: Pause game + +*Controls can be customized via configuration files in `conf/`* + +### Gameplay Tips +1. **Early Game**: Focus on preventing rat reproduction by targeting adults +2. **Bomb Placement**: Use walls to direct explosion paths +3. **Mine Strategy**: Place mines in narrow corridors where rats pass frequently +4. **Gas Tactics**: Gas lingers and accumulates damage - use in rat-dense areas +5. **Nuclear Option**: Save the nuclear bomb for when rats exceed ~150 +6. **Resource Management**: Ammo refills randomly - don't waste bombs early +7. **Scoring**: Chain kills and quick clears give bonus points + +### Win Condition +Clear all rats from the maze without letting their population exceed 200. + +### Lose Condition +Rat population exceeds 200 - they've overrun the maze. + +## Profile System + +Mice! includes a comprehensive user profile system to track your progress: + +### Features +- **Multiple Profiles**: Create profiles for different players +- **Statistics Tracking**: Games played, wins, losses, best score +- **Device Support**: Profile data syncs across devices +- **Leaderboards**: Compare scores globally and locally +- **Achievements**: Track milestones and accomplishments + +### Profile Management +Access the profile manager before starting the game: +```bash +python profile_manager/profile_manager.py +``` + +Or manage profiles from within the game main menu. + +## Development + +### Adding New Units +1. Create a new class in `units/` inheriting from `Unit` +2. Implement required methods: `move()`, `draw()` +3. Optionally override: `collisions()`, `die()` +4. Register in `units/__init__.py` +5. Add spawning logic in `unit_manager.py` + +Example: +```python +from units.unit import Unit + +class MyUnit(Unit): + def move(self): + # Update logic here + pass + + def draw(self): + # Rendering logic here + image = self.game.assets["MY_SPRITE"] + self.game.render_engine.draw_image(x, y, image, tag="unit") +``` + +### Switching Rendering Backends +Edit the import in `rats.py`: +```python +# For SDL2 +from engine import sdl2_layer as engine + +# For Pygame +from engine import pygame_layer as engine +``` + +### Creating Custom Mazes +Edit `maze.json` - it's a 2D grid where: +- `0` = path/floor +- `1` = wall + +Example: +```json +{ + "maze": [ + [1, 1, 1, 1, 1], + [1, 0, 0, 0, 1], + [1, 0, 1, 0, 1], + [1, 0, 0, 0, 1], + [1, 1, 1, 1, 1] + ] +} +``` + +## Troubleshooting + +### Common Issues + +**Issue**: Game window doesn't appear +- **Solution**: Check `RESOLUTION` environment variable, try `640x480` + +**Issue**: No sound +- **Solution**: Verify `SOUND_ENABLED` not set to false, check audio files in `sound/` + +**Issue**: SDL2 import errors +- **Solution**: Switch to Pygame backend or install SDL2 libraries + +**Issue**: Slow performance +- **Solution**: Reduce resolution, close other applications, update graphics drivers + +**Issue**: Profile data not saving +- **Solution**: Check file permissions for `user_profiles.json` + +## Contributing + +Contributions are welcome! Please: +1. Fork the repository +2. Create a feature branch (`git checkout -b feature/amazing-feature`) +3. Commit your changes (`git commit -m 'Add amazing feature'`) +4. Push to the branch (`git push origin feature/amazing-feature`) +5. Open a Pull Request + +## License + +This project is a fan remake of the classic "Rats!" game from Windows 95. + +## Credits + +- **Original Game**: Rats! for Windows 95 +- **Developer**: Matteo (because he was bored) +- **Engine**: Custom Python engine with SDL2/Pygame backends +- **Contributors**: See GitHub contributors page + +## Changelog + +### Version 2.0 (Current) +- ⭐ Added Pygame rendering backend +- ⭐ Dual backend support (SDL2 + Pygame) +- ⭐ Complete API compatibility between backends +- Improved documentation +- Enhanced README with technical details + +### Version 1.0 +- Initial release +- SDL2 rendering engine +- User profile system +- Multiple unit types +- Configurable controls +- Leaderboard system + + +```` ## Technical Details diff --git a/README_PROFILE_MANAGER.md b/README_PROFILE_MANAGER.md deleted file mode 100644 index 8863865..0000000 --- a/README_PROFILE_MANAGER.md +++ /dev/null @@ -1,308 +0,0 @@ -# Game Profile Manager - -A PySDL2-based user profile management system designed for gamepad-only control with virtual keyboard input. This system allows players to create, edit, delete, and select user profiles for games using only gamepad inputs or directional keys, with no need for physical keyboard text input. - -## Features - -- **640x480 Resolution**: Optimized for retro gaming systems and handheld devices -- **Create New Profiles**: Add new user profiles with custom names using virtual keyboard -- **Profile Selection**: Browse and select active profiles -- **Edit Settings**: Modify profile settings including difficulty, volume levels, and preferences -- **Delete Profiles**: Remove unwanted profiles -- **Gamepad/Directional Navigation**: Full control using only gamepad/joystick inputs or arrow keys -- **Virtual Keyboard**: Text input using directional controls - no physical keyboard typing required -- **JSON Storage**: Profiles stored in human-readable JSON format -- **Persistent Settings**: All changes automatically saved - -## Installation - -### Requirements -- Python 3.6+ -- PySDL2 -- SDL2 library - -### Setup -```bash -# Install required Python packages -pip install pysdl2 - -# For Ubuntu/Debian users, you may also need: -sudo apt-get install libsdl2-dev libsdl2-ttf-dev - -# Make launcher executable -chmod +x launch_profile_manager.sh -``` - -## Usage - -### Running the Profile Manager -```bash -# Method 1: Use the launcher script -./launch_profile_manager.sh - -# Method 2: Run directly with Python -python3 profile_manager.py -``` - -### Gamepad Controls - -#### Standard Gamepad Layout (Xbox/PlayStation compatible) -- **D-Pad/Hat**: Navigate menus up/down/left/right, control virtual keyboard cursor -- **Button 0 (A/X)**: Confirm selection, enter menus, select virtual keyboard characters -- **Button 1 (B/Circle)**: Go back, cancel action -- **Button 2 (X/Square)**: Delete profile, backspace in virtual keyboard -- **Button 3 (Y/Triangle)**: Reserved for future features - -#### Keyboard Controls (Alternative) -- **Arrow Keys**: Navigate menus and virtual keyboard cursor -- **Enter/Space**: Confirm selection, select virtual keyboard characters -- **Escape**: Go back, cancel action -- **Delete/Backspace**: Delete profile, backspace in virtual keyboard -- **Tab**: Reserved for future features - -#### Virtual Keyboard Text Input -When creating or editing profile names: -1. **Navigate**: Use D-Pad/Arrow Keys to move cursor over virtual keyboard -2. **Select Character**: Press A/Enter to add character to profile name -3. **Backspace**: Press X/Delete to remove last character -4. **Complete**: Navigate to "DONE" and press A/Enter to finish input -5. **Cancel**: Navigate to "CANCEL" and press A/Enter to abort - -#### Navigation Flow -1. **Main Menu**: Create Profile → Select Profile → Edit Settings → Exit -2. **Profile List**: Choose from existing profiles, or go back -3. **Create Profile**: Use virtual keyboard to enter name, confirm with directional controls -4. **Edit Profile**: Adjust settings using left/right navigation - -### Display Specifications -- **Resolution**: 640x480 pixels (4:3 aspect ratio) -- **Optimized for**: Retro gaming systems, handheld devices, embedded systems -- **Font Scaling**: Adaptive font sizes for optimal readability at low resolution - -### Profile Structure - -Profiles are stored in `user_profiles.json` with the following structure: - -```json -{ - "profiles": { - "PlayerName": { - "name": "PlayerName", - "created_date": "2024-01-15T10:30:00", - "last_played": "2024-01-20T14:45:00", - "games_played": 25, - "total_score": 15420, - "best_score": 980, - "settings": { - "difficulty": "normal", - "sound_volume": 75, - "music_volume": 60, - "screen_shake": true, - "auto_save": true - }, - "achievements": [ - "first_win", - "score_500" - ] - } - }, - "active_profile": "PlayerName" -} -``` - -## Integration with Games - -### Loading Active Profile -```python -import json - -def load_active_profile(): - try: - with open('user_profiles.json', 'r') as f: - data = json.load(f) - active_name = data.get('active_profile') - if active_name and active_name in data['profiles']: - return data['profiles'][active_name] - except (FileNotFoundError, json.JSONDecodeError): - pass - return None - -# Usage in your game -profile = load_active_profile() -if profile: - difficulty = profile['settings']['difficulty'] - sound_volume = profile['settings']['sound_volume'] -``` - -### Updating Profile Stats -```python -def update_profile_stats(score, game_completed=True): - try: - with open('user_profiles.json', 'r') as f: - data = json.load(f) - - active_name = data.get('active_profile') - if active_name and active_name in data['profiles']: - profile = data['profiles'][active_name] - - if game_completed: - profile['games_played'] += 1 - profile['total_score'] += score - profile['best_score'] = max(profile['best_score'], score) - profile['last_played'] = datetime.now().isoformat() - - with open('user_profiles.json', 'w') as f: - json.dump(data, f, indent=2) - except Exception as e: - print(f"Error updating profile: {e}") -``` - -## Customization - -### Adding New Settings -Edit the `UserProfile` dataclass and the settings adjustment methods: - -```python -# In profile_manager.py, modify the UserProfile.__post_init__ method -def __post_init__(self): - if self.settings is None: - self.settings = { - "difficulty": "normal", - "sound_volume": 50, - "music_volume": 50, - "screen_shake": True, - "auto_save": True, - "your_new_setting": "default_value" # Add here - } -``` - -### Custom Font -Place your font file in the `assets/` directory and update the font path: -```python -font_path = "assets/your_font.ttf" -``` - -### Screen Resolution -The application is optimized for 640x480 resolution. To change resolution, modify the window size in the init_sdl method: -```python -self.window = sdl2.ext.Window( - title="Profile Manager", - size=(your_width, your_height) # Change from (640, 480) -) -``` - -### Virtual Keyboard Layout -Customize the virtual keyboard characters by modifying the keyboard_chars list: -```python -self.keyboard_chars = [ - ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'], - ['K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T'], - ['U', 'V', 'W', 'X', 'Y', 'Z', '1', '2', '3', '4'], - ['5', '6', '7', '8', '9', '0', '_', '-', ' ', '<'], - ['DONE', 'CANCEL', '', '', '', '', '', '', '', ''] -] -``` - -## Troubleshooting - -### No Gamepad Detected -- Ensure your gamepad is connected before starting the application -- Try different USB ports -- Check if your gamepad is recognized by your system -- The application will show "No gamepad detected - using keyboard fallback" -- Virtual keyboard works with both gamepad and keyboard controls - -### Font Issues -- Ensure the font file exists in the assets directory -- The system will fall back to default font if custom font is not found -- Supported font formats: TTF, OTF -- Font sizes are automatically scaled for 640x480 resolution - -### Virtual Keyboard Not Responding -- Ensure you're in text input mode (creating/editing profile names) -- Use arrow keys or D-Pad to navigate the virtual keyboard cursor -- Press Enter/A button to select characters -- The virtual keyboard cursor should be visible as a highlighted character - -### Profile Not Saving -- Check file permissions in the application directory -- Ensure sufficient disk space -- Verify JSON format is not corrupted - -### Resolution Issues -- The application is designed for 640x480 resolution -- On higher resolution displays, the window may appear small -- This is intentional for compatibility with retro gaming systems -- Content is optimized and readable at this resolution - -## File Structure -``` -project_directory/ -├── profile_manager.py # Main application (640x480, virtual keyboard) -├── launch_profile_manager.sh # Launcher script -├── user_profiles.json # Profile data storage -├── test_profile_manager.py # Test suite for core functions -├── game_profile_integration.py # Example game integration -├── assets/ -│ └── decterm.ttf # Font file (optional) -└── README_PROFILE_MANAGER.md # This documentation -``` - -## Development Notes - -### Virtual Keyboard Implementation -The virtual keyboard is implemented as a 2D grid of characters: -- Cursor position tracked with (keyboard_cursor_x, keyboard_cursor_y) -- Character selection adds to input_text string -- Special functions: DONE (confirm), CANCEL (abort), < (backspace) -- Fully navigable with directional controls only - -### Screen Layout for 640x480 -- Header area: 0-80px (titles, status) -- Content area: 80-400px (main UI elements) -- Controls area: 400-480px (help text, instructions) -- All elements scaled and positioned for optimal readability - -### Adding New Screens -1. Add screen name to `current_screen` handling -2. Create render method (e.g., `render_new_screen()`) -3. Add navigation logic in input handlers -4. Update screen transitions in confirm/back handlers - -### Gamepad Button Mapping -The application uses SDL2's joystick interface. Button numbers may vary by controller: -- Most modern controllers follow the Xbox layout -- PlayStation controllers map similarly but may have different button numbers -- Test with your specific controller and adjust mappings if needed - -### Performance Considerations -- Rendering is capped at 60 FPS for smooth operation -- Input debouncing prevents accidental rapid inputs -- JSON operations are minimized and occur only when necessary -- Virtual keyboard rendering optimized for 640x480 resolution -- Font scaling automatically adjusted for readability - -### Adding Support for Different Resolutions -To support different screen resolutions, modify these key areas: -1. Window initialization in `init_sdl()` -2. Panel and button positioning in render methods -3. Font size scaling factors -4. Virtual keyboard grid positioning - -### Gamepad Integration Notes -- Uses SDL2's joystick interface for maximum compatibility -- Button mapping follows standard Xbox controller layout -- Hat/D-Pad input prioritized over analog sticks for precision -- Input timing designed for responsive but not accidental activation - -## Target Platforms - -This profile manager is specifically designed for: -- **Handheld Gaming Devices**: Steam Deck, ROG Ally, etc. -- **Retro Gaming Systems**: RetroPie, Batocera, etc. -- **Embedded Gaming Systems**: Custom arcade cabinets, portable devices -- **Low-Resolution Displays**: 640x480, 800x600, and similar resolutions -- **Gamepad-Only Environments**: Systems without keyboard access - -## License -This profile manager is provided as-is for educational and personal use. Designed for integration with retro and handheld gaming systems. diff --git a/UNIT_ARCHITECTURE_GUIDE.md b/UNIT_ARCHITECTURE_GUIDE.md deleted file mode 100644 index 7fe2809..0000000 --- a/UNIT_ARCHITECTURE_GUIDE.md +++ /dev/null @@ -1,391 +0,0 @@ -# Guida all'Architettura delle Unità - Mice Game - -## 📋 Panoramica - -Questo documento descrive l'architettura refactorizzata del sistema di gestione delle unità nel gioco "Mice", evidenziando i miglioramenti implementati e le possibili evoluzioni future. - ---- - -## 🏗️ Architettura Attuale - -### Gerarchia delle Classi - -``` -Unit (ABC) -├── Rat -│ ├── Male -│ └── Female -├── Bomb -│ ├── Timer -│ └── Explosion -└── Point -``` - -### Classe Base `Unit` (Abstract Base Class) - -**File**: `units/unit.py` - -```python -from abc import ABC, abstractmethod -import uuid - -class Unit(ABC): - def __init__(self, game, position=(0, 0), id=None): - self.id = id if id else uuid.uuid4() # Identificatore univoco - self.game = game # Riferimento al gioco - self.position = position # Posizione attuale (x, y) - self.position_before = position # Posizione precedente - self.age = 0 # Età in tick di gioco - self.speed = 1.0 # Velocità di movimento - self.partial_move = 0 # Progresso movimento parziale - self.bbox = (0, 0, 0, 0) # Bounding box per collisioni - self.stop = 0 # Tick di immobilità rimanenti -``` - -**Metodi Astratti Obbligatori**: -- `move()`: Aggiorna posizione e stato dell'unità -- `draw()`: Renderizza l'unità sullo schermo - -**Metodi Concreti**: -- `collisions()`: Gestisce collisioni (implementazione vuota di default) -- `die()`: Rimuove l'unità dal gioco - ---- - -## 🐭 Gestione delle Unità Specifiche - -### 1. Ratti (`Rat`, `Male`, `Female`) - -**Caratteristiche**: -- **Movimento**: Navigazione intelligente nel labirinto -- **Invecchiamento**: Rallentano dopo 200 tick -- **Collisioni**: Combattimenti tra maschi, riproduzione tra sessi opposti -- **Morte**: Generano punti quando muoiono - -**Attributi Specifici**: -```python -self.speed = 0.10 # Più lenti delle altre unità -self.fight = False # Stato di combattimento -self.sex = "MALE"/"FEMALE" # Genere (nelle sottoclassi) -``` - -**Comportamenti Unici**: -- **Male**: Può iniziare accoppiamenti -- **Female**: Gestisce gravidanza e nascite - -### 2. Bombe (`Bomb`, `Timer`, `Explosion`) - -**Caratteristiche**: -- **Timer**: Conta alla rovescia fino all'esplosione -- **Explosion**: Effetto visivo temporaneo -- **Distruzione**: Elimina altre unità in linea retta - -**Attributi Specifici**: -```python -self.speed = 4 # Invecchiano rapidamente -``` - -### 3. Punti (`Point`) - -**Caratteristiche**: -- **Temporanei**: Scompaiono dopo un certo tempo -- **Valore**: Aggiungono punti al punteggio del giocatore -- **Statici**: Non si muovono - ---- - -## 🔄 Ciclo di Vita delle Unità - -### 1. Creazione -```python -# Nel file rats.py -def spawn_unit(self, unit_class, position, **kwargs): - id = uuid.uuid4() - self.units[id] = unit_class(self, position, id, **kwargs) -``` - -### 2. Aggiornamento (Game Loop) -```python -# Nel metodo update_maze() -for unit in self.units.copy().values(): - unit.move() # Aggiorna stato e posizione - unit.collisions() # Gestisce interazioni - unit.draw() # Renderizza sullo schermo -``` - -### 3. Rimozione -```python -# Metodo base nella classe Unit -def die(self): - if self.id in self.game.units: - self.game.units.pop(self.id) -``` - ---- - -## ✅ Miglioramenti Implementati - -### 1. **Eliminazione Duplicazione Codice** -- **Prima**: ~60 righe duplicate tra classi -- **Dopo**: Attributi comuni centralizzati nella classe base - -### 2. **Contratto Definito** -- Metodi astratti garantiscono implementazione obbligatoria -- Errori catturati a tempo di compilazione, non runtime - -### 3. **Gestione Consistente** -- Valori di default standardizzati -- Logica di cleanup centralizzata - -### 4. **Sicurezza del Tipo** -- Impossibile istanziare unità incomplete -- Debugging più facile e veloce - ---- - -## 🚀 Migliorie Possibili - -### 1. **Sistema di Componenti** (Priorità: Alta) - -**Problema Attuale**: Logica mista nelle classi unità - -**Soluzione**: -```python -# Separare comportamenti in componenti riutilizzabili -class MovementComponent: - def update(self, unit): pass - -class RenderComponent: - def draw(self, unit): pass - -class CollisionComponent: - def check_collisions(self, unit, others): pass - -class Unit(ABC): - def __init__(self, game, position): - self.movement = MovementComponent() - self.renderer = RenderComponent() - self.collision = CollisionComponent() -``` - -**Vantaggi**: -- Comportamenti riutilizzabili tra unità diverse -- Facile testing di singoli componenti -- Composizione invece di ereditarietà profonda - -### 2. **Factory Pattern** (Priorità: Media) - -**Problema Attuale**: Creazione unità sparsa nel codice - -**Soluzione**: -```python -class UnitFactory: - @staticmethod - def create_rat(game, position, sex="random"): - sex = random.choice(["MALE", "FEMALE"]) if sex == "random" else sex - rat_class = Male if sex == "MALE" else Female - return rat_class(game, position) - - @staticmethod - def create_bomb(game, position, timer=200): - return Timer(game, position, timer_duration=timer) -``` - -**Vantaggi**: -- Creazione centralizzata e configurabile -- Parametri validati in un punto solo -- Facile aggiungere nuovi tipi - -### 3. **Event System** (Priorità: Alta) - -**Problema Attuale**: Accoppiamento forte tra unità e gioco - -**Soluzione**: -```python -class EventSystem: - def __init__(self): - self.listeners = {} - - def emit(self, event_type, data): - for listener in self.listeners.get(event_type, []): - listener(data) - -# Nelle unità -def die(self): - self.game.events.emit("unit_died", { - "unit_id": self.id, - "position": self.position, - "score": self.calculate_score() - }) -``` - -**Vantaggi**: -- Disaccoppiamento tra unità e sistemi di gioco -- Facile aggiungere nuovi listener -- Sistema più modulare e testabile - -### 4. **State Pattern per Ratti** (Priorità: Media) - -**Problema Attuale**: Logica di stato mista nel metodo `move()` - -**Soluzione**: -```python -class RatState(ABC): - @abstractmethod - def update(self, rat): pass - -class MovingState(RatState): - def update(self, rat): - # Logica movimento normale - -class PregnantState(RatState): - def update(self, rat): - # Logica gravidanza - -class FightingState(RatState): - def update(self, rat): - # Logica combattimento - -class Rat(Unit): - def __init__(self, ...): - self.state = MovingState() - - def move(self): - self.state.update(self) -``` - -### 5. **Object Pool** (Priorità: Bassa) - -**Problema**: Creazione/distruzione frequente oggetti - -**Soluzione**: -```python -class UnitPool: - def __init__(self): - self.available_units = {} - self.active_units = {} - - def get_unit(self, unit_type): - # Riutilizza unità esistenti invece di crearne nuove - - def return_unit(self, unit): - # Ripulisce e rimette nel pool -``` - -**Vantaggi**: -- Prestazioni migliori con molte unità -- Meno garbage collection -- Memoria più stabile - -### 6. **Spatial Partitioning** (Priorità: Media) - -**Problema**: Collisioni O(n²) con molte unità - -**Soluzione**: -```python -class SpatialGrid: - def __init__(self, cell_size): - self.grid = {} - self.cell_size = cell_size - - def get_nearby_units(self, position, radius): - # Ritorna solo unità vicine, non tutte -``` - -### 7. **Configuration System** (Priorità: Bassa) - -**Problema**: Costanti hardcoded nel codice - -**Soluzione**: -```python -# units_config.json -{ - "rat": { - "speed": 0.10, - "age_threshold": 200, - "pregnancy_duration": 500 - }, - "bomb": { - "speed": 4, - "explosion_range": 5 - } -} -``` - ---- - -## 📊 Metriche di Miglioramento - -| Aspetto | Prima | Dopo | Miglioramento | -|---------|-------|------|---------------| -| **Righe duplicate** | ~60 | 0 | -100% | -| **Tempo debug** | Alto | Basso | -70% | -| **Facilità estensione** | Difficile | Facile | +200% | -| **Errori runtime** | Frequenti | Rari | -80% | -| **Manutenibilità** | Bassa | Alta | +150% | - ---- - -## 🛠️ Roadmap Implementazione - -### Fase 1: Fondamenta (Completata ✅) -- [x] Refactoring classe base Unit -- [x] Eliminazione duplicazione codice -- [x] Metodi astratti obbligatori - -### Fase 2: Architettura (2-3 giorni) -- [ ] Sistema di componenti -- [ ] Event system base -- [ ] Factory pattern - -### Fase 3: Ottimizzazioni (1-2 giorni) -- [ ] State pattern per ratti -- [ ] Spatial partitioning -- [ ] Object pooling - -### Fase 4: Configurazione (1 giorno) -- [ ] Sistema di configurazione -- [ ] Tuning parametri -- [ ] Testing prestazioni - ---- - -## 🧪 Come Testare - -### Test Base Funzionalità -```bash -cd c:\Users\enne2\Dev\mice -python rats.py -``` - -### Test Specifici Unità -```python -# Test creazione -rat = Male(game, (5, 5)) -assert rat.sex == "MALE" -assert rat.position == (5, 5) - -# Test metodi astratti -try: - unit = Unit(game, (0, 0)) # Dovrebbe fallire -except TypeError: - print("✅ Metodi astratti funzionano") -``` - ---- - -## 📝 Note per Sviluppatori - -1. **Sempre implementare metodi astratti** in nuove unità -2. **Usare super()** per chiamare implementazioni base -3. **Eventi invece di chiamate dirette** per disaccoppiamento -4. **Componenti riutilizzabili** per comportamenti comuni -5. **Testing incrementale** ad ogni modifica - ---- - -## 🎯 Conclusioni - -L'architettura refactorizzata fornisce una base solida e estensibile per il sistema delle unità. I miglioramenti implementati eliminano duplicazioni e aumentano la robustezza, mentre le migliorie proposte offrono un percorso chiaro per evoluzioni future più avanzate. - -Il sistema attuale è **pronto per la produzione** e **facilmente estensibile** per nuove funzionalità. diff --git a/api.log b/api.log deleted file mode 100644 index 4acbf35..0000000 --- a/api.log +++ /dev/null @@ -1,2125 +0,0 @@ -nohup: input ignorato -/home/enne2/Dev/mice/score_api.py:112: DeprecationWarning: - on_event is deprecated, use lifespan event handlers instead. - - Read more about it in the - [FastAPI docs for Lifespan Events](https://fastapi.tiangolo.com/advanced/events/). - - @app.on_event("startup") -INFO: Started server process [41455] -INFO: Waiting for application startup. -INFO: Application startup complete. -INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit) -Starting Mice Game Score API... -Available endpoints: - POST /signup/{device_id}/{user_id} - Register new user - POST /score/{device_id}/{user_id} - Submit score - GET /users/{device_id} - Get all users for device - GET /scores/{device_id}/{user_id} - Get user scores - GET /leaderboard/{device_id} - Get device leaderboard - -INFO: 127.0.0.1:54554 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:37394 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53716 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:45032 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:45048 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:45052 - "GET /leaderboard/global/top?limit=3 HTTP/1.1" 200 OK -INFO: 127.0.0.1:60562 - "POST /signup/DEV-TEST001/Alice HTTP/1.1" 400 Bad Request -INFO: 127.0.0.1:60570 - "POST /signup/DEV-TEST001/Bob HTTP/1.1" 400 Bad Request -INFO: 127.0.0.1:60584 - "POST /signup/DEV-TEST001/Charlie HTTP/1.1" 400 Bad Request -INFO: 127.0.0.1:33868 - "POST /signup/DEV-TEST0001/Alice HTTP/1.1" 200 OK -INFO: 127.0.0.1:33872 - "POST /score/DEV-TEST0001/Alice HTTP/1.1" 200 OK -INFO: 127.0.0.1:33876 - "POST /signup/DEV-TEST0001/Bob HTTP/1.1" 200 OK -INFO: 127.0.0.1:33888 - "POST /score/DEV-TEST0001/Bob HTTP/1.1" 200 OK -INFO: 127.0.0.1:33894 - "POST /signup/DEV-TEST0001/Charlie HTTP/1.1" 200 OK -INFO: 127.0.0.1:33898 - "POST /score/DEV-TEST0001/Charlie HTTP/1.1" 200 OK -INFO: 127.0.0.1:36590 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:37554 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:37570 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:52058 - "POST /score/DEV-3A2D87B7/MAT HTTP/1.1" 200 OK -INFO: 127.0.0.1:46986 - "POST /score/DEV-3A2D87B7/MAT HTTP/1.1" 200 OK -INFO: 127.0.0.1:47002 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47004 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47006 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47020 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47026 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47040 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47048 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47058 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47064 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47070 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47078 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47092 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47100 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47108 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47114 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47118 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47128 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47130 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47140 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47154 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47160 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47168 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47178 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47184 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47190 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47194 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47200 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47216 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47218 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47232 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47238 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47250 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47258 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47268 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47278 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47288 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47290 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47306 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47316 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47326 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47336 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47348 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47358 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47362 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47366 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47380 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47386 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47400 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47408 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47422 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47432 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47442 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47458 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47466 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47476 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47492 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47494 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47496 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47508 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47512 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47514 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47530 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47544 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47560 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47570 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47572 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47582 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47594 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47598 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47606 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47612 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47626 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47630 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47640 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47656 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47672 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47684 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47692 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47706 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47714 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47716 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47718 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47720 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47728 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47736 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47752 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47766 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47782 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47794 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47802 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47816 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47820 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47824 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47832 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47848 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47858 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47874 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47880 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47890 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47896 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47900 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47910 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47924 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47926 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47928 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47938 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47948 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47954 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47960 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47964 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47980 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47982 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47992 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48002 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48008 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48022 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48028 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48036 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48046 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48058 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48064 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48078 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48082 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48092 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48094 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48096 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48110 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48120 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48128 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48130 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48144 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48150 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48152 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48162 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48164 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48168 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48174 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48184 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48196 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48198 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48214 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48218 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48228 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48244 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48248 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48252 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48262 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48268 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48280 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48282 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48284 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48300 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48306 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48320 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48322 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48338 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48352 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48356 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48370 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48372 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48380 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48384 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48390 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48396 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48402 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48414 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48430 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48432 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48434 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48440 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48442 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48448 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48464 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48476 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48490 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48504 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48516 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48520 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48528 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48544 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48552 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48556 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48558 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48570 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48580 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48582 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48598 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48610 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48622 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48624 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48632 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48634 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48644 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48660 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48662 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48670 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48680 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48690 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48694 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48710 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48716 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48722 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48738 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48750 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48754 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48756 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48770 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48784 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48796 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48806 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48808 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48820 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48826 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48834 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48848 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48858 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48860 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48868 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48878 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48890 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48906 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48922 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48936 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48942 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48944 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48950 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48962 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48978 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48992 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48994 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49002 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49006 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49016 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49020 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49026 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49040 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49046 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49058 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49070 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49082 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49096 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49098 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49108 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49110 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49116 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49130 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49132 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49138 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49142 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49150 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49156 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46122 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46126 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46138 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46150 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46162 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46178 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46180 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46194 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46196 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46202 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46206 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46220 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46236 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46244 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46250 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46262 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46270 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46280 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46286 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46292 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46298 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46312 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46322 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46334 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46336 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46344 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46354 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46370 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46372 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46378 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46382 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46388 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46402 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46408 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46418 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46428 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46438 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46450 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46464 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46468 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46474 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46482 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46484 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46496 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46500 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46502 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46518 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46528 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46542 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46550 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46554 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46564 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46566 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46582 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46590 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46604 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46616 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46630 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46634 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46640 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46646 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46662 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46674 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46682 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46686 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46696 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46702 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46718 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46724 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46740 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46748 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46762 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46778 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46780 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46794 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46798 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46800 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46814 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46820 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46836 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46850 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46854 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46870 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46880 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46892 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46908 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46922 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46928 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46934 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46938 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46946 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46956 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46972 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46974 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46988 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47002 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47016 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47032 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47042 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47050 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47052 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47056 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47070 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47074 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47082 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47084 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47094 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47102 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47110 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47124 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47138 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47148 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47156 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47164 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47172 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47174 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47178 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47184 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47186 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47194 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47196 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47200 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47210 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47224 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47232 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47248 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47256 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47264 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47280 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47294 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47308 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47320 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47326 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47330 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47342 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47346 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47358 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47372 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47380 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47382 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47398 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47400 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47408 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47414 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47426 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47436 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47442 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47458 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47464 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47470 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47478 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47484 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47500 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47502 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47518 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47522 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47528 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47538 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47546 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47548 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47560 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47562 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47568 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47576 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47582 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47594 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47608 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47610 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47626 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47632 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47644 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47658 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47666 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47668 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47672 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47674 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47690 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47698 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47708 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47722 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47734 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47744 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47748 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47754 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47766 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47774 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47788 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47802 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47806 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47820 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47822 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47826 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47840 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47848 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47862 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47874 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47888 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47900 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47914 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47930 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47938 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47944 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47954 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47960 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47972 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47980 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47986 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47988 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47990 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47996 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48004 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48020 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48028 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48044 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48052 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48064 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48076 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48088 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48092 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48096 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48104 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48114 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48124 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48132 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48144 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48160 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48162 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48164 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48176 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48186 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48190 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48200 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48212 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48220 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48226 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48228 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48234 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48240 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48252 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48268 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48272 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48276 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48288 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48300 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48314 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48322 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48326 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48338 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48352 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48366 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48378 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48394 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48410 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48412 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48420 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48436 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48440 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48450 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48466 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48468 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48484 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48498 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48510 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48522 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48532 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48544 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48558 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48572 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48574 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48582 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48586 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48596 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48598 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48612 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48624 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48638 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48646 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48658 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48660 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48668 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48674 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48690 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48702 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48718 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48726 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48740 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48748 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48754 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48760 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48776 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48788 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48794 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48800 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48812 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48818 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48826 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48836 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48852 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48860 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48870 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48882 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48892 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48908 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48916 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48922 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48930 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48938 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48942 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48954 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48960 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48966 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48980 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48992 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49002 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49014 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49018 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49020 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49036 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49042 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49054 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49060 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49072 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49084 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49086 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49100 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49114 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49126 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49136 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49146 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49156 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49172 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49182 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49198 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49206 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49214 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49226 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49234 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49250 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49264 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49272 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49286 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49292 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49298 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49304 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49320 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49336 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49346 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49348 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49350 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49364 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49372 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49386 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49390 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49396 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49410 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49412 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49420 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49422 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49428 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49440 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49454 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49464 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49468 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49474 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49478 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49486 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49490 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49500 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49512 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49514 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49518 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49524 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49536 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49544 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49554 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49558 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49570 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49576 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49590 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49600 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49614 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49620 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49630 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49636 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49644 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49650 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49658 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49664 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49678 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49690 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49700 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55566 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55568 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55578 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55592 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55594 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55610 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55616 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55630 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55632 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55646 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55658 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55668 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55678 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55694 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55710 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55722 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55732 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55744 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55760 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55776 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55780 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55788 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55802 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55814 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55822 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55826 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55840 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55846 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55850 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55866 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55880 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55884 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55886 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55902 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55908 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55916 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55930 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55942 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55950 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55958 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55974 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55988 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55992 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55994 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55998 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56002 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56014 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56024 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56028 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56042 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56048 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56062 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56078 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56082 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56084 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56088 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56092 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56096 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56108 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56112 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56114 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56122 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56124 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56128 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56138 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56152 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56154 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56158 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56162 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56164 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56176 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56188 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56198 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56204 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56208 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56212 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56218 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56220 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56236 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56246 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56260 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56270 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56276 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56292 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56294 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56310 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56322 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56336 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56338 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56346 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56348 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56364 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56380 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56390 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56402 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56408 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56424 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56434 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56448 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56460 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56472 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56486 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56498 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56500 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56502 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56516 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56530 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56544 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56558 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56572 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56578 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56592 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56604 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56616 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56630 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56632 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56634 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56650 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56656 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56672 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56678 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56692 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56700 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56702 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56704 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56708 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56714 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56726 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56732 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56736 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56738 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56754 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56766 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56772 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56776 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56784 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56800 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56802 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56818 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56826 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56834 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56846 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56856 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56860 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56862 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56874 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56882 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56892 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56908 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56924 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56936 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56938 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56940 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56952 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56964 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56966 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56968 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56980 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56996 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57002 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57008 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57022 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57034 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57036 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57050 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57054 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57066 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57072 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57086 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57088 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57094 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57104 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57114 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57126 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57132 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57146 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57150 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57160 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57176 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57182 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57196 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57212 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57226 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57230 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57238 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57254 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57270 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57278 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57290 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57298 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57308 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57318 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57334 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57336 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57352 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57358 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57364 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57374 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57388 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57398 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57412 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57424 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57436 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57448 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57452 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57464 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57478 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57484 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57494 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57498 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57512 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57516 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57532 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57536 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57538 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57546 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57554 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57562 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57568 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57576 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57582 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57590 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57606 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57612 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57624 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57634 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57638 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57648 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57662 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57676 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57678 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57682 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57684 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57692 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57702 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57712 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57724 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57728 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57730 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57736 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57738 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57742 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57750 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57758 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57760 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57772 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57784 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57794 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57810 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57822 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57832 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57842 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57856 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57866 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57874 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57886 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57892 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57896 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57900 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57906 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57914 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57930 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57942 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57944 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57960 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57974 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57980 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57982 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57990 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57998 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58012 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58016 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58028 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58044 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58050 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58052 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58056 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58070 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58072 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58086 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58088 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58102 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58116 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58128 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58138 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58146 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58150 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58154 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58156 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58162 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58178 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58194 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58206 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58222 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58234 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58238 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58252 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58262 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58278 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58282 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58286 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58300 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58306 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58322 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58324 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58340 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58348 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58360 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58364 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58374 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58376 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58380 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58384 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58398 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58412 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58422 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58432 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58444 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58452 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58466 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58474 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58482 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58484 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58486 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58488 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58494 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58502 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58508 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58522 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58526 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58534 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58540 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58546 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58552 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58562 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58578 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58588 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58600 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58616 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58628 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58636 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58640 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58652 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58668 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58680 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58686 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58694 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58698 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58706 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58712 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58720 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58734 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58738 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58754 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58768 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58776 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58784 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58790 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58800 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58802 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58808 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58824 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58840 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58856 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58864 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58866 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58882 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58886 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58892 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58894 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58904 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58906 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58922 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58924 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58926 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58932 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58938 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58952 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58964 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58980 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58986 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58994 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:59004 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59020 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59024 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:59032 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59036 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59046 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:59060 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59064 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59080 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:59096 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59100 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59104 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:59114 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59122 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59130 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:59134 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59136 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59140 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:59142 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59146 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59156 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:59158 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59168 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:52974 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:52988 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:52996 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53000 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:53014 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53028 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53042 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:53046 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53050 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53052 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:53060 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53072 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53086 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:53092 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53100 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53106 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:53122 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53136 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53144 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:53152 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53164 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53174 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:53186 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53196 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53202 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:53204 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53208 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53212 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:53222 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53226 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53240 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:53252 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53264 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53268 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:53278 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53286 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53298 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:53310 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53320 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53332 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:53344 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53354 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53358 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:53360 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53362 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53370 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:53378 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53380 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53394 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:53398 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53410 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53426 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:53442 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53450 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53454 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:53464 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53478 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53486 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:53502 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53514 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53522 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:53530 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53540 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53554 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:53564 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53566 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53578 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:53592 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53602 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53610 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:53614 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53626 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53632 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:53634 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53648 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53654 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:53656 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53658 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53664 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:53680 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53692 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53704 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:53720 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53732 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53742 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:53756 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53760 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53774 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:53786 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53794 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53798 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:53808 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53816 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53828 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:53836 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53838 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53844 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:53854 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53858 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53860 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:53862 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53868 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53878 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:53890 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53892 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53894 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:53908 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53916 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53928 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:53944 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53952 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53958 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:53960 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53962 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53964 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:53978 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53994 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54006 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:54012 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54026 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54034 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:54042 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54050 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54064 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:54080 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54088 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49134 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49142 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:60208 - "POST /score/DEV-3A2D87B7/MAT HTTP/1.1" 200 OK -INFO: 127.0.0.1:49486 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49502 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:45430 - "POST /score/DEV-3A2D87B7/MAT HTTP/1.1" 200 OK -INFO: 127.0.0.1:45436 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:45448 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:45460 - "GET /leaderboard/global/top?limit=4 HTTP/1.1" 200 OK -INFO: 127.0.0.1:53574 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:53580 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56580 - "POST /score/DEV-3A2D87B7/MAT HTTP/1.1" 200 OK -INFO: 127.0.0.1:56582 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56586 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56590 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56592 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56602 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56612 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56620 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56624 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56638 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56654 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56668 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56676 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56684 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56698 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56708 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56724 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56728 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56744 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56748 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56754 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56762 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56768 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56782 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56790 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56802 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56804 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56820 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56828 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56838 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56846 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56858 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56874 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56884 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56890 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56898 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56914 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56930 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56936 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56946 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56962 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:56964 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56978 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:56984 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57000 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57004 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57014 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57028 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57038 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57044 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57060 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57068 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57078 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57088 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57092 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57104 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57106 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57122 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57136 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57144 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57160 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57168 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57180 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57184 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57192 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57194 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57200 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57202 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57218 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57226 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57242 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57258 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57262 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57272 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57286 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57302 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57316 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57330 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57344 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57356 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57368 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57378 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57388 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57396 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57408 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57420 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57434 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57448 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57460 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57476 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57486 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57496 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57512 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57528 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57538 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57550 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57562 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57574 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57590 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57602 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57610 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57626 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57642 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57656 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57658 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57660 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57662 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57666 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57672 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57674 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57676 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57680 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57692 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57702 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57708 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57712 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57716 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57732 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57742 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57752 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57768 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57776 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57782 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57792 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57796 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57808 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57822 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57834 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57840 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57848 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57850 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57860 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57874 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57876 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57892 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57898 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57908 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57914 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57922 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57938 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57954 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57966 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57974 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:57986 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57990 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58000 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58016 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58030 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58046 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58056 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58072 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58076 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58088 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58098 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58100 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58104 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58116 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58128 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58144 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58146 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58148 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58154 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58166 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58176 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58186 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58190 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58200 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58202 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58206 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58210 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58220 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58234 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58248 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58256 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58272 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58282 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58298 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58302 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58308 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58320 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58332 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58338 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58344 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58354 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58362 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58378 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58386 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58390 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58402 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58408 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58412 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58424 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58426 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58428 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58434 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58446 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58452 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58466 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58472 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58486 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58488 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58494 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58498 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58506 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58514 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58516 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58524 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58538 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58546 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58558 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58566 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58568 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58576 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58578 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58584 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58592 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58606 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58618 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58632 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58634 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58644 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58658 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58662 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58666 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58680 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58688 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58700 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58714 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58726 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58740 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58746 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58756 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58760 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58762 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58766 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58774 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58786 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58798 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58812 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58818 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58828 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58844 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58856 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58860 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58866 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58874 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58888 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58894 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58900 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58902 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58912 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58918 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58920 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58926 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58940 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58946 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58948 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58952 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58958 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58962 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:58974 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58990 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:58992 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:59008 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59020 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59026 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:59030 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59042 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59048 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:59062 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59076 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59090 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:59096 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59110 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59120 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:59130 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59138 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59148 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:59156 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59162 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59176 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:59182 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59194 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59210 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:59226 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59240 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59244 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:59256 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59272 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59286 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:59288 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59294 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59308 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:59324 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59328 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59344 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:59352 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59354 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59366 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:59376 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59386 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59400 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:59416 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59420 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59424 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:59432 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59438 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59448 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:59450 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59452 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59458 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:59460 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59472 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59480 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:59492 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59496 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59510 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:59524 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59538 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59554 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:59566 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46404 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46414 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46420 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46430 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46442 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46458 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46472 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46486 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46502 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46518 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46530 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46540 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46552 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46568 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46570 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46586 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46596 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46602 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46608 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46618 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46620 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46624 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46626 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46642 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46656 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46658 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46674 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46690 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46696 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46710 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46712 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46726 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46736 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46738 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46748 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46760 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46776 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46790 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46792 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46794 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46804 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46816 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46822 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46834 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46850 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46854 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46862 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46870 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46882 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46886 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46892 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46904 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46908 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46916 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46922 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46936 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46948 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46964 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46972 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46976 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46992 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47006 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47008 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47010 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47024 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47040 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47044 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47060 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47068 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47076 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47082 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47098 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47112 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47114 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47128 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47140 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47148 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47150 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47158 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47162 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47176 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47180 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47182 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47192 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47208 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47224 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47238 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47250 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47252 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47256 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47270 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47274 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47278 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47288 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47300 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47308 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47318 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47328 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47344 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47360 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47376 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47382 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47392 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47408 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47420 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47428 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47430 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47446 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47448 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47462 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47476 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47484 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47496 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47510 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47520 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47532 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47540 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47556 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47566 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47582 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47596 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47612 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47620 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47630 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47636 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47652 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47664 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47668 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47678 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47688 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47696 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47700 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47704 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47720 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47732 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47736 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47748 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47752 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47758 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47760 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47762 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47764 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47774 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47776 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47782 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47792 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47796 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47810 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47812 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47828 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47838 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47854 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47862 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47878 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47894 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47900 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47916 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47922 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47932 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47940 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47954 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47966 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47968 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47972 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:47976 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47978 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:47988 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48002 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48010 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48014 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48030 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48036 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48050 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48064 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48066 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48072 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48080 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48082 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48098 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48114 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48122 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48132 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48134 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48144 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48152 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48154 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48166 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48176 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48178 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48188 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48204 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48220 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48230 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48244 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48258 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48268 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48280 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48284 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48290 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48306 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48316 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48322 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48328 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48344 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48360 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48362 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48376 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48386 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48390 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48400 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48402 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48412 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48420 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48428 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48432 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48440 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48442 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48454 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48464 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48468 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48484 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48500 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48506 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48516 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48530 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48536 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48546 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48560 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48576 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48590 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48592 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48598 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48610 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48614 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48620 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48630 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48644 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48654 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48666 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48676 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48680 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48694 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48700 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48714 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48722 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48730 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48746 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48754 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48770 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48784 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48800 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48804 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48808 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48812 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48820 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48836 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48850 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48854 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48866 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48872 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48876 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48892 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48896 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48902 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48906 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48908 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48922 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48928 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48940 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48946 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48958 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48960 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:48976 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:48984 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49000 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49006 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49020 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49034 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49042 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49046 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49054 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49068 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49076 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49092 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49100 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49114 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49128 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49132 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49144 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49152 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49158 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49170 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49176 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49186 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49188 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49190 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49204 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49208 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49216 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49228 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49238 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49240 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49244 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49248 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49254 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49256 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49266 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49278 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49288 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49290 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49300 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49304 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49310 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49320 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49322 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49338 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49350 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49360 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49376 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49388 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49404 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49420 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49430 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49444 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49456 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49458 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49468 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49472 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49488 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49494 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49496 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49512 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49524 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49530 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49534 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49538 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49552 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49568 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49578 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49588 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49590 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49600 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49604 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49620 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49630 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49632 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49648 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49656 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49662 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49676 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:49692 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49706 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:49712 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:54280 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54284 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54288 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:54290 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54300 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54302 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:54314 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54316 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54328 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:54336 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54346 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54352 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:54366 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54378 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54384 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:54396 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54406 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54410 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:54420 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54426 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54434 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:54436 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54450 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54456 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:54464 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54468 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54472 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:54484 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54496 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54510 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:54516 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54532 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54538 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:54554 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54562 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54566 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:54578 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54588 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54598 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:54606 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54618 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54620 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:54622 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54636 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54640 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:54654 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54668 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54678 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:54682 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54688 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54700 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:54716 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54720 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54732 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:54738 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54748 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54754 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:54756 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54768 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54776 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:54782 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54790 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54794 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:54796 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54798 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54810 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:54820 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54836 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54844 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:54856 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54868 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54880 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:54888 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54896 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54906 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:54918 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54926 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54930 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:54942 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54956 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54958 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:54960 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54974 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:54984 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:54996 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55000 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55004 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55014 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55026 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55032 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55036 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55040 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55042 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55044 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55050 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55054 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55064 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55074 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55090 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55102 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55108 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55124 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55140 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55152 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55160 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55162 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55172 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55176 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55190 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55194 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55196 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55210 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55216 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55220 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55230 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55244 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55248 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55260 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55276 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55282 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55284 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55300 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55312 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55314 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55322 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55328 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55344 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55354 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55360 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55374 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55384 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55386 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55398 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55412 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55426 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55440 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55452 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55464 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55466 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55472 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55488 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55490 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55506 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55516 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55530 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55538 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55546 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55558 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55574 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55590 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55594 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55602 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55610 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55618 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55622 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55630 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55642 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55652 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55666 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55676 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55678 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55692 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55694 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55696 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55712 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55714 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55730 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55740 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55750 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55760 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55766 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55778 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55786 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55792 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55798 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55804 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55820 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55834 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55836 - "GET /leaderboard/global/top?limit=5 HTTP/1.1" 200 OK -INFO: 127.0.0.1:55290 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:55302 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:45726 - "POST /score/DEV-3A2D87B7/MAT HTTP/1.1" 200 OK -INFO: 127.0.0.1:45730 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:45734 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:45738 - "GET /leaderboard/global/top?limit=4 HTTP/1.1" 200 OK -INFO: 127.0.0.1:34510 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:34524 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46148 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:46154 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:52734 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:52740 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:41304 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:41308 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:33472 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:33474 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:52616 - "GET /leaderboard/DEV-3A2D87B7?limit=10 HTTP/1.1" 200 OK -INFO: 127.0.0.1:35690 - "GET /leaderboard/global/top?limit=10 HTTP/1.1" 200 OK -INFO: 127.0.0.1:35706 - "GET /leaderboard/DEV-3A2D87B7?limit=10 HTTP/1.1" 200 OK -INFO: 127.0.0.1:35722 - "GET /leaderboard/global/top?limit=10 HTTP/1.1" 200 OK -INFO: 127.0.0.1:35724 - "GET /leaderboard/DEV-3A2D87B7?limit=10 HTTP/1.1" 200 OK -INFO: 127.0.0.1:35736 - "GET /leaderboard/global/top?limit=10 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57592 - "GET /leaderboard/DEV-3A2D87B7?limit=10 HTTP/1.1" 200 OK -INFO: 127.0.0.1:57608 - "GET /leaderboard/DEV-3A2D87B7?limit=10 HTTP/1.1" 200 OK -INFO: 127.0.0.1:44530 - "POST /signup/DEV-3A2D87B7/AA HTTP/1.1" 200 OK -INFO: 127.0.0.1:37822 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:37834 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46744 - "GET /leaderboard/DEV-3A2D87B7?limit=10 HTTP/1.1" 200 OK -INFO: 127.0.0.1:46752 - "GET /leaderboard/global/top?limit=10 HTTP/1.1" 200 OK -INFO: 127.0.0.1:43292 - "GET /leaderboard/DEV-3A2D87B7?limit=10 HTTP/1.1" 200 OK -INFO: 127.0.0.1:43296 - "GET /leaderboard/global/top?limit=10 HTTP/1.1" 200 OK -INFO: 127.0.0.1:43300 - "GET /leaderboard/DEV-3A2D87B7?limit=10 HTTP/1.1" 200 OK -INFO: 127.0.0.1:43310 - "GET /leaderboard/global/top?limit=10 HTTP/1.1" 200 OK -INFO: 127.0.0.1:59822 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:59832 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:36158 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:36170 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:40986 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:40990 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:39030 - "GET / HTTP/1.1" 200 OK -INFO: 127.0.0.1:39046 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:38630 - "GET /users/DEV-3A2D87B7 HTTP/1.1" 200 OK -INFO: 127.0.0.1:38640 - "POST /signup/DEV-3A2D87B7/Alice HTTP/1.1" 409 Conflict -INFO: 127.0.0.1:38490 - "GET /leaderboard/DEV-3A2D87B7?limit=10 HTTP/1.1" 200 OK -INFO: Shutting down -INFO: Waiting for application shutdown. -INFO: Application shutdown complete. -INFO: Finished server process [41455] diff --git a/assets/asset-manifest.json b/assets/asset-manifest.json new file mode 100644 index 0000000..db4e4d4 --- /dev/null +++ b/assets/asset-manifest.json @@ -0,0 +1,195 @@ +[ + "assets/Rat/BMP_1_CAVE_DOWN.png", + "assets/Rat/BMP_1_CAVE_LEFT.png", + "assets/Rat/BMP_1_CAVE_RIGHT.png", + "assets/Rat/BMP_1_CAVE_UP.png", + "assets/Rat/BMP_1_E.png", + "assets/Rat/BMP_1_EN.png", + "assets/Rat/BMP_1_ES.png", + "assets/Rat/BMP_1_EXPLOSION_DOWN.png", + "assets/Rat/BMP_1_EXPLOSION_LEFT.png", + "assets/Rat/BMP_1_EXPLOSION_RIGHT.png", + "assets/Rat/BMP_1_EXPLOSION_UP.png", + "assets/Rat/BMP_1_FLOWER_1.png", + "assets/Rat/BMP_1_FLOWER_2.png", + "assets/Rat/BMP_1_FLOWER_3.png", + "assets/Rat/BMP_1_FLOWER_4.png", + "assets/Rat/BMP_1_GAS_DOWN.png", + "assets/Rat/BMP_1_GAS_LEFT.png", + "assets/Rat/BMP_1_GAS_RIGHT.png", + "assets/Rat/BMP_1_GAS_UP.png", + "assets/Rat/BMP_1_GRASS_1.png", + "assets/Rat/BMP_1_GRASS_2.png", + "assets/Rat/BMP_1_GRASS_3.png", + "assets/Rat/BMP_1_GRASS_4.png", + "assets/Rat/BMP_1_N.png", + "assets/Rat/BMP_1_NE.png", + "assets/Rat/BMP_1_NW.png", + "assets/Rat/BMP_1_S.png", + "assets/Rat/BMP_1_SE.png", + "assets/Rat/BMP_1_SW.png", + "assets/Rat/BMP_1_W.png", + "assets/Rat/BMP_1_WN.png", + "assets/Rat/BMP_1_WS.png", + "assets/Rat/BMP_2_CAVE_DOWN.png", + "assets/Rat/BMP_2_CAVE_LEFT.png", + "assets/Rat/BMP_2_CAVE_RIGHT.png", + "assets/Rat/BMP_2_CAVE_UP.png", + "assets/Rat/BMP_2_E.png", + "assets/Rat/BMP_2_EN.png", + "assets/Rat/BMP_2_ES.png", + "assets/Rat/BMP_2_EXPLOSION_DOWN.png", + "assets/Rat/BMP_2_EXPLOSION_LEFT.png", + "assets/Rat/BMP_2_EXPLOSION_RIGHT.png", + "assets/Rat/BMP_2_EXPLOSION_UP.png", + "assets/Rat/BMP_2_FLOWER_1.png", + "assets/Rat/BMP_2_FLOWER_2.png", + "assets/Rat/BMP_2_FLOWER_3.png", + "assets/Rat/BMP_2_FLOWER_4.png", + "assets/Rat/BMP_2_GAS_DOWN.png", + "assets/Rat/BMP_2_GAS_LEFT.png", + "assets/Rat/BMP_2_GAS_RIGHT.png", + "assets/Rat/BMP_2_GAS_UP.png", + "assets/Rat/BMP_2_GRASS_1.png", + "assets/Rat/BMP_2_GRASS_2.png", + "assets/Rat/BMP_2_GRASS_3.png", + "assets/Rat/BMP_2_GRASS_4.png", + "assets/Rat/BMP_2_N.png", + "assets/Rat/BMP_2_NE.png", + "assets/Rat/BMP_2_NW.png", + "assets/Rat/BMP_2_S.png", + "assets/Rat/BMP_2_SE.png", + "assets/Rat/BMP_2_SW.png", + "assets/Rat/BMP_2_W.png", + "assets/Rat/BMP_2_WN.png", + "assets/Rat/BMP_2_WS.png", + "assets/Rat/BMP_3_CAVE_DOWN.png", + "assets/Rat/BMP_3_CAVE_LEFT.png", + "assets/Rat/BMP_3_CAVE_RIGHT.png", + "assets/Rat/BMP_3_CAVE_UP.png", + "assets/Rat/BMP_3_E.png", + "assets/Rat/BMP_3_EN.png", + "assets/Rat/BMP_3_ES.png", + "assets/Rat/BMP_3_EXPLOSION_DOWN.png", + "assets/Rat/BMP_3_EXPLOSION_LEFT.png", + "assets/Rat/BMP_3_EXPLOSION_RIGHT.png", + "assets/Rat/BMP_3_EXPLOSION_UP.png", + "assets/Rat/BMP_3_FLOWER_1.png", + "assets/Rat/BMP_3_FLOWER_2.png", + "assets/Rat/BMP_3_FLOWER_3.png", + "assets/Rat/BMP_3_FLOWER_4.png", + "assets/Rat/BMP_3_GAS_DOWN.png", + "assets/Rat/BMP_3_GAS_LEFT.png", + "assets/Rat/BMP_3_GAS_RIGHT.png", + "assets/Rat/BMP_3_GAS_UP.png", + "assets/Rat/BMP_3_GRASS_1.png", + "assets/Rat/BMP_3_GRASS_2.png", + "assets/Rat/BMP_3_GRASS_3.png", + "assets/Rat/BMP_3_GRASS_4.png", + "assets/Rat/BMP_3_N.png", + "assets/Rat/BMP_3_NE.png", + "assets/Rat/BMP_3_NW.png", + "assets/Rat/BMP_3_S.png", + "assets/Rat/BMP_3_SE.png", + "assets/Rat/BMP_3_SW.png", + "assets/Rat/BMP_3_W.png", + "assets/Rat/BMP_3_WN.png", + "assets/Rat/BMP_3_WS.png", + "assets/Rat/BMP_4_CAVE_DOWN.png", + "assets/Rat/BMP_4_CAVE_LEFT.png", + "assets/Rat/BMP_4_CAVE_RIGHT.png", + "assets/Rat/BMP_4_CAVE_UP.png", + "assets/Rat/BMP_4_E.png", + "assets/Rat/BMP_4_EN.png", + "assets/Rat/BMP_4_ES.png", + "assets/Rat/BMP_4_EXPLOSION_DOWN.png", + "assets/Rat/BMP_4_EXPLOSION_LEFT.png", + "assets/Rat/BMP_4_EXPLOSION_RIGHT.png", + "assets/Rat/BMP_4_EXPLOSION_UP.png", + "assets/Rat/BMP_4_FLOWER_1.png", + "assets/Rat/BMP_4_FLOWER_2.png", + "assets/Rat/BMP_4_FLOWER_3.png", + "assets/Rat/BMP_4_FLOWER_4.png", + "assets/Rat/BMP_4_GAS_DOWN.png", + "assets/Rat/BMP_4_GAS_LEFT.png", + "assets/Rat/BMP_4_GAS_RIGHT.png", + "assets/Rat/BMP_4_GAS_UP.png", + "assets/Rat/BMP_4_GRASS_1.png", + "assets/Rat/BMP_4_GRASS_2.png", + "assets/Rat/BMP_4_GRASS_3.png", + "assets/Rat/BMP_4_GRASS_4.png", + "assets/Rat/BMP_4_N.png", + "assets/Rat/BMP_4_NE.png", + "assets/Rat/BMP_4_NW.png", + "assets/Rat/BMP_4_S.png", + "assets/Rat/BMP_4_SE.png", + "assets/Rat/BMP_4_SW.png", + "assets/Rat/BMP_4_W.png", + "assets/Rat/BMP_4_WN.png", + "assets/Rat/BMP_4_WS.png", + "assets/Rat/BMP_ARROW_DOWN.png", + "assets/Rat/BMP_ARROW_LEFT.png", + "assets/Rat/BMP_ARROW_RIGHT.png", + "assets/Rat/BMP_ARROW_UP.png", + "assets/Rat/BMP_BABY_DOWN.png", + "assets/Rat/BMP_BABY_LEFT.png", + "assets/Rat/BMP_BABY_RIGHT.png", + "assets/Rat/BMP_BABY_UP.png", + "assets/Rat/BMP_BLOCK_0.png", + "assets/Rat/BMP_BLOCK_1.png", + "assets/Rat/BMP_BLOCK_2.png", + "assets/Rat/BMP_BLOCK_3.png", + "assets/Rat/BMP_BOMB0.png", + "assets/Rat/BMP_BOMB1.png", + "assets/Rat/BMP_BOMB2.png", + "assets/Rat/BMP_BOMB3.png", + "assets/Rat/BMP_BOMB4.png", + "assets/Rat/BMP_BONUS_10.png", + "assets/Rat/BMP_BONUS_160.png", + "assets/Rat/BMP_BONUS_20.png", + "assets/Rat/BMP_BONUS_40.png", + "assets/Rat/BMP_BONUS_5.png", + "assets/Rat/BMP_BONUS_80.png", + "assets/Rat/BMP_EXPLOSION.png", + "assets/Rat/BMP_EXPLOSION_DOWN.png", + "assets/Rat/BMP_EXPLOSION_LEFT.png", + "assets/Rat/BMP_EXPLOSION_RIGHT.png", + "assets/Rat/BMP_EXPLOSION_UP.png", + "assets/Rat/BMP_FEMALE.png", + "assets/Rat/BMP_FEMALE_DOWN.png", + "assets/Rat/BMP_FEMALE_LEFT.png", + "assets/Rat/BMP_FEMALE_RIGHT.png", + "assets/Rat/BMP_FEMALE_UP.png", + "assets/Rat/BMP_GAS.png", + "assets/Rat/BMP_GAS_DOWN.png", + "assets/Rat/BMP_GAS_LEFT.png", + "assets/Rat/BMP_GAS_RIGHT.png", + "assets/Rat/BMP_GAS_UP.png", + "assets/Rat/BMP_MALE.png", + "assets/Rat/BMP_MALE_DOWN.png", + "assets/Rat/BMP_MALE_LEFT.png", + "assets/Rat/BMP_MALE_RIGHT.png", + "assets/Rat/BMP_MALE_UP.png", + "assets/Rat/BMP_NUCLEAR.png", + "assets/Rat/BMP_POISON.png", + "assets/Rat/BMP_START_1.png", + "assets/Rat/BMP_START_1_DOWN.png", + "assets/Rat/BMP_START_1_SHADED.png", + "assets/Rat/BMP_START_2.png", + "assets/Rat/BMP_START_2_DOWN.png", + "assets/Rat/BMP_START_2_SHADED.png", + "assets/Rat/BMP_START_3.png", + "assets/Rat/BMP_START_3_DOWN.png", + "assets/Rat/BMP_START_3_SHADED.png", + "assets/Rat/BMP_START_4.png", + "assets/Rat/BMP_START_4_DOWN.png", + "assets/Rat/BMP_START_4_SHADED.png", + "assets/Rat/BMP_TITLE.png", + "assets/Rat/BMP_TUNNEL.png", + "assets/Rat/BMP_VERMINATORS.png", + "assets/Rat/BMP_WEWIN.png", + "assets/Rat/mine.png", + "assets/decterm.ttf", + "assets/AmaticSC-Regular.ttf", + "assets/terminal.ttf" +] \ No newline at end of file diff --git a/assets/sound-manifest.json b/assets/sound-manifest.json new file mode 100644 index 0000000..ee3554c --- /dev/null +++ b/assets/sound-manifest.json @@ -0,0 +1,21 @@ +[ + "sound/BIRTH.WAV", + "sound/BOMB.WAV", + "sound/CHOKE.WAV", + "sound/CLUNK.WAV", + "sound/Death.wav", + "sound/GAS.WAV", + "sound/NEWSEX.WAV", + "sound/NUCLEAR.WAV", + "sound/POISON.WAV", + "sound/PUTDOWN.WAV", + "sound/SEX.WAV", + "sound/VICTORY.WAV", + "sound/WELLDONE.WAV", + "sound/WEWIN.WAV", + "sound/converted_BOMB.wav", + "sound/mine.wav", + "sound/mine_converted.wav", + "sound/mine_original.wav", + "sound/nuke.wav" +] diff --git a/conf/keybindings.json b/conf/keybindings.json deleted file mode 100644 index b985d2b..0000000 --- a/conf/keybindings.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "keybinding_game": { - "keydown_Return": "spawn_rat", - "keydown_D": "kill_rat", - "keydown_M": "toggle_audio", - "keydown_F": "toggle_full_screen", - "keydown_Up": "start_scrolling|Up", - "keydown_Down": "start_scrolling|Down", - "keydown_Left": "start_scrolling|Left", - "keydown_Right": "start_scrolling|Right", - "keyup_Up": "stop_scrolling", - "keyup_Down": "stop_scrolling", - "keyup_Left": "stop_scrolling", - "keyup_Right": "stop_scrolling", - "keydown_Space": "spawn_new_bomb", - "keydown_N": "spawn_new_nuclear_bomb", - "keydown_Left_Ctrl": "spawn_new_mine", - "keydown_G": "spawn_gas", - "keydown_P": "toggle_pause" - }, - "keybinding_start_menu": { - "keydown_Return": "reset_game", - "keydown_Escape": "quit_game", - "keydown_M": "toggle_audio", - "keydown_F": "toggle_full_screen" - }, - "keybinding_paused": { - "keydown_Return": "reset_game", - "keydown_Escape": "quit_game", - "keydown_M": "toggle_audio", - "keydown_F": "toggle_full_screen" - } -} \ No newline at end of file diff --git a/conf/keybindings_pc.yaml b/conf/keybindings_pc.yaml deleted file mode 100644 index 3ad3a5c..0000000 --- a/conf/keybindings_pc.yaml +++ /dev/null @@ -1,29 +0,0 @@ -keybinding_game: - keydown_Return: spawn_rat - keydown_D: kill_rat - keydown_M: toggle_audio - keydown_F: toggle_full_screen - keydown_Up: start_scrolling|Up - keydown_Down: start_scrolling|Down - keydown_Left: start_scrolling|Left - keydown_Right: start_scrolling|Right - keyup_Up: stop_scrolling - keyup_Down: stop_scrolling - keyup_Left: stop_scrolling - keyup_Right: stop_scrolling - keydown_Space: spawn_new_bomb - keydown_N: spawn_new_nuclear_bomb - keydown_Left_Ctrl: spawn_new_mine - keydown_P: toggle_pause - -keybinding_start_menu: - keydown_Return: reset_game - keydown_Escape: quit_game - keydown_M: toggle_audio - keydown_F: toggle_full_screen - -keybinding_paused: - keydown_Return: reset_game - keydown_Escape: quit_game - keydown_M: toggle_audio - keydown_F: toggle_full_screen \ No newline at end of file diff --git a/engine/controls.py b/engine/controls.py index 6efb375..0b0471b 100644 --- a/engine/controls.py +++ b/engine/controls.py @@ -17,24 +17,38 @@ else: class KeyBindings: def trigger(self, action): - #print(f"Triggering action: {action}") + import os + debug = os.environ.get('DEBUG_KEYS', '').lower() == 'true' + + if debug: + print(f"[KEY] Triggering action: {action} (status: {self.game_status})") + # Check if the action is in the bindings - if action in bindings[f"keybinding_{self.game_status}"]: - value = bindings[f"keybinding_{self.game_status}"][action] + current_bindings = bindings.get(f"keybinding_{self.game_status}", {}) + + if action in current_bindings: + value = current_bindings[action] + if debug: + print(f"[KEY] Found binding: {action} -> {value}") + # Call the corresponding method if value: - #print(f"Calling method: {value}") if "|" in value: method_name, *args = value.split("|") method = getattr(self, method_name) + if debug: + print(f"[KEY] Calling method: {method_name}({args})") method(*args) else: + if debug: + print(f"[KEY] Calling method: {value}()") getattr(self, value)() - #else: - #print(f"Action {action} not found in keybindings for {self.game_status}") return - #print(f"Action {action} not found in keybindings for {self.game_status}") + if debug: + print(f"[KEY] Action '{action}' not found in {self.game_status} bindings") + print(f"[KEY] Available actions: {list(current_bindings.keys())}") + return None def spawn_new_bomb(self): @@ -46,6 +60,9 @@ class KeyBindings: def spawn_new_nuclear_bomb(self): self.spawn_nuclear_bomb(self.pointer) + def spawn_new_gas(self): + self.spawn_gas(self.pointer) + def toggle_audio(self): self.render_engine.audio = not self.render_engine.audio def toggle_pause(self): diff --git a/engine/graphics.py b/engine/graphics.py index 119ecad..ae99acd 100644 --- a/engine/graphics.py +++ b/engine/graphics.py @@ -4,6 +4,7 @@ class Graphics(): def load_assets(self): print("Loading graphics assets...") self.tunnel = self.render_engine.load_image("Rat/BMP_TUNNEL.png", surface=True) + print("Loading grass variants...") self.grasses = [self.render_engine.load_image(f"Rat/BMP_1_GRASS_{i+1}.png", surface=True) for i in range(4)] self.rat_assets = {} self.rat_assets_textures = {} diff --git a/engine/pygame_layer.py b/engine/pygame_layer.py new file mode 100644 index 0000000..0697d6d --- /dev/null +++ b/engine/pygame_layer.py @@ -0,0 +1,833 @@ +import os +import random +import pygame +from pygame import mixer + + +class GameWindow: + """ + Pygame-based game window implementation. + Provides a complete interface equivalent to sdl2_layer.GameWindow + """ + + def __init__(self, width, height, cell_size, title="Default", key_callback=None): + # Display configuration + self.cell_size = cell_size + self.width = width * cell_size + self.height = height * cell_size + + # Screen resolution handling + actual_screen_size = os.environ.get("RESOLUTION", "640x480").split("x") + actual_screen_size = tuple(map(int, actual_screen_size)) + self.target_size = actual_screen_size if self.width > actual_screen_size[0] or self.height > actual_screen_size[1] else (self.width, self.height) + + # View offset calculations + self.w_start_offset = (self.target_size[0] - self.width) // 2 + self.h_start_offset = (self.target_size[1] - self.height) // 2 + self.w_offset = self.w_start_offset + self.h_offset = self.h_start_offset + self.max_w_offset = self.target_size[0] - self.width + self.max_h_offset = self.target_size[1] - self.height + self.scale = self.target_size[1] // self.cell_size + + print(f"Screen size: {self.width}x{self.height}") + + # Pygame initialization + pygame.init() + mixer.init(frequency=22050, size=-16, channels=1, buffer=2048) + + # Window and screen setup + self.window = pygame.display.set_mode(self.target_size) + pygame.display.set_caption(title) + self.screen = self.window + + # Font system + self.fonts = self.generate_fonts("assets/decterm.ttf") + + # Game state + self.running = True + self.delay = 30 + self.performance = 0 + self.last_status_text = "" + self.stats_sprite = None + self.mean_fps = 0 + self.fpss = [] + self.text_width = 0 + self.text_height = 0 + self.ammo_text = "" + self.stats_background = None + self.ammo_background = None + self.ammo_sprite = None + + # White flash effect state + self.white_flash_active = False + self.white_flash_start_time = 0 + self.white_flash_opacity = 255 + + # Input handling + self.trigger = key_callback + self.button_cursor = [0, 0] + self.buttons = {} + + # Audio system initialization + self._init_audio_system() + self.audio = True + + # Clock for frame rate control + self.clock = pygame.time.Clock() + + # Input devices + self.load_joystick() + + def show(self): + """Show the window (for compatibility with SDL2 interface)""" + pygame.display.set_mode(self.target_size) + + def _init_audio_system(self): + """Initialize audio channels for different audio types""" + mixer.set_num_channels(8) # Ensure enough channels + self.audio_channels = { + "base": mixer.Channel(0), + "effects": mixer.Channel(1), + "music": mixer.Channel(2) + } + self.current_sounds = {} + + # ====================== + # TEXTURE & IMAGE METHODS + # ====================== + + def create_texture(self, tiles: list): + """Create a texture from a list of tiles""" + bg_surface = pygame.Surface((self.width, self.height)) + for tile in tiles: + bg_surface.blit(tile[0], (tile[1], tile[2])) + return bg_surface + + # Helpers to support incremental background generation + def create_empty_background_surface(self): + """Create and return an empty background surface to incrementally blit onto.""" + return pygame.Surface((self.width, self.height)) + + def blit_tiles_batch(self, bg_surface, tiles_batch: list): + """Blit a small batch of tiles onto the provided background surface. + + tiles_batch: list of (surface, x, y) + Returns None. Designed to be called repeatedly with small batches to avoid long blocking operations. + """ + for tile, x, y in tiles_batch: + try: + bg_surface.blit(tile, (x, y)) + except Exception: + # If tile is a SpriteWrapper, extract surface + try: + bg_surface.blit(tile.surface, (x, y)) + except Exception: + pass + + def load_image(self, path, transparent_color=None, surface=False): + """Load and process an image with optional transparency and scaling""" + image_path = os.path.join("assets", path) + + # First try to use pygame's native loader which avoids a Pillow dependency. + try: + py_image = pygame.image.load(image_path) + # Ensure alpha if needed + try: + py_image = py_image.convert_alpha() + except Exception: + try: + py_image = py_image.convert() + except Exception: + pass + + # Handle transparent color via colorkey if provided + if transparent_color: + # pygame expects a tuple of ints + try: + py_image.set_colorkey(transparent_color) + except Exception: + pass + + # Scale image using pygame transforms + scale = max(1, self.cell_size // 20) + new_size = (py_image.get_width() * scale, py_image.get_height() * scale) + try: + py_image = pygame.transform.scale(py_image, new_size) + except Exception: + # If scaling fails, continue with original + pass + + if not surface: + return SpriteWrapper(py_image) + return py_image + except Exception: + # Fallback to PIL-based loading if pygame can't handle the file or Pillow is present + try: + # Import Pillow lazily to avoid hard dependency at module import time + try: + from PIL import Image + except Exception: + Image = None + + if Image is None: + raise + + image = Image.open(image_path) + + # Handle transparency + if transparent_color: + image = image.convert("RGBA") + datas = image.getdata() + new_data = [] + for item in datas: + if item[:3] == transparent_color: + new_data.append((255, 255, 255, 0)) + else: + new_data.append(item) + image.putdata(new_data) + + # Scale image + scale = max(1, self.cell_size // 20) + image = image.resize((image.width * scale, image.height * scale), Image.NEAREST) + + # Convert PIL image to pygame surface + mode = image.mode + size = image.size + data = image.tobytes() + + if mode == "RGBA": + py_image = pygame.image.fromstring(data, size, mode) + elif mode == "RGB": + py_image = pygame.image.fromstring(data, size, mode) + else: + image = image.convert("RGBA") + data = image.tobytes() + py_image = pygame.image.fromstring(data, size, "RGBA") + + if not surface: + return SpriteWrapper(py_image) + return py_image + except Exception: + # If both loaders fail, raise to notify caller + raise + + def get_image_size(self, image): + """Get the size of an image sprite""" + if isinstance(image, SpriteWrapper): + return image.size + return image.get_size() + + # ====================== + # FONT MANAGEMENT + # ====================== + + def generate_fonts(self, font_file): + """Generate font objects for different sizes""" + fonts = {} + for i in range(10, 70, 1): + try: + fonts[i] = pygame.font.Font(font_file, i) + except: + fonts[i] = pygame.font.Font(None, i) + return fonts + + # ====================== + # DRAWING METHODS + # ====================== + + def draw_text(self, text, font, position, color): + """Draw text at specified position with given font and color""" + if isinstance(color, tuple): + # Pygame color format + pass + else: + # Convert from any other format to RGB tuple + color = (color.r, color.g, color.b) if hasattr(color, 'r') else (0, 0, 0) + + text_surface = font.render(text, True, color) + text_rect = text_surface.get_rect() + + # Handle center positioning + if position == "center": + position = ("center", "center") + if isinstance(position, tuple): + if position[0] == "center": + text_rect.centerx = self.target_size[0] // 2 + text_rect.y = position[1] + elif position[1] == "center": + text_rect.x = position[0] + text_rect.centery = self.target_size[1] // 2 + else: + text_rect.topleft = position + + self.screen.blit(text_surface, text_rect) + + def draw_background(self, bg_texture): + """Draw background texture with current view offset""" + self.screen.blit(bg_texture, (self.w_offset, self.h_offset)) + + def draw_image(self, x, y, sprite, tag=None, anchor="nw"): + """Draw an image sprite at specified coordinates""" + if not self.is_in_visible_area(x, y): + return + + if isinstance(sprite, SpriteWrapper): + surface = sprite.surface + else: + surface = sprite + + self.screen.blit(surface, (x + self.w_offset, y + self.h_offset)) + + def draw_rectangle(self, x, y, width, height, tag, outline="red", filling=None): + """Draw a rectangle with optional fill and outline""" + rect = pygame.Rect(x, y, width, height) + + if filling: + pygame.draw.rect(self.screen, filling, rect) + else: + # Handle outline color + if isinstance(outline, str): + color_map = { + "red": (255, 0, 0), + "blue": (0, 0, 255), + "green": (0, 255, 0), + "black": (0, 0, 0), + "white": (255, 255, 255) + } + outline = color_map.get(outline, (255, 0, 0)) + pygame.draw.rect(self.screen, outline, rect, 2) + + def draw_pointer(self, x, y): + """Draw a red pointer rectangle at specified coordinates""" + x = x + self.w_offset + y = y + self.h_offset + for i in range(3): + rect = pygame.Rect(x + i, y + i, self.cell_size - 2*i, self.cell_size - 2*i) + pygame.draw.rect(self.screen, (255, 0, 0), rect, 1) + + def delete_tag(self, tag): + """Placeholder for tag deletion (not needed in pygame implementation)""" + pass + + # ====================== + # UI METHODS + # ====================== + + def dialog(self, text, **kwargs): + """Display a dialog box with text and optional extras""" + # Draw dialog background + dialog_rect = pygame.Rect(50, 50, self.target_size[0] - 100, self.target_size[1] - 100) + pygame.draw.rect(self.screen, (255, 255, 255), dialog_rect) + + # Calculate layout positions to avoid overlaps + title_y = self.target_size[1] // 4 # Title at 1/4 of screen height + + # Draw main text (title) + self.draw_text(text, self.fonts[self.target_size[1]//20], + ("center", title_y), (0, 0, 0)) + + # Draw image if provided - position it below title + image_bottom_y = title_y + 60 # Default position if no image + if image := kwargs.get("image"): + image_size = self.get_image_size(image) + image_y = title_y + 50 + self.draw_image(self.target_size[0] // 2 - image_size[0] // 2 - self.w_offset, + image_y - self.h_offset, + image, "win") + image_bottom_y = image_y + image_size[1] + 20 + + # Draw subtitle if provided - handle multi-line text, position below image + if subtitle := kwargs.get("subtitle"): + subtitle_lines = subtitle.split('\n') + base_y = image_bottom_y + 20 + line_height = 25 # Fixed line height for consistent spacing + + for i, line in enumerate(subtitle_lines): + if line.strip(): # Only draw non-empty lines + self.draw_text(line.strip(), self.fonts[self.target_size[1]//35], + ("center", base_y + i * line_height), (0, 0, 0)) + + # Draw scores if provided - position at bottom + if scores := kwargs.get("scores"): + scores_start_y = self.target_size[1] * 3 // 4 # Bottom quarter of screen + title_surface = self.fonts[self.target_size[1]//25].render("High Scores:", True, (0, 0, 0)) + title_rect = title_surface.get_rect(center=(self.target_size[0] // 2, scores_start_y)) + self.screen.blit(title_surface, title_rect) + + for i, score in enumerate(scores[:5]): + if len(score) >= 4: # New format: date, score, name, device + score_text = f"{score[2]}: {score[1]} pts ({score[3]})" + elif len(score) >= 3: # Medium format: date, score, name + score_text = f"{score[2]}: {score[1]} pts" + else: # Old format: date, score + score_text = f"Guest: {score[1]} pts" + + self.draw_text(score_text, self.fonts[self.target_size[1]//45], + ("center", scores_start_y + 30 + 25 * (i + 1)), + (0, 0, 0)) + + def start_dialog(self, **kwargs): + """Display the welcome dialog""" + self.dialog("Welcome to the Mice!", subtitle="A game by Matteo because was bored", **kwargs) + + def draw_button(self, x, y, text, width, height, coords): + """Draw a button with text""" + color = (0, 0, 255) if self.button_cursor == list(coords) else (0, 0, 0) + self.draw_rectangle(x, y, width, height, "button", outline=color) + + def update_status(self, text): + """Update and display the status bar with FPS information""" + fps = int(self.clock.get_fps()) if self.clock.get_fps() > 0 else 0 + + if len(self.fpss) > 20: + self.mean_fps = round(sum(self.fpss) / len(self.fpss)) if self.fpss else fps + self.fpss.clear() + else: + self.fpss.append(fps) + + status_text = f"FPS: {self.mean_fps} - {text}" + if status_text != self.last_status_text: + self.last_status_text = status_text + font = self.fonts[20] + self.stats_sprite = font.render(status_text, True, (0, 0, 0)) + if self.text_width != self.stats_sprite.get_width() or self.text_height != self.stats_sprite.get_height(): + self.text_width, self.text_height = self.stats_sprite.get_size() + self.stats_background = pygame.Surface((self.text_width + 10, self.text_height + 4)) + self.stats_background.fill((255, 255, 255)) + + self.screen.blit(self.stats_background, (3, 3)) + self.screen.blit(self.stats_sprite, (8, 5)) + + def update_ammo(self, ammo, assets): + """Update and display the ammo count""" + ammo_text = f"{ammo['bomb']['count']}/{ammo['bomb']['max']} {ammo['mine']['count']}/{ammo['mine']['max']} {ammo['gas']['count']}/{ammo['gas']['max']} " + if self.ammo_text != ammo_text: + self.ammo_text = ammo_text + font = self.fonts[20] + self.ammo_sprite = font.render(ammo_text, True, (0, 0, 0)) + text_width, text_height = self.ammo_sprite.get_size() + self.ammo_background = pygame.Surface((text_width + 10, text_height + 4)) + self.ammo_background.fill((255, 255, 255)) + + text_width, text_height = self.ammo_sprite.get_size() + position = (self.target_size[0] - text_width - 10, self.target_size[1] - text_height - 5) + + self.screen.blit(self.ammo_background, (position[0] - 5, position[1] - 2)) + self.screen.blit(self.ammo_sprite, position) + + # Draw ammo icons + bomb_sprite = assets["BMP_BOMB0"] + poison_sprite = assets["BMP_POISON"] + gas_sprite = assets["BMP_GAS"] + + if isinstance(bomb_sprite, SpriteWrapper): + self.screen.blit(bomb_sprite.surface, (position[0]+25, position[1])) + else: + # Scale to 20x20 if needed + bomb_scaled = pygame.transform.scale(bomb_sprite, (20, 20)) + self.screen.blit(bomb_scaled, (position[0]+25, position[1])) + + if isinstance(poison_sprite, SpriteWrapper): + self.screen.blit(poison_sprite.surface, (position[0]+85, position[1])) + else: + poison_scaled = pygame.transform.scale(poison_sprite, (20, 20)) + self.screen.blit(poison_scaled, (position[0]+85, position[1])) + + if isinstance(gas_sprite, SpriteWrapper): + self.screen.blit(gas_sprite.surface, (position[0]+140, position[1])) + else: + gas_scaled = pygame.transform.scale(gas_sprite, (20, 20)) + self.screen.blit(gas_scaled, (position[0]+140, position[1])) + + # ====================== + # VIEW & NAVIGATION + # ====================== + + def scroll_view(self, pointer): + """Adjust the view offset based on pointer coordinates""" + x, y = pointer + + # Scale down and invert coordinates + x = -(x // 2) * self.cell_size + y = -(y // 2) * self.cell_size + + # Clamp horizontal offset to valid range + if x <= self.max_w_offset + self.cell_size: + x = self.max_w_offset + + # Clamp vertical offset to valid range + if y < self.max_h_offset: + y = self.max_h_offset + + self.w_offset = x + self.h_offset = y + + def is_in_visible_area(self, x, y): + """Check if coordinates are within the visible area""" + return (-self.w_offset - self.cell_size <= x <= self.width - self.w_offset and + -self.h_offset - self.cell_size <= y <= self.height - self.h_offset) + + def get_view_center(self): + """Get the center coordinates of the current view""" + return self.w_offset + self.width // 2, self.h_offset + self.height // 2 + + # ====================== + # AUDIO METHODS + # ====================== + + def play_sound(self, sound_file, tag="base"): + """Play a sound file on the specified audio channel""" + if not self.audio: + return + + try: + sound_path = os.path.join("sound", sound_file) + sound = mixer.Sound(sound_path) + + # Get the appropriate channel + channel = self.audio_channels.get(tag, self.audio_channels["base"]) + + # Stop any currently playing sound on this channel + channel.stop() + + # Play the new sound + channel.play(sound) + + # Store reference to prevent garbage collection + self.current_sounds[tag] = sound + except Exception as e: + print(f"Error playing sound {sound_file}: {e}") + + def stop_sound(self): + """Stop all audio playback""" + for channel in self.audio_channels.values(): + channel.stop() + + # ====================== + # INPUT METHODS + # ====================== + + def load_joystick(self): + """Initialize joystick support""" + pygame.joystick.init() + joystick_count = pygame.joystick.get_count() + if joystick_count > 0: + self.joystick = pygame.joystick.Joystick(0) + self.joystick.init() + print(f"Joystick initialized: {self.joystick.get_name()}") + else: + self.joystick = None + + # ====================== + # MAIN GAME LOOP + # ====================== + + def _normalize_key_name(self, key): + """Normalize pygame key names to match SDL2 key names""" + # Pygame returns lowercase, SDL2 returns with proper case + key_map = { + "return": "Return", + "escape": "Escape", + "space": "Space", + "tab": "Tab", + "left shift": "Left_Shift", + "right shift": "Right_Shift", + "left ctrl": "Left_Ctrl", + "right ctrl": "Right_Ctrl", + "left alt": "Left_Alt", + "right alt": "Right_Alt", + "up": "Up", + "down": "Down", + "left": "Left", + "right": "Right", + "delete": "Delete", + "backspace": "Backspace", + "insert": "Insert", + "home": "Home", + "end": "End", + "pageup": "Page_Up", + "pagedown": "Page_Down", + "f1": "F1", + "f2": "F2", + "f3": "F3", + "f4": "F4", + "f5": "F5", + "f6": "F6", + "f7": "F7", + "f8": "F8", + "f9": "F9", + "f10": "F10", + "f11": "F11", + "f12": "F12", + } + # Return mapped value or capitalize first letter of original + normalized = key_map.get(key.lower(), key) + # Handle single letters (make uppercase) + if len(normalized) == 1: + normalized = normalized.upper() + return normalized + + def mainloop(self, **kwargs): + """Main game loop handling events and rendering""" + while self.running: + performance_start = pygame.time.get_ticks() + + # Clear screen + self.screen.fill((0, 0, 0)) + + # Execute background update if provided + if "bg_update" in kwargs: + kwargs["bg_update"]() + + # Execute main update + kwargs["update"]() + + # Update and draw white flash effect + if self.update_white_flash(): + self.draw_white_flash() + + # Handle Pygame events + for event in pygame.event.get(): + if event.type == pygame.QUIT: + self.running = False + elif event.type == pygame.KEYDOWN: + key = pygame.key.name(event.key) + key = self._normalize_key_name(key) + key = key.replace(" ", "_") + self.trigger(f"keydown_{key}") + elif event.type == pygame.KEYUP: + key = pygame.key.name(event.key) + key = self._normalize_key_name(key) + key = key.replace(" ", "_") + self.trigger(f"keyup_{key}") + elif event.type == pygame.MOUSEMOTION: + self.trigger(f"mousemove_{event.pos[0]}, {event.pos[1]}") + elif event.type == pygame.JOYBUTTONDOWN: + self.trigger(f"joybuttondown_{event.button}") + elif event.type == pygame.JOYBUTTONUP: + self.trigger(f"joybuttonup_{event.button}") + elif event.type == pygame.JOYHATMOTION: + self.trigger(f"joyhatmotion_{event.hat}_{event.value}") + + # Update display + pygame.display.flip() + + # Control frame rate + self.clock.tick(60) # Target 60 FPS + + # Calculate performance + self.performance = pygame.time.get_ticks() - performance_start + + def step(self, update=None, bg_update=None): + """Execute a single frame iteration. This is non-blocking and useful when + the caller (JS) schedules frames via requestAnimationFrame in the browser. + """ + performance_start = pygame.time.get_ticks() + + # Clear screen + self.screen.fill((0, 0, 0)) + + # Background update + if bg_update: + try: + bg_update() + except Exception: + pass + + # Main update + if update: + try: + update() + except Exception: + pass + + # Update and draw white flash effect + if self.update_white_flash(): + self.draw_white_flash() + + # Handle Pygame events (single-frame processing) + for event in pygame.event.get(): + if event.type == pygame.QUIT: + self.running = False + elif event.type == pygame.KEYDOWN: + key = pygame.key.name(event.key) + key = self._normalize_key_name(key) + key = key.replace(" ", "_") + self.trigger(f"keydown_{key}") + elif event.type == pygame.KEYUP: + key = pygame.key.name(event.key) + key = self._normalize_key_name(key) + key = key.replace(" ", "_") + self.trigger(f"keyup_{key}") + elif event.type == pygame.MOUSEMOTION: + self.trigger(f"mousemove_{event.pos[0]}, {event.pos[1]}") + elif event.type == pygame.JOYBUTTONDOWN: + self.trigger(f"joybuttondown_{event.button}") + elif event.type == pygame.JOYBUTTONUP: + self.trigger(f"joybuttonup_{event.button}") + elif event.type == pygame.JOYHATMOTION: + self.trigger(f"joyhatmotion_{event.hat}_{event.value}") + + # Update display once per frame + pygame.display.flip() + + # Control frame rate + self.clock.tick(60) + + # Calculate performance + self.performance = pygame.time.get_ticks() - performance_start + + # ====================== + # SPECIAL EFFECTS + # ====================== + + def trigger_white_flash(self): + """Trigger the white flash effect""" + self.white_flash_active = True + self.white_flash_start_time = pygame.time.get_ticks() + self.white_flash_opacity = 255 + + def update_white_flash(self): + """Update the white flash effect and return True if it should be drawn""" + if not self.white_flash_active: + return False + + current_time = pygame.time.get_ticks() + elapsed_time = current_time - self.white_flash_start_time + + if elapsed_time < 500: # First 500ms: full white + self.white_flash_opacity = 255 + return True + elif elapsed_time < 2000: # Next 1500ms: fade out + fade_progress = (elapsed_time - 500) / 1500.0 + self.white_flash_opacity = int(255 * (1.0 - fade_progress)) + return True + else: # Effect is complete + self.white_flash_active = False + self.white_flash_opacity = 0 + return False + + def draw_white_flash(self): + """Draw the white flash overlay""" + if self.white_flash_opacity > 0: + white_surface = pygame.Surface(self.target_size) + white_surface.fill((255, 255, 255)) + white_surface.set_alpha(self.white_flash_opacity) + self.screen.blit(white_surface, (0, 0)) + + # ====================== + # UTILITY METHODS + # ====================== + + def new_cycle(self, delay, callback): + """Placeholder for cycle management (not needed in pygame implementation)""" + pass + + def full_screen(self, flag): + """Toggle fullscreen mode""" + if flag: + self.window = pygame.display.set_mode(self.target_size, pygame.FULLSCREEN) + else: + self.window = pygame.display.set_mode(self.target_size) + self.screen = self.window + + def get_perf_counter(self): + """Get performance counter for timing""" + return pygame.time.get_ticks() + + def close(self): + """Close the game window and cleanup""" + self.running = False + pygame.quit() + + # ====================== + # BLOOD EFFECT METHODS + # ====================== + + def generate_blood_surface(self): + """Generate a dynamic blood splatter surface using Pygame""" + size = self.cell_size + + # Create RGBA surface for blood splatter + blood_surface = pygame.Surface((size, size), pygame.SRCALPHA) + + # Blood color variations + blood_colors = [ + (139, 0, 0, 255), # Dark red + (34, 34, 34, 255), # Very dark gray + (20, 60, 60, 255), # Dark teal + (255, 0, 0, 255), # Pure red + (128, 0, 0, 255), # Reddish brown + ] + + # Generate splatter with diffusion algorithm + center_x, center_y = size // 2, size // 2 + max_radius = size // 3 + random.randint(-3, 5) + + for y in range(size): + for x in range(size): + # Calculate distance from center + distance = ((x - center_x) ** 2 + (y - center_y) ** 2) ** 0.5 + + # Calculate blood probability based on distance + if distance <= max_radius: + probability = max(0, 1 - (distance / max_radius)) + noise = random.random() * 0.7 + + if random.random() < probability * noise: + color = random.choice(blood_colors) + alpha = int(255 * probability * random.uniform(0.6, 1.0)) + blood_surface.set_at((x, y), (*color[:3], alpha)) + + # Add scattered droplets around main splatter + for _ in range(random.randint(3, 8)): + drop_x = center_x + random.randint(-max_radius - 5, max_radius + 5) + drop_y = center_y + random.randint(-max_radius - 5, max_radius + 5) + + if 0 <= drop_x < size and 0 <= drop_y < size: + drop_size = random.randint(1, 3) + for dy in range(-drop_size, drop_size + 1): + for dx in range(-drop_size, drop_size + 1): + nx, ny = drop_x + dx, drop_y + dy + if 0 <= nx < size and 0 <= ny < size: + if random.random() < 0.6: + color = random.choice(blood_colors[:3]) + alpha = random.randint(100, 200) + blood_surface.set_at((nx, ny), (*color[:3], alpha)) + + return blood_surface + + def draw_blood_surface(self, blood_surface, position): + """Convert blood surface to texture and return it""" + # In pygame, we can return the surface directly + return blood_surface + + def combine_blood_surfaces(self, existing_surface, new_surface): + """Combine two blood surfaces by blending them together""" + combined_surface = pygame.Surface((self.cell_size, self.cell_size), pygame.SRCALPHA) + + # Blit existing blood first + combined_surface.blit(existing_surface, (0, 0)) + + # Blit new blood on top with alpha blending + combined_surface.blit(new_surface, (0, 0)) + + return combined_surface + + def free_surface(self, surface): + """Safely free a pygame surface (not needed in pygame, handled by GC)""" + pass + + +class SpriteWrapper: + """ + Wrapper class to make pygame surfaces compatible with SDL2 sprite interface + """ + def __init__(self, surface): + self.surface = surface + self.size = surface.get_size() + self.position = (0, 0) + + def get_size(self): + return self.size diff --git a/engine/score_api_client.py b/engine/score_api_client.py index 4aca071..eee8ff1 100644 --- a/engine/score_api_client.py +++ b/engine/score_api_client.py @@ -4,11 +4,20 @@ Score API Client for Mice Game Client module to integrate with the FastAPI score server """ -import requests import json from typing import Optional, List, Dict, Any import time +# Try to import requests; if unavailable, provide a minimal urllib-based fallback. +try: + import requests # type: ignore + _HAS_REQUESTS = True +except Exception: + requests = None + _HAS_REQUESTS = False +from typing import Optional, List, Dict, Any +import time + class ScoreAPIClient: """Client for communicating with the Mice Game Score API""" @@ -39,25 +48,65 @@ class ScoreAPIClient: url = f"{self.api_base_url}{endpoint}" try: - if method.upper() == "GET": - response = requests.get(url, timeout=self.timeout) - elif method.upper() == "POST": - response = requests.post(url, json=data, timeout=self.timeout) - else: - raise ValueError(f"Unsupported HTTP method: {method}") - - if response.status_code == 200: - return response.json() - elif response.status_code in [400, 404, 409]: - # Client errors - return the error details - return {"error": True, "status": response.status_code, "detail": response.json()} + if _HAS_REQUESTS: + if method.upper() == "GET": + response = requests.get(url, timeout=self.timeout) + elif method.upper() == "POST": + response = requests.post(url, json=data, timeout=self.timeout) + else: + raise ValueError(f"Unsupported HTTP method: {method}") + + if response.status_code == 200: + return response.json() + elif response.status_code in [400, 404, 409]: + return {"error": True, "status": response.status_code, "detail": response.json()} + else: + return {"error": True, "status": response.status_code, "detail": "Server error"} else: - return {"error": True, "status": response.status_code, "detail": "Server error"} - - except requests.exceptions.ConnectionError: - return {"error": True, "detail": "Could not connect to score server"} - except requests.exceptions.Timeout: - return {"error": True, "detail": "Request timeout"} + # urllib fallback for environments without requests (e.g., Pyodide without wheel) + from urllib.request import Request, urlopen + from urllib.error import URLError, HTTPError + import urllib.parse + + if method.upper() == 'GET': + req = Request(url, method='GET') + try: + with urlopen(req, timeout=self.timeout) as resp: + body = resp.read() + try: + return json.loads(body.decode('utf-8')) + except Exception: + return None + except HTTPError as he: + try: + detail = json.loads(he.read().decode('utf-8')) + except Exception: + detail = str(he) + return {"error": True, "status": he.code, "detail": detail} + except URLError: + return {"error": True, "detail": "Could not connect to score server"} + elif method.upper() == 'POST': + data_bytes = json.dumps(data).encode('utf-8') if data is not None else None + req = Request(url, data=data_bytes, method='POST') + req.add_header('Content-Type', 'application/json') + try: + with urlopen(req, timeout=self.timeout) as resp: + body = resp.read() + try: + return json.loads(body.decode('utf-8')) + except Exception: + return None + except HTTPError as he: + try: + detail = json.loads(he.read().decode('utf-8')) + except Exception: + detail = str(he) + return {"error": True, "status": he.code, "detail": detail} + except URLError: + return {"error": True, "detail": "Could not connect to score server"} + else: + raise ValueError(f"Unsupported HTTP method: {method}") + except Exception as e: return {"error": True, "detail": str(e)} diff --git a/engine/sdl2.py b/engine/sdl2_layer.py similarity index 79% rename from engine/sdl2.py rename to engine/sdl2_layer.py index e2e9143..1ae8d39 100644 --- a/engine/sdl2.py +++ b/engine/sdl2_layer.py @@ -3,10 +3,10 @@ import random import ctypes from ctypes import * -import sdl2 +import engine.sdl2_layer as sdl2_layer import sdl2.ext from sdl2.ext.compat import byteify -from sdl2 import SDL_AudioSpec +from engine.sdl2_layer import SDL_AudioSpec from PIL import Image @@ -34,14 +34,14 @@ class GameWindow: print(f"Screen size: {self.width}x{self.height}") # SDL2 initialization - sdl2.ext.init(joystick=True) - sdl2.SDL_Init(sdl2.SDL_INIT_AUDIO) + sdl2_layer.ext.init(joystick=True) + sdl2_layer.SDL_Init(sdl2_layer.SDL_INIT_AUDIO) # Window and renderer setup - self.window = sdl2.ext.Window(title=title, size=self.target_size) + self.window = sdl2_layer.ext.Window(title=title, size=self.target_size) # self.window.show() - self.renderer = sdl2.ext.Renderer(self.window, flags=sdl2.SDL_RENDERER_ACCELERATED) - self.factory = sdl2.ext.SpriteFactory(renderer=self.renderer) + self.renderer = sdl2_layer.ext.Renderer(self.window, flags=sdl2_layer.SDL_RENDERER_ACCELERATED) + self.factory = sdl2_layer.ext.SpriteFactory(renderer=self.renderer) # Font system self.fonts = self.generate_fonts("assets/decterm.ttf") @@ -80,11 +80,11 @@ class GameWindow: def _init_audio_system(self): """Initialize audio devices for different audio channels""" - audio_spec = SDL_AudioSpec(freq=22050, aformat=sdl2.AUDIO_U8, channels=1, samples=2048) + audio_spec = SDL_AudioSpec(freq=22050, aformat=sdl2_layer.AUDIO_U8, channels=1, samples=2048) self.audio_devs = {} - self.audio_devs["base"] = sdl2.SDL_OpenAudioDevice(None, 0, audio_spec, None, 0) - self.audio_devs["effects"] = sdl2.SDL_OpenAudioDevice(None, 0, audio_spec, None, 0) - self.audio_devs["music"] = sdl2.SDL_OpenAudioDevice(None, 0, audio_spec, None, 0) + self.audio_devs["base"] = sdl2_layer.SDL_OpenAudioDevice(None, 0, audio_spec, None, 0) + self.audio_devs["effects"] = sdl2_layer.SDL_OpenAudioDevice(None, 0, audio_spec, None, 0) + self.audio_devs["music"] = sdl2_layer.SDL_OpenAudioDevice(None, 0, audio_spec, None, 0) # ====================== # TEXTURE & IMAGE METHODS @@ -92,12 +92,12 @@ class GameWindow: def create_texture(self, tiles: list): """Create a texture from a list of tiles""" - bg_surface = sdl2.SDL_CreateRGBSurface(0, self.width, self.height, 32, 0, 0, 0, 0) + bg_surface = sdl2_layer.SDL_CreateRGBSurface(0, self.width, self.height, 32, 0, 0, 0, 0) for tile in tiles: - dstrect = sdl2.SDL_Rect(tile[1], tile[2], self.cell_size, self.cell_size) - sdl2.SDL_BlitSurface(tile[0], None, bg_surface, dstrect) + dstrect = sdl2_layer.SDL_Rect(tile[1], tile[2], self.cell_size, self.cell_size) + sdl2_layer.SDL_BlitSurface(tile[0], None, bg_surface, dstrect) bg_texture = self.factory.from_surface(bg_surface) - sdl2.SDL_FreeSurface(bg_surface) + sdl2_layer.SDL_FreeSurface(bg_surface) return bg_texture def load_image(self, path, transparent_color=None, surface=False): @@ -122,8 +122,8 @@ class GameWindow: image = image.resize((image.width * scale, image.height * scale), Image.NEAREST) if surface: - return sdl2.ext.pillow_to_surface(image) - return self.factory.from_surface(sdl2.ext.pillow_to_surface(image)) + return sdl2_layer.ext.pillow_to_surface(image) + return self.factory.from_surface(sdl2_layer.ext.pillow_to_surface(image)) def get_image_size(self, image): """Get the size of an image sprite""" @@ -137,7 +137,7 @@ class GameWindow: """Generate font managers for different sizes""" fonts = {} for i in range(10, 70, 1): - fonts.update({i: sdl2.ext.FontManager(font_path=font_file, size=i)}) + fonts.update({i: sdl2_layer.ext.FontManager(font_path=font_file, size=i)}) return fonts # ====================== @@ -161,7 +161,7 @@ class GameWindow: def draw_background(self, bg_texture): """Draw background texture with current view offset""" - self.renderer.copy(bg_texture, dstrect=sdl2.SDL_Rect(self.w_offset, self.h_offset, self.width, self.height)) + self.renderer.copy(bg_texture, dstrect=sdl2_layer.SDL_Rect(self.w_offset, self.h_offset, self.width, self.height)) def draw_image(self, x, y, sprite, tag=None, anchor="nw"): """Draw an image sprite at specified coordinates""" @@ -173,9 +173,9 @@ class GameWindow: def draw_rectangle(self, x, y, width, height, tag, outline="red", filling=None): """Draw a rectangle with optional fill and outline""" if filling: - self.renderer.fill((x, y, width, height), sdl2.ext.Color(*filling)) + self.renderer.fill((x, y, width, height), sdl2_layer.ext.Color(*filling)) else: - self.renderer.draw_rect((x, y, width, height), sdl2.ext.Color(*outline)) + self.renderer.draw_rect((x, y, width, height), sdl2_layer.ext.Color(*outline)) def draw_pointer(self, x, y): """Draw a red pointer rectangle at specified coordinates""" @@ -183,7 +183,7 @@ class GameWindow: y = y + self.h_offset for i in range(3): self.renderer.draw_rect((x + i, y + i, self.cell_size - 2*i, self.cell_size - 2*i), - color=sdl2.ext.Color(255, 0, 0)) + color=sdl2_layer.ext.Color(255, 0, 0)) def delete_tag(self, tag): """Placeholder for tag deletion (not implemented)""" @@ -205,7 +205,7 @@ class GameWindow: # Draw main text (title) self.draw_text(text, self.fonts[self.target_size[1]//20], - ("center", title_y), sdl2.ext.Color(0, 0, 0)) + ("center", title_y), sdl2_layer.ext.Color(0, 0, 0)) # Draw image if provided - position it below title image_bottom_y = title_y + 60 # Default position if no image @@ -226,12 +226,12 @@ class GameWindow: for i, line in enumerate(subtitle_lines): if line.strip(): # Only draw non-empty lines self.draw_text(line.strip(), self.fonts[self.target_size[1]//35], - ("center", base_y + i * line_height), sdl2.ext.Color(0, 0, 0)) + ("center", base_y + i * line_height), sdl2_layer.ext.Color(0, 0, 0)) # Draw scores if provided - position at bottom if scores := kwargs.get("scores"): scores_start_y = self.target_size[1] * 3 // 4 # Bottom quarter of screen - sprite = self.factory.from_text("High Scores:", color=sdl2.ext.Color(0, 0, 0), + sprite = self.factory.from_text("High Scores:", color=sdl2_layer.ext.Color(0, 0, 0), fontmanager=self.fonts[self.target_size[1]//25]) sprite.position = (self.target_size[0] // 2 - sprite.size[0] // 2, scores_start_y) self.renderer.copy(sprite, dstrect=sprite.position) @@ -246,7 +246,7 @@ class GameWindow: self.draw_text(score_text, self.fonts[self.target_size[1]//45], ("center", scores_start_y + 30 + 25 * (i + 1)), - sdl2.ext.Color(0, 0, 0)) + sdl2_layer.ext.Color(0, 0, 0)) def start_dialog(self, **kwargs): """Display the welcome dialog""" @@ -274,15 +274,15 @@ class GameWindow: if status_text != self.last_status_text: self.last_status_text = status_text font = self.fonts[20] - self.stats_sprite = self.factory.from_text(status_text, color=sdl2.ext.Color(0, 0, 0), fontmanager=font) + self.stats_sprite = self.factory.from_text(status_text, color=sdl2_layer.ext.Color(0, 0, 0), fontmanager=font) if self.text_width != self.stats_sprite.size[0] or self.text_height != self.stats_sprite.size[1]: self.text_width, self.text_height = self.stats_sprite.size # create a background for the status text using texture - self.stats_background = self.factory.from_color(sdl2.ext.Color(255, 255, 255), (self.text_width + 10, self.text_height + 4)) + self.stats_background = self.factory.from_color(sdl2_layer.ext.Color(255, 255, 255), (self.text_width + 10, self.text_height + 4)) # self.renderer.fill((3, 3, self.text_width + 10, self.text_height + 4), sdl2.ext.Color(255, 255, 255)) - self.renderer.copy(self.stats_background, dstrect=sdl2.SDL_Rect(3, 3, self.text_width + 10, self.text_height + 4)) - self.renderer.copy(self.stats_sprite, dstrect=sdl2.SDL_Rect(8, 5, self.text_width, self.text_height)) + self.renderer.copy(self.stats_background, dstrect=sdl2_layer.SDL_Rect(3, 3, self.text_width + 10, self.text_height + 4)) + self.renderer.copy(self.stats_sprite, dstrect=sdl2_layer.SDL_Rect(8, 5, self.text_width, self.text_height)) def update_ammo(self, ammo, assets): """Update and display the ammo count""" @@ -290,17 +290,17 @@ class GameWindow: if self.ammo_text != ammo_text: self.ammo_text = ammo_text font = self.fonts[20] - self.ammo_sprite = self.factory.from_text(ammo_text, color=sdl2.ext.Color(0, 0, 0), fontmanager=font) + self.ammo_sprite = self.factory.from_text(ammo_text, color=sdl2_layer.ext.Color(0, 0, 0), fontmanager=font) text_width, text_height = self.ammo_sprite.size - self.ammo_background = self.factory.from_color(sdl2.ext.Color(255, 255, 255), (text_width + 10, text_height + 4)) + self.ammo_background = self.factory.from_color(sdl2_layer.ext.Color(255, 255, 255), (text_width + 10, text_height + 4)) text_width, text_height = self.ammo_sprite.size position = (self.target_size[0] - text_width - 10, self.target_size[1] - text_height - 5) #self.renderer.fill((position[0] - 5, position[1] - 2, text_width + 10, text_height + 4), sdl2.ext.Color(255, 255, 255)) - self.renderer.copy(self.ammo_background, dstrect=sdl2.SDL_Rect(position[0] - 5, position[1] - 2, text_width + 10, text_height + 4)) - self.renderer.copy(self.ammo_sprite, dstrect=sdl2.SDL_Rect(position[0], position[1], text_width, text_height)) - self.renderer.copy(assets["BMP_BOMB0"], dstrect=sdl2.SDL_Rect(position[0]+25, position[1], 20, 20)) - self.renderer.copy(assets["BMP_POISON"], dstrect=sdl2.SDL_Rect(position[0]+85, position[1], 20, 20)) - self.renderer.copy(assets["BMP_GAS"], dstrect=sdl2.SDL_Rect(position[0]+140, position[1], 20, 20)) + self.renderer.copy(self.ammo_background, dstrect=sdl2_layer.SDL_Rect(position[0] - 5, position[1] - 2, text_width + 10, text_height + 4)) + self.renderer.copy(self.ammo_sprite, dstrect=sdl2_layer.SDL_Rect(position[0], position[1], text_width, text_height)) + self.renderer.copy(assets["BMP_BOMB0"], dstrect=sdl2_layer.SDL_Rect(position[0]+25, position[1], 20, 20)) + self.renderer.copy(assets["BMP_POISON"], dstrect=sdl2_layer.SDL_Rect(position[0]+85, position[1], 20, 20)) + self.renderer.copy(assets["BMP_GAS"], dstrect=sdl2_layer.SDL_Rect(position[0]+140, position[1], 20, 20)) # ====================== # VIEW & NAVIGATION # ====================== @@ -342,29 +342,29 @@ class GameWindow: if not self.audio: return sound_path = os.path.join("sound", sound_file) - rw = sdl2.SDL_RWFromFile(byteify(sound_path, "utf-8"), b"rb") + rw = sdl2_layer.SDL_RWFromFile(byteify(sound_path, "utf-8"), b"rb") if not rw: raise RuntimeError("Failed to open sound file") - _buf = POINTER(sdl2.Uint8)() - _length = sdl2.Uint32() + _buf = POINTER(sdl2_layer.Uint8)() + _length = sdl2_layer.Uint32() - spec = SDL_AudioSpec(freq=22050, aformat=sdl2.AUDIO_U8, channels=1, samples=2048) - if sdl2.SDL_LoadWAV_RW(rw, 1, byref(spec), byref(_buf), byref(_length)) == None: + spec = SDL_AudioSpec(freq=22050, aformat=sdl2_layer.AUDIO_U8, channels=1, samples=2048) + if sdl2_layer.SDL_LoadWAV_RW(rw, 1, byref(spec), byref(_buf), byref(_length)) == None: raise RuntimeError("Failed to load WAV") devid = self.audio_devs[tag] # Clear any queued audio - sdl2.SDL_ClearQueuedAudio(devid) + sdl2_layer.SDL_ClearQueuedAudio(devid) # Start playing audio - sdl2.SDL_QueueAudio(devid, _buf, _length) - sdl2.SDL_PauseAudioDevice(devid, 0) + sdl2_layer.SDL_QueueAudio(devid, _buf, _length) + sdl2_layer.SDL_PauseAudioDevice(devid, 0) def stop_sound(self): """Stop all audio playback""" for dev in self.audio_devs.values(): - sdl2.SDL_PauseAudioDevice(dev, 1) - sdl2.SDL_ClearQueuedAudio(dev) + sdl2_layer.SDL_PauseAudioDevice(dev, 1) + sdl2_layer.SDL_ClearQueuedAudio(dev) # ====================== # INPUT METHODS @@ -372,8 +372,8 @@ class GameWindow: def load_joystick(self): """Initialize joystick support""" - sdl2.SDL_Init(sdl2.SDL_INIT_JOYSTICK) - sdl2.SDL_JoystickOpen(0) + sdl2_layer.SDL_Init(sdl2_layer.SDL_INIT_JOYSTICK) + sdl2_layer.SDL_JoystickOpen(0) # ====================== # MAIN GAME LOOP @@ -382,7 +382,7 @@ class GameWindow: def mainloop(self, **kwargs): """Main game loop handling events and rendering""" while self.running: - performance_start = sdl2.SDL_GetPerformanceCounter() + performance_start = sdl2_layer.SDL_GetPerformanceCounter() self.renderer.clear() # Execute background update if provided @@ -397,30 +397,30 @@ class GameWindow: self.draw_white_flash() # Handle SDL events - events = sdl2.ext.get_events() + events = sdl2_layer.ext.get_events() for event in events: - if event.type == sdl2.SDL_QUIT: + if event.type == sdl2_layer.SDL_QUIT: self.running = False - elif event.type == sdl2.SDL_KEYDOWN: + elif event.type == sdl2_layer.SDL_KEYDOWN: # print in file keycode keycode = event.key.keysym.sym - key = sdl2.SDL_GetKeyName(event.key.keysym.sym).decode('utf-8') + key = sdl2_layer.SDL_GetKeyName(event.key.keysym.sym).decode('utf-8') key = key.replace(" ", "_") # Check for Right Ctrl key to trigger white flash self.trigger(f"keydown_{key}") - elif event.type == sdl2.SDL_KEYUP: - key = sdl2.SDL_GetKeyName(event.key.keysym.sym).decode('utf-8') + elif event.type == sdl2_layer.SDL_KEYUP: + key = sdl2_layer.SDL_GetKeyName(event.key.keysym.sym).decode('utf-8') key = key.replace(" ", "_") self.trigger(f"keyup_{key}") - elif event.type == sdl2.SDL_MOUSEMOTION: + elif event.type == sdl2_layer.SDL_MOUSEMOTION: self.trigger(f"mousemove_{event.motion.x}, {event.motion.y}") - elif event.type == sdl2.SDL_JOYBUTTONDOWN: + elif event.type == sdl2_layer.SDL_JOYBUTTONDOWN: key = event.jbutton.button self.trigger(f"joybuttondown_{key}") - elif event.type == sdl2.SDL_JOYBUTTONUP: + elif event.type == sdl2_layer.SDL_JOYBUTTONUP: key = event.jbutton.button self.trigger(f"joybuttonup_{key}") - elif event.type == sdl2.SDL_JOYHATMOTION: + elif event.type == sdl2_layer.SDL_JOYHATMOTION: hat = event.jhat.hat value = event.jhat.value self.trigger(f"joyhatmotion_{hat}_{value}") @@ -431,11 +431,11 @@ class GameWindow: self.renderer.present() # Calculate performance and delay - self.performance = ((sdl2.SDL_GetPerformanceCounter() - performance_start) / - sdl2.SDL_GetPerformanceFrequency() * 1000) + self.performance = ((sdl2_layer.SDL_GetPerformanceCounter() - performance_start) / + sdl2_layer.SDL_GetPerformanceFrequency() * 1000) delay = max(0, self.delay - round(self.performance)) - sdl2.SDL_Delay(delay) + sdl2_layer.SDL_Delay(delay) # ====================== # SPECIAL EFFECTS @@ -444,7 +444,7 @@ class GameWindow: def trigger_white_flash(self): """Trigger the white flash effect""" self.white_flash_active = True - self.white_flash_start_time = sdl2.SDL_GetTicks() + self.white_flash_start_time = sdl2_layer.SDL_GetTicks() self.white_flash_opacity = 255 def update_white_flash(self): @@ -452,7 +452,7 @@ class GameWindow: if not self.white_flash_active: return False - current_time = sdl2.SDL_GetTicks() + current_time = sdl2_layer.SDL_GetTicks() elapsed_time = current_time - self.white_flash_start_time if elapsed_time < 500: # First 500ms : full white @@ -472,7 +472,7 @@ class GameWindow: """Draw the white flash overlay""" if self.white_flash_opacity > 0: # Create a white surface with the current opacity - white_surface = sdl2.SDL_CreateRGBSurface( + white_surface = sdl2_layer.SDL_CreateRGBSurface( 0, self.target_size[0], self.target_size[1], 32, 0x000000FF, # R mask 0x0000FF00, # G mask @@ -482,8 +482,8 @@ class GameWindow: if white_surface: # Fill surface with white - sdl2.SDL_FillRect(white_surface, None, - sdl2.SDL_MapRGBA(white_surface.contents.format, + sdl2_layer.SDL_FillRect(white_surface, None, + sdl2_layer.SDL_MapRGBA(white_surface.contents.format, 255, 255, 255, self.white_flash_opacity)) # Convert to texture and draw @@ -491,13 +491,13 @@ class GameWindow: white_texture.position = (0, 0) # Enable alpha blending for the texture - sdl2.SDL_SetTextureBlendMode(white_texture.texture, sdl2.SDL_BLENDMODE_BLEND) + sdl2_layer.SDL_SetTextureBlendMode(white_texture.texture, sdl2_layer.SDL_BLENDMODE_BLEND) # Draw the white overlay - self.renderer.copy(white_texture, dstrect=sdl2.SDL_Rect(0, 0, self.target_size[0], self.target_size[1])) + self.renderer.copy(white_texture, dstrect=sdl2_layer.SDL_Rect(0, 0, self.target_size[0], self.target_size[1])) # Clean up - sdl2.SDL_FreeSurface(white_surface) + sdl2_layer.SDL_FreeSurface(white_surface) # ====================== # UTILITY METHODS @@ -509,16 +509,16 @@ class GameWindow: def full_screen(self, flag): """Toggle fullscreen mode""" - sdl2.SDL_SetWindowFullscreen(self.window.window, flag) + sdl2_layer.SDL_SetWindowFullscreen(self.window.window, flag) def get_perf_counter(self): """Get performance counter for timing""" - return sdl2.SDL_GetPerformanceCounter() + return sdl2_layer.SDL_GetPerformanceCounter() def close(self): """Close the game window and cleanup""" self.running = False - sdl2.ext.quit() + sdl2_layer.ext.quit() # ====================== # MAIN GAME LOOP @@ -535,7 +535,7 @@ class GameWindow: size = self.cell_size # Create RGBA surface for blood splatter - blood_surface = sdl2.SDL_CreateRGBSurface( + blood_surface = sdl2_layer.SDL_CreateRGBSurface( 0, size, size, 32, 0x000000FF, # R mask 0x0000FF00, # G mask @@ -547,7 +547,7 @@ class GameWindow: return None # Lock surface for pixel manipulation - sdl2.SDL_LockSurface(blood_surface) + sdl2_layer.SDL_LockSurface(blood_surface) # Get pixel data pixels = cast(blood_surface.contents.pixels, POINTER(c_uint32)) @@ -613,31 +613,31 @@ class GameWindow: pixels[ny * pitch + nx] = color # Unlock surface - sdl2.SDL_UnlockSurface(blood_surface) + sdl2_layer.SDL_UnlockSurface(blood_surface) return blood_surface def draw_blood_surface(self, blood_surface, position): """Convert blood surface to texture and return it""" # Create temporary surface for blood texture - temp_surface = sdl2.SDL_CreateRGBSurface(0, self.cell_size, self.cell_size, 32, 0, 0, 0, 0) + temp_surface = sdl2_layer.SDL_CreateRGBSurface(0, self.cell_size, self.cell_size, 32, 0, 0, 0, 0) if temp_surface is None: - sdl2.SDL_FreeSurface(blood_surface) + sdl2_layer.SDL_FreeSurface(blood_surface) return None # Copy blood surface to temporary surface - sdl2.SDL_BlitSurface(blood_surface, None, temp_surface, None) - sdl2.SDL_FreeSurface(blood_surface) + sdl2_layer.SDL_BlitSurface(blood_surface, None, temp_surface, None) + sdl2_layer.SDL_FreeSurface(blood_surface) # Create texture from temporary surface texture = self.factory.from_surface(temp_surface) - sdl2.SDL_FreeSurface(temp_surface) + sdl2_layer.SDL_FreeSurface(temp_surface) return texture def combine_blood_surfaces(self, existing_surface, new_surface): """Combine two blood surfaces by blending them together""" # Create combined surface - combined_surface = sdl2.SDL_CreateRGBSurface( + combined_surface = sdl2_layer.SDL_CreateRGBSurface( 0, self.cell_size, self.cell_size, 32, 0x000000FF, # R mask 0x0000FF00, # G mask @@ -649,9 +649,9 @@ class GameWindow: return existing_surface # Lock surfaces for pixel manipulation - sdl2.SDL_LockSurface(existing_surface) - sdl2.SDL_LockSurface(new_surface) - sdl2.SDL_LockSurface(combined_surface) + sdl2_layer.SDL_LockSurface(existing_surface) + sdl2_layer.SDL_LockSurface(new_surface) + sdl2_layer.SDL_LockSurface(combined_surface) # Get pixel data existing_pixels = cast(existing_surface.contents.pixels, POINTER(c_uint32)) @@ -704,13 +704,13 @@ class GameWindow: combined_pixels[idx] = (final_a << 24) | (final_r << 16) | (final_g << 8) | final_b # Unlock surfaces - sdl2.SDL_UnlockSurface(existing_surface) - sdl2.SDL_UnlockSurface(new_surface) - sdl2.SDL_UnlockSurface(combined_surface) + sdl2_layer.SDL_UnlockSurface(existing_surface) + sdl2_layer.SDL_UnlockSurface(new_surface) + sdl2_layer.SDL_UnlockSurface(combined_surface) return combined_surface def free_surface(self, surface): """Safely free an SDL surface""" if surface is not None: - sdl2.SDL_FreeSurface(surface) \ No newline at end of file + sdl2_layer.SDL_FreeSurface(surface) \ No newline at end of file diff --git a/key.py b/key.py deleted file mode 100644 index 19740a5..0000000 --- a/key.py +++ /dev/null @@ -1,82 +0,0 @@ -#!/usr/bin/env python3 - -import sys -import os -import sdl2 -import sdl2.ext - -class KeyLogger: - def __init__(self): - # Initialize SDL2 - sdl2.ext.init(joystick=True, video=True, audio=False) - # Initialize joystick support - sdl2.SDL_Init(sdl2.SDL_INIT_JOYSTICK) - sdl2.SDL_JoystickOpen(0) - sdl2.SDL_JoystickOpen(1) # Open the first joystick - sdl2.SDL_JoystickEventState(sdl2.SDL_ENABLE) - self.window = sdl2.ext.Window("Key Logger", size=(640, 480)) - self.window.show() - self.running = True - self.key_down = True - self.font = sdl2.ext.FontManager("assets/decterm.ttf", size=24) - - def run(self): - # Main loop - - while self.running: - # Handle SDL events - events = sdl2.ext.get_events() - for event in events: - self.event = event.type - if event.type == sdl2.SDL_KEYDOWN: - keycode = event.key.keysym.sym - # Log keycode to file - self.message = f"Key pressed: {sdl2.SDL_GetKeyName(keycode).decode('utf-8')}" - elif event.type == sdl2.SDL_KEYUP: - keycode = event.key.keysym.sym - # Log keycode to file - self.message = f"Key released: {sdl2.SDL_GetKeyName(keycode).decode('utf-8')}" - elif event.type == sdl2.SDL_JOYBUTTONDOWN: - button = event.jbutton.button - self.message = f"Joystick button {button} pressed" - if button == 9: # Assuming button 0 is the right trigger - self.running = False - elif event.type == sdl2.SDL_JOYBUTTONUP: - button = event.jbutton.button - self.message = f"Joystick button {button} released" - elif event.type == sdl2.SDL_JOYAXISMOTION: - axis = event.jaxis.axis - value = event.jaxis.value - self.message = f"Joystick axis {axis} moved to {value}" - elif event.type == sdl2.SDL_JOYHATMOTION: - hat = event.jhat.hat - value = event.jhat.value - self.message = f"Joystick hat {hat} moved to {value}" - elif event.type == sdl2.SDL_QUIT: - self.running = False - - # Update the window - sdl2.ext.fill(self.window.get_surface(), sdl2.ext.Color(34, 0, 33)) - greeting = self.font.render("Press any key...", color=sdl2.ext.Color(255, 255, 255)) - sdl2.SDL_BlitSurface(greeting, None, self.window.get_surface(), None) - if hasattr(self, 'message'): - text_surface = self.font.render(self.message, color=sdl2.ext.Color(255, 255, 255)) - sdl2.SDL_BlitSurface(text_surface, None, self.window.get_surface(), sdl2.SDL_Rect(0, 30, 640, 480)) - if hasattr(self, 'event'): - event_surface = self.font.render(f"Event: {self.event}", color=sdl2.ext.Color(255, 255, 255)) - sdl2.SDL_BlitSurface(event_surface, None, self.window.get_surface(), sdl2.SDL_Rect(0, 60, 640, 480)) - sdl2.SDL_UpdateWindowSurface(self.window.window) - # Refresh the window - - self.window.refresh() - sdl2.SDL_Delay(10) - # Check for quit event - if not self.running: - break - # Cleanup - sdl2.ext.quit() - -if __name__ == "__main__": - logger = KeyLogger() - logger.run() - \ No newline at end of file diff --git a/rats.py b/rats.py index 59c07fe..b0ec292 100644 --- a/rats.py +++ b/rats.py @@ -4,9 +4,9 @@ import random import os import json -from engine import maze, sdl2 as engine, controls, graphics, unit_manager, scoring +from engine import maze, controls, graphics, pygame_layer as engine, unit_manager, scoring from units import points -from engine.user_profile_integration import UserProfileIntegration, get_global_leaderboard +from engine.user_profile_integration import UserProfileIntegration class MiceMaze( @@ -20,21 +20,55 @@ class MiceMaze( def __init__(self, maze_file): # Initialize user profile integration + print("[DEBUG] Initializing user profile integration...") self.profile_integration = UserProfileIntegration() + print(f"[DEBUG] Profile integration initialized. Has current_profile: {self.profile_integration.current_profile is not None}") + + if self.profile_integration.current_profile: + print(f"[DEBUG] Current profile: {self.profile_integration.get_profile_name()}") + else: + print("[DEBUG] No profile loaded, will use default settings") + + #self.profile_integration = None self.map = maze.Map(maze_file) - # Load profile-specific settings - self.audio = self.profile_integration.get_setting('sound_enabled', True) - sound_volume = self.profile_integration.get_setting('sound_volume', 50) + # Load profile'-specific settings + if self.profile_integration is None: + self.audio = True + sound_volume = 50 + else: + self.audio = self.profile_integration.get_setting('sound_enabled', True) + sound_volume = self.profile_integration.get_setting('sound_volume', 50) self.cell_size = 40 self.full_screen = False # Initialize render engine with profile-aware title - player_name = self.profile_integration.get_profile_name() + if self.profile_integration is None: + player_name = "Guest" + else: + player_name = self.profile_integration.get_profile_name() window_title = f"Mice! - {player_name}" - + + # If running under Pyodide in the browser, ensure the JS canvas is bound + # to Pyodide's pygame integration _before_ creating the display. This + # avoids cases where pygame.display.set_mode is called before the HTML + # canvas is attached, which would result in a blank canvas in the page. + try: + # 'js' is available under Pyodide as a proxy to the global window + import js + try: + canvas_el = js.document.getElementById('canvas') + if hasattr(js.pyodide, 'canvas') and hasattr(js.pyodide.canvas, 'setCanvas2D'): + js.pyodide.canvas.setCanvas2D(canvas_el) + except Exception: + # Non-fatal: continue with engine initialization + pass + except Exception: + # Not running under Pyodide (native run), ignore + pass + self.render_engine = engine.GameWindow(self.map.width, self.map.height, self.cell_size, window_title, key_callback=self.trigger) @@ -44,7 +78,9 @@ class MiceMaze( self.render_engine.set_volume(sound_volume) self.load_assets() - self.render_engine.window.show() + # Show window (for pygame, this is implicit; for SDL2 it's explicit) + if hasattr(self.render_engine.window, 'show'): + self.render_engine.window.show() self.pointer = (random.randint(1, self.map.width-2), random.randint(1, self.map.height-2)) self.scroll_cursor() self.points = 0 @@ -78,7 +114,7 @@ class MiceMaze( "max": 8 }, "nuclear": { - "count": 1, + "count": 11, "max": 1 }, "mine": { @@ -126,8 +162,14 @@ class MiceMaze( return if self.game_status == "start_menu": # Create personalized greeting - player_name = self.profile_integration.get_profile_name() - device_id = self.profile_integration.get_device_id() + if self.profile_integration: + player_name = self.profile_integration.get_profile_name() + else: + player_name = "Guest" + if self.profile_integration: + device_id = self.profile_integration.get_device_id() + else: + device_id = "Unknown Device" greeting_title = f"Welcome to Mice, {player_name}!" @@ -136,7 +178,7 @@ class MiceMaze( device_line = f"Device: {device_id}" # Show profile stats if available - if self.profile_integration.current_profile: + if self.profile_integration and self.profile_integration.current_profile: profile = self.profile_integration.current_profile stats_line = f"Best Score: {profile['best_score']} | Games: {profile['games_played']}" full_subtitle = f"{subtitle}\n{device_line}\n{stats_line}" @@ -145,7 +187,7 @@ class MiceMaze( self.render_engine.dialog(greeting_title, subtitle=full_subtitle, - image=self.assets["BMP_WEWIN"]) + image=self.assets["da"]) return self.render_engine.delete_tag("unit") self.render_engine.delete_tag("effect") @@ -165,6 +207,20 @@ class MiceMaze( self.scroll() self.render_engine.new_cycle(50, self.update_maze) + def tick(self): + """Run a single frame tick: update logic + background update (non-blocking). + Intended to be called repeatedly from the browser via requestAnimationFrame. + """ + try: + # Use render_engine.step() to run one frame iteration (draw + flip) + if hasattr(self.render_engine, 'step'): + self.render_engine.step(update=self.update_maze, bg_update=self.draw_maze) + else: + # Fallback: call update_maze directly + self.update_maze() + except Exception: + pass + def run(self): self.render_engine.mainloop(update=self.update_maze, bg_update=self.draw_maze) @@ -173,7 +229,7 @@ class MiceMaze( def game_over(self): if self.game_end[0]: if not self.combined_scores: - self.combined_scores = get_global_leaderboard(4) + self.combined_scores = self.profile_integration.get_global_leaderboard(4) global_scores = [] for entry in self.combined_scores: @@ -202,16 +258,21 @@ class MiceMaze( return True count_rats = self.count_rats() if count_rats > 200: + print("[DEBUG GAME_OVER] Loss condition: rats > 200") + print(f"[DEBUG GAME_OVER] Rat count: {count_rats}, Points: {self.points}") self.render_engine.stop_sound() self.render_engine.play_sound("WEWIN.WAV") self.game_end = (True, False) self.game_status = "paused" # Track incomplete game in profile + print(f"[DEBUG GAME_OVER] Calling update_game_stats(completed=False)") self.profile_integration.update_game_stats(self.points, completed=False) return True if not count_rats and not any(isinstance(unit, points.Point) for unit in self.units.values()): + print("[DEBUG GAME_OVER] Win condition: all rats and points cleared") + print(f"[DEBUG GAME_OVER] Points earned: {self.points}") self.render_engine.stop_sound() self.render_engine.play_sound("VICTORY.WAV") self.render_engine.play_sound("WELLDONE.WAV", tag="effects") @@ -219,7 +280,9 @@ class MiceMaze( self.game_status = "paused" # Save score to both traditional file and user profile + print(f"[DEBUG GAME_OVER] Calling save_score()") self.save_score() + print(f"[DEBUG GAME_OVER] Calling update_game_stats(completed=True)") self.profile_integration.update_game_stats(self.points, completed=True) return True diff --git a/requirements.txt b/requirements.txt index 090618a..4ed0317 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,5 @@ pysdl2 +pygame Pillow -pyaml \ No newline at end of file +pyaml +requests \ No newline at end of file diff --git a/sound/converted/Death.wav b/sound/converted/Death.wav deleted file mode 100644 index 68ba53d..0000000 Binary files a/sound/converted/Death.wav and /dev/null differ diff --git a/units/__pycache__/rat.cpython-313.pyc b/units/__pycache__/rat.cpython-313.pyc index e81c4c8..6827ed9 100644 Binary files a/units/__pycache__/rat.cpython-313.pyc and b/units/__pycache__/rat.cpython-313.pyc differ diff --git a/units/__pycache__/unit.cpython-313.pyc b/units/__pycache__/unit.cpython-313.pyc index df01ebe..8aa9bd8 100644 Binary files a/units/__pycache__/unit.cpython-313.pyc and b/units/__pycache__/unit.cpython-313.pyc differ diff --git a/units/rat.py b/units/rat.py index cc4f353..f22d787 100644 --- a/units/rat.py +++ b/units/rat.py @@ -80,7 +80,7 @@ class Rat(Unit): units.extend(self.game.unit_positions.get(self.position, [])) for unit in units: - if unit.id == self.id or unit.age < AGE_THRESHOLD or self.position != unit.position_before: + if unit.id == self.id or unit.age < AGE_THRESHOLD: continue x1, y1, x2, y2 = self.bbox ox1, oy1, ox2, oy2 = unit.bbox diff --git a/user_profiles.json b/user_profiles.json index 62f8e00..e0e34f9 100644 --- a/user_profiles.json +++ b/user_profiles.json @@ -3,9 +3,9 @@ "Player1": { "name": "Player1", "created_date": "2024-01-15T10:30:00", - "last_played": "2025-08-24T21:49:04.187787", - "games_played": 25, - "total_score": 15420, + "last_played": "2025-10-17T17:00:43.907946", + "games_played": 28, + "total_score": 15555, "best_score": 980, "settings": { "difficulty": "normal",