Skip to content

Commit 617857a

Browse files
committed
🚑 📝 ✨ ✨ Update pyproject.toml to include development dependencies; enhance docstrings and unit tests for clarity and coverage
1 parent c0b6020 commit 617857a

File tree

5 files changed

+224
-6
lines changed

5 files changed

+224
-6
lines changed

poetry.lock

Lines changed: 187 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,15 @@ pandas = "^2.2.3"
1111
scikit-learn = "^1.6.0"
1212
numpy = "^2.2.1"
1313
matplotlib = "^3.10.0"
14-
pytest = "^8.3.4"
1514

1615

16+
[tool.poetry.group.dev.dependencies]
17+
ruff = "^0.8.4"
18+
black = "^24.10.0"
19+
flake8 = "^7.1.1"
20+
autopep8 = "^2.3.1"
21+
pytest = "^8.3.4"
22+
1723
[build-system]
1824
requires = ["poetry-core"]
1925
build-backend = "poetry.core.masonry.api"

src/battle_clustering.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
from sklearn.preprocessing import StandardScaler
77
import matplotlib.pyplot as plt
88

9+
910
class BattleClustering:
11+
"""Clustering battles using K-Means"""
1012
def __init__(self, data_path, n_clusters=3, random_state=42):
1113
self.data_path = data_path
1214
self.n_clusters = n_clusters
@@ -24,8 +26,15 @@ def load_data(self):
2426
def preprocess_data(self):
2527
"""Preprocess data by encoding categorical columns and scaling features"""
2628
categorical_columns = ["Terrain", "Weather", "Key_Factors"]
27-
self.data_encoded = pd.get_dummies(self.data, columns=categorical_columns, drop_first=True)
28-
X = self.data_encoded.drop(columns=["Outcome", "Battle_Name"]) # Drop the target and non-feature columns
29+
self.data_encoded = pd.get_dummies(
30+
self.data, columns=categorical_columns, drop_first=True
31+
)
32+
X = self.data_encoded.drop(
33+
columns=[
34+
"Outcome",
35+
"Battle_Name",
36+
]
37+
) # Drop the target and non-feature columns
2938
scaler = StandardScaler()
3039
self.X_scaled = scaler.fit_transform(X)
3140

@@ -40,12 +49,15 @@ def save_results(self, output_path):
4049

4150
def visualize_clusters(self, output_path):
4251
"""Visualize the clusters (if dataset is 2D or reduced to 2D)"""
43-
plt.scatter(self.X_scaled[:, 0], self.X_scaled[:, 1], c=self.clusters, cmap="viridis")
52+
plt.scatter(
53+
self.X_scaled[:, 0], self.X_scaled[:, 1], c=self.clusters, cmap="viridis"
54+
)
4455
plt.title("Battle Clusters")
4556
plt.xlabel("Feature 1")
4657
plt.ylabel("Feature 2")
4758
plt.savefig(output_path)
4859

60+
4961
if __name__ == "__main__":
5062
clustering = BattleClustering(data_path="data/napoleon_battles.csv")
5163
clustering.load_data()

src/battle_predict.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ def __init__(self):
2424
self.y = None
2525

2626
def load_data(self):
27+
"""load data"""
2728
data = {
2829
"Battle Name": ["Austerlitz", "Waterloo", "Borodino"],
2930
"Date": ["1805-12-02", "1815-06-18", "1812-09-07"],
@@ -48,6 +49,7 @@ def load_data(self):
4849
self.data.to_csv("battles.csv", index=False)
4950

5051
def preprocess_data(self):
52+
"""preprocess data"""
5153
self.data["Outcome"] = self.label_encoder.fit_transform(
5254
self.data["Outcome"]
5355
) # Encode outcome
@@ -73,6 +75,7 @@ def preprocess_data(self):
7375
self.X = self.scaler.fit_transform(self.X)
7476

7577
def train_model(self):
78+
"""train model"""
7679
X_train, X_test, y_train, y_test = train_test_split(
7780
self.X, self.y, test_size=0.2, random_state=42
7881
)

tests/test_cluster.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
1+
#!/usr/bin/env python3
2+
"""test_cluster.py - unit tests for the BattleClustering class"""
3+
import os
14
import unittest
5+
26
import pandas as pd
3-
import os
7+
48
from battle_clustering import BattleClustering
59

10+
611
class TestBattleClustering(unittest.TestCase):
12+
"""Unit tests for the BattleClustering class"""
713
@classmethod
814
def setUpClass(cls):
915
# Create a sample dataset for testing
@@ -32,24 +38,29 @@ def setUp(self):
3238
self.clustering = BattleClustering(data_path=self.sample_data_path)
3339

3440
def test_load_data(self):
41+
"""Test the load_data method"""
3542
self.clustering.load_data()
3643
self.assertIsNotNone(self.clustering.data)
3744
self.assertEqual(len(self.clustering.data), 3)
3845

3946
def test_preprocess_data(self):
47+
"""Test the preprocess_data method"""
4048
self.clustering.load_data()
4149
self.clustering.preprocess_data()
4250
self.assertIsNotNone(self.clustering.X_scaled)
4351
self.assertEqual(self.clustering.X_scaled.shape[0], 3)
4452

4553
def test_perform_clustering(self):
54+
"""Test the perform_clustering method"""
4655
self.clustering.load_data()
4756
self.clustering.preprocess_data()
4857
self.clustering.perform_clustering()
4958
self.assertIsNotNone(self.clustering.clusters)
5059
self.assertEqual(len(self.clustering.clusters), 3)
5160

5261
def test_save_results(self):
62+
"""Test the save_results method
63+
"""
5364
self.clustering.load_data()
5465
self.clustering.preprocess_data()
5566
self.clustering.perform_clustering()

0 commit comments

Comments
 (0)