From 7e4c3d66388215e7aa528279b6411a0dc64e2685 Mon Sep 17 00:00:00 2001 From: apocalypsai-bot Date: Wed, 8 Jul 2026 02:22:42 +0000 Subject: [PATCH] feat(gemini): A Dockerized utility that simulates a scavenger drone reporting on discovered resources and anomalies in a post-apocalyptic wasteland. --- .../Dockerfile | 10 ++ .../README.md | 103 ++++++++++++++ .../src/drone_sim.py | 47 +++++++ .../src/requirements.txt | 1 + .../tests/test_drone_sim.py | 132 ++++++++++++++++++ 5 files changed, 293 insertions(+) create mode 100644 docker-tools/nightly-nightly-scavenger-drone-sim/Dockerfile create mode 100644 docker-tools/nightly-nightly-scavenger-drone-sim/README.md create mode 100644 docker-tools/nightly-nightly-scavenger-drone-sim/src/drone_sim.py create mode 100644 docker-tools/nightly-nightly-scavenger-drone-sim/src/requirements.txt create mode 100644 docker-tools/nightly-nightly-scavenger-drone-sim/tests/test_drone_sim.py diff --git a/docker-tools/nightly-nightly-scavenger-drone-sim/Dockerfile b/docker-tools/nightly-nightly-scavenger-drone-sim/Dockerfile new file mode 100644 index 0000000000..181fc941f7 --- /dev/null +++ b/docker-tools/nightly-nightly-scavenger-drone-sim/Dockerfile @@ -0,0 +1,10 @@ +FROM python:3.9-slim-buster + +WORKDIR /app + +COPY src/requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +COPY src/drone_sim.py . + +CMD ["python", "drone_sim.py"] diff --git a/docker-tools/nightly-nightly-scavenger-drone-sim/README.md b/docker-tools/nightly-nightly-scavenger-drone-sim/README.md new file mode 100644 index 0000000000..15de765e8e --- /dev/null +++ b/docker-tools/nightly-nightly-scavenger-drone-sim/README.md @@ -0,0 +1,103 @@ +# Nightly Scavenger Drone Simulator (`nightly-scavenger-drone-sim`) + +A whimsical-yet-useful Dockerized utility that simulates a scavenger drone reporting on discovered resources and anomalies in a post-apocalyptic wasteland. This tool can be used for: + +- **Testing Monitoring Systems**: Generate a stream of simulated resource reports and anomalies to test how your monitoring or log aggregation systems handle varied data. +- **Demonstrating Docker**: A simple, self-contained example of packaging a Python script into a Docker image. +- **Whimsical Background Process**: Run it as a cron job on a server to add a touch of post-apocalyptic flavor to your system logs. + +## Classifier + +`docker-tools` + +## How it Works + +The utility runs a Python script inside a Docker container. The script randomly generates a JSON report containing: +- A timestamp and a drone ID (configurable via `DRONE_ID` environment variable). +- A simulated location (sector and grid). +- A list of "findings," which can include: + - Discovered resources (e.g., "scrap metal", "purified water") with quantities. + - Detected anomalies (e.g., "temporal distortion", "unidentified signal source"). + - A "no significant findings" status if nothing else is found. + +The report is printed to standard output (stdout) as a JSON string. + +## Usage + +### 1. Build the Docker Image + +Navigate to the `nightly-scavenger-drone-sim` directory and build the Docker image: + +```bash +docker build -t scavenger-drone-sim . +``` + +### 2. Run the Simulator + +You can run the simulator to generate a single report: + +```bash +docker run scavenger-drone-sim +``` + +Example output: + +```json +{ + "timestamp": "2023-10-27T10:30:00+00:00", + "drone_id": "DRONE-ALPHA-7", + "location": { + "sector": "Alpha", + "grid": "42-88" + }, + "findings": [ + { + "type": "resource", + "item": "scrap metal", + "quantity": 5 + }, + { + "type": "anomaly", + "description": "temporal distortion detected" + } + ] +} +``` + +### 3. Customize Drone ID + +Set the `DRONE_ID` environment variable to give your drone a unique identifier: + +```bash +docker run -e DRONE_ID="DRONE-BETA-9000" scavenger-drone-sim +``` + +### 4. Continuous Reporting (Example) + +To simulate continuous reporting, you could run it in a loop (e.g., every 5 seconds): + +```bash +while true; do docker run scavenger-drone-sim; sleep 5; done +``` + +Or, for a more robust solution, integrate it into a `cron` job or a container orchestration platform. + +## Development and Testing + +### Prerequisites + +- Python 3.9+ +- Docker + +### Running Tests + +The tests ensure that the report generation logic works as expected under various conditions, using mocks to make random outcomes deterministic. + +```bash +# Ensure you are in the nightly-scavenger-drone-sim directory +python -m unittest tests/test_drone_sim.py +``` + +## Contributing + +Feel free to enhance the drone's findings, add more resource types, or introduce new anomaly categories! diff --git a/docker-tools/nightly-nightly-scavenger-drone-sim/src/drone_sim.py b/docker-tools/nightly-nightly-scavenger-drone-sim/src/drone_sim.py new file mode 100644 index 0000000000..ee8ea5cfa0 --- /dev/null +++ b/docker-tools/nightly-nightly-scavenger-drone-sim/src/drone_sim.py @@ -0,0 +1,47 @@ +import random +import json +import datetime +import os + +def generate_report(): + resources = [ + "scrap metal", "diluted fuel", "purified water", "ancient tech parts", + "mutated flora samples", "intact pre-fall rations", "medical supplies" + ] + anomalies = [ + "temporal distortion detected", "faint energy signature", "unidentified signal source", + "strange atmospheric phenomenon", "ghostly echo of a bygone era", "localized gravity fluctuation" + ] + + report = { + "timestamp": datetime.datetime.now(datetime.timezone.utc).isoformat(), + "drone_id": os.getenv("DRONE_ID", "DRONE-ALPHA-7"), + "location": { + "sector": random.choice(["Alpha", "Beta", "Gamma", "Delta"]), + "grid": f"{random.randint(1, 99):02d}-{random.randint(1, 99):02d}" + }, + "findings": [] + } + + # Decide if we find resources + if random.random() < 0.7: # 70% chance of finding resources + num_resources = random.randint(1, 3) + for _ in range(num_resources): + resource = random.choice(resources) + quantity = random.randint(1, 10) + report["findings"].append({"type": "resource", "item": resource, "quantity": quantity}) + + # Decide if we detect anomalies + if random.random() < 0.3: # 30% chance of detecting anomalies + num_anomalies = random.randint(1, 2) + for _ in range(num_anomalies): + anomaly = random.choice(anomalies) + report["findings"].append({"type": "anomaly", "description": anomaly}) + + if not report["findings"]: + report["findings"].append({"type": "status", "description": "No significant findings, routine patrol."}) + + return json.dumps(report, indent=2) + +if __name__ == "__main__": + print(generate_report()) diff --git a/docker-tools/nightly-nightly-scavenger-drone-sim/src/requirements.txt b/docker-tools/nightly-nightly-scavenger-drone-sim/src/requirements.txt new file mode 100644 index 0000000000..f59638a7b8 --- /dev/null +++ b/docker-tools/nightly-nightly-scavenger-drone-sim/src/requirements.txt @@ -0,0 +1 @@ +# No external dependencies for this simple script diff --git a/docker-tools/nightly-nightly-scavenger-drone-sim/tests/test_drone_sim.py b/docker-tools/nightly-nightly-scavenger-drone-sim/tests/test_drone_sim.py new file mode 100644 index 0000000000..5d6235f17d --- /dev/null +++ b/docker-tools/nightly-nightly-scavenger-drone-sim/tests/test_drone_sim.py @@ -0,0 +1,132 @@ +import unittest +from unittest.mock import patch, MagicMock +import json +import datetime +import os +from drone_sim import generate_report # Assuming drone_sim.py is in the same directory for testing + +class TestDroneSim(unittest.TestCase): + + @patch('drone_sim.datetime') + @patch('drone_sim.random.random') + @patch('drone_sim.random.choice') + @patch('drone_sim.random.randint') + @patch.dict(os.environ, {'DRONE_ID': 'TEST-DRONE-001'}) # Mock rationale: Set a consistent DRONE_ID for tests + def test_report_with_resources_and_anomalies(self, mock_randint, mock_choice, mock_random, mock_datetime): + # Mock rationale: Ensure deterministic timestamp + mock_datetime.datetime.now.return_value = datetime.datetime(2023, 10, 27, 10, 30, 0, tzinfo=datetime.timezone.utc) + mock_datetime.timezone.utc = datetime.timezone.utc + + # Mock rationale: Control random outcomes for resources and anomalies + # random.random() calls: + # 1. For resources (should be < 0.7) + # 2. For anomalies (should be < 0.3) + mock_random.side_effect = [0.5, 0.2] # 0.5 < 0.7 (resources), 0.2 < 0.3 (anomalies) + + # Mock rationale: Control random choices for items and descriptions + mock_choice.side_effect = [ + "Alpha", "01-01", # Location + "scrap metal", # Resource 1 + "diluted fuel", # Resource 2 + "temporal distortion detected", # Anomaly 1 + "unidentified signal source" # Anomaly 2 + ] + + # Mock rationale: Control random integers for quantities and counts + # random.randint() calls: + # 1. num_resources (1-3) -> 2 + # 2. quantity for scrap metal (1-10) -> 5 + # 3. quantity for diluted fuel (1-10) -> 3 + # 4. num_anomalies (1-2) -> 2 + mock_randint.side_effect = [2, 5, 3, 2] + + report_str = generate_report() + report = json.loads(report_str) + + self.assertEqual(report["drone_id"], "TEST-DRONE-001") + self.assertEqual(report["timestamp"], "2023-10-27T10:30:00+00:00") + self.assertEqual(report["location"]["sector"], "Alpha") + self.assertEqual(report["location"]["grid"], "01-01") + self.assertEqual(len(report["findings"]), 4) # 2 resources + 2 anomalies + + self.assertEqual(report["findings"][0]["type"], "resource") + self.assertEqual(report["findings"][0]["item"], "scrap metal") + self.assertEqual(report["findings"][0]["quantity"], 5) + + self.assertEqual(report["findings"][1]["type"], "resource") + self.assertEqual(report["findings"][1]["item"], "diluted fuel") + self.assertEqual(report["findings"][1]["quantity"], 3) + + self.assertEqual(report["findings"][2]["type"], "anomaly") + self.assertEqual(report["findings"][2]["description"], "temporal distortion detected") + + self.assertEqual(report["findings"][3]["type"], "anomaly") + self.assertEqual(report["findings"][3]["description"], "unidentified signal source") + + @patch('drone_sim.datetime') + @patch('drone_sim.random.random') + @patch('drone_sim.random.choice') + @patch('drone_sim.random.randint') + @patch.dict(os.environ, {'DRONE_ID': 'TEST-DRONE-002'}) # Mock rationale: Set a consistent DRONE_ID for tests + def test_report_no_findings(self, mock_randint, mock_choice, mock_random, mock_datetime): + # Mock rationale: Ensure deterministic timestamp + mock_datetime.datetime.now.return_value = datetime.datetime(2023, 10, 27, 11, 0, 0, tzinfo=datetime.timezone.utc) + mock_datetime.timezone.utc = datetime.timezone.utc + + # Mock rationale: Control random outcomes to ensure no resources or anomalies are found + mock_random.side_effect = [0.8, 0.4] # 0.8 > 0.7 (no resources), 0.4 > 0.3 (no anomalies) + + # Mock rationale: Control random choices for location + mock_choice.side_effect = ["Beta", "02-02"] + + # Mock rationale: No randint calls expected for findings, but location grid uses it. + mock_randint.side_effect = [2, 2] # For location grid 02-02 + + report_str = generate_report() + report = json.loads(report_str) + + self.assertEqual(report["drone_id"], "TEST-DRONE-002") + self.assertEqual(report["timestamp"], "2023-10-27T11:00:00+00:00") + self.assertEqual(report["location"]["sector"], "Beta") + self.assertEqual(report["location"]["grid"], "02-02") + self.assertEqual(len(report["findings"]), 1) + self.assertEqual(report["findings"][0]["type"], "status") + self.assertEqual(report["findings"][0]["description"], "No significant findings, routine patrol.") + + @patch('drone_sim.datetime') + @patch('drone_sim.random.random') + @patch('drone_sim.random.choice') + @patch('drone_sim.random.randint') + @patch.dict(os.environ, {'DRONE_ID': 'TEST-DRONE-003'}) # Mock rationale: Set a consistent DRONE_ID for tests + def test_report_only_resources(self, mock_randint, mock_choice, mock_random, mock_datetime): + # Mock rationale: Ensure deterministic timestamp + mock_datetime.datetime.now.return_value = datetime.datetime(2023, 10, 27, 12, 0, 0, tzinfo=datetime.timezone.utc) + mock_datetime.timezone.utc = datetime.timezone.utc + + # Mock rationale: Control random outcomes to ensure resources are found, but no anomalies + mock_random.side_effect = [0.1, 0.5] # 0.1 < 0.7 (resources), 0.5 > 0.3 (no anomalies) + + # Mock rationale: Control random choices for location and resources + mock_choice.side_effect = [ + "Gamma", "03-03", # Location + "purified water" # Resource 1 + ] + + # Mock rationale: Control random integers for quantities and counts + mock_randint.side_effect = [1, 7, 3, 3] # num_resources=1, quantity=7, location grid 03-03 + + report_str = generate_report() + report = json.loads(report_str) + + self.assertEqual(report["drone_id"], "TEST-DRONE-003") + self.assertEqual(report["timestamp"], "2023-10-27T12:00:00+00:00") + self.assertEqual(report["location"]["sector"], "Gamma") + self.assertEqual(report["location"]["grid"], "03-03") + self.assertEqual(len(report["findings"]), 1) + + self.assertEqual(report["findings"][0]["type"], "resource") + self.assertEqual(report["findings"][0]["item"], "purified water") + self.assertEqual(report["findings"][0]["quantity"], 7) + +if __name__ == '__main__': + unittest.main()