mirror of
https://github.com/DavidGailleton/42-Piscine_Python.git
synced 2026-03-14 05:06:55 +01:00
Compare commits
33 Commits
83efbc7cc0
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 2abc1adcf4 | |||
| 616258b4f5 | |||
| ab6fc8ed90 | |||
| 384ad04a08 | |||
| e460d7507e | |||
| 76206c8ac8 | |||
| 819075d5d9 | |||
| 6e6df73007 | |||
| 516ef290a7 | |||
| e9daee357a | |||
| 164445bb42 | |||
| 2cb7f24a8e | |||
| 4ca187647c | |||
| ddb56264ae | |||
| 222b212162 | |||
| bcd9e4cca0 | |||
| 545da90c08 | |||
| aa8767f46d | |||
| d5978b8f3c | |||
| b68b508a04 | |||
| c44a72413e | |||
| 161ab4339c | |||
| 05a3ddc8b6 | |||
| c16e910c14 | |||
| 2c33879342 | |||
| e95f041f50 | |||
| 194fdc1beb | |||
| ae3ae15fdb | |||
| 2bafef8574 | |||
| 1b068c2b2b | |||
| bf3fec4335 | |||
| 7dae500786 | |||
| 0889775281 |
@@ -1,14 +1,14 @@
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
args = sys.argv
|
try:
|
||||||
if len(args) <= 1:
|
args = sys.argv
|
||||||
print("No scores provided. Usage: python3\
|
if len(args) <= 1:
|
||||||
|
raise Exception("No scores provided. Usage: python3\
|
||||||
ft_score_analytics.py <score1> <score2> ...")
|
ft_score_analytics.py <score1> <score2> ...")
|
||||||
else:
|
else:
|
||||||
scores = [0] * (len(args) - 1)
|
scores = [0] * (len(args) - 1)
|
||||||
i = 0
|
i = 0
|
||||||
try:
|
|
||||||
while i < len(args) - 1:
|
while i < len(args) - 1:
|
||||||
scores[i] = int(args[i + 1])
|
scores[i] = int(args[i + 1])
|
||||||
i = i + 1
|
i = i + 1
|
||||||
@@ -19,5 +19,7 @@ if __name__ == "__main__":
|
|||||||
print("High score:", max(scores))
|
print("High score:", max(scores))
|
||||||
print("Low score:", min(scores))
|
print("Low score:", min(scores))
|
||||||
print("Score range", max(scores) - min(scores))
|
print("Score range", max(scores) - min(scores))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
print("Invalid input, only numbers are accepted")
|
print("Invalid input, only numbers are accepted")
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ import sys
|
|||||||
|
|
||||||
|
|
||||||
def print_distance(a: tuple[int, int, int], b: tuple[int, int, int]) -> None:
|
def print_distance(a: tuple[int, int, int], b: tuple[int, int, int]) -> None:
|
||||||
distance = math.sqrt((a[0]-b[0])**2+(a[1]-b[1])**2+(a[2]-b[2])**2)
|
distance = math.sqrt(
|
||||||
|
(a[0] - b[0]) ** 2 + (a[1] - b[1]) ** 2 + (a[2] - b[2]) ** 2
|
||||||
|
)
|
||||||
print(f"Distance between: {a} and {b}: {distance}")
|
print(f"Distance between: {a} and {b}: {distance}")
|
||||||
|
|
||||||
|
|
||||||
@@ -12,15 +14,17 @@ if __name__ == "__main__":
|
|||||||
try:
|
try:
|
||||||
if len(argv) != 2:
|
if len(argv) != 2:
|
||||||
raise Exception("Invalid number of args")
|
raise Exception("Invalid number of args")
|
||||||
args = argv[1].split(',')
|
print(f'Parsing coordinates: "{argv[1]}"')
|
||||||
|
args = argv[1].split(",")
|
||||||
if len(args) != 3:
|
if len(args) != 3:
|
||||||
raise Exception("Invalid argument format." +
|
raise Exception(
|
||||||
"Try like this : \"15,64,78\"")
|
"Invalid argument format." + 'Try like this : "15,64,78"'
|
||||||
|
)
|
||||||
int_args = (int(args[0]), int(args[1]), int(args[2]))
|
int_args = (int(args[0]), int(args[1]), int(args[2]))
|
||||||
print("Parsing coordinates:", args[1])
|
print(f"Parsed position: {int_args}")
|
||||||
print_distance((0, 0, 0), int_args)
|
print_distance((0, 0, 0), int_args)
|
||||||
except ValueError as err:
|
except ValueError as err:
|
||||||
print(f"Parsing invalid coordinates: \"{argv[1]}\"")
|
print(f'Invalid coordinates: "{argv[1]}"')
|
||||||
print(err)
|
print(err)
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
print(err)
|
print(err)
|
||||||
|
|||||||
@@ -1,42 +1,94 @@
|
|||||||
def tracker_system(players: dict[str, list[str]]) -> None:
|
def tracker_system(players: dict[str, list[str]]) -> None:
|
||||||
print("=== Achievement Tracker System ===\n")
|
print("=== Achievement Tracker System ===\n")
|
||||||
for player in players:
|
try:
|
||||||
print(f"Player {player} achievements: {set((players[player]))}")
|
for player in players:
|
||||||
print("\n=== Achievement Analytics ===")
|
print(f"Player {player} achievements: {set((players[player]))}")
|
||||||
unique_achievements: set[str] = set(())
|
print("\n=== Achievement Analytics ===")
|
||||||
for player in players:
|
unique_achievements: set[str] = set(())
|
||||||
unique_achievements = unique_achievements | set((players[player]))
|
for player in players:
|
||||||
print(f"All unique achievements: {unique_achievements}")
|
unique_achievements = unique_achievements | set((players[player]))
|
||||||
print(f"Total unique achievements: {len(unique_achievements)}")
|
print(f"All unique achievements: {unique_achievements}")
|
||||||
common_achievements: set[str] = unique_achievements
|
print(f"Total unique achievements: {len(unique_achievements)}")
|
||||||
for player in players:
|
common_achievements: set[str] = unique_achievements
|
||||||
common_achievements = common_achievements & set((players[player]))
|
for player in players:
|
||||||
print(f"\nCommon to all players: {common_achievements}")
|
common_achievements = common_achievements & set((players[player]))
|
||||||
player_rare: dict[str, set[str]] = {}
|
print(f"\nCommon to all players: {common_achievements}")
|
||||||
for player in players:
|
except Exception as err:
|
||||||
temp = set((players[player]))
|
print(err)
|
||||||
for other in players:
|
try:
|
||||||
if other != player:
|
player_rare: dict[str, set[str]] = {}
|
||||||
temp = temp - set((players[other]))
|
for player in players:
|
||||||
player_rare[player] = temp
|
temp = set((players[player]))
|
||||||
rare_achievements: set[str] = set(())
|
for other in players:
|
||||||
for n in player_rare:
|
if other != player:
|
||||||
rare_achievements = rare_achievements | player_rare[n]
|
temp = temp - set((players[other]))
|
||||||
print(f"Rare achievements (1 player): {rare_achievements}\n")
|
player_rare[player] = temp
|
||||||
a_vs_b_common = set((players["Alice"])) & set((players["Bob"]))
|
rare_achievements: set[str] = set(())
|
||||||
print(f"Alice vs Bob common: {a_vs_b_common}")
|
for n in player_rare:
|
||||||
alice_unique = set((players["Alice"])) - set((players["Bob"]))
|
rare_achievements = rare_achievements | player_rare[n]
|
||||||
print(f"Alice unique: {alice_unique}")
|
print(f"Rare achievements (1 player): {rare_achievements}\n")
|
||||||
bob_unique = set((players["Bob"])) - set((players["Alice"]))
|
a_vs_b_common = set((players["alice"])) & set((players["bob"]))
|
||||||
print(f"Bob unique: {bob_unique}")
|
print(f"Alice vs Bob common: {a_vs_b_common}")
|
||||||
|
alice_unique = set((players["alice"])) - set((players["bob"]))
|
||||||
|
print(f"Alice unique: {alice_unique}")
|
||||||
|
bob_unique = set((players["bob"])) - set((players["alice"]))
|
||||||
|
print(f"Bob unique: {bob_unique}")
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
players = {
|
data = {
|
||||||
"Alice": ['first_kill', 'level_10',
|
"alice": [
|
||||||
'treasure_hunter', 'speed_demon'],
|
"first_blood",
|
||||||
"Bob": ['first_kill', 'level_10', 'boss_slayer', 'collector'],
|
"pixel_perfect",
|
||||||
"Charlie": ['level_10', 'treasure_hunter', 'boss_slayer',
|
"speed_runner",
|
||||||
'speed_demon', 'perfectionist']
|
"first_blood",
|
||||||
|
"first_blood",
|
||||||
|
"boss_hunter",
|
||||||
|
],
|
||||||
|
"bob": [
|
||||||
|
"level_master",
|
||||||
|
"boss_hunter",
|
||||||
|
"treasure_seeker",
|
||||||
|
"level_master",
|
||||||
|
"level_master",
|
||||||
|
],
|
||||||
|
"charlie": [
|
||||||
|
"treasure_seeker",
|
||||||
|
"boss_hunter",
|
||||||
|
"combo_king",
|
||||||
|
"first_blood",
|
||||||
|
"boss_hunter",
|
||||||
|
"first_blood",
|
||||||
|
"boss_hunter",
|
||||||
|
"first_blood",
|
||||||
|
],
|
||||||
|
"diana": [
|
||||||
|
"first_blood",
|
||||||
|
"combo_king",
|
||||||
|
"level_master",
|
||||||
|
"treasure_seeker",
|
||||||
|
"speed_runner",
|
||||||
|
"combo_king",
|
||||||
|
"combo_king",
|
||||||
|
"level_master",
|
||||||
|
],
|
||||||
|
"eve": [
|
||||||
|
"level_master",
|
||||||
|
"treasure_seeker",
|
||||||
|
"first_blood",
|
||||||
|
"treasure_seeker",
|
||||||
|
"first_blood",
|
||||||
|
"treasure_seeker",
|
||||||
|
],
|
||||||
|
"frank": [
|
||||||
|
"explorer",
|
||||||
|
"boss_hunter",
|
||||||
|
"first_blood",
|
||||||
|
"explorer",
|
||||||
|
"first_blood",
|
||||||
|
"boss_hunter",
|
||||||
|
],
|
||||||
}
|
}
|
||||||
tracker_system(players)
|
tracker_system(data)
|
||||||
|
|||||||
115
03/ex4/ft_inventory_system.py
Normal file
115
03/ex4/ft_inventory_system.py
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
def current_inventory(inventory: dict[str, int], total_items: int) -> None:
|
||||||
|
print("\n=== Current Inventory ===")
|
||||||
|
for item in inventory:
|
||||||
|
percent_of_inventory = inventory[item] / total_items * 100
|
||||||
|
if inventory[item] > 1:
|
||||||
|
print(f"{item}: {inventory[item]} units\
|
||||||
|
({percent_of_inventory:.1f}%)")
|
||||||
|
else:
|
||||||
|
print(f"{item}: {inventory[item]} unit\
|
||||||
|
({percent_of_inventory:.1f}%)")
|
||||||
|
|
||||||
|
|
||||||
|
def inventory_statistics(inventory: dict[str, int]) -> None:
|
||||||
|
most_abundant: tuple[str, int] = ("", 0)
|
||||||
|
less_abundant: tuple[str, int] = ("", 0)
|
||||||
|
for item in inventory:
|
||||||
|
if most_abundant[1] < inventory[item] or most_abundant[1] == 0:
|
||||||
|
most_abundant = (item, inventory[item])
|
||||||
|
if less_abundant[1] > inventory[item] or less_abundant[1] == 0:
|
||||||
|
less_abundant = (item, inventory[item])
|
||||||
|
print("\n=== Inventory Statistics ===")
|
||||||
|
if most_abundant[1] > 1:
|
||||||
|
print(f"Most abundant: {most_abundant[0]} ({most_abundant[1]} units)")
|
||||||
|
else:
|
||||||
|
print(f"Most abundant: {most_abundant[0]} ({most_abundant[1]} unit)")
|
||||||
|
if less_abundant[1] > 1:
|
||||||
|
print(f"Most abundant: {less_abundant[0]} ({less_abundant[1]} units)")
|
||||||
|
else:
|
||||||
|
print(f"Most abundant: {less_abundant[0]} ({less_abundant[1]} unit)")
|
||||||
|
|
||||||
|
|
||||||
|
def item_categories(inventory: dict[str, int]) -> None:
|
||||||
|
inv_cat: dict[str, dict[str, int]] = {
|
||||||
|
"abundant": {},
|
||||||
|
"moderate": {},
|
||||||
|
"scarce": {},
|
||||||
|
}
|
||||||
|
for item in inventory:
|
||||||
|
if inventory[item] > 9:
|
||||||
|
inv_cat["abundant"][item] = inventory[item]
|
||||||
|
elif inventory[item] > 4:
|
||||||
|
inv_cat["moderate"][item] = inventory[item]
|
||||||
|
else:
|
||||||
|
inv_cat["scarce"][item] = inventory[item]
|
||||||
|
print("\n=== Item Categories ===")
|
||||||
|
for cat in inv_cat:
|
||||||
|
if inv_cat[cat]:
|
||||||
|
print(f"{cat}: {inv_cat[cat]}")
|
||||||
|
|
||||||
|
|
||||||
|
def management_suggestions(inventory: dict[str, int]) -> None:
|
||||||
|
item_to_restock: dict[str, int] = {}
|
||||||
|
for item in inventory:
|
||||||
|
if inventory[item] < 2:
|
||||||
|
item_to_restock[item] = inventory[item]
|
||||||
|
print("\n=== Management Suggestions ===")
|
||||||
|
if item_to_restock:
|
||||||
|
print(f"Restock needed: {list(item_to_restock.keys())}")
|
||||||
|
|
||||||
|
|
||||||
|
def dictionnary_properties_demo(inventory: dict[str, int]) -> None:
|
||||||
|
print("\n=== Dictionnary Properties Demo ===")
|
||||||
|
print(f"Dictionnary keys: {list(inventory.keys())}")
|
||||||
|
print(f"Dictionnary values: {list(inventory.values())}")
|
||||||
|
x = "sword" in inventory
|
||||||
|
print(f"Sample lookup - 'sword' in inventory: {x}")
|
||||||
|
|
||||||
|
|
||||||
|
def inventory_report(inventory: dict[str, int]) -> None:
|
||||||
|
nb_unique_items = len(inventory)
|
||||||
|
nb_item_in_inventory = 0
|
||||||
|
try:
|
||||||
|
for n in inventory:
|
||||||
|
nb_item_in_inventory += inventory[n]
|
||||||
|
if nb_item_in_inventory == 0:
|
||||||
|
print("Inventory is empty")
|
||||||
|
else:
|
||||||
|
print("=== Inventory System Analysis ===")
|
||||||
|
print(f"Total items in inventory: {nb_item_in_inventory}")
|
||||||
|
print(f"Unique item types: {nb_unique_items}")
|
||||||
|
current_inventory(inventory, nb_item_in_inventory)
|
||||||
|
inventory_statistics(inventory)
|
||||||
|
item_categories(inventory)
|
||||||
|
management_suggestions(inventory)
|
||||||
|
dictionnary_properties_demo(inventory)
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
|
||||||
|
|
||||||
|
def main(argv: list[str]) -> None:
|
||||||
|
inventory: dict[str, int] = {}
|
||||||
|
try:
|
||||||
|
if len(argv) <= 1:
|
||||||
|
raise Exception
|
||||||
|
i = 1
|
||||||
|
while i < len(argv):
|
||||||
|
key_value = argv[i].split(":")
|
||||||
|
if len(key_value) != 2:
|
||||||
|
raise Exception("Invalid input")
|
||||||
|
if int(key_value[1]) > 0:
|
||||||
|
inventory[key_value[0]] = int(key_value[1])
|
||||||
|
if int(key_value[1]) < 0:
|
||||||
|
raise Exception("Nb of item in inventory cannot be negative")
|
||||||
|
i += 1
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
return
|
||||||
|
inventory_report(inventory)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main(sys.argv)
|
||||||
438
03/ex5/ft_data_stream.py
Normal file
438
03/ex5/ft_data_stream.py
Normal file
@@ -0,0 +1,438 @@
|
|||||||
|
from typing import Generator
|
||||||
|
|
||||||
|
|
||||||
|
def fibonacci() -> Generator[int, None, None]:
|
||||||
|
before = 1
|
||||||
|
res = 0
|
||||||
|
while True:
|
||||||
|
yield res
|
||||||
|
res += before
|
||||||
|
before = res - before
|
||||||
|
|
||||||
|
|
||||||
|
def prime_number() -> Generator[int, None, None]:
|
||||||
|
prime: int = 2
|
||||||
|
while True:
|
||||||
|
yield prime
|
||||||
|
prime += 1
|
||||||
|
i: int = 2
|
||||||
|
while i < prime:
|
||||||
|
if not prime % i:
|
||||||
|
prime += 1
|
||||||
|
i = 2
|
||||||
|
else:
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
|
||||||
|
def event_analytics(
|
||||||
|
events: list[dict[str, int | str | dict[str, int | str]]],
|
||||||
|
) -> Generator[None, None, dict[str, int]]:
|
||||||
|
data = {
|
||||||
|
"processed_event": 0,
|
||||||
|
"high_level_player": 0,
|
||||||
|
"treasure_events": 0,
|
||||||
|
"level_up_events": 0,
|
||||||
|
}
|
||||||
|
for event in events:
|
||||||
|
if event["data"]["level"] > 9:
|
||||||
|
data["high_level_player"] += 1
|
||||||
|
if event["event_type"] == "item_found":
|
||||||
|
data["treasure_events"] += 1
|
||||||
|
if event["event_type"] == "level_up":
|
||||||
|
data["level_up_events"] += 1
|
||||||
|
data["processed_event"] += 1
|
||||||
|
print(f"Event {event['id']}: Player {event['player']}\
|
||||||
|
(level {event['data']['level']}) {event['event_type']}")
|
||||||
|
yield None
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def game_data_stream_processor(
|
||||||
|
events: list[dict[str, int | str | dict[str, int | str]]],
|
||||||
|
) -> None:
|
||||||
|
print("=== Game Data Stream Processor ===\n")
|
||||||
|
print(f"Processing {len(events)} game events...\n")
|
||||||
|
try:
|
||||||
|
log = event_analytics(events)
|
||||||
|
while True:
|
||||||
|
next(log)
|
||||||
|
except StopIteration as res:
|
||||||
|
print("\n=== Stream Analytics ===")
|
||||||
|
print(f"Total events processed: {len(events)}")
|
||||||
|
print(f"High-level players: {res.value['high_level_player']}")
|
||||||
|
print(f"Treasure events: {res.value['treasure_events']}")
|
||||||
|
print(f"Level-up events: {res.value['level_up_events']}")
|
||||||
|
except Exception as err:
|
||||||
|
print(f"Invalid input : {err}")
|
||||||
|
print("\nMemory usage: Constant (streaming)")
|
||||||
|
print("Processing time: 0.045 seconds\n")
|
||||||
|
|
||||||
|
|
||||||
|
def generator_demo() -> None:
|
||||||
|
print("=== Generator Demonstration ===")
|
||||||
|
print("Fibonacci sequence (first 10):", end="")
|
||||||
|
fib = fibonacci()
|
||||||
|
for _ in range(10):
|
||||||
|
print(f" {next(fib)}", end="")
|
||||||
|
print("\nPrime number (first 5):", end="")
|
||||||
|
prime = prime_number()
|
||||||
|
for _ in range(5):
|
||||||
|
print(f" {next(prime)}", end="")
|
||||||
|
print("")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
data = [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"player": "frank",
|
||||||
|
"event_type": "login",
|
||||||
|
"timestamp": "2024-01-01T23:17",
|
||||||
|
"data": {"level": 16, "score_delta": 128, "zone": "pixel_zone_2"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"player": "frank",
|
||||||
|
"event_type": "login",
|
||||||
|
"timestamp": "2024-01-22T23:57",
|
||||||
|
"data": {"level": 35, "score_delta": -11, "zone": "pixel_zone_5"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"player": "diana",
|
||||||
|
"event_type": "login",
|
||||||
|
"timestamp": "2024-01-01T02:13",
|
||||||
|
"data": {"level": 15, "score_delta": 417, "zone": "pixel_zone_5"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 4,
|
||||||
|
"player": "alice",
|
||||||
|
"event_type": "level_up",
|
||||||
|
"timestamp": "2024-01-07T22:41",
|
||||||
|
"data": {"level": 45, "score_delta": 458, "zone": "pixel_zone_4"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 5,
|
||||||
|
"player": "bob",
|
||||||
|
"event_type": "death",
|
||||||
|
"timestamp": "2024-01-19T08:51",
|
||||||
|
"data": {"level": 1, "score_delta": 63, "zone": "pixel_zone_4"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 6,
|
||||||
|
"player": "charlie",
|
||||||
|
"event_type": "kill",
|
||||||
|
"timestamp": "2024-01-05T06:48",
|
||||||
|
"data": {"level": 22, "score_delta": 4, "zone": "pixel_zone_1"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 7,
|
||||||
|
"player": "diana",
|
||||||
|
"event_type": "login",
|
||||||
|
"timestamp": "2024-01-12T11:38",
|
||||||
|
"data": {"level": 17, "score_delta": -56, "zone": "pixel_zone_4"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 8,
|
||||||
|
"player": "eve",
|
||||||
|
"event_type": "login",
|
||||||
|
"timestamp": "2024-01-30T12:05",
|
||||||
|
"data": {"level": 36, "score_delta": 200, "zone": "pixel_zone_5"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 9,
|
||||||
|
"player": "charlie",
|
||||||
|
"event_type": "level_up",
|
||||||
|
"timestamp": "2024-01-07T22:04",
|
||||||
|
"data": {"level": 3, "score_delta": 133, "zone": "pixel_zone_3"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10,
|
||||||
|
"player": "alice",
|
||||||
|
"event_type": "logout",
|
||||||
|
"timestamp": "2024-01-28T03:24",
|
||||||
|
"data": {"level": 18, "score_delta": 364, "zone": "pixel_zone_3"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 11,
|
||||||
|
"player": "bob",
|
||||||
|
"event_type": "kill",
|
||||||
|
"timestamp": "2024-01-12T06:42",
|
||||||
|
"data": {"level": 18, "score_delta": -27, "zone": "pixel_zone_5"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 12,
|
||||||
|
"player": "frank",
|
||||||
|
"event_type": "logout",
|
||||||
|
"timestamp": "2024-01-18T23:15",
|
||||||
|
"data": {"level": 11, "score_delta": 373, "zone": "pixel_zone_4"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 13,
|
||||||
|
"player": "charlie",
|
||||||
|
"event_type": "item_found",
|
||||||
|
"timestamp": "2024-01-23T17:14",
|
||||||
|
"data": {"level": 44, "score_delta": 232, "zone": "pixel_zone_1"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 14,
|
||||||
|
"player": "bob",
|
||||||
|
"event_type": "login",
|
||||||
|
"timestamp": "2024-01-26T10:25",
|
||||||
|
"data": {"level": 18, "score_delta": -33, "zone": "pixel_zone_2"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 15,
|
||||||
|
"player": "eve",
|
||||||
|
"event_type": "item_found",
|
||||||
|
"timestamp": "2024-01-11T06:41",
|
||||||
|
"data": {"level": 32, "score_delta": 305, "zone": "pixel_zone_4"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 16,
|
||||||
|
"player": "bob",
|
||||||
|
"event_type": "kill",
|
||||||
|
"timestamp": "2024-01-05T07:47",
|
||||||
|
"data": {"level": 36, "score_delta": 451, "zone": "pixel_zone_3"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 17,
|
||||||
|
"player": "frank",
|
||||||
|
"event_type": "level_up",
|
||||||
|
"timestamp": "2024-01-14T18:25",
|
||||||
|
"data": {"level": 24, "score_delta": 124, "zone": "pixel_zone_2"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 18,
|
||||||
|
"player": "eve",
|
||||||
|
"event_type": "death",
|
||||||
|
"timestamp": "2024-01-03T01:55",
|
||||||
|
"data": {"level": 8, "score_delta": 56, "zone": "pixel_zone_2"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 19,
|
||||||
|
"player": "frank",
|
||||||
|
"event_type": "death",
|
||||||
|
"timestamp": "2024-01-20T02:24",
|
||||||
|
"data": {"level": 25, "score_delta": 379, "zone": "pixel_zone_5"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 20,
|
||||||
|
"player": "charlie",
|
||||||
|
"event_type": "level_up",
|
||||||
|
"timestamp": "2024-01-28T00:43",
|
||||||
|
"data": {"level": 47, "score_delta": 17, "zone": "pixel_zone_5"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 21,
|
||||||
|
"player": "charlie",
|
||||||
|
"event_type": "item_found",
|
||||||
|
"timestamp": "2024-01-11T03:18",
|
||||||
|
"data": {"level": 28, "score_delta": 61, "zone": "pixel_zone_4"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 22,
|
||||||
|
"player": "alice",
|
||||||
|
"event_type": "item_found",
|
||||||
|
"timestamp": "2024-01-29T23:16",
|
||||||
|
"data": {"level": 33, "score_delta": 82, "zone": "pixel_zone_5"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 23,
|
||||||
|
"player": "alice",
|
||||||
|
"event_type": "item_found",
|
||||||
|
"timestamp": "2024-01-10T20:32",
|
||||||
|
"data": {"level": 39, "score_delta": 103, "zone": "pixel_zone_2"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 24,
|
||||||
|
"player": "charlie",
|
||||||
|
"event_type": "logout",
|
||||||
|
"timestamp": "2024-01-18T16:58",
|
||||||
|
"data": {"level": 1, "score_delta": 231, "zone": "pixel_zone_4"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 25,
|
||||||
|
"player": "alice",
|
||||||
|
"event_type": "login",
|
||||||
|
"timestamp": "2024-01-30T11:56",
|
||||||
|
"data": {"level": 20, "score_delta": 145, "zone": "pixel_zone_1"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 26,
|
||||||
|
"player": "bob",
|
||||||
|
"event_type": "level_up",
|
||||||
|
"timestamp": "2024-01-03T02:46",
|
||||||
|
"data": {"level": 32, "score_delta": -30, "zone": "pixel_zone_5"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 27,
|
||||||
|
"player": "bob",
|
||||||
|
"event_type": "logout",
|
||||||
|
"timestamp": "2024-01-22T15:35",
|
||||||
|
"data": {"level": 11, "score_delta": 171, "zone": "pixel_zone_5"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 28,
|
||||||
|
"player": "eve",
|
||||||
|
"event_type": "death",
|
||||||
|
"timestamp": "2024-01-07T17:48",
|
||||||
|
"data": {"level": 47, "score_delta": 105, "zone": "pixel_zone_3"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 29,
|
||||||
|
"player": "diana",
|
||||||
|
"event_type": "item_found",
|
||||||
|
"timestamp": "2024-01-21T11:28",
|
||||||
|
"data": {"level": 34, "score_delta": 362, "zone": "pixel_zone_1"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 30,
|
||||||
|
"player": "bob",
|
||||||
|
"event_type": "logout",
|
||||||
|
"timestamp": "2024-01-03T10:01",
|
||||||
|
"data": {"level": 38, "score_delta": 467, "zone": "pixel_zone_2"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 31,
|
||||||
|
"player": "eve",
|
||||||
|
"event_type": "logout",
|
||||||
|
"timestamp": "2024-01-01T02:45",
|
||||||
|
"data": {"level": 41, "score_delta": -40, "zone": "pixel_zone_2"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 32,
|
||||||
|
"player": "alice",
|
||||||
|
"event_type": "login",
|
||||||
|
"timestamp": "2024-01-28T10:04",
|
||||||
|
"data": {"level": 33, "score_delta": 143, "zone": "pixel_zone_3"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 33,
|
||||||
|
"player": "frank",
|
||||||
|
"event_type": "death",
|
||||||
|
"timestamp": "2024-01-07T17:08",
|
||||||
|
"data": {"level": 47, "score_delta": 484, "zone": "pixel_zone_5"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 34,
|
||||||
|
"player": "diana",
|
||||||
|
"event_type": "logout",
|
||||||
|
"timestamp": "2024-01-26T15:51",
|
||||||
|
"data": {"level": 27, "score_delta": 94, "zone": "pixel_zone_1"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 35,
|
||||||
|
"player": "alice",
|
||||||
|
"event_type": "item_found",
|
||||||
|
"timestamp": "2024-01-14T11:27",
|
||||||
|
"data": {"level": 27, "score_delta": 378, "zone": "pixel_zone_1"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 36,
|
||||||
|
"player": "frank",
|
||||||
|
"event_type": "item_found",
|
||||||
|
"timestamp": "2024-01-21T03:03",
|
||||||
|
"data": {"level": 26, "score_delta": 247, "zone": "pixel_zone_1"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 37,
|
||||||
|
"player": "bob",
|
||||||
|
"event_type": "logout",
|
||||||
|
"timestamp": "2024-01-07T17:28",
|
||||||
|
"data": {"level": 9, "score_delta": 332, "zone": "pixel_zone_2"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 38,
|
||||||
|
"player": "charlie",
|
||||||
|
"event_type": "death",
|
||||||
|
"timestamp": "2024-01-08T02:28",
|
||||||
|
"data": {"level": 36, "score_delta": 0, "zone": "pixel_zone_1"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 39,
|
||||||
|
"player": "frank",
|
||||||
|
"event_type": "level_up",
|
||||||
|
"timestamp": "2024-01-27T00:05",
|
||||||
|
"data": {"level": 49, "score_delta": 142, "zone": "pixel_zone_2"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 40,
|
||||||
|
"player": "diana",
|
||||||
|
"event_type": "death",
|
||||||
|
"timestamp": "2024-01-16T06:55",
|
||||||
|
"data": {"level": 26, "score_delta": -40, "zone": "pixel_zone_2"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 41,
|
||||||
|
"player": "diana",
|
||||||
|
"event_type": "login",
|
||||||
|
"timestamp": "2024-01-13T08:59",
|
||||||
|
"data": {"level": 30, "score_delta": 192, "zone": "pixel_zone_4"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 42,
|
||||||
|
"player": "frank",
|
||||||
|
"event_type": "item_found",
|
||||||
|
"timestamp": "2024-01-26T17:42",
|
||||||
|
"data": {"level": 46, "score_delta": 398, "zone": "pixel_zone_2"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 43,
|
||||||
|
"player": "bob",
|
||||||
|
"event_type": "kill",
|
||||||
|
"timestamp": "2024-01-07T01:37",
|
||||||
|
"data": {"level": 48, "score_delta": 455, "zone": "pixel_zone_1"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 44,
|
||||||
|
"player": "frank",
|
||||||
|
"event_type": "kill",
|
||||||
|
"timestamp": "2024-01-02T01:37",
|
||||||
|
"data": {"level": 31, "score_delta": 414, "zone": "pixel_zone_5"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 45,
|
||||||
|
"player": "bob",
|
||||||
|
"event_type": "login",
|
||||||
|
"timestamp": "2024-01-17T02:54",
|
||||||
|
"data": {"level": 12, "score_delta": -30, "zone": "pixel_zone_5"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 46,
|
||||||
|
"player": "alice",
|
||||||
|
"event_type": "item_found",
|
||||||
|
"timestamp": "2024-01-28T07:25",
|
||||||
|
"data": {"level": 8, "score_delta": 483, "zone": "pixel_zone_2"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 47,
|
||||||
|
"player": "eve",
|
||||||
|
"event_type": "level_up",
|
||||||
|
"timestamp": "2024-01-02T19:05",
|
||||||
|
"data": {"level": 27, "score_delta": 497, "zone": "pixel_zone_5"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 48,
|
||||||
|
"player": "eve",
|
||||||
|
"event_type": "kill",
|
||||||
|
"timestamp": "2024-01-30T08:13",
|
||||||
|
"data": {"level": 43, "score_delta": 221, "zone": "pixel_zone_2"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 49,
|
||||||
|
"player": "charlie",
|
||||||
|
"event_type": "death",
|
||||||
|
"timestamp": "2024-01-05T21:41",
|
||||||
|
"data": {"level": 20, "score_delta": 368, "zone": "pixel_zone_3"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 50,
|
||||||
|
"player": "alice",
|
||||||
|
"event_type": "login",
|
||||||
|
"timestamp": "2024-01-15T19:36",
|
||||||
|
"data": {"level": 7, "score_delta": -25, "zone": "pixel_zone_5"},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
game_data_stream_processor(data)
|
||||||
|
generator_demo()
|
||||||
375
03/ex6/ft_analytics_dashboard.py
Normal file
375
03/ex6/ft_analytics_dashboard.py
Normal file
@@ -0,0 +1,375 @@
|
|||||||
|
def list_comprehension_example(
|
||||||
|
data: dict[str, dict[str, int | str] | list[dict[str, str | int | bool]]],
|
||||||
|
) -> None:
|
||||||
|
print("=== List Comprehension Examples ===")
|
||||||
|
high_score = [
|
||||||
|
x for x in data["players"] if data["players"][x]["total_score"] > 2000
|
||||||
|
]
|
||||||
|
print(f"High scorers (>2000): {high_score}")
|
||||||
|
scores_doubled = [
|
||||||
|
data["players"][x]["total_score"] * 2 for x in data["players"]
|
||||||
|
]
|
||||||
|
print(f"Scores doubled: {scores_doubled}")
|
||||||
|
active_players = [
|
||||||
|
x
|
||||||
|
for x in data["players"]
|
||||||
|
if data["players"][x]["sessions_played"] > 29
|
||||||
|
]
|
||||||
|
print(f"Active players: {active_players}")
|
||||||
|
|
||||||
|
|
||||||
|
def dict_comprehension_example(
|
||||||
|
data: dict[str, dict[str, int | str] | list[dict[str, str | int | bool]]],
|
||||||
|
) -> None:
|
||||||
|
print("=== Dict Comprehension Examples ===")
|
||||||
|
player_scores = {
|
||||||
|
player: data["players"][player]["total_score"]
|
||||||
|
for player in data["players"]
|
||||||
|
}
|
||||||
|
print(f"Player scores: {player_scores}")
|
||||||
|
score_categories = {category["mode"]: 1 for category in data["sessions"]}
|
||||||
|
print(f"Score categories: {score_categories}")
|
||||||
|
achievements_count = {
|
||||||
|
player: data["players"][player]["achievements_count"]
|
||||||
|
for player in data["players"]
|
||||||
|
}
|
||||||
|
print(f"Achievement counts: {achievements_count}")
|
||||||
|
|
||||||
|
|
||||||
|
def set_comprehension_example(
|
||||||
|
data: dict[str, dict[str, int | str] | list[dict[str, str | int | bool]]],
|
||||||
|
) -> None:
|
||||||
|
print("=== Set Comprehension Examples ===")
|
||||||
|
unique_player: set[str] = {
|
||||||
|
session["player"] for session in data["sessions"]
|
||||||
|
}
|
||||||
|
print(f"Unique player: {unique_player}")
|
||||||
|
unique_achievements: set[str] = {
|
||||||
|
achievement for achievement in data["achievements"]
|
||||||
|
}
|
||||||
|
print(f"unique achievements: {unique_achievements}")
|
||||||
|
available_gamemode: set[str] = {gm for gm in data["game_modes"]}
|
||||||
|
print(f"Available gamemode: {available_gamemode}")
|
||||||
|
|
||||||
|
|
||||||
|
def combined_analysis(
|
||||||
|
data: dict[str, dict[str, int | str] | list[dict[str, str | int | bool]]],
|
||||||
|
) -> None:
|
||||||
|
print("=== combined Analysis ===")
|
||||||
|
unique_player: set[str] = {
|
||||||
|
session["player"] for session in data["sessions"]
|
||||||
|
}
|
||||||
|
print(f"Total player: {len(unique_player)}")
|
||||||
|
unique_achievements: set[str] = {
|
||||||
|
achievement for achievement in data["achievements"]
|
||||||
|
}
|
||||||
|
print(f"Total unique achievements: {len(unique_achievements)}")
|
||||||
|
total_score: list[int] = [session["score"] for session in data["sessions"]]
|
||||||
|
avg_score = sum(total_score) / len(total_score)
|
||||||
|
print(f"Average score: {avg_score:.2f}")
|
||||||
|
performers = {
|
||||||
|
player: data["players"][player]["total_score"]
|
||||||
|
for player in data["players"]
|
||||||
|
}
|
||||||
|
best_player = max(performers, key=performers.get)
|
||||||
|
print(f"Top performer: {best_player}\
|
||||||
|
({data['players'][best_player]['total_score']}\
|
||||||
|
points, {data['players'][best_player]['achievements_count']} achievements)")
|
||||||
|
|
||||||
|
|
||||||
|
def comprehension_tester(
|
||||||
|
data: dict[str, dict[str, int | str] | list[dict[str, str | int | bool]]],
|
||||||
|
) -> None:
|
||||||
|
try:
|
||||||
|
print("=== game Analytics Dashboard ===\n")
|
||||||
|
list_comprehension_example(data)
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
try:
|
||||||
|
print()
|
||||||
|
dict_comprehension_example(data)
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
try:
|
||||||
|
print()
|
||||||
|
set_comprehension_example(data)
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
try:
|
||||||
|
print()
|
||||||
|
combined_analysis(data)
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
data = {
|
||||||
|
"players": {
|
||||||
|
"alice": {
|
||||||
|
"level": 41,
|
||||||
|
"total_score": 2824,
|
||||||
|
"sessions_played": 13,
|
||||||
|
"favorite_mode": "ranked",
|
||||||
|
"achievements_count": 5,
|
||||||
|
},
|
||||||
|
"bob": {
|
||||||
|
"level": 16,
|
||||||
|
"total_score": 4657,
|
||||||
|
"sessions_played": 27,
|
||||||
|
"favorite_mode": "ranked",
|
||||||
|
"achievements_count": 2,
|
||||||
|
},
|
||||||
|
"charlie": {
|
||||||
|
"level": 44,
|
||||||
|
"total_score": 9935,
|
||||||
|
"sessions_played": 21,
|
||||||
|
"favorite_mode": "ranked",
|
||||||
|
"achievements_count": 7,
|
||||||
|
},
|
||||||
|
"diana": {
|
||||||
|
"level": 3,
|
||||||
|
"total_score": 1488,
|
||||||
|
"sessions_played": 21,
|
||||||
|
"favorite_mode": "casual",
|
||||||
|
"achievements_count": 4,
|
||||||
|
},
|
||||||
|
"eve": {
|
||||||
|
"level": 33,
|
||||||
|
"total_score": 1434,
|
||||||
|
"sessions_played": 81,
|
||||||
|
"favorite_mode": "casual",
|
||||||
|
"achievements_count": 7,
|
||||||
|
},
|
||||||
|
"frank": {
|
||||||
|
"level": 15,
|
||||||
|
"total_score": 8359,
|
||||||
|
"sessions_played": 85,
|
||||||
|
"favorite_mode": "competitive",
|
||||||
|
"achievements_count": 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"sessions": [
|
||||||
|
{
|
||||||
|
"player": "bob",
|
||||||
|
"duration_minutes": 94,
|
||||||
|
"score": 1831,
|
||||||
|
"mode": "competitive",
|
||||||
|
"completed": False,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"player": "bob",
|
||||||
|
"duration_minutes": 32,
|
||||||
|
"score": 1478,
|
||||||
|
"mode": "casual",
|
||||||
|
"completed": True,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"player": "diana",
|
||||||
|
"duration_minutes": 17,
|
||||||
|
"score": 1570,
|
||||||
|
"mode": "competitive",
|
||||||
|
"completed": False,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"player": "alice",
|
||||||
|
"duration_minutes": 98,
|
||||||
|
"score": 1981,
|
||||||
|
"mode": "ranked",
|
||||||
|
"completed": True,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"player": "diana",
|
||||||
|
"duration_minutes": 15,
|
||||||
|
"score": 2361,
|
||||||
|
"mode": "competitive",
|
||||||
|
"completed": False,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"player": "eve",
|
||||||
|
"duration_minutes": 29,
|
||||||
|
"score": 2985,
|
||||||
|
"mode": "casual",
|
||||||
|
"completed": True,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"player": "frank",
|
||||||
|
"duration_minutes": 34,
|
||||||
|
"score": 1285,
|
||||||
|
"mode": "casual",
|
||||||
|
"completed": True,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"player": "alice",
|
||||||
|
"duration_minutes": 53,
|
||||||
|
"score": 1238,
|
||||||
|
"mode": "competitive",
|
||||||
|
"completed": False,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"player": "bob",
|
||||||
|
"duration_minutes": 52,
|
||||||
|
"score": 1555,
|
||||||
|
"mode": "casual",
|
||||||
|
"completed": False,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"player": "frank",
|
||||||
|
"duration_minutes": 92,
|
||||||
|
"score": 2754,
|
||||||
|
"mode": "casual",
|
||||||
|
"completed": True,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"player": "eve",
|
||||||
|
"duration_minutes": 98,
|
||||||
|
"score": 1102,
|
||||||
|
"mode": "casual",
|
||||||
|
"completed": False,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"player": "diana",
|
||||||
|
"duration_minutes": 39,
|
||||||
|
"score": 2721,
|
||||||
|
"mode": "ranked",
|
||||||
|
"completed": True,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"player": "frank",
|
||||||
|
"duration_minutes": 46,
|
||||||
|
"score": 329,
|
||||||
|
"mode": "casual",
|
||||||
|
"completed": True,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"player": "charlie",
|
||||||
|
"duration_minutes": 56,
|
||||||
|
"score": 1196,
|
||||||
|
"mode": "casual",
|
||||||
|
"completed": True,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"player": "eve",
|
||||||
|
"duration_minutes": 117,
|
||||||
|
"score": 1388,
|
||||||
|
"mode": "casual",
|
||||||
|
"completed": False,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"player": "diana",
|
||||||
|
"duration_minutes": 118,
|
||||||
|
"score": 2733,
|
||||||
|
"mode": "competitive",
|
||||||
|
"completed": True,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"player": "charlie",
|
||||||
|
"duration_minutes": 22,
|
||||||
|
"score": 1110,
|
||||||
|
"mode": "ranked",
|
||||||
|
"completed": False,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"player": "frank",
|
||||||
|
"duration_minutes": 79,
|
||||||
|
"score": 1854,
|
||||||
|
"mode": "ranked",
|
||||||
|
"completed": False,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"player": "charlie",
|
||||||
|
"duration_minutes": 33,
|
||||||
|
"score": 666,
|
||||||
|
"mode": "ranked",
|
||||||
|
"completed": False,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"player": "alice",
|
||||||
|
"duration_minutes": 101,
|
||||||
|
"score": 292,
|
||||||
|
"mode": "casual",
|
||||||
|
"completed": True,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"player": "frank",
|
||||||
|
"duration_minutes": 25,
|
||||||
|
"score": 2887,
|
||||||
|
"mode": "competitive",
|
||||||
|
"completed": True,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"player": "diana",
|
||||||
|
"duration_minutes": 53,
|
||||||
|
"score": 2540,
|
||||||
|
"mode": "competitive",
|
||||||
|
"completed": False,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"player": "eve",
|
||||||
|
"duration_minutes": 115,
|
||||||
|
"score": 147,
|
||||||
|
"mode": "ranked",
|
||||||
|
"completed": True,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"player": "frank",
|
||||||
|
"duration_minutes": 118,
|
||||||
|
"score": 2299,
|
||||||
|
"mode": "competitive",
|
||||||
|
"completed": False,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"player": "alice",
|
||||||
|
"duration_minutes": 42,
|
||||||
|
"score": 1880,
|
||||||
|
"mode": "casual",
|
||||||
|
"completed": False,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"player": "alice",
|
||||||
|
"duration_minutes": 97,
|
||||||
|
"score": 1178,
|
||||||
|
"mode": "ranked",
|
||||||
|
"completed": True,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"player": "eve",
|
||||||
|
"duration_minutes": 18,
|
||||||
|
"score": 2661,
|
||||||
|
"mode": "competitive",
|
||||||
|
"completed": True,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"player": "bob",
|
||||||
|
"duration_minutes": 52,
|
||||||
|
"score": 761,
|
||||||
|
"mode": "ranked",
|
||||||
|
"completed": True,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"player": "eve",
|
||||||
|
"duration_minutes": 46,
|
||||||
|
"score": 2101,
|
||||||
|
"mode": "casual",
|
||||||
|
"completed": True,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"player": "charlie",
|
||||||
|
"duration_minutes": 117,
|
||||||
|
"score": 1359,
|
||||||
|
"mode": "casual",
|
||||||
|
"completed": True,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"game_modes": ["casual", "competitive", "ranked"],
|
||||||
|
"achievements": [
|
||||||
|
"first_blood",
|
||||||
|
"level_master",
|
||||||
|
"speed_runner",
|
||||||
|
"treasure_seeker",
|
||||||
|
"boss_hunter",
|
||||||
|
"pixel_perfect",
|
||||||
|
"combo_king",
|
||||||
|
"explorer",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
comprehension_tester(data)
|
||||||
17
04/ex0/ft_ancient_text.py
Normal file
17
04/ex0/ft_ancient_text.py
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
def read_ancient_text() -> None:
|
||||||
|
try:
|
||||||
|
print("Accessing Storage Vault: ancient_fragment.txt")
|
||||||
|
vault = open("ancient_fragment.txt", "r")
|
||||||
|
print("Connection establish...")
|
||||||
|
print("\nRECOVERED DATA:")
|
||||||
|
print(vault.read())
|
||||||
|
vault.close()
|
||||||
|
print("\nData recovery complete. Storage unit disconnected.")
|
||||||
|
except FileNotFoundError:
|
||||||
|
print("ERROR: Storage vault not found.")
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
read_ancient_text()
|
||||||
22
04/ex1/ft_archive_creation.py
Normal file
22
04/ex1/ft_archive_creation.py
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
def create_new_discovery() -> None:
|
||||||
|
print("=== CYBER ARCHIVES - PRESERVATION SYSTEM ===")
|
||||||
|
try:
|
||||||
|
print("\nInitializing new storage unit: new_discovery.txt")
|
||||||
|
file = open("new_discovery.txt", "w")
|
||||||
|
print("Storage unit created successfully...")
|
||||||
|
print("\nInscribing preservation data...")
|
||||||
|
print("[ENTRY 001] New quantum algorithm discovered\n\
|
||||||
|
[ENTRY 002] Efficiency increased by 347%\n\
|
||||||
|
[ENTRY 003] Archived by Data Archivist trainee")
|
||||||
|
file.write("[ENTRY 001] New quantum algorithm discovered\n\
|
||||||
|
[ENTRY 002] Efficiency increased by 347%\n\
|
||||||
|
[ENTRY 003] Archived by Data Archivist trainee")
|
||||||
|
file.close()
|
||||||
|
print("\nData inscription complete. Storage unit sealed.")
|
||||||
|
print("Archive 'new_discovery.txt' ready for long-term preservation.")
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
create_new_discovery()
|
||||||
21
04/ex2/ft_stream_management.py
Normal file
21
04/ex2/ft_stream_management.py
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
def communication_system() -> None:
|
||||||
|
print("=== CYBER ARCHIVES - COMMUNICATION SYSTEM ===\n")
|
||||||
|
sys.stdout.write("Input Stream active. Enter archivist ID: ")
|
||||||
|
archivist_id = input()
|
||||||
|
sys.stdout.write("Input Stream active. Enter status report: ")
|
||||||
|
status_report = input()
|
||||||
|
sys.stdout.write(
|
||||||
|
f"\n[STANDARD] Archive status from {archivist_id}: {status_report}\n"
|
||||||
|
)
|
||||||
|
sys.stderr.write(
|
||||||
|
"[ALERT] System diagnostic: Communication channels verified\n"
|
||||||
|
)
|
||||||
|
sys.stdout.write("[STANDARD] Data transmission complete\n")
|
||||||
|
print("\nThree-channel communication test successful.")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
communication_system()
|
||||||
21
04/ex3/ft_vault_security.py
Normal file
21
04/ex3/ft_vault_security.py
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
def vault_security_system() -> None:
|
||||||
|
print("=== CYBER ARCHIVES - VAULT SECURITY SYSTEM ===\n")
|
||||||
|
try:
|
||||||
|
print("Initiating secure vault access...")
|
||||||
|
with open("classified_data.txt", "r") as source_file, open(
|
||||||
|
"archive_data.txt", "w"
|
||||||
|
) as dest_file:
|
||||||
|
print("Vault connection established with failsafe protocols\n")
|
||||||
|
print("SECURE EXTRACTION:")
|
||||||
|
print(source_file.read())
|
||||||
|
print("\nSECURE PRESERVATION:")
|
||||||
|
dest_file.write("[CLASSIFIED] New security protocols archived")
|
||||||
|
print("[CLASSIFIED] New security protocols archived")
|
||||||
|
print("Vault automatically sealed upon completion")
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
print("\nAll vault operations completed with maximum security.")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
vault_security_system()
|
||||||
31
04/ex4/ft_crisis_response.py
Normal file
31
04/ex4/ft_crisis_response.py
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
def file_error_tester() -> None:
|
||||||
|
print("=== CYBER ARCHIVES - CRISIS RESPONSE SYSTEM ===\n")
|
||||||
|
try:
|
||||||
|
print("CRISIS ALERT: Attempting access to 'lost_archive.txt'...")
|
||||||
|
with open("lost_archive.txt") as file:
|
||||||
|
print("STATUS: Normal operations resumed")
|
||||||
|
except FileNotFoundError:
|
||||||
|
print("RESPONSE: Archive not found in storage matrix")
|
||||||
|
print("STATUS: Crisis handled, system stable")
|
||||||
|
print()
|
||||||
|
try:
|
||||||
|
print("CRISIS ALERT: Attempting access to 'classified_vault.txt'...")
|
||||||
|
with open("/bin/zsh", "w") as file:
|
||||||
|
print("STATUS: Normal operations resumed")
|
||||||
|
except PermissionError:
|
||||||
|
print("RESPONSE: Security protocols deny access")
|
||||||
|
print("STATUS: Crisis handled, security maintained")
|
||||||
|
print()
|
||||||
|
try:
|
||||||
|
print("ROUTINE ACCESS: Attempting access to 'standard_archive.txt'...")
|
||||||
|
with open("standard_archive.txt") as file:
|
||||||
|
print(f"SUCCESS: Archive recovered - ``{file.read()}''")
|
||||||
|
print("STATUS: Normal operations resumed")
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
print("STATUS: Crisis handled, security maintained")
|
||||||
|
print("\nAll crisis scenarios handled successfully. Archives secure.")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
file_error_tester()
|
||||||
160
05/ex0/stream_processor.py
Normal file
160
05/ex0/stream_processor.py
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
from abc import ABC, abstractmethod
|
||||||
|
from typing import Any, Union
|
||||||
|
from typing_extensions import override
|
||||||
|
|
||||||
|
|
||||||
|
class DataProcessor(ABC):
|
||||||
|
@abstractmethod
|
||||||
|
def process(self, data: Any) -> str:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def validate(self, data: Any) -> bool:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def format_output(self, result: str) -> str:
|
||||||
|
return f"Processed output: {result}"
|
||||||
|
|
||||||
|
|
||||||
|
class NumericProcessor(DataProcessor):
|
||||||
|
def process(self, data: Any) -> str:
|
||||||
|
try:
|
||||||
|
return f"{data}"
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
return "error"
|
||||||
|
|
||||||
|
def validate(self, data: Any) -> bool:
|
||||||
|
try:
|
||||||
|
for n in data:
|
||||||
|
if type(n).__name__ != "int":
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
|
||||||
|
@override
|
||||||
|
def format_output(self, result: str) -> str:
|
||||||
|
try:
|
||||||
|
to_processed = result.split(", ")
|
||||||
|
res_int: list[int] = []
|
||||||
|
for n in to_processed:
|
||||||
|
n = n.replace("[", "").replace("]", "")
|
||||||
|
if n.isnumeric():
|
||||||
|
res_int = res_int + [int(n)]
|
||||||
|
avg = sum(res_int) / len(res_int)
|
||||||
|
return f"Processed {len(res_int)} numeric value,\
|
||||||
|
sum={sum(res_int)}, avg={avg:.2f}"
|
||||||
|
except Exception as err:
|
||||||
|
print(f"NumericProcessor / format_output: {err}")
|
||||||
|
return "error"
|
||||||
|
|
||||||
|
|
||||||
|
class TextProcessor(DataProcessor):
|
||||||
|
def process(self, data: Any) -> str:
|
||||||
|
return str(data)
|
||||||
|
|
||||||
|
def validate(self, data: Any) -> bool:
|
||||||
|
try:
|
||||||
|
for char in data:
|
||||||
|
if type(char).__name__ != "str":
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
|
||||||
|
@override
|
||||||
|
def format_output(self, result: str) -> str:
|
||||||
|
return f"Processed text: {len(result)}\
|
||||||
|
characters, {len(result.split(' '))} words"
|
||||||
|
|
||||||
|
|
||||||
|
class LogProcessor(DataProcessor):
|
||||||
|
def process(self, data: Any) -> str:
|
||||||
|
try:
|
||||||
|
return f"{data[0]}: {data[1]}"
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
return "error"
|
||||||
|
|
||||||
|
def validate(self, data: Any) -> bool:
|
||||||
|
try:
|
||||||
|
if len(data) == 2:
|
||||||
|
for n in data:
|
||||||
|
if type(n).__name__ != "str":
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
|
||||||
|
@override
|
||||||
|
def format_output(self, result: str) -> str:
|
||||||
|
try:
|
||||||
|
log_res = result.split(":")[0]
|
||||||
|
if log_res == "ERROR":
|
||||||
|
header = "[ALERT]"
|
||||||
|
elif log_res == "INFO":
|
||||||
|
header = "[INFO]"
|
||||||
|
elif log_res == "SUCCESS":
|
||||||
|
header = "[SUCCESS]"
|
||||||
|
else:
|
||||||
|
header = "[UNKNOWN]"
|
||||||
|
return (
|
||||||
|
f"{header} {result.split(':', 1)[0]}{result.split(':', 1)[1]}"
|
||||||
|
)
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
return "error"
|
||||||
|
|
||||||
|
|
||||||
|
def class_tester() -> None:
|
||||||
|
print("=== CODE NEXUS - DATA PROCESSOR FOUNDATION ===\n")
|
||||||
|
print("Initializing Numeric Processor...")
|
||||||
|
data: Union[list[int | str], str] = [1, 2, 3, 4, 5]
|
||||||
|
processor: DataProcessor = NumericProcessor()
|
||||||
|
res = processor.process(data)
|
||||||
|
is_valid = processor.validate(data)
|
||||||
|
formatted_output = processor.format_output(res)
|
||||||
|
print(f"processing data: {res}")
|
||||||
|
if is_valid:
|
||||||
|
print("Validation: Numeric data verified")
|
||||||
|
else:
|
||||||
|
print("Validation: Invalid numeric data")
|
||||||
|
print(f"Output: {formatted_output}")
|
||||||
|
print("\nInitializing Text Processor...")
|
||||||
|
data = "Hello Nexus World"
|
||||||
|
processor = TextProcessor()
|
||||||
|
res = processor.process(data)
|
||||||
|
is_valid = processor.validate(data)
|
||||||
|
formatted_output = processor.format_output(res)
|
||||||
|
print(f"processing data: {res}")
|
||||||
|
if is_valid:
|
||||||
|
print("Validation: Text data verified")
|
||||||
|
else:
|
||||||
|
print("Validation: Invalid text data")
|
||||||
|
print(f"Output: {formatted_output}")
|
||||||
|
print("\nInitializing Log Processor...")
|
||||||
|
data = ["ERROR", "Connection timeout"]
|
||||||
|
processor = LogProcessor()
|
||||||
|
res = processor.process(data)
|
||||||
|
is_valid = processor.validate(data)
|
||||||
|
formatted_output = processor.format_output(res)
|
||||||
|
print(f"processing data: {res}")
|
||||||
|
if is_valid:
|
||||||
|
print("Validation: Log data verified")
|
||||||
|
else:
|
||||||
|
print("Validation: Invalid log data")
|
||||||
|
print(f"Output: {formatted_output}")
|
||||||
|
print("\n=== Polymorphic Processing Demo ===\n")
|
||||||
|
print(f"Result 1:\
|
||||||
|
{NumericProcessor().format_output('[1, 2, 3]')}")
|
||||||
|
print(f"Result 2:\
|
||||||
|
{TextProcessor().format_output('Hello World !')}")
|
||||||
|
print(f"Result 3:\
|
||||||
|
{LogProcessor().format_output('INFO: level detected: System ready')}")
|
||||||
|
print("\nFoundation systems online. Nexus ready for advanced streams.")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
class_tester()
|
||||||
273
05/ex1/data_stream.py
Normal file
273
05/ex1/data_stream.py
Normal file
@@ -0,0 +1,273 @@
|
|||||||
|
from abc import ABC, abstractmethod
|
||||||
|
from typing import Any, List, Optional, Dict, Union
|
||||||
|
from typing_extensions import override
|
||||||
|
|
||||||
|
|
||||||
|
class DataStream(ABC):
|
||||||
|
def __init__(self, stream_id: str, stream_type: str) -> None:
|
||||||
|
self.stream_id = stream_id
|
||||||
|
self.stream_type = stream_type
|
||||||
|
self.data_batch: List[str] = []
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def process_batch(self, data_batch: List[Any]) -> str:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def filter_data(
|
||||||
|
self, data_batch: List[Any], criteria: Optional[str] = None
|
||||||
|
) -> List[Any]:
|
||||||
|
res = []
|
||||||
|
if not criteria:
|
||||||
|
return data_batch
|
||||||
|
for data in data_batch:
|
||||||
|
if data.split(":", 1)[0] in criteria:
|
||||||
|
res += [data]
|
||||||
|
return res
|
||||||
|
|
||||||
|
def get_stats(self) -> Dict[str, Union[str, int, float]]:
|
||||||
|
return {
|
||||||
|
"nb_process": len(self.data_batch),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class SensorStream(DataStream):
|
||||||
|
def __init__(
|
||||||
|
self, stream_id: str, stream_type: str = "Environmental Data"
|
||||||
|
) -> None:
|
||||||
|
super().__init__(stream_id, stream_type)
|
||||||
|
|
||||||
|
def process_batch(self, data_batch: List[Any]) -> str:
|
||||||
|
res: List[str] = []
|
||||||
|
for data in data_batch:
|
||||||
|
try:
|
||||||
|
if len(data.split(":", 1)) == 2:
|
||||||
|
if data.split(":", 1)[0] == "temp":
|
||||||
|
float(data.split(":", 1)[1])
|
||||||
|
elif (
|
||||||
|
data.split(":", 1)[0] == "humidity"
|
||||||
|
or data.split(":", 1)[0] == "pressure"
|
||||||
|
):
|
||||||
|
int(data.split(":", 1)[1])
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
res += [data]
|
||||||
|
except Exception:
|
||||||
|
continue
|
||||||
|
self.data_batch += res
|
||||||
|
return f"{res}"
|
||||||
|
|
||||||
|
@override
|
||||||
|
def filter_data(
|
||||||
|
self, data_batch: List[Any], criteria: Optional[str] = None
|
||||||
|
) -> List[Any]:
|
||||||
|
return super().filter_data(data_batch, criteria)
|
||||||
|
|
||||||
|
@override
|
||||||
|
def get_stats(self) -> Dict[str, Union[str, int, float]]:
|
||||||
|
temp_data: List[float] = []
|
||||||
|
for temp in self.filter_data(self.data_batch, "temp"):
|
||||||
|
temp_data += [float(temp.split(":", 1)[1])]
|
||||||
|
res: Dict[str, Union[str, int, float]] = {}
|
||||||
|
res["nb_process"] = len(self.data_batch)
|
||||||
|
res["avg_temp"] = sum(temp_data) / len(temp_data)
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
class TransactionStream(DataStream):
|
||||||
|
def __init__(
|
||||||
|
self, stream_id: str, stream_type: str = "Financial Data"
|
||||||
|
) -> None:
|
||||||
|
super().__init__(stream_id, stream_type)
|
||||||
|
|
||||||
|
def process_batch(self, data_batch: List[Any]) -> str:
|
||||||
|
res: List[str] = []
|
||||||
|
for data in data_batch:
|
||||||
|
try:
|
||||||
|
if len(data.split(":", 1)) == 2:
|
||||||
|
if (
|
||||||
|
data.split(":", 1)[0] == "buy"
|
||||||
|
or data.split(":", 1)[0] == "sell"
|
||||||
|
):
|
||||||
|
int(data.split(":", 1)[1])
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
res += [data]
|
||||||
|
except Exception:
|
||||||
|
continue
|
||||||
|
self.data_batch += res
|
||||||
|
return f"{res}"
|
||||||
|
|
||||||
|
@override
|
||||||
|
def filter_data(
|
||||||
|
self, data_batch: List[Any], criteria: Optional[str] = None
|
||||||
|
) -> List[Any]:
|
||||||
|
res: List[Any] = []
|
||||||
|
if criteria and ">" == criteria[0]:
|
||||||
|
try:
|
||||||
|
higher_than = int(criteria.split(">")[1])
|
||||||
|
for data in data_batch:
|
||||||
|
if int(data.split(":", 1)[1]) > higher_than:
|
||||||
|
res += [data]
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
return res
|
||||||
|
else:
|
||||||
|
return super().filter_data(data_batch, criteria)
|
||||||
|
|
||||||
|
@override
|
||||||
|
def get_stats(self) -> Dict[str, Union[str, int, float]]:
|
||||||
|
net_flow = 0
|
||||||
|
for data in self.data_batch:
|
||||||
|
if data.split(":", 1)[0] == "buy":
|
||||||
|
net_flow += int(data.split(":", 1)[1])
|
||||||
|
else:
|
||||||
|
net_flow -= int(data.split(":", 1)[1])
|
||||||
|
res: Dict[str, Union[str, int, float]] = {}
|
||||||
|
res["nb_process"] = len(self.data_batch)
|
||||||
|
res["net_flow"] = net_flow
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
class EventStream(DataStream):
|
||||||
|
def __init__(
|
||||||
|
self, stream_id: str, stream_type: str = "System Events"
|
||||||
|
) -> None:
|
||||||
|
super().__init__(stream_id, stream_type)
|
||||||
|
|
||||||
|
def process_batch(self, data_batch: List[Any]) -> str:
|
||||||
|
res: List[str] = []
|
||||||
|
for data in data_batch:
|
||||||
|
try:
|
||||||
|
if data not in ["login", "logout", "error"]:
|
||||||
|
continue
|
||||||
|
res += [data]
|
||||||
|
except Exception:
|
||||||
|
continue
|
||||||
|
self.data_batch += res
|
||||||
|
return f"{res}"
|
||||||
|
|
||||||
|
@override
|
||||||
|
def filter_data(
|
||||||
|
self, data_batch: List[Any], criteria: Optional[str] = None
|
||||||
|
) -> List[Any]:
|
||||||
|
return super().filter_data(data_batch, criteria)
|
||||||
|
|
||||||
|
@override
|
||||||
|
def get_stats(self) -> Dict[str, Union[str, int, float]]:
|
||||||
|
nb_error = 0
|
||||||
|
for data in self.data_batch:
|
||||||
|
if data == "error":
|
||||||
|
nb_error += 1
|
||||||
|
res: Dict[str, Union[str, int, float]] = {}
|
||||||
|
res["nb_process"] = len(self.data_batch)
|
||||||
|
res["nb_error"] = nb_error
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
class StreamProcessor:
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.streams: Dict[str, List[DataStream]] = {
|
||||||
|
"sensor": [],
|
||||||
|
"transaction": [],
|
||||||
|
"event": [],
|
||||||
|
}
|
||||||
|
|
||||||
|
def process_batch(
|
||||||
|
self,
|
||||||
|
data_batch: List[Any],
|
||||||
|
stream: DataStream,
|
||||||
|
) -> DataStream:
|
||||||
|
try:
|
||||||
|
stream.process_batch(data_batch)
|
||||||
|
if isinstance(stream, SensorStream):
|
||||||
|
self.streams["sensor"] += [stream]
|
||||||
|
elif isinstance(stream, TransactionStream):
|
||||||
|
self.streams["transaction"] += [stream]
|
||||||
|
elif isinstance(stream, EventStream):
|
||||||
|
self.streams["event"] += [stream]
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
return stream
|
||||||
|
|
||||||
|
def get_stats(
|
||||||
|
self, stream: Union[SensorStream, TransactionStream, EventStream]
|
||||||
|
) -> Dict[str, Union[str, int, float]]:
|
||||||
|
return stream.get_stats()
|
||||||
|
|
||||||
|
def get_high_priority(
|
||||||
|
self,
|
||||||
|
) -> Dict[str, int]:
|
||||||
|
res: Dict[str, int] = {}
|
||||||
|
for stream in self.streams["transaction"]:
|
||||||
|
try:
|
||||||
|
res["large transaction"] = len(
|
||||||
|
stream.filter_data(stream.data_batch, ">100")
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
print("Error on catching large transaction")
|
||||||
|
continue
|
||||||
|
for stream in self.streams["event"]:
|
||||||
|
res["error detected"] = len(
|
||||||
|
stream.filter_data(stream.data_batch, "error")
|
||||||
|
)
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
def data_stream_tester() -> None:
|
||||||
|
print("=== CODE NEXUS - POLYMORPHIC STREAM SYSTEM ===\n")
|
||||||
|
sensor_stream = SensorStream("SENSOR_001", "Environmental Data")
|
||||||
|
print(f"Stream ID: {sensor_stream.stream_id},\
|
||||||
|
Type: {sensor_stream.stream_type}")
|
||||||
|
print(f"Processing sensor batch:\
|
||||||
|
{sensor_stream.process_batch(['temp:22.5', 'humidity:65', 'pressure:1013'])}")
|
||||||
|
sensor_analysis = sensor_stream.get_stats()
|
||||||
|
print(f"Sensor analysis: {sensor_analysis['nb_process']} reading\
|
||||||
|
process, avg temp: {sensor_analysis['avg_temp']}°C")
|
||||||
|
print()
|
||||||
|
transaction_stream = TransactionStream("TRANS_001", "Financial Data")
|
||||||
|
print(f"Stream ID: {transaction_stream.stream_id},\
|
||||||
|
Type: {transaction_stream.stream_type}")
|
||||||
|
print(f"Processing transaction batch:\
|
||||||
|
{transaction_stream.process_batch(['buy:100', 'sell:150', 'buy:75'])}")
|
||||||
|
transaction_analysis = transaction_stream.get_stats()
|
||||||
|
print(f"Transaction analysis: {transaction_analysis['nb_process']}\
|
||||||
|
operations, net flow: {transaction_analysis['net_flow']} units")
|
||||||
|
print()
|
||||||
|
event_stream = EventStream("EVENT_001", "System Events")
|
||||||
|
print(f"Stream ID: {event_stream.stream_id},\
|
||||||
|
Type: {event_stream.stream_type}")
|
||||||
|
print(f"Processing event batch:\
|
||||||
|
{event_stream.process_batch(['login', 'error', 'logout'])}")
|
||||||
|
event_analysis = event_stream.get_stats()
|
||||||
|
print(f"Sensor analysis: {event_analysis['nb_process']}\
|
||||||
|
events, {event_analysis['nb_error']} error detected")
|
||||||
|
|
||||||
|
|
||||||
|
def stream_processor_tester() -> None:
|
||||||
|
print("=== Polymorphic Stream Processing ===\n")
|
||||||
|
processor = StreamProcessor()
|
||||||
|
data_batch = [
|
||||||
|
["temp:22.5", "humidity:65", "pressure:1013"],
|
||||||
|
["buy:100", "sell:150"],
|
||||||
|
["login", "error", "logout", "login", "error"],
|
||||||
|
]
|
||||||
|
streams: list[DataStream] = [
|
||||||
|
SensorStream("SENSOR_001", "Environmental Data"),
|
||||||
|
TransactionStream("TRANS_001", "Financial Data"),
|
||||||
|
EventStream("EVENT_001", "System Events"),
|
||||||
|
]
|
||||||
|
for i in range(0, len(data_batch)):
|
||||||
|
streams[i] = processor.process_batch(data_batch[i], streams[i])
|
||||||
|
print("Batch 1 results:")
|
||||||
|
for stream in streams:
|
||||||
|
stat = stream.get_stats()
|
||||||
|
print(f"- {stream.stream_id}: {stat['nb_process']}")
|
||||||
|
print("\nHigh priority data:")
|
||||||
|
hp_data = processor.get_high_priority()
|
||||||
|
for data in hp_data:
|
||||||
|
print(f"- {hp_data[data]} {data}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
data_stream_tester()
|
||||||
|
stream_processor_tester()
|
||||||
149
05/ex2/nexus_pipeline.py
Normal file
149
05/ex2/nexus_pipeline.py
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
from abc import ABC
|
||||||
|
from typing import Any, Dict, List, Protocol, Union
|
||||||
|
from typing_extensions import override
|
||||||
|
|
||||||
|
|
||||||
|
class ProcessingStage(Protocol):
|
||||||
|
def process(self, data: Any) -> Any:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class InputStage:
|
||||||
|
def process(self, data: Any) -> Dict[int, float]:
|
||||||
|
res: Dict[int, float] = {}
|
||||||
|
i = 0
|
||||||
|
for n in data:
|
||||||
|
try:
|
||||||
|
if not isinstance(n, float):
|
||||||
|
n = float(n)
|
||||||
|
res[i] = n
|
||||||
|
i += 1
|
||||||
|
except ValueError:
|
||||||
|
continue
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
class TransformStage:
|
||||||
|
def process(self, data: Any) -> Dict[str, float]:
|
||||||
|
res: Dict[str, Union[int, float]] = {}
|
||||||
|
res["processed_data"] = len(data)
|
||||||
|
try:
|
||||||
|
res["avg"] = sum(data.values()) / len(data)
|
||||||
|
except ZeroDivisionError:
|
||||||
|
res["avg"] = 0
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
class OutputStage:
|
||||||
|
def process(self, data: Any) -> str:
|
||||||
|
return f"Summary:\n\t\
|
||||||
|
- Processed_data: {data['processed_data']}\n\t- avg temp: {data['avg']:.1f}°C"
|
||||||
|
|
||||||
|
|
||||||
|
class ProcessingPipeline(ABC):
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.stages: List[InputStage | TransformStage | OutputStage] = []
|
||||||
|
|
||||||
|
def add_stage(
|
||||||
|
self, stage: Union[InputStage, TransformStage, OutputStage]
|
||||||
|
) -> None:
|
||||||
|
self.stages += [stage]
|
||||||
|
|
||||||
|
def process(self, data: Any) -> Any:
|
||||||
|
for stage in self.stages:
|
||||||
|
data = stage.process(data)
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
class JSONAdapter(ProcessingPipeline):
|
||||||
|
def __init__(self, pipeline_id: str) -> None:
|
||||||
|
self.pipeline_id = pipeline_id
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
@override
|
||||||
|
def process(self, data: Any) -> Any:
|
||||||
|
res: List[Any] = []
|
||||||
|
for n in data:
|
||||||
|
res += [data[n]]
|
||||||
|
return super().process(res)
|
||||||
|
|
||||||
|
|
||||||
|
class CSVAdapter(ProcessingPipeline):
|
||||||
|
def __init__(self, pipeline_id: str) -> None:
|
||||||
|
self.pipeline_id = pipeline_id
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
@override
|
||||||
|
def process(self, data: Any) -> Any:
|
||||||
|
return super().process(data.split(","))
|
||||||
|
|
||||||
|
|
||||||
|
class StreamAdapter(ProcessingPipeline):
|
||||||
|
def __init__(self, pipeline_id: str) -> None:
|
||||||
|
self.pipeline_id = pipeline_id
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
@override
|
||||||
|
def process(self, data: Any) -> Any:
|
||||||
|
if not isinstance(data, List):
|
||||||
|
raise Exception
|
||||||
|
return super().process(data)
|
||||||
|
|
||||||
|
|
||||||
|
class NexusManager:
|
||||||
|
def __init__(self, pipelines: List[ProcessingPipeline]) -> None:
|
||||||
|
self.pipelines: List[ProcessingPipeline] = pipelines
|
||||||
|
|
||||||
|
def add_pipeline(self, pipeline: ProcessingPipeline) -> None:
|
||||||
|
self.pipelines += [pipeline]
|
||||||
|
|
||||||
|
def process_data(self, data: Any) -> str:
|
||||||
|
res: str | None = None
|
||||||
|
for pipeline in self.pipelines:
|
||||||
|
pipeline.add_stage(InputStage())
|
||||||
|
pipeline.add_stage(TransformStage())
|
||||||
|
pipeline.add_stage(OutputStage())
|
||||||
|
try:
|
||||||
|
res = pipeline.process(data)
|
||||||
|
break
|
||||||
|
except Exception:
|
||||||
|
continue
|
||||||
|
if res is None:
|
||||||
|
return "[ERROR] Unknown format, incompatible with pipelines"
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
def tester() -> None:
|
||||||
|
print("=== CODE NEXUS - ENTERPRISE PIPELINE SYSTEM ===\n")
|
||||||
|
print("Initializing Nexus Manager...")
|
||||||
|
manager = NexusManager(
|
||||||
|
[
|
||||||
|
JSONAdapter("JSON_01"),
|
||||||
|
CSVAdapter("CSV_01"),
|
||||||
|
StreamAdapter("Stream_01"),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
print("\n=== test JSONAdapter ===")
|
||||||
|
data: Any = {"temp": 10, "est": "10.3", "t": 10.6, "p": "Hello"}
|
||||||
|
print(f"input: {data}")
|
||||||
|
res = manager.process_data(data)
|
||||||
|
print(f"Output: {res}\n")
|
||||||
|
print("\n=== test CSVAdapter ===")
|
||||||
|
data = "10,20,40,30"
|
||||||
|
print(f'input: "{data}"')
|
||||||
|
res = manager.process_data(data)
|
||||||
|
print(f"Output: {res}\n")
|
||||||
|
print("\n=== test StreamAdapter ===")
|
||||||
|
data = [10, 30, 0, "100"]
|
||||||
|
print(f"input: {data}")
|
||||||
|
res = manager.process_data(data)
|
||||||
|
print(f"Output: {res}\n")
|
||||||
|
print("\n=== test Invalid input ===")
|
||||||
|
data = 10
|
||||||
|
print(f"input: {data}")
|
||||||
|
res = manager.process_data(data)
|
||||||
|
print(f"Output: {res}\n")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
tester()
|
||||||
571
05/main.py
Normal file
571
05/main.py
Normal file
@@ -0,0 +1,571 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Code Nexus - Polymorphism Testing Suite with Type Checking
|
||||||
|
|
||||||
|
This testing suite validates your implementation of polymorphic data processing systems.
|
||||||
|
It checks for proper method overriding, inheritance relationships, polymorphic behavior,
|
||||||
|
and type annotations across all three exercises.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
python3 main.py [OPTIONS]
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-h, --help Show this help message and exit
|
||||||
|
-v, --verbose Enable verbose output with detailed test information
|
||||||
|
|
||||||
|
Requirements:
|
||||||
|
- Python 3.10 or later
|
||||||
|
- Your exercise files must be in ex0/, ex1/, and ex2/ directories
|
||||||
|
- All code must include proper type annotations
|
||||||
|
|
||||||
|
Expected Directory Structure:
|
||||||
|
your-project/
|
||||||
|
├── ex0/
|
||||||
|
│ └── stream_processor.py
|
||||||
|
├── ex1/
|
||||||
|
│ └── data_stream.py
|
||||||
|
├── ex2/
|
||||||
|
│ └── nexus_pipeline.py
|
||||||
|
└── main.py (this file)
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
python3 main.py # Run all tests
|
||||||
|
python3 main.py --help # Show this help message
|
||||||
|
python3 main.py --verbose # Run with detailed output
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import importlib.util
|
||||||
|
import ast
|
||||||
|
from typing import List, Dict, Any, Optional, Tuple # noqa: F401
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
class TestResult:
|
||||||
|
"""Encapsulates test results with detailed feedback."""
|
||||||
|
|
||||||
|
def __init__(self, name: str) -> None:
|
||||||
|
self.name: str = name
|
||||||
|
self.passed: bool = False
|
||||||
|
self.errors: List[str] = []
|
||||||
|
self.warnings: List[str] = []
|
||||||
|
|
||||||
|
def add_error(self, error: str) -> None:
|
||||||
|
"""Add an error message."""
|
||||||
|
self.errors.append(error)
|
||||||
|
|
||||||
|
def add_warning(self, warning: str) -> None:
|
||||||
|
"""Add a warning message."""
|
||||||
|
self.warnings.append(warning)
|
||||||
|
|
||||||
|
def mark_passed(self) -> None:
|
||||||
|
"""Mark test as passed."""
|
||||||
|
self.passed = True
|
||||||
|
|
||||||
|
|
||||||
|
class TypeChecker:
|
||||||
|
"""Validates type annotations in Python code."""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.required_imports = [
|
||||||
|
"typing", "Any", "List", "Dict", "Union", "Optional"
|
||||||
|
]
|
||||||
|
|
||||||
|
def check_file_typing(self, file_path: str) -> Tuple[bool, List[str]]:
|
||||||
|
"""Check if file has proper type annotations."""
|
||||||
|
try:
|
||||||
|
with open(file_path, 'r') as f:
|
||||||
|
content = f.read()
|
||||||
|
|
||||||
|
tree = ast.parse(content)
|
||||||
|
issues = []
|
||||||
|
has_typing_imports = False
|
||||||
|
|
||||||
|
# Check for typing imports
|
||||||
|
for node in ast.walk(tree):
|
||||||
|
if isinstance(node, ast.ImportFrom) and node.module == "typing":
|
||||||
|
has_typing_imports = True
|
||||||
|
elif isinstance(node, ast.Import):
|
||||||
|
for alias in node.names:
|
||||||
|
if alias.name == "typing":
|
||||||
|
has_typing_imports = True
|
||||||
|
|
||||||
|
if not has_typing_imports:
|
||||||
|
issues.append("Missing typing imports")
|
||||||
|
|
||||||
|
# Check function definitions for type annotations
|
||||||
|
function_count = 0
|
||||||
|
typed_functions = 0
|
||||||
|
|
||||||
|
for node in ast.walk(tree):
|
||||||
|
if isinstance(node, ast.FunctionDef):
|
||||||
|
function_count += 1
|
||||||
|
|
||||||
|
# Check return type annotation
|
||||||
|
if node.returns is not None:
|
||||||
|
typed_functions += 1
|
||||||
|
|
||||||
|
# Check parameter type annotations
|
||||||
|
for arg in node.args.args:
|
||||||
|
if arg.annotation is None and arg.arg != "self":
|
||||||
|
issues.append(
|
||||||
|
f"Function '{node.name}' parameter "
|
||||||
|
f"'{arg.arg}' missing type annotation"
|
||||||
|
)
|
||||||
|
|
||||||
|
if function_count > 0:
|
||||||
|
typing_coverage = (typed_functions / function_count) * 100
|
||||||
|
if typing_coverage < 80:
|
||||||
|
issues.append(
|
||||||
|
f"Low typing coverage: {typing_coverage:.1f}% of "
|
||||||
|
f"functions have return type annotations"
|
||||||
|
)
|
||||||
|
|
||||||
|
return len(issues) == 0, issues
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
return False, [f"Error checking types: {str(e)}"]
|
||||||
|
|
||||||
|
|
||||||
|
class PolymorphismTester:
|
||||||
|
"""Main testing class for polymorphic implementations with type checking."""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.results: List[TestResult] = []
|
||||||
|
self.type_checker = TypeChecker()
|
||||||
|
|
||||||
|
def load_module(self, file_path: str, module_name: str) -> Optional[Any]:
|
||||||
|
"""Dynamically load a Python module from file path."""
|
||||||
|
try:
|
||||||
|
spec = importlib.util.spec_from_file_location(module_name, file_path)
|
||||||
|
if spec is None or spec.loader is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
module = importlib.util.module_from_spec(spec)
|
||||||
|
spec.loader.exec_module(module)
|
||||||
|
return module
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error loading module {module_name}: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def run_all_tests(self, verbose: bool = False) -> bool:
|
||||||
|
"""Execute all test suites and return overall success status."""
|
||||||
|
print("CODE NEXUS - POLYMORPHISM TESTING SUITE WITH TYPE CHECKING")
|
||||||
|
print("=" * 60)
|
||||||
|
print("Testing polymorphic implementations with type annotations.")
|
||||||
|
if verbose:
|
||||||
|
print("Verbose mode enabled - detailed output will be shown.")
|
||||||
|
print()
|
||||||
|
|
||||||
|
# Run individual test suites
|
||||||
|
self._test_exercise_0()
|
||||||
|
self._test_exercise_1()
|
||||||
|
self._test_exercise_2()
|
||||||
|
|
||||||
|
# Display summary
|
||||||
|
self._display_summary()
|
||||||
|
|
||||||
|
return all(result.passed for result in self.results)
|
||||||
|
|
||||||
|
def _test_exercise_0(self) -> None:
|
||||||
|
"""Test Exercise 0: Data Processor Foundation with type checking."""
|
||||||
|
result = TestResult("Exercise 0: Data Processor Foundation")
|
||||||
|
|
||||||
|
print("=== Testing Exercise 0: Data Processor Foundation ===")
|
||||||
|
|
||||||
|
try:
|
||||||
|
file_path = "ex0/stream_processor.py"
|
||||||
|
|
||||||
|
# Check type annotations first
|
||||||
|
has_proper_typing, typing_issues = self.type_checker.check_file_typing(file_path)
|
||||||
|
if not has_proper_typing:
|
||||||
|
result.add_error("Type annotation issues found:")
|
||||||
|
for issue in typing_issues:
|
||||||
|
result.add_error(f" • {issue}")
|
||||||
|
else:
|
||||||
|
print("✓ Type annotations properly implemented")
|
||||||
|
|
||||||
|
# Import your implementation
|
||||||
|
stream_processor = self.load_module(file_path, "stream_processor")
|
||||||
|
if not stream_processor:
|
||||||
|
result.add_error("Could not load stream_processor.py module")
|
||||||
|
else:
|
||||||
|
# Verify required classes exist
|
||||||
|
required_classes = [
|
||||||
|
'DataProcessor', 'NumericProcessor',
|
||||||
|
'TextProcessor', 'LogProcessor'
|
||||||
|
]
|
||||||
|
missing_classes = []
|
||||||
|
|
||||||
|
for class_name in required_classes:
|
||||||
|
if not hasattr(stream_processor, class_name):
|
||||||
|
missing_classes.append(class_name)
|
||||||
|
|
||||||
|
if missing_classes:
|
||||||
|
result.add_error(f"Missing classes: {', '.join(missing_classes)}")
|
||||||
|
else:
|
||||||
|
print("✓ All required classes found")
|
||||||
|
|
||||||
|
# Test inheritance relationships
|
||||||
|
DataProcessor = getattr(stream_processor, 'DataProcessor')
|
||||||
|
NumericProcessor = getattr(stream_processor, 'NumericProcessor')
|
||||||
|
TextProcessor = getattr(stream_processor, 'TextProcessor')
|
||||||
|
LogProcessor = getattr(stream_processor, 'LogProcessor')
|
||||||
|
|
||||||
|
if not issubclass(NumericProcessor, DataProcessor):
|
||||||
|
result.add_error(
|
||||||
|
"NumericProcessor must inherit from DataProcessor"
|
||||||
|
)
|
||||||
|
if not issubclass(TextProcessor, DataProcessor):
|
||||||
|
result.add_error(
|
||||||
|
"TextProcessor must inherit from DataProcessor"
|
||||||
|
)
|
||||||
|
if not issubclass(LogProcessor, DataProcessor):
|
||||||
|
result.add_error(
|
||||||
|
"LogProcessor must inherit from DataProcessor"
|
||||||
|
)
|
||||||
|
|
||||||
|
if not result.errors:
|
||||||
|
print("✓ Inheritance relationships verified")
|
||||||
|
|
||||||
|
# Test method overriding
|
||||||
|
try:
|
||||||
|
numeric_proc = NumericProcessor()
|
||||||
|
text_proc = TextProcessor()
|
||||||
|
log_proc = LogProcessor()
|
||||||
|
|
||||||
|
# Verify methods exist and are callable
|
||||||
|
for processor in [numeric_proc, text_proc, log_proc]:
|
||||||
|
for method in ['process', 'validate',
|
||||||
|
'format_output']:
|
||||||
|
if not hasattr(processor, method) or \
|
||||||
|
not callable(getattr(processor, method)):
|
||||||
|
result.add_error(
|
||||||
|
f"{processor.__class__.__name__} "
|
||||||
|
f"missing method: {method}"
|
||||||
|
)
|
||||||
|
|
||||||
|
if not result.errors:
|
||||||
|
print("✓ Method overriding implemented correctly")
|
||||||
|
if has_proper_typing:
|
||||||
|
result.mark_passed()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
result.add_error(f"Error testing method overriding: {str(e)}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
result.add_error(f"Unexpected error: {str(e)}")
|
||||||
|
|
||||||
|
if not result.passed:
|
||||||
|
print("✗ Exercise 0 failed - check implementation and type annotations")
|
||||||
|
|
||||||
|
self.results.append(result)
|
||||||
|
|
||||||
|
def _test_exercise_1(self) -> None:
|
||||||
|
"""Test Exercise 1: Polymorphic Streams with type checking."""
|
||||||
|
result = TestResult("Exercise 1: Polymorphic Streams")
|
||||||
|
|
||||||
|
print("\n=== Testing Exercise 1: Polymorphic Streams ===")
|
||||||
|
|
||||||
|
try:
|
||||||
|
file_path = "ex1/data_stream.py"
|
||||||
|
|
||||||
|
# Check type annotations first
|
||||||
|
has_proper_typing, typing_issues = self.type_checker.check_file_typing(file_path)
|
||||||
|
if not has_proper_typing:
|
||||||
|
result.add_error("Type annotation issues found:")
|
||||||
|
for issue in typing_issues:
|
||||||
|
result.add_error(f" • {issue}")
|
||||||
|
else:
|
||||||
|
print("✓ Type annotations properly implemented")
|
||||||
|
|
||||||
|
# Import your implementation
|
||||||
|
data_stream = self.load_module(file_path, "data_stream")
|
||||||
|
if not data_stream:
|
||||||
|
result.add_error("Could not load data_stream.py module")
|
||||||
|
else:
|
||||||
|
# Verify required classes exist
|
||||||
|
required_classes = [
|
||||||
|
'DataStream', 'SensorStream', 'TransactionStream',
|
||||||
|
'EventStream', 'StreamProcessor'
|
||||||
|
]
|
||||||
|
missing_classes = []
|
||||||
|
|
||||||
|
for class_name in required_classes:
|
||||||
|
if not hasattr(data_stream, class_name):
|
||||||
|
missing_classes.append(class_name)
|
||||||
|
|
||||||
|
if missing_classes:
|
||||||
|
result.add_error(f"Missing classes: {', '.join(missing_classes)}")
|
||||||
|
else:
|
||||||
|
print("✓ All required classes found")
|
||||||
|
|
||||||
|
# Test inheritance and polymorphism
|
||||||
|
DataStream = getattr(data_stream, 'DataStream')
|
||||||
|
SensorStream = getattr(data_stream, 'SensorStream')
|
||||||
|
TransactionStream = getattr(data_stream, 'TransactionStream')
|
||||||
|
EventStream = getattr(data_stream, 'EventStream')
|
||||||
|
|
||||||
|
# Verify inheritance
|
||||||
|
stream_classes = [
|
||||||
|
SensorStream, TransactionStream, EventStream
|
||||||
|
]
|
||||||
|
for stream_class in stream_classes:
|
||||||
|
if not issubclass(stream_class, DataStream):
|
||||||
|
result.add_error(
|
||||||
|
f"{stream_class.__name__} must inherit "
|
||||||
|
f"from DataStream"
|
||||||
|
)
|
||||||
|
|
||||||
|
if not result.errors:
|
||||||
|
print("✓ Inheritance relationships verified")
|
||||||
|
|
||||||
|
# Test polymorphic behavior
|
||||||
|
try:
|
||||||
|
sensor = SensorStream("SENSOR_001")
|
||||||
|
transaction = TransactionStream("TRANS_001")
|
||||||
|
event = EventStream("EVENT_001")
|
||||||
|
|
||||||
|
# Verify polymorphic processing
|
||||||
|
streams = [sensor, transaction, event]
|
||||||
|
for stream in streams:
|
||||||
|
if not hasattr(stream, 'process_batch') or \
|
||||||
|
not callable(getattr(stream, 'process_batch')):
|
||||||
|
result.add_error(
|
||||||
|
f"{stream.__class__.__name__} "
|
||||||
|
f"missing process_batch method"
|
||||||
|
)
|
||||||
|
|
||||||
|
if not result.errors:
|
||||||
|
print("✓ Polymorphic behavior implemented correctly")
|
||||||
|
if has_proper_typing:
|
||||||
|
result.mark_passed()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
result.add_error(f"Error testing polymorphic behavior: {str(e)}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
result.add_error(f"Unexpected error: {str(e)}")
|
||||||
|
|
||||||
|
if not result.passed:
|
||||||
|
print("✗ Exercise 1 failed - check implementation and type annotations")
|
||||||
|
|
||||||
|
self.results.append(result)
|
||||||
|
|
||||||
|
def _test_exercise_2(self) -> None:
|
||||||
|
"""Test Exercise 2: Nexus Integration with type checking."""
|
||||||
|
result = TestResult("Exercise 2: Nexus Integration")
|
||||||
|
|
||||||
|
print("\n=== Testing Exercise 2: Nexus Integration ===")
|
||||||
|
|
||||||
|
try:
|
||||||
|
file_path = "ex2/nexus_pipeline.py"
|
||||||
|
|
||||||
|
# Check type annotations first
|
||||||
|
has_proper_typing, typing_issues = self.type_checker.check_file_typing(file_path)
|
||||||
|
if not has_proper_typing:
|
||||||
|
result.add_error("Type annotation issues found:")
|
||||||
|
for issue in typing_issues:
|
||||||
|
result.add_error(f" • {issue}")
|
||||||
|
else:
|
||||||
|
print("✓ Type annotations properly implemented")
|
||||||
|
|
||||||
|
# Import your implementation
|
||||||
|
nexus_pipeline = self.load_module(file_path, "nexus_pipeline")
|
||||||
|
if not nexus_pipeline:
|
||||||
|
result.add_error("Could not load nexus_pipeline.py module")
|
||||||
|
else:
|
||||||
|
# Verify required classes exist
|
||||||
|
required_classes = [
|
||||||
|
'ProcessingPipeline', 'InputStage', 'TransformStage',
|
||||||
|
'OutputStage', 'JSONAdapter', 'CSVAdapter',
|
||||||
|
'StreamAdapter', 'NexusManager'
|
||||||
|
]
|
||||||
|
missing_classes = []
|
||||||
|
|
||||||
|
for class_name in required_classes:
|
||||||
|
if not hasattr(nexus_pipeline, class_name):
|
||||||
|
missing_classes.append(class_name)
|
||||||
|
|
||||||
|
if missing_classes:
|
||||||
|
result.add_error(f"Missing classes: {', '.join(missing_classes)}")
|
||||||
|
else:
|
||||||
|
print("✓ All required classes found")
|
||||||
|
|
||||||
|
# Test complex inheritance hierarchy
|
||||||
|
ProcessingPipeline = getattr(nexus_pipeline, 'ProcessingPipeline')
|
||||||
|
JSONAdapter = getattr(nexus_pipeline, 'JSONAdapter')
|
||||||
|
CSVAdapter = getattr(nexus_pipeline, 'CSVAdapter')
|
||||||
|
StreamAdapter = getattr(nexus_pipeline, 'StreamAdapter')
|
||||||
|
|
||||||
|
# Verify inheritance
|
||||||
|
adapter_classes = [
|
||||||
|
JSONAdapter, CSVAdapter, StreamAdapter
|
||||||
|
]
|
||||||
|
for adapter_class in adapter_classes:
|
||||||
|
if not issubclass(adapter_class, ProcessingPipeline):
|
||||||
|
result.add_error(
|
||||||
|
f"{adapter_class.__name__} must inherit "
|
||||||
|
f"from ProcessingPipeline"
|
||||||
|
)
|
||||||
|
|
||||||
|
if not result.errors:
|
||||||
|
print("✓ Complex inheritance hierarchy verified")
|
||||||
|
|
||||||
|
# Test enterprise-level polymorphism
|
||||||
|
try:
|
||||||
|
# Verify manager can handle different pipeline types
|
||||||
|
json_adapter = JSONAdapter("JSON_001")
|
||||||
|
csv_adapter = CSVAdapter("CSV_001")
|
||||||
|
stream_adapter = StreamAdapter("STREAM_001")
|
||||||
|
|
||||||
|
adapters = [
|
||||||
|
json_adapter, csv_adapter, stream_adapter
|
||||||
|
]
|
||||||
|
for adapter in adapters:
|
||||||
|
if not hasattr(adapter, 'process') or \
|
||||||
|
not callable(getattr(adapter, 'process')):
|
||||||
|
result.add_error(
|
||||||
|
f"{adapter.__class__.__name__} "
|
||||||
|
f"missing process method"
|
||||||
|
)
|
||||||
|
|
||||||
|
if not result.errors:
|
||||||
|
print("✓ Enterprise-level polymorphism implemented correctly")
|
||||||
|
if has_proper_typing:
|
||||||
|
result.mark_passed()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
result.add_error(f"Error testing enterprise polymorphism: {str(e)}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
result.add_error(f"Unexpected error: {str(e)}")
|
||||||
|
|
||||||
|
if not result.passed:
|
||||||
|
print("✗ Exercise 2 failed - check implementation and type annotations")
|
||||||
|
|
||||||
|
self.results.append(result)
|
||||||
|
|
||||||
|
def _display_summary(self) -> None:
|
||||||
|
"""Display comprehensive test summary."""
|
||||||
|
print("\n" + "=" * 60)
|
||||||
|
print("TESTING SUMMARY")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
passed_count = sum(1 for result in self.results if result.passed)
|
||||||
|
total_count = len(self.results)
|
||||||
|
|
||||||
|
print(f"Exercises passed: {passed_count}/{total_count}")
|
||||||
|
|
||||||
|
if passed_count == total_count:
|
||||||
|
print("🎉 All tests passed! Your polymorphic implementations "
|
||||||
|
"with type annotations are working correctly.")
|
||||||
|
else:
|
||||||
|
print("⚠️ Some exercises need work. "
|
||||||
|
"Check the error messages above.")
|
||||||
|
print("Make sure you've implemented all required classes, "
|
||||||
|
"methods, and type annotations.")
|
||||||
|
|
||||||
|
# Display detailed errors if any
|
||||||
|
for result in self.results:
|
||||||
|
if result.errors:
|
||||||
|
print(f"\n❌ {result.name}:")
|
||||||
|
for error in result.errors:
|
||||||
|
print(f" • {error}")
|
||||||
|
|
||||||
|
print("\nRemember: This tests basic functionality "
|
||||||
|
"and type annotations.")
|
||||||
|
print("Make sure your code demonstrates proper polymorphic behavior "
|
||||||
|
"with complete typing!")
|
||||||
|
|
||||||
|
|
||||||
|
def print_help() -> None:
|
||||||
|
"""Display help message."""
|
||||||
|
help_text = """
|
||||||
|
CODE NEXUS - POLYMORPHISM TESTING SUITE
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
python3 main.py [OPTIONS]
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-h, --help Show this help message and exit
|
||||||
|
-v, --verbose Enable verbose output with detailed test information
|
||||||
|
|
||||||
|
Description:
|
||||||
|
This testing suite validates your polymorphic data processing
|
||||||
|
implementations across three exercises. It checks for:
|
||||||
|
- Proper method overriding and inheritance relationships
|
||||||
|
- Polymorphic behavior using abstract base classes (ABC)
|
||||||
|
- Comprehensive type annotations throughout all code
|
||||||
|
- Correct implementation of required classes and methods
|
||||||
|
|
||||||
|
Requirements:
|
||||||
|
- Python 3.10 or later
|
||||||
|
- Exercise files in ex0/, ex1/, and ex2/ directories
|
||||||
|
- All code must include proper type annotations
|
||||||
|
|
||||||
|
Expected Directory Structure:
|
||||||
|
your-project/
|
||||||
|
├── ex0/
|
||||||
|
│ └── stream_processor.py
|
||||||
|
├── ex1/
|
||||||
|
│ └── data_stream.py
|
||||||
|
├── ex2/
|
||||||
|
│ └── nexus_pipeline.py
|
||||||
|
└── main.py (this file)
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
python3 main.py # Run all tests
|
||||||
|
python3 main.py --help # Show this help message
|
||||||
|
python3 main.py --verbose # Run with detailed output
|
||||||
|
|
||||||
|
For more information, refer to the project subject.
|
||||||
|
"""
|
||||||
|
print(help_text)
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
"""Main entry point for the testing suite."""
|
||||||
|
# Parse command line arguments
|
||||||
|
verbose = False
|
||||||
|
if len(sys.argv) > 1:
|
||||||
|
if sys.argv[1] in ['-h', '--help']:
|
||||||
|
print_help()
|
||||||
|
sys.exit(0)
|
||||||
|
elif sys.argv[1] in ['-v', '--verbose']:
|
||||||
|
verbose = True
|
||||||
|
else:
|
||||||
|
print(f"Unknown option: {sys.argv[1]}")
|
||||||
|
print("Use --help for usage information")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Verify exercise directories exist
|
||||||
|
ex0_dir = Path("ex0")
|
||||||
|
ex1_dir = Path("ex1")
|
||||||
|
ex2_dir = Path("ex2")
|
||||||
|
|
||||||
|
missing_dirs = []
|
||||||
|
if not ex0_dir.exists():
|
||||||
|
missing_dirs.append("ex0/")
|
||||||
|
if not ex1_dir.exists():
|
||||||
|
missing_dirs.append("ex1/")
|
||||||
|
if not ex2_dir.exists():
|
||||||
|
missing_dirs.append("ex2/")
|
||||||
|
|
||||||
|
if missing_dirs:
|
||||||
|
print("❌ Exercise directories not found!")
|
||||||
|
print(f"Missing: {', '.join(missing_dirs)}")
|
||||||
|
print("Please ensure your exercise files are in "
|
||||||
|
"ex0/, ex1/, and ex2/ directories")
|
||||||
|
print("\nUse --help for more information")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
tester = PolymorphismTester()
|
||||||
|
success = tester.run_all_tests(verbose=verbose)
|
||||||
|
|
||||||
|
# Exit with appropriate code
|
||||||
|
sys.exit(0 if success else 1)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
5
06/alchemy/__init__.py
Normal file
5
06/alchemy/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
from .elements import create_fire, create_water
|
||||||
|
|
||||||
|
__version__ = "1.0.0"
|
||||||
|
__author__ = "Master Pythonicus"
|
||||||
|
__all__ = ["create_fire", "create_water"]
|
||||||
14
06/alchemy/elements.py
Normal file
14
06/alchemy/elements.py
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
def create_fire() -> str:
|
||||||
|
return "Fire element created"
|
||||||
|
|
||||||
|
|
||||||
|
def create_water() -> str:
|
||||||
|
return "Water element created"
|
||||||
|
|
||||||
|
|
||||||
|
def create_earth() -> str:
|
||||||
|
return "Earth element created"
|
||||||
|
|
||||||
|
|
||||||
|
def create_air() -> str:
|
||||||
|
return "Air element created"
|
||||||
6
06/alchemy/grimoire/__init__.py
Normal file
6
06/alchemy/grimoire/__init__.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
from .spellbook import record_spell
|
||||||
|
from .validator import validate_ingredients
|
||||||
|
|
||||||
|
__version__ = "1.0.0"
|
||||||
|
__author__ = "Master Pythonicus"
|
||||||
|
__all__ = ["record_spell", "validate_ingredients"]
|
||||||
8
06/alchemy/grimoire/spellbook.py
Normal file
8
06/alchemy/grimoire/spellbook.py
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
def record_spell(spell_name: str, ingredients: str) -> str:
|
||||||
|
from .validator import validate_ingredients
|
||||||
|
|
||||||
|
validation_res = validate_ingredients(ingredients)
|
||||||
|
if validation_res == f"{ingredients} - VALID":
|
||||||
|
return f"Spell recorded: {spell_name} ({validation_res})"
|
||||||
|
else:
|
||||||
|
return f"Spell rejected: {spell_name} ({validation_res})"
|
||||||
8
06/alchemy/grimoire/validator.py
Normal file
8
06/alchemy/grimoire/validator.py
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
def validate_ingredients(ingredients: str) -> str:
|
||||||
|
try:
|
||||||
|
for ingredient in ingredients.split(" "):
|
||||||
|
if ingredient not in ["fire", "water", "earth", "air"]:
|
||||||
|
raise ValueError
|
||||||
|
return f"{ingredients} - VALID"
|
||||||
|
except ValueError:
|
||||||
|
return f"{ingredients} - INVALID"
|
||||||
27
06/alchemy/potions.py
Normal file
27
06/alchemy/potions.py
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
def healing_potion() -> str:
|
||||||
|
from .elements import create_water, create_fire
|
||||||
|
|
||||||
|
return f"Healing potion brewed with {create_fire()} and {create_water()}"
|
||||||
|
|
||||||
|
|
||||||
|
def strength_potion() -> str:
|
||||||
|
from .elements import create_earth, create_fire
|
||||||
|
|
||||||
|
return f"Strength potion brewed with {create_earth()} and {create_fire()}"
|
||||||
|
|
||||||
|
|
||||||
|
def invisibility_potion() -> str:
|
||||||
|
from .elements import create_air, create_water
|
||||||
|
|
||||||
|
return (
|
||||||
|
f"Invisibility potion brewed with {create_air()} and {create_water()}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def wisdom_potion() -> str:
|
||||||
|
from .elements import create_water, create_fire, create_air, create_earth
|
||||||
|
|
||||||
|
res = ""
|
||||||
|
for fn in (create_water(), create_fire(), create_air(), create_earth()):
|
||||||
|
res += fn
|
||||||
|
return f"Wisdom potion brewed with all elements: {res}"
|
||||||
11
06/alchemy/transmutation/__init__.py
Normal file
11
06/alchemy/transmutation/__init__.py
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
from .basic import lead_to_gold, stone_to_gem
|
||||||
|
from .advanced import philosophers_stone, elixir_of_life
|
||||||
|
|
||||||
|
__version__ = "1.0.0"
|
||||||
|
__author__ = "Master Pythonicus"
|
||||||
|
__all__ = [
|
||||||
|
"lead_to_gold",
|
||||||
|
"stone_to_gem",
|
||||||
|
"philosophers_stone",
|
||||||
|
"elixir_of_life",
|
||||||
|
]
|
||||||
11
06/alchemy/transmutation/advanced.py
Normal file
11
06/alchemy/transmutation/advanced.py
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
from .basic import lead_to_gold
|
||||||
|
from ..potions import healing_potion
|
||||||
|
|
||||||
|
|
||||||
|
def philosophers_stone() -> str:
|
||||||
|
return f"Philosopher’s stone created using {lead_to_gold()}\
|
||||||
|
and {healing_potion()}"
|
||||||
|
|
||||||
|
|
||||||
|
def elixir_of_life() -> str:
|
||||||
|
return f"Elixir of life: eternal youth achieved!"
|
||||||
9
06/alchemy/transmutation/basic.py
Normal file
9
06/alchemy/transmutation/basic.py
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
from alchemy.elements import create_fire, create_earth
|
||||||
|
|
||||||
|
|
||||||
|
def lead_to_gold() -> str:
|
||||||
|
return f"Lead transmuted to gold using {create_fire()}"
|
||||||
|
|
||||||
|
|
||||||
|
def stone_to_gem() -> str:
|
||||||
|
return f"Stone transmuted to gem using {create_earth()}"
|
||||||
44
06/ft_circular_curse.py
Normal file
44
06/ft_circular_curse.py
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
def ingredients_validation() -> None:
|
||||||
|
from alchemy.grimoire.validator import validate_ingredients
|
||||||
|
|
||||||
|
print(
|
||||||
|
f'validate_ingredients("fire air"): {validate_ingredients("fire air")}'
|
||||||
|
)
|
||||||
|
print(
|
||||||
|
f'validate_ingredients("dragon scale"): {validate_ingredients("dragon scale")}'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def spell_recording_test() -> None:
|
||||||
|
from alchemy.grimoire.spellbook import record_spell
|
||||||
|
|
||||||
|
print(
|
||||||
|
f'record_spell("Fireball", "fire air"): {record_spell("Fireball", "fire air")}'
|
||||||
|
)
|
||||||
|
print(
|
||||||
|
f'record_spell("Dark Magic", "shadow"): {record_spell("Dark Magic", "shadow")}'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def late_import_test() -> None:
|
||||||
|
from alchemy.grimoire.spellbook import record_spell
|
||||||
|
|
||||||
|
print(
|
||||||
|
f'record_spell("Lightning", "air"): {record_spell("Lightning", "air")}'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
print("=== Circular Curse Breaking ===\n")
|
||||||
|
print("Testing ingredient validation:")
|
||||||
|
ingredients_validation()
|
||||||
|
print("\nTesting spell recording with validation:")
|
||||||
|
spell_recording_test()
|
||||||
|
print("\nTesting late import technique:")
|
||||||
|
late_import_test()
|
||||||
|
print("\nCircular dependency curse avoided using late imports!")
|
||||||
|
print("All spells processed safely!")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
54
06/ft_import_transmutation.py
Normal file
54
06/ft_import_transmutation.py
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
def full_module_import() -> None:
|
||||||
|
import alchemy.elements
|
||||||
|
|
||||||
|
print(f"alchemy.elements.create_fire(): {alchemy.elements.create_fire()}")
|
||||||
|
|
||||||
|
|
||||||
|
def specific_function_import() -> None:
|
||||||
|
from alchemy.elements import create_water
|
||||||
|
|
||||||
|
print(f"create_water(): {create_water()}")
|
||||||
|
|
||||||
|
|
||||||
|
def aliased_import() -> None:
|
||||||
|
from alchemy.potions import healing_potion as heal
|
||||||
|
|
||||||
|
print(f"heal(): {heal()}")
|
||||||
|
|
||||||
|
|
||||||
|
def multiple_import() -> None:
|
||||||
|
from alchemy.elements import create_fire, create_earth
|
||||||
|
from alchemy.potions import strength_potion
|
||||||
|
|
||||||
|
print(f"create_earth(): {create_earth()}")
|
||||||
|
print(f"create_fire(): {create_fire()}")
|
||||||
|
print(f"strength_potion(): {strength_potion()}")
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
print("=== Import Transmutation Mastery ===\n")
|
||||||
|
print("Method 1 - Full module import:")
|
||||||
|
try:
|
||||||
|
full_module_import()
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
print("\nMethod 2 - Specific function import:")
|
||||||
|
try:
|
||||||
|
specific_function_import()
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
print("\nMethod 3 - Aliased import:")
|
||||||
|
try:
|
||||||
|
aliased_import()
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
print("\nMethod 4 - Multiple imports:")
|
||||||
|
try:
|
||||||
|
multiple_import()
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
print("\nAll import transmutation methods mastered!")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
48
06/ft_pathway_debate.py
Normal file
48
06/ft_pathway_debate.py
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
def absolute_import() -> None:
|
||||||
|
from alchemy.transmutation import lead_to_gold, stone_to_gem
|
||||||
|
|
||||||
|
print(f"lead_to_gold(): {lead_to_gold()}")
|
||||||
|
print(f"stone_to_gem(): {stone_to_gem()}")
|
||||||
|
|
||||||
|
|
||||||
|
def relative_import() -> None:
|
||||||
|
from alchemy.transmutation.advanced import (
|
||||||
|
philosophers_stone,
|
||||||
|
elixir_of_life,
|
||||||
|
)
|
||||||
|
|
||||||
|
print(f"philosophers_stone(): {philosophers_stone()}")
|
||||||
|
print(f"elixir_of_life(): {elixir_of_life()}")
|
||||||
|
|
||||||
|
|
||||||
|
def package_import() -> None:
|
||||||
|
import alchemy.transmutation
|
||||||
|
|
||||||
|
print(f"alchemy.transmutation.lead_to_gold():\
|
||||||
|
{alchemy.transmutation.lead_to_gold()}")
|
||||||
|
print(f"alchemy.transmutation.philosophers_stone():\
|
||||||
|
{alchemy.transmutation.philosophers_stone()}")
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
print("=== Pathway Debate Mastery ===\n")
|
||||||
|
print("Testing Absolute Imports (from basic.py):")
|
||||||
|
try:
|
||||||
|
absolute_import()
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
print("\nTesting Relative Imports (from advanced.py):")
|
||||||
|
try:
|
||||||
|
relative_import()
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
print("\nTesting Package Access:")
|
||||||
|
try:
|
||||||
|
package_import()
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
print("\nBoth pathways work! Absolute: clear, Relative: concise")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
32
06/ft_sacred_scroll.py
Normal file
32
06/ft_sacred_scroll.py
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
def main() -> None:
|
||||||
|
import alchemy
|
||||||
|
|
||||||
|
print("=== Sacred Scroll Mastery ===\n")
|
||||||
|
print("Testing direct module access:")
|
||||||
|
print(f"alchemy.elements.create_fire(): {alchemy.elements.create_fire()}")
|
||||||
|
print(
|
||||||
|
f"alchemy.elements.create_water(): {alchemy.elements.create_water()}"
|
||||||
|
)
|
||||||
|
print(
|
||||||
|
f"alchemy.elements.create_earth(): {alchemy.elements.create_earth()}"
|
||||||
|
)
|
||||||
|
print(f"alchemy.elements.create_air(): {alchemy.elements.create_air()}")
|
||||||
|
print("\nTesting package-level access (controlled by __init__.py):")
|
||||||
|
print(f"alchemy.create_fire(): {alchemy.create_fire()}")
|
||||||
|
print(f"alchemy.create_water(): {alchemy.create_water()}")
|
||||||
|
|
||||||
|
print("alchemy.create_earth(): ", end="")
|
||||||
|
try:
|
||||||
|
print(f"{alchemy.create_earth()}")
|
||||||
|
except AttributeError:
|
||||||
|
print("AttributeError - not exposed")
|
||||||
|
|
||||||
|
print("alchemy.create_air(): ", end="")
|
||||||
|
try:
|
||||||
|
print(f"{alchemy.create_air()}")
|
||||||
|
except AttributeError:
|
||||||
|
print("AttributeError - not exposed")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
19
07/ex0/Card.py
Normal file
19
07/ex0/Card.py
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
from abc import ABC, abstractmethod
|
||||||
|
|
||||||
|
|
||||||
|
class Card(ABC):
|
||||||
|
def __init__(self, name: str, cost: int, rarity: str) -> None:
|
||||||
|
self.name = name
|
||||||
|
self.cost = cost
|
||||||
|
self.rarity = rarity
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def play(self, game_state: dict) -> dict:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def get_card_info(self) -> dict:
|
||||||
|
res = dict(self.__dict__)
|
||||||
|
return res
|
||||||
|
|
||||||
|
def is_playable(self, available_mana: int) -> bool:
|
||||||
|
return available_mana > 5
|
||||||
32
07/ex0/CreatureCard.py
Normal file
32
07/ex0/CreatureCard.py
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
from .Card import Card
|
||||||
|
from typing import Dict, Union
|
||||||
|
|
||||||
|
|
||||||
|
class CreatureCard(Card):
|
||||||
|
def __init__(
|
||||||
|
self, name: str, cost: int, rarity: str, attack: int, health: int
|
||||||
|
) -> None:
|
||||||
|
super().__init__(name, cost, rarity)
|
||||||
|
self.attack = attack
|
||||||
|
self.health = health
|
||||||
|
|
||||||
|
def play(self, game_state: dict) -> dict:
|
||||||
|
try:
|
||||||
|
res: dict[str, Union[int, str]] = {}
|
||||||
|
if game_state["mana"] < 5:
|
||||||
|
raise Exception("Not enough mana")
|
||||||
|
res["card_played"] = self.name
|
||||||
|
res["mana_used"] = 5
|
||||||
|
res["effect"] = "Creature summoned to battlefield"
|
||||||
|
return res
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def attack_target(self, target: str) -> dict:
|
||||||
|
res: Dict[str, Union[int, str, bool]] = {}
|
||||||
|
res["attacker"] = self.name
|
||||||
|
res["target"] = target
|
||||||
|
res["damage_dealt"] = self.attack
|
||||||
|
res["combat_resolved"] = True
|
||||||
|
return res
|
||||||
6
07/ex0/__init__.py
Normal file
6
07/ex0/__init__.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
from .Card import Card
|
||||||
|
from .CreatureCard import CreatureCard
|
||||||
|
|
||||||
|
__version__ = "1.0.0"
|
||||||
|
__author__ = "moi"
|
||||||
|
__all__ = ["Card", "CreatureCard"]
|
||||||
22
07/ex0/main.py
Normal file
22
07/ex0/main.py
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
def main() -> None:
|
||||||
|
from .CreatureCard import CreatureCard
|
||||||
|
|
||||||
|
game_state = {"player": "michel", "mana": 6}
|
||||||
|
print("=== DataDeck Card Foundation ===\n")
|
||||||
|
print("Testing Abstract Base Class Design:\n")
|
||||||
|
creature_card = CreatureCard("Fire Dragon", 5, "Legendary", 7, 5)
|
||||||
|
print(f"CreatureCard info:\n{creature_card.get_card_info()}")
|
||||||
|
print("\nPlaying Fire Dragon with 6 mana available:")
|
||||||
|
playable = creature_card.is_playable(game_state["mana"])
|
||||||
|
print(f"Playable: {playable}")
|
||||||
|
if playable:
|
||||||
|
print(f"Play result: {creature_card.play(game_state)}")
|
||||||
|
print("\nFire Dragon attacks Goblin Warrior:")
|
||||||
|
print(f"Attack result: {creature_card.attack_target('Goblin Warrior')}")
|
||||||
|
print("\nTesting insufficient mana (3 available):")
|
||||||
|
print(f"Playable: {creature_card.is_playable(3)}")
|
||||||
|
print("\nAbstract pattern successfully demonstrated!")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
34
07/ex1/ArtifactCard.py
Normal file
34
07/ex1/ArtifactCard.py
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
from ex0 import Card
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
|
|
||||||
|
class ArtifactCard(Card):
|
||||||
|
def __init__(
|
||||||
|
self, name: str, cost: int, rarity: str, durability: int, effect: str
|
||||||
|
) -> None:
|
||||||
|
super().__init__(name, cost, rarity)
|
||||||
|
self.durability = durability
|
||||||
|
self.effect = effect
|
||||||
|
|
||||||
|
def play(self, game_state: dict) -> dict:
|
||||||
|
try:
|
||||||
|
res: dict[str, Union[int, str]] = {}
|
||||||
|
if game_state["mana"] < 2:
|
||||||
|
raise Exception("Not enough mana")
|
||||||
|
res["card_played"] = self.name
|
||||||
|
res["mana_used"] = 2
|
||||||
|
res["effect"] = self.effect
|
||||||
|
return res
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def activate_ability(self) -> dict:
|
||||||
|
if self.durability <= 0:
|
||||||
|
return {
|
||||||
|
"name": self.name,
|
||||||
|
"durability": self.durability,
|
||||||
|
"destroyed": True,
|
||||||
|
}
|
||||||
|
self.durability -= 1
|
||||||
|
return self.get_card_info()
|
||||||
49
07/ex1/Deck.py
Normal file
49
07/ex1/Deck.py
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
from ex0 import Card, CreatureCard
|
||||||
|
|
||||||
|
|
||||||
|
class Deck:
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.cards: list[Card] = []
|
||||||
|
|
||||||
|
def add_card(self, card: Card) -> None:
|
||||||
|
self.cards += [card]
|
||||||
|
|
||||||
|
def remove_card(self, card_name: Card) -> None:
|
||||||
|
for n in range(len(self.cards)):
|
||||||
|
if self.cards[n].name == card_name:
|
||||||
|
self.cards.pop(n)
|
||||||
|
return
|
||||||
|
print("{card_name} not found")
|
||||||
|
|
||||||
|
def shuffle(self) -> None:
|
||||||
|
from random import shuffle
|
||||||
|
|
||||||
|
shuffle(self.cards)
|
||||||
|
|
||||||
|
def draw_card(self) -> Card:
|
||||||
|
self.shuffle()
|
||||||
|
return self.cards.pop()
|
||||||
|
|
||||||
|
def get_deck_stats(self) -> dict:
|
||||||
|
from .ArtifactCard import ArtifactCard
|
||||||
|
from .SpellCard import SpellCard
|
||||||
|
|
||||||
|
creatures = 0
|
||||||
|
spells = 0
|
||||||
|
artifacts = 0
|
||||||
|
total_cost = 0.0
|
||||||
|
for card in self.cards:
|
||||||
|
if isinstance(card, CreatureCard):
|
||||||
|
creatures += 1
|
||||||
|
elif isinstance(card, ArtifactCard):
|
||||||
|
artifacts += 1
|
||||||
|
elif isinstance(card, SpellCard):
|
||||||
|
spells += 1
|
||||||
|
total_cost += card.cost
|
||||||
|
return {
|
||||||
|
"total_card": len(self.cards),
|
||||||
|
"creatures": creatures,
|
||||||
|
"spells": spells,
|
||||||
|
"artifacts": artifacts,
|
||||||
|
"avg_cost": total_cost / len(self.cards),
|
||||||
|
}
|
||||||
27
07/ex1/SpellCard.py
Normal file
27
07/ex1/SpellCard.py
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
from ex0 import Card
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
|
|
||||||
|
class SpellCard(Card):
|
||||||
|
def __init__(
|
||||||
|
self, name: str, cost: int, rarity: str, effect_type: str, mana: int
|
||||||
|
) -> None:
|
||||||
|
super().__init__(name, cost, rarity)
|
||||||
|
self.effect_type = effect_type
|
||||||
|
self.mana = mana
|
||||||
|
|
||||||
|
def play(self, game_state: dict) -> dict:
|
||||||
|
try:
|
||||||
|
res: dict[str, Union[int, str]] = {}
|
||||||
|
if game_state["mana"] < 3:
|
||||||
|
raise Exception("Not enough mana")
|
||||||
|
res["card_played"] = self.name
|
||||||
|
res["mana_used"] = 3
|
||||||
|
res["effect"] = self.effect_type
|
||||||
|
return res
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def resolve_effect(self, targets: list) -> dict:
|
||||||
|
return {"card": self.name, "targets": targets, "resolved": True}
|
||||||
7
07/ex1/__init__.py
Normal file
7
07/ex1/__init__.py
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
from .ArtifactCard import ArtifactCard
|
||||||
|
from .SpellCard import SpellCard
|
||||||
|
from .Deck import Deck
|
||||||
|
|
||||||
|
__version__ = "1.0.0"
|
||||||
|
__author__ = "David GAILLETON"
|
||||||
|
__all__ = ["ArtifactCard", "Deck", "SpellCard"]
|
||||||
32
07/ex1/main.py
Normal file
32
07/ex1/main.py
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
def main() -> None:
|
||||||
|
from .Deck import Deck
|
||||||
|
from .SpellCard import SpellCard
|
||||||
|
from .ArtifactCard import ArtifactCard
|
||||||
|
from ex0 import CreatureCard
|
||||||
|
|
||||||
|
print("=== DataDeck Deck Builder ===\n")
|
||||||
|
deck = Deck()
|
||||||
|
print("Building deck with different card types...")
|
||||||
|
deck.add_card(
|
||||||
|
SpellCard("Lightning Bolt", 5, "Common", "Deal 3 dammage to target", 5)
|
||||||
|
)
|
||||||
|
deck.add_card(
|
||||||
|
ArtifactCard(
|
||||||
|
"Mana Crystal", 7, "Medium", 1, "Permanent: +1 mana per turn"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
deck.add_card(CreatureCard("Fire dragon", 10, "Rare", 15, 20))
|
||||||
|
print(f"Deck stats: {deck.get_deck_stats()}")
|
||||||
|
print("\nDrawing and playing cards:\n")
|
||||||
|
for _ in range(deck.get_deck_stats()["total_card"]):
|
||||||
|
try:
|
||||||
|
card = deck.draw_card()
|
||||||
|
print(f"Drew: {card.name} ({card.__class__.__name__})")
|
||||||
|
print(f"{card.play({'mana': 5})}\n")
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
print("Polymorphism in action: Same interface, different card behaviors!")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
12
07/ex2/Combatable.py
Normal file
12
07/ex2/Combatable.py
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
from abc import ABC, abstractmethod
|
||||||
|
|
||||||
|
|
||||||
|
class Combatable(ABC):
|
||||||
|
@abstractmethod
|
||||||
|
def attack(self, target: str) -> dict: ...
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def defend(self, incoming_damage: int) -> dict: ...
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def get_combate_stats(self) -> dict: ...
|
||||||
87
07/ex2/EliteCard.py
Normal file
87
07/ex2/EliteCard.py
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
from ex0.Card import Card
|
||||||
|
from .Combatable import Combatable
|
||||||
|
from .Magical import Magical
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
|
|
||||||
|
class EliteCard(Card, Combatable, Magical):
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
name: str,
|
||||||
|
cost: int,
|
||||||
|
rarity: str,
|
||||||
|
damage: int,
|
||||||
|
health: int,
|
||||||
|
shield: int,
|
||||||
|
initial_mana: int,
|
||||||
|
spell_cost: int,
|
||||||
|
) -> None:
|
||||||
|
super().__init__(name, cost, rarity)
|
||||||
|
self.damage = damage
|
||||||
|
self.health = health
|
||||||
|
self.shield = shield
|
||||||
|
self.mana = initial_mana
|
||||||
|
self.spell_cost = spell_cost
|
||||||
|
|
||||||
|
def play(self, game_state: dict) -> dict:
|
||||||
|
try:
|
||||||
|
res: dict[str, int | str] = {}
|
||||||
|
if game_state["mana"] < 5:
|
||||||
|
raise Exception("Not enough mana")
|
||||||
|
res["card_played"] = self.name
|
||||||
|
res["mana_used"] = 5
|
||||||
|
res["effect"] = "Creature summoned to battlefield"
|
||||||
|
return res
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def attack(self, target: str) -> dict:
|
||||||
|
return {
|
||||||
|
"attacker": self.name,
|
||||||
|
"target": target,
|
||||||
|
"damage_dealt": self.damage,
|
||||||
|
"combat_type": "melee",
|
||||||
|
}
|
||||||
|
|
||||||
|
def defend(self, incoming_damage: int) -> dict:
|
||||||
|
res: dict[str, Union[str, int, bool]] = {}
|
||||||
|
res["defender"] = self.name
|
||||||
|
if incoming_damage <= self.shield:
|
||||||
|
res["damage_blocked"] = incoming_damage
|
||||||
|
res["damage_taken"] = 0
|
||||||
|
else:
|
||||||
|
res["damage_taken"] = incoming_damage - self.shield
|
||||||
|
res["damage_blocked"] = self.shield
|
||||||
|
self.health -= incoming_damage - self.shield
|
||||||
|
res["still_alive"] = self.health > 0
|
||||||
|
return res
|
||||||
|
|
||||||
|
def get_combate_stats(self) -> dict:
|
||||||
|
return {
|
||||||
|
"damage": self.damage,
|
||||||
|
"health": self.health,
|
||||||
|
"shield": self.shield,
|
||||||
|
}
|
||||||
|
|
||||||
|
def cast_spell(self, spell_name: str, targets: list) -> dict:
|
||||||
|
try:
|
||||||
|
if self.mana < self.spell_cost:
|
||||||
|
raise Exception("Not enough mana")
|
||||||
|
self.mana -= self.spell_cost
|
||||||
|
return {
|
||||||
|
"caster": self.name,
|
||||||
|
"spell": spell_name,
|
||||||
|
"targets": targets,
|
||||||
|
"mana_used": self.spell_cost,
|
||||||
|
}
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def channel_mana(self, amount: int) -> dict:
|
||||||
|
self.mana += amount
|
||||||
|
return {"channeled": amount, "total_mana": self.mana}
|
||||||
|
|
||||||
|
def get_magic_stats(self) -> dict:
|
||||||
|
return {"mana": self.mana, "spell cost": self.spell_cost}
|
||||||
12
07/ex2/Magical.py
Normal file
12
07/ex2/Magical.py
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
from abc import ABC, abstractmethod
|
||||||
|
|
||||||
|
|
||||||
|
class Magical(ABC):
|
||||||
|
@abstractmethod
|
||||||
|
def cast_spell(self, spell_name: str, targets: list) -> dict: ...
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def channel_mana(self, amount: int) -> dict: ...
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def get_magic_stats(self) -> dict: ...
|
||||||
7
07/ex2/__init__.py
Normal file
7
07/ex2/__init__.py
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
from .Combatable import Combatable
|
||||||
|
from .Magical import Magical
|
||||||
|
from .EliteCard import EliteCard
|
||||||
|
|
||||||
|
__version__ = "1.0.0"
|
||||||
|
__author__ = "dgaillet"
|
||||||
|
__all__ = ["Combatable", "Magical", "EliteCard"]
|
||||||
21
07/ex2/main.py
Normal file
21
07/ex2/main.py
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
def main() -> None:
|
||||||
|
from .EliteCard import EliteCard
|
||||||
|
|
||||||
|
print("=== DataDeck Ability System ===\n")
|
||||||
|
card = EliteCard("Arcane Warrior", 25, "Legendary", 5, 20, 3, 4, 4)
|
||||||
|
print("EliteCard capabilities:")
|
||||||
|
print("- Card: ['play', 'get_card_info', 'is_playable']")
|
||||||
|
print("- Combatable: ['attack', 'defend', 'get_combat_stats']")
|
||||||
|
print("- Magical: ['cast_spell', 'channel_mana', 'get_magic_stats']")
|
||||||
|
print("\nPlaying Arcane Warrior (Elite Card):\n")
|
||||||
|
print("Combat phase:")
|
||||||
|
print(f"Attack result: {card.attack('Enemy')}")
|
||||||
|
print(f"Defense result: {card.defend(5)}")
|
||||||
|
print("\nMagic phase:")
|
||||||
|
print(f"Spell cast: {card.cast_spell('Fireball', ['Enemy1', 'Enemy2'])}")
|
||||||
|
print(f"Mana channel: {card.channel_mana(3)}")
|
||||||
|
print("Multiple interface implementation successful!")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
22
07/ex3/AggresiveStrategy.py
Normal file
22
07/ex3/AggresiveStrategy.py
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
from .GameStrategy import GameStrategy
|
||||||
|
from operator import attrgetter
|
||||||
|
|
||||||
|
|
||||||
|
class AgressiveStrategy(GameStrategy):
|
||||||
|
def execute_turn(self, hand: list, battlefield: list) -> dict:
|
||||||
|
return {
|
||||||
|
"cards_played": [card.name for card in hand],
|
||||||
|
"mana_used": 5,
|
||||||
|
"targets_attacked": battlefield,
|
||||||
|
"damage_dealt": 8,
|
||||||
|
}
|
||||||
|
|
||||||
|
def get_strategy_name(self) -> str:
|
||||||
|
return "Aggressive"
|
||||||
|
|
||||||
|
def prioritize_targets(self, available_targets: list) -> list:
|
||||||
|
try:
|
||||||
|
return sorted(available_targets, key=attrgetter("health"))
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
return available_targets
|
||||||
23
07/ex3/CardFactory.py
Normal file
23
07/ex3/CardFactory.py
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
from abc import ABC, abstractmethod
|
||||||
|
from ex0 import Card
|
||||||
|
|
||||||
|
|
||||||
|
class CardFactory(ABC):
|
||||||
|
@abstractmethod
|
||||||
|
def create_creature(
|
||||||
|
self, name_or_power: str | int | None = None
|
||||||
|
) -> Card: ...
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def create_spell(self, name_or_power: str | int | None = None) -> Card: ...
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def create_artifact(
|
||||||
|
self, name_or_power: str | int | None = None
|
||||||
|
) -> Card: ...
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def create_themed_deck(self, size: int) -> dict: ...
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def get_supported_types(self) -> dict: ...
|
||||||
76
07/ex3/FantasyCardFactory.py
Normal file
76
07/ex3/FantasyCardFactory.py
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
from .CardFactory import CardFactory
|
||||||
|
from random import choice
|
||||||
|
from ex0 import Card, CreatureCard
|
||||||
|
from ex1 import SpellCard, ArtifactCard
|
||||||
|
from copy import deepcopy
|
||||||
|
|
||||||
|
creature_cards = [
|
||||||
|
CreatureCard("Fire Dragon", 20, "Rare", 7, 20),
|
||||||
|
CreatureCard("Goblin Warrior", 12, "Common", 4, 10),
|
||||||
|
]
|
||||||
|
|
||||||
|
spell_cards = [
|
||||||
|
SpellCard("Fire Ball", 5, "Rare", "Decrase health by 1 for 3 round", 5),
|
||||||
|
SpellCard("Ice Spike", 3, "Common", "Reduce damage by 2 for 1 round", 3),
|
||||||
|
SpellCard(
|
||||||
|
"Lightning bolt", 10, "Legendary", "Card can't play for 3 round", 10
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
artifact_cards = [
|
||||||
|
ArtifactCard(
|
||||||
|
"Mana Ring", 2, "Common", 3, "Increase mana by 1 for each round"
|
||||||
|
),
|
||||||
|
ArtifactCard(
|
||||||
|
"Witch Staff", 6, "Legendary", 5, "Decrease 5 mana of a card"
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class FantasyCardFactory(CardFactory):
|
||||||
|
def create_creature(self, name_or_power: str | int | None = None) -> Card:
|
||||||
|
card = deepcopy(choice(creature_cards))
|
||||||
|
if isinstance(name_or_power, str):
|
||||||
|
card.name = name_or_power
|
||||||
|
elif isinstance(name_or_power, int):
|
||||||
|
card.attack = name_or_power
|
||||||
|
return card
|
||||||
|
|
||||||
|
def create_spell(self, name_or_power: str | int | None = None) -> Card:
|
||||||
|
card = deepcopy(choice(spell_cards))
|
||||||
|
if isinstance(name_or_power, str):
|
||||||
|
card.name = name_or_power
|
||||||
|
elif isinstance(name_or_power, int):
|
||||||
|
card.mana = name_or_power
|
||||||
|
return card
|
||||||
|
|
||||||
|
def create_artifact(self, name_or_power: str | int | None = None) -> Card:
|
||||||
|
card = deepcopy(choice(artifact_cards))
|
||||||
|
if isinstance(name_or_power, str):
|
||||||
|
card.name = name_or_power
|
||||||
|
elif isinstance(name_or_power, int):
|
||||||
|
card.durability = name_or_power
|
||||||
|
return card
|
||||||
|
|
||||||
|
def create_themed_deck(self, size: int) -> dict:
|
||||||
|
deck: dict[str, list[Card]] = {}
|
||||||
|
for _ in range(size):
|
||||||
|
card = choice(
|
||||||
|
[
|
||||||
|
self.create_creature(),
|
||||||
|
self.create_artifact(),
|
||||||
|
self.create_spell(),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
if card.name in deck:
|
||||||
|
deck[card.name] += [card]
|
||||||
|
else:
|
||||||
|
deck[card.name] = [card]
|
||||||
|
return deck
|
||||||
|
|
||||||
|
def get_supported_types(self) -> dict:
|
||||||
|
return {
|
||||||
|
"creatures": [card.name for card in creature_cards],
|
||||||
|
"spells": [card.name for card in spell_cards],
|
||||||
|
"artifacts": [card.name for card in artifact_cards],
|
||||||
|
}
|
||||||
41
07/ex3/GameEngine.py
Normal file
41
07/ex3/GameEngine.py
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
from .CardFactory import CardFactory
|
||||||
|
from .GameStrategy import GameStrategy
|
||||||
|
|
||||||
|
|
||||||
|
class GameEngine:
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.turns_simulated = 0
|
||||||
|
self.total_damage = 0
|
||||||
|
self.created_cards = 0
|
||||||
|
|
||||||
|
def configure_engine(
|
||||||
|
self, factory: CardFactory, strategy: GameStrategy
|
||||||
|
) -> None:
|
||||||
|
self.factory = factory
|
||||||
|
self.strategy = strategy
|
||||||
|
|
||||||
|
def simulate_turn(self) -> dict:
|
||||||
|
try:
|
||||||
|
cards = []
|
||||||
|
deck = self.factory.create_themed_deck(3).values()
|
||||||
|
for card_list in deck:
|
||||||
|
for card in card_list:
|
||||||
|
cards += [card]
|
||||||
|
hand = [f"{card.name} ({card.cost})" for card in cards]
|
||||||
|
print(f"Hand: {hand}")
|
||||||
|
turn = self.strategy.execute_turn(cards, ["Enemy player"])
|
||||||
|
self.total_damage += turn["damage_dealt"]
|
||||||
|
self.created_cards += 3
|
||||||
|
self.turns_simulated += 1
|
||||||
|
return turn
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def get_engine_status(self) -> dict:
|
||||||
|
return {
|
||||||
|
"turns_simulated": self.turns_simulated,
|
||||||
|
"strategy_used": self.strategy.get_strategy_name(),
|
||||||
|
"total_damage": self.total_damage,
|
||||||
|
"cards_created": self.created_cards,
|
||||||
|
}
|
||||||
12
07/ex3/GameStrategy.py
Normal file
12
07/ex3/GameStrategy.py
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
from abc import ABC, abstractmethod
|
||||||
|
|
||||||
|
|
||||||
|
class GameStrategy(ABC):
|
||||||
|
@abstractmethod
|
||||||
|
def execute_turn(self, hand: list, battlefield: list) -> dict: ...
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def get_strategy_name(self) -> str: ...
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def prioritize_targets(self, available_targets: list) -> list: ...
|
||||||
15
07/ex3/__init__.py
Normal file
15
07/ex3/__init__.py
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
from .AggresiveStrategy import AgressiveStrategy
|
||||||
|
from .CardFactory import CardFactory
|
||||||
|
from .FantasyCardFactory import FantasyCardFactory
|
||||||
|
from .GameEngine import GameEngine
|
||||||
|
from .GameStrategy import GameStrategy
|
||||||
|
|
||||||
|
__version__ = "1.0.0"
|
||||||
|
__author__ = "dgaillet"
|
||||||
|
__all__ = [
|
||||||
|
"AgressiveStrategy",
|
||||||
|
"CardFactory",
|
||||||
|
"FantasyCardFactory",
|
||||||
|
"GameEngine",
|
||||||
|
"GameStrategy",
|
||||||
|
]
|
||||||
27
07/ex3/main.py
Normal file
27
07/ex3/main.py
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
from .GameEngine import GameEngine
|
||||||
|
from .FantasyCardFactory import FantasyCardFactory
|
||||||
|
from .AggresiveStrategy import AgressiveStrategy
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
print("=== DataDeck Game Engine ===\n")
|
||||||
|
print("Configuring Fantasy Card Game...")
|
||||||
|
engine = GameEngine()
|
||||||
|
engine.configure_engine(FantasyCardFactory(), AgressiveStrategy())
|
||||||
|
print(f"Factory: {engine.factory.__class__.__name__}")
|
||||||
|
print(f"Strategy: {engine.strategy.__class__.__name__}")
|
||||||
|
print(f"Available types: {engine.factory.get_supported_types()}")
|
||||||
|
print("\nSimulating aggressive turn...")
|
||||||
|
actions = engine.simulate_turn()
|
||||||
|
print("\nTurn execution:")
|
||||||
|
print(f"Strategy: {engine.strategy.get_strategy_name()}")
|
||||||
|
print(f"Actions: {actions}")
|
||||||
|
print("\nGame Report:")
|
||||||
|
print(f"{engine.get_engine_status()}")
|
||||||
|
print(
|
||||||
|
"\nAbstract Factory + Strategy Pattern: Maximum flexibility achieved!"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
15
07/ex4/Rankable.py
Normal file
15
07/ex4/Rankable.py
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
from abc import ABC, abstractmethod
|
||||||
|
|
||||||
|
|
||||||
|
class Rankable(ABC):
|
||||||
|
@abstractmethod
|
||||||
|
def calculate_rating(self) -> int: ...
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def update_wins(self, wins: int) -> None: ...
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def update_losses(self, losses: int) -> None: ...
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def get_rank_info(self) -> dict: ...
|
||||||
97
07/ex4/TournamentCard.py
Normal file
97
07/ex4/TournamentCard.py
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
from ex0 import Card
|
||||||
|
from ex2 import Combatable
|
||||||
|
from .Rankable import Rankable
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
|
|
||||||
|
class TournamentCard(Card, Combatable, Rankable):
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
id: str,
|
||||||
|
name: str,
|
||||||
|
cost: int,
|
||||||
|
rarity: str,
|
||||||
|
damage: int,
|
||||||
|
health: int,
|
||||||
|
shield: int,
|
||||||
|
rank: int,
|
||||||
|
) -> None:
|
||||||
|
super().__init__(name, cost, rarity)
|
||||||
|
self.id = id
|
||||||
|
self.looses = 0
|
||||||
|
self.wins = 0
|
||||||
|
self.damage = damage
|
||||||
|
self.health = health
|
||||||
|
self.shield = shield
|
||||||
|
self.rank = rank
|
||||||
|
|
||||||
|
def play(self, game_state: dict) -> dict:
|
||||||
|
try:
|
||||||
|
res: dict[str, int | str] = {}
|
||||||
|
if game_state["mana"] < 2:
|
||||||
|
raise Exception("Not enough mana")
|
||||||
|
res["card_played"] = self.name
|
||||||
|
res["mana_used"] = 2
|
||||||
|
return res
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def attack(self, target: str) -> dict:
|
||||||
|
return {
|
||||||
|
"attacker": self.name,
|
||||||
|
"target": target,
|
||||||
|
"damage_dealt": self.damage,
|
||||||
|
"combat_type": "melee",
|
||||||
|
}
|
||||||
|
|
||||||
|
def defend(self, incoming_damage: int) -> dict:
|
||||||
|
res: dict[str, Union[str, int, bool]] = {}
|
||||||
|
res["defender"] = self.name
|
||||||
|
if incoming_damage <= self.shield:
|
||||||
|
res["damage_blocked"] = incoming_damage
|
||||||
|
res["damage_taken"] = 0
|
||||||
|
else:
|
||||||
|
res["damage_taken"] = incoming_damage - self.shield
|
||||||
|
res["damage_blocked"] = self.shield
|
||||||
|
self.health -= incoming_damage - self.shield
|
||||||
|
res["still_alive"] = self.health > 0
|
||||||
|
return res
|
||||||
|
|
||||||
|
def get_combate_stats(self) -> dict:
|
||||||
|
return {
|
||||||
|
"damage": self.damage,
|
||||||
|
"health": self.health,
|
||||||
|
"shield": self.shield,
|
||||||
|
}
|
||||||
|
|
||||||
|
def calculate_rating(self) -> int:
|
||||||
|
try:
|
||||||
|
if self.wins == 0:
|
||||||
|
return self.rank - self.looses * 10
|
||||||
|
return self.rank + (int(self.wins / self.looses) * 10)
|
||||||
|
except ZeroDivisionError:
|
||||||
|
return self.rank + self.wins * 10
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
return self.rank
|
||||||
|
|
||||||
|
def get_tournament_stats(self) -> dict:
|
||||||
|
return {
|
||||||
|
"Interfaces": "[Card, Combatable, Rankable]",
|
||||||
|
"Rating": self.calculate_rating(),
|
||||||
|
"Record": f"{self.wins}-{self.looses}",
|
||||||
|
}
|
||||||
|
|
||||||
|
def update_wins(self, wins: int) -> None:
|
||||||
|
self.wins = wins
|
||||||
|
|
||||||
|
def update_losses(self, losses: int) -> None:
|
||||||
|
self.looses = losses
|
||||||
|
|
||||||
|
def get_rank_info(self) -> dict:
|
||||||
|
return {
|
||||||
|
"wins": self.wins,
|
||||||
|
"looses": self.looses,
|
||||||
|
"rank": self.rank,
|
||||||
|
}
|
||||||
65
07/ex4/TournamentPlatform.py
Normal file
65
07/ex4/TournamentPlatform.py
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
from .TournamentCard import TournamentCard
|
||||||
|
|
||||||
|
|
||||||
|
class TournamentPlatform:
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.cards: list[TournamentCard] = []
|
||||||
|
self.math_played = 0
|
||||||
|
|
||||||
|
def register_card(self, card: TournamentCard) -> str:
|
||||||
|
try:
|
||||||
|
stats = card.get_tournament_stats()
|
||||||
|
res = f"{card.name} (ID: {card.id}):\n\
|
||||||
|
- Interfaces: {stats['Interfaces']}\n\
|
||||||
|
- Rating: {stats['Rating']}\n\
|
||||||
|
- Record: {stats['Record']}\n"
|
||||||
|
self.cards += [card]
|
||||||
|
return res
|
||||||
|
except Exception:
|
||||||
|
print("Invalid card")
|
||||||
|
return "error"
|
||||||
|
|
||||||
|
def create_match(self, card1_id: str, card2_id: str) -> dict:
|
||||||
|
from random import shuffle
|
||||||
|
|
||||||
|
try:
|
||||||
|
cards = [
|
||||||
|
card
|
||||||
|
for card in self.cards
|
||||||
|
if card.id == card1_id or card.id == card2_id
|
||||||
|
]
|
||||||
|
if len(cards) != 2:
|
||||||
|
raise Exception(
|
||||||
|
"At least once of cards id provide isn't in platform"
|
||||||
|
)
|
||||||
|
shuffle(cards)
|
||||||
|
winner = cards.pop()
|
||||||
|
loser = cards.pop()
|
||||||
|
winner.update_wins(winner.wins + 1)
|
||||||
|
loser.update_losses(loser.looses + 1)
|
||||||
|
self.math_played += 1
|
||||||
|
return {
|
||||||
|
"winner": winner.id,
|
||||||
|
"loser": loser.id,
|
||||||
|
"winner_rating": winner.calculate_rating(),
|
||||||
|
"loser_rating": loser.calculate_rating(),
|
||||||
|
}
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def get_leaderboard(self) -> list:
|
||||||
|
return sorted(
|
||||||
|
self.cards, key=lambda x: x.calculate_rating(), reverse=True
|
||||||
|
)
|
||||||
|
|
||||||
|
def generate_tournament_report(self) -> dict:
|
||||||
|
return {
|
||||||
|
"total_cards": len(self.cards),
|
||||||
|
"mathes_played": self.math_played,
|
||||||
|
"avg_rating": int(
|
||||||
|
sum([card.calculate_rating() for card in self.cards])
|
||||||
|
/ len(self.cards)
|
||||||
|
),
|
||||||
|
"platform_status": "active",
|
||||||
|
}
|
||||||
7
07/ex4/__init__.py
Normal file
7
07/ex4/__init__.py
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
from .Rankable import Rankable
|
||||||
|
from .TournamentCard import TournamentCard
|
||||||
|
from .TournamentPlatform import TournamentPlatform
|
||||||
|
|
||||||
|
__version__ = "1.0.0"
|
||||||
|
__author__ = "dgaillet"
|
||||||
|
__all__ = ["Rankable", "TournamentCard", "TournamentPlatform"]
|
||||||
39
07/ex4/main.py
Normal file
39
07/ex4/main.py
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
from .TournamentCard import TournamentCard
|
||||||
|
from .TournamentPlatform import TournamentPlatform
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
print("=== DataDeck Tournament Platform ===\n")
|
||||||
|
print("Registering Tournament Cards...\n")
|
||||||
|
platform = TournamentPlatform()
|
||||||
|
print(
|
||||||
|
platform.register_card(
|
||||||
|
TournamentCard(
|
||||||
|
"dragon_001", "Fire Dragon", 20, "Rare", 15, 25, 5, 1200
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
print(
|
||||||
|
platform.register_card(
|
||||||
|
TournamentCard(
|
||||||
|
"wizard_001", "Ice Wizard", 15, "common", 10, 30, 4, 1150
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
print("Creating tournament match...")
|
||||||
|
match_res = platform.create_match("dragon_001", "wizard_001")
|
||||||
|
print(f"Math result: {match_res}\n")
|
||||||
|
print("Tournament Leaderboard:")
|
||||||
|
leaderboard = platform.get_leaderboard()
|
||||||
|
for i in range(len(leaderboard)):
|
||||||
|
print(f"{i + 1}. {leaderboard[i].name} - Rating:\
|
||||||
|
{leaderboard[i].calculate_rating()}\
|
||||||
|
({leaderboard[i].get_tournament_stats()['Record']})")
|
||||||
|
print("\nPlatform Report:")
|
||||||
|
print(platform.generate_tournament_report())
|
||||||
|
print("\n=== Tournament Platform Successfully Deployed! ===")
|
||||||
|
print("All abstract patterns working together harmoniously!")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
41
08/ex0/construct.py
Normal file
41
08/ex0/construct.py
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import site
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
def not_in_venv() -> None:
|
||||||
|
print("\nMATRIX STATUS: You're still plugged in\n")
|
||||||
|
print(f"Current Python: {sys.executable}")
|
||||||
|
print("Virtual Environment: None detected\n")
|
||||||
|
print("WARNING: You're in the global environment!\n\
|
||||||
|
The machines can see everything you install.\n")
|
||||||
|
print("To enter the construct, run:\n\
|
||||||
|
python -m venv matrix_env\n\
|
||||||
|
source matrix_env/bin/activate # On Unix\n\
|
||||||
|
matrix_env\n\
|
||||||
|
Scripts\n\
|
||||||
|
activate # On Windows\n")
|
||||||
|
print("Then run this program again.")
|
||||||
|
|
||||||
|
|
||||||
|
def in_venv() -> None:
|
||||||
|
print("\nMATRIX STATUS: Welcome to the construct\n")
|
||||||
|
print(f"Current Python: {sys.executable}")
|
||||||
|
print(f"Virtual Environment: {sys.prefix.split('/')[-1]}")
|
||||||
|
print(f"Environment Path: {sys.prefix}")
|
||||||
|
print("\nSUCCESS: You're in an isolated environment!\n\
|
||||||
|
Safe to install packages without affecting\n\
|
||||||
|
the global system.\n")
|
||||||
|
print("Package installation path:")
|
||||||
|
print(site.getsitepackages()[0])
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
if "VIRTUAL_ENV" in os.environ:
|
||||||
|
in_venv()
|
||||||
|
else:
|
||||||
|
not_in_venv()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
60
08/ex1/loading.py
Normal file
60
08/ex1/loading.py
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
from importlib.metadata import PackageNotFoundError, version
|
||||||
|
from numpy import ndarray
|
||||||
|
from pandas import pandas as pd
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
from os import mkdir
|
||||||
|
|
||||||
|
|
||||||
|
def check_package(packages: dict[str, str]) -> bool:
|
||||||
|
print("Checking dependencies:")
|
||||||
|
imported = 0
|
||||||
|
for package in packages:
|
||||||
|
try:
|
||||||
|
print(f"[\u001b[32mOK\u001b[0m] {package}\
|
||||||
|
({version(package)}) - {packages[package]} ready")
|
||||||
|
imported += 1
|
||||||
|
except PackageNotFoundError:
|
||||||
|
print(f"[\u001b[31mKO\u001b[0m] {package} -\
|
||||||
|
{packages[package]} not ready")
|
||||||
|
return imported == len(packages)
|
||||||
|
|
||||||
|
|
||||||
|
def analyze(data: ndarray) -> None:
|
||||||
|
print("Processing 1000 data points...")
|
||||||
|
x = data[:, 0]
|
||||||
|
y = data[:, 1].astype(float)
|
||||||
|
plt.figure(figsize=(8, 8), dpi=1200)
|
||||||
|
plt.plot(x, y)
|
||||||
|
try:
|
||||||
|
mkdir("matrix")
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
print("Generating visualization...\n")
|
||||||
|
plt.savefig("matrix/_analysis.png")
|
||||||
|
print("Analysis complete!")
|
||||||
|
print("Results saved to: matrix/_analysis.png}")
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
print("\nLOADING STATUS: Loading programs...\n")
|
||||||
|
if check_package(
|
||||||
|
{
|
||||||
|
"pandas": "Data manipulation",
|
||||||
|
"numpy": "mathematics manipulation",
|
||||||
|
"matplotlib": "Visualization",
|
||||||
|
}
|
||||||
|
):
|
||||||
|
try:
|
||||||
|
print("\nAnalyzing Matrix data...")
|
||||||
|
data = pd.read_csv("meteo.csv", parse_dates=["time"]).to_numpy()
|
||||||
|
analyze(data)
|
||||||
|
except FileNotFoundError:
|
||||||
|
print("File not found")
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
else:
|
||||||
|
print("\nPackages not installed")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
BIN
08/ex1/matrix/_analysis.png
Normal file
BIN
08/ex1/matrix/_analysis.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 MiB |
193
08/ex1/meteo.csv
Normal file
193
08/ex1/meteo.csv
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
time,temperature
|
||||||
|
2026-02-28T00:00,9.7
|
||||||
|
2026-02-28T01:00,9.2
|
||||||
|
2026-02-28T02:00,9.3
|
||||||
|
2026-02-28T03:00,9.0
|
||||||
|
2026-02-28T04:00,8.5
|
||||||
|
2026-02-28T05:00,8.0
|
||||||
|
2026-02-28T06:00,7.3
|
||||||
|
2026-02-28T07:00,8.6
|
||||||
|
2026-02-28T08:00,10.0
|
||||||
|
2026-02-28T09:00,11.4
|
||||||
|
2026-02-28T10:00,13.7
|
||||||
|
2026-02-28T11:00,15.3
|
||||||
|
2026-02-28T12:00,16.7
|
||||||
|
2026-02-28T13:00,17.1
|
||||||
|
2026-02-28T14:00,17.2
|
||||||
|
2026-02-28T15:00,17.1
|
||||||
|
2026-02-28T16:00,16.6
|
||||||
|
2026-02-28T17:00,15.8
|
||||||
|
2026-02-28T18:00,14.6
|
||||||
|
2026-02-28T19:00,14.0
|
||||||
|
2026-02-28T20:00,13.4
|
||||||
|
2026-02-28T21:00,12.4
|
||||||
|
2026-02-28T22:00,11.9
|
||||||
|
2026-02-28T23:00,11.4
|
||||||
|
2026-03-01T00:00,10.8
|
||||||
|
2026-03-01T01:00,10.0
|
||||||
|
2026-03-01T02:00,8.9
|
||||||
|
2026-03-01T03:00,8.2
|
||||||
|
2026-03-01T04:00,7.6
|
||||||
|
2026-03-01T05:00,7.0
|
||||||
|
2026-03-01T06:00,6.5
|
||||||
|
2026-03-01T07:00,6.4
|
||||||
|
2026-03-01T08:00,6.5
|
||||||
|
2026-03-01T09:00,7.1
|
||||||
|
2026-03-01T10:00,7.9
|
||||||
|
2026-03-01T11:00,8.7
|
||||||
|
2026-03-01T12:00,9.6
|
||||||
|
2026-03-01T13:00,10.4
|
||||||
|
2026-03-01T14:00,10.4
|
||||||
|
2026-03-01T15:00,10.8
|
||||||
|
2026-03-01T16:00,10.4
|
||||||
|
2026-03-01T17:00,9.7
|
||||||
|
2026-03-01T18:00,8.3
|
||||||
|
2026-03-01T19:00,7.0
|
||||||
|
2026-03-01T20:00,5.8
|
||||||
|
2026-03-01T21:00,4.7
|
||||||
|
2026-03-01T22:00,4.3
|
||||||
|
2026-03-01T23:00,3.6
|
||||||
|
2026-03-02T00:00,3.3
|
||||||
|
2026-03-02T01:00,3.5
|
||||||
|
2026-03-02T02:00,3.9
|
||||||
|
2026-03-02T03:00,3.2
|
||||||
|
2026-03-02T04:00,3.0
|
||||||
|
2026-03-02T05:00,2.6
|
||||||
|
2026-03-02T06:00,3.0
|
||||||
|
2026-03-02T07:00,3.8
|
||||||
|
2026-03-02T08:00,5.5
|
||||||
|
2026-03-02T09:00,7.7
|
||||||
|
2026-03-02T10:00,9.8
|
||||||
|
2026-03-02T11:00,11.8
|
||||||
|
2026-03-02T12:00,13.0
|
||||||
|
2026-03-02T13:00,13.6
|
||||||
|
2026-03-02T14:00,13.8
|
||||||
|
2026-03-02T15:00,13.4
|
||||||
|
2026-03-02T16:00,12.9
|
||||||
|
2026-03-02T17:00,11.9
|
||||||
|
2026-03-02T18:00,10.1
|
||||||
|
2026-03-02T19:00,8.7
|
||||||
|
2026-03-02T20:00,7.5
|
||||||
|
2026-03-02T21:00,7.0
|
||||||
|
2026-03-02T22:00,6.0
|
||||||
|
2026-03-02T23:00,5.3
|
||||||
|
2026-03-03T00:00,4.7
|
||||||
|
2026-03-03T01:00,4.1
|
||||||
|
2026-03-03T02:00,3.4
|
||||||
|
2026-03-03T03:00,3.0
|
||||||
|
2026-03-03T04:00,2.4
|
||||||
|
2026-03-03T05:00,1.7
|
||||||
|
2026-03-03T06:00,2.3
|
||||||
|
2026-03-03T07:00,4.0
|
||||||
|
2026-03-03T08:00,6.0
|
||||||
|
2026-03-03T09:00,8.0
|
||||||
|
2026-03-03T10:00,10.5
|
||||||
|
2026-03-03T11:00,12.5
|
||||||
|
2026-03-03T12:00,14.0
|
||||||
|
2026-03-03T13:00,15.1
|
||||||
|
2026-03-03T14:00,15.3
|
||||||
|
2026-03-03T15:00,15.4
|
||||||
|
2026-03-03T16:00,14.6
|
||||||
|
2026-03-03T17:00,13.3
|
||||||
|
2026-03-03T18:00,11.8
|
||||||
|
2026-03-03T19:00,10.5
|
||||||
|
2026-03-03T20:00,8.7
|
||||||
|
2026-03-03T21:00,8.5
|
||||||
|
2026-03-03T22:00,7.8
|
||||||
|
2026-03-03T23:00,7.5
|
||||||
|
2026-03-04T00:00,6.8
|
||||||
|
2026-03-04T01:00,5.9
|
||||||
|
2026-03-04T02:00,5.1
|
||||||
|
2026-03-04T03:00,4.7
|
||||||
|
2026-03-04T04:00,5.1
|
||||||
|
2026-03-04T05:00,5.0
|
||||||
|
2026-03-04T06:00,5.4
|
||||||
|
2026-03-04T07:00,6.0
|
||||||
|
2026-03-04T08:00,6.6
|
||||||
|
2026-03-04T09:00,7.9
|
||||||
|
2026-03-04T10:00,8.4
|
||||||
|
2026-03-04T11:00,9.4
|
||||||
|
2026-03-04T12:00,10.0
|
||||||
|
2026-03-04T13:00,10.8
|
||||||
|
2026-03-04T14:00,11.2
|
||||||
|
2026-03-04T15:00,11.0
|
||||||
|
2026-03-04T16:00,10.4
|
||||||
|
2026-03-04T17:00,9.1
|
||||||
|
2026-03-04T18:00,7.6
|
||||||
|
2026-03-04T19:00,6.8
|
||||||
|
2026-03-04T20:00,6.1
|
||||||
|
2026-03-04T21:00,5.6
|
||||||
|
2026-03-04T22:00,3.8
|
||||||
|
2026-03-04T23:00,3.4
|
||||||
|
2026-03-05T00:00,3.0
|
||||||
|
2026-03-05T01:00,2.2
|
||||||
|
2026-03-05T02:00,1.5
|
||||||
|
2026-03-05T03:00,1.3
|
||||||
|
2026-03-05T04:00,0.7
|
||||||
|
2026-03-05T05:00,0.3
|
||||||
|
2026-03-05T06:00,0.7
|
||||||
|
2026-03-05T07:00,2.0
|
||||||
|
2026-03-05T08:00,4.4
|
||||||
|
2026-03-05T09:00,6.8
|
||||||
|
2026-03-05T10:00,8.6
|
||||||
|
2026-03-05T11:00,10.2
|
||||||
|
2026-03-05T12:00,11.3
|
||||||
|
2026-03-05T13:00,12.3
|
||||||
|
2026-03-05T14:00,12.6
|
||||||
|
2026-03-05T15:00,12.6
|
||||||
|
2026-03-05T16:00,11.6
|
||||||
|
2026-03-05T17:00,10.1
|
||||||
|
2026-03-05T18:00,8.9
|
||||||
|
2026-03-05T19:00,7.4
|
||||||
|
2026-03-05T20:00,6.3
|
||||||
|
2026-03-05T21:00,5.3
|
||||||
|
2026-03-05T22:00,4.6
|
||||||
|
2026-03-05T23:00,3.7
|
||||||
|
2026-03-06T00:00,3.2
|
||||||
|
2026-03-06T01:00,2.9
|
||||||
|
2026-03-06T02:00,2.5
|
||||||
|
2026-03-06T03:00,2.1
|
||||||
|
2026-03-06T04:00,1.6
|
||||||
|
2026-03-06T05:00,1.0
|
||||||
|
2026-03-06T06:00,1.3
|
||||||
|
2026-03-06T07:00,2.5
|
||||||
|
2026-03-06T08:00,4.7
|
||||||
|
2026-03-06T09:00,7.7
|
||||||
|
2026-03-06T10:00,10.5
|
||||||
|
2026-03-06T11:00,12.7
|
||||||
|
2026-03-06T12:00,14.1
|
||||||
|
2026-03-06T13:00,15.0
|
||||||
|
2026-03-06T14:00,15.0
|
||||||
|
2026-03-06T15:00,14.9
|
||||||
|
2026-03-06T16:00,13.9
|
||||||
|
2026-03-06T17:00,12.4
|
||||||
|
2026-03-06T18:00,10.6
|
||||||
|
2026-03-06T19:00,8.8
|
||||||
|
2026-03-06T20:00,8.1
|
||||||
|
2026-03-06T21:00,7.3
|
||||||
|
2026-03-06T22:00,6.5
|
||||||
|
2026-03-06T23:00,5.9
|
||||||
|
2026-03-07T00:00,5.1
|
||||||
|
2026-03-07T01:00,4.6
|
||||||
|
2026-03-07T02:00,4.2
|
||||||
|
2026-03-07T03:00,3.6
|
||||||
|
2026-03-07T04:00,2.8
|
||||||
|
2026-03-07T05:00,2.9
|
||||||
|
2026-03-07T06:00,3.3
|
||||||
|
2026-03-07T07:00,4.2
|
||||||
|
2026-03-07T08:00,6.1
|
||||||
|
2026-03-07T09:00,9.0
|
||||||
|
2026-03-07T10:00,11.6
|
||||||
|
2026-03-07T11:00,13.7
|
||||||
|
2026-03-07T12:00,15.1
|
||||||
|
2026-03-07T13:00,16.2
|
||||||
|
2026-03-07T14:00,16.4
|
||||||
|
2026-03-07T15:00,16.4
|
||||||
|
2026-03-07T16:00,16.4
|
||||||
|
2026-03-07T17:00,14.7
|
||||||
|
2026-03-07T18:00,12.8
|
||||||
|
2026-03-07T19:00,11.5
|
||||||
|
2026-03-07T20:00,10.2
|
||||||
|
2026-03-07T21:00,9.0
|
||||||
|
2026-03-07T22:00,8.1
|
||||||
|
2026-03-07T23:00,7.3
|
||||||
|
984
08/ex1/poetry.lock
generated
Normal file
984
08/ex1/poetry.lock
generated
Normal file
@@ -0,0 +1,984 @@
|
|||||||
|
# This file is automatically @generated by Poetry 2.3.2 and should not be changed by hand.
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "contourpy"
|
||||||
|
version = "1.3.2"
|
||||||
|
description = "Python library for calculating contours of 2D quadrilateral grids"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.10"
|
||||||
|
groups = ["main"]
|
||||||
|
markers = "python_version == \"3.10\""
|
||||||
|
files = [
|
||||||
|
{file = "contourpy-1.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ba38e3f9f330af820c4b27ceb4b9c7feee5fe0493ea53a8720f4792667465934"},
|
||||||
|
{file = "contourpy-1.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:dc41ba0714aa2968d1f8674ec97504a8f7e334f48eeacebcaa6256213acb0989"},
|
||||||
|
{file = "contourpy-1.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9be002b31c558d1ddf1b9b415b162c603405414bacd6932d031c5b5a8b757f0d"},
|
||||||
|
{file = "contourpy-1.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8d2e74acbcba3bfdb6d9d8384cdc4f9260cae86ed9beee8bd5f54fee49a430b9"},
|
||||||
|
{file = "contourpy-1.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e259bced5549ac64410162adc973c5e2fb77f04df4a439d00b478e57a0e65512"},
|
||||||
|
{file = "contourpy-1.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad687a04bc802cbe8b9c399c07162a3c35e227e2daccf1668eb1f278cb698631"},
|
||||||
|
{file = "contourpy-1.3.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cdd22595308f53ef2f891040ab2b93d79192513ffccbd7fe19be7aa773a5e09f"},
|
||||||
|
{file = "contourpy-1.3.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b4f54d6a2defe9f257327b0f243612dd051cc43825587520b1bf74a31e2f6ef2"},
|
||||||
|
{file = "contourpy-1.3.2-cp310-cp310-win32.whl", hash = "sha256:f939a054192ddc596e031e50bb13b657ce318cf13d264f095ce9db7dc6ae81c0"},
|
||||||
|
{file = "contourpy-1.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:c440093bbc8fc21c637c03bafcbef95ccd963bc6e0514ad887932c18ca2a759a"},
|
||||||
|
{file = "contourpy-1.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6a37a2fb93d4df3fc4c0e363ea4d16f83195fc09c891bc8ce072b9d084853445"},
|
||||||
|
{file = "contourpy-1.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b7cd50c38f500bbcc9b6a46643a40e0913673f869315d8e70de0438817cb7773"},
|
||||||
|
{file = "contourpy-1.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6658ccc7251a4433eebd89ed2672c2ed96fba367fd25ca9512aa92a4b46c4f1"},
|
||||||
|
{file = "contourpy-1.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:70771a461aaeb335df14deb6c97439973d253ae70660ca085eec25241137ef43"},
|
||||||
|
{file = "contourpy-1.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65a887a6e8c4cd0897507d814b14c54a8c2e2aa4ac9f7686292f9769fcf9a6ab"},
|
||||||
|
{file = "contourpy-1.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3859783aefa2b8355697f16642695a5b9792e7a46ab86da1118a4a23a51a33d7"},
|
||||||
|
{file = "contourpy-1.3.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:eab0f6db315fa4d70f1d8ab514e527f0366ec021ff853d7ed6a2d33605cf4b83"},
|
||||||
|
{file = "contourpy-1.3.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d91a3ccc7fea94ca0acab82ceb77f396d50a1f67412efe4c526f5d20264e6ecd"},
|
||||||
|
{file = "contourpy-1.3.2-cp311-cp311-win32.whl", hash = "sha256:1c48188778d4d2f3d48e4643fb15d8608b1d01e4b4d6b0548d9b336c28fc9b6f"},
|
||||||
|
{file = "contourpy-1.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:5ebac872ba09cb8f2131c46b8739a7ff71de28a24c869bcad554477eb089a878"},
|
||||||
|
{file = "contourpy-1.3.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4caf2bcd2969402bf77edc4cb6034c7dd7c0803213b3523f111eb7460a51b8d2"},
|
||||||
|
{file = "contourpy-1.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:82199cb78276249796419fe36b7386bd8d2cc3f28b3bc19fe2454fe2e26c4c15"},
|
||||||
|
{file = "contourpy-1.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:106fab697af11456fcba3e352ad50effe493a90f893fca6c2ca5c033820cea92"},
|
||||||
|
{file = "contourpy-1.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d14f12932a8d620e307f715857107b1d1845cc44fdb5da2bc8e850f5ceba9f87"},
|
||||||
|
{file = "contourpy-1.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:532fd26e715560721bb0d5fc7610fce279b3699b018600ab999d1be895b09415"},
|
||||||
|
{file = "contourpy-1.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f26b383144cf2d2c29f01a1e8170f50dacf0eac02d64139dcd709a8ac4eb3cfe"},
|
||||||
|
{file = "contourpy-1.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c49f73e61f1f774650a55d221803b101d966ca0c5a2d6d5e4320ec3997489441"},
|
||||||
|
{file = "contourpy-1.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3d80b2c0300583228ac98d0a927a1ba6a2ba6b8a742463c564f1d419ee5b211e"},
|
||||||
|
{file = "contourpy-1.3.2-cp312-cp312-win32.whl", hash = "sha256:90df94c89a91b7362e1142cbee7568f86514412ab8a2c0d0fca72d7e91b62912"},
|
||||||
|
{file = "contourpy-1.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:8c942a01d9163e2e5cfb05cb66110121b8d07ad438a17f9e766317bcb62abf73"},
|
||||||
|
{file = "contourpy-1.3.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:de39db2604ae755316cb5967728f4bea92685884b1e767b7c24e983ef5f771cb"},
|
||||||
|
{file = "contourpy-1.3.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3f9e896f447c5c8618f1edb2bafa9a4030f22a575ec418ad70611450720b5b08"},
|
||||||
|
{file = "contourpy-1.3.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71e2bd4a1c4188f5c2b8d274da78faab884b59df20df63c34f74aa1813c4427c"},
|
||||||
|
{file = "contourpy-1.3.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de425af81b6cea33101ae95ece1f696af39446db9682a0b56daaa48cfc29f38f"},
|
||||||
|
{file = "contourpy-1.3.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:977e98a0e0480d3fe292246417239d2d45435904afd6d7332d8455981c408b85"},
|
||||||
|
{file = "contourpy-1.3.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:434f0adf84911c924519d2b08fc10491dd282b20bdd3fa8f60fd816ea0b48841"},
|
||||||
|
{file = "contourpy-1.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c66c4906cdbc50e9cba65978823e6e00b45682eb09adbb78c9775b74eb222422"},
|
||||||
|
{file = "contourpy-1.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8b7fc0cd78ba2f4695fd0a6ad81a19e7e3ab825c31b577f384aa9d7817dc3bef"},
|
||||||
|
{file = "contourpy-1.3.2-cp313-cp313-win32.whl", hash = "sha256:15ce6ab60957ca74cff444fe66d9045c1fd3e92c8936894ebd1f3eef2fff075f"},
|
||||||
|
{file = "contourpy-1.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:e1578f7eafce927b168752ed7e22646dad6cd9bca673c60bff55889fa236ebf9"},
|
||||||
|
{file = "contourpy-1.3.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0475b1f6604896bc7c53bb070e355e9321e1bc0d381735421a2d2068ec56531f"},
|
||||||
|
{file = "contourpy-1.3.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:c85bb486e9be652314bb5b9e2e3b0d1b2e643d5eec4992c0fbe8ac71775da739"},
|
||||||
|
{file = "contourpy-1.3.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:745b57db7758f3ffc05a10254edd3182a2a83402a89c00957a8e8a22f5582823"},
|
||||||
|
{file = "contourpy-1.3.2-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:970e9173dbd7eba9b4e01aab19215a48ee5dd3f43cef736eebde064a171f89a5"},
|
||||||
|
{file = "contourpy-1.3.2-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c6c4639a9c22230276b7bffb6a850dfc8258a2521305e1faefe804d006b2e532"},
|
||||||
|
{file = "contourpy-1.3.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc829960f34ba36aad4302e78eabf3ef16a3a100863f0d4eeddf30e8a485a03b"},
|
||||||
|
{file = "contourpy-1.3.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:d32530b534e986374fc19eaa77fcb87e8a99e5431499949b828312bdcd20ac52"},
|
||||||
|
{file = "contourpy-1.3.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:e298e7e70cf4eb179cc1077be1c725b5fd131ebc81181bf0c03525c8abc297fd"},
|
||||||
|
{file = "contourpy-1.3.2-cp313-cp313t-win32.whl", hash = "sha256:d0e589ae0d55204991450bb5c23f571c64fe43adaa53f93fc902a84c96f52fe1"},
|
||||||
|
{file = "contourpy-1.3.2-cp313-cp313t-win_amd64.whl", hash = "sha256:78e9253c3de756b3f6a5174d024c4835acd59eb3f8e2ca13e775dbffe1558f69"},
|
||||||
|
{file = "contourpy-1.3.2-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:fd93cc7f3139b6dd7aab2f26a90dde0aa9fc264dbf70f6740d498a70b860b82c"},
|
||||||
|
{file = "contourpy-1.3.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:107ba8a6a7eec58bb475329e6d3b95deba9440667c4d62b9b6063942b61d7f16"},
|
||||||
|
{file = "contourpy-1.3.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:ded1706ed0c1049224531b81128efbd5084598f18d8a2d9efae833edbd2b40ad"},
|
||||||
|
{file = "contourpy-1.3.2-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:5f5964cdad279256c084b69c3f412b7801e15356b16efa9d78aa974041903da0"},
|
||||||
|
{file = "contourpy-1.3.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49b65a95d642d4efa8f64ba12558fcb83407e58a2dfba9d796d77b63ccfcaff5"},
|
||||||
|
{file = "contourpy-1.3.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:8c5acb8dddb0752bf252e01a3035b21443158910ac16a3b0d20e7fed7d534ce5"},
|
||||||
|
{file = "contourpy-1.3.2.tar.gz", hash = "sha256:b6945942715a034c671b7fc54f9588126b0b8bf23db2696e3ca8328f3ff0ab54"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
numpy = ">=1.23"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
bokeh = ["bokeh", "selenium"]
|
||||||
|
docs = ["furo", "sphinx (>=7.2)", "sphinx-copybutton"]
|
||||||
|
mypy = ["bokeh", "contourpy[bokeh,docs]", "docutils-stubs", "mypy (==1.15.0)", "types-Pillow"]
|
||||||
|
test = ["Pillow", "contourpy[test-no-images]", "matplotlib"]
|
||||||
|
test-no-images = ["pytest", "pytest-cov", "pytest-rerunfailures", "pytest-xdist", "wurlitzer"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "contourpy"
|
||||||
|
version = "1.3.3"
|
||||||
|
description = "Python library for calculating contours of 2D quadrilateral grids"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.11"
|
||||||
|
groups = ["main"]
|
||||||
|
markers = "python_version >= \"3.11\""
|
||||||
|
files = [
|
||||||
|
{file = "contourpy-1.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:709a48ef9a690e1343202916450bc48b9e51c049b089c7f79a267b46cffcdaa1"},
|
||||||
|
{file = "contourpy-1.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:23416f38bfd74d5d28ab8429cc4d63fa67d5068bd711a85edb1c3fb0c3e2f381"},
|
||||||
|
{file = "contourpy-1.3.3-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:929ddf8c4c7f348e4c0a5a3a714b5c8542ffaa8c22954862a46ca1813b667ee7"},
|
||||||
|
{file = "contourpy-1.3.3-cp311-cp311-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9e999574eddae35f1312c2b4b717b7885d4edd6cb46700e04f7f02db454e67c1"},
|
||||||
|
{file = "contourpy-1.3.3-cp311-cp311-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0bf67e0e3f482cb69779dd3061b534eb35ac9b17f163d851e2a547d56dba0a3a"},
|
||||||
|
{file = "contourpy-1.3.3-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:51e79c1f7470158e838808d4a996fa9bac72c498e93d8ebe5119bc1e6becb0db"},
|
||||||
|
{file = "contourpy-1.3.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:598c3aaece21c503615fd59c92a3598b428b2f01bfb4b8ca9c4edeecc2438620"},
|
||||||
|
{file = "contourpy-1.3.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:322ab1c99b008dad206d406bb61d014cf0174df491ae9d9d0fac6a6fda4f977f"},
|
||||||
|
{file = "contourpy-1.3.3-cp311-cp311-win32.whl", hash = "sha256:fd907ae12cd483cd83e414b12941c632a969171bf90fc937d0c9f268a31cafff"},
|
||||||
|
{file = "contourpy-1.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:3519428f6be58431c56581f1694ba8e50626f2dd550af225f82fb5f5814d2a42"},
|
||||||
|
{file = "contourpy-1.3.3-cp311-cp311-win_arm64.whl", hash = "sha256:15ff10bfada4bf92ec8b31c62bf7c1834c244019b4a33095a68000d7075df470"},
|
||||||
|
{file = "contourpy-1.3.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b08a32ea2f8e42cf1d4be3169a98dd4be32bafe4f22b6c4cb4ba810fa9e5d2cb"},
|
||||||
|
{file = "contourpy-1.3.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:556dba8fb6f5d8742f2923fe9457dbdd51e1049c4a43fd3986a0b14a1d815fc6"},
|
||||||
|
{file = "contourpy-1.3.3-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92d9abc807cf7d0e047b95ca5d957cf4792fcd04e920ca70d48add15c1a90ea7"},
|
||||||
|
{file = "contourpy-1.3.3-cp312-cp312-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b2e8faa0ed68cb29af51edd8e24798bb661eac3bd9f65420c1887b6ca89987c8"},
|
||||||
|
{file = "contourpy-1.3.3-cp312-cp312-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:626d60935cf668e70a5ce6ff184fd713e9683fb458898e4249b63be9e28286ea"},
|
||||||
|
{file = "contourpy-1.3.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4d00e655fcef08aba35ec9610536bfe90267d7ab5ba944f7032549c55a146da1"},
|
||||||
|
{file = "contourpy-1.3.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:451e71b5a7d597379ef572de31eeb909a87246974d960049a9848c3bc6c41bf7"},
|
||||||
|
{file = "contourpy-1.3.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:459c1f020cd59fcfe6650180678a9993932d80d44ccde1fa1868977438f0b411"},
|
||||||
|
{file = "contourpy-1.3.3-cp312-cp312-win32.whl", hash = "sha256:023b44101dfe49d7d53932be418477dba359649246075c996866106da069af69"},
|
||||||
|
{file = "contourpy-1.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:8153b8bfc11e1e4d75bcb0bff1db232f9e10b274e0929de9d608027e0d34ff8b"},
|
||||||
|
{file = "contourpy-1.3.3-cp312-cp312-win_arm64.whl", hash = "sha256:07ce5ed73ecdc4a03ffe3e1b3e3c1166db35ae7584be76f65dbbe28a7791b0cc"},
|
||||||
|
{file = "contourpy-1.3.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:177fb367556747a686509d6fef71d221a4b198a3905fe824430e5ea0fda54eb5"},
|
||||||
|
{file = "contourpy-1.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d002b6f00d73d69333dac9d0b8d5e84d9724ff9ef044fd63c5986e62b7c9e1b1"},
|
||||||
|
{file = "contourpy-1.3.3-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:348ac1f5d4f1d66d3322420f01d42e43122f43616e0f194fc1c9f5d830c5b286"},
|
||||||
|
{file = "contourpy-1.3.3-cp313-cp313-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:655456777ff65c2c548b7c454af9c6f33f16c8884f11083244b5819cc214f1b5"},
|
||||||
|
{file = "contourpy-1.3.3-cp313-cp313-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:644a6853d15b2512d67881586bd03f462c7ab755db95f16f14d7e238f2852c67"},
|
||||||
|
{file = "contourpy-1.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4debd64f124ca62069f313a9cb86656ff087786016d76927ae2cf37846b006c9"},
|
||||||
|
{file = "contourpy-1.3.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a15459b0f4615b00bbd1e91f1b9e19b7e63aea7483d03d804186f278c0af2659"},
|
||||||
|
{file = "contourpy-1.3.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ca0fdcd73925568ca027e0b17ab07aad764be4706d0a925b89227e447d9737b7"},
|
||||||
|
{file = "contourpy-1.3.3-cp313-cp313-win32.whl", hash = "sha256:b20c7c9a3bf701366556e1b1984ed2d0cedf999903c51311417cf5f591d8c78d"},
|
||||||
|
{file = "contourpy-1.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:1cadd8b8969f060ba45ed7c1b714fe69185812ab43bd6b86a9123fe8f99c3263"},
|
||||||
|
{file = "contourpy-1.3.3-cp313-cp313-win_arm64.whl", hash = "sha256:fd914713266421b7536de2bfa8181aa8c699432b6763a0ea64195ebe28bff6a9"},
|
||||||
|
{file = "contourpy-1.3.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:88df9880d507169449d434c293467418b9f6cbe82edd19284aa0409e7fdb933d"},
|
||||||
|
{file = "contourpy-1.3.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:d06bb1f751ba5d417047db62bca3c8fde202b8c11fb50742ab3ab962c81e8216"},
|
||||||
|
{file = "contourpy-1.3.3-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e4e6b05a45525357e382909a4c1600444e2a45b4795163d3b22669285591c1ae"},
|
||||||
|
{file = "contourpy-1.3.3-cp313-cp313t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ab3074b48c4e2cf1a960e6bbeb7f04566bf36b1861d5c9d4d8ac04b82e38ba20"},
|
||||||
|
{file = "contourpy-1.3.3-cp313-cp313t-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6c3d53c796f8647d6deb1abe867daeb66dcc8a97e8455efa729516b997b8ed99"},
|
||||||
|
{file = "contourpy-1.3.3-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:50ed930df7289ff2a8d7afeb9603f8289e5704755c7e5c3bbd929c90c817164b"},
|
||||||
|
{file = "contourpy-1.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4feffb6537d64b84877da813a5c30f1422ea5739566abf0bd18065ac040e120a"},
|
||||||
|
{file = "contourpy-1.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:2b7e9480ffe2b0cd2e787e4df64270e3a0440d9db8dc823312e2c940c167df7e"},
|
||||||
|
{file = "contourpy-1.3.3-cp313-cp313t-win32.whl", hash = "sha256:283edd842a01e3dcd435b1c5116798d661378d83d36d337b8dde1d16a5fc9ba3"},
|
||||||
|
{file = "contourpy-1.3.3-cp313-cp313t-win_amd64.whl", hash = "sha256:87acf5963fc2b34825e5b6b048f40e3635dd547f590b04d2ab317c2619ef7ae8"},
|
||||||
|
{file = "contourpy-1.3.3-cp313-cp313t-win_arm64.whl", hash = "sha256:3c30273eb2a55024ff31ba7d052dde990d7d8e5450f4bbb6e913558b3d6c2301"},
|
||||||
|
{file = "contourpy-1.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fde6c716d51c04b1c25d0b90364d0be954624a0ee9d60e23e850e8d48353d07a"},
|
||||||
|
{file = "contourpy-1.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:cbedb772ed74ff5be440fa8eee9bd49f64f6e3fc09436d9c7d8f1c287b121d77"},
|
||||||
|
{file = "contourpy-1.3.3-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:22e9b1bd7a9b1d652cd77388465dc358dafcd2e217d35552424aa4f996f524f5"},
|
||||||
|
{file = "contourpy-1.3.3-cp314-cp314-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a22738912262aa3e254e4f3cb079a95a67132fc5a063890e224393596902f5a4"},
|
||||||
|
{file = "contourpy-1.3.3-cp314-cp314-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:afe5a512f31ee6bd7d0dda52ec9864c984ca3d66664444f2d72e0dc4eb832e36"},
|
||||||
|
{file = "contourpy-1.3.3-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f64836de09927cba6f79dcd00fdd7d5329f3fccc633468507079c829ca4db4e3"},
|
||||||
|
{file = "contourpy-1.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1fd43c3be4c8e5fd6e4f2baeae35ae18176cf2e5cced681cca908addf1cdd53b"},
|
||||||
|
{file = "contourpy-1.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6afc576f7b33cf00996e5c1102dc2a8f7cc89e39c0b55df93a0b78c1bd992b36"},
|
||||||
|
{file = "contourpy-1.3.3-cp314-cp314-win32.whl", hash = "sha256:66c8a43a4f7b8df8b71ee1840e4211a3c8d93b214b213f590e18a1beca458f7d"},
|
||||||
|
{file = "contourpy-1.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:cf9022ef053f2694e31d630feaacb21ea24224be1c3ad0520b13d844274614fd"},
|
||||||
|
{file = "contourpy-1.3.3-cp314-cp314-win_arm64.whl", hash = "sha256:95b181891b4c71de4bb404c6621e7e2390745f887f2a026b2d99e92c17892339"},
|
||||||
|
{file = "contourpy-1.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:33c82d0138c0a062380332c861387650c82e4cf1747aaa6938b9b6516762e772"},
|
||||||
|
{file = "contourpy-1.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ea37e7b45949df430fe649e5de8351c423430046a2af20b1c1961cae3afcda77"},
|
||||||
|
{file = "contourpy-1.3.3-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d304906ecc71672e9c89e87c4675dc5c2645e1f4269a5063b99b0bb29f232d13"},
|
||||||
|
{file = "contourpy-1.3.3-cp314-cp314t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ca658cd1a680a5c9ea96dc61cdbae1e85c8f25849843aa799dfd3cb370ad4fbe"},
|
||||||
|
{file = "contourpy-1.3.3-cp314-cp314t-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ab2fd90904c503739a75b7c8c5c01160130ba67944a7b77bbf36ef8054576e7f"},
|
||||||
|
{file = "contourpy-1.3.3-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b7301b89040075c30e5768810bc96a8e8d78085b47d8be6e4c3f5a0b4ed478a0"},
|
||||||
|
{file = "contourpy-1.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:2a2a8b627d5cc6b7c41a4beff6c5ad5eb848c88255fda4a8745f7e901b32d8e4"},
|
||||||
|
{file = "contourpy-1.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:fd6ec6be509c787f1caf6b247f0b1ca598bef13f4ddeaa126b7658215529ba0f"},
|
||||||
|
{file = "contourpy-1.3.3-cp314-cp314t-win32.whl", hash = "sha256:e74a9a0f5e3fff48fb5a7f2fd2b9b70a3fe014a67522f79b7cca4c0c7e43c9ae"},
|
||||||
|
{file = "contourpy-1.3.3-cp314-cp314t-win_amd64.whl", hash = "sha256:13b68d6a62db8eafaebb8039218921399baf6e47bf85006fd8529f2a08ef33fc"},
|
||||||
|
{file = "contourpy-1.3.3-cp314-cp314t-win_arm64.whl", hash = "sha256:b7448cb5a725bb1e35ce88771b86fba35ef418952474492cf7c764059933ff8b"},
|
||||||
|
{file = "contourpy-1.3.3-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:cd5dfcaeb10f7b7f9dc8941717c6c2ade08f587be2226222c12b25f0483ed497"},
|
||||||
|
{file = "contourpy-1.3.3-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:0c1fc238306b35f246d61a1d416a627348b5cf0648648a031e14bb8705fcdfe8"},
|
||||||
|
{file = "contourpy-1.3.3-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:70f9aad7de812d6541d29d2bbf8feb22ff7e1c299523db288004e3157ff4674e"},
|
||||||
|
{file = "contourpy-1.3.3-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5ed3657edf08512fc3fe81b510e35c2012fbd3081d2e26160f27ca28affec989"},
|
||||||
|
{file = "contourpy-1.3.3-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:3d1a3799d62d45c18bafd41c5fa05120b96a28079f2393af559b843d1a966a77"},
|
||||||
|
{file = "contourpy-1.3.3.tar.gz", hash = "sha256:083e12155b210502d0bca491432bb04d56dc3432f95a979b429f2848c3dbe880"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
numpy = ">=1.25"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
bokeh = ["bokeh", "selenium"]
|
||||||
|
docs = ["furo", "sphinx (>=7.2)", "sphinx-copybutton"]
|
||||||
|
mypy = ["bokeh", "contourpy[bokeh,docs]", "docutils-stubs", "mypy (==1.17.0)", "types-Pillow"]
|
||||||
|
test = ["Pillow", "contourpy[test-no-images]", "matplotlib"]
|
||||||
|
test-no-images = ["pytest", "pytest-cov", "pytest-rerunfailures", "pytest-xdist", "wurlitzer"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cycler"
|
||||||
|
version = "0.12.1"
|
||||||
|
description = "Composable style cycles"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
groups = ["main"]
|
||||||
|
files = [
|
||||||
|
{file = "cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30"},
|
||||||
|
{file = "cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
docs = ["ipython", "matplotlib", "numpydoc", "sphinx"]
|
||||||
|
tests = ["pytest", "pytest-cov", "pytest-xdist"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fonttools"
|
||||||
|
version = "4.61.1"
|
||||||
|
description = "Tools to manipulate font files"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.10"
|
||||||
|
groups = ["main"]
|
||||||
|
files = [
|
||||||
|
{file = "fonttools-4.61.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7c7db70d57e5e1089a274cbb2b1fd635c9a24de809a231b154965d415d6c6d24"},
|
||||||
|
{file = "fonttools-4.61.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5fe9fd43882620017add5eabb781ebfbc6998ee49b35bd7f8f79af1f9f99a958"},
|
||||||
|
{file = "fonttools-4.61.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d8db08051fc9e7d8bc622f2112511b8107d8f27cd89e2f64ec45e9825e8288da"},
|
||||||
|
{file = "fonttools-4.61.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a76d4cb80f41ba94a6691264be76435e5f72f2cb3cab0b092a6212855f71c2f6"},
|
||||||
|
{file = "fonttools-4.61.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a13fc8aeb24bad755eea8f7f9d409438eb94e82cf86b08fe77a03fbc8f6a96b1"},
|
||||||
|
{file = "fonttools-4.61.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b846a1fcf8beadeb9ea4f44ec5bdde393e2f1569e17d700bfc49cd69bde75881"},
|
||||||
|
{file = "fonttools-4.61.1-cp310-cp310-win32.whl", hash = "sha256:78a7d3ab09dc47ac1a363a493e6112d8cabed7ba7caad5f54dbe2f08676d1b47"},
|
||||||
|
{file = "fonttools-4.61.1-cp310-cp310-win_amd64.whl", hash = "sha256:eff1ac3cc66c2ac7cda1e64b4e2f3ffef474b7335f92fc3833fc632d595fcee6"},
|
||||||
|
{file = "fonttools-4.61.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:c6604b735bb12fef8e0efd5578c9fb5d3d8532d5001ea13a19cddf295673ee09"},
|
||||||
|
{file = "fonttools-4.61.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5ce02f38a754f207f2f06557523cd39a06438ba3aafc0639c477ac409fc64e37"},
|
||||||
|
{file = "fonttools-4.61.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:77efb033d8d7ff233385f30c62c7c79271c8885d5c9657d967ede124671bbdfb"},
|
||||||
|
{file = "fonttools-4.61.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:75c1a6dfac6abd407634420c93864a1e274ebc1c7531346d9254c0d8f6ca00f9"},
|
||||||
|
{file = "fonttools-4.61.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0de30bfe7745c0d1ffa2b0b7048fb7123ad0d71107e10ee090fa0b16b9452e87"},
|
||||||
|
{file = "fonttools-4.61.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:58b0ee0ab5b1fc9921eccfe11d1435added19d6494dde14e323f25ad2bc30c56"},
|
||||||
|
{file = "fonttools-4.61.1-cp311-cp311-win32.whl", hash = "sha256:f79b168428351d11e10c5aeb61a74e1851ec221081299f4cf56036a95431c43a"},
|
||||||
|
{file = "fonttools-4.61.1-cp311-cp311-win_amd64.whl", hash = "sha256:fe2efccb324948a11dd09d22136fe2ac8a97d6c1347cf0b58a911dcd529f66b7"},
|
||||||
|
{file = "fonttools-4.61.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:f3cb4a569029b9f291f88aafc927dd53683757e640081ca8c412781ea144565e"},
|
||||||
|
{file = "fonttools-4.61.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:41a7170d042e8c0024703ed13b71893519a1a6d6e18e933e3ec7507a2c26a4b2"},
|
||||||
|
{file = "fonttools-4.61.1-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:10d88e55330e092940584774ee5e8a6971b01fc2f4d3466a1d6c158230880796"},
|
||||||
|
{file = "fonttools-4.61.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:15acc09befd16a0fb8a8f62bc147e1a82817542d72184acca9ce6e0aeda9fa6d"},
|
||||||
|
{file = "fonttools-4.61.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e6bcdf33aec38d16508ce61fd81838f24c83c90a1d1b8c68982857038673d6b8"},
|
||||||
|
{file = "fonttools-4.61.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5fade934607a523614726119164ff621e8c30e8fa1ffffbbd358662056ba69f0"},
|
||||||
|
{file = "fonttools-4.61.1-cp312-cp312-win32.whl", hash = "sha256:75da8f28eff26defba42c52986de97b22106cb8f26515b7c22443ebc9c2d3261"},
|
||||||
|
{file = "fonttools-4.61.1-cp312-cp312-win_amd64.whl", hash = "sha256:497c31ce314219888c0e2fce5ad9178ca83fe5230b01a5006726cdf3ac9f24d9"},
|
||||||
|
{file = "fonttools-4.61.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8c56c488ab471628ff3bfa80964372fc13504ece601e0d97a78ee74126b2045c"},
|
||||||
|
{file = "fonttools-4.61.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:dc492779501fa723b04d0ab1f5be046797fee17d27700476edc7ee9ae535a61e"},
|
||||||
|
{file = "fonttools-4.61.1-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:64102ca87e84261419c3747a0d20f396eb024bdbeb04c2bfb37e2891f5fadcb5"},
|
||||||
|
{file = "fonttools-4.61.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4c1b526c8d3f615a7b1867f38a9410849c8f4aef078535742198e942fba0e9bd"},
|
||||||
|
{file = "fonttools-4.61.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:41ed4b5ec103bd306bb68f81dc166e77409e5209443e5773cb4ed837bcc9b0d3"},
|
||||||
|
{file = "fonttools-4.61.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b501c862d4901792adaec7c25b1ecc749e2662543f68bb194c42ba18d6eec98d"},
|
||||||
|
{file = "fonttools-4.61.1-cp313-cp313-win32.whl", hash = "sha256:4d7092bb38c53bbc78e9255a59158b150bcdc115a1e3b3ce0b5f267dc35dd63c"},
|
||||||
|
{file = "fonttools-4.61.1-cp313-cp313-win_amd64.whl", hash = "sha256:21e7c8d76f62ab13c9472ccf74515ca5b9a761d1bde3265152a6dc58700d895b"},
|
||||||
|
{file = "fonttools-4.61.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:fff4f534200a04b4a36e7ae3cb74493afe807b517a09e99cb4faa89a34ed6ecd"},
|
||||||
|
{file = "fonttools-4.61.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:d9203500f7c63545b4ce3799319fe4d9feb1a1b89b28d3cb5abd11b9dd64147e"},
|
||||||
|
{file = "fonttools-4.61.1-cp314-cp314-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fa646ecec9528bef693415c79a86e733c70a4965dd938e9a226b0fc64c9d2e6c"},
|
||||||
|
{file = "fonttools-4.61.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:11f35ad7805edba3aac1a3710d104592df59f4b957e30108ae0ba6c10b11dd75"},
|
||||||
|
{file = "fonttools-4.61.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b931ae8f62db78861b0ff1ac017851764602288575d65b8e8ff1963fed419063"},
|
||||||
|
{file = "fonttools-4.61.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b148b56f5de675ee16d45e769e69f87623a4944f7443850bf9a9376e628a89d2"},
|
||||||
|
{file = "fonttools-4.61.1-cp314-cp314-win32.whl", hash = "sha256:9b666a475a65f4e839d3d10473fad6d47e0a9db14a2f4a224029c5bfde58ad2c"},
|
||||||
|
{file = "fonttools-4.61.1-cp314-cp314-win_amd64.whl", hash = "sha256:4f5686e1fe5fce75d82d93c47a438a25bf0d1319d2843a926f741140b2b16e0c"},
|
||||||
|
{file = "fonttools-4.61.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:e76ce097e3c57c4bcb67c5aa24a0ecdbd9f74ea9219997a707a4061fbe2707aa"},
|
||||||
|
{file = "fonttools-4.61.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:9cfef3ab326780c04d6646f68d4b4742aae222e8b8ea1d627c74e38afcbc9d91"},
|
||||||
|
{file = "fonttools-4.61.1-cp314-cp314t-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a75c301f96db737e1c5ed5fd7d77d9c34466de16095a266509e13da09751bd19"},
|
||||||
|
{file = "fonttools-4.61.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:91669ccac46bbc1d09e9273546181919064e8df73488ea087dcac3e2968df9ba"},
|
||||||
|
{file = "fonttools-4.61.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c33ab3ca9d3ccd581d58e989d67554e42d8d4ded94ab3ade3508455fe70e65f7"},
|
||||||
|
{file = "fonttools-4.61.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:664c5a68ec406f6b1547946683008576ef8b38275608e1cee6c061828171c118"},
|
||||||
|
{file = "fonttools-4.61.1-cp314-cp314t-win32.whl", hash = "sha256:aed04cabe26f30c1647ef0e8fbb207516fd40fe9472e9439695f5c6998e60ac5"},
|
||||||
|
{file = "fonttools-4.61.1-cp314-cp314t-win_amd64.whl", hash = "sha256:2180f14c141d2f0f3da43f3a81bc8aa4684860f6b0e6f9e165a4831f24e6a23b"},
|
||||||
|
{file = "fonttools-4.61.1-py3-none-any.whl", hash = "sha256:17d2bf5d541add43822bcf0c43d7d847b160c9bb01d15d5007d84e2217aaa371"},
|
||||||
|
{file = "fonttools-4.61.1.tar.gz", hash = "sha256:6675329885c44657f826ef01d9e4fb33b9158e9d93c537d84ad8399539bc6f69"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
all = ["brotli (>=1.0.1) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\"", "lxml (>=4.0)", "lz4 (>=1.7.4.2)", "matplotlib", "munkres ; platform_python_implementation == \"PyPy\"", "pycairo", "scipy ; platform_python_implementation != \"PyPy\"", "skia-pathops (>=0.5.0)", "sympy", "uharfbuzz (>=0.45.0)", "unicodedata2 (>=17.0.0) ; python_version <= \"3.14\"", "xattr ; sys_platform == \"darwin\"", "zopfli (>=0.1.4)"]
|
||||||
|
graphite = ["lz4 (>=1.7.4.2)"]
|
||||||
|
interpolatable = ["munkres ; platform_python_implementation == \"PyPy\"", "pycairo", "scipy ; platform_python_implementation != \"PyPy\""]
|
||||||
|
lxml = ["lxml (>=4.0)"]
|
||||||
|
pathops = ["skia-pathops (>=0.5.0)"]
|
||||||
|
plot = ["matplotlib"]
|
||||||
|
repacker = ["uharfbuzz (>=0.45.0)"]
|
||||||
|
symfont = ["sympy"]
|
||||||
|
type1 = ["xattr ; sys_platform == \"darwin\""]
|
||||||
|
unicode = ["unicodedata2 (>=17.0.0) ; python_version <= \"3.14\""]
|
||||||
|
woff = ["brotli (>=1.0.1) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\"", "zopfli (>=0.1.4)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "kiwisolver"
|
||||||
|
version = "1.4.9"
|
||||||
|
description = "A fast implementation of the Cassowary constraint solver"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.10"
|
||||||
|
groups = ["main"]
|
||||||
|
files = [
|
||||||
|
{file = "kiwisolver-1.4.9-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b4b4d74bda2b8ebf4da5bd42af11d02d04428b2c32846e4c2c93219df8a7987b"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:fb3b8132019ea572f4611d770991000d7f58127560c4889729248eb5852a102f"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:84fd60810829c27ae375114cd379da1fa65e6918e1da405f356a775d49a62bcf"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b78efa4c6e804ecdf727e580dbb9cba85624d2e1c6b5cb059c66290063bd99a9"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d4efec7bcf21671db6a3294ff301d2fc861c31faa3c8740d1a94689234d1b415"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp310-cp310-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:90f47e70293fc3688b71271100a1a5453aa9944a81d27ff779c108372cf5567b"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp310-cp310-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8fdca1def57a2e88ef339de1737a1449d6dbf5fab184c54a1fca01d541317154"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9cf554f21be770f5111a1690d42313e140355e687e05cf82cb23d0a721a64a48"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:fc1795ac5cd0510207482c3d1d3ed781143383b8cfd36f5c645f3897ce066220"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:ccd09f20ccdbbd341b21a67ab50a119b64a403b09288c27481575105283c1586"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:540c7c72324d864406a009d72f5d6856f49693db95d1fbb46cf86febef873634"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp310-cp310-win_amd64.whl", hash = "sha256:ede8c6d533bc6601a47ad4046080d36b8fc99f81e6f1c17b0ac3c2dc91ac7611"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp310-cp310-win_arm64.whl", hash = "sha256:7b4da0d01ac866a57dd61ac258c5607b4cd677f63abaec7b148354d2b2cdd536"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:eb14a5da6dc7642b0f3a18f13654847cd8b7a2550e2645a5bda677862b03ba16"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:39a219e1c81ae3b103643d2aedb90f1ef22650deb266ff12a19e7773f3e5f089"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2405a7d98604b87f3fc28b1716783534b1b4b8510d8142adca34ee0bc3c87543"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:dc1ae486f9abcef254b5618dfb4113dd49f94c68e3e027d03cf0143f3f772b61"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8a1f570ce4d62d718dce3f179ee78dac3b545ac16c0c04bb363b7607a949c0d1"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cb27e7b78d716c591e88e0a09a2139c6577865d7f2e152488c2cc6257f460872"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp311-cp311-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:15163165efc2f627eb9687ea5f3a28137217d217ac4024893d753f46bce9de26"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:bdee92c56a71d2b24c33a7d4c2856bd6419d017e08caa7802d2963870e315028"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:412f287c55a6f54b0650bd9b6dce5aceddb95864a1a90c87af16979d37c89771"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:2c93f00dcba2eea70af2be5f11a830a742fe6b579a1d4e00f47760ef13be247a"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f117e1a089d9411663a3207ba874f31be9ac8eaa5b533787024dc07aeb74f464"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp311-cp311-win_amd64.whl", hash = "sha256:be6a04e6c79819c9a8c2373317d19a96048e5a3f90bec587787e86a1153883c2"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp311-cp311-win_arm64.whl", hash = "sha256:0ae37737256ba2de764ddc12aed4956460277f00c4996d51a197e72f62f5eec7"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:ac5a486ac389dddcc5bef4f365b6ae3ffff2c433324fb38dd35e3fab7c957999"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f2ba92255faa7309d06fe44c3a4a97efe1c8d640c2a79a5ef728b685762a6fd2"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4a2899935e724dd1074cb568ce7ac0dce28b2cd6ab539c8e001a8578eb106d14"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f6008a4919fdbc0b0097089f67a1eb55d950ed7e90ce2cc3e640abadd2757a04"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:67bb8b474b4181770f926f7b7d2f8c0248cbcb78b660fdd41a47054b28d2a752"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2327a4a30d3ee07d2fbe2e7933e8a37c591663b96ce42a00bc67461a87d7df77"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7a08b491ec91b1d5053ac177afe5290adacf1f0f6307d771ccac5de30592d198"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d8fc5c867c22b828001b6a38d2eaeb88160bf5783c6cb4a5e440efc981ce286d"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:3b3115b2581ea35bb6d1f24a4c90af37e5d9b49dcff267eeed14c3893c5b86ab"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:858e4c22fb075920b96a291928cb7dea5644e94c0ee4fcd5af7e865655e4ccf2"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ed0fecd28cc62c54b262e3736f8bb2512d8dcfdc2bcf08be5f47f96bf405b145"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp312-cp312-win_amd64.whl", hash = "sha256:f68208a520c3d86ea51acf688a3e3002615a7f0238002cccc17affecc86a8a54"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp312-cp312-win_arm64.whl", hash = "sha256:2c1a4f57df73965f3f14df20b80ee29e6a7930a57d2d9e8491a25f676e197c60"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a5d0432ccf1c7ab14f9949eec60c5d1f924f17c037e9f8b33352fa05799359b8"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efb3a45b35622bb6c16dbfab491a8f5a391fe0e9d45ef32f4df85658232ca0e2"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1a12cf6398e8a0a001a059747a1cbf24705e18fe413bc22de7b3d15c67cffe3f"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b67e6efbf68e077dd71d1a6b37e43e1a99d0bff1a3d51867d45ee8908b931098"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5656aa670507437af0207645273ccdfee4f14bacd7f7c67a4306d0dcaeaf6eed"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:bfc08add558155345129c7803b3671cf195e6a56e7a12f3dde7c57d9b417f525"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:40092754720b174e6ccf9e845d0d8c7d8e12c3d71e7fc35f55f3813e96376f78"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:497d05f29a1300d14e02e6441cf0f5ee81c1ff5a304b0d9fb77423974684e08b"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:bdd1a81a1860476eb41ac4bc1e07b3f07259e6d55bbf739b79c8aaedcf512799"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:e6b93f13371d341afee3be9f7c5964e3fe61d5fa30f6a30eb49856935dfe4fc3"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d75aa530ccfaa593da12834b86a0724f58bff12706659baa9227c2ccaa06264c"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp313-cp313-win_amd64.whl", hash = "sha256:dd0a578400839256df88c16abddf9ba14813ec5f21362e1fe65022e00c883d4d"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp313-cp313-win_arm64.whl", hash = "sha256:d4188e73af84ca82468f09cadc5ac4db578109e52acb4518d8154698d3a87ca2"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:5a0f2724dfd4e3b3ac5a82436a8e6fd16baa7d507117e4279b660fe8ca38a3a1"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:1b11d6a633e4ed84fc0ddafd4ebfd8ea49b3f25082c04ad12b8315c11d504dc1"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61874cdb0a36016354853593cffc38e56fc9ca5aa97d2c05d3dcf6922cd55a11"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:60c439763a969a6af93b4881db0eed8fadf93ee98e18cbc35bc8da868d0c4f0c"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92a2f997387a1b79a75e7803aa7ded2cfbe2823852ccf1ba3bcf613b62ae3197"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp313-cp313t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a31d512c812daea6d8b3be3b2bfcbeb091dbb09177706569bcfc6240dcf8b41c"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp313-cp313t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:52a15b0f35dad39862d376df10c5230155243a2c1a436e39eb55623ccbd68185"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a30fd6fdef1430fd9e1ba7b3398b5ee4e2887783917a687d86ba69985fb08748"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:cc9617b46837c6468197b5945e196ee9ca43057bb7d9d1ae688101e4e1dddf64"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:0ab74e19f6a2b027ea4f845a78827969af45ce790e6cb3e1ebab71bdf9f215ff"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dba5ee5d3981160c28d5490f0d1b7ed730c22470ff7f6cc26cfcfaacb9896a07"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp313-cp313t-win_arm64.whl", hash = "sha256:0749fd8f4218ad2e851e11cc4dc05c7cbc0cbc4267bdfdb31782e65aace4ee9c"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:9928fe1eb816d11ae170885a74d074f57af3a0d65777ca47e9aeb854a1fba386"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:d0005b053977e7b43388ddec89fa567f43d4f6d5c2c0affe57de5ebf290dc552"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:2635d352d67458b66fd0667c14cb1d4145e9560d503219034a18a87e971ce4f3"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:767c23ad1c58c9e827b649a9ab7809fd5fd9db266a9cf02b0e926ddc2c680d58"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:72d0eb9fba308b8311685c2268cf7d0a0639a6cd027d8128659f72bdd8a024b4"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f68e4f3eeca8fb22cc3d731f9715a13b652795ef657a13df1ad0c7dc0e9731df"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d84cd4061ae292d8ac367b2c3fa3aad11cb8625a95d135fe93f286f914f3f5a6"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a60ea74330b91bd22a29638940d115df9dc00af5035a9a2a6ad9399ffb4ceca5"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:ce6a3a4e106cf35c2d9c4fa17c05ce0b180db622736845d4315519397a77beaf"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:77937e5e2a38a7b48eef0585114fe7930346993a88060d0bf886086d2aa49ef5"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:24c175051354f4a28c5d6a31c93906dc653e2bf234e8a4bbfb964892078898ce"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp314-cp314-win_amd64.whl", hash = "sha256:0763515d4df10edf6d06a3c19734e2566368980d21ebec439f33f9eb936c07b7"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp314-cp314-win_arm64.whl", hash = "sha256:0e4e2bf29574a6a7b7f6cb5fa69293b9f96c928949ac4a53ba3f525dffb87f9c"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:d976bbb382b202f71c67f77b0ac11244021cfa3f7dfd9e562eefcea2df711548"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2489e4e5d7ef9a1c300a5e0196e43d9c739f066ef23270607d45aba368b91f2d"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:e2ea9f7ab7fbf18fffb1b5434ce7c69a07582f7acc7717720f1d69f3e806f90c"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b34e51affded8faee0dfdb705416153819d8ea9250bbbf7ea1b249bdeb5f1122"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d8aacd3d4b33b772542b2e01beb50187536967b514b00003bdda7589722d2a64"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7cf974dd4e35fa315563ac99d6287a1024e4dc2077b8a7d7cd3d2fb65d283134"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:85bd218b5ecfbee8c8a82e121802dcb519a86044c9c3b2e4aef02fa05c6da370"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:0856e241c2d3df4efef7c04a1e46b1936b6120c9bcf36dd216e3acd84bc4fb21"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:9af39d6551f97d31a4deebeac6f45b156f9755ddc59c07b402c148f5dbb6482a"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:bb4ae2b57fc1d8cbd1cf7b1d9913803681ffa903e7488012be5b76dedf49297f"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:aedff62918805fb62d43a4aa2ecd4482c380dc76cd31bd7c8878588a61bd0369"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp314-cp314t-win_amd64.whl", hash = "sha256:1fa333e8b2ce4d9660f2cda9c0e1b6bafcfb2457a9d259faa82289e73ec24891"},
|
||||||
|
{file = "kiwisolver-1.4.9-cp314-cp314t-win_arm64.whl", hash = "sha256:4a48a2ce79d65d363597ef7b567ce3d14d68783d2b2263d98db3d9477805ba32"},
|
||||||
|
{file = "kiwisolver-1.4.9-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:4d1d9e582ad4d63062d34077a9a1e9f3c34088a2ec5135b1f7190c07cf366527"},
|
||||||
|
{file = "kiwisolver-1.4.9-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:deed0c7258ceb4c44ad5ec7d9918f9f14fd05b2be86378d86cf50e63d1e7b771"},
|
||||||
|
{file = "kiwisolver-1.4.9-pp310-pypy310_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0a590506f303f512dff6b7f75fd2fd18e16943efee932008fe7140e5fa91d80e"},
|
||||||
|
{file = "kiwisolver-1.4.9-pp310-pypy310_pp73-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e09c2279a4d01f099f52d5c4b3d9e208e91edcbd1a175c9662a8b16e000fece9"},
|
||||||
|
{file = "kiwisolver-1.4.9-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c9e7cdf45d594ee04d5be1b24dd9d49f3d1590959b2271fb30b5ca2b262c00fb"},
|
||||||
|
{file = "kiwisolver-1.4.9-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:720e05574713db64c356e86732c0f3c5252818d05f9df320f0ad8380641acea5"},
|
||||||
|
{file = "kiwisolver-1.4.9-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:17680d737d5335b552994a2008fab4c851bcd7de33094a82067ef3a576ff02fa"},
|
||||||
|
{file = "kiwisolver-1.4.9-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:85b5352f94e490c028926ea567fc569c52ec79ce131dadb968d3853e809518c2"},
|
||||||
|
{file = "kiwisolver-1.4.9-pp311-pypy311_pp73-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:464415881e4801295659462c49461a24fb107c140de781d55518c4b80cb6790f"},
|
||||||
|
{file = "kiwisolver-1.4.9-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:fb940820c63a9590d31d88b815e7a3aa5915cad3ce735ab45f0c730b39547de1"},
|
||||||
|
{file = "kiwisolver-1.4.9.tar.gz", hash = "sha256:c3b22c26c6fd6811b0ae8363b95ca8ce4ea3c202d3d0975b2914310ceb1bcc4d"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "matplotlib"
|
||||||
|
version = "3.10.8"
|
||||||
|
description = "Python plotting package"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.10"
|
||||||
|
groups = ["main"]
|
||||||
|
files = [
|
||||||
|
{file = "matplotlib-3.10.8-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:00270d217d6b20d14b584c521f810d60c5c78406dc289859776550df837dcda7"},
|
||||||
|
{file = "matplotlib-3.10.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:37b3c1cc42aa184b3f738cfa18c1c1d72fd496d85467a6cf7b807936d39aa656"},
|
||||||
|
{file = "matplotlib-3.10.8-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ee40c27c795bda6a5292e9cff9890189d32f7e3a0bf04e0e3c9430c4a00c37df"},
|
||||||
|
{file = "matplotlib-3.10.8-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a48f2b74020919552ea25d222d5cc6af9ca3f4eb43a93e14d068457f545c2a17"},
|
||||||
|
{file = "matplotlib-3.10.8-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f254d118d14a7f99d616271d6c3c27922c092dac11112670b157798b89bf4933"},
|
||||||
|
{file = "matplotlib-3.10.8-cp310-cp310-win_amd64.whl", hash = "sha256:f9b587c9c7274c1613a30afabf65a272114cd6cdbe67b3406f818c79d7ab2e2a"},
|
||||||
|
{file = "matplotlib-3.10.8-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:6be43b667360fef5c754dda5d25a32e6307a03c204f3c0fc5468b78fa87b4160"},
|
||||||
|
{file = "matplotlib-3.10.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a2b336e2d91a3d7006864e0990c83b216fcdca64b5a6484912902cef87313d78"},
|
||||||
|
{file = "matplotlib-3.10.8-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:efb30e3baaea72ce5928e32bab719ab4770099079d66726a62b11b1ef7273be4"},
|
||||||
|
{file = "matplotlib-3.10.8-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d56a1efd5bfd61486c8bc968fa18734464556f0fb8e51690f4ac25d85cbbbbc2"},
|
||||||
|
{file = "matplotlib-3.10.8-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:238b7ce5717600615c895050239ec955d91f321c209dd110db988500558e70d6"},
|
||||||
|
{file = "matplotlib-3.10.8-cp311-cp311-win_amd64.whl", hash = "sha256:18821ace09c763ec93aef5eeff087ee493a24051936d7b9ebcad9662f66501f9"},
|
||||||
|
{file = "matplotlib-3.10.8-cp311-cp311-win_arm64.whl", hash = "sha256:bab485bcf8b1c7d2060b4fcb6fc368a9e6f4cd754c9c2fea281f4be21df394a2"},
|
||||||
|
{file = "matplotlib-3.10.8-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:64fcc24778ca0404ce0cb7b6b77ae1f4c7231cdd60e6778f999ee05cbd581b9a"},
|
||||||
|
{file = "matplotlib-3.10.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b9a5ca4ac220a0cdd1ba6bcba3608547117d30468fefce49bb26f55c1a3d5c58"},
|
||||||
|
{file = "matplotlib-3.10.8-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3ab4aabc72de4ff77b3ec33a6d78a68227bf1123465887f9905ba79184a1cc04"},
|
||||||
|
{file = "matplotlib-3.10.8-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:24d50994d8c5816ddc35411e50a86ab05f575e2530c02752e02538122613371f"},
|
||||||
|
{file = "matplotlib-3.10.8-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:99eefd13c0dc3b3c1b4d561c1169e65fe47aab7b8158754d7c084088e2329466"},
|
||||||
|
{file = "matplotlib-3.10.8-cp312-cp312-win_amd64.whl", hash = "sha256:dd80ecb295460a5d9d260df63c43f4afbdd832d725a531f008dad1664f458adf"},
|
||||||
|
{file = "matplotlib-3.10.8-cp312-cp312-win_arm64.whl", hash = "sha256:3c624e43ed56313651bc18a47f838b60d7b8032ed348911c54906b130b20071b"},
|
||||||
|
{file = "matplotlib-3.10.8-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:3f2e409836d7f5ac2f1c013110a4d50b9f7edc26328c108915f9075d7d7a91b6"},
|
||||||
|
{file = "matplotlib-3.10.8-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:56271f3dac49a88d7fca5060f004d9d22b865f743a12a23b1e937a0be4818ee1"},
|
||||||
|
{file = "matplotlib-3.10.8-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a0a7f52498f72f13d4a25ea70f35f4cb60642b466cbb0a9be951b5bc3f45a486"},
|
||||||
|
{file = "matplotlib-3.10.8-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:646d95230efb9ca614a7a594d4fcacde0ac61d25e37dd51710b36477594963ce"},
|
||||||
|
{file = "matplotlib-3.10.8-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f89c151aab2e2e23cb3fe0acad1e8b82841fd265379c4cecd0f3fcb34c15e0f6"},
|
||||||
|
{file = "matplotlib-3.10.8-cp313-cp313-win_amd64.whl", hash = "sha256:e8ea3e2d4066083e264e75c829078f9e149fa119d27e19acd503de65e0b13149"},
|
||||||
|
{file = "matplotlib-3.10.8-cp313-cp313-win_arm64.whl", hash = "sha256:c108a1d6fa78a50646029cb6d49808ff0fc1330fda87fa6f6250c6b5369b6645"},
|
||||||
|
{file = "matplotlib-3.10.8-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:ad3d9833a64cf48cc4300f2b406c3d0f4f4724a91c0bd5640678a6ba7c102077"},
|
||||||
|
{file = "matplotlib-3.10.8-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:eb3823f11823deade26ce3b9f40dcb4a213da7a670013929f31d5f5ed1055b22"},
|
||||||
|
{file = "matplotlib-3.10.8-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d9050fee89a89ed57b4fb2c1bfac9a3d0c57a0d55aed95949eedbc42070fea39"},
|
||||||
|
{file = "matplotlib-3.10.8-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b44d07310e404ba95f8c25aa5536f154c0a8ec473303535949e52eb71d0a1565"},
|
||||||
|
{file = "matplotlib-3.10.8-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:0a33deb84c15ede243aead39f77e990469fff93ad1521163305095b77b72ce4a"},
|
||||||
|
{file = "matplotlib-3.10.8-cp313-cp313t-win_amd64.whl", hash = "sha256:3a48a78d2786784cc2413e57397981fb45c79e968d99656706018d6e62e57958"},
|
||||||
|
{file = "matplotlib-3.10.8-cp313-cp313t-win_arm64.whl", hash = "sha256:15d30132718972c2c074cd14638c7f4592bd98719e2308bccea40e0538bc0cb5"},
|
||||||
|
{file = "matplotlib-3.10.8-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:b53285e65d4fa4c86399979e956235deb900be5baa7fc1218ea67fbfaeaadd6f"},
|
||||||
|
{file = "matplotlib-3.10.8-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:32f8dce744be5569bebe789e46727946041199030db8aeb2954d26013a0eb26b"},
|
||||||
|
{file = "matplotlib-3.10.8-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4cf267add95b1c88300d96ca837833d4112756045364f5c734a2276038dae27d"},
|
||||||
|
{file = "matplotlib-3.10.8-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2cf5bd12cecf46908f286d7838b2abc6c91cda506c0445b8223a7c19a00df008"},
|
||||||
|
{file = "matplotlib-3.10.8-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:41703cc95688f2516b480f7f339d8851a6035f18e100ee6a32bc0b8536a12a9c"},
|
||||||
|
{file = "matplotlib-3.10.8-cp314-cp314-win_amd64.whl", hash = "sha256:83d282364ea9f3e52363da262ce32a09dfe241e4080dcedda3c0db059d3c1f11"},
|
||||||
|
{file = "matplotlib-3.10.8-cp314-cp314-win_arm64.whl", hash = "sha256:2c1998e92cd5999e295a731bcb2911c75f597d937341f3030cc24ef2733d78a8"},
|
||||||
|
{file = "matplotlib-3.10.8-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:b5a2b97dbdc7d4f353ebf343744f1d1f1cca8aa8bfddb4262fcf4306c3761d50"},
|
||||||
|
{file = "matplotlib-3.10.8-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:3f5c3e4da343bba819f0234186b9004faba952cc420fbc522dc4e103c1985908"},
|
||||||
|
{file = "matplotlib-3.10.8-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f62550b9a30afde8c1c3ae450e5eb547d579dd69b25c2fc7a1c67f934c1717a"},
|
||||||
|
{file = "matplotlib-3.10.8-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:495672de149445ec1b772ff2c9ede9b769e3cb4f0d0aa7fa730d7f59e2d4e1c1"},
|
||||||
|
{file = "matplotlib-3.10.8-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:595ba4d8fe983b88f0eec8c26a241e16d6376fe1979086232f481f8f3f67494c"},
|
||||||
|
{file = "matplotlib-3.10.8-cp314-cp314t-win_amd64.whl", hash = "sha256:25d380fe8b1dc32cf8f0b1b448470a77afb195438bafdf1d858bfb876f3edf7b"},
|
||||||
|
{file = "matplotlib-3.10.8-cp314-cp314t-win_arm64.whl", hash = "sha256:113bb52413ea508ce954a02c10ffd0d565f9c3bc7f2eddc27dfe1731e71c7b5f"},
|
||||||
|
{file = "matplotlib-3.10.8-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:f97aeb209c3d2511443f8797e3e5a569aebb040d4f8bc79aa3ee78a8fb9e3dd8"},
|
||||||
|
{file = "matplotlib-3.10.8-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:fb061f596dad3a0f52b60dc6a5dec4a0c300dec41e058a7efe09256188d170b7"},
|
||||||
|
{file = "matplotlib-3.10.8-pp310-pypy310_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:12d90df9183093fcd479f4172ac26b322b1248b15729cb57f42f71f24c7e37a3"},
|
||||||
|
{file = "matplotlib-3.10.8-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:6da7c2ce169267d0d066adcf63758f0604aa6c3eebf67458930f9d9b79ad1db1"},
|
||||||
|
{file = "matplotlib-3.10.8-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:9153c3292705be9f9c64498a8872118540c3f4123d1a1c840172edf262c8be4a"},
|
||||||
|
{file = "matplotlib-3.10.8-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1ae029229a57cd1e8fe542485f27e7ca7b23aa9e8944ddb4985d0bc444f1eca2"},
|
||||||
|
{file = "matplotlib-3.10.8.tar.gz", hash = "sha256:2299372c19d56bcd35cf05a2738308758d32b9eaed2371898d8f5bd33f084aa3"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
contourpy = ">=1.0.1"
|
||||||
|
cycler = ">=0.10"
|
||||||
|
fonttools = ">=4.22.0"
|
||||||
|
kiwisolver = ">=1.3.1"
|
||||||
|
numpy = ">=1.23"
|
||||||
|
packaging = ">=20.0"
|
||||||
|
pillow = ">=8"
|
||||||
|
pyparsing = ">=3"
|
||||||
|
python-dateutil = ">=2.7"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
dev = ["meson-python (>=0.13.1,<0.17.0)", "pybind11 (>=2.13.2,!=2.13.3)", "setuptools (>=64)", "setuptools_scm (>=7)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "numpy"
|
||||||
|
version = "2.2.6"
|
||||||
|
description = "Fundamental package for array computing in Python"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.10"
|
||||||
|
groups = ["main"]
|
||||||
|
markers = "python_version == \"3.10\""
|
||||||
|
files = [
|
||||||
|
{file = "numpy-2.2.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b412caa66f72040e6d268491a59f2c43bf03eb6c96dd8f0307829feb7fa2b6fb"},
|
||||||
|
{file = "numpy-2.2.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e41fd67c52b86603a91c1a505ebaef50b3314de0213461c7a6e99c9a3beff90"},
|
||||||
|
{file = "numpy-2.2.6-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:37e990a01ae6ec7fe7fa1c26c55ecb672dd98b19c3d0e1d1f326fa13cb38d163"},
|
||||||
|
{file = "numpy-2.2.6-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:5a6429d4be8ca66d889b7cf70f536a397dc45ba6faeb5f8c5427935d9592e9cf"},
|
||||||
|
{file = "numpy-2.2.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:efd28d4e9cd7d7a8d39074a4d44c63eda73401580c5c76acda2ce969e0a38e83"},
|
||||||
|
{file = "numpy-2.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc7b73d02efb0e18c000e9ad8b83480dfcd5dfd11065997ed4c6747470ae8915"},
|
||||||
|
{file = "numpy-2.2.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:74d4531beb257d2c3f4b261bfb0fc09e0f9ebb8842d82a7b4209415896adc680"},
|
||||||
|
{file = "numpy-2.2.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8fc377d995680230e83241d8a96def29f204b5782f371c532579b4f20607a289"},
|
||||||
|
{file = "numpy-2.2.6-cp310-cp310-win32.whl", hash = "sha256:b093dd74e50a8cba3e873868d9e93a85b78e0daf2e98c6797566ad8044e8363d"},
|
||||||
|
{file = "numpy-2.2.6-cp310-cp310-win_amd64.whl", hash = "sha256:f0fd6321b839904e15c46e0d257fdd101dd7f530fe03fd6359c1ea63738703f3"},
|
||||||
|
{file = "numpy-2.2.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f9f1adb22318e121c5c69a09142811a201ef17ab257a1e66ca3025065b7f53ae"},
|
||||||
|
{file = "numpy-2.2.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c820a93b0255bc360f53eca31a0e676fd1101f673dda8da93454a12e23fc5f7a"},
|
||||||
|
{file = "numpy-2.2.6-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:3d70692235e759f260c3d837193090014aebdf026dfd167834bcba43e30c2a42"},
|
||||||
|
{file = "numpy-2.2.6-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:481b49095335f8eed42e39e8041327c05b0f6f4780488f61286ed3c01368d491"},
|
||||||
|
{file = "numpy-2.2.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b64d8d4d17135e00c8e346e0a738deb17e754230d7e0810ac5012750bbd85a5a"},
|
||||||
|
{file = "numpy-2.2.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba10f8411898fc418a521833e014a77d3ca01c15b0c6cdcce6a0d2897e6dbbdf"},
|
||||||
|
{file = "numpy-2.2.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:bd48227a919f1bafbdda0583705e547892342c26fb127219d60a5c36882609d1"},
|
||||||
|
{file = "numpy-2.2.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9551a499bf125c1d4f9e250377c1ee2eddd02e01eac6644c080162c0c51778ab"},
|
||||||
|
{file = "numpy-2.2.6-cp311-cp311-win32.whl", hash = "sha256:0678000bb9ac1475cd454c6b8c799206af8107e310843532b04d49649c717a47"},
|
||||||
|
{file = "numpy-2.2.6-cp311-cp311-win_amd64.whl", hash = "sha256:e8213002e427c69c45a52bbd94163084025f533a55a59d6f9c5b820774ef3303"},
|
||||||
|
{file = "numpy-2.2.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:41c5a21f4a04fa86436124d388f6ed60a9343a6f767fced1a8a71c3fbca038ff"},
|
||||||
|
{file = "numpy-2.2.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:de749064336d37e340f640b05f24e9e3dd678c57318c7289d222a8a2f543e90c"},
|
||||||
|
{file = "numpy-2.2.6-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:894b3a42502226a1cac872f840030665f33326fc3dac8e57c607905773cdcde3"},
|
||||||
|
{file = "numpy-2.2.6-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:71594f7c51a18e728451bb50cc60a3ce4e6538822731b2933209a1f3614e9282"},
|
||||||
|
{file = "numpy-2.2.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2618db89be1b4e05f7a1a847a9c1c0abd63e63a1607d892dd54668dd92faf87"},
|
||||||
|
{file = "numpy-2.2.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd83c01228a688733f1ded5201c678f0c53ecc1006ffbc404db9f7a899ac6249"},
|
||||||
|
{file = "numpy-2.2.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:37c0ca431f82cd5fa716eca9506aefcabc247fb27ba69c5062a6d3ade8cf8f49"},
|
||||||
|
{file = "numpy-2.2.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fe27749d33bb772c80dcd84ae7e8df2adc920ae8297400dabec45f0dedb3f6de"},
|
||||||
|
{file = "numpy-2.2.6-cp312-cp312-win32.whl", hash = "sha256:4eeaae00d789f66c7a25ac5f34b71a7035bb474e679f410e5e1a94deb24cf2d4"},
|
||||||
|
{file = "numpy-2.2.6-cp312-cp312-win_amd64.whl", hash = "sha256:c1f9540be57940698ed329904db803cf7a402f3fc200bfe599334c9bd84a40b2"},
|
||||||
|
{file = "numpy-2.2.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0811bb762109d9708cca4d0b13c4f67146e3c3b7cf8d34018c722adb2d957c84"},
|
||||||
|
{file = "numpy-2.2.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:287cc3162b6f01463ccd86be154f284d0893d2b3ed7292439ea97eafa8170e0b"},
|
||||||
|
{file = "numpy-2.2.6-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:f1372f041402e37e5e633e586f62aa53de2eac8d98cbfb822806ce4bbefcb74d"},
|
||||||
|
{file = "numpy-2.2.6-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:55a4d33fa519660d69614a9fad433be87e5252f4b03850642f88993f7b2ca566"},
|
||||||
|
{file = "numpy-2.2.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f92729c95468a2f4f15e9bb94c432a9229d0d50de67304399627a943201baa2f"},
|
||||||
|
{file = "numpy-2.2.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bc23a79bfabc5d056d106f9befb8d50c31ced2fbc70eedb8155aec74a45798f"},
|
||||||
|
{file = "numpy-2.2.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e3143e4451880bed956e706a3220b4e5cf6172ef05fcc397f6f36a550b1dd868"},
|
||||||
|
{file = "numpy-2.2.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b4f13750ce79751586ae2eb824ba7e1e8dba64784086c98cdbbcc6a42112ce0d"},
|
||||||
|
{file = "numpy-2.2.6-cp313-cp313-win32.whl", hash = "sha256:5beb72339d9d4fa36522fc63802f469b13cdbe4fdab4a288f0c441b74272ebfd"},
|
||||||
|
{file = "numpy-2.2.6-cp313-cp313-win_amd64.whl", hash = "sha256:b0544343a702fa80c95ad5d3d608ea3599dd54d4632df855e4c8d24eb6ecfa1c"},
|
||||||
|
{file = "numpy-2.2.6-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0bca768cd85ae743b2affdc762d617eddf3bcf8724435498a1e80132d04879e6"},
|
||||||
|
{file = "numpy-2.2.6-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:fc0c5673685c508a142ca65209b4e79ed6740a4ed6b2267dbba90f34b0b3cfda"},
|
||||||
|
{file = "numpy-2.2.6-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:5bd4fc3ac8926b3819797a7c0e2631eb889b4118a9898c84f585a54d475b7e40"},
|
||||||
|
{file = "numpy-2.2.6-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:fee4236c876c4e8369388054d02d0e9bb84821feb1a64dd59e137e6511a551f8"},
|
||||||
|
{file = "numpy-2.2.6-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1dda9c7e08dc141e0247a5b8f49cf05984955246a327d4c48bda16821947b2f"},
|
||||||
|
{file = "numpy-2.2.6-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f447e6acb680fd307f40d3da4852208af94afdfab89cf850986c3ca00562f4fa"},
|
||||||
|
{file = "numpy-2.2.6-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:389d771b1623ec92636b0786bc4ae56abafad4a4c513d36a55dce14bd9ce8571"},
|
||||||
|
{file = "numpy-2.2.6-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8e9ace4a37db23421249ed236fdcdd457d671e25146786dfc96835cd951aa7c1"},
|
||||||
|
{file = "numpy-2.2.6-cp313-cp313t-win32.whl", hash = "sha256:038613e9fb8c72b0a41f025a7e4c3f0b7a1b5d768ece4796b674c8f3fe13efff"},
|
||||||
|
{file = "numpy-2.2.6-cp313-cp313t-win_amd64.whl", hash = "sha256:6031dd6dfecc0cf9f668681a37648373bddd6421fff6c66ec1624eed0180ee06"},
|
||||||
|
{file = "numpy-2.2.6-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0b605b275d7bd0c640cad4e5d30fa701a8d59302e127e5f79138ad62762c3e3d"},
|
||||||
|
{file = "numpy-2.2.6-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:7befc596a7dc9da8a337f79802ee8adb30a552a94f792b9c9d18c840055907db"},
|
||||||
|
{file = "numpy-2.2.6-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce47521a4754c8f4593837384bd3424880629f718d87c5d44f8ed763edd63543"},
|
||||||
|
{file = "numpy-2.2.6-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d042d24c90c41b54fd506da306759e06e568864df8ec17ccc17e9e884634fd00"},
|
||||||
|
{file = "numpy-2.2.6.tar.gz", hash = "sha256:e29554e2bef54a90aa5cc07da6ce955accb83f21ab5de01a62c8478897b264fd"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "numpy"
|
||||||
|
version = "2.4.2"
|
||||||
|
description = "Fundamental package for array computing in Python"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.11"
|
||||||
|
groups = ["main"]
|
||||||
|
markers = "python_version >= \"3.11\""
|
||||||
|
files = [
|
||||||
|
{file = "numpy-2.4.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e7e88598032542bd49af7c4747541422884219056c268823ef6e5e89851c8825"},
|
||||||
|
{file = "numpy-2.4.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7edc794af8b36ca37ef5fcb5e0d128c7e0595c7b96a2318d1badb6fcd8ee86b1"},
|
||||||
|
{file = "numpy-2.4.2-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:6e9f61981ace1360e42737e2bae58b27bf28a1b27e781721047d84bd754d32e7"},
|
||||||
|
{file = "numpy-2.4.2-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:cb7bbb88aa74908950d979eeaa24dbdf1a865e3c7e45ff0121d8f70387b55f73"},
|
||||||
|
{file = "numpy-2.4.2-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4f069069931240b3fc703f1e23df63443dbd6390614c8c44a87d96cd0ec81eb1"},
|
||||||
|
{file = "numpy-2.4.2-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c02ef4401a506fb60b411467ad501e1429a3487abca4664871d9ae0b46c8ba32"},
|
||||||
|
{file = "numpy-2.4.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2653de5c24910e49c2b106499803124dde62a5a1fe0eedeaecf4309a5f639390"},
|
||||||
|
{file = "numpy-2.4.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1ae241bbfc6ae276f94a170b14785e561cb5e7f626b6688cf076af4110887413"},
|
||||||
|
{file = "numpy-2.4.2-cp311-cp311-win32.whl", hash = "sha256:df1b10187212b198dd45fa943d8985a3c8cf854aed4923796e0e019e113a1bda"},
|
||||||
|
{file = "numpy-2.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:b9c618d56a29c9cb1c4da979e9899be7578d2e0b3c24d52079c166324c9e8695"},
|
||||||
|
{file = "numpy-2.4.2-cp311-cp311-win_arm64.whl", hash = "sha256:47c5a6ed21d9452b10227e5e8a0e1c22979811cad7dcc19d8e3e2fb8fa03f1a3"},
|
||||||
|
{file = "numpy-2.4.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:21982668592194c609de53ba4933a7471880ccbaadcc52352694a59ecc860b3a"},
|
||||||
|
{file = "numpy-2.4.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40397bda92382fcec844066efb11f13e1c9a3e2a8e8f318fb72ed8b6db9f60f1"},
|
||||||
|
{file = "numpy-2.4.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:b3a24467af63c67829bfaa61eecf18d5432d4f11992688537be59ecd6ad32f5e"},
|
||||||
|
{file = "numpy-2.4.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:805cc8de9fd6e7a22da5aed858e0ab16be5a4db6c873dde1d7451c541553aa27"},
|
||||||
|
{file = "numpy-2.4.2-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d82351358ffbcdcd7b686b90742a9b86632d6c1c051016484fa0b326a0a1548"},
|
||||||
|
{file = "numpy-2.4.2-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9e35d3e0144137d9fdae62912e869136164534d64a169f86438bc9561b6ad49f"},
|
||||||
|
{file = "numpy-2.4.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:adb6ed2ad29b9e15321d167d152ee909ec73395901b70936f029c3bc6d7f4460"},
|
||||||
|
{file = "numpy-2.4.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8906e71fd8afcb76580404e2a950caef2685df3d2a57fe82a86ac8d33cc007ba"},
|
||||||
|
{file = "numpy-2.4.2-cp312-cp312-win32.whl", hash = "sha256:ec055f6dae239a6299cace477b479cca2fc125c5675482daf1dd886933a1076f"},
|
||||||
|
{file = "numpy-2.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:209fae046e62d0ce6435fcfe3b1a10537e858249b3d9b05829e2a05218296a85"},
|
||||||
|
{file = "numpy-2.4.2-cp312-cp312-win_arm64.whl", hash = "sha256:fbde1b0c6e81d56f5dccd95dd4a711d9b95df1ae4009a60887e56b27e8d903fa"},
|
||||||
|
{file = "numpy-2.4.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:25f2059807faea4b077a2b6837391b5d830864b3543627f381821c646f31a63c"},
|
||||||
|
{file = "numpy-2.4.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bd3a7a9f5847d2fb8c2c6d1c862fa109c31a9abeca1a3c2bd5a64572955b2979"},
|
||||||
|
{file = "numpy-2.4.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:8e4549f8a3c6d13d55041925e912bfd834285ef1dd64d6bc7d542583355e2e98"},
|
||||||
|
{file = "numpy-2.4.2-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:aea4f66ff44dfddf8c2cffd66ba6538c5ec67d389285292fe428cb2c738c8aef"},
|
||||||
|
{file = "numpy-2.4.2-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c3cd545784805de05aafe1dde61752ea49a359ccba9760c1e5d1c88a93bbf2b7"},
|
||||||
|
{file = "numpy-2.4.2-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d0d9b7c93578baafcbc5f0b83eaf17b79d345c6f36917ba0c67f45226911d499"},
|
||||||
|
{file = "numpy-2.4.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f74f0f7779cc7ae07d1810aab8ac6b1464c3eafb9e283a40da7309d5e6e48fbb"},
|
||||||
|
{file = "numpy-2.4.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c7ac672d699bf36275c035e16b65539931347d68b70667d28984c9fb34e07fa7"},
|
||||||
|
{file = "numpy-2.4.2-cp313-cp313-win32.whl", hash = "sha256:8e9afaeb0beff068b4d9cd20d322ba0ee1cecfb0b08db145e4ab4dd44a6b5110"},
|
||||||
|
{file = "numpy-2.4.2-cp313-cp313-win_amd64.whl", hash = "sha256:7df2de1e4fba69a51c06c28f5a3de36731eb9639feb8e1cf7e4a7b0daf4cf622"},
|
||||||
|
{file = "numpy-2.4.2-cp313-cp313-win_arm64.whl", hash = "sha256:0fece1d1f0a89c16b03442eae5c56dc0be0c7883b5d388e0c03f53019a4bfd71"},
|
||||||
|
{file = "numpy-2.4.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5633c0da313330fd20c484c78cdd3f9b175b55e1a766c4a174230c6b70ad8262"},
|
||||||
|
{file = "numpy-2.4.2-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:d9f64d786b3b1dd742c946c42d15b07497ed14af1a1f3ce840cce27daa0ce913"},
|
||||||
|
{file = "numpy-2.4.2-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:b21041e8cb6a1eb5312dd1d2f80a94d91efffb7a06b70597d44f1bd2dfc315ab"},
|
||||||
|
{file = "numpy-2.4.2-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:00ab83c56211a1d7c07c25e3217ea6695e50a3e2f255053686b081dc0b091a82"},
|
||||||
|
{file = "numpy-2.4.2-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2fb882da679409066b4603579619341c6d6898fc83a8995199d5249f986e8e8f"},
|
||||||
|
{file = "numpy-2.4.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:66cb9422236317f9d44b67b4d18f44efe6e9c7f8794ac0462978513359461554"},
|
||||||
|
{file = "numpy-2.4.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:0f01dcf33e73d80bd8dc0f20a71303abbafa26a19e23f6b68d1aa9990af90257"},
|
||||||
|
{file = "numpy-2.4.2-cp313-cp313t-win32.whl", hash = "sha256:52b913ec40ff7ae845687b0b34d8d93b60cb66dcee06996dd5c99f2fc9328657"},
|
||||||
|
{file = "numpy-2.4.2-cp313-cp313t-win_amd64.whl", hash = "sha256:5eea80d908b2c1f91486eb95b3fb6fab187e569ec9752ab7d9333d2e66bf2d6b"},
|
||||||
|
{file = "numpy-2.4.2-cp313-cp313t-win_arm64.whl", hash = "sha256:fd49860271d52127d61197bb50b64f58454e9f578cb4b2c001a6de8b1f50b0b1"},
|
||||||
|
{file = "numpy-2.4.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:444be170853f1f9d528428eceb55f12918e4fda5d8805480f36a002f1415e09b"},
|
||||||
|
{file = "numpy-2.4.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:d1240d50adff70c2a88217698ca844723068533f3f5c5fa6ee2e3220e3bdb000"},
|
||||||
|
{file = "numpy-2.4.2-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:7cdde6de52fb6664b00b056341265441192d1291c130e99183ec0d4b110ff8b1"},
|
||||||
|
{file = "numpy-2.4.2-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:cda077c2e5b780200b6b3e09d0b42205a3d1c68f30c6dceb90401c13bff8fe74"},
|
||||||
|
{file = "numpy-2.4.2-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d30291931c915b2ab5717c2974bb95ee891a1cf22ebc16a8006bd59cd210d40a"},
|
||||||
|
{file = "numpy-2.4.2-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bba37bc29d4d85761deed3954a1bc62be7cf462b9510b51d367b769a8c8df325"},
|
||||||
|
{file = "numpy-2.4.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b2f0073ed0868db1dcd86e052d37279eef185b9c8db5bf61f30f46adac63c909"},
|
||||||
|
{file = "numpy-2.4.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7f54844851cdb630ceb623dcec4db3240d1ac13d4990532446761baede94996a"},
|
||||||
|
{file = "numpy-2.4.2-cp314-cp314-win32.whl", hash = "sha256:12e26134a0331d8dbd9351620f037ec470b7c75929cb8a1537f6bfe411152a1a"},
|
||||||
|
{file = "numpy-2.4.2-cp314-cp314-win_amd64.whl", hash = "sha256:068cdb2d0d644cdb45670810894f6a0600797a69c05f1ac478e8d31670b8ee75"},
|
||||||
|
{file = "numpy-2.4.2-cp314-cp314-win_arm64.whl", hash = "sha256:6ed0be1ee58eef41231a5c943d7d1375f093142702d5723ca2eb07db9b934b05"},
|
||||||
|
{file = "numpy-2.4.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:98f16a80e917003a12c0580f97b5f875853ebc33e2eaa4bccfc8201ac6869308"},
|
||||||
|
{file = "numpy-2.4.2-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:20abd069b9cda45874498b245c8015b18ace6de8546bf50dfa8cea1696ed06ef"},
|
||||||
|
{file = "numpy-2.4.2-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:e98c97502435b53741540a5717a6749ac2ada901056c7db951d33e11c885cc7d"},
|
||||||
|
{file = "numpy-2.4.2-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:da6cad4e82cb893db4b69105c604d805e0c3ce11501a55b5e9f9083b47d2ffe8"},
|
||||||
|
{file = "numpy-2.4.2-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9e4424677ce4b47fe73c8b5556d876571f7c6945d264201180db2dc34f676ab5"},
|
||||||
|
{file = "numpy-2.4.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:2b8f157c8a6f20eb657e240f8985cc135598b2b46985c5bccbde7616dc9c6b1e"},
|
||||||
|
{file = "numpy-2.4.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5daf6f3914a733336dab21a05cdec343144600e964d2fcdabaac0c0269874b2a"},
|
||||||
|
{file = "numpy-2.4.2-cp314-cp314t-win32.whl", hash = "sha256:8c50dd1fc8826f5b26a5ee4d77ca55d88a895f4e4819c7ecc2a9f5905047a443"},
|
||||||
|
{file = "numpy-2.4.2-cp314-cp314t-win_amd64.whl", hash = "sha256:fcf92bee92742edd401ba41135185866f7026c502617f422eb432cfeca4fe236"},
|
||||||
|
{file = "numpy-2.4.2-cp314-cp314t-win_arm64.whl", hash = "sha256:1f92f53998a17265194018d1cc321b2e96e900ca52d54c7c77837b71b9465181"},
|
||||||
|
{file = "numpy-2.4.2-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:89f7268c009bc492f506abd6f5265defa7cb3f7487dc21d357c3d290add45082"},
|
||||||
|
{file = "numpy-2.4.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:e6dee3bb76aa4009d5a912180bf5b2de012532998d094acee25d9cb8dee3e44a"},
|
||||||
|
{file = "numpy-2.4.2-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:cd2bd2bbed13e213d6b55dc1d035a4f91748a7d3edc9480c13898b0353708920"},
|
||||||
|
{file = "numpy-2.4.2-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:cf28c0c1d4c4bf00f509fa7eb02c58d7caf221b50b467bcb0d9bbf1584d5c821"},
|
||||||
|
{file = "numpy-2.4.2-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e04ae107ac591763a47398bb45b568fc38f02dbc4aa44c063f67a131f99346cb"},
|
||||||
|
{file = "numpy-2.4.2-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:602f65afdef699cda27ec0b9224ae5dc43e328f4c24c689deaf77133dbee74d0"},
|
||||||
|
{file = "numpy-2.4.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:be71bf1edb48ebbbf7f6337b5bfd2f895d1902f6335a5830b20141fc126ffba0"},
|
||||||
|
{file = "numpy-2.4.2.tar.gz", hash = "sha256:659a6107e31a83c4e33f763942275fd278b21d095094044eb35569e86a21ddae"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "packaging"
|
||||||
|
version = "26.0"
|
||||||
|
description = "Core utilities for Python packages"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
groups = ["main"]
|
||||||
|
files = [
|
||||||
|
{file = "packaging-26.0-py3-none-any.whl", hash = "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529"},
|
||||||
|
{file = "packaging-26.0.tar.gz", hash = "sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pandas"
|
||||||
|
version = "2.3.3"
|
||||||
|
description = "Powerful data structures for data analysis, time series, and statistics"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.9"
|
||||||
|
groups = ["main"]
|
||||||
|
markers = "python_version == \"3.10\""
|
||||||
|
files = [
|
||||||
|
{file = "pandas-2.3.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:376c6446ae31770764215a6c937f72d917f214b43560603cd60da6408f183b6c"},
|
||||||
|
{file = "pandas-2.3.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e19d192383eab2f4ceb30b412b22ea30690c9e618f78870357ae1d682912015a"},
|
||||||
|
{file = "pandas-2.3.3-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5caf26f64126b6c7aec964f74266f435afef1c1b13da3b0636c7518a1fa3e2b1"},
|
||||||
|
{file = "pandas-2.3.3-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dd7478f1463441ae4ca7308a70e90b33470fa593429f9d4c578dd00d1fa78838"},
|
||||||
|
{file = "pandas-2.3.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4793891684806ae50d1288c9bae9330293ab4e083ccd1c5e383c34549c6e4250"},
|
||||||
|
{file = "pandas-2.3.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:28083c648d9a99a5dd035ec125d42439c6c1c525098c58af0fc38dd1a7a1b3d4"},
|
||||||
|
{file = "pandas-2.3.3-cp310-cp310-win_amd64.whl", hash = "sha256:503cf027cf9940d2ceaa1a93cfb5f8c8c7e6e90720a2850378f0b3f3b1e06826"},
|
||||||
|
{file = "pandas-2.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:602b8615ebcc4a0c1751e71840428ddebeb142ec02c786e8ad6b1ce3c8dec523"},
|
||||||
|
{file = "pandas-2.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8fe25fc7b623b0ef6b5009149627e34d2a4657e880948ec3c840e9402e5c1b45"},
|
||||||
|
{file = "pandas-2.3.3-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b468d3dad6ff947df92dcb32ede5b7bd41a9b3cceef0a30ed925f6d01fb8fa66"},
|
||||||
|
{file = "pandas-2.3.3-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b98560e98cb334799c0b07ca7967ac361a47326e9b4e5a7dfb5ab2b1c9d35a1b"},
|
||||||
|
{file = "pandas-2.3.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37b5848ba49824e5c30bedb9c830ab9b7751fd049bc7914533e01c65f79791"},
|
||||||
|
{file = "pandas-2.3.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:db4301b2d1f926ae677a751eb2bd0e8c5f5319c9cb3f88b0becbbb0b07b34151"},
|
||||||
|
{file = "pandas-2.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:f086f6fe114e19d92014a1966f43a3e62285109afe874f067f5abbdcbb10e59c"},
|
||||||
|
{file = "pandas-2.3.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d21f6d74eb1725c2efaa71a2bfc661a0689579b58e9c0ca58a739ff0b002b53"},
|
||||||
|
{file = "pandas-2.3.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3fd2f887589c7aa868e02632612ba39acb0b8948faf5cc58f0850e165bd46f35"},
|
||||||
|
{file = "pandas-2.3.3-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ecaf1e12bdc03c86ad4a7ea848d66c685cb6851d807a26aa245ca3d2017a1908"},
|
||||||
|
{file = "pandas-2.3.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b3d11d2fda7eb164ef27ffc14b4fcab16a80e1ce67e9f57e19ec0afaf715ba89"},
|
||||||
|
{file = "pandas-2.3.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a68e15f780eddf2b07d242e17a04aa187a7ee12b40b930bfdd78070556550e98"},
|
||||||
|
{file = "pandas-2.3.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:371a4ab48e950033bcf52b6527eccb564f52dc826c02afd9a1bc0ab731bba084"},
|
||||||
|
{file = "pandas-2.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:a16dcec078a01eeef8ee61bf64074b4e524a2a3f4b3be9326420cabe59c4778b"},
|
||||||
|
{file = "pandas-2.3.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:56851a737e3470de7fa88e6131f41281ed440d29a9268dcbf0002da5ac366713"},
|
||||||
|
{file = "pandas-2.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bdcd9d1167f4885211e401b3036c0c8d9e274eee67ea8d0758a256d60704cfe8"},
|
||||||
|
{file = "pandas-2.3.3-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e32e7cc9af0f1cc15548288a51a3b681cc2a219faa838e995f7dc53dbab1062d"},
|
||||||
|
{file = "pandas-2.3.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:318d77e0e42a628c04dc56bcef4b40de67918f7041c2b061af1da41dcff670ac"},
|
||||||
|
{file = "pandas-2.3.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4e0a175408804d566144e170d0476b15d78458795bb18f1304fb94160cabf40c"},
|
||||||
|
{file = "pandas-2.3.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:93c2d9ab0fc11822b5eece72ec9587e172f63cff87c00b062f6e37448ced4493"},
|
||||||
|
{file = "pandas-2.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:f8bfc0e12dc78f777f323f55c58649591b2cd0c43534e8355c51d3fede5f4dee"},
|
||||||
|
{file = "pandas-2.3.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:75ea25f9529fdec2d2e93a42c523962261e567d250b0013b16210e1d40d7c2e5"},
|
||||||
|
{file = "pandas-2.3.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:74ecdf1d301e812db96a465a525952f4dde225fdb6d8e5a521d47e1f42041e21"},
|
||||||
|
{file = "pandas-2.3.3-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6435cb949cb34ec11cc9860246ccb2fdc9ecd742c12d3304989017d53f039a78"},
|
||||||
|
{file = "pandas-2.3.3-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:900f47d8f20860de523a1ac881c4c36d65efcb2eb850e6948140fa781736e110"},
|
||||||
|
{file = "pandas-2.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a45c765238e2ed7d7c608fc5bc4a6f88b642f2f01e70c0c23d2224dd21829d86"},
|
||||||
|
{file = "pandas-2.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c4fc4c21971a1a9f4bdb4c73978c7f7256caa3e62b323f70d6cb80db583350bc"},
|
||||||
|
{file = "pandas-2.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:ee15f284898e7b246df8087fc82b87b01686f98ee67d85a17b7ab44143a3a9a0"},
|
||||||
|
{file = "pandas-2.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1611aedd912e1ff81ff41c745822980c49ce4a7907537be8692c8dbc31924593"},
|
||||||
|
{file = "pandas-2.3.3-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d2cefc361461662ac48810cb14365a365ce864afe85ef1f447ff5a1e99ea81c"},
|
||||||
|
{file = "pandas-2.3.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ee67acbbf05014ea6c763beb097e03cd629961c8a632075eeb34247120abcb4b"},
|
||||||
|
{file = "pandas-2.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c46467899aaa4da076d5abc11084634e2d197e9460643dd455ac3db5856b24d6"},
|
||||||
|
{file = "pandas-2.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6253c72c6a1d990a410bc7de641d34053364ef8bcd3126f7e7450125887dffe3"},
|
||||||
|
{file = "pandas-2.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:1b07204a219b3b7350abaae088f451860223a52cfb8a6c53358e7948735158e5"},
|
||||||
|
{file = "pandas-2.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2462b1a365b6109d275250baaae7b760fd25c726aaca0054649286bcfbb3e8ec"},
|
||||||
|
{file = "pandas-2.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0242fe9a49aa8b4d78a4fa03acb397a58833ef6199e9aa40a95f027bb3a1b6e7"},
|
||||||
|
{file = "pandas-2.3.3-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a21d830e78df0a515db2b3d2f5570610f5e6bd2e27749770e8bb7b524b89b450"},
|
||||||
|
{file = "pandas-2.3.3-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2e3ebdb170b5ef78f19bfb71b0dc5dc58775032361fa188e814959b74d726dd5"},
|
||||||
|
{file = "pandas-2.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:d051c0e065b94b7a3cea50eb1ec32e912cd96dba41647eb24104b6c6c14c5788"},
|
||||||
|
{file = "pandas-2.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3869faf4bd07b3b66a9f462417d0ca3a9df29a9f6abd5d0d0dbab15dac7abe87"},
|
||||||
|
{file = "pandas-2.3.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c503ba5216814e295f40711470446bc3fd00f0faea8a086cbc688808e26f92a2"},
|
||||||
|
{file = "pandas-2.3.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a637c5cdfa04b6d6e2ecedcb81fc52ffb0fd78ce2ebccc9ea964df9f658de8c8"},
|
||||||
|
{file = "pandas-2.3.3-cp39-cp39-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:854d00d556406bffe66a4c0802f334c9ad5a96b4f1f868adf036a21b11ef13ff"},
|
||||||
|
{file = "pandas-2.3.3-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bf1f8a81d04ca90e32a0aceb819d34dbd378a98bf923b6398b9a3ec0bf44de29"},
|
||||||
|
{file = "pandas-2.3.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:23ebd657a4d38268c7dfbdf089fbc31ea709d82e4923c5ffd4fbd5747133ce73"},
|
||||||
|
{file = "pandas-2.3.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5554c929ccc317d41a5e3d1234f3be588248e61f08a74dd17c9eabb535777dc9"},
|
||||||
|
{file = "pandas-2.3.3-cp39-cp39-win_amd64.whl", hash = "sha256:d3e28b3e83862ccf4d85ff19cf8c20b2ae7e503881711ff2d534dc8f761131aa"},
|
||||||
|
{file = "pandas-2.3.3.tar.gz", hash = "sha256:e05e1af93b977f7eafa636d043f9f94c7ee3ac81af99c13508215942e64c993b"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
numpy = {version = ">=1.22.4", markers = "python_version < \"3.11\""}
|
||||||
|
python-dateutil = ">=2.8.2"
|
||||||
|
pytz = ">=2020.1"
|
||||||
|
tzdata = ">=2022.7"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
all = ["PyQt5 (>=5.15.9)", "SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)", "beautifulsoup4 (>=4.11.2)", "bottleneck (>=1.3.6)", "dataframe-api-compat (>=0.1.7)", "fastparquet (>=2022.12.0)", "fsspec (>=2022.11.0)", "gcsfs (>=2022.11.0)", "html5lib (>=1.1)", "hypothesis (>=6.46.1)", "jinja2 (>=3.1.2)", "lxml (>=4.9.2)", "matplotlib (>=3.6.3)", "numba (>=0.56.4)", "numexpr (>=2.8.4)", "odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "pandas-gbq (>=0.19.0)", "psycopg2 (>=2.9.6)", "pyarrow (>=10.0.1)", "pymysql (>=1.0.2)", "pyreadstat (>=1.2.0)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "qtpy (>=2.3.0)", "s3fs (>=2022.11.0)", "scipy (>=1.10.0)", "tables (>=3.8.0)", "tabulate (>=0.9.0)", "xarray (>=2022.12.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)", "zstandard (>=0.19.0)"]
|
||||||
|
aws = ["s3fs (>=2022.11.0)"]
|
||||||
|
clipboard = ["PyQt5 (>=5.15.9)", "qtpy (>=2.3.0)"]
|
||||||
|
compression = ["zstandard (>=0.19.0)"]
|
||||||
|
computation = ["scipy (>=1.10.0)", "xarray (>=2022.12.0)"]
|
||||||
|
consortium-standard = ["dataframe-api-compat (>=0.1.7)"]
|
||||||
|
excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)"]
|
||||||
|
feather = ["pyarrow (>=10.0.1)"]
|
||||||
|
fss = ["fsspec (>=2022.11.0)"]
|
||||||
|
gcp = ["gcsfs (>=2022.11.0)", "pandas-gbq (>=0.19.0)"]
|
||||||
|
hdf5 = ["tables (>=3.8.0)"]
|
||||||
|
html = ["beautifulsoup4 (>=4.11.2)", "html5lib (>=1.1)", "lxml (>=4.9.2)"]
|
||||||
|
mysql = ["SQLAlchemy (>=2.0.0)", "pymysql (>=1.0.2)"]
|
||||||
|
output-formatting = ["jinja2 (>=3.1.2)", "tabulate (>=0.9.0)"]
|
||||||
|
parquet = ["pyarrow (>=10.0.1)"]
|
||||||
|
performance = ["bottleneck (>=1.3.6)", "numba (>=0.56.4)", "numexpr (>=2.8.4)"]
|
||||||
|
plot = ["matplotlib (>=3.6.3)"]
|
||||||
|
postgresql = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "psycopg2 (>=2.9.6)"]
|
||||||
|
pyarrow = ["pyarrow (>=10.0.1)"]
|
||||||
|
spss = ["pyreadstat (>=1.2.0)"]
|
||||||
|
sql-other = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)"]
|
||||||
|
test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"]
|
||||||
|
xml = ["lxml (>=4.9.2)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pandas"
|
||||||
|
version = "3.0.1"
|
||||||
|
description = "Powerful data structures for data analysis, time series, and statistics"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.11"
|
||||||
|
groups = ["main"]
|
||||||
|
markers = "python_version >= \"3.11\""
|
||||||
|
files = [
|
||||||
|
{file = "pandas-3.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:de09668c1bf3b925c07e5762291602f0d789eca1b3a781f99c1c78f6cac0e7ea"},
|
||||||
|
{file = "pandas-3.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:24ba315ba3d6e5806063ac6eb717504e499ce30bd8c236d8693a5fd3f084c796"},
|
||||||
|
{file = "pandas-3.0.1-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:406ce835c55bac912f2a0dcfaf27c06d73c6b04a5dde45f1fd3169ce31337389"},
|
||||||
|
{file = "pandas-3.0.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:830994d7e1f31dd7e790045235605ab61cff6c94defc774547e8b7fdfbff3dc7"},
|
||||||
|
{file = "pandas-3.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a64ce8b0f2de1d2efd2ae40b0abe7f8ae6b29fbfb3812098ed5a6f8e235ad9bf"},
|
||||||
|
{file = "pandas-3.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9832c2c69da24b602c32e0c7b1b508a03949c18ba08d4d9f1c1033426685b447"},
|
||||||
|
{file = "pandas-3.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:84f0904a69e7365f79a0c77d3cdfccbfb05bf87847e3a51a41e1426b0edb9c79"},
|
||||||
|
{file = "pandas-3.0.1-cp311-cp311-win_arm64.whl", hash = "sha256:4a68773d5a778afb31d12e34f7dd4612ab90de8c6fb1d8ffe5d4a03b955082a1"},
|
||||||
|
{file = "pandas-3.0.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:476f84f8c20c9f5bc47252b66b4bb25e1a9fc2fa98cead96744d8116cb85771d"},
|
||||||
|
{file = "pandas-3.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0ab749dfba921edf641d4036c4c21c0b3ea70fea478165cb98a998fb2a261955"},
|
||||||
|
{file = "pandas-3.0.1-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b8e36891080b87823aff3640c78649b91b8ff6eea3c0d70aeabd72ea43ab069b"},
|
||||||
|
{file = "pandas-3.0.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:532527a701281b9dd371e2f582ed9094f4c12dd9ffb82c0c54ee28d8ac9520c4"},
|
||||||
|
{file = "pandas-3.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:356e5c055ed9b0da1580d465657bc7d00635af4fd47f30afb23025352ba764d1"},
|
||||||
|
{file = "pandas-3.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9d810036895f9ad6345b8f2a338dd6998a74e8483847403582cab67745bff821"},
|
||||||
|
{file = "pandas-3.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:536232a5fe26dd989bd633e7a0c450705fdc86a207fec7254a55e9a22950fe43"},
|
||||||
|
{file = "pandas-3.0.1-cp312-cp312-win_arm64.whl", hash = "sha256:0f463ebfd8de7f326d38037c7363c6dacb857c5881ab8961fb387804d6daf2f7"},
|
||||||
|
{file = "pandas-3.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5272627187b5d9c20e55d27caf5f2cd23e286aba25cadf73c8590e432e2b7262"},
|
||||||
|
{file = "pandas-3.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:661e0f665932af88c7877f31da0dc743fe9c8f2524bdffe23d24fdcb67ef9d56"},
|
||||||
|
{file = "pandas-3.0.1-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:75e6e292ff898679e47a2199172593d9f6107fd2dd3617c22c2946e97d5df46e"},
|
||||||
|
{file = "pandas-3.0.1-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1ff8cf1d2896e34343197685f432450ec99a85ba8d90cce2030c5eee2ef98791"},
|
||||||
|
{file = "pandas-3.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:eca8b4510f6763f3d37359c2105df03a7a221a508f30e396a51d0713d462e68a"},
|
||||||
|
{file = "pandas-3.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:06aff2ad6f0b94a17822cf8b83bbb563b090ed82ff4fe7712db2ce57cd50d9b8"},
|
||||||
|
{file = "pandas-3.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:9fea306c783e28884c29057a1d9baa11a349bbf99538ec1da44c8476563d1b25"},
|
||||||
|
{file = "pandas-3.0.1-cp313-cp313-win_arm64.whl", hash = "sha256:a8d37a43c52917427e897cb2e429f67a449327394396a81034a4449b99afda59"},
|
||||||
|
{file = "pandas-3.0.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:d54855f04f8246ed7b6fc96b05d4871591143c46c0b6f4af874764ed0d2d6f06"},
|
||||||
|
{file = "pandas-3.0.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4e1b677accee34a09e0dc2ce5624e4a58a1870ffe56fc021e9caf7f23cd7668f"},
|
||||||
|
{file = "pandas-3.0.1-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a9cabbdcd03f1b6cd254d6dda8ae09b0252524be1592594c00b7895916cb1324"},
|
||||||
|
{file = "pandas-3.0.1-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5ae2ab1f166668b41e770650101e7090824fd34d17915dd9cd479f5c5e0065e9"},
|
||||||
|
{file = "pandas-3.0.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6bf0603c2e30e2cafac32807b06435f28741135cb8697eae8b28c7d492fc7d76"},
|
||||||
|
{file = "pandas-3.0.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6c426422973973cae1f4a23e51d4ae85974f44871b24844e4f7de752dd877098"},
|
||||||
|
{file = "pandas-3.0.1-cp313-cp313t-win_amd64.whl", hash = "sha256:b03f91ae8c10a85c1613102c7bef5229b5379f343030a3ccefeca8a33414cf35"},
|
||||||
|
{file = "pandas-3.0.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:99d0f92ed92d3083d140bf6b97774f9f13863924cf3f52a70711f4e7588f9d0a"},
|
||||||
|
{file = "pandas-3.0.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:3b66857e983208654294bb6477b8a63dee26b37bdd0eb34d010556e91261784f"},
|
||||||
|
{file = "pandas-3.0.1-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:56cf59638bf24dc9bdf2154c81e248b3289f9a09a6d04e63608c159022352749"},
|
||||||
|
{file = "pandas-3.0.1-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c1a9f55e0f46951874b863d1f3906dcb57df2d9be5c5847ba4dfb55b2c815249"},
|
||||||
|
{file = "pandas-3.0.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1849f0bba9c8a2fb0f691d492b834cc8dadf617e29015c66e989448d58d011ee"},
|
||||||
|
{file = "pandas-3.0.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:c3d288439e11b5325b02ae6e9cc83e6805a62c40c5a6220bea9beb899c073b1c"},
|
||||||
|
{file = "pandas-3.0.1-cp314-cp314-win_amd64.whl", hash = "sha256:93325b0fe372d192965f4cca88d97667f49557398bbf94abdda3bf1b591dbe66"},
|
||||||
|
{file = "pandas-3.0.1-cp314-cp314-win_arm64.whl", hash = "sha256:97ca08674e3287c7148f4858b01136f8bdfe7202ad25ad04fec602dd1d29d132"},
|
||||||
|
{file = "pandas-3.0.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:58eeb1b2e0fb322befcf2bbc9ba0af41e616abadb3d3414a6bc7167f6cbfce32"},
|
||||||
|
{file = "pandas-3.0.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:cd9af1276b5ca9e298bd79a26bda32fa9cc87ed095b2a9a60978d2ca058eaf87"},
|
||||||
|
{file = "pandas-3.0.1-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:94f87a04984d6b63788327cd9f79dda62b7f9043909d2440ceccf709249ca988"},
|
||||||
|
{file = "pandas-3.0.1-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:85fe4c4df62e1e20f9db6ebfb88c844b092c22cd5324bdcf94bfa2fc1b391221"},
|
||||||
|
{file = "pandas-3.0.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:331ca75a2f8672c365ae25c0b29e46f5ac0c6551fdace8eec4cd65e4fac271ff"},
|
||||||
|
{file = "pandas-3.0.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:15860b1fdb1973fffade772fdb931ccf9b2f400a3f5665aef94a00445d7d8dd5"},
|
||||||
|
{file = "pandas-3.0.1-cp314-cp314t-win_amd64.whl", hash = "sha256:44f1364411d5670efa692b146c748f4ed013df91ee91e9bec5677fb1fd58b937"},
|
||||||
|
{file = "pandas-3.0.1-cp314-cp314t-win_arm64.whl", hash = "sha256:108dd1790337a494aa80e38def654ca3f0968cf4f362c85f44c15e471667102d"},
|
||||||
|
{file = "pandas-3.0.1.tar.gz", hash = "sha256:4186a699674af418f655dbd420ed87f50d56b4cd6603784279d9eef6627823c8"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
numpy = [
|
||||||
|
{version = ">=1.26.0", markers = "python_version < \"3.14\""},
|
||||||
|
{version = ">=2.3.3", markers = "python_version >= \"3.14\""},
|
||||||
|
]
|
||||||
|
python-dateutil = ">=2.8.2"
|
||||||
|
tzdata = {version = "*", markers = "sys_platform == \"win32\" or sys_platform == \"emscripten\""}
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
all = ["PyQt5 (>=5.15.9)", "SQLAlchemy (>=2.0.36)", "adbc-driver-postgresql (>=1.2.0)", "adbc-driver-sqlite (>=1.2.0)", "beautifulsoup4 (>=4.12.3)", "bottleneck (>=1.4.2)", "fastparquet (>=2024.11.0)", "fsspec (>=2024.10.0)", "gcsfs (>=2024.10.0)", "html5lib (>=1.1)", "hypothesis (>=6.116.0)", "jinja2 (>=3.1.5)", "lxml (>=5.3.0)", "matplotlib (>=3.9.3)", "numba (>=0.60.0)", "numexpr (>=2.10.2)", "odfpy (>=1.4.1)", "openpyxl (>=3.1.5)", "psycopg2 (>=2.9.10)", "pyarrow (>=13.0.0)", "pyiceberg (>=0.8.1)", "pymysql (>=1.1.1)", "pyreadstat (>=1.2.8)", "pytest (>=8.3.4)", "pytest-xdist (>=3.6.1)", "python-calamine (>=0.3.0)", "pytz (>=2024.2)", "pyxlsb (>=1.0.10)", "qtpy (>=2.4.2)", "s3fs (>=2024.10.0)", "scipy (>=1.14.1)", "tables (>=3.10.1)", "tabulate (>=0.9.0)", "xarray (>=2024.10.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.2.0)", "zstandard (>=0.23.0)"]
|
||||||
|
aws = ["s3fs (>=2024.10.0)"]
|
||||||
|
clipboard = ["PyQt5 (>=5.15.9)", "qtpy (>=2.4.2)"]
|
||||||
|
compression = ["zstandard (>=0.23.0)"]
|
||||||
|
computation = ["scipy (>=1.14.1)", "xarray (>=2024.10.0)"]
|
||||||
|
excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.1.5)", "python-calamine (>=0.3.0)", "pyxlsb (>=1.0.10)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.2.0)"]
|
||||||
|
feather = ["pyarrow (>=13.0.0)"]
|
||||||
|
fss = ["fsspec (>=2024.10.0)"]
|
||||||
|
gcp = ["gcsfs (>=2024.10.0)"]
|
||||||
|
hdf5 = ["tables (>=3.10.1)"]
|
||||||
|
html = ["beautifulsoup4 (>=4.12.3)", "html5lib (>=1.1)", "lxml (>=5.3.0)"]
|
||||||
|
iceberg = ["pyiceberg (>=0.8.1)"]
|
||||||
|
mysql = ["SQLAlchemy (>=2.0.36)", "pymysql (>=1.1.1)"]
|
||||||
|
output-formatting = ["jinja2 (>=3.1.5)", "tabulate (>=0.9.0)"]
|
||||||
|
parquet = ["pyarrow (>=13.0.0)"]
|
||||||
|
performance = ["bottleneck (>=1.4.2)", "numba (>=0.60.0)", "numexpr (>=2.10.2)"]
|
||||||
|
plot = ["matplotlib (>=3.9.3)"]
|
||||||
|
postgresql = ["SQLAlchemy (>=2.0.36)", "adbc-driver-postgresql (>=1.2.0)", "psycopg2 (>=2.9.10)"]
|
||||||
|
pyarrow = ["pyarrow (>=13.0.0)"]
|
||||||
|
spss = ["pyreadstat (>=1.2.8)"]
|
||||||
|
sql-other = ["SQLAlchemy (>=2.0.36)", "adbc-driver-postgresql (>=1.2.0)", "adbc-driver-sqlite (>=1.2.0)"]
|
||||||
|
test = ["hypothesis (>=6.116.0)", "pytest (>=8.3.4)", "pytest-xdist (>=3.6.1)"]
|
||||||
|
timezone = ["pytz (>=2024.2)"]
|
||||||
|
xml = ["lxml (>=5.3.0)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pillow"
|
||||||
|
version = "12.1.1"
|
||||||
|
description = "Python Imaging Library (fork)"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.10"
|
||||||
|
groups = ["main"]
|
||||||
|
files = [
|
||||||
|
{file = "pillow-12.1.1-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:1f1625b72740fdda5d77b4def688eb8fd6490975d06b909fd19f13f391e077e0"},
|
||||||
|
{file = "pillow-12.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:178aa072084bd88ec759052feca8e56cbb14a60b39322b99a049e58090479713"},
|
||||||
|
{file = "pillow-12.1.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b66e95d05ba806247aaa1561f080abc7975daf715c30780ff92a20e4ec546e1b"},
|
||||||
|
{file = "pillow-12.1.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:89c7e895002bbe49cdc5426150377cbbc04767d7547ed145473f496dfa40408b"},
|
||||||
|
{file = "pillow-12.1.1-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a5cbdcddad0af3da87cb16b60d23648bc3b51967eb07223e9fed77a82b457c4"},
|
||||||
|
{file = "pillow-12.1.1-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9f51079765661884a486727f0729d29054242f74b46186026582b4e4769918e4"},
|
||||||
|
{file = "pillow-12.1.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:99c1506ea77c11531d75e3a412832a13a71c7ebc8192ab9e4b2e355555920e3e"},
|
||||||
|
{file = "pillow-12.1.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:36341d06738a9f66c8287cf8b876d24b18db9bd8740fa0672c74e259ad408cff"},
|
||||||
|
{file = "pillow-12.1.1-cp310-cp310-win32.whl", hash = "sha256:6c52f062424c523d6c4db85518774cc3d50f5539dd6eed32b8f6229b26f24d40"},
|
||||||
|
{file = "pillow-12.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:c6008de247150668a705a6338156efb92334113421ceecf7438a12c9a12dab23"},
|
||||||
|
{file = "pillow-12.1.1-cp310-cp310-win_arm64.whl", hash = "sha256:1a9b0ee305220b392e1124a764ee4265bd063e54a751a6b62eff69992f457fa9"},
|
||||||
|
{file = "pillow-12.1.1-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:e879bb6cd5c73848ef3b2b48b8af9ff08c5b71ecda8048b7dd22d8a33f60be32"},
|
||||||
|
{file = "pillow-12.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:365b10bb9417dd4498c0e3b128018c4a624dc11c7b97d8cc54effe3b096f4c38"},
|
||||||
|
{file = "pillow-12.1.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d4ce8e329c93845720cd2014659ca67eac35f6433fd3050393d85f3ecef0dad5"},
|
||||||
|
{file = "pillow-12.1.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fc354a04072b765eccf2204f588a7a532c9511e8b9c7f900e1b64e3e33487090"},
|
||||||
|
{file = "pillow-12.1.1-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7e7976bf1910a8116b523b9f9f58bf410f3e8aa330cd9a2bb2953f9266ab49af"},
|
||||||
|
{file = "pillow-12.1.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:597bd9c8419bc7c6af5604e55847789b69123bbe25d65cc6ad3012b4f3c98d8b"},
|
||||||
|
{file = "pillow-12.1.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2c1fc0f2ca5f96a3c8407e41cca26a16e46b21060fe6d5b099d2cb01412222f5"},
|
||||||
|
{file = "pillow-12.1.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:578510d88c6229d735855e1f278aa305270438d36a05031dfaae5067cc8eb04d"},
|
||||||
|
{file = "pillow-12.1.1-cp311-cp311-win32.whl", hash = "sha256:7311c0a0dcadb89b36b7025dfd8326ecfa36964e29913074d47382706e516a7c"},
|
||||||
|
{file = "pillow-12.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:fbfa2a7c10cc2623f412753cddf391c7f971c52ca40a3f65dc5039b2939e8563"},
|
||||||
|
{file = "pillow-12.1.1-cp311-cp311-win_arm64.whl", hash = "sha256:b81b5e3511211631b3f672a595e3221252c90af017e399056d0faabb9538aa80"},
|
||||||
|
{file = "pillow-12.1.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ab323b787d6e18b3d91a72fc99b1a2c28651e4358749842b8f8dfacd28ef2052"},
|
||||||
|
{file = "pillow-12.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:adebb5bee0f0af4909c30db0d890c773d1a92ffe83da908e2e9e720f8edf3984"},
|
||||||
|
{file = "pillow-12.1.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:bb66b7cc26f50977108790e2456b7921e773f23db5630261102233eb355a3b79"},
|
||||||
|
{file = "pillow-12.1.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:aee2810642b2898bb187ced9b349e95d2a7272930796e022efaf12e99dccd293"},
|
||||||
|
{file = "pillow-12.1.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a0b1cd6232e2b618adcc54d9882e4e662a089d5768cd188f7c245b4c8c44a397"},
|
||||||
|
{file = "pillow-12.1.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7aac39bcf8d4770d089588a2e1dd111cbaa42df5a94be3114222057d68336bd0"},
|
||||||
|
{file = "pillow-12.1.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ab174cd7d29a62dd139c44bf74b698039328f45cb03b4596c43473a46656b2f3"},
|
||||||
|
{file = "pillow-12.1.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:339ffdcb7cbeaa08221cd401d517d4b1fe7a9ed5d400e4a8039719238620ca35"},
|
||||||
|
{file = "pillow-12.1.1-cp312-cp312-win32.whl", hash = "sha256:5d1f9575a12bed9e9eedd9a4972834b08c97a352bd17955ccdebfeca5913fa0a"},
|
||||||
|
{file = "pillow-12.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:21329ec8c96c6e979cd0dfd29406c40c1d52521a90544463057d2aaa937d66a6"},
|
||||||
|
{file = "pillow-12.1.1-cp312-cp312-win_arm64.whl", hash = "sha256:af9a332e572978f0218686636610555ae3defd1633597be015ed50289a03c523"},
|
||||||
|
{file = "pillow-12.1.1-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:d242e8ac078781f1de88bf823d70c1a9b3c7950a44cdf4b7c012e22ccbcd8e4e"},
|
||||||
|
{file = "pillow-12.1.1-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:02f84dfad02693676692746df05b89cf25597560db2857363a208e393429f5e9"},
|
||||||
|
{file = "pillow-12.1.1-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:e65498daf4b583091ccbb2556c7000abf0f3349fcd57ef7adc9a84a394ed29f6"},
|
||||||
|
{file = "pillow-12.1.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:6c6db3b84c87d48d0088943bf33440e0c42370b99b1c2a7989216f7b42eede60"},
|
||||||
|
{file = "pillow-12.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8b7e5304e34942bf62e15184219a7b5ad4ff7f3bb5cca4d984f37df1a0e1aee2"},
|
||||||
|
{file = "pillow-12.1.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:18e5bddd742a44b7e6b1e773ab5db102bd7a94c32555ba656e76d319d19c3850"},
|
||||||
|
{file = "pillow-12.1.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fc44ef1f3de4f45b50ccf9136999d71abb99dca7706bc75d222ed350b9fd2289"},
|
||||||
|
{file = "pillow-12.1.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5a8eb7ed8d4198bccbd07058416eeec51686b498e784eda166395a23eb99138e"},
|
||||||
|
{file = "pillow-12.1.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:47b94983da0c642de92ced1702c5b6c292a84bd3a8e1d1702ff923f183594717"},
|
||||||
|
{file = "pillow-12.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:518a48c2aab7ce596d3bf79d0e275661b846e86e4d0e7dec34712c30fe07f02a"},
|
||||||
|
{file = "pillow-12.1.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a550ae29b95c6dc13cf69e2c9dc5747f814c54eeb2e32d683e5e93af56caa029"},
|
||||||
|
{file = "pillow-12.1.1-cp313-cp313-win32.whl", hash = "sha256:a003d7422449f6d1e3a34e3dd4110c22148336918ddbfc6a32581cd54b2e0b2b"},
|
||||||
|
{file = "pillow-12.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:344cf1e3dab3be4b1fa08e449323d98a2a3f819ad20f4b22e77a0ede31f0faa1"},
|
||||||
|
{file = "pillow-12.1.1-cp313-cp313-win_arm64.whl", hash = "sha256:5c0dd1636633e7e6a0afe7bf6a51a14992b7f8e60de5789018ebbdfae55b040a"},
|
||||||
|
{file = "pillow-12.1.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0330d233c1a0ead844fc097a7d16c0abff4c12e856c0b325f231820fee1f39da"},
|
||||||
|
{file = "pillow-12.1.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5dae5f21afb91322f2ff791895ddd8889e5e947ff59f71b46041c8ce6db790bc"},
|
||||||
|
{file = "pillow-12.1.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:2e0c664be47252947d870ac0d327fea7e63985a08794758aa8af5b6cb6ec0c9c"},
|
||||||
|
{file = "pillow-12.1.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:691ab2ac363b8217f7d31b3497108fb1f50faab2f75dfb03284ec2f217e87bf8"},
|
||||||
|
{file = "pillow-12.1.1-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e9e8064fb1cc019296958595f6db671fba95209e3ceb0c4734c9baf97de04b20"},
|
||||||
|
{file = "pillow-12.1.1-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:472a8d7ded663e6162dafdf20015c486a7009483ca671cece7a9279b512fcb13"},
|
||||||
|
{file = "pillow-12.1.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:89b54027a766529136a06cfebeecb3a04900397a3590fd252160b888479517bf"},
|
||||||
|
{file = "pillow-12.1.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:86172b0831b82ce4f7877f280055892b31179e1576aa00d0df3bb1bbf8c3e524"},
|
||||||
|
{file = "pillow-12.1.1-cp313-cp313t-win32.whl", hash = "sha256:44ce27545b6efcf0fdbdceb31c9a5bdea9333e664cda58a7e674bb74608b3986"},
|
||||||
|
{file = "pillow-12.1.1-cp313-cp313t-win_amd64.whl", hash = "sha256:a285e3eb7a5a45a2ff504e31f4a8d1b12ef62e84e5411c6804a42197c1cf586c"},
|
||||||
|
{file = "pillow-12.1.1-cp313-cp313t-win_arm64.whl", hash = "sha256:cc7d296b5ea4d29e6570dabeaed58d31c3fea35a633a69679fb03d7664f43fb3"},
|
||||||
|
{file = "pillow-12.1.1-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:417423db963cb4be8bac3fc1204fe61610f6abeed1580a7a2cbb2fbda20f12af"},
|
||||||
|
{file = "pillow-12.1.1-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:b957b71c6b2387610f556a7eb0828afbe40b4a98036fc0d2acfa5a44a0c2036f"},
|
||||||
|
{file = "pillow-12.1.1-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:097690ba1f2efdeb165a20469d59d8bb03c55fb6621eb2041a060ae8ea3e9642"},
|
||||||
|
{file = "pillow-12.1.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:2815a87ab27848db0321fb78c7f0b2c8649dee134b7f2b80c6a45c6831d75ccd"},
|
||||||
|
{file = "pillow-12.1.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:f7ed2c6543bad5a7d5530eb9e78c53132f93dfa44a28492db88b41cdab885202"},
|
||||||
|
{file = "pillow-12.1.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:652a2c9ccfb556235b2b501a3a7cf3742148cd22e04b5625c5fe057ea3e3191f"},
|
||||||
|
{file = "pillow-12.1.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d6e4571eedf43af33d0fc233a382a76e849badbccdf1ac438841308652a08e1f"},
|
||||||
|
{file = "pillow-12.1.1-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b574c51cf7d5d62e9be37ba446224b59a2da26dc4c1bb2ecbe936a4fb1a7cb7f"},
|
||||||
|
{file = "pillow-12.1.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a37691702ed687799de29a518d63d4682d9016932db66d4e90c345831b02fb4e"},
|
||||||
|
{file = "pillow-12.1.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f95c00d5d6700b2b890479664a06e754974848afaae5e21beb4d83c106923fd0"},
|
||||||
|
{file = "pillow-12.1.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:559b38da23606e68681337ad74622c4dbba02254fc9cb4488a305dd5975c7eeb"},
|
||||||
|
{file = "pillow-12.1.1-cp314-cp314-win32.whl", hash = "sha256:03edcc34d688572014ff223c125a3f77fb08091e4607e7745002fc214070b35f"},
|
||||||
|
{file = "pillow-12.1.1-cp314-cp314-win_amd64.whl", hash = "sha256:50480dcd74fa63b8e78235957d302d98d98d82ccbfac4c7e12108ba9ecbdba15"},
|
||||||
|
{file = "pillow-12.1.1-cp314-cp314-win_arm64.whl", hash = "sha256:5cb1785d97b0c3d1d1a16bc1d710c4a0049daefc4935f3a8f31f827f4d3d2e7f"},
|
||||||
|
{file = "pillow-12.1.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:1f90cff8aa76835cba5769f0b3121a22bd4eb9e6884cfe338216e557a9a548b8"},
|
||||||
|
{file = "pillow-12.1.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1f1be78ce9466a7ee64bfda57bdba0f7cc499d9794d518b854816c41bf0aa4e9"},
|
||||||
|
{file = "pillow-12.1.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:42fc1f4677106188ad9a55562bbade416f8b55456f522430fadab3cef7cd4e60"},
|
||||||
|
{file = "pillow-12.1.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:98edb152429ab62a1818039744d8fbb3ccab98a7c29fc3d5fcef158f3f1f68b7"},
|
||||||
|
{file = "pillow-12.1.1-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d470ab1178551dd17fdba0fef463359c41aaa613cdcd7ff8373f54be629f9f8f"},
|
||||||
|
{file = "pillow-12.1.1-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6408a7b064595afcab0a49393a413732a35788f2a5092fdc6266952ed67de586"},
|
||||||
|
{file = "pillow-12.1.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5d8c41325b382c07799a3682c1c258469ea2ff97103c53717b7893862d0c98ce"},
|
||||||
|
{file = "pillow-12.1.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:c7697918b5be27424e9ce568193efd13d925c4481dd364e43f5dff72d33e10f8"},
|
||||||
|
{file = "pillow-12.1.1-cp314-cp314t-win32.whl", hash = "sha256:d2912fd8114fc5545aa3a4b5576512f64c55a03f3ebcca4c10194d593d43ea36"},
|
||||||
|
{file = "pillow-12.1.1-cp314-cp314t-win_amd64.whl", hash = "sha256:4ceb838d4bd9dab43e06c363cab2eebf63846d6a4aeaea283bbdfd8f1a8ed58b"},
|
||||||
|
{file = "pillow-12.1.1-cp314-cp314t-win_arm64.whl", hash = "sha256:7b03048319bfc6170e93bd60728a1af51d3dd7704935feb228c4d4faab35d334"},
|
||||||
|
{file = "pillow-12.1.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:600fd103672b925fe62ed08e0d874ea34d692474df6f4bf7ebe148b30f89f39f"},
|
||||||
|
{file = "pillow-12.1.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:665e1b916b043cef294bc54d47bf02d87e13f769bc4bc5fa225a24b3a6c5aca9"},
|
||||||
|
{file = "pillow-12.1.1-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:495c302af3aad1ca67420ddd5c7bd480c8867ad173528767d906428057a11f0e"},
|
||||||
|
{file = "pillow-12.1.1-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8fd420ef0c52c88b5a035a0886f367748c72147b2b8f384c9d12656678dfdfa9"},
|
||||||
|
{file = "pillow-12.1.1-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f975aa7ef9684ce7e2c18a3aa8f8e2106ce1e46b94ab713d156b2898811651d3"},
|
||||||
|
{file = "pillow-12.1.1-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8089c852a56c2966cf18835db62d9b34fef7ba74c726ad943928d494fa7f4735"},
|
||||||
|
{file = "pillow-12.1.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:cb9bb857b2d057c6dfc72ac5f3b44836924ba15721882ef103cecb40d002d80e"},
|
||||||
|
{file = "pillow-12.1.1.tar.gz", hash = "sha256:9ad8fa5937ab05218e2b6a4cff30295ad35afd2f83ac592e68c0d871bb0fdbc4"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
docs = ["furo", "olefile", "sphinx (>=8.2)", "sphinx-autobuild", "sphinx-copybutton", "sphinx-inline-tabs", "sphinxext-opengraph"]
|
||||||
|
fpx = ["olefile"]
|
||||||
|
mic = ["olefile"]
|
||||||
|
test-arrow = ["arro3-compute", "arro3-core", "nanoarrow", "pyarrow"]
|
||||||
|
tests = ["check-manifest", "coverage (>=7.4.2)", "defusedxml", "markdown2", "olefile", "packaging", "pyroma (>=5)", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "trove-classifiers (>=2024.10.12)"]
|
||||||
|
xmp = ["defusedxml"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pyparsing"
|
||||||
|
version = "3.3.2"
|
||||||
|
description = "pyparsing - Classes and methods to define and execute parsing grammars"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.9"
|
||||||
|
groups = ["main"]
|
||||||
|
files = [
|
||||||
|
{file = "pyparsing-3.3.2-py3-none-any.whl", hash = "sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d"},
|
||||||
|
{file = "pyparsing-3.3.2.tar.gz", hash = "sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
diagrams = ["jinja2", "railroad-diagrams"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "python-dateutil"
|
||||||
|
version = "2.9.0.post0"
|
||||||
|
description = "Extensions to the standard Python datetime module"
|
||||||
|
optional = false
|
||||||
|
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
|
||||||
|
groups = ["main"]
|
||||||
|
files = [
|
||||||
|
{file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"},
|
||||||
|
{file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
six = ">=1.5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pytz"
|
||||||
|
version = "2026.1.post1"
|
||||||
|
description = "World timezone definitions, modern and historical"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
groups = ["main"]
|
||||||
|
markers = "python_version == \"3.10\""
|
||||||
|
files = [
|
||||||
|
{file = "pytz-2026.1.post1-py2.py3-none-any.whl", hash = "sha256:f2fd16142fda348286a75e1a524be810bb05d444e5a081f37f7affc635035f7a"},
|
||||||
|
{file = "pytz-2026.1.post1.tar.gz", hash = "sha256:3378dde6a0c3d26719182142c56e60c7f9af7e968076f31aae569d72a0358ee1"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "six"
|
||||||
|
version = "1.17.0"
|
||||||
|
description = "Python 2 and 3 compatibility utilities"
|
||||||
|
optional = false
|
||||||
|
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
|
||||||
|
groups = ["main"]
|
||||||
|
files = [
|
||||||
|
{file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"},
|
||||||
|
{file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tzdata"
|
||||||
|
version = "2025.3"
|
||||||
|
description = "Provider of IANA time zone data"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=2"
|
||||||
|
groups = ["main"]
|
||||||
|
markers = "sys_platform == \"win32\" or sys_platform == \"emscripten\" or python_version == \"3.10\""
|
||||||
|
files = [
|
||||||
|
{file = "tzdata-2025.3-py2.py3-none-any.whl", hash = "sha256:06a47e5700f3081aab02b2e513160914ff0694bce9947d6b76ebd6bf57cfc5d1"},
|
||||||
|
{file = "tzdata-2025.3.tar.gz", hash = "sha256:de39c2ca5dc7b0344f2eba86f49d614019d29f060fc4ebc8a417896a620b56a7"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[metadata]
|
||||||
|
lock-version = "2.1"
|
||||||
|
python-versions = ">=3.10"
|
||||||
|
content-hash = "870a0670af1ce4f6de547b9d027a5a952b895066c9f91ebea1da2ae3cbb1eddd"
|
||||||
16
08/ex1/pyproject.toml
Normal file
16
08/ex1/pyproject.toml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
[project]
|
||||||
|
|
||||||
|
name = "ex1"
|
||||||
|
|
||||||
|
version = "1.0.0"
|
||||||
|
|
||||||
|
requires-python = ">=3.10"
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
"pandas",
|
||||||
|
"numpy",
|
||||||
|
"matplotlib",
|
||||||
|
]
|
||||||
|
|
||||||
|
[tool.poetry]
|
||||||
|
package-mode = false
|
||||||
3
08/ex1/requirements.txt
Normal file
3
08/ex1/requirements.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
pandas
|
||||||
|
numpy
|
||||||
|
matplotlib
|
||||||
5
08/ex2/.env.example
Normal file
5
08/ex2/.env.example
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
MATRIX_MODE="" # "development" or "production"
|
||||||
|
DATABASE_URL="" # Connection string for data storage
|
||||||
|
API_KEY="" # Secret key for external services
|
||||||
|
LOG_LEVEL="" # Logging verbosity
|
||||||
|
ZION_ENDPOINT="" # URL for the resistance network
|
||||||
1
08/ex2/.gitignore
vendored
Normal file
1
08/ex2/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
.env
|
||||||
48
08/ex2/oracle.py
Normal file
48
08/ex2/oracle.py
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import os
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
|
|
||||||
|
def check_env() -> None:
|
||||||
|
configs = [
|
||||||
|
"MATRIX_MODE",
|
||||||
|
"DATABASE_URL",
|
||||||
|
"API_KEY",
|
||||||
|
"LOG_LEVEL",
|
||||||
|
"ZION_ENDPOINT",
|
||||||
|
]
|
||||||
|
for config in configs:
|
||||||
|
if os.getenv(config) is None or os.getenv(config) == "":
|
||||||
|
raise Exception(f"{config} var isn't instanciate in dotenv")
|
||||||
|
if (
|
||||||
|
os.getenv("MATRIX_MODE") != "development"
|
||||||
|
and os.getenv("MATRIX_MODE") != "production"
|
||||||
|
):
|
||||||
|
raise Exception("MATRIX_MODE value isn't manage")
|
||||||
|
|
||||||
|
|
||||||
|
def print_env() -> None:
|
||||||
|
print("Configuration loaded:")
|
||||||
|
print(f"Mode: {os.getenv('MATRIX_MODE')}")
|
||||||
|
print("Database: Connected to local instance")
|
||||||
|
print("API Access: Authenticated")
|
||||||
|
print(f"Log Level: {os.getenv('LOG_LEV')}")
|
||||||
|
print("Zion Network: Online")
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
try:
|
||||||
|
print("\nORACLE STATUS: Reading the Matrix...\n")
|
||||||
|
load_dotenv()
|
||||||
|
check_env()
|
||||||
|
print_env()
|
||||||
|
print("\nEnvironment security check:")
|
||||||
|
print("[OK] No hardcoded secrets detected")
|
||||||
|
print("[OK] .env file properly configured")
|
||||||
|
print("[OK] Production overrides available")
|
||||||
|
print("The Oracle sees all configurations.")
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
237
09/data_exporter.py
Normal file
237
09/data_exporter.py
Normal file
@@ -0,0 +1,237 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Data export utilities for the Cosmic Data Observatory
|
||||||
|
Exports generated data to JSON, CSV, and Python formats for testing
|
||||||
|
"""
|
||||||
|
|
||||||
|
import json
|
||||||
|
import csv
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import List, Dict, Any, Union
|
||||||
|
from data_generator import SpaceStationGenerator, AlienContactGenerator, CrewMissionGenerator, DataConfig
|
||||||
|
|
||||||
|
|
||||||
|
class DataExporter:
|
||||||
|
"""Handles data export in multiple formats"""
|
||||||
|
|
||||||
|
def __init__(self, output_dir: str = "generated_data"):
|
||||||
|
self.output_dir = Path(output_dir)
|
||||||
|
self.output_dir.mkdir(exist_ok=True)
|
||||||
|
|
||||||
|
def export_to_json(self, data: List[Dict[str, Any]], filename: str) -> Path:
|
||||||
|
"""Export data to JSON format"""
|
||||||
|
filepath = self.output_dir / f"{filename}.json"
|
||||||
|
|
||||||
|
with open(filepath, 'w', encoding='utf-8') as f:
|
||||||
|
json.dump(data, f, indent=2, ensure_ascii=False)
|
||||||
|
|
||||||
|
return filepath
|
||||||
|
|
||||||
|
def export_to_csv(self, data: List[Dict[str, Any]], filename: str) -> Path:
|
||||||
|
"""Export flat data to CSV format"""
|
||||||
|
if not data:
|
||||||
|
return None
|
||||||
|
|
||||||
|
filepath = self.output_dir / f"{filename}.csv"
|
||||||
|
|
||||||
|
# Handle nested data by flattening
|
||||||
|
flat_data = []
|
||||||
|
for item in data:
|
||||||
|
flat_item = self._flatten_dict(item)
|
||||||
|
flat_data.append(flat_item)
|
||||||
|
|
||||||
|
# Get all unique keys for CSV headers
|
||||||
|
all_keys = set()
|
||||||
|
for item in flat_data:
|
||||||
|
all_keys.update(item.keys())
|
||||||
|
|
||||||
|
with open(filepath, 'w', newline='', encoding='utf-8') as f:
|
||||||
|
writer = csv.DictWriter(f, fieldnames=sorted(all_keys))
|
||||||
|
writer.writeheader()
|
||||||
|
writer.writerows(flat_data)
|
||||||
|
|
||||||
|
return filepath
|
||||||
|
|
||||||
|
def export_to_python(self, data: List[Dict[str, Any]], filename: str, variable_name: str) -> Path:
|
||||||
|
"""Export data as Python variable for direct import"""
|
||||||
|
filepath = self.output_dir / f"{filename}.py"
|
||||||
|
|
||||||
|
with open(filepath, 'w', encoding='utf-8') as f:
|
||||||
|
f.write(f'"""\nGenerated test data for {filename}\n"""\n\n')
|
||||||
|
# Use repr() to get proper Python syntax instead of JSON
|
||||||
|
f.write(f'{variable_name} = {self._format_python_data(data)}\n')
|
||||||
|
|
||||||
|
return filepath
|
||||||
|
|
||||||
|
def _format_python_data(self, data: Any, indent: int = 0) -> str:
|
||||||
|
"""Format data as valid Python code with proper True/False/None"""
|
||||||
|
indent_str = ' ' * indent
|
||||||
|
next_indent_str = ' ' * (indent + 1)
|
||||||
|
|
||||||
|
if data is None:
|
||||||
|
return 'None'
|
||||||
|
elif isinstance(data, bool):
|
||||||
|
return 'True' if data else 'False'
|
||||||
|
elif isinstance(data, (int, float)):
|
||||||
|
return str(data)
|
||||||
|
elif isinstance(data, str):
|
||||||
|
# Escape quotes and format as Python string
|
||||||
|
return repr(data)
|
||||||
|
elif isinstance(data, list):
|
||||||
|
if not data:
|
||||||
|
return '[]'
|
||||||
|
items = []
|
||||||
|
for item in data:
|
||||||
|
formatted_item = self._format_python_data(item, indent + 1)
|
||||||
|
items.append(f'{next_indent_str}{formatted_item}')
|
||||||
|
return '[\n' + ',\n'.join(items) + f'\n{indent_str}]'
|
||||||
|
elif isinstance(data, dict):
|
||||||
|
if not data:
|
||||||
|
return '{}'
|
||||||
|
items = []
|
||||||
|
for key, value in data.items():
|
||||||
|
formatted_value = self._format_python_data(value, indent + 1)
|
||||||
|
items.append(f'{next_indent_str}{repr(key)}: {formatted_value}')
|
||||||
|
return '{\n' + ',\n'.join(items) + f'\n{indent_str}}}'
|
||||||
|
else:
|
||||||
|
return repr(data)
|
||||||
|
|
||||||
|
def _flatten_dict(self, d: Dict[str, Any], parent_key: str = '', sep: str = '_') -> Dict[str, Any]:
|
||||||
|
"""Flatten nested dictionary for CSV export"""
|
||||||
|
items = []
|
||||||
|
|
||||||
|
for k, v in d.items():
|
||||||
|
new_key = f"{parent_key}{sep}{k}" if parent_key else k
|
||||||
|
|
||||||
|
if isinstance(v, dict):
|
||||||
|
items.extend(self._flatten_dict(v, new_key, sep=sep).items())
|
||||||
|
elif isinstance(v, list) and v and isinstance(v[0], dict):
|
||||||
|
# Handle list of dictionaries by creating numbered entries
|
||||||
|
for i, item in enumerate(v):
|
||||||
|
if isinstance(item, dict):
|
||||||
|
items.extend(self._flatten_dict(item, f"{new_key}_{i}", sep=sep).items())
|
||||||
|
else:
|
||||||
|
items.append((f"{new_key}_{i}", item))
|
||||||
|
elif isinstance(v, list):
|
||||||
|
# Simple list - join as string
|
||||||
|
items.append((new_key, ', '.join(map(str, v))))
|
||||||
|
else:
|
||||||
|
items.append((new_key, v))
|
||||||
|
|
||||||
|
return dict(items)
|
||||||
|
|
||||||
|
|
||||||
|
def generate_all_datasets():
|
||||||
|
"""Generate complete datasets for all exercise types"""
|
||||||
|
config = DataConfig()
|
||||||
|
exporter = DataExporter()
|
||||||
|
|
||||||
|
print("🔄 Generating complete datasets...")
|
||||||
|
|
||||||
|
# Generate space station data
|
||||||
|
station_gen = SpaceStationGenerator(config)
|
||||||
|
stations = station_gen.generate_station_data(10)
|
||||||
|
|
||||||
|
# Generate alien contact data
|
||||||
|
contact_gen = AlienContactGenerator(config)
|
||||||
|
contacts = contact_gen.generate_contact_data(15)
|
||||||
|
|
||||||
|
# Generate mission data
|
||||||
|
mission_gen = CrewMissionGenerator(config)
|
||||||
|
missions = mission_gen.generate_mission_data(5)
|
||||||
|
|
||||||
|
# Export in multiple formats
|
||||||
|
datasets = [
|
||||||
|
(stations, "space_stations", "SPACE_STATIONS"),
|
||||||
|
(contacts, "alien_contacts", "ALIEN_CONTACTS"),
|
||||||
|
(missions, "space_missions", "SPACE_MISSIONS")
|
||||||
|
]
|
||||||
|
|
||||||
|
exported_files = []
|
||||||
|
|
||||||
|
for data, filename, var_name in datasets:
|
||||||
|
# Export to JSON
|
||||||
|
json_file = exporter.export_to_json(data, filename)
|
||||||
|
exported_files.append(json_file)
|
||||||
|
|
||||||
|
# Export to Python
|
||||||
|
py_file = exporter.export_to_python(data, filename, var_name)
|
||||||
|
exported_files.append(py_file)
|
||||||
|
|
||||||
|
# Export to CSV (only for non-nested data)
|
||||||
|
if filename != "space_missions": # Missions have nested crew data
|
||||||
|
csv_file = exporter.export_to_csv(data, filename)
|
||||||
|
if csv_file:
|
||||||
|
exported_files.append(csv_file)
|
||||||
|
|
||||||
|
print(f"✅ Generated {len(exported_files)} data files:")
|
||||||
|
for file_path in exported_files:
|
||||||
|
print(f" 📄 {file_path}")
|
||||||
|
|
||||||
|
return exported_files
|
||||||
|
|
||||||
|
|
||||||
|
def create_test_scenarios():
|
||||||
|
"""Create specific test scenarios for validation testing"""
|
||||||
|
config = DataConfig()
|
||||||
|
exporter = DataExporter()
|
||||||
|
|
||||||
|
# Invalid space station data
|
||||||
|
invalid_stations = [
|
||||||
|
{
|
||||||
|
"station_id": "TOOLONG123456", # Too long
|
||||||
|
"name": "Test Station",
|
||||||
|
"crew_size": 25, # Too many crew
|
||||||
|
"power_level": 85.0,
|
||||||
|
"oxygen_level": 92.0,
|
||||||
|
"last_maintenance": "2024-01-15T10:30:00",
|
||||||
|
"is_operational": True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"station_id": "TS", # Too short
|
||||||
|
"name": "", # Empty name
|
||||||
|
"crew_size": 0, # No crew
|
||||||
|
"power_level": -10.0, # Negative power
|
||||||
|
"oxygen_level": 150.0, # Over 100%
|
||||||
|
"last_maintenance": "2024-01-15T10:30:00",
|
||||||
|
"is_operational": True
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
# Invalid alien contacts
|
||||||
|
invalid_contacts = [
|
||||||
|
{
|
||||||
|
"contact_id": "WRONG_FORMAT", # Doesn't start with AC
|
||||||
|
"timestamp": "2024-01-15T14:30:00",
|
||||||
|
"location": "Area 51",
|
||||||
|
"contact_type": "radio",
|
||||||
|
"signal_strength": 8.5,
|
||||||
|
"duration_minutes": 45,
|
||||||
|
"witness_count": 5,
|
||||||
|
"message_received": None, # Strong signal without message
|
||||||
|
"is_verified": False
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"contact_id": "AC_2024_002",
|
||||||
|
"timestamp": "2024-01-16T09:15:00",
|
||||||
|
"location": "Roswell",
|
||||||
|
"contact_type": "telepathic",
|
||||||
|
"signal_strength": 6.2,
|
||||||
|
"duration_minutes": 30,
|
||||||
|
"witness_count": 1, # Too few witnesses for telepathic
|
||||||
|
"message_received": None,
|
||||||
|
"is_verified": False
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
# Export test scenarios
|
||||||
|
exporter.export_to_json(invalid_stations, "invalid_stations")
|
||||||
|
exporter.export_to_json(invalid_contacts, "invalid_contacts")
|
||||||
|
|
||||||
|
print("🧪 Created validation test scenarios")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
generate_all_datasets()
|
||||||
|
create_test_scenarios()
|
||||||
|
print("\n🎯 All data files ready for testing!")
|
||||||
302
09/data_generator.py
Normal file
302
09/data_generator.py
Normal file
@@ -0,0 +1,302 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Cosmic Data Observatory - Data Generator
|
||||||
|
Generates realistic test data for space station monitoring, alien contacts, and crew missions.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import random
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
from typing import List, Dict, Any
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class DataConfig:
|
||||||
|
"""Configuration parameters for data generation"""
|
||||||
|
seed: int = 42
|
||||||
|
base_date: datetime = datetime(2024, 1, 1)
|
||||||
|
date_range_days: int = 365
|
||||||
|
|
||||||
|
|
||||||
|
class SpaceStationGenerator:
|
||||||
|
"""Generates space station monitoring data"""
|
||||||
|
|
||||||
|
STATION_NAMES = [
|
||||||
|
"International Space Station", "Lunar Gateway", "Mars Orbital Platform",
|
||||||
|
"Europa Research Station", "Titan Mining Outpost", "Asteroid Belt Relay",
|
||||||
|
"Deep Space Observatory", "Solar Wind Monitor", "Quantum Communications Hub"
|
||||||
|
]
|
||||||
|
|
||||||
|
STATION_PREFIXES = ["ISS", "LGW", "MOP", "ERS", "TMO", "ABR", "DSO", "SWM", "QCH"]
|
||||||
|
|
||||||
|
def __init__(self, config: DataConfig):
|
||||||
|
self.config = config
|
||||||
|
random.seed(config.seed)
|
||||||
|
|
||||||
|
def generate_station_data(self, count: int = 5) -> List[Dict[str, Any]]:
|
||||||
|
"""Generate multiple space station records"""
|
||||||
|
stations = []
|
||||||
|
|
||||||
|
for i in range(count):
|
||||||
|
station_id = f"{random.choice(self.STATION_PREFIXES)}{random.randint(100, 999)}"
|
||||||
|
name = random.choice(self.STATION_NAMES)
|
||||||
|
|
||||||
|
# Realistic operational parameters
|
||||||
|
crew_size = random.randint(3, 12)
|
||||||
|
power_level = round(random.uniform(70.0, 98.5), 1)
|
||||||
|
oxygen_level = round(random.uniform(85.0, 99.2), 1)
|
||||||
|
|
||||||
|
# Recent maintenance date
|
||||||
|
days_ago = random.randint(1, 180)
|
||||||
|
maintenance_date = self.config.base_date - timedelta(days=days_ago)
|
||||||
|
|
||||||
|
# Operational status based on system health
|
||||||
|
is_operational = power_level > 75.0 and oxygen_level > 90.0
|
||||||
|
|
||||||
|
# Optional maintenance notes
|
||||||
|
notes = None
|
||||||
|
if not is_operational:
|
||||||
|
notes = "System diagnostics required"
|
||||||
|
elif random.random() < 0.3:
|
||||||
|
notes = "All systems nominal"
|
||||||
|
|
||||||
|
stations.append({
|
||||||
|
"station_id": station_id,
|
||||||
|
"name": name,
|
||||||
|
"crew_size": crew_size,
|
||||||
|
"power_level": power_level,
|
||||||
|
"oxygen_level": oxygen_level,
|
||||||
|
"last_maintenance": maintenance_date.isoformat(),
|
||||||
|
"is_operational": is_operational,
|
||||||
|
"notes": notes
|
||||||
|
})
|
||||||
|
|
||||||
|
return stations
|
||||||
|
|
||||||
|
|
||||||
|
class AlienContactGenerator:
|
||||||
|
"""Generates alien contact report data"""
|
||||||
|
|
||||||
|
LOCATIONS = [
|
||||||
|
"Area 51, Nevada", "Roswell, New Mexico", "SETI Institute, California",
|
||||||
|
"Arecibo Observatory, Puerto Rico", "Atacama Desert, Chile",
|
||||||
|
"Antarctic Research Station", "International Space Station",
|
||||||
|
"Mauna Kea Observatory, Hawaii", "Very Large Array, New Mexico"
|
||||||
|
]
|
||||||
|
|
||||||
|
CONTACT_TYPES = ["radio", "visual", "physical", "telepathic"]
|
||||||
|
|
||||||
|
MESSAGES = [
|
||||||
|
"Greetings from Zeta Reticuli",
|
||||||
|
"Mathematical sequence detected: prime numbers",
|
||||||
|
"Coordinates to star system received",
|
||||||
|
"Warning about solar flare activity",
|
||||||
|
"Request for peaceful contact",
|
||||||
|
"Unknown language pattern identified"
|
||||||
|
]
|
||||||
|
|
||||||
|
def __init__(self, config: DataConfig):
|
||||||
|
self.config = config
|
||||||
|
random.seed(config.seed + 1)
|
||||||
|
|
||||||
|
def generate_contact_data(self, count: int = 8) -> List[Dict[str, Any]]:
|
||||||
|
"""Generate multiple alien contact records"""
|
||||||
|
contacts = []
|
||||||
|
|
||||||
|
for i in range(count):
|
||||||
|
contact_id = f"AC_{self.config.base_date.year}_{str(i+1).zfill(3)}"
|
||||||
|
|
||||||
|
# Random contact timing within date range
|
||||||
|
days_offset = random.randint(0, self.config.date_range_days)
|
||||||
|
contact_time = self.config.base_date + timedelta(days=days_offset)
|
||||||
|
|
||||||
|
location = random.choice(self.LOCATIONS)
|
||||||
|
contact_type = random.choice(self.CONTACT_TYPES)
|
||||||
|
|
||||||
|
# Signal characteristics
|
||||||
|
signal_strength = round(random.uniform(1.0, 10.0), 1)
|
||||||
|
duration = random.randint(5, 240) # 5 minutes to 4 hours
|
||||||
|
witnesses = random.randint(1, 15)
|
||||||
|
|
||||||
|
# Message content for strong signals
|
||||||
|
message = None
|
||||||
|
if signal_strength > 6.0 and random.random() < 0.7:
|
||||||
|
message = random.choice(self.MESSAGES)
|
||||||
|
|
||||||
|
# Verification status
|
||||||
|
is_verified = False
|
||||||
|
if contact_type == "physical":
|
||||||
|
is_verified = True # Physical contacts must be verified
|
||||||
|
elif contact_type == "radio" and signal_strength > 8.0:
|
||||||
|
is_verified = random.random() < 0.8
|
||||||
|
|
||||||
|
# Adjust witnesses for telepathic contacts
|
||||||
|
if contact_type == "telepathic" and witnesses < 3:
|
||||||
|
witnesses = random.randint(3, 8)
|
||||||
|
|
||||||
|
contacts.append({
|
||||||
|
"contact_id": contact_id,
|
||||||
|
"timestamp": contact_time.isoformat(),
|
||||||
|
"location": location,
|
||||||
|
"contact_type": contact_type,
|
||||||
|
"signal_strength": signal_strength,
|
||||||
|
"duration_minutes": duration,
|
||||||
|
"witness_count": witnesses,
|
||||||
|
"message_received": message,
|
||||||
|
"is_verified": is_verified
|
||||||
|
})
|
||||||
|
|
||||||
|
return contacts
|
||||||
|
|
||||||
|
|
||||||
|
class CrewMissionGenerator:
|
||||||
|
"""Generates space crew and mission data"""
|
||||||
|
|
||||||
|
FIRST_NAMES = [
|
||||||
|
"Sarah", "John", "Alice", "Michael", "Emma", "David", "Lisa", "Robert",
|
||||||
|
"Maria", "James", "Anna", "William", "Elena", "Thomas", "Sofia", "Daniel"
|
||||||
|
]
|
||||||
|
|
||||||
|
LAST_NAMES = [
|
||||||
|
"Connor", "Smith", "Johnson", "Williams", "Brown", "Jones", "Garcia",
|
||||||
|
"Miller", "Davis", "Rodriguez", "Martinez", "Hernandez", "Lopez", "Gonzalez"
|
||||||
|
]
|
||||||
|
|
||||||
|
SPECIALIZATIONS = [
|
||||||
|
"Mission Command", "Navigation", "Engineering", "Life Support",
|
||||||
|
"Communications", "Medical Officer", "Pilot", "Science Officer",
|
||||||
|
"Maintenance", "Security", "Research", "Systems Analysis"
|
||||||
|
]
|
||||||
|
|
||||||
|
RANKS = ["cadet", "officer", "lieutenant", "captain", "commander"]
|
||||||
|
|
||||||
|
DESTINATIONS = [
|
||||||
|
"Mars", "Moon", "Europa", "Titan", "Asteroid Belt",
|
||||||
|
"Jupiter Orbit", "Saturn Rings", "Deep Space", "Solar Observatory"
|
||||||
|
]
|
||||||
|
|
||||||
|
def __init__(self, config: DataConfig):
|
||||||
|
self.config = config
|
||||||
|
random.seed(config.seed + 2)
|
||||||
|
|
||||||
|
def generate_crew_member(self, member_id: str) -> Dict[str, Any]:
|
||||||
|
"""Generate a single crew member"""
|
||||||
|
name = f"{random.choice(self.FIRST_NAMES)} {random.choice(self.LAST_NAMES)}"
|
||||||
|
rank = random.choice(self.RANKS)
|
||||||
|
age = random.randint(25, 55)
|
||||||
|
specialization = random.choice(self.SPECIALIZATIONS)
|
||||||
|
|
||||||
|
# Experience correlates with age and rank
|
||||||
|
base_experience = max(0, age - 22)
|
||||||
|
rank_bonus = {"cadet": 0, "officer": 2, "lieutenant": 5, "captain": 8, "commander": 12}
|
||||||
|
years_experience = min(base_experience + rank_bonus[rank] + random.randint(-2, 3), 30)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"member_id": member_id,
|
||||||
|
"name": name,
|
||||||
|
"rank": rank,
|
||||||
|
"age": age,
|
||||||
|
"specialization": specialization,
|
||||||
|
"years_experience": max(0, years_experience),
|
||||||
|
"is_active": True
|
||||||
|
}
|
||||||
|
|
||||||
|
def generate_mission_data(self, count: int = 3) -> List[Dict[str, Any]]:
|
||||||
|
"""Generate complete mission records with crews"""
|
||||||
|
missions = []
|
||||||
|
|
||||||
|
for i in range(count):
|
||||||
|
mission_id = f"M{self.config.base_date.year}_{random.choice(['MARS', 'LUNA', 'EUROPA', 'TITAN'])}"
|
||||||
|
destination = random.choice(self.DESTINATIONS)
|
||||||
|
mission_name = f"{destination} {'Colony' if random.random() < 0.5 else 'Research'} Mission"
|
||||||
|
|
||||||
|
# Mission timing
|
||||||
|
launch_offset = random.randint(30, 300)
|
||||||
|
launch_date = self.config.base_date + timedelta(days=launch_offset)
|
||||||
|
|
||||||
|
# Mission parameters
|
||||||
|
duration = random.randint(90, 1200) # 3 months to 3+ years
|
||||||
|
budget = round(random.uniform(500.0, 5000.0), 1)
|
||||||
|
|
||||||
|
# Generate crew (3-8 members)
|
||||||
|
crew_size = random.randint(3, 8)
|
||||||
|
crew = []
|
||||||
|
|
||||||
|
# Ensure at least one high-ranking officer
|
||||||
|
has_commander = False
|
||||||
|
for j in range(crew_size):
|
||||||
|
member_id = f"CM{str(i*10 + j + 1).zfill(3)}"
|
||||||
|
member = self.generate_crew_member(member_id)
|
||||||
|
|
||||||
|
# First member has higher chance of being high-ranking
|
||||||
|
if j == 0 and not has_commander:
|
||||||
|
member["rank"] = random.choice(["captain", "commander"])
|
||||||
|
has_commander = True
|
||||||
|
|
||||||
|
crew.append(member)
|
||||||
|
|
||||||
|
# For long missions, ensure experienced crew
|
||||||
|
if duration > 365:
|
||||||
|
experienced_needed = len(crew) // 2
|
||||||
|
experienced_count = sum(1 for member in crew if member["years_experience"] >= 5)
|
||||||
|
|
||||||
|
if experienced_count < experienced_needed:
|
||||||
|
# Boost experience for some crew members
|
||||||
|
for member in crew[:experienced_needed]:
|
||||||
|
if member["years_experience"] < 5:
|
||||||
|
member["years_experience"] = random.randint(5, 15)
|
||||||
|
|
||||||
|
missions.append({
|
||||||
|
"mission_id": mission_id,
|
||||||
|
"mission_name": mission_name,
|
||||||
|
"destination": destination,
|
||||||
|
"launch_date": launch_date.isoformat(),
|
||||||
|
"duration_days": duration,
|
||||||
|
"crew": crew,
|
||||||
|
"mission_status": "planned",
|
||||||
|
"budget_millions": budget
|
||||||
|
})
|
||||||
|
|
||||||
|
return missions
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Generate sample data for all exercise types"""
|
||||||
|
config = DataConfig()
|
||||||
|
|
||||||
|
print("🚀 Cosmic Data Observatory - Sample Data Generator")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
# Generate space station data
|
||||||
|
station_gen = SpaceStationGenerator(config)
|
||||||
|
stations = station_gen.generate_station_data(5)
|
||||||
|
|
||||||
|
print(f"\n📡 Generated {len(stations)} space stations:")
|
||||||
|
for station in stations:
|
||||||
|
status = "✅ Operational" if station["is_operational"] else "⚠️ Maintenance"
|
||||||
|
print(f" {station['station_id']}: {station['name']} - {status}")
|
||||||
|
|
||||||
|
# Generate alien contact data
|
||||||
|
contact_gen = AlienContactGenerator(config)
|
||||||
|
contacts = contact_gen.generate_contact_data(6)
|
||||||
|
|
||||||
|
print(f"\n👽 Generated {len(contacts)} alien contacts:")
|
||||||
|
for contact in contacts:
|
||||||
|
verified = "✅ Verified" if contact["is_verified"] else "❓ Unverified"
|
||||||
|
print(f" {contact['contact_id']}: {contact['contact_type']} at {contact['location']} - {verified}")
|
||||||
|
|
||||||
|
# Generate mission data
|
||||||
|
mission_gen = CrewMissionGenerator(config)
|
||||||
|
missions = mission_gen.generate_mission_data(3)
|
||||||
|
|
||||||
|
print(f"\n🚀 Generated {len(missions)} space missions:")
|
||||||
|
for mission in missions:
|
||||||
|
print(f" {mission['mission_id']}: {mission['mission_name']}")
|
||||||
|
print(f" Crew: {len(mission['crew'])} members, Duration: {mission['duration_days']} days")
|
||||||
|
|
||||||
|
print("\n" + "=" * 60)
|
||||||
|
print("Data generation complete! Use these generators in your exercises.")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
194
09/ex0/space_station.py
Normal file
194
09/ex0/space_station.py
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
import datetime
|
||||||
|
from typing import Optional
|
||||||
|
from pydantic import BaseModel, Field, ValidationError
|
||||||
|
|
||||||
|
SPACE_STATIONS = [
|
||||||
|
{
|
||||||
|
"station_id": "LGW125",
|
||||||
|
"name": "Titan Mining Outpost",
|
||||||
|
"crew_size": 6,
|
||||||
|
"power_level": 76.4,
|
||||||
|
"oxygen_level": 95.5,
|
||||||
|
"last_maintenance": "2023-07-11T00:00:00",
|
||||||
|
"is_operational": True,
|
||||||
|
"notes": None,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"station_id": "QCH189",
|
||||||
|
"name": "Deep Space Observatory",
|
||||||
|
"crew_size": 3,
|
||||||
|
"power_level": 70.8,
|
||||||
|
"oxygen_level": 88.1,
|
||||||
|
"last_maintenance": "2023-08-24T00:00:00",
|
||||||
|
"is_operational": False,
|
||||||
|
"notes": "System diagnostics required",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"station_id": "ISS674",
|
||||||
|
"name": "Europa Research Station",
|
||||||
|
"crew_size": 11,
|
||||||
|
"power_level": 82.0,
|
||||||
|
"oxygen_level": 91.4,
|
||||||
|
"last_maintenance": "2023-10-21T00:00:00",
|
||||||
|
"is_operational": True,
|
||||||
|
"notes": None,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"station_id": "ISS877",
|
||||||
|
"name": "Mars Orbital Platform",
|
||||||
|
"crew_size": 9,
|
||||||
|
"power_level": 79.7,
|
||||||
|
"oxygen_level": 87.2,
|
||||||
|
"last_maintenance": "2023-10-06T00:00:00",
|
||||||
|
"is_operational": False,
|
||||||
|
"notes": "System diagnostics required",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"station_id": "LGW194",
|
||||||
|
"name": "Deep Space Observatory",
|
||||||
|
"crew_size": 4,
|
||||||
|
"power_level": 80.2,
|
||||||
|
"oxygen_level": 89.9,
|
||||||
|
"last_maintenance": "2023-10-25T00:00:00",
|
||||||
|
"is_operational": False,
|
||||||
|
"notes": "System diagnostics required",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"station_id": "ISS847",
|
||||||
|
"name": "Solar Wind Monitor",
|
||||||
|
"crew_size": 11,
|
||||||
|
"power_level": 73.6,
|
||||||
|
"oxygen_level": 98.1,
|
||||||
|
"last_maintenance": "2023-12-11T00:00:00",
|
||||||
|
"is_operational": False,
|
||||||
|
"notes": "System diagnostics required",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"station_id": "QCH400",
|
||||||
|
"name": "Asteroid Belt Relay",
|
||||||
|
"crew_size": 12,
|
||||||
|
"power_level": 75.5,
|
||||||
|
"oxygen_level": 86.0,
|
||||||
|
"last_maintenance": "2023-07-15T00:00:00",
|
||||||
|
"is_operational": False,
|
||||||
|
"notes": "System diagnostics required",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"station_id": "ERS891",
|
||||||
|
"name": "Titan Mining Outpost",
|
||||||
|
"crew_size": 4,
|
||||||
|
"power_level": 94.4,
|
||||||
|
"oxygen_level": 97.3,
|
||||||
|
"last_maintenance": "2023-09-25T00:00:00",
|
||||||
|
"is_operational": True,
|
||||||
|
"notes": "All systems nominal",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"station_id": "ABR266",
|
||||||
|
"name": "Asteroid Belt Relay",
|
||||||
|
"crew_size": 8,
|
||||||
|
"power_level": 76.0,
|
||||||
|
"oxygen_level": 88.8,
|
||||||
|
"last_maintenance": "2023-07-10T00:00:00",
|
||||||
|
"is_operational": False,
|
||||||
|
"notes": "System diagnostics required",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"station_id": "LGW723",
|
||||||
|
"name": "Mars Orbital Platform",
|
||||||
|
"crew_size": 11,
|
||||||
|
"power_level": 90.8,
|
||||||
|
"oxygen_level": 87.3,
|
||||||
|
"last_maintenance": "2023-09-25T00:00:00",
|
||||||
|
"is_operational": False,
|
||||||
|
"notes": "System diagnostics required",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class SpaceStation(BaseModel):
|
||||||
|
station_id: str = Field(max_length=10, min_length=3)
|
||||||
|
name: str = Field(min_length=1, max_length=50)
|
||||||
|
crew_size: int = Field(le=20, ge=1)
|
||||||
|
power_level: float = Field(ge=0.0, le=100.0)
|
||||||
|
oxygen_level: float = Field(ge=0.0, le=100.0)
|
||||||
|
last_maintenance: datetime.datetime
|
||||||
|
is_operational: bool = Field(default=True)
|
||||||
|
notes: str | None = Field(default=None, max_length=200)
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
try:
|
||||||
|
valid_station = {
|
||||||
|
"station_id": "ISS001",
|
||||||
|
"name": "International Space Station",
|
||||||
|
"crew_size": 6,
|
||||||
|
"power_level": 85.5,
|
||||||
|
"oxygen_level": 92.3,
|
||||||
|
"last_maintenance": "2023-09-25T00:00:00",
|
||||||
|
}
|
||||||
|
|
||||||
|
invalid_station = {
|
||||||
|
"station_id": "ISS001",
|
||||||
|
"name": "International Space Station",
|
||||||
|
"crew_size": 26,
|
||||||
|
"power_level": 85.5,
|
||||||
|
"oxygen_level": 92.3,
|
||||||
|
"last_maintenance": "2023-09-25T00:00:00",
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
print("\nValid station:n\n")
|
||||||
|
ss = SpaceStation(**valid_station)
|
||||||
|
print("Valid station created")
|
||||||
|
print(
|
||||||
|
f"ID: {ss.station_id}\n"
|
||||||
|
f"Name {ss.name}\n"
|
||||||
|
f"Crew: {ss.crew_size} people\n"
|
||||||
|
f"Power: {ss.power_level}%\n"
|
||||||
|
f"Oxygen: {ss.oxygen_level}%\n"
|
||||||
|
f"Status: {'operational' if ss.is_operational else 'not operational'}\n"
|
||||||
|
f"Note: {ss.notes}\n"
|
||||||
|
)
|
||||||
|
except ValidationError as err:
|
||||||
|
print(err)
|
||||||
|
|
||||||
|
try:
|
||||||
|
print("\nInvalid station:\n")
|
||||||
|
ss = SpaceStation(**invalid_station)
|
||||||
|
print("Valid station created")
|
||||||
|
print(
|
||||||
|
f"ID: {ss.station_id}\n"
|
||||||
|
f"Name {ss.name}\n"
|
||||||
|
f"Crew: {ss.crew_size} people\n"
|
||||||
|
f"Power: {ss.power_level}%\n"
|
||||||
|
f"Oxygen: {ss.oxygen_level}%\n"
|
||||||
|
f"Status: {'operational' if ss.is_operational else 'not operational'}\n"
|
||||||
|
f"Note: {ss.notes}\n"
|
||||||
|
)
|
||||||
|
except ValidationError as err:
|
||||||
|
print(err)
|
||||||
|
|
||||||
|
print("\nBatch stations:\n")
|
||||||
|
for station in SPACE_STATIONS:
|
||||||
|
try:
|
||||||
|
ss = SpaceStation(**station)
|
||||||
|
print("========================================")
|
||||||
|
print("Valid station created")
|
||||||
|
print(
|
||||||
|
f"ID: {ss.station_id}\n"
|
||||||
|
f"Name {ss.name}\n"
|
||||||
|
f"Crew: {ss.crew_size} people\n"
|
||||||
|
f"Power: {ss.power_level}%\n"
|
||||||
|
f"Oxygen: {ss.oxygen_level}%\n"
|
||||||
|
f"Status: {'operational' if ss.is_operational else 'not operational'}\n"
|
||||||
|
f"Note: {ss.notes}\n"
|
||||||
|
)
|
||||||
|
except ValidationError as e:
|
||||||
|
print(e.errors())
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
75
09/ex1/alien_contact.py
Normal file
75
09/ex1/alien_contact.py
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
from typing_extensions import Self
|
||||||
|
import datetime
|
||||||
|
from enum import Enum
|
||||||
|
from pydantic import BaseModel, Field, model_validator
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
class ContactType(Enum):
|
||||||
|
RADIO = "radio"
|
||||||
|
VISUAL = "visual"
|
||||||
|
PHYSICAL = "physical"
|
||||||
|
TELEPATHIC = "telepathic"
|
||||||
|
|
||||||
|
|
||||||
|
class AlienContact(BaseModel):
|
||||||
|
contact_id: str = Field(min_length=5, max_length=15)
|
||||||
|
timestamp: datetime.datetime
|
||||||
|
location: str = Field(min_length=3, max_length=100)
|
||||||
|
contact_type: ContactType
|
||||||
|
signal_strength: float = Field(ge=0.0, le=10.0)
|
||||||
|
duration_minutes: int = Field(ge=1, le=1440)
|
||||||
|
witness_count: int = Field(ge=1, le=100)
|
||||||
|
message_received: str | None = Field(default=None, max_length=500)
|
||||||
|
is_verified: bool = Field(default=False)
|
||||||
|
|
||||||
|
@model_validator(mode="after")
|
||||||
|
def format_validation(self) -> Self:
|
||||||
|
if not self.contact_id.startswith("AC"):
|
||||||
|
raise ValueError('Contact ID must start with "AC"')
|
||||||
|
if (
|
||||||
|
self.contact_type == ContactType.PHYSICAL
|
||||||
|
and self.is_verified == False
|
||||||
|
):
|
||||||
|
raise ValueError("Physical contact reports must be verified")
|
||||||
|
if (
|
||||||
|
self.contact_type == ContactType.TELEPATHIC
|
||||||
|
and self.witness_count < 3
|
||||||
|
):
|
||||||
|
raise ValueError(
|
||||||
|
"Telepathic contact requires at least 3 witnesses"
|
||||||
|
)
|
||||||
|
if self.signal_strength > 7.0 and not self.message_received:
|
||||||
|
raise ValueError(
|
||||||
|
"Strong signals (> 7.0) should include received messages"
|
||||||
|
)
|
||||||
|
return self
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
try:
|
||||||
|
with open("../generated_data/alien_contacts.json") as file:
|
||||||
|
data = json.load(file)
|
||||||
|
for contact in data:
|
||||||
|
try:
|
||||||
|
ac = AlienContact(**contact)
|
||||||
|
print(
|
||||||
|
f"======================================\n"
|
||||||
|
f"Valid contact report:\n"
|
||||||
|
f"ID: {ac.contact_id}\n"
|
||||||
|
f"Type: {ac.contact_type}\n"
|
||||||
|
f"Location: {ac.location}\n"
|
||||||
|
f"Signal: {ac.signal_strength:.1f}/10\n"
|
||||||
|
f"Duration: {ac.duration_minutes} minutes\n"
|
||||||
|
f"Witness: {ac.witness_count}\n"
|
||||||
|
f"Message: {ac.message_received}\n"
|
||||||
|
f"Is verified: {ac.is_verified}\n"
|
||||||
|
)
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
97
09/ex2/space_crew.py
Normal file
97
09/ex2/space_crew.py
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
from enum import Enum
|
||||||
|
from typing_extensions import Self
|
||||||
|
from pydantic import BaseModel, Field, model_validator
|
||||||
|
from datetime import datetime
|
||||||
|
from json import load
|
||||||
|
|
||||||
|
|
||||||
|
class Rank(Enum):
|
||||||
|
CADET = "cadet"
|
||||||
|
OFFICER = "officer"
|
||||||
|
LIEUTENANT = "lieutenant"
|
||||||
|
CAPTAIN = "captain"
|
||||||
|
COMMANDER = "commander"
|
||||||
|
|
||||||
|
|
||||||
|
class CrewMember(BaseModel):
|
||||||
|
member_id: str = Field(min_length=3, max_length=10)
|
||||||
|
name: str = Field(min_length=2, max_length=50)
|
||||||
|
rank: Rank
|
||||||
|
age: int = Field(ge=18, le=80)
|
||||||
|
specialization: str = Field(min_length=3, max_length=30)
|
||||||
|
years_experience: int = Field(ge=0, le=50)
|
||||||
|
is_active: bool = Field(default=True)
|
||||||
|
|
||||||
|
|
||||||
|
class SpaceMission(BaseModel):
|
||||||
|
mission_id: str = Field(min_length=5, max_length=15)
|
||||||
|
mission_name: str = Field(min_length=3, max_length=100)
|
||||||
|
destination: str = Field(min_length=3, max_length=50)
|
||||||
|
launch_date: datetime
|
||||||
|
duration_days: int = Field(ge=1, le=3650)
|
||||||
|
crew: list[CrewMember] = Field(min_length=1, max_length=12)
|
||||||
|
mission_status: str = Field(default="planned")
|
||||||
|
budget_millions: float = Field(ge=1.0, le=10000.0)
|
||||||
|
|
||||||
|
@model_validator(mode="after")
|
||||||
|
def validation(self) -> Self:
|
||||||
|
if not self.mission_id.startswith("M"):
|
||||||
|
raise ValueError('Mission ID must start with "M"')
|
||||||
|
try:
|
||||||
|
crew = {member.rank: member for member in self.crew}
|
||||||
|
crew[Rank.CAPTAIN]
|
||||||
|
crew[Rank.COMMANDER]
|
||||||
|
except KeyError:
|
||||||
|
raise ValueError("Must have at least one Commander or Captain")
|
||||||
|
if (
|
||||||
|
self.duration_days > 365
|
||||||
|
and len(
|
||||||
|
[
|
||||||
|
member
|
||||||
|
for member in self.crew
|
||||||
|
if member.years_experience >= 5
|
||||||
|
]
|
||||||
|
)
|
||||||
|
< len(self.crew) / 2
|
||||||
|
):
|
||||||
|
raise ValueError(
|
||||||
|
"Long missions (> 365 days) need 50% "
|
||||||
|
"experienced crew (5+ years)"
|
||||||
|
)
|
||||||
|
for member in self.crew:
|
||||||
|
if member.is_active == False:
|
||||||
|
raise ValueError("All crew members must be active")
|
||||||
|
return self
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
try:
|
||||||
|
with open("../generated_data/space_missions.json") as file:
|
||||||
|
data = load(file)
|
||||||
|
for mission in data:
|
||||||
|
try:
|
||||||
|
print("=========================================")
|
||||||
|
sp = SpaceMission(**mission)
|
||||||
|
print(
|
||||||
|
"Valid mission created:\n"
|
||||||
|
f"Mission: {sp.mission_name}\n"
|
||||||
|
f"ID: {sp.mission_id}\n"
|
||||||
|
f"Destination: {sp.destination}\n"
|
||||||
|
f"Duration: {sp.duration_days} days\n"
|
||||||
|
f"Budget: ${sp.budget_millions}M\n"
|
||||||
|
f"Crew size: {len(sp.crew)}\n"
|
||||||
|
"Crew members:"
|
||||||
|
)
|
||||||
|
for member in sp.crew:
|
||||||
|
print(
|
||||||
|
f"- {member.name} ({member.rank}) - "
|
||||||
|
f"{member.specialization}"
|
||||||
|
)
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
16
09/generated_data/alien_contacts.csv
Normal file
16
09/generated_data/alien_contacts.csv
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
contact_id,contact_type,duration_minutes,is_verified,location,message_received,signal_strength,timestamp,witness_count
|
||||||
|
AC_2024_001,visual,99,False,"Atacama Desert, Chile",Greetings from Zeta Reticuli,9.6,2024-01-20T00:00:00,11
|
||||||
|
AC_2024_002,radio,152,False,"Mauna Kea Observatory, Hawaii",,5.6,2024-08-20T00:00:00,6
|
||||||
|
AC_2024_003,telepathic,19,False,"Very Large Array, New Mexico",,4.5,2024-11-15T00:00:00,14
|
||||||
|
AC_2024_004,telepathic,46,False,"Roswell, New Mexico",,2.4,2024-02-24T00:00:00,9
|
||||||
|
AC_2024_005,telepathic,134,False,"SETI Institute, California",Warning about solar flare activity,6.4,2024-09-10T00:00:00,5
|
||||||
|
AC_2024_006,radio,20,False,"Area 51, Nevada",,2.7,2024-02-02T00:00:00,14
|
||||||
|
AC_2024_007,physical,138,True,"Atacama Desert, Chile",Request for peaceful contact,9.0,2024-03-25T00:00:00,10
|
||||||
|
AC_2024_008,radio,122,True,"Area 51, Nevada",Unknown language pattern identified,8.6,2024-11-30T00:00:00,13
|
||||||
|
AC_2024_009,visual,25,False,"Mauna Kea Observatory, Hawaii",,2.1,2024-09-27T00:00:00,13
|
||||||
|
AC_2024_010,physical,52,True,"Area 51, Nevada",,4.3,2024-06-12T00:00:00,11
|
||||||
|
AC_2024_011,radio,235,False,"Roswell, New Mexico",,3.7,2024-11-05T00:00:00,13
|
||||||
|
AC_2024_012,radio,111,False,International Space Station,,5.3,2024-07-04T00:00:00,10
|
||||||
|
AC_2024_013,visual,228,False,Antarctic Research Station,,6.8,2024-02-12T00:00:00,11
|
||||||
|
AC_2024_014,radio,113,False,"Atacama Desert, Chile",Mathematical sequence detected: prime numbers,7.2,2024-10-20T00:00:00,8
|
||||||
|
AC_2024_015,radio,9,False,"Roswell, New Mexico",,2.1,2024-01-02T00:00:00,13
|
||||||
|
167
09/generated_data/alien_contacts.json
Normal file
167
09/generated_data/alien_contacts.json
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"contact_id": "AC_2024_001",
|
||||||
|
"timestamp": "2024-01-20T00:00:00",
|
||||||
|
"location": "Atacama Desert, Chile",
|
||||||
|
"contact_type": "visual",
|
||||||
|
"signal_strength": 9.6,
|
||||||
|
"duration_minutes": 99,
|
||||||
|
"witness_count": 11,
|
||||||
|
"message_received": "Greetings from Zeta Reticuli",
|
||||||
|
"is_verified": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"contact_id": "AC_2024_002",
|
||||||
|
"timestamp": "2024-08-20T00:00:00",
|
||||||
|
"location": "Mauna Kea Observatory, Hawaii",
|
||||||
|
"contact_type": "radio",
|
||||||
|
"signal_strength": 5.6,
|
||||||
|
"duration_minutes": 152,
|
||||||
|
"witness_count": 6,
|
||||||
|
"message_received": null,
|
||||||
|
"is_verified": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"contact_id": "AC_2024_003",
|
||||||
|
"timestamp": "2024-11-15T00:00:00",
|
||||||
|
"location": "Very Large Array, New Mexico",
|
||||||
|
"contact_type": "telepathic",
|
||||||
|
"signal_strength": 4.5,
|
||||||
|
"duration_minutes": 19,
|
||||||
|
"witness_count": 14,
|
||||||
|
"message_received": null,
|
||||||
|
"is_verified": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"contact_id": "AC_2024_004",
|
||||||
|
"timestamp": "2024-02-24T00:00:00",
|
||||||
|
"location": "Roswell, New Mexico",
|
||||||
|
"contact_type": "telepathic",
|
||||||
|
"signal_strength": 2.4,
|
||||||
|
"duration_minutes": 46,
|
||||||
|
"witness_count": 9,
|
||||||
|
"message_received": null,
|
||||||
|
"is_verified": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"contact_id": "AC_2024_005",
|
||||||
|
"timestamp": "2024-09-10T00:00:00",
|
||||||
|
"location": "SETI Institute, California",
|
||||||
|
"contact_type": "telepathic",
|
||||||
|
"signal_strength": 6.4,
|
||||||
|
"duration_minutes": 134,
|
||||||
|
"witness_count": 5,
|
||||||
|
"message_received": "Warning about solar flare activity",
|
||||||
|
"is_verified": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"contact_id": "AC_2024_006",
|
||||||
|
"timestamp": "2024-02-02T00:00:00",
|
||||||
|
"location": "Area 51, Nevada",
|
||||||
|
"contact_type": "radio",
|
||||||
|
"signal_strength": 2.7,
|
||||||
|
"duration_minutes": 20,
|
||||||
|
"witness_count": 14,
|
||||||
|
"message_received": null,
|
||||||
|
"is_verified": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"contact_id": "AC_2024_007",
|
||||||
|
"timestamp": "2024-03-25T00:00:00",
|
||||||
|
"location": "Atacama Desert, Chile",
|
||||||
|
"contact_type": "physical",
|
||||||
|
"signal_strength": 9.0,
|
||||||
|
"duration_minutes": 138,
|
||||||
|
"witness_count": 10,
|
||||||
|
"message_received": "Request for peaceful contact",
|
||||||
|
"is_verified": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"contact_id": "AC_2024_008",
|
||||||
|
"timestamp": "2024-11-30T00:00:00",
|
||||||
|
"location": "Area 51, Nevada",
|
||||||
|
"contact_type": "radio",
|
||||||
|
"signal_strength": 8.6,
|
||||||
|
"duration_minutes": 122,
|
||||||
|
"witness_count": 13,
|
||||||
|
"message_received": "Unknown language pattern identified",
|
||||||
|
"is_verified": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"contact_id": "AC_2024_009",
|
||||||
|
"timestamp": "2024-09-27T00:00:00",
|
||||||
|
"location": "Mauna Kea Observatory, Hawaii",
|
||||||
|
"contact_type": "visual",
|
||||||
|
"signal_strength": 2.1,
|
||||||
|
"duration_minutes": 25,
|
||||||
|
"witness_count": 13,
|
||||||
|
"message_received": null,
|
||||||
|
"is_verified": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"contact_id": "AC_2024_010",
|
||||||
|
"timestamp": "2024-06-12T00:00:00",
|
||||||
|
"location": "Area 51, Nevada",
|
||||||
|
"contact_type": "physical",
|
||||||
|
"signal_strength": 4.3,
|
||||||
|
"duration_minutes": 52,
|
||||||
|
"witness_count": 11,
|
||||||
|
"message_received": null,
|
||||||
|
"is_verified": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"contact_id": "AC_2024_011",
|
||||||
|
"timestamp": "2024-11-05T00:00:00",
|
||||||
|
"location": "Roswell, New Mexico",
|
||||||
|
"contact_type": "radio",
|
||||||
|
"signal_strength": 3.7,
|
||||||
|
"duration_minutes": 235,
|
||||||
|
"witness_count": 13,
|
||||||
|
"message_received": null,
|
||||||
|
"is_verified": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"contact_id": "AC_2024_012",
|
||||||
|
"timestamp": "2024-07-04T00:00:00",
|
||||||
|
"location": "International Space Station",
|
||||||
|
"contact_type": "radio",
|
||||||
|
"signal_strength": 5.3,
|
||||||
|
"duration_minutes": 111,
|
||||||
|
"witness_count": 10,
|
||||||
|
"message_received": null,
|
||||||
|
"is_verified": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"contact_id": "AC_2024_013",
|
||||||
|
"timestamp": "2024-02-12T00:00:00",
|
||||||
|
"location": "Antarctic Research Station",
|
||||||
|
"contact_type": "visual",
|
||||||
|
"signal_strength": 6.8,
|
||||||
|
"duration_minutes": 228,
|
||||||
|
"witness_count": 11,
|
||||||
|
"message_received": null,
|
||||||
|
"is_verified": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"contact_id": "AC_2024_014",
|
||||||
|
"timestamp": "2024-10-20T00:00:00",
|
||||||
|
"location": "Atacama Desert, Chile",
|
||||||
|
"contact_type": "radio",
|
||||||
|
"signal_strength": 7.2,
|
||||||
|
"duration_minutes": 113,
|
||||||
|
"witness_count": 8,
|
||||||
|
"message_received": "Mathematical sequence detected: prime numbers",
|
||||||
|
"is_verified": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"contact_id": "AC_2024_015",
|
||||||
|
"timestamp": "2024-01-02T00:00:00",
|
||||||
|
"location": "Roswell, New Mexico",
|
||||||
|
"contact_type": "radio",
|
||||||
|
"signal_strength": 2.1,
|
||||||
|
"duration_minutes": 9,
|
||||||
|
"witness_count": 13,
|
||||||
|
"message_received": null,
|
||||||
|
"is_verified": false
|
||||||
|
}
|
||||||
|
]
|
||||||
171
09/generated_data/alien_contacts.py
Normal file
171
09/generated_data/alien_contacts.py
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
"""
|
||||||
|
Generated test data for alien_contacts
|
||||||
|
"""
|
||||||
|
|
||||||
|
ALIEN_CONTACTS = [
|
||||||
|
{
|
||||||
|
'contact_id': 'AC_2024_001',
|
||||||
|
'timestamp': '2024-01-20T00:00:00',
|
||||||
|
'location': 'Atacama Desert, Chile',
|
||||||
|
'contact_type': 'visual',
|
||||||
|
'signal_strength': 9.6,
|
||||||
|
'duration_minutes': 99,
|
||||||
|
'witness_count': 11,
|
||||||
|
'message_received': 'Greetings from Zeta Reticuli',
|
||||||
|
'is_verified': False
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'contact_id': 'AC_2024_002',
|
||||||
|
'timestamp': '2024-08-20T00:00:00',
|
||||||
|
'location': 'Mauna Kea Observatory, Hawaii',
|
||||||
|
'contact_type': 'radio',
|
||||||
|
'signal_strength': 5.6,
|
||||||
|
'duration_minutes': 152,
|
||||||
|
'witness_count': 6,
|
||||||
|
'message_received': None,
|
||||||
|
'is_verified': False
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'contact_id': 'AC_2024_003',
|
||||||
|
'timestamp': '2024-11-15T00:00:00',
|
||||||
|
'location': 'Very Large Array, New Mexico',
|
||||||
|
'contact_type': 'telepathic',
|
||||||
|
'signal_strength': 4.5,
|
||||||
|
'duration_minutes': 19,
|
||||||
|
'witness_count': 14,
|
||||||
|
'message_received': None,
|
||||||
|
'is_verified': False
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'contact_id': 'AC_2024_004',
|
||||||
|
'timestamp': '2024-02-24T00:00:00',
|
||||||
|
'location': 'Roswell, New Mexico',
|
||||||
|
'contact_type': 'telepathic',
|
||||||
|
'signal_strength': 2.4,
|
||||||
|
'duration_minutes': 46,
|
||||||
|
'witness_count': 9,
|
||||||
|
'message_received': None,
|
||||||
|
'is_verified': False
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'contact_id': 'AC_2024_005',
|
||||||
|
'timestamp': '2024-09-10T00:00:00',
|
||||||
|
'location': 'SETI Institute, California',
|
||||||
|
'contact_type': 'telepathic',
|
||||||
|
'signal_strength': 6.4,
|
||||||
|
'duration_minutes': 134,
|
||||||
|
'witness_count': 5,
|
||||||
|
'message_received': 'Warning about solar flare activity',
|
||||||
|
'is_verified': False
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'contact_id': 'AC_2024_006',
|
||||||
|
'timestamp': '2024-02-02T00:00:00',
|
||||||
|
'location': 'Area 51, Nevada',
|
||||||
|
'contact_type': 'radio',
|
||||||
|
'signal_strength': 2.7,
|
||||||
|
'duration_minutes': 20,
|
||||||
|
'witness_count': 14,
|
||||||
|
'message_received': None,
|
||||||
|
'is_verified': False
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'contact_id': 'AC_2024_007',
|
||||||
|
'timestamp': '2024-03-25T00:00:00',
|
||||||
|
'location': 'Atacama Desert, Chile',
|
||||||
|
'contact_type': 'physical',
|
||||||
|
'signal_strength': 9.0,
|
||||||
|
'duration_minutes': 138,
|
||||||
|
'witness_count': 10,
|
||||||
|
'message_received': 'Request for peaceful contact',
|
||||||
|
'is_verified': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'contact_id': 'AC_2024_008',
|
||||||
|
'timestamp': '2024-11-30T00:00:00',
|
||||||
|
'location': 'Area 51, Nevada',
|
||||||
|
'contact_type': 'radio',
|
||||||
|
'signal_strength': 8.6,
|
||||||
|
'duration_minutes': 122,
|
||||||
|
'witness_count': 13,
|
||||||
|
'message_received': 'Unknown language pattern identified',
|
||||||
|
'is_verified': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'contact_id': 'AC_2024_009',
|
||||||
|
'timestamp': '2024-09-27T00:00:00',
|
||||||
|
'location': 'Mauna Kea Observatory, Hawaii',
|
||||||
|
'contact_type': 'visual',
|
||||||
|
'signal_strength': 2.1,
|
||||||
|
'duration_minutes': 25,
|
||||||
|
'witness_count': 13,
|
||||||
|
'message_received': None,
|
||||||
|
'is_verified': False
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'contact_id': 'AC_2024_010',
|
||||||
|
'timestamp': '2024-06-12T00:00:00',
|
||||||
|
'location': 'Area 51, Nevada',
|
||||||
|
'contact_type': 'physical',
|
||||||
|
'signal_strength': 4.3,
|
||||||
|
'duration_minutes': 52,
|
||||||
|
'witness_count': 11,
|
||||||
|
'message_received': None,
|
||||||
|
'is_verified': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'contact_id': 'AC_2024_011',
|
||||||
|
'timestamp': '2024-11-05T00:00:00',
|
||||||
|
'location': 'Roswell, New Mexico',
|
||||||
|
'contact_type': 'radio',
|
||||||
|
'signal_strength': 3.7,
|
||||||
|
'duration_minutes': 235,
|
||||||
|
'witness_count': 13,
|
||||||
|
'message_received': None,
|
||||||
|
'is_verified': False
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'contact_id': 'AC_2024_012',
|
||||||
|
'timestamp': '2024-07-04T00:00:00',
|
||||||
|
'location': 'International Space Station',
|
||||||
|
'contact_type': 'radio',
|
||||||
|
'signal_strength': 5.3,
|
||||||
|
'duration_minutes': 111,
|
||||||
|
'witness_count': 10,
|
||||||
|
'message_received': None,
|
||||||
|
'is_verified': False
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'contact_id': 'AC_2024_013',
|
||||||
|
'timestamp': '2024-02-12T00:00:00',
|
||||||
|
'location': 'Antarctic Research Station',
|
||||||
|
'contact_type': 'visual',
|
||||||
|
'signal_strength': 6.8,
|
||||||
|
'duration_minutes': 228,
|
||||||
|
'witness_count': 11,
|
||||||
|
'message_received': None,
|
||||||
|
'is_verified': False
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'contact_id': 'AC_2024_014',
|
||||||
|
'timestamp': '2024-10-20T00:00:00',
|
||||||
|
'location': 'Atacama Desert, Chile',
|
||||||
|
'contact_type': 'radio',
|
||||||
|
'signal_strength': 7.2,
|
||||||
|
'duration_minutes': 113,
|
||||||
|
'witness_count': 8,
|
||||||
|
'message_received': 'Mathematical sequence detected: prime numbers',
|
||||||
|
'is_verified': False
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'contact_id': 'AC_2024_015',
|
||||||
|
'timestamp': '2024-01-02T00:00:00',
|
||||||
|
'location': 'Roswell, New Mexico',
|
||||||
|
'contact_type': 'radio',
|
||||||
|
'signal_strength': 2.1,
|
||||||
|
'duration_minutes': 9,
|
||||||
|
'witness_count': 13,
|
||||||
|
'message_received': None,
|
||||||
|
'is_verified': False
|
||||||
|
}
|
||||||
|
]
|
||||||
24
09/generated_data/invalid_contacts.json
Normal file
24
09/generated_data/invalid_contacts.json
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"contact_id": "WRONG_FORMAT",
|
||||||
|
"timestamp": "2024-01-15T14:30:00",
|
||||||
|
"location": "Area 51",
|
||||||
|
"contact_type": "radio",
|
||||||
|
"signal_strength": 8.5,
|
||||||
|
"duration_minutes": 45,
|
||||||
|
"witness_count": 5,
|
||||||
|
"message_received": null,
|
||||||
|
"is_verified": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"contact_id": "AC_2024_002",
|
||||||
|
"timestamp": "2024-01-16T09:15:00",
|
||||||
|
"location": "Roswell",
|
||||||
|
"contact_type": "telepathic",
|
||||||
|
"signal_strength": 6.2,
|
||||||
|
"duration_minutes": 30,
|
||||||
|
"witness_count": 1,
|
||||||
|
"message_received": null,
|
||||||
|
"is_verified": false
|
||||||
|
}
|
||||||
|
]
|
||||||
20
09/generated_data/invalid_stations.json
Normal file
20
09/generated_data/invalid_stations.json
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"station_id": "TOOLONG123456",
|
||||||
|
"name": "Test Station",
|
||||||
|
"crew_size": 25,
|
||||||
|
"power_level": 85.0,
|
||||||
|
"oxygen_level": 92.0,
|
||||||
|
"last_maintenance": "2024-01-15T10:30:00",
|
||||||
|
"is_operational": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"station_id": "TS",
|
||||||
|
"name": "",
|
||||||
|
"crew_size": 0,
|
||||||
|
"power_level": -10.0,
|
||||||
|
"oxygen_level": 150.0,
|
||||||
|
"last_maintenance": "2024-01-15T10:30:00",
|
||||||
|
"is_operational": true
|
||||||
|
}
|
||||||
|
]
|
||||||
309
09/generated_data/space_missions.json
Normal file
309
09/generated_data/space_missions.json
Normal file
@@ -0,0 +1,309 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"mission_id": "M2024_TITAN",
|
||||||
|
"mission_name": "Solar Observatory Research Mission",
|
||||||
|
"destination": "Solar Observatory",
|
||||||
|
"launch_date": "2024-03-30T00:00:00",
|
||||||
|
"duration_days": 451,
|
||||||
|
"crew": [
|
||||||
|
{
|
||||||
|
"member_id": "CM001",
|
||||||
|
"name": "Sarah Williams",
|
||||||
|
"rank": "captain",
|
||||||
|
"age": 43,
|
||||||
|
"specialization": "Mission Command",
|
||||||
|
"years_experience": 19,
|
||||||
|
"is_active": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"member_id": "CM002",
|
||||||
|
"name": "James Hernandez",
|
||||||
|
"rank": "captain",
|
||||||
|
"age": 43,
|
||||||
|
"specialization": "Pilot",
|
||||||
|
"years_experience": 30,
|
||||||
|
"is_active": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"member_id": "CM003",
|
||||||
|
"name": "Anna Jones",
|
||||||
|
"rank": "cadet",
|
||||||
|
"age": 35,
|
||||||
|
"specialization": "Communications",
|
||||||
|
"years_experience": 15,
|
||||||
|
"is_active": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"member_id": "CM004",
|
||||||
|
"name": "David Smith",
|
||||||
|
"rank": "commander",
|
||||||
|
"age": 27,
|
||||||
|
"specialization": "Security",
|
||||||
|
"years_experience": 15,
|
||||||
|
"is_active": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"member_id": "CM005",
|
||||||
|
"name": "Maria Jones",
|
||||||
|
"rank": "cadet",
|
||||||
|
"age": 55,
|
||||||
|
"specialization": "Research",
|
||||||
|
"years_experience": 30,
|
||||||
|
"is_active": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"mission_status": "planned",
|
||||||
|
"budget_millions": 2208.1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"mission_id": "M2024_MARS",
|
||||||
|
"mission_name": "Jupiter Orbit Colony Mission",
|
||||||
|
"destination": "Jupiter Orbit",
|
||||||
|
"launch_date": "2024-10-01T00:00:00",
|
||||||
|
"duration_days": 1065,
|
||||||
|
"crew": [
|
||||||
|
{
|
||||||
|
"member_id": "CM011",
|
||||||
|
"name": "Emma Brown",
|
||||||
|
"rank": "commander",
|
||||||
|
"age": 49,
|
||||||
|
"specialization": "Mission Command",
|
||||||
|
"years_experience": 27,
|
||||||
|
"is_active": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"member_id": "CM012",
|
||||||
|
"name": "John Hernandez",
|
||||||
|
"rank": "lieutenant",
|
||||||
|
"age": 36,
|
||||||
|
"specialization": "Science Officer",
|
||||||
|
"years_experience": 22,
|
||||||
|
"is_active": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"member_id": "CM013",
|
||||||
|
"name": "Sofia Rodriguez",
|
||||||
|
"rank": "commander",
|
||||||
|
"age": 29,
|
||||||
|
"specialization": "Life Support",
|
||||||
|
"years_experience": 20,
|
||||||
|
"is_active": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"member_id": "CM014",
|
||||||
|
"name": "Sofia Lopez",
|
||||||
|
"rank": "lieutenant",
|
||||||
|
"age": 44,
|
||||||
|
"specialization": "Systems Analysis",
|
||||||
|
"years_experience": 25,
|
||||||
|
"is_active": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"mission_status": "planned",
|
||||||
|
"budget_millions": 4626.0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"mission_id": "M2024_EUROPA",
|
||||||
|
"mission_name": "Europa Colony Mission",
|
||||||
|
"destination": "Europa",
|
||||||
|
"launch_date": "2024-02-07T00:00:00",
|
||||||
|
"duration_days": 666,
|
||||||
|
"crew": [
|
||||||
|
{
|
||||||
|
"member_id": "CM021",
|
||||||
|
"name": "Lisa Garcia",
|
||||||
|
"rank": "captain",
|
||||||
|
"age": 36,
|
||||||
|
"specialization": "Medical Officer",
|
||||||
|
"years_experience": 12,
|
||||||
|
"is_active": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"member_id": "CM022",
|
||||||
|
"name": "John Garcia",
|
||||||
|
"rank": "cadet",
|
||||||
|
"age": 46,
|
||||||
|
"specialization": "Security",
|
||||||
|
"years_experience": 25,
|
||||||
|
"is_active": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"member_id": "CM023",
|
||||||
|
"name": "Michael Johnson",
|
||||||
|
"rank": "officer",
|
||||||
|
"age": 54,
|
||||||
|
"specialization": "Research",
|
||||||
|
"years_experience": 30,
|
||||||
|
"is_active": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"member_id": "CM024",
|
||||||
|
"name": "Sarah Rodriguez",
|
||||||
|
"rank": "lieutenant",
|
||||||
|
"age": 54,
|
||||||
|
"specialization": "Research",
|
||||||
|
"years_experience": 30,
|
||||||
|
"is_active": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"member_id": "CM025",
|
||||||
|
"name": "Maria Smith",
|
||||||
|
"rank": "cadet",
|
||||||
|
"age": 38,
|
||||||
|
"specialization": "Communications",
|
||||||
|
"years_experience": 15,
|
||||||
|
"is_active": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"mission_status": "planned",
|
||||||
|
"budget_millions": 4976.0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"mission_id": "M2024_LUNA",
|
||||||
|
"mission_name": "Mars Colony Mission",
|
||||||
|
"destination": "Mars",
|
||||||
|
"launch_date": "2024-06-13T00:00:00",
|
||||||
|
"duration_days": 222,
|
||||||
|
"crew": [
|
||||||
|
{
|
||||||
|
"member_id": "CM031",
|
||||||
|
"name": "Anna Davis",
|
||||||
|
"rank": "commander",
|
||||||
|
"age": 27,
|
||||||
|
"specialization": "Communications",
|
||||||
|
"years_experience": 14,
|
||||||
|
"is_active": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"member_id": "CM032",
|
||||||
|
"name": "Elena Garcia",
|
||||||
|
"rank": "lieutenant",
|
||||||
|
"age": 42,
|
||||||
|
"specialization": "Science Officer",
|
||||||
|
"years_experience": 23,
|
||||||
|
"is_active": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"member_id": "CM033",
|
||||||
|
"name": "Anna Brown",
|
||||||
|
"rank": "officer",
|
||||||
|
"age": 55,
|
||||||
|
"specialization": "Engineering",
|
||||||
|
"years_experience": 30,
|
||||||
|
"is_active": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"member_id": "CM034",
|
||||||
|
"name": "Emma Smith",
|
||||||
|
"rank": "captain",
|
||||||
|
"age": 37,
|
||||||
|
"specialization": "Research",
|
||||||
|
"years_experience": 23,
|
||||||
|
"is_active": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"member_id": "CM035",
|
||||||
|
"name": "Sofia Smith",
|
||||||
|
"rank": "lieutenant",
|
||||||
|
"age": 53,
|
||||||
|
"specialization": "Security",
|
||||||
|
"years_experience": 30,
|
||||||
|
"is_active": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"member_id": "CM036",
|
||||||
|
"name": "Maria Hernandez",
|
||||||
|
"rank": "commander",
|
||||||
|
"age": 41,
|
||||||
|
"specialization": "Medical Officer",
|
||||||
|
"years_experience": 30,
|
||||||
|
"is_active": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"member_id": "CM037",
|
||||||
|
"name": "John Hernandez",
|
||||||
|
"rank": "officer",
|
||||||
|
"age": 42,
|
||||||
|
"specialization": "Science Officer",
|
||||||
|
"years_experience": 20,
|
||||||
|
"is_active": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"mission_status": "planned",
|
||||||
|
"budget_millions": 4984.6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"mission_id": "M2024_EUROPA",
|
||||||
|
"mission_name": "Saturn Rings Research Mission",
|
||||||
|
"destination": "Saturn Rings",
|
||||||
|
"launch_date": "2024-09-18T00:00:00",
|
||||||
|
"duration_days": 602,
|
||||||
|
"crew": [
|
||||||
|
{
|
||||||
|
"member_id": "CM041",
|
||||||
|
"name": "William Davis",
|
||||||
|
"rank": "captain",
|
||||||
|
"age": 35,
|
||||||
|
"specialization": "Medical Officer",
|
||||||
|
"years_experience": 14,
|
||||||
|
"is_active": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"member_id": "CM042",
|
||||||
|
"name": "Sarah Smith",
|
||||||
|
"rank": "captain",
|
||||||
|
"age": 55,
|
||||||
|
"specialization": "Research",
|
||||||
|
"years_experience": 30,
|
||||||
|
"is_active": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"member_id": "CM043",
|
||||||
|
"name": "Elena Garcia",
|
||||||
|
"rank": "commander",
|
||||||
|
"age": 55,
|
||||||
|
"specialization": "Research",
|
||||||
|
"years_experience": 30,
|
||||||
|
"is_active": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"member_id": "CM044",
|
||||||
|
"name": "Sofia Williams",
|
||||||
|
"rank": "officer",
|
||||||
|
"age": 30,
|
||||||
|
"specialization": "Systems Analysis",
|
||||||
|
"years_experience": 9,
|
||||||
|
"is_active": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"member_id": "CM045",
|
||||||
|
"name": "Sarah Jones",
|
||||||
|
"rank": "lieutenant",
|
||||||
|
"age": 25,
|
||||||
|
"specialization": "Maintenance",
|
||||||
|
"years_experience": 11,
|
||||||
|
"is_active": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"member_id": "CM046",
|
||||||
|
"name": "Lisa Rodriguez",
|
||||||
|
"rank": "officer",
|
||||||
|
"age": 30,
|
||||||
|
"specialization": "Life Support",
|
||||||
|
"years_experience": 12,
|
||||||
|
"is_active": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"member_id": "CM047",
|
||||||
|
"name": "Sarah Smith",
|
||||||
|
"rank": "cadet",
|
||||||
|
"age": 28,
|
||||||
|
"specialization": "Pilot",
|
||||||
|
"years_experience": 8,
|
||||||
|
"is_active": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"mission_status": "planned",
|
||||||
|
"budget_millions": 1092.6
|
||||||
|
}
|
||||||
|
]
|
||||||
313
09/generated_data/space_missions.py
Normal file
313
09/generated_data/space_missions.py
Normal file
@@ -0,0 +1,313 @@
|
|||||||
|
"""
|
||||||
|
Generated test data for space_missions
|
||||||
|
"""
|
||||||
|
|
||||||
|
SPACE_MISSIONS = [
|
||||||
|
{
|
||||||
|
'mission_id': 'M2024_TITAN',
|
||||||
|
'mission_name': 'Solar Observatory Research Mission',
|
||||||
|
'destination': 'Solar Observatory',
|
||||||
|
'launch_date': '2024-03-30T00:00:00',
|
||||||
|
'duration_days': 451,
|
||||||
|
'crew': [
|
||||||
|
{
|
||||||
|
'member_id': 'CM001',
|
||||||
|
'name': 'Sarah Williams',
|
||||||
|
'rank': 'captain',
|
||||||
|
'age': 43,
|
||||||
|
'specialization': 'Mission Command',
|
||||||
|
'years_experience': 19,
|
||||||
|
'is_active': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'member_id': 'CM002',
|
||||||
|
'name': 'James Hernandez',
|
||||||
|
'rank': 'captain',
|
||||||
|
'age': 43,
|
||||||
|
'specialization': 'Pilot',
|
||||||
|
'years_experience': 30,
|
||||||
|
'is_active': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'member_id': 'CM003',
|
||||||
|
'name': 'Anna Jones',
|
||||||
|
'rank': 'cadet',
|
||||||
|
'age': 35,
|
||||||
|
'specialization': 'Communications',
|
||||||
|
'years_experience': 15,
|
||||||
|
'is_active': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'member_id': 'CM004',
|
||||||
|
'name': 'David Smith',
|
||||||
|
'rank': 'commander',
|
||||||
|
'age': 27,
|
||||||
|
'specialization': 'Security',
|
||||||
|
'years_experience': 15,
|
||||||
|
'is_active': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'member_id': 'CM005',
|
||||||
|
'name': 'Maria Jones',
|
||||||
|
'rank': 'cadet',
|
||||||
|
'age': 55,
|
||||||
|
'specialization': 'Research',
|
||||||
|
'years_experience': 30,
|
||||||
|
'is_active': True
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'mission_status': 'planned',
|
||||||
|
'budget_millions': 2208.1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'mission_id': 'M2024_MARS',
|
||||||
|
'mission_name': 'Jupiter Orbit Colony Mission',
|
||||||
|
'destination': 'Jupiter Orbit',
|
||||||
|
'launch_date': '2024-10-01T00:00:00',
|
||||||
|
'duration_days': 1065,
|
||||||
|
'crew': [
|
||||||
|
{
|
||||||
|
'member_id': 'CM011',
|
||||||
|
'name': 'Emma Brown',
|
||||||
|
'rank': 'commander',
|
||||||
|
'age': 49,
|
||||||
|
'specialization': 'Mission Command',
|
||||||
|
'years_experience': 27,
|
||||||
|
'is_active': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'member_id': 'CM012',
|
||||||
|
'name': 'John Hernandez',
|
||||||
|
'rank': 'lieutenant',
|
||||||
|
'age': 36,
|
||||||
|
'specialization': 'Science Officer',
|
||||||
|
'years_experience': 22,
|
||||||
|
'is_active': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'member_id': 'CM013',
|
||||||
|
'name': 'Sofia Rodriguez',
|
||||||
|
'rank': 'commander',
|
||||||
|
'age': 29,
|
||||||
|
'specialization': 'Life Support',
|
||||||
|
'years_experience': 20,
|
||||||
|
'is_active': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'member_id': 'CM014',
|
||||||
|
'name': 'Sofia Lopez',
|
||||||
|
'rank': 'lieutenant',
|
||||||
|
'age': 44,
|
||||||
|
'specialization': 'Systems Analysis',
|
||||||
|
'years_experience': 25,
|
||||||
|
'is_active': True
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'mission_status': 'planned',
|
||||||
|
'budget_millions': 4626.0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'mission_id': 'M2024_EUROPA',
|
||||||
|
'mission_name': 'Europa Colony Mission',
|
||||||
|
'destination': 'Europa',
|
||||||
|
'launch_date': '2024-02-07T00:00:00',
|
||||||
|
'duration_days': 666,
|
||||||
|
'crew': [
|
||||||
|
{
|
||||||
|
'member_id': 'CM021',
|
||||||
|
'name': 'Lisa Garcia',
|
||||||
|
'rank': 'captain',
|
||||||
|
'age': 36,
|
||||||
|
'specialization': 'Medical Officer',
|
||||||
|
'years_experience': 12,
|
||||||
|
'is_active': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'member_id': 'CM022',
|
||||||
|
'name': 'John Garcia',
|
||||||
|
'rank': 'cadet',
|
||||||
|
'age': 46,
|
||||||
|
'specialization': 'Security',
|
||||||
|
'years_experience': 25,
|
||||||
|
'is_active': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'member_id': 'CM023',
|
||||||
|
'name': 'Michael Johnson',
|
||||||
|
'rank': 'officer',
|
||||||
|
'age': 54,
|
||||||
|
'specialization': 'Research',
|
||||||
|
'years_experience': 30,
|
||||||
|
'is_active': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'member_id': 'CM024',
|
||||||
|
'name': 'Sarah Rodriguez',
|
||||||
|
'rank': 'lieutenant',
|
||||||
|
'age': 54,
|
||||||
|
'specialization': 'Research',
|
||||||
|
'years_experience': 30,
|
||||||
|
'is_active': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'member_id': 'CM025',
|
||||||
|
'name': 'Maria Smith',
|
||||||
|
'rank': 'cadet',
|
||||||
|
'age': 38,
|
||||||
|
'specialization': 'Communications',
|
||||||
|
'years_experience': 15,
|
||||||
|
'is_active': True
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'mission_status': 'planned',
|
||||||
|
'budget_millions': 4976.0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'mission_id': 'M2024_LUNA',
|
||||||
|
'mission_name': 'Mars Colony Mission',
|
||||||
|
'destination': 'Mars',
|
||||||
|
'launch_date': '2024-06-13T00:00:00',
|
||||||
|
'duration_days': 222,
|
||||||
|
'crew': [
|
||||||
|
{
|
||||||
|
'member_id': 'CM031',
|
||||||
|
'name': 'Anna Davis',
|
||||||
|
'rank': 'commander',
|
||||||
|
'age': 27,
|
||||||
|
'specialization': 'Communications',
|
||||||
|
'years_experience': 14,
|
||||||
|
'is_active': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'member_id': 'CM032',
|
||||||
|
'name': 'Elena Garcia',
|
||||||
|
'rank': 'lieutenant',
|
||||||
|
'age': 42,
|
||||||
|
'specialization': 'Science Officer',
|
||||||
|
'years_experience': 23,
|
||||||
|
'is_active': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'member_id': 'CM033',
|
||||||
|
'name': 'Anna Brown',
|
||||||
|
'rank': 'officer',
|
||||||
|
'age': 55,
|
||||||
|
'specialization': 'Engineering',
|
||||||
|
'years_experience': 30,
|
||||||
|
'is_active': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'member_id': 'CM034',
|
||||||
|
'name': 'Emma Smith',
|
||||||
|
'rank': 'captain',
|
||||||
|
'age': 37,
|
||||||
|
'specialization': 'Research',
|
||||||
|
'years_experience': 23,
|
||||||
|
'is_active': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'member_id': 'CM035',
|
||||||
|
'name': 'Sofia Smith',
|
||||||
|
'rank': 'lieutenant',
|
||||||
|
'age': 53,
|
||||||
|
'specialization': 'Security',
|
||||||
|
'years_experience': 30,
|
||||||
|
'is_active': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'member_id': 'CM036',
|
||||||
|
'name': 'Maria Hernandez',
|
||||||
|
'rank': 'commander',
|
||||||
|
'age': 41,
|
||||||
|
'specialization': 'Medical Officer',
|
||||||
|
'years_experience': 30,
|
||||||
|
'is_active': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'member_id': 'CM037',
|
||||||
|
'name': 'John Hernandez',
|
||||||
|
'rank': 'officer',
|
||||||
|
'age': 42,
|
||||||
|
'specialization': 'Science Officer',
|
||||||
|
'years_experience': 20,
|
||||||
|
'is_active': True
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'mission_status': 'planned',
|
||||||
|
'budget_millions': 4984.6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'mission_id': 'M2024_EUROPA',
|
||||||
|
'mission_name': 'Saturn Rings Research Mission',
|
||||||
|
'destination': 'Saturn Rings',
|
||||||
|
'launch_date': '2024-09-18T00:00:00',
|
||||||
|
'duration_days': 602,
|
||||||
|
'crew': [
|
||||||
|
{
|
||||||
|
'member_id': 'CM041',
|
||||||
|
'name': 'William Davis',
|
||||||
|
'rank': 'captain',
|
||||||
|
'age': 35,
|
||||||
|
'specialization': 'Medical Officer',
|
||||||
|
'years_experience': 14,
|
||||||
|
'is_active': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'member_id': 'CM042',
|
||||||
|
'name': 'Sarah Smith',
|
||||||
|
'rank': 'captain',
|
||||||
|
'age': 55,
|
||||||
|
'specialization': 'Research',
|
||||||
|
'years_experience': 30,
|
||||||
|
'is_active': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'member_id': 'CM043',
|
||||||
|
'name': 'Elena Garcia',
|
||||||
|
'rank': 'commander',
|
||||||
|
'age': 55,
|
||||||
|
'specialization': 'Research',
|
||||||
|
'years_experience': 30,
|
||||||
|
'is_active': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'member_id': 'CM044',
|
||||||
|
'name': 'Sofia Williams',
|
||||||
|
'rank': 'officer',
|
||||||
|
'age': 30,
|
||||||
|
'specialization': 'Systems Analysis',
|
||||||
|
'years_experience': 9,
|
||||||
|
'is_active': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'member_id': 'CM045',
|
||||||
|
'name': 'Sarah Jones',
|
||||||
|
'rank': 'lieutenant',
|
||||||
|
'age': 25,
|
||||||
|
'specialization': 'Maintenance',
|
||||||
|
'years_experience': 11,
|
||||||
|
'is_active': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'member_id': 'CM046',
|
||||||
|
'name': 'Lisa Rodriguez',
|
||||||
|
'rank': 'officer',
|
||||||
|
'age': 30,
|
||||||
|
'specialization': 'Life Support',
|
||||||
|
'years_experience': 12,
|
||||||
|
'is_active': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'member_id': 'CM047',
|
||||||
|
'name': 'Sarah Smith',
|
||||||
|
'rank': 'cadet',
|
||||||
|
'age': 28,
|
||||||
|
'specialization': 'Pilot',
|
||||||
|
'years_experience': 8,
|
||||||
|
'is_active': True
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'mission_status': 'planned',
|
||||||
|
'budget_millions': 1092.6
|
||||||
|
}
|
||||||
|
]
|
||||||
11
09/generated_data/space_stations.csv
Normal file
11
09/generated_data/space_stations.csv
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
crew_size,is_operational,last_maintenance,name,notes,oxygen_level,power_level,station_id
|
||||||
|
6,True,2023-07-11T00:00:00,Titan Mining Outpost,,95.5,76.4,LGW125
|
||||||
|
3,False,2023-08-24T00:00:00,Deep Space Observatory,System diagnostics required,88.1,70.8,QCH189
|
||||||
|
11,True,2023-10-21T00:00:00,Europa Research Station,,91.4,82.0,ISS674
|
||||||
|
9,False,2023-10-06T00:00:00,Mars Orbital Platform,System diagnostics required,87.2,79.7,ISS877
|
||||||
|
4,False,2023-10-25T00:00:00,Deep Space Observatory,System diagnostics required,89.9,80.2,LGW194
|
||||||
|
11,False,2023-12-11T00:00:00,Solar Wind Monitor,System diagnostics required,98.1,73.6,ISS847
|
||||||
|
12,False,2023-07-15T00:00:00,Asteroid Belt Relay,System diagnostics required,86.0,75.5,QCH400
|
||||||
|
4,True,2023-09-25T00:00:00,Titan Mining Outpost,All systems nominal,97.3,94.4,ERS891
|
||||||
|
8,False,2023-07-10T00:00:00,Asteroid Belt Relay,System diagnostics required,88.8,76.0,ABR266
|
||||||
|
11,False,2023-09-25T00:00:00,Mars Orbital Platform,System diagnostics required,87.3,90.8,LGW723
|
||||||
|
102
09/generated_data/space_stations.json
Normal file
102
09/generated_data/space_stations.json
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"station_id": "LGW125",
|
||||||
|
"name": "Titan Mining Outpost",
|
||||||
|
"crew_size": 6,
|
||||||
|
"power_level": 76.4,
|
||||||
|
"oxygen_level": 95.5,
|
||||||
|
"last_maintenance": "2023-07-11T00:00:00",
|
||||||
|
"is_operational": true,
|
||||||
|
"notes": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"station_id": "QCH189",
|
||||||
|
"name": "Deep Space Observatory",
|
||||||
|
"crew_size": 3,
|
||||||
|
"power_level": 70.8,
|
||||||
|
"oxygen_level": 88.1,
|
||||||
|
"last_maintenance": "2023-08-24T00:00:00",
|
||||||
|
"is_operational": false,
|
||||||
|
"notes": "System diagnostics required"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"station_id": "ISS674",
|
||||||
|
"name": "Europa Research Station",
|
||||||
|
"crew_size": 11,
|
||||||
|
"power_level": 82.0,
|
||||||
|
"oxygen_level": 91.4,
|
||||||
|
"last_maintenance": "2023-10-21T00:00:00",
|
||||||
|
"is_operational": true,
|
||||||
|
"notes": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"station_id": "ISS877",
|
||||||
|
"name": "Mars Orbital Platform",
|
||||||
|
"crew_size": 9,
|
||||||
|
"power_level": 79.7,
|
||||||
|
"oxygen_level": 87.2,
|
||||||
|
"last_maintenance": "2023-10-06T00:00:00",
|
||||||
|
"is_operational": false,
|
||||||
|
"notes": "System diagnostics required"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"station_id": "LGW194",
|
||||||
|
"name": "Deep Space Observatory",
|
||||||
|
"crew_size": 4,
|
||||||
|
"power_level": 80.2,
|
||||||
|
"oxygen_level": 89.9,
|
||||||
|
"last_maintenance": "2023-10-25T00:00:00",
|
||||||
|
"is_operational": false,
|
||||||
|
"notes": "System diagnostics required"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"station_id": "ISS847",
|
||||||
|
"name": "Solar Wind Monitor",
|
||||||
|
"crew_size": 11,
|
||||||
|
"power_level": 73.6,
|
||||||
|
"oxygen_level": 98.1,
|
||||||
|
"last_maintenance": "2023-12-11T00:00:00",
|
||||||
|
"is_operational": false,
|
||||||
|
"notes": "System diagnostics required"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"station_id": "QCH400",
|
||||||
|
"name": "Asteroid Belt Relay",
|
||||||
|
"crew_size": 12,
|
||||||
|
"power_level": 75.5,
|
||||||
|
"oxygen_level": 86.0,
|
||||||
|
"last_maintenance": "2023-07-15T00:00:00",
|
||||||
|
"is_operational": false,
|
||||||
|
"notes": "System diagnostics required"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"station_id": "ERS891",
|
||||||
|
"name": "Titan Mining Outpost",
|
||||||
|
"crew_size": 4,
|
||||||
|
"power_level": 94.4,
|
||||||
|
"oxygen_level": 97.3,
|
||||||
|
"last_maintenance": "2023-09-25T00:00:00",
|
||||||
|
"is_operational": true,
|
||||||
|
"notes": "All systems nominal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"station_id": "ABR266",
|
||||||
|
"name": "Asteroid Belt Relay",
|
||||||
|
"crew_size": 8,
|
||||||
|
"power_level": 76.0,
|
||||||
|
"oxygen_level": 88.8,
|
||||||
|
"last_maintenance": "2023-07-10T00:00:00",
|
||||||
|
"is_operational": false,
|
||||||
|
"notes": "System diagnostics required"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"station_id": "LGW723",
|
||||||
|
"name": "Mars Orbital Platform",
|
||||||
|
"crew_size": 11,
|
||||||
|
"power_level": 90.8,
|
||||||
|
"oxygen_level": 87.3,
|
||||||
|
"last_maintenance": "2023-09-25T00:00:00",
|
||||||
|
"is_operational": false,
|
||||||
|
"notes": "System diagnostics required"
|
||||||
|
}
|
||||||
|
]
|
||||||
106
09/generated_data/space_stations.py
Normal file
106
09/generated_data/space_stations.py
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
"""
|
||||||
|
Generated test data for space_stations
|
||||||
|
"""
|
||||||
|
|
||||||
|
SPACE_STATIONS = [
|
||||||
|
{
|
||||||
|
'station_id': 'LGW125',
|
||||||
|
'name': 'Titan Mining Outpost',
|
||||||
|
'crew_size': 6,
|
||||||
|
'power_level': 76.4,
|
||||||
|
'oxygen_level': 95.5,
|
||||||
|
'last_maintenance': '2023-07-11T00:00:00',
|
||||||
|
'is_operational': True,
|
||||||
|
'notes': None
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'station_id': 'QCH189',
|
||||||
|
'name': 'Deep Space Observatory',
|
||||||
|
'crew_size': 3,
|
||||||
|
'power_level': 70.8,
|
||||||
|
'oxygen_level': 88.1,
|
||||||
|
'last_maintenance': '2023-08-24T00:00:00',
|
||||||
|
'is_operational': False,
|
||||||
|
'notes': 'System diagnostics required'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'station_id': 'ISS674',
|
||||||
|
'name': 'Europa Research Station',
|
||||||
|
'crew_size': 11,
|
||||||
|
'power_level': 82.0,
|
||||||
|
'oxygen_level': 91.4,
|
||||||
|
'last_maintenance': '2023-10-21T00:00:00',
|
||||||
|
'is_operational': True,
|
||||||
|
'notes': None
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'station_id': 'ISS877',
|
||||||
|
'name': 'Mars Orbital Platform',
|
||||||
|
'crew_size': 9,
|
||||||
|
'power_level': 79.7,
|
||||||
|
'oxygen_level': 87.2,
|
||||||
|
'last_maintenance': '2023-10-06T00:00:00',
|
||||||
|
'is_operational': False,
|
||||||
|
'notes': 'System diagnostics required'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'station_id': 'LGW194',
|
||||||
|
'name': 'Deep Space Observatory',
|
||||||
|
'crew_size': 4,
|
||||||
|
'power_level': 80.2,
|
||||||
|
'oxygen_level': 89.9,
|
||||||
|
'last_maintenance': '2023-10-25T00:00:00',
|
||||||
|
'is_operational': False,
|
||||||
|
'notes': 'System diagnostics required'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'station_id': 'ISS847',
|
||||||
|
'name': 'Solar Wind Monitor',
|
||||||
|
'crew_size': 11,
|
||||||
|
'power_level': 73.6,
|
||||||
|
'oxygen_level': 98.1,
|
||||||
|
'last_maintenance': '2023-12-11T00:00:00',
|
||||||
|
'is_operational': False,
|
||||||
|
'notes': 'System diagnostics required'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'station_id': 'QCH400',
|
||||||
|
'name': 'Asteroid Belt Relay',
|
||||||
|
'crew_size': 12,
|
||||||
|
'power_level': 75.5,
|
||||||
|
'oxygen_level': 86.0,
|
||||||
|
'last_maintenance': '2023-07-15T00:00:00',
|
||||||
|
'is_operational': False,
|
||||||
|
'notes': 'System diagnostics required'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'station_id': 'ERS891',
|
||||||
|
'name': 'Titan Mining Outpost',
|
||||||
|
'crew_size': 4,
|
||||||
|
'power_level': 94.4,
|
||||||
|
'oxygen_level': 97.3,
|
||||||
|
'last_maintenance': '2023-09-25T00:00:00',
|
||||||
|
'is_operational': True,
|
||||||
|
'notes': 'All systems nominal'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'station_id': 'ABR266',
|
||||||
|
'name': 'Asteroid Belt Relay',
|
||||||
|
'crew_size': 8,
|
||||||
|
'power_level': 76.0,
|
||||||
|
'oxygen_level': 88.8,
|
||||||
|
'last_maintenance': '2023-07-10T00:00:00',
|
||||||
|
'is_operational': False,
|
||||||
|
'notes': 'System diagnostics required'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'station_id': 'LGW723',
|
||||||
|
'name': 'Mars Orbital Platform',
|
||||||
|
'crew_size': 11,
|
||||||
|
'power_level': 90.8,
|
||||||
|
'oxygen_level': 87.3,
|
||||||
|
'last_maintenance': '2023-09-25T00:00:00',
|
||||||
|
'is_operational': False,
|
||||||
|
'notes': 'System diagnostics required'
|
||||||
|
}
|
||||||
|
]
|
||||||
14
10/ex0/lambda_spells.py
Normal file
14
10/ex0/lambda_spells.py
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
def artifact_sorter(artifacts: list[dict]) -> list[dict]:
|
||||||
|
return sorted(artifacts, key=lambda artifact: artifact["power"])
|
||||||
|
|
||||||
|
|
||||||
|
def power_filter(mages: list[dict], min_power: int) -> list[dict]:
|
||||||
|
return list(filter(lambda x: x["power"] >= min_power, mages))
|
||||||
|
|
||||||
|
|
||||||
|
def spell_transformer(spells: list[str]) -> list[str]:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def mage_stats(mages: list[dict]) -> dict:
|
||||||
|
pass
|
||||||
Reference in New Issue
Block a user