Compare commits

..

20 Commits

Author SHA1 Message Date
DarkPhoenix
57c2d37e3c Bump version 2026-01-13 11:42:28 +01:00
DarkPhoenix
5558cc8a51 Revert "Merge pull request #2706 from freeone3000/master"
This reverts commit 2201dde8ed, reversing
changes made to 3a324b9f9f.
2026-01-13 11:41:31 +01:00
DarkPhoenix
76e6dd86e1 Revert "Add new packages to linux build"
This reverts commit ec4a0743b8.
2026-01-13 11:30:58 +01:00
DarkPhoenix
83973dda73 Bump macos image version, p2 2026-01-11 21:11:07 +01:00
DarkPhoenix
e68530d08c Bump macos image version 2026-01-11 19:30:41 +01:00
DarkPhoenix
750ed8b6fa Bump version 2026-01-11 18:05:06 +01:00
Anton Vorobyov
8225dc8f49 Merge pull request #2675 from tsadler1988/contributing-suggested-changes
CONTRIBUTING.md suggested changes
2026-01-11 20:24:40 +04:00
DarkPhoenix
ec4a0743b8 Add new packages to linux build 2026-01-11 17:19:22 +01:00
Anton Vorobyov
2201dde8ed Merge pull request #2706 from freeone3000/master
fix: Fixed clipboard issues on Wayland, using pyclip instead of wx
2026-01-11 20:12:32 +04:00
Anton Vorobyov
3a324b9f9f Merge pull request #2713 from alexjurkiewicz/tox-py-minver
Update minimum Python version in tox.ini
2026-01-11 20:11:23 +04:00
DarkPhoenix
11dcc31554 Update effects 2026-01-11 15:49:34 +01:00
DarkPhoenix
074048890c Update static data 2026-01-11 15:17:59 +01:00
Alex Jurkiewicz
4ac1627b33 Update minimum Python version in tox.ini
To match the minimum version specified in CONTRIBUTING.md.
2026-01-02 09:04:43 +08:00
Jasmine Moore
84f532284e fix: remove debug statement 2025-12-17 12:31:05 -05:00
Jasmine Moore
ccbe88d3bf fix: Fixed clipboard issues on Wayland, using pyclip instead of wx 2025-12-17 12:26:36 -05:00
Tom Sadler
8afb2139b3 venv activation for PowerShell (running tests) 2025-05-23 20:06:43 +01:00
Tom Sadler
c7412a5174 Add PyfaDEV path for translations and database scripts 2025-05-23 20:04:57 +01:00
Tom Sadler
2494ad8cef venv activation for PowerShell 2025-05-23 20:02:54 +01:00
Tom Sadler
a2f17e3205 Add note on C compiler 2025-05-23 19:53:24 +01:00
Tom Sadler
f4d50792ea Add note on Python versions 2025-05-23 19:39:49 +01:00
45 changed files with 2927 additions and 5256 deletions

View File

@@ -1,7 +1,7 @@
image:
- Ubuntu2204
- Visual Studio 2022
- macos-catalina
- macos-monterey
for:
-
matrix:
@@ -147,7 +147,7 @@ for:
-
matrix:
only:
- image: macos-catalina
- image: macos-monterey
environment:
APPVEYOR_SSH_KEY: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDJDW/+oYNGOiPvwuwAL9tc/LQgg58aosIVpMYfepQZ20V+VZnHpZh8IRDA8Jo5xht19p2PksA+hFgqA0kpKtrSkuiWdE8rATQItfk4gf7yB0yGasJGGQZYazy9k/9XtmYkq2HHOOeEqdxvrICddJQ88MLCLT9lJENSUP/YS/yGcjZFXVxE11pTeIcqlCRU+3eYa1v7BeNvXIKNhZoK5orXWrtuH3cy8jrSns/u70aYfJ6B2jA8CnWnDbuvpeQtEY61SQqlKUsSArNa8NAsXj41wr3Ar9gAG9330w7EMTqlutk8HZO35uHI0q5qinUhaQYufPPrVkb2L/N+ZCfu0fnh appveyor"
cache:

2
.gitattributes vendored
View File

@@ -33,4 +33,4 @@ pyfa.py text eol=lf
*.jpg binary
*.icns binary
*.ico binary
*.dll filter=lfs diff=lfs merge=lfs -text

3
.gitignore vendored
View File

@@ -126,5 +126,4 @@ gitversion
/locale/progress.json
# vscode settings
.vscode
eve.db
.vscode

3
.gitmodules vendored
View File

@@ -1,3 +0,0 @@
[submodule "Pyfa-Mod"]
path = Pyfa-Mod
url = https://github.com/Eivonz/Pyfa-Mod

View File

@@ -2,7 +2,7 @@
## Requirements
- Python 3.11
- Python 3.11 (later versions may not work)
- Git CLI installed
- Python, pip and git are all available as command-line commands (add to the path if needed)
@@ -26,6 +26,7 @@ Activate the virtual environment
```
For cmd.exe: PyfaEnv\scripts\activate.bat
For PowerShell: PyfaEnv\Scripts\Activate.ps1
For bash: source <venv>/Scripts/activate
```
> For other OS check [Python documentation](https://docs.python.org/3/library/venv.html)
@@ -36,6 +37,8 @@ pip install -r PyfaDEV\requirements.txt
```
> For some Linux distributions, you may need to install separate wxPython bindings, such as `python-matplotlib-wx`
> You may need to [install a C compiler](https://mesonbuild.com/SimpleStart.html#installing-a-compiler-toolchain)
Check that the libs from *requirements.txt* are installed
```
pip list
@@ -43,8 +46,8 @@ pip list
Build translations and database:
```
python scripts\compile_lang.py
python db_update.py
python PyfaDEV\scripts\compile_lang.py
python PyfaDEV\db_update.py
```
Test that the project is starting properly
@@ -88,6 +91,7 @@ Check that the project is starting properly.
Switch to the proper virtual environment
```
For cmd.exe: PyfaEnv\scripts\activate.bat
For PowerShell: PyfaEnv\Scripts\Activate.ps1
For bash: source <venv>/Scripts/activate
```

View File

@@ -1,30 +0,0 @@
#!/bin/bash
set -e
echo "Building pyfa binary..."
# Ensure we're using the local venv
if [ ! -d ".venv" ]; then
echo "Creating virtual environment..."
uv venv
fi
# Install dependencies
echo "Installing dependencies..."
uv pip install -r requirements.txt
uv pip install pyinstaller
# Clean previous builds
echo "Cleaning previous builds..."
rm -rf build dist
# Build the binary
echo "Building binary with PyInstaller..."
uv run pyinstaller pyfa.spec
# cp oleacc* dist/pyfa/
echo ""
echo "Build complete! Binary is located at: dist/pyfa/pyfa.exe"
echo "You can run it with: dist/pyfa/pyfa.exe"

View File

@@ -1333,10 +1333,11 @@ class Effect446(BaseEffect):
Implants named like: Capsuleer Defense Augmentation Chip (3 of 3)
Implants named like: Festival only 'Rock' SH Dose (4 of 4)
Implants named like: Halcyon G Booster (5 of 5)
Implants named like: Nirvana Booster (5 of 5)
Implants named like: Serenity Limited 'Hardshell' Dose (3 of 3)
Implants named like: Wightstorm Nirvana Booster (4 of 4)
Implants named like: Zainou 'Gnome' Shield Management SM (6 of 6)
Modules named like: Core Defense Field Extender (8 of 8)
Implant: AIR Nirvana Booster II
Implant: Genolution Core Augmentation CA-3
Implant: Sansha Modified 'Gnome' Implant
Skill: Shield Management
@@ -1358,11 +1359,10 @@ class Effect485(BaseEffect):
Implants named like: Halcyon G Booster (5 of 5)
Implants named like: Halcyon R Booster (5 of 5)
Implants named like: Inherent Implants 'Squire' Capacitor Systems Operation EO (6 of 6)
Implants named like: Wightstorm Rapture Booster (4 of 4)
Implants named like: Rapture Booster (5 of 5)
Implants named like: grade Rapture (15 of 18)
Modules named like: Capacitor Control Circuit (8 of 8)
Implant: AIR Overclocker Booster III
Implant: AIR Rapture Booster II
Implant: Basic Capsuleer Engineering Augmentation Chip
Implant: Genolution Core Augmentation CA-2
Implant: Quafe Zero Green Apple
@@ -2604,7 +2604,6 @@ class Effect891(BaseEffect):
Used by:
Variations of ship: Raven (3 of 4)
Module: Anhinga Tertiary Mode
"""
type = 'passive'
@@ -2628,7 +2627,6 @@ class Effect892(BaseEffect):
Used by:
Variations of ship: Raven (3 of 4)
Module: Anhinga Tertiary Mode
"""
type = 'passive'
@@ -3300,7 +3298,6 @@ class Effect1024(BaseEffect):
shipMissileHeavyVelocityBonusCC2
Used by:
Module: Anhinga Tertiary Mode
Ship: Caracal
Ship: Osprey Navy Issue
"""
@@ -3927,7 +3924,6 @@ class Effect1230(BaseEffect):
shipMissileVelocityPirateFactionFrigate
Used by:
Module: Anhinga Primary Mode
Ship: Barghest
Ship: Garmur
Ship: Laelaps
@@ -5679,7 +5675,6 @@ class Effect1885(BaseEffect):
shipCruiseLauncherROFBonus2CB
Used by:
Modules named like: Anhinga Mode (3 of 3)
Ship: Raven
Ship: Raven State Issue
"""
@@ -5707,7 +5702,6 @@ class Effect1886(BaseEffect):
shipSiegeLauncherROFBonus2CB
Used by:
Modules named like: Anhinga Mode (3 of 3)
Ship: Raven
Ship: Raven State Issue
"""
@@ -16831,6 +16825,7 @@ class Effect4990(BaseEffect):
Used by:
Ship: Hematos
Ship: Impairor
Ship: Succubus
"""
type = 'passive'
@@ -18227,7 +18222,6 @@ class Effect5213(BaseEffect):
shipRocketMaxVelocityBonusRookie
Used by:
Module: Skua Sharpshooter Mode
Ship: Taipan
"""
@@ -18246,7 +18240,6 @@ class Effect5214(BaseEffect):
shipLightMissileMaxVelocityBonusRookie
Used by:
Module: Skua Sharpshooter Mode
Ship: Taipan
"""
@@ -20399,7 +20392,6 @@ class Effect5468(BaseEffect):
shipBonusAgilityCI2
Used by:
Module: Anhinga Tertiary Mode
Ship: Badger
"""
@@ -21155,7 +21147,6 @@ class Effect5618(BaseEffect):
shipBonusRHMLROF2CB
Used by:
Modules named like: Anhinga Mode (3 of 3)
Ship: Raven
Ship: Widow
"""
@@ -22464,8 +22455,6 @@ class Effect5867(BaseEffect):
shipBonusMissileExplosionDelayPirateFaction2
Used by:
Module: Anhinga Primary Mode
Module: Anhinga Secondary Mode
Ship: Barghest
Ship: Garmur
Ship: Laelaps
@@ -23525,6 +23514,7 @@ class Effect6016(BaseEffect):
Used by:
Modules named like: Propulsion Mode (5 of 5)
Module: Anhinga Tertiary Mode
"""
type = 'passive'
@@ -42732,3 +42722,115 @@ class Effect12790(BaseEffect):
fit.modules.filteredChargeBoost(
lambda mod: mod.charge.requiresSkill('Torpedoes') or mod.charge.requiresSkill('Cruise Missiles'),
'aoeVelocity', ship.getModifiedItemAttr('shipBonusCBC2'), skill='Caldari Battlecruiser', **kwargs)
class Effect12794(BaseEffect):
"""
shipRocketMaxVelocityBonusPostDivSkua
Used by:
Module: Skua Sharpshooter Mode
"""
type = 'passive'
@staticmethod
def handler(fit, module, context, projectionRange, **kwargs):
fit.modules.filteredChargeMultiply(
lambda mod: mod.charge.requiresSkill('Rockets'),
'maxVelocity', 1 / module.getModifiedItemAttr('modeRocketMissileMaxVelocityBonusPostDivSkua'),
stackingPenalties=True, penaltyGroup='postDiv', **kwargs)
class Effect12795(BaseEffect):
"""
shipLightMissileMaxVelocityBonusPostDivSkua
Used by:
Module: Skua Sharpshooter Mode
"""
type = 'passive'
@staticmethod
def handler(fit, module, context, projectionRange, **kwargs):
fit.modules.filteredChargeMultiply(
lambda mod: mod.charge.requiresSkill('Light Missiles'),
'maxVelocity', 1 / module.getModifiedItemAttr('modeLightMissileMaxVelocityBonusPostDivSkua'),
stackingPenalties=True, penaltyGroup='postDiv', **kwargs)
class Effect12796(BaseEffect):
"""
shipModeMissileFlightTimePostDiv
Used by:
Module: Anhinga Primary Mode
Module: Anhinga Secondary Mode
"""
type = 'passive'
@staticmethod
def handler(fit, ship, context, projectionRange, **kwargs):
fit.modules.filteredChargeMultiply(
lambda mod: mod.charge.requiresSkill('Missile Launcher Operation'),
'explosionDelay', 1 / ship.getModifiedItemAttr('modeAnhingaMissileFlightTimePostDiv'),
stackingPenalties=True, penaltyGroup='postDiv', **kwargs)
class Effect12798(BaseEffect):
"""
shipModeMissileVelocityPostDiv
Used by:
Module: Anhinga Primary Mode
Module: Anhinga Tertiary Mode
"""
type = 'passive'
@staticmethod
def handler(fit, module, context, projectionRange, **kwargs):
fit.modules.filteredChargeMultiply(
lambda mod: mod.charge.requiresSkill('Missile Launcher Operation'),
'maxVelocity', 1 / module.getModifiedItemAttr('modeAnhingaMissileMaxVelocityPostDiv'),
stackingPenalties=True, penaltyGroup='postDiv', **kwargs)
class Effect12799(BaseEffect):
"""
shipModeAnhingaCruiseLauncherTorpedoLauncherRapidHeavyLauncherROFPostDiv
Used by:
Modules named like: Anhinga Mode (3 of 3)
"""
type = 'passive'
@staticmethod
def handler(fit, ship, context, projectionRange, **kwargs):
fit.modules.filteredItemMultiply(
lambda mod: mod.item.group.name in (
'Missile Launcher Rapid Heavy',
'Missile Launcher Cruise',
'Missile Launcher Torpedo'),
'speed', 1 / ship.getModifiedItemAttr('modeAnhingaCruiseLauncherTorpedoLauncherRapidHeavyLauncherROFPostDiv'),
stackingPenalties=True, penaltyGroup='postDiv',**kwargs)
class Effect12802(BaseEffect):
"""
MutatedMiningDroneOperationMiningAmountBonusPostPercentMiningDroneAmountPercentChar
Used by:
Skill: Mutated Drone Specialization
"""
type = 'passive'
@staticmethod
def handler(fit, src, context, projectionRange, **kwargs):
fit.drones.filteredItemBoost(
lambda mod: mod.item.requiresSkill('Mutated Drone Specialization'), 'miningAmount',
src.getModifiedItemAttr('miningAmountBonus') * src.level, **kwargs)

View File

@@ -332,78 +332,3 @@ class Distance2TpStrGetter(SmoothPointGetter):
strMult = calculateMultiplier(strMults)
strength = (strMult - 1) * 100
return strength
class Distance2JamChanceGetter(SmoothPointGetter):
_baseResolution = 50
_extraDepth = 2
ECM_ATTRS_GENERAL = ('scanGravimetricStrengthBonus', 'scanLadarStrengthBonus', 'scanMagnetometricStrengthBonus', 'scanRadarStrengthBonus')
ECM_ATTRS_FIGHTERS = ('fighterAbilityECMStrengthGravimetric', 'fighterAbilityECMStrengthLadar', 'fighterAbilityECMStrengthMagnetometric', 'fighterAbilityECMStrengthRadar')
SCAN_TYPES = ('Gravimetric', 'Ladar', 'Magnetometric', 'Radar')
def _getCommonData(self, miscParams, src, tgt):
ecms = []
for mod in src.item.activeModulesIter():
for effectName in ('remoteECMFalloff', 'structureModuleEffectECM'):
if effectName in mod.item.effects:
ecms.append((
tuple(mod.getModifiedItemAttr(a) or 0 for a in self.ECM_ATTRS_GENERAL),
mod.maxRange or 0, mod.falloff or 0, True, False))
if 'doomsdayAOEECM' in mod.item.effects:
ecms.append((
tuple(mod.getModifiedItemAttr(a) or 0 for a in self.ECM_ATTRS_GENERAL),
max(0, (mod.maxRange or 0) + mod.getModifiedItemAttr('doomsdayAOERange')),
mod.falloff or 0, False, False))
for drone in src.item.activeDronesIter():
if 'entityECMFalloff' in drone.item.effects:
ecms.extend(drone.amountActive * ((
tuple(drone.getModifiedItemAttr(a) or 0 for a in self.ECM_ATTRS_GENERAL),
math.inf, 0, True, True),))
for fighter, ability in src.item.activeFighterAbilityIter():
if ability.effect.name == 'fighterAbilityECM':
ecms.append((
tuple(fighter.getModifiedItemAttr(a) or 0 for a in self.ECM_ATTRS_FIGHTERS),
math.inf, 0, True, False))
# Determine target's strongest sensor type if target is available
targetScanTypeIndex = None
if tgt is not None:
maxStr = -1
for i, scanType in enumerate(self.SCAN_TYPES):
currStr = tgt.item.ship.getModifiedItemAttr('scan%sStrength' % scanType) or 0
if currStr > maxStr:
maxStr = currStr
targetScanTypeIndex = i
return {'ecms': ecms, 'targetScanTypeIndex': targetScanTypeIndex}
def _calculatePoint(self, x, miscParams, src, tgt, commonData):
distance = x
inLockRange = checkLockRange(src=src, distance=distance)
inDroneRange = checkDroneControlRange(src=src, distance=distance)
jamStrengths = []
targetScanTypeIndex = commonData['targetScanTypeIndex']
for strengths, optimal, falloff, needsLock, needsDcr in commonData['ecms']:
if (needsLock and not inLockRange) or (needsDcr and not inDroneRange):
continue
rangeFactor = calculateRangeFactor(srcOptimalRange=optimal, srcFalloffRange=falloff, distance=distance)
# Use the strength matching the target's sensor type
if targetScanTypeIndex is not None and targetScanTypeIndex < len(strengths):
strength = strengths[targetScanTypeIndex]
effectiveStrength = strength * rangeFactor
if effectiveStrength > 0:
jamStrengths.append(effectiveStrength)
if not jamStrengths:
return 0
# Get sensor strength from target
if tgt is None:
return 0
sensorStrength = max([tgt.item.ship.getModifiedItemAttr('scan%sStrength' % scanType)
for scanType in self.SCAN_TYPES]) or 0
if sensorStrength <= 0:
return 100 # If target has no sensor strength, 100% jam chance
# Calculate jam chance: 1 - (1 - (ecmStrength / sensorStrength)) ^ numJammers
retainLockChance = 1
for jamStrength in jamStrengths:
retainLockChance *= 1 - min(1, jamStrength / sensorStrength)
return (1 - retainLockChance) * 100

View File

@@ -21,8 +21,8 @@
import wx
from graphs.data.base import FitGraph, Input, XDef, YDef
from .getter import (Distance2DampStrLockRangeGetter, Distance2EcmStrMaxGetter, Distance2GdStrRangeGetter, Distance2JamChanceGetter, Distance2NeutingStrGetter,
Distance2TdStrOptimalGetter, Distance2TpStrGetter, Distance2WebbingStrGetter)
from .getter import (Distance2DampStrLockRangeGetter, Distance2EcmStrMaxGetter, Distance2GdStrRangeGetter, Distance2NeutingStrGetter, Distance2TdStrOptimalGetter,
Distance2TpStrGetter, Distance2WebbingStrGetter)
_t = wx.GetTranslation
@@ -31,13 +31,11 @@ class FitEwarStatsGraph(FitGraph):
# UI stuff
internalName = 'ewarStatsGraph'
name = _t('Electronic Warfare Stats')
hasTargets = True
xDefs = [XDef(handle='distance', unit='km', label=_t('Distance'), mainInput=('distance', 'km'))]
yDefs = [
YDef(handle='neutStr', unit=None, label=_t('Cap neutralized per second'), selectorLabel=_t('Neuts: cap per second')),
YDef(handle='webStr', unit='%', label=_t('Speed reduction'), selectorLabel=_t('Webs: speed reduction')),
YDef(handle='ecmStrMax', unit=None, label=_t('Combined ECM strength'), selectorLabel=_t('ECM: combined strength')),
YDef(handle='jamChance', unit='%', label=_t('Jam chance'), selectorLabel=_t('ECM: jam chance')),
YDef(handle='dampStrLockRange', unit='%', label=_t('Lock range reduction'), selectorLabel=_t('Damps: lock range reduction')),
YDef(handle='tdStrOptimal', unit='%', label=_t('Turret optimal range reduction'), selectorLabel=_t('TDs: turret optimal range reduction')),
YDef(handle='gdStrRange', unit='%', label=_t('Missile flight range reduction'), selectorLabel=_t('GDs: missile flight range reduction')),
@@ -55,7 +53,6 @@ class FitEwarStatsGraph(FitGraph):
('distance', 'neutStr'): Distance2NeutingStrGetter,
('distance', 'webStr'): Distance2WebbingStrGetter,
('distance', 'ecmStrMax'): Distance2EcmStrMaxGetter,
('distance', 'jamChance'): Distance2JamChanceGetter,
('distance', 'dampStrLockRange'): Distance2DampStrLockRangeGetter,
('distance', 'tdStrOptimal'): Distance2TdStrOptimalGetter,
('distance', 'gdStrRange'): Distance2GdStrRangeGetter,

View File

@@ -159,24 +159,11 @@ class CargoView(d.Display):
else:
dstCargoItemID = None
modifiers = wx.GetMouseState().GetModifiers()
isCopy = modifiers == wx.MOD_CONTROL
isBatch = modifiers == wx.MOD_SHIFT
if isBatch:
self.mainFrame.command.Submit(
cmd.GuiBatchLocalModuleToCargoCommand(
fitID=self.mainFrame.getActiveFit(), modPosition=modIdx, copy=isCopy
)
)
else:
self.mainFrame.command.Submit(
cmd.GuiLocalModuleToCargoCommand(
fitID=self.mainFrame.getActiveFit(),
modPosition=modIdx,
cargoItemID=dstCargoItemID,
copy=isCopy,
)
)
self.mainFrame.command.Submit(cmd.GuiLocalModuleToCargoCommand(
fitID=self.mainFrame.getActiveFit(),
modPosition=modIdx,
cargoItemID=dstCargoItemID,
copy=wx.GetMouseState().GetModifiers() == wx.MOD_CONTROL))
def fitChanged(self, event):
event.Skip()

View File

@@ -18,7 +18,6 @@ from gui.builtinContextMenus import resistMode
from gui.builtinContextMenus.targetProfile import editor
# Item info
from gui.builtinContextMenus import itemStats
from gui.builtinContextMenus import fitDiff
from gui.builtinContextMenus import itemMarketJump
from gui.builtinContextMenus import fitSystemSecurity # Not really an item info but want to keep it here
from gui.builtinContextMenus import fitPilotSecurity # Not really an item info but want to keep it here

View File

@@ -1,48 +0,0 @@
# =============================================================================
# Copyright (C) 2025
#
# This file is part of pyfa.
#
# pyfa is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# pyfa is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
import gui.mainFrame
from gui.contextMenu import ContextMenuSingle
_t = wx.GetTranslation
class FitDiff(ContextMenuSingle):
def __init__(self):
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def display(self, callingWindow, srcContext, mainItem):
# Only show for fittingShip context (right-click on ship)
return srcContext == "fittingShip"
def getText(self, callingWindow, itmContext, mainItem):
return _t("Fit Diff...")
def activate(self, callingWindow, fullContext, mainItem, i):
fitID = self.mainFrame.getActiveFit()
if fitID is not None:
from gui.fitDiffFrame import FitDiffFrame
FitDiffFrame(self.mainFrame, fitID)
FitDiff.register()

View File

@@ -79,7 +79,7 @@ class ChangeAffectingSkills(ContextMenuSingle):
label = _t("Level %s") % i
id = ContextMenuSingle.nextID()
self.skillIds[id] = (skill, i, False) # False = not "up" for individual skills
self.skillIds[id] = (skill, i)
menuItem = wx.MenuItem(rootMenu, id, label, kind=wx.ITEM_RADIO)
rootMenu.Bind(wx.EVT_MENU, self.handleSkillChange, menuItem)
return menuItem
@@ -89,40 +89,6 @@ class ChangeAffectingSkills(ContextMenuSingle):
self.skillIds = {}
sub = wx.Menu()
# When rootMenu is None (direct menu access), use sub for binding on Windows
bindMenu = rootMenu if (rootMenu is not None and msw) else (sub if msw else None)
# Add "All" entry
allItem = wx.MenuItem(sub, ContextMenuSingle.nextID(), _t("All"))
grandSubAll = wx.Menu()
allItem.SetSubMenu(grandSubAll)
# For "All", only show levels 1-5 (not "Not Learned")
for i in range(1, 6):
id = ContextMenuSingle.nextID()
self.skillIds[id] = (None, i, False) # None indicates "All" was selected, False = not "up"
label = _t("Level %s") % i
menuItem = wx.MenuItem(bindMenu if bindMenu else grandSubAll, id, label, kind=wx.ITEM_RADIO)
grandSubAll.Bind(wx.EVT_MENU, self.handleSkillChange, menuItem)
grandSubAll.Append(menuItem)
# Add separator
grandSubAll.AppendSeparator()
# Add "Up Level 1..5" entries
for i in range(1, 6):
id = ContextMenuSingle.nextID()
self.skillIds[id] = (None, i, True) # None indicates "All" was selected, True = "up" only
label = _t("Up Level %s") % i
menuItem = wx.MenuItem(bindMenu if bindMenu else grandSubAll, id, label, kind=wx.ITEM_RADIO)
grandSubAll.Bind(wx.EVT_MENU, self.handleSkillChange, menuItem)
grandSubAll.Append(menuItem)
sub.Append(allItem)
# Add separator
sub.AppendSeparator()
for skill in self.skills:
skillItem = wx.MenuItem(sub, ContextMenuSingle.nextID(), skill.item.name)
grandSub = wx.Menu()
@@ -133,7 +99,7 @@ class ChangeAffectingSkills(ContextMenuSingle):
skillItem.SetBitmap(bitmap)
for i in range(-1, 6):
levelItem = self.addSkill(bindMenu if bindMenu else grandSub, skill, i)
levelItem = self.addSkill(rootMenu if msw else grandSub, skill, i)
grandSub.Append(levelItem)
if (not skill.learned and i == -1) or (skill.learned and skill.level == i):
levelItem.Check(True)
@@ -142,24 +108,9 @@ class ChangeAffectingSkills(ContextMenuSingle):
return sub
def handleSkillChange(self, event):
skill, level, up = self.skillIds[event.Id]
if skill is None: # "All" was selected
for s in self.skills:
if up:
# Only increase skill if it's below the target level
if not s.learned or s.level < level:
self.sChar.changeLevel(self.charID, s.item.ID, level)
else:
self.sChar.changeLevel(self.charID, s.item.ID, level)
else:
if up:
# Only increase skill if it's below the target level
if not skill.learned or skill.level < level:
self.sChar.changeLevel(self.charID, skill.item.ID, level)
else:
self.sChar.changeLevel(self.charID, skill.item.ID, level)
skill, level = self.skillIds[event.Id]
self.sChar.changeLevel(self.charID, skill.item.ID, level)
fitID = self.mainFrame.getActiveFit()
self.sFit.changeChar(fitID, self.charID)

View File

@@ -9,46 +9,6 @@ from gui.utils.numberFormatter import formatAmount
_t = wx.GetTranslation
# Mapping of repair/transfer amount attributes to their duration attribute and display name
PER_SECOND_ATTRIBUTES = {
"armorDamageAmount": {
"durationAttr": "duration",
"displayName": "Armor Hitpoints Repaired per second",
"unit": "HP/s"
},
"shieldBonus": {
"durationAttr": "duration",
"displayName": "Shield Hitpoints Repaired per second",
"unit": "HP/s"
},
"powerTransferAmount": {
"durationAttr": "duration",
"displayName": "Capacitor Transferred per second",
"unit": "GJ/s"
}
}
class PerSecondAttributeInfo:
"""Helper class to store info about computed per-second attributes"""
def __init__(self, displayName, unit):
self.displayName = displayName
self.unit = PerSecondUnit(unit)
class PerSecondUnit:
"""Helper class to mimic the Unit class for per-second attributes"""
def __init__(self, displayName):
self.displayName = displayName
self.name = ""
class PerSecondAttributeValue:
"""Helper class to store computed per-second attribute values"""
def __init__(self, value):
self.value = value
self.info = None # Will be set when adding to attrs
def defaultSort(item):
return (item.metaLevel or 0, item.name)
@@ -76,12 +36,8 @@ class ItemCompare(wx.Panel):
self.item = item
self.items = sorted(items, key=defaultSort)
self.attrs = {}
self.computedAttrs = {} # Store computed per-second attributes
self.HighlightOn = wx.Colour(255, 255, 0, wx.ALPHA_OPAQUE)
self.highlightedNames = []
self.bangBuckColumn = None # Store the column selected for bang/buck calculation
self.bangBuckColumnName = None # Store the display name of the selected column
self.columnHighlightColour = wx.Colour(173, 216, 230, wx.ALPHA_OPAQUE) # Light blue for column highlight
# get a dict of attrName: attrInfo of all unique attributes across all items
for item in self.items:
@@ -89,66 +45,23 @@ class ItemCompare(wx.Panel):
if item.attributes[attr].info.displayName:
self.attrs[attr] = item.attributes[attr].info
# Compute per-second attributes for items that have both the amount and duration
for perSecondKey, config in PER_SECOND_ATTRIBUTES.items():
amountAttr = perSecondKey
durationAttr = config["durationAttr"]
perSecondAttrName = f"{perSecondKey}_per_second"
# Check if any item has both attributes
hasPerSecondAttr = False
for item in self.items:
if amountAttr in item.attributes and durationAttr in item.attributes:
hasPerSecondAttr = True
break
if hasPerSecondAttr:
# Add the per-second attribute info to attrs
perSecondInfo = PerSecondAttributeInfo(config["displayName"], config["unit"])
self.attrs[perSecondAttrName] = perSecondInfo
self.computedAttrs[perSecondAttrName] = {
"amountAttr": amountAttr,
"durationAttr": durationAttr
}
# Process attributes for items and find ones that differ
for attr in list(self.attrs.keys()):
value = None
for item in self.items:
# Check if this is a computed attribute
if attr in self.computedAttrs:
computed = self.computedAttrs[attr]
amountAttr = computed["amountAttr"]
durationAttr = computed["durationAttr"]
# we can automatically break here if this item doesn't have the attribute,
# as that means at least one item did
if attr not in item.attributes:
break
# Item needs both attributes to compute per-second value
if amountAttr not in item.attributes or durationAttr not in item.attributes:
break
# this is the first attribute for the item set, set the initial value
if value is None:
value = item.attributes[attr].value
continue
# Calculate per-second value
amountValue = item.attributes[amountAttr].value
durationValue = item.attributes[durationAttr].value
# Duration is in milliseconds, convert to seconds
perSecondValue = amountValue / (durationValue / 1000.0) if durationValue > 0 else 0
if value is None:
value = perSecondValue
continue
if perSecondValue != value:
break
else:
# Regular attribute handling
if attr not in item.attributes:
break
if value is None:
value = item.attributes[attr].value
continue
if item.attributes[attr].value != value:
break
if attr not in item.attributes or item.attributes[attr].value != value:
break
else:
# attribute values were all the same, delete
del self.attrs[attr]
@@ -176,7 +89,6 @@ class ItemCompare(wx.Panel):
self.toggleViewBtn.Bind(wx.EVT_TOGGLEBUTTON, self.ToggleViewMode)
self.Bind(wx.EVT_LIST_COL_CLICK, self.SortCompareCols)
self.Bind(wx.EVT_LIST_COL_RIGHT_CLICK, self.OnColumnRightClick)
self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.HighlightRow)
@@ -193,23 +105,6 @@ class ItemCompare(wx.Panel):
self.Thaw()
event.Skip()
def OnColumnRightClick(self, event):
column = event.GetColumn()
# Column 0 is "Item", column len(self.attrs) + 1 is "Price", len(self.attrs) + 2 is "Buck/bang"
# Only allow selecting attribute columns (1 to len(self.attrs))
if 1 <= column <= len(self.attrs):
# If clicking the same column, deselect it
if self.bangBuckColumn == column:
self.bangBuckColumn = None
self.bangBuckColumnName = None
else:
self.bangBuckColumn = column
# Get the display name of the selected column
attr_key = list(self.attrs.keys())[column - 1]
self.bangBuckColumnName = self.attrs[attr_key].displayName if self.attrs[attr_key].displayName else attr_key
self.UpdateList()
event.Skip()
def SortCompareCols(self, event):
self.Freeze()
self.paramList.ClearAll()
@@ -253,32 +148,12 @@ class ItemCompare(wx.Panel):
# Remember to reduce by 1, because the attrs array
# starts at 0 while the list has the item name as column 0.
attr = str(list(self.attrs.keys())[sort - 1])
# Handle computed attributes for sorting
if attr in self.computedAttrs:
computed = self.computedAttrs[attr]
amountAttr = computed["amountAttr"]
durationAttr = computed["durationAttr"]
func = lambda _val: (_val.attributes[amountAttr].value / (_val.attributes[durationAttr].value / 1000.0)) if (amountAttr in _val.attributes and durationAttr in _val.attributes and _val.attributes[durationAttr].value > 0) else 0.0
else:
func = lambda _val: _val.attributes[attr].value if attr in _val.attributes else 0.0
func = lambda _val: _val.attributes[attr].value if attr in _val.attributes else 0.0
# Clicked on a column that's not part of our array (price most likely)
except IndexError:
# Price
if sort == len(self.attrs) + 1:
func = lambda i: i.price.price if i.price.price != 0 else float("Inf")
# Buck/bang
elif sort == len(self.attrs) + 2:
if self.bangBuckColumn is not None:
attr_key = list(self.attrs.keys())[self.bangBuckColumn - 1]
if attr_key in self.computedAttrs:
computed = self.computedAttrs[attr_key]
amountAttr = computed["amountAttr"]
durationAttr = computed["durationAttr"]
func = lambda i: (i.price.price / (i.attributes[amountAttr].value / (i.attributes[durationAttr].value / 1000.0)) if (amountAttr in i.attributes and durationAttr in i.attributes and i.attributes[durationAttr].value > 0 and (i.attributes[amountAttr].value / (i.attributes[durationAttr].value / 1000.0)) > 0) else float("Inf"))
else:
func = lambda i: (i.price.price / i.attributes[attr_key].value if (attr_key in i.attributes and i.attributes[attr_key].value > 0) else float("Inf"))
else:
func = defaultSort
# Something else
else:
self.sortReverse = False
@@ -291,49 +166,18 @@ class ItemCompare(wx.Panel):
for i, attr in enumerate(self.attrs.keys()):
name = self.attrs[attr].displayName if self.attrs[attr].displayName else attr
# Add indicator if this column is selected for bang/buck calculation
if self.bangBuckColumn == i + 1:
name = "" + name
self.paramList.InsertColumn(i + 1, name)
self.paramList.SetColumnWidth(i + 1, 120)
self.paramList.InsertColumn(len(self.attrs) + 1, _t("Price"))
self.paramList.SetColumnWidth(len(self.attrs) + 1, 60)
# Add Buck/bang column header
buckBangHeader = _t("Buck/bang")
if self.bangBuckColumnName:
buckBangHeader = _t("Buck/bang ({})").format(self.bangBuckColumnName)
self.paramList.InsertColumn(len(self.attrs) + 2, buckBangHeader)
self.paramList.SetColumnWidth(len(self.attrs) + 2, 80)
toHighlight = []
for item in self.items:
i = self.paramList.InsertItem(self.paramList.GetItemCount(), item.name)
for x, attr in enumerate(self.attrs.keys()):
# Handle computed attributes
if attr in self.computedAttrs:
computed = self.computedAttrs[attr]
amountAttr = computed["amountAttr"]
durationAttr = computed["durationAttr"]
# Item needs both attributes to display per-second value
if amountAttr in item.attributes and durationAttr in item.attributes:
amountValue = item.attributes[amountAttr].value
durationValue = item.attributes[durationAttr].value
# Duration is in milliseconds, convert to seconds
perSecondValue = amountValue / (durationValue / 1000.0) if durationValue > 0 else 0
info = self.attrs[attr]
if self.toggleView == 1:
valueUnit = formatAmount(perSecondValue, 3, 0, 0) + " " + info.unit.displayName
else:
valueUnit = str(perSecondValue)
self.paramList.SetItem(i, x + 1, valueUnit)
# else: leave cell empty
elif attr in item.attributes:
if attr in item.attributes:
info = self.attrs[attr]
value = item.attributes[attr].value
if self.toggleView != 1:
@@ -347,27 +191,6 @@ class ItemCompare(wx.Panel):
# Add prices
self.paramList.SetItem(i, len(self.attrs) + 1, formatAmount(item.price.price, 3, 3, 9, currency=True) if item.price.price else "")
# Add buck/bang values
if self.bangBuckColumn is not None and item.price.price and item.price.price > 0:
attr_key = list(self.attrs.keys())[self.bangBuckColumn - 1]
if attr_key in self.computedAttrs:
computed = self.computedAttrs[attr_key]
amountAttr = computed["amountAttr"]
durationAttr = computed["durationAttr"]
if amountAttr in item.attributes and durationAttr in item.attributes:
amountValue = item.attributes[amountAttr].value
durationValue = item.attributes[durationAttr].value
perSecondValue = amountValue / (durationValue / 1000.0) if durationValue > 0 else 0
if perSecondValue > 0:
buckBangValue = item.price.price / perSecondValue
self.paramList.SetItem(i, len(self.attrs) + 2, formatAmount(buckBangValue, 3, 3, 9, currency=True))
elif attr_key in item.attributes:
attrValue = item.attributes[attr_key].value
if attrValue > 0:
buckBangValue = item.price.price / attrValue
self.paramList.SetItem(i, len(self.attrs) + 2, formatAmount(buckBangValue, 3, 3, 9, currency=True))
if item.name in self.highlightedNames:
toHighlight.append(i)

View File

@@ -1,220 +0,0 @@
# noinspection PyPackageRequirements
import wx
import itertools
import gui.mainFrame
from eos.saveddata.character import Skill
from eos.saveddata.fighter import Fighter as es_Fighter
from eos.saveddata.module import Module as es_Module
from eos.saveddata.ship import Ship
from gui.utils.clipboard import toClipboard
from gui.utils.numberFormatter import formatAmount
from service.fit import Fit
_t = wx.GetTranslation
class ItemSkills(wx.Panel):
def __init__(self, parent, stuff, item):
wx.Panel.__init__(self, parent)
self.stuff = stuff
self.item = item
mainSizer = wx.BoxSizer(wx.HORIZONTAL)
leftPanel = wx.Panel(self)
leftSizer = wx.BoxSizer(wx.VERTICAL)
leftPanel.SetSizer(leftSizer)
header = wx.StaticText(leftPanel, wx.ID_ANY, _t("Components"))
font = header.GetFont()
font.SetWeight(wx.FONTWEIGHT_BOLD)
header.SetFont(font)
leftSizer.Add(header, 0, wx.ALL, 5)
self.checkboxes = {}
components = [
("Ship", "ship"),
("Modules", "modules"),
("Drones", "drones"),
("Fighters", "fighters"),
("Cargo", "cargo"),
("Implants", "appliedImplants"),
("Boosters", "boosters"),
("Necessary", "necessary"),
]
for label, key in components:
cb = wx.CheckBox(leftPanel, wx.ID_ANY, label)
cb.SetValue(True)
cb.Bind(wx.EVT_CHECKBOX, self.onCheckboxChange)
self.checkboxes[key] = cb
leftSizer.Add(cb, 0, wx.ALL, 2)
leftSizer.AddStretchSpacer()
mainSizer.Add(leftPanel, 0, wx.EXPAND | wx.ALL, 5)
rightPanel = wx.Panel(self)
rightSizer = wx.BoxSizer(wx.VERTICAL)
rightPanel.SetSizer(rightSizer)
headerRight = wx.StaticText(rightPanel, wx.ID_ANY, _t("Skills"))
fontRight = headerRight.GetFont()
fontRight.SetWeight(wx.FONTWEIGHT_BOLD)
headerRight.SetFont(fontRight)
rightSizer.Add(headerRight, 0, wx.ALL, 5)
self.skillsText = wx.TextCtrl(rightPanel, wx.ID_ANY, "", style=wx.TE_MULTILINE | wx.TE_READONLY | wx.TE_DONTWRAP)
font = wx.Font(9, wx.FONTFAMILY_TELETYPE, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)
self.skillsText.SetFont(font)
rightSizer.Add(self.skillsText, 1, wx.EXPAND | wx.ALL, 5)
mainSizer.Add(rightPanel, 1, wx.EXPAND | wx.ALL, 5)
self.SetSizer(mainSizer)
self.nbContainer = parent if isinstance(parent, wx.Notebook) else None
if self.nbContainer:
self.nbContainer.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.onTabChanged)
self.updateSkills()
def onCheckboxChange(self, event):
self.updateSkills()
self._copyToClipboard()
def updateSkills(self):
fitID = gui.mainFrame.MainFrame.getInstance().getActiveFit()
if fitID is None:
self.skillsText.SetValue("")
self._updateCheckboxStates(None)
return
sFit = Fit.getInstance()
fit = sFit.getFit(fitID)
if fit is None:
self.skillsText.SetValue("")
self._updateCheckboxStates(None)
return
if not fit.calculated:
fit.calculate()
self._updateCheckboxStates(fit)
char = fit.character
skillsMap = {}
items = []
if self.checkboxes["ship"].GetValue():
items.append(fit.ship)
if self.checkboxes["modules"].GetValue():
items.extend(fit.modules)
if self.checkboxes["drones"].GetValue():
items.extend(fit.drones)
if self.checkboxes["fighters"].GetValue():
items.extend(fit.fighters)
if self.checkboxes["cargo"].GetValue():
items.extend(fit.cargo)
if self.checkboxes["appliedImplants"].GetValue():
items.extend(fit.appliedImplants)
if self.checkboxes["boosters"].GetValue():
items.extend(fit.boosters)
for thing in items:
self._collectAffectingSkills(thing, char, skillsMap)
if self.checkboxes["necessary"].GetValue():
self._collectRequiredSkills(items, char, skillsMap)
skillsList = ""
for skillName in sorted(skillsMap):
charLevel = skillsMap[skillName]
for level in range(1, charLevel + 1):
skillsList += "%s %d\n" % (skillName, level)
self.skillsText.SetValue(skillsList)
self._copyToClipboard()
def _copyToClipboard(self):
skillsText = self.skillsText.GetValue()
if skillsText:
toClipboard(skillsText)
def onTabChanged(self, event):
if self.nbContainer:
pageIndex = self.nbContainer.FindPage(self)
if pageIndex != -1 and event.GetSelection() == pageIndex:
self.updateSkills()
event.Skip()
def _updateCheckboxStates(self, fit):
if fit is None:
for cb in self.checkboxes.values():
cb.Enable(False)
return
self.checkboxes["ship"].Enable(True)
self.checkboxes["modules"].Enable(len(fit.modules) > 0)
self.checkboxes["drones"].Enable(len(fit.drones) > 0)
self.checkboxes["fighters"].Enable(len(fit.fighters) > 0)
self.checkboxes["cargo"].Enable(len(fit.cargo) > 0)
self.checkboxes["appliedImplants"].Enable(len(fit.appliedImplants) > 0)
self.checkboxes["boosters"].Enable(len(fit.boosters) > 0)
self.checkboxes["necessary"].Enable(True)
def _collectAffectingSkills(self, thing, char, skillsMap):
for attr in ("item", "charge"):
if attr == "charge" and isinstance(thing, es_Fighter):
continue
subThing = getattr(thing, attr, None)
if subThing is None:
continue
if isinstance(thing, es_Fighter) and attr == "charge":
continue
if attr == "charge":
cont = getattr(thing, "chargeModifiedAttributes", None)
else:
cont = getattr(thing, "itemModifiedAttributes", None)
if cont is not None:
for attrName in cont.iterAfflictions():
for fit, afflictors in cont.getAfflictions(attrName).items():
for afflictor, operator, stackingGroup, preResAmount, postResAmount, used in afflictors:
if isinstance(afflictor, Skill) and afflictor.character == char:
skillName = afflictor.item.name
if skillName not in skillsMap:
skillsMap[skillName] = afflictor.level
elif skillsMap[skillName] < afflictor.level:
skillsMap[skillName] = afflictor.level
def _collectRequiredSkills(self, items, char, skillsMap):
"""Collect required skills from items (necessary to use them)"""
for thing in items:
for attr in ("item", "charge"):
if attr == "charge" and isinstance(thing, es_Fighter):
continue
subThing = getattr(thing, attr, None)
if subThing is None:
continue
if isinstance(thing, es_Fighter) and attr == "charge":
continue
if hasattr(subThing, "requiredSkills"):
for reqSkill, level in subThing.requiredSkills.items():
skillName = reqSkill.name
charSkill = char.getSkill(reqSkill) if char else None
charLevel = charSkill.level if charSkill else 0
if charLevel > 0:
if skillName not in skillsMap:
skillsMap[skillName] = charLevel
elif skillsMap[skillName] < charLevel:
skillsMap[skillName] = charLevel
else:
if skillName not in skillsMap:
skillsMap[skillName] = level
elif skillsMap[skillName] < level:
skillsMap[skillName] = level

View File

@@ -5,7 +5,6 @@ import gui.builtinMarketBrowser.pfSearchBox as SBox
import gui.globalEvents as GE
from config import slotColourMap, slotColourMapDark
from eos.saveddata.module import Module
from eos.const import FittingSlot
from gui.builtinMarketBrowser.events import ItemSelected, RECENTLY_USED_MODULES, CHARGES_FOR_FIT
from gui.contextMenu import ContextMenu
from gui.display import Display
@@ -23,7 +22,6 @@ class ItemView(Display):
DEFAULT_COLS = ["Base Icon",
"Base Name",
"Price",
"attr:power,,,True",
"attr:cpu,,,True"]
@@ -155,22 +153,19 @@ class ItemView(Display):
# skip the event so the other handlers also get called
event.Skip()
if self.marketBrowser.mode != 'charges':
return
activeFitID = self.mainFrame.getActiveFit()
# if it was not the active fitting that was changed, do not do anything
if activeFitID is not None and activeFitID not in event.fitIDs:
return
# Handle charges mode
if self.marketBrowser.mode == 'charges':
items = self.getChargesForActiveFit()
# update the UI
self.updateItemStore(items)
self.filterItemStore()
return
items = self.getChargesForActiveFit()
# If "Fits" filter is active, re-filter the current view
if self.marketBrowser.getFitsFilter():
self.filterItemStore()
# update the UI
self.updateItemStore(items)
self.filterItemStore()
def updateItemStore(self, items):
self.unfilteredStore = items
@@ -202,115 +197,13 @@ class ItemView(Display):
if btn.userSelected:
selectedMetas.update(sMkt.META_MAP[btn.metaName])
filteredItems = sMkt.filterItemsByMeta(self.unfilteredStore, selectedMetas)
# Apply slot/fits filters - works IDENTICALLY to meta buttons (filters CURRENT VIEW only)
activeSlotFilters = []
fitsFilterActive = False
for btn in self.marketBrowser.slotButtons:
if btn.userSelected and btn.IsEnabled():
if btn.filterType == "fits":
fitsFilterActive = True
elif btn.filterType == "slot":
activeSlotFilters.append(btn.slotType)
# Apply fits filter
if fitsFilterActive:
filteredItems = self._filterByFits(filteredItems)
# Apply slot filters
if activeSlotFilters:
filteredItems = [item for item in filteredItems if Module.calculateSlot(item) in activeSlotFilters]
return filteredItems
def _filterByFits(self, items):
"""Filter items by remaining CPU/PG - filters CURRENT VIEW only"""
fitId = self.mainFrame.getActiveFit()
if fitId is None:
return []
fit = self.sFit.getFit(fitId)
# Get remaining CPU and power grid
cpuOutput = fit.ship.getModifiedItemAttr("cpuOutput")
powerOutput = fit.ship.getModifiedItemAttr("powerOutput")
cpuUsed = fit.cpuUsed
pgUsed = fit.pgUsed
cpuRemaining = cpuOutput - cpuUsed
pgRemaining = powerOutput - pgUsed
# Get remaining calibration (for rigs)
calibrationCapacity = fit.ship.getModifiedItemAttr("upgradeCapacity")
calibrationUsed = fit.calibrationUsed
calibrationRemaining = None
if calibrationCapacity is not None and calibrationCapacity > 0:
calibrationRemaining = calibrationCapacity - calibrationUsed
fittingItems = []
for item in items:
# Check if item is a module (has a slot)
slot = Module.calculateSlot(item)
if slot is None:
continue
# Rigs don't use CPU/power, they use calibration - check rig size and calibration
if slot == FittingSlot.RIG:
# Check if item can fit on the ship
if not fit.canFit(item):
continue
# Check rig size compatibility with ship
shipRigSize = fit.ship.getModifiedItemAttr("rigSize")
itemRigSize = item.attributes.get("rigSize")
if shipRigSize is not None and itemRigSize is not None:
if shipRigSize != itemRigSize.value:
continue
# Check calibration requirement
if calibrationRemaining is not None and calibrationRemaining > 0:
itemCalibration = item.attributes.get("upgradeCost")
if itemCalibration is not None:
itemCalibrationValue = itemCalibration.value
if itemCalibrationValue > calibrationRemaining:
continue
fittingItems.append(item)
continue
# For non-rigs, check CPU and power requirements
itemCpu = item.attributes.get("cpu")
itemPower = item.attributes.get("power")
# Skip items without CPU or power (not modules)
if itemCpu is None and itemPower is None:
continue
# Check CPU requirement
if itemCpu is not None:
itemCpuValue = itemCpu.value
if itemCpuValue > cpuRemaining:
continue
# Check power requirement
if itemPower is not None:
itemPowerValue = itemPower.value
if itemPowerValue > pgRemaining:
continue
# Check if item can fit on the ship (most expensive check, do last)
if not fit.canFit(item):
continue
fittingItems.append(item)
return fittingItems
def setToggles(self):
metaIDs = set()
slotIDs = set()
sMkt = self.sMkt
for item in self.unfilteredStore:
metaIDs.add(sMkt.getMetaGroupIdByItem(item))
slot = Module.calculateSlot(item)
if slot is not None:
slotIDs.add(slot)
for btn in self.marketBrowser.metaButtons:
btn.reset()
@@ -319,23 +212,6 @@ class ItemView(Display):
btn.setMetaAvailable(True)
else:
btn.setMetaAvailable(False)
# Set toggles for slot/fits buttons
for btn in self.marketBrowser.slotButtons:
btn.reset()
if btn.filterType == "fits":
# Fits button is available if there's an active fit
fitId = self.mainFrame.getActiveFit()
isAvailable = fitId is not None
btn.setMetaAvailable(isAvailable)
if not isAvailable:
btn.setUserSelection(False)
elif btn.filterType == "slot":
# Slot button is available if items with that slot exist in current view
isAvailable = btn.slotType in slotIDs
btn.setMetaAvailable(isAvailable)
if not isAvailable:
btn.setUserSelection(False)
def scheduleSearch(self, event=None):
self.searchTimer.Stop() # Cancel any pending timers

View File

@@ -20,7 +20,6 @@
# noinspection PyPackageRequirements
import wx
from eos.gamedata import Item
from eos.saveddata.cargo import Cargo
from eos.saveddata.drone import Drone
from eos.saveddata.fighter import Fighter
@@ -54,14 +53,7 @@ class Price(ViewColumn):
self.imageId = fittingView.imageList.GetImageIndex("totalPrice_small", "gui")
def getText(self, stuff):
if isinstance(stuff, Item):
item = stuff
else:
if not hasattr(stuff, "item") or stuff.item is None:
return ""
item = stuff.item
if item.group.name == "Ship Modifiers":
if stuff.item is None or stuff.item.group.name == "Ship Modifiers":
return ""
if hasattr(stuff, "isEmpty"):
@@ -71,7 +63,7 @@ class Price(ViewColumn):
if isinstance(stuff, Module) and stuff.isMutated:
return ""
priceObj = item.price
priceObj = stuff.item.price
if not priceObj.isValid():
return False
@@ -87,11 +79,7 @@ class Price(ViewColumn):
display.SetItem(colItem)
if isinstance(mod, Item):
item = mod
else:
item = mod.item
sPrice.getPrices([item], callback, waitforthread=True)
sPrice.getPrices([mod.item], callback, waitforthread=True)
def getImageId(self, mod):
return -1

View File

@@ -497,27 +497,11 @@ class FittingView(d.Display):
fit = Fit.getInstance().getFit(fitID)
if mod in fit.modules:
position = fit.modules.index(mod)
modifiers = wx.GetMouseState().GetModifiers()
isCopy = modifiers == wx.MOD_CONTROL
isBatch = modifiers == wx.MOD_SHIFT
if isBatch:
self.mainFrame.command.Submit(
cmd.GuiBatchCargoToLocalModuleCommand(
fitID=fitID,
cargoItemID=cargoItemID,
targetPosition=position,
copy=isCopy,
)
)
else:
self.mainFrame.command.Submit(
cmd.GuiCargoToLocalModuleCommand(
fitID=fitID,
cargoItemID=cargoItemID,
modPosition=position,
copy=isCopy,
)
)
self.mainFrame.command.Submit(cmd.GuiCargoToLocalModuleCommand(
fitID=fitID,
cargoItemID=cargoItemID,
modPosition=position,
copy=wx.GetMouseState().GetModifiers() == wx.MOD_CONTROL))
def swapItems(self, x, y, srcIdx):
"""Swap two modules in fitting window"""
@@ -684,21 +668,6 @@ class FittingView(d.Display):
contexts.append(fullContext)
contexts.append(("fittingShip", _t("Ship") if not fit.isStructure else _t("Citadel")))
# Check if shift is held for direct skills menu access
if wx.GetKeyState(wx.WXK_SHIFT):
from gui.builtinContextMenus.skillAffectors import ChangeAffectingSkills
for fullContext in contexts:
srcContext = fullContext[0]
itemContext = fullContext[1] if len(fullContext) > 1 else None
skillsMenu = ChangeAffectingSkills()
if skillsMenu.display(self, srcContext, mainMod):
# On Windows, menu items need to be bound to the menu shown with PopupMenu
# We pass None as rootMenu so items are bound to their parent submenus
sub = skillsMenu.getSubMenu(self, srcContext, mainMod, None, 0, None)
if sub:
self.PopupMenu(sub)
return
menu = ContextMenu.getMenu(self, mainMod, selection, *contexts)
self.PopupMenu(menu)
@@ -811,6 +780,7 @@ class FittingView(d.Display):
del mod.restrictionOverridden
hasRestrictionOverriden = not hasRestrictionOverriden
if slotMap[mod.slot] or hasRestrictionOverriden: # Color too many modules as red
self.SetItemBackgroundColour(i, errColorDark if isDark() else errColor)
elif sFit.serviceFittingOptions["colorFitBySlot"]: # Color by slot it enabled

View File

@@ -29,7 +29,7 @@ import config
import gui.globalEvents as GE
import gui.mainFrame
from gui.bitmap_loader import BitmapLoader
from gui.utils.clipboard import toClipboard, fromClipboard
from gui.utils.clipboard import toClipboard
from service.character import Character
from service.fit import Fit
@@ -49,10 +49,6 @@ class CharacterSelection(wx.Panel):
# cache current selection to fall back in case we choose to open char editor
self.charCache = None
# history for Shift-Tab navigation
self.charHistory = []
self._updatingFromHistory = False
self.charChoice = wx.Choice(self)
mainSizer.Add(self.charChoice, 1, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT | wx.LEFT, 3)
@@ -96,7 +92,7 @@ class CharacterSelection(wx.Panel):
sFit = Fit.getInstance()
fit = sFit.getFit(self.mainFrame.getActiveFit())
if not fit:
if not fit or not self.needsSkills:
return
pos = wx.GetMousePosition()
@@ -104,23 +100,17 @@ class CharacterSelection(wx.Panel):
menu = wx.Menu()
if self.needsSkills:
grantItem = menu.Append(wx.ID_ANY, _t("Grant Missing Skills"))
self.Bind(wx.EVT_MENU, self.grantMissingSkills, grantItem)
grantItem = menu.Append(wx.ID_ANY, _t("Grant Missing Skills"))
self.Bind(wx.EVT_MENU, self.grantMissingSkills, grantItem)
exportItem = menu.Append(wx.ID_ANY, _t("Copy Missing Skills"))
self.Bind(wx.EVT_MENU, self.exportSkills, exportItem)
exportItem = menu.Append(wx.ID_ANY, _t("Copy Missing Skills"))
self.Bind(wx.EVT_MENU, self.exportSkills, exportItem)
exportItem = menu.Append(wx.ID_ANY, _t("Copy Missing Skills (condensed)"))
self.Bind(wx.EVT_MENU, self.exportSkillsCondensed, exportItem)
exportItem = menu.Append(wx.ID_ANY, _t("Copy Missing Skills (condensed)"))
self.Bind(wx.EVT_MENU, self.exportSkillsCondensed, exportItem)
exportItem = menu.Append(wx.ID_ANY, _t("Copy Missing Skills (EVEMon)"))
self.Bind(wx.EVT_MENU, self.exportSkillsEveMon, exportItem)
menu.AppendSeparator()
importItem = menu.Append(wx.ID_ANY, _t("Import Skills from Clipboard"))
self.Bind(wx.EVT_MENU, self.importSkillsFromClipboard, importItem)
exportItem = menu.Append(wx.ID_ANY, _t("Copy Missing Skills (EVEMon)"))
self.Bind(wx.EVT_MENU, self.exportSkillsEveMon, exportItem)
self.PopupMenu(menu, pos)
@@ -199,13 +189,6 @@ class CharacterSelection(wx.Panel):
sFit = Fit.getInstance()
sFit.changeChar(fitID, charID)
self.charCache = self.charChoice.GetCurrentSelection()
if not self._updatingFromHistory and charID is not None:
currentChar = self.getActiveCharacter()
if currentChar is not None:
if not self.charHistory or self.charHistory[-1] != currentChar:
self.charHistory.append(currentChar)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitIDs=(fitID,)))
def toggleRefreshButton(self):
@@ -227,29 +210,6 @@ class CharacterSelection(wx.Panel):
return True
return False
def selectPreviousChar(self):
currentChar = self.getActiveCharacter()
if currentChar is None:
return
if not self.charHistory:
return
if self.charHistory and self.charHistory[-1] == currentChar:
self.charHistory.pop()
if not self.charHistory:
return
prevChar = self.charHistory.pop()
if currentChar != prevChar:
self.charHistory.append(currentChar)
self._updatingFromHistory = True
if self.selectChar(prevChar):
self.charChanged(None)
self._updatingFromHistory = False
def fitChanged(self, event):
"""
@@ -262,7 +222,7 @@ class CharacterSelection(wx.Panel):
self.charChoice.Enable(activeFitID is not None)
choice = self.charChoice
sFit = Fit.getInstance()
currCharID = choice.GetClientData(choice.GetCurrentSelection()) if choice.GetCurrentSelection() != -1 else None
currCharID = choice.GetClientData(choice.GetCurrentSelection())
fit = sFit.getFit(activeFitID)
newCharID = fit.character.ID if fit is not None else None
@@ -296,9 +256,6 @@ class CharacterSelection(wx.Panel):
self.selectChar(sChar.all5ID())
elif currCharID != newCharID:
if currCharID is not None and not self._updatingFromHistory:
if not self.charHistory or self.charHistory[-1] != currCharID:
self.charHistory.append(currCharID)
self.selectChar(newCharID)
if not fit.calculated:
self.charChanged(None)
@@ -332,83 +289,6 @@ class CharacterSelection(wx.Panel):
toClipboard(list)
def importSkillsFromClipboard(self, evt):
charID = self.getActiveCharacter()
if charID is None:
return
sChar = Character.getInstance()
char = sChar.getCharacter(charID)
text = fromClipboard()
if not text:
with wx.MessageDialog(self, _t("Clipboard is empty"), _t("Error"), wx.OK | wx.ICON_ERROR) as dlg:
dlg.ShowModal()
return
try:
lines = text.strip().splitlines()
imported = 0
errors = []
for line in lines:
line = line.strip()
if not line:
continue
try:
parts = line.rsplit(None, 1)
if len(parts) != 2:
errors.append(_t("Invalid format: {}").format(line))
continue
skillName = parts[0]
levelStr = parts[1]
try:
level = int(levelStr)
except ValueError:
try:
level = roman.fromRoman(levelStr.upper())
except (roman.InvalidRomanNumeralError, ValueError):
errors.append(_t("Invalid level format: {}").format(line))
continue
if level < 0 or level > 5:
errors.append(_t("Level must be between 0 and 5: {}").format(line))
continue
skill = char.getSkill(skillName)
sChar.changeLevel(charID, skill.item.ID, level)
imported += 1
except KeyError as e:
errors.append(_t("Skill not found: {}").format(skillName))
pyfalog.error("Skill not found: '{}'", skillName)
except Exception as e:
errors.append(_t("Error processing line '{}': {}").format(line, str(e)))
pyfalog.error("Error importing skill from line '{}': {}", line, e)
if imported > 0:
self.refreshCharacterList()
wx.PostEvent(self.mainFrame, GE.CharListUpdated())
fitID = self.mainFrame.getActiveFit()
if fitID is not None:
wx.PostEvent(self.mainFrame, GE.FitChanged(fitIDs=(fitID,)))
if errors:
errorMsg = _t("Imported {} skill(s). Errors:\n{}").format(imported, "\n".join(errors))
with wx.MessageDialog(self, errorMsg, _t("Import Skills"), wx.OK | wx.ICON_WARNING) as dlg:
dlg.ShowModal()
elif imported > 0:
with wx.MessageDialog(self, _t("Successfully imported {} skill(s)").format(imported), _t("Import Skills"), wx.OK) as dlg:
dlg.ShowModal()
except Exception as e:
pyfalog.error("Error importing skills from clipboard: {}", e)
with wx.MessageDialog(self, _t("Error importing skills. Please check the log file."), _t("Error"), wx.OK | wx.ICON_ERROR) as dlg:
dlg.ShowModal()
def _buildSkillsTooltip(self, reqs, currItem="", tabulationLevel=0):
tip = ""
sCharacter = Character.getInstance()

View File

@@ -59,12 +59,6 @@ from .gui.localModule.mutatedRevert import GuiRevertMutatedLocalModuleCommand
from .gui.localModule.remove import GuiRemoveLocalModuleCommand
from .gui.localModule.replace import GuiReplaceLocalModuleCommand
from .gui.localModule.swap import GuiSwapLocalModulesCommand
from .gui.localModuleCargo.batchCargoToLocalModule import (
GuiBatchCargoToLocalModuleCommand,
)
from .gui.localModuleCargo.batchLocalModuleToCargo import (
GuiBatchLocalModuleToCargoCommand,
)
from .gui.localModuleCargo.cargoToLocalModule import GuiCargoToLocalModuleCommand
from .gui.localModuleCargo.localModuleToCargo import GuiLocalModuleToCargoCommand
from .gui.projectedChangeProjectionRange import GuiChangeProjectedItemsProjectionRangeCommand

View File

@@ -1,325 +0,0 @@
import wx
import eos.db
import gui.mainFrame
from gui import globalEvents as GE
from gui.fitCommands.calc.cargo.add import CalcAddCargoCommand
from gui.fitCommands.calc.cargo.remove import CalcRemoveCargoCommand
from gui.fitCommands.calc.module.changeCharges import CalcChangeModuleChargesCommand
from gui.fitCommands.calc.module.localReplace import CalcReplaceLocalModuleCommand
from gui.fitCommands.helpers import (
CargoInfo,
InternalCommandHistory,
ModuleInfo,
restoreRemovedDummies,
)
from service.fit import Fit
class GuiBatchCargoToLocalModuleCommand(wx.Command):
def __init__(self, fitID, cargoItemID, targetPosition, copy):
wx.Command.__init__(self, True, "Batch Cargo to Local Modules")
self.internalHistory = InternalCommandHistory()
self.fitID = fitID
self.srcCargoItemID = cargoItemID
self.targetPosition = targetPosition
self.copy = copy
self.replacedModItemIDs = []
self.savedRemovedDummies = None
def Do(self):
sFit = Fit.getInstance()
fit = sFit.getFit(self.fitID)
if fit is None:
return False
srcCargo = next((c for c in fit.cargo if c.itemID == self.srcCargoItemID), None)
if srcCargo is None:
return False
if srcCargo.item.isCharge:
return self._handleCharges(fit, srcCargo)
if not srcCargo.item.isModule:
return False
if self.targetPosition >= len(fit.modules):
return False
targetMod = fit.modules[self.targetPosition]
if targetMod.isEmpty:
return self._fillEmptySlots(fit, srcCargo, targetMod.slot)
else:
return self._replaceSimilarModules(fit, srcCargo, targetMod)
def _getSimilarModulePositions(self, fit, targetMod):
targetItemID = targetMod.itemID
matchingPositions = []
for position, mod in enumerate(fit.modules):
if mod.isEmpty:
continue
if mod.itemID == targetItemID:
matchingPositions.append(position)
return matchingPositions
def _replaceSimilarModules(self, fit, srcCargo, targetMod):
availableAmount = srcCargo.amount if not self.copy else float("inf")
matchingPositions = self._getSimilarModulePositions(fit, targetMod)
if not matchingPositions:
return False
positionsToReplace = matchingPositions[: int(availableAmount)]
if not positionsToReplace:
return False
self.replacedModItemIDs = []
commands = []
cargoToRemove = 0
for position in positionsToReplace:
mod = fit.modules[position]
if mod.isEmpty:
continue
dstModItemID = mod.itemID
newModInfo = ModuleInfo.fromModule(mod, unmutate=True)
newModInfo.itemID = self.srcCargoItemID
newCargoModItemID = ModuleInfo.fromModule(mod, unmutate=True).itemID
commands.append(
CalcAddCargoCommand(
fitID=self.fitID,
cargoInfo=CargoInfo(itemID=newCargoModItemID, amount=1),
)
)
cmdReplace = CalcReplaceLocalModuleCommand(
fitID=self.fitID,
position=position,
newModInfo=newModInfo,
unloadInvalidCharges=True,
)
commands.append(cmdReplace)
self.replacedModItemIDs.append(dstModItemID)
cargoToRemove += 1
if not self.copy and cargoToRemove > 0:
commands.insert(
0,
CalcRemoveCargoCommand(
fitID=self.fitID,
cargoInfo=CargoInfo(
itemID=self.srcCargoItemID, amount=cargoToRemove
),
),
)
success = self.internalHistory.submitBatch(*commands)
if not success:
self.internalHistory.undoAll()
return False
eos.db.flush()
sFit = Fit.getInstance()
sFit.recalc(self.fitID)
self.savedRemovedDummies = sFit.fill(self.fitID)
eos.db.commit()
events = []
for removedModItemID in self.replacedModItemIDs:
events.append(
GE.FitChanged(
fitIDs=(self.fitID,), action="moddel", typeID=removedModItemID
)
)
if self.srcCargoItemID is not None:
events.append(
GE.FitChanged(
fitIDs=(self.fitID,), action="modadd", typeID=self.srcCargoItemID
)
)
if not events:
events.append(GE.FitChanged(fitIDs=(self.fitID,)))
for event in events:
wx.PostEvent(gui.mainFrame.MainFrame.getInstance(), event)
return True
def _fillEmptySlots(self, fit, srcCargo, targetSlot):
availableAmount = srcCargo.amount if not self.copy else float("inf")
emptyPositions = []
for position, mod in enumerate(fit.modules):
if mod.isEmpty and mod.slot == targetSlot:
emptyPositions.append(position)
if not emptyPositions:
return False
positionsToFill = emptyPositions[: int(availableAmount)]
if not positionsToFill:
return False
commands = []
cargoToRemove = 0
for position in positionsToFill:
newModInfo = ModuleInfo(itemID=self.srcCargoItemID)
cmdReplace = CalcReplaceLocalModuleCommand(
fitID=self.fitID,
position=position,
newModInfo=newModInfo,
unloadInvalidCharges=True,
)
commands.append(cmdReplace)
cargoToRemove += 1
if not self.copy and cargoToRemove > 0:
commands.insert(
0,
CalcRemoveCargoCommand(
fitID=self.fitID,
cargoInfo=CargoInfo(
itemID=self.srcCargoItemID, amount=cargoToRemove
),
),
)
success = self.internalHistory.submitBatch(*commands)
if not success:
self.internalHistory.undoAll()
return False
eos.db.flush()
sFit = Fit.getInstance()
sFit.recalc(self.fitID)
self.savedRemovedDummies = sFit.fill(self.fitID)
eos.db.commit()
events = []
if self.srcCargoItemID is not None:
events.append(
GE.FitChanged(
fitIDs=(self.fitID,), action="modadd", typeID=self.srcCargoItemID
)
)
if not events:
events.append(GE.FitChanged(fitIDs=(self.fitID,)))
for event in events:
wx.PostEvent(gui.mainFrame.MainFrame.getInstance(), event)
return True
def _handleCharges(self, fit, srcCargo):
availableAmount = srcCargo.amount if not self.copy else float("inf")
targetMod = fit.modules[self.targetPosition]
if targetMod.isEmpty:
return False
targetItemID = targetMod.itemID
matchingPositions = []
for position, mod in enumerate(fit.modules):
if mod.isEmpty:
continue
if mod.itemID == targetItemID:
matchingPositions.append(position)
if not matchingPositions:
return False
positionsToReplace = matchingPositions[: int(availableAmount)]
if not positionsToReplace:
return False
commands = []
chargeMap = {}
totalChargesNeeded = 0
for position in positionsToReplace:
mod = fit.modules[position]
if mod.isEmpty:
continue
oldChargeID = mod.chargeID
oldChargeAmount = mod.numCharges
newChargeAmount = mod.getNumCharges(srcCargo.item)
if oldChargeID is not None and oldChargeID != srcCargo.itemID:
commands.append(
CalcAddCargoCommand(
fitID=self.fitID,
cargoInfo=CargoInfo(itemID=oldChargeID, amount=oldChargeAmount),
)
)
chargeMap[position] = srcCargo.itemID
totalChargesNeeded += newChargeAmount
if not self.copy and totalChargesNeeded > 0:
commands.append(
CalcRemoveCargoCommand(
fitID=self.fitID,
cargoInfo=CargoInfo(
itemID=srcCargo.itemID, amount=totalChargesNeeded
),
)
)
commands.append(
CalcChangeModuleChargesCommand(
fitID=self.fitID, projected=False, chargeMap=chargeMap
)
)
success = self.internalHistory.submitBatch(*commands)
if not success:
self.internalHistory.undoAll()
return False
eos.db.flush()
sFit = Fit.getInstance()
sFit.recalc(self.fitID)
self.savedRemovedDummies = sFit.fill(self.fitID)
eos.db.commit()
events = [GE.FitChanged(fitIDs=(self.fitID,))]
for event in events:
wx.PostEvent(gui.mainFrame.MainFrame.getInstance(), event)
return True
def Undo(self):
sFit = Fit.getInstance()
fit = sFit.getFit(self.fitID)
restoreRemovedDummies(fit, self.savedRemovedDummies)
success = self.internalHistory.undoAll()
eos.db.flush()
sFit.recalc(self.fitID)
sFit.fill(self.fitID)
eos.db.commit()
events = []
if self.srcCargoItemID is not None:
events.append(
GE.FitChanged(
fitIDs=(self.fitID,), action="moddel", typeID=self.srcCargoItemID
)
)
for removedModItemID in self.replacedModItemIDs:
events.append(
GE.FitChanged(
fitIDs=(self.fitID,), action="modadd", typeID=removedModItemID
)
)
if not events:
events.append(GE.FitChanged(fitIDs=(self.fitID,)))
for event in events:
wx.PostEvent(gui.mainFrame.MainFrame.getInstance(), event)
return success

View File

@@ -1,167 +0,0 @@
import wx
import eos.db
import gui.mainFrame
from gui import globalEvents as GE
from gui.fitCommands.calc.cargo.add import CalcAddCargoCommand
from gui.fitCommands.calc.module.localRemove import CalcRemoveLocalModulesCommand
from gui.fitCommands.helpers import (
CargoInfo,
InternalCommandHistory,
ModuleInfo,
restoreRemovedDummies,
)
from service.fit import Fit
class GuiBatchLocalModuleToCargoCommand(wx.Command):
def __init__(self, fitID, modPosition, copy):
wx.Command.__init__(self, True, "Batch Local Module to Cargo")
self.internalHistory = InternalCommandHistory()
self.fitID = fitID
self.srcModPosition = modPosition
self.copy = copy
self.removedModItemIDs = []
self.savedRemovedDummies = None
def Do(self):
fit = Fit.getInstance().getFit(self.fitID)
srcMod = fit.modules[self.srcModPosition]
if srcMod.isEmpty:
return False
if srcMod.chargeID is not None:
return self._unloadCharges(fit, srcMod)
else:
return self._moveModulesToCargo(fit, srcMod)
def _getSimilarModulePositions(self, fit, targetMod):
targetItemID = targetMod.itemID
matchingPositions = []
for position, mod in enumerate(fit.modules):
if mod.isEmpty:
continue
if mod.itemID == targetItemID:
matchingPositions.append(position)
return matchingPositions
def _unloadCharges(self, fit, srcMod):
matchingPositions = self._getSimilarModulePositions(fit, srcMod)
if not matchingPositions:
return False
commands = []
for position in matchingPositions:
mod = fit.modules[position]
if mod.isEmpty:
continue
if mod.chargeID is not None:
commands.append(
CalcAddCargoCommand(
fitID=self.fitID,
cargoInfo=CargoInfo(itemID=mod.chargeID, amount=mod.numCharges),
)
)
if not self.copy:
from gui.fitCommands.calc.module.changeCharges import (
CalcChangeModuleChargesCommand,
)
chargeMap = {pos: None for pos in matchingPositions}
commands.append(
CalcChangeModuleChargesCommand(
fitID=self.fitID, projected=False, chargeMap=chargeMap
)
)
success = self.internalHistory.submitBatch(*commands)
if not success:
self.internalHistory.undoAll()
return False
eos.db.flush()
sFit = Fit.getInstance()
sFit.recalc(self.fitID)
self.savedRemovedDummies = sFit.fill(self.fitID)
eos.db.commit()
events = [GE.FitChanged(fitIDs=(self.fitID,))]
for event in events:
wx.PostEvent(gui.mainFrame.MainFrame.getInstance(), event)
return success
def _moveModulesToCargo(self, fit, srcMod):
matchingPositions = self._getSimilarModulePositions(fit, srcMod)
if not matchingPositions:
return False
commands = []
for position in matchingPositions:
mod = fit.modules[position]
if mod.isEmpty:
continue
commands.append(
CalcAddCargoCommand(
fitID=self.fitID,
cargoInfo=CargoInfo(
itemID=ModuleInfo.fromModule(mod, unmutate=True).itemID,
amount=1,
),
)
)
self.removedModItemIDs.append(mod.itemID)
if not self.copy:
commands.append(
CalcRemoveLocalModulesCommand(
fitID=self.fitID, positions=matchingPositions
)
)
success = self.internalHistory.submitBatch(*commands)
if not success:
self.internalHistory.undoAll()
return False
eos.db.flush()
sFit = Fit.getInstance()
sFit.recalc(self.fitID)
self.savedRemovedDummies = sFit.fill(self.fitID)
eos.db.commit()
events = []
for removedModItemID in self.removedModItemIDs:
events.append(
GE.FitChanged(
fitIDs=(self.fitID,), action="moddel", typeID=removedModItemID
)
)
if not events:
events.append(GE.FitChanged(fitIDs=(self.fitID,)))
for event in events:
wx.PostEvent(gui.mainFrame.MainFrame.getInstance(), event)
return success
def Undo(self):
sFit = Fit.getInstance()
fit = sFit.getFit(self.fitID)
restoreRemovedDummies(fit, self.savedRemovedDummies)
success = self.internalHistory.undoAll()
eos.db.flush()
sFit.recalc(self.fitID)
sFit.fill(self.fitID)
eos.db.commit()
events = []
for removedModItemID in self.removedModItemIDs:
events.append(
GE.FitChanged(
fitIDs=(self.fitID,), action="modadd", typeID=removedModItemID
)
)
if not events:
events.append(GE.FitChanged(fitIDs=(self.fitID,)))
for event in events:
wx.PostEvent(gui.mainFrame.MainFrame.getInstance(), event)
return success

View File

@@ -1,326 +0,0 @@
# =============================================================================
# Copyright (C) 2025
#
# This file is part of pyfa.
#
# pyfa is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# pyfa is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# =============================================================================
# noinspection PyPackageRequirements
import wx
from collections import Counter
from eos.const import FittingSlot
from service.fit import Fit as svcFit
from service.port.eft import exportEft, importEft, _importPrepare
from service.const import PortEftOptions
_t = wx.GetTranslation
class FitDiffFrame(wx.Frame):
"""A frame to display differences between two fits."""
def __init__(self, parent, fitID):
super().__init__(
parent,
title=_t("Fit Diff"),
style=wx.DEFAULT_FRAME_STYLE | wx.RESIZE_BORDER,
size=(1000, 600)
)
self.parent = parent
self.fitID = fitID
self.sFit = svcFit.getInstance()
# EFT export options (same as CTRL-C)
self.eftOptions = {
PortEftOptions.LOADED_CHARGES: True,
PortEftOptions.MUTATIONS: True,
PortEftOptions.IMPLANTS: True,
PortEftOptions.BOOSTERS: True,
PortEftOptions.CARGO: True,
}
self.initUI()
self.Centre()
self.Show()
def initUI(self):
panel = wx.Panel(self)
mainSizer = wx.BoxSizer(wx.VERTICAL)
# Instructions and flip button at the top
topSizer = wx.BoxSizer(wx.HORIZONTAL)
instructions = wx.StaticText(
panel,
label=_t("Paste fits in EFT format to compare")
)
topSizer.Add(instructions, 1, wx.ALL | wx.EXPAND, 5)
flipButton = wx.Button(panel, label=_t("Flip"))
flipButton.Bind(wx.EVT_BUTTON, self.onFlip)
topSizer.Add(flipButton, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
mainSizer.Add(topSizer, 0, wx.EXPAND)
# Three panes: Fit 1 | Diff | Fit 2
panesSizer = wx.BoxSizer(wx.HORIZONTAL)
# Pane 1: Fit 1 (editable)
fit1Box = wx.StaticBox(panel, label=_t("Fit 1"))
fit1Sizer = wx.StaticBoxSizer(fit1Box, wx.VERTICAL)
self.fit1Text = wx.TextCtrl(
panel,
style=wx.TE_MULTILINE | wx.TE_DONTWRAP
)
fit1Sizer.Add(self.fit1Text, 1, wx.EXPAND)
panesSizer.Add(fit1Sizer, 1, wx.ALL | wx.EXPAND, 5)
# Bind text changed event to update diff
self.fit1Text.Bind(wx.EVT_TEXT, self.onFitChanged)
# Pane 2: Diff (simple text format)
diffBox = wx.StaticBox(panel, label=_t("Differences"))
diffSizer = wx.StaticBoxSizer(diffBox, wx.VERTICAL)
self.diffText = wx.TextCtrl(
panel,
style=wx.TE_MULTILINE | wx.TE_READONLY | wx.TE_DONTWRAP
)
diffSizer.Add(self.diffText, 1, wx.EXPAND)
panesSizer.Add(diffSizer, 1, wx.ALL | wx.EXPAND, 5)
# Pane 3: Fit 2 (user input)
fit2Box = wx.StaticBox(panel, label=_t("Fit 2"))
fit2Sizer = wx.StaticBoxSizer(fit2Box, wx.VERTICAL)
self.fit2Text = wx.TextCtrl(
panel,
style=wx.TE_MULTILINE | wx.TE_DONTWRAP
)
fit2Sizer.Add(self.fit2Text, 1, wx.EXPAND)
# Bind text changed event to update diff
self.fit2Text.Bind(wx.EVT_TEXT, self.onFitChanged)
panesSizer.Add(fit2Sizer, 1, wx.ALL | wx.EXPAND, 5)
mainSizer.Add(panesSizer, 1, wx.EXPAND | wx.ALL, 5)
panel.SetSizer(mainSizer)
# Load current fit into pane 1
self.loadFit1()
def loadFit1(self):
"""Load the current fit into pane 1 as EFT format."""
fit = self.sFit.getFit(self.fitID)
if fit:
eftText = exportEft(fit, self.eftOptions, callback=None)
self.fit1Text.SetValue(eftText)
def onFitChanged(self, event):
"""Handle text change in either fit pane - update diff."""
self.updateDiff()
event.Skip()
def onFlip(self, event):
"""Swap Fit 1 and Fit 2."""
fit1Value = self.fit1Text.GetValue()
fit2Value = self.fit2Text.GetValue()
self.fit1Text.SetValue(fit2Value)
self.fit2Text.SetValue(fit1Value)
self.updateDiff()
event.Skip()
def updateDiff(self):
"""Calculate and display the differences between the two fits."""
self.diffText.Clear()
fit1Text = self.fit1Text.GetValue().strip()
fit2Text = self.fit2Text.GetValue().strip()
if not fit1Text or not fit2Text:
return
# Parse both fits
fit1 = self.parsePastedFit(fit1Text)
fit2 = self.parsePastedFit(fit2Text)
if fit1 is None:
self.diffText.SetValue(_t("Error: Fit 1 has invalid EFT format"))
return
if fit2 is None:
self.diffText.SetValue(_t("Error: Fit 2 has invalid EFT format"))
return
# Calculate differences and format as simple text list
diffLines = self.calculateDiff(fit1, fit2)
self.diffText.SetValue('\n'.join(diffLines))
def parsePastedFit(self, text):
"""Parse pasted EFT text into a fit object."""
try:
lines = _importPrepare(text.splitlines())
if not lines:
return None
return importEft(lines)
except Exception:
return None
def calculateDiff(self, fit1, fit2):
"""Calculate items needed to transform fit1 into fit2.
Returns a list of strings in the format: "<item> <quantity>"
Only shows items that need to be added (no negative values).
"""
diffLines = []
# Get module counts by type for each fit (grouped by slot type)
fit1_modules = self.getModuleCounts(fit1)
fit2_modules = self.getModuleCounts(fit2)
# Slot order
slotOrder = [
FittingSlot.HIGH,
FittingSlot.MED,
FittingSlot.LOW,
FittingSlot.RIG,
FittingSlot.SUBSYSTEM,
FittingSlot.SERVICE,
]
# Diff modules by slot - only show items needed to add
for slot in slotOrder:
fit1_slot_modules = fit1_modules.get(slot, Counter())
fit2_slot_modules = fit2_modules.get(slot, Counter())
all_module_types = set(fit1_slot_modules.keys()) | set(fit2_slot_modules.keys())
slot_diff_lines = []
for module_type in sorted(all_module_types):
count1 = fit1_slot_modules.get(module_type, 0)
count2 = fit2_slot_modules.get(module_type, 0)
if count2 > count1:
slot_diff_lines.append(f"{module_type} x{count2 - count1}")
if slot_diff_lines:
if diffLines:
diffLines.append("")
diffLines.extend(slot_diff_lines)
# Get drone counts
fit1_drones = self.getDroneCounts(fit1)
fit2_drones = self.getDroneCounts(fit2)
all_drone_types = set(fit1_drones.keys()) | set(fit2_drones.keys())
for drone_type in sorted(all_drone_types):
count1 = fit1_drones.get(drone_type, 0)
count2 = fit2_drones.get(drone_type, 0)
if count2 > count1:
diffLines.append(f"{drone_type} x{count2 - count1}")
# Get fighter counts
fit1_fighters = self.getFighterCounts(fit1)
fit2_fighters = self.getFighterCounts(fit2)
all_fighter_types = set(fit1_fighters.keys()) | set(fit2_fighters.keys())
for fighter_type in sorted(all_fighter_types):
count1 = fit1_fighters.get(fighter_type, 0)
count2 = fit2_fighters.get(fighter_type, 0)
if count2 > count1:
diffLines.append(f"{fighter_type} x{count2 - count1}")
# Get cargo counts
fit1_cargo = self.getCargoCounts(fit1)
fit2_cargo = self.getCargoCounts(fit2)
all_cargo_types = set(fit1_cargo.keys()) | set(fit2_cargo.keys())
for cargo_type in sorted(all_cargo_types):
count1 = fit1_cargo.get(cargo_type, 0)
count2 = fit2_cargo.get(cargo_type, 0)
if count2 > count1:
diffLines.append(f"{cargo_type} x{count2 - count1}")
# Get implants
fit1_implants = self.getImplantNames(fit1)
fit2_implants = self.getImplantNames(fit2)
for implant in sorted(fit2_implants - fit1_implants):
diffLines.append(f"{implant} x1")
# Get boosters
fit1_boosters = self.getBoosterNames(fit1)
fit2_boosters = self.getBoosterNames(fit2)
for booster in sorted(fit2_boosters - fit1_boosters):
diffLines.append(f"{booster} x1")
return diffLines
def getModuleCounts(self, fit):
"""Get a counter of module types for a fit, grouped by slot type.
Returns a dict mapping FittingSlot -> Counter of module names.
Position doesn't matter, just counts by module name.
"""
counts_by_slot = {}
for module in fit.modules:
if module.isEmpty:
continue
slot = module.slot
if slot not in counts_by_slot:
counts_by_slot[slot] = Counter()
# Use item type name for comparison
name = module.item.typeName if module.item else ""
counts_by_slot[slot][name] += 1
return counts_by_slot
def getDroneCounts(self, fit):
"""Get a counter of drone types for a fit."""
counts = Counter()
for drone in fit.drones:
if drone.item:
counts[drone.item.typeName] += drone.amount
return counts
def getFighterCounts(self, fit):
"""Get a counter of fighter types for a fit."""
counts = Counter()
for fighter in fit.fighters:
if fighter.item:
counts[fighter.item.typeName] += fighter.amount
return counts
def getCargoCounts(self, fit):
"""Get a counter of cargo items for a fit."""
counts = Counter()
for cargo in fit.cargo:
if cargo.item:
counts[cargo.item.typeName] += cargo.amount
return counts
def getImplantNames(self, fit):
"""Get a set of implant names for a fit."""
names = set()
for implant in fit.implants:
if implant.item:
names.add(implant.item.typeName)
return names
def getBoosterNames(self, fit):
"""Get a set of booster names for a fit."""
names = set()
for booster in fit.boosters:
if booster.item:
names.add(booster.item.typeName)
return names

View File

@@ -24,7 +24,6 @@ import config
import gui.mainFrame
from eos.saveddata.drone import Drone
from eos.saveddata.module import Module
from eos.saveddata.ship import Ship
from gui.auxWindow import AuxiliaryFrame
from gui.bitmap_loader import BitmapLoader
from gui.builtinItemStatsViews.itemAffectedBy import ItemAffectedBy
@@ -36,7 +35,6 @@ from gui.builtinItemStatsViews.itemEffects import ItemEffects
from gui.builtinItemStatsViews.itemMutator import ItemMutatorPanel
from gui.builtinItemStatsViews.itemProperties import ItemProperties
from gui.builtinItemStatsViews.itemRequirements import ItemRequirements
from gui.builtinItemStatsViews.itemSkills import ItemSkills
from gui.builtinItemStatsViews.itemTraits import ItemTraits
from service.market import Market
@@ -158,8 +156,6 @@ class ItemStatsContainer(wx.Panel):
def __init__(self, parent, stuff, item, context=None):
wx.Panel.__init__(self, parent)
sMkt = Market.getInstance()
self.stuff = stuff
self.context = context
mainSizer = wx.BoxSizer(wx.VERTICAL)
@@ -200,10 +196,6 @@ class ItemStatsContainer(wx.Panel):
self.affectedby = ItemAffectedBy(self.nbContainer, stuff, item)
self.nbContainer.AddPage(self.affectedby, _t("Affected by"))
if stuff is not None and isinstance(stuff, Ship):
self.skills = ItemSkills(self.nbContainer, stuff, item)
self.nbContainer.AddPage(self.skills, _t("Skills"))
if config.debug:
self.properties = ItemProperties(self.nbContainer, stuff, item, context)
self.nbContainer.AddPage(self.properties, _t("Properties"))

View File

@@ -18,7 +18,6 @@
# =============================================================================
import datetime
import itertools
import os.path
import threading
import time
@@ -61,12 +60,8 @@ from gui.shipBrowser import ShipBrowser
from gui.statsPane import StatsPane
from gui.targetProfileEditor import TargetProfileEditor
from gui.updateDialog import UpdateDialog
from gui.utils.clipboard import fromClipboard, toClipboard
from gui.utils.clipboard import fromClipboard
from gui.utils.progressHelper import ProgressHelper
from eos.const import FittingSlot as es_Slot
from eos.saveddata.character import Skill
from eos.saveddata.fighter import Fighter as es_Fighter
from eos.saveddata.module import Module as es_Module
from service.character import Character
from service.esi import Esi
from service.fit import Fit
@@ -527,8 +522,6 @@ class MainFrame(wx.Frame):
self.Bind(wx.EVT_MENU, self.backupToXml, id=menuBar.backupFitsId)
# Export skills needed
self.Bind(wx.EVT_MENU, self.exportSkillsNeeded, id=menuBar.exportSkillsNeededId)
# Copy skills needed
self.Bind(wx.EVT_MENU, self.copySkillsNeeded, id=menuBar.copySkillsNeededId)
# Import character
self.Bind(wx.EVT_MENU, self.importCharacter, id=menuBar.importCharacterId)
# Export HTML
@@ -565,8 +558,7 @@ class MainFrame(wx.Frame):
self.Bind(wx.EVT_MENU, self.toggleOverrides, id=menuBar.toggleOverridesId)
# Clipboard exports
self.Bind(wx.EVT_MENU, self.exportToClipboardDirectEft, id=menuBar.copyDirectEftId)
self.Bind(wx.EVT_MENU, self.exportToClipboard, id=menuBar.copyWithDialogId)
self.Bind(wx.EVT_MENU, self.exportToClipboard, id=wx.ID_COPY)
# Fitting Restrictions
self.Bind(wx.EVT_MENU, self.toggleIgnoreRestriction, id=menuBar.toggleIgnoreRestrictionID)
@@ -579,7 +571,6 @@ class MainFrame(wx.Frame):
toggleShipMarketId = wx.NewId()
ctabnext = wx.NewId()
ctabprev = wx.NewId()
charPrevId = wx.NewId()
# Close Page
self.Bind(wx.EVT_MENU, self.CloseCurrentPage, id=self.closePageId)
@@ -589,7 +580,6 @@ class MainFrame(wx.Frame):
self.Bind(wx.EVT_MENU, self.toggleShipMarket, id=toggleShipMarketId)
self.Bind(wx.EVT_MENU, self.CTabNext, id=ctabnext)
self.Bind(wx.EVT_MENU, self.CTabPrev, id=ctabprev)
self.Bind(wx.EVT_MENU, self.selectPreviousCharacter, id=charPrevId)
actb = [(wx.ACCEL_CTRL, ord('T'), self.addPageId),
(wx.ACCEL_CMD, ord('T'), self.addPageId),
@@ -623,19 +613,7 @@ class MainFrame(wx.Frame):
(wx.ACCEL_CMD, wx.WXK_PAGEDOWN, ctabnext),
(wx.ACCEL_CMD, wx.WXK_PAGEUP, ctabprev),
(wx.ACCEL_CMD | wx.ACCEL_SHIFT, ord("Z"), wx.ID_REDO),
# Ctrl+Shift+C for copy with dialog (must come before Ctrl+C)
# Note: use lowercase 'c' because SHIFT is already in flags
(wx.ACCEL_CTRL | wx.ACCEL_SHIFT, ord('c'), menuBar.copyWithDialogId),
(wx.ACCEL_CMD | wx.ACCEL_SHIFT, ord('c'), menuBar.copyWithDialogId),
# Ctrl+C for direct EFT copy
(wx.ACCEL_CTRL, ord('c'), menuBar.copyDirectEftId),
(wx.ACCEL_CMD, ord('c'), menuBar.copyDirectEftId),
# Shift+Tab for previous character
(wx.ACCEL_SHIFT, wx.WXK_TAB, charPrevId)
(wx.ACCEL_CMD | wx.ACCEL_SHIFT, ord("Z"), wx.ID_REDO)
]
# Ctrl/Cmd+# for addition pane selection
@@ -761,9 +739,6 @@ class MainFrame(wx.Frame):
def CTabPrev(self, event):
self.fitMultiSwitch.PrevPage()
def selectPreviousCharacter(self, event):
self.charSelection.selectPreviousChar()
def HAddPage(self, event):
self.fitMultiSwitch.AddPage()
@@ -823,32 +798,6 @@ class MainFrame(wx.Frame):
else:
self._openAfterImport(importData)
def exportToClipboardDirectEft(self, event):
""" Copy fit to clipboard in EFT format without showing dialog """
from eos.db import getFit
from service.const import PortEftOptions
from service.settings import SettingsProvider
fit = getFit(self.getActiveFit())
if fit is None:
return
# Get the default EFT export options from settings
defaultOptions = {
PortEftOptions.LOADED_CHARGES: True,
PortEftOptions.MUTATIONS: True,
PortEftOptions.IMPLANTS: True,
PortEftOptions.BOOSTERS: True,
PortEftOptions.CARGO: True,
}
settings = SettingsProvider.getInstance().getSettings("pyfaExport", {"format": CopySelectDialog.copyFormatEft, "options": {CopySelectDialog.copyFormatEft: defaultOptions}})
options = settings["options"].get(CopySelectDialog.copyFormatEft, defaultOptions)
def copyToClipboard(text):
toClipboard(text)
Port.exportEft(fit, options, callback=copyToClipboard)
def exportToClipboard(self, event):
with CopySelectDialog(self) as dlg:
dlg.ShowModal()
@@ -883,61 +832,6 @@ class MainFrame(wx.Frame):
self.waitDialog = wx.BusyInfo(_t("Exporting skills needed..."), parent=self)
sCharacter.backupSkills(filePath, saveFmt, self.getActiveFit(), self.closeWaitDialog)
def copySkillsNeeded(self, event):
""" Copies skills used by the fit that the character has to clipboard """
activeFitID = self.getActiveFit()
if activeFitID is None:
return
sFit = Fit.getInstance()
fit = sFit.getFit(activeFitID)
if fit is None:
return
if not fit.calculated:
fit.calculate()
char = fit.character
skillsMap = {}
# for thing in itertools.chain(fit.modules, fit.drones, fit.fighters, [fit.ship], fit.appliedImplants, fit.boosters, fit.cargo):
for thing in itertools.chain(fit.modules, fit.drones, fit.fighters, fit.appliedImplants, fit.boosters, fit.cargo):
self._collectAffectingSkills(thing, char, skillsMap)
skillsList = ""
for skillName in sorted(skillsMap):
charLevel = skillsMap[skillName]
for level in range(1, charLevel + 1):
skillsList += "%s %d\n" % (skillName, level)
toClipboard(skillsList)
def _collectAffectingSkills(self, thing, char, skillsMap):
""" Collect skills that affect items in the fit that the character has """
for attr in ("item", "charge"):
if attr == "charge" and isinstance(thing, es_Fighter):
continue
subThing = getattr(thing, attr, None)
if subThing is None:
continue
if isinstance(thing, es_Fighter) and attr == "charge":
continue
if attr == "charge":
cont = getattr(thing, "chargeModifiedAttributes", None)
else:
cont = getattr(thing, "itemModifiedAttributes", None)
if cont is not None:
for attrName in cont.iterAfflictions():
for fit, afflictors in cont.getAfflictions(attrName).items():
for afflictor, operator, stackingGroup, preResAmount, postResAmount, used in afflictors:
if isinstance(afflictor, Skill) and afflictor.character == char:
skillName = afflictor.item.name
if skillName not in skillsMap:
skillsMap[skillName] = afflictor.level
elif skillsMap[skillName] < afflictor.level:
skillsMap[skillName] = afflictor.level
def fileImportDialog(self, event):
"""Handles importing single/multiple EVE XML / EFT cfg fit files"""
with wx.FileDialog(

View File

@@ -42,7 +42,6 @@ class MainMenuBar(wx.MenuBar):
self.graphFrameId = wx.NewId()
self.backupFitsId = wx.NewId()
self.exportSkillsNeededId = wx.NewId()
self.copySkillsNeededId = wx.NewId()
self.importCharacterId = wx.NewId()
self.exportHtmlId = wx.NewId()
self.wikiId = wx.NewId()
@@ -58,8 +57,6 @@ class MainMenuBar(wx.MenuBar):
self.toggleIgnoreRestrictionID = wx.NewId()
self.devToolsId = wx.NewId()
self.optimizeFitPrice = wx.NewId()
self.copyWithDialogId = wx.NewId()
self.copyDirectEftId = wx.NewId()
self.mainFrame = mainFrame
wx.MenuBar.__init__(self)
@@ -87,8 +84,7 @@ class MainMenuBar(wx.MenuBar):
fitMenu.Append(wx.ID_REDO, _t("&Redo") + "\tCTRL+Y", _t("Redo the most recent undone action"))
fitMenu.AppendSeparator()
fitMenu.Append(self.copyDirectEftId, _t("&To Clipboard (EFT)") + "\tCTRL+C", _t("Export a fit to the clipboard in EFT format"))
fitMenu.Append(self.copyWithDialogId, _t("&To Clipboard (Select Format)") + "\tCTRL+SHIFT+C", _t("Export a fit to the clipboard with format selection"))
fitMenu.Append(wx.ID_COPY, _t("&To Clipboard") + "\tCTRL+C", _t("Export a fit to the clipboard"))
fitMenu.Append(wx.ID_PASTE, _t("&From Clipboard") + "\tCTRL+V", _t("Import a fit from the clipboard"))
fitMenu.AppendSeparator()
@@ -121,7 +117,6 @@ class MainMenuBar(wx.MenuBar):
characterMenu.AppendSeparator()
characterMenu.Append(self.importCharacterId, _t("&Import Character File"), _t("Import characters into pyfa from file"))
characterMenu.Append(self.exportSkillsNeededId, _t("&Export Skills Needed"), _t("Export skills needed for this fitting"))
characterMenu.Append(self.copySkillsNeededId, _t("&Copy Skills Needed"), _t("Copy skills needed for this fitting to clipboard"))
characterMenu.AppendSeparator()
characterMenu.Append(self.ssoLoginId, _t("&Manage ESI Characters"))
@@ -181,10 +176,8 @@ class MainMenuBar(wx.MenuBar):
return
enable = activeFitID is not None
self.Enable(wx.ID_SAVEAS, enable)
self.Enable(self.copyDirectEftId, enable)
self.Enable(self.copyWithDialogId, enable)
self.Enable(wx.ID_COPY, enable)
self.Enable(self.exportSkillsNeededId, enable)
self.Enable(self.copySkillsNeededId, enable)
self.refreshUndo()

View File

@@ -54,7 +54,6 @@ class MarketBrowser(wx.Panel):
self.settings = MarketPriceSettings.getInstance()
self.__mode = 'normal'
self.__normalBtnMap = {}
self.__normalSlotBtnMap = {}
self.marketView = MarketTree(self.splitter, self)
self.itemView = ItemView(self.splitter, self)
@@ -65,61 +64,22 @@ class MarketBrowser(wx.Panel):
# Same fix as for search box on macs,
# need some pixels of extra space or everything clips and is ugly
p = wx.Panel(self)
vbox_panel = wx.BoxSizer(wx.VERTICAL)
p.SetSizer(vbox_panel)
box = wx.BoxSizer(wx.HORIZONTAL)
p.SetSizer(box)
vbox.Add(p, 0, wx.EXPAND)
# First row: meta buttons
metaBox = wx.BoxSizer(wx.HORIZONTAL)
vbox_panel.Add(metaBox, 0, wx.EXPAND)
self.metaButtons = []
btn = None
for name in list(self.sMkt.META_MAP.keys()):
btn = MetaButton(p, wx.ID_ANY, name.capitalize(), style=wx.BU_EXACTFIT)
setattr(self, name, btn)
metaBox.Add(btn, 1, wx.ALIGN_CENTER)
box.Add(btn, 1, wx.ALIGN_CENTER)
btn.Bind(wx.EVT_TOGGLEBUTTON, self.toggleMetaButton)
btn.metaName = name
self.metaButtons.append(btn)
# Second row: slot/fits filter buttons (BELOW meta buttons)
slotBox = wx.BoxSizer(wx.HORIZONTAL)
vbox_panel.Add(slotBox, 0, wx.EXPAND)
self.slotButtons = []
from eos.const import FittingSlot
# Fits button
fitsBtn = MetaButton(p, wx.ID_ANY, "Fits", style=wx.BU_EXACTFIT)
setattr(self, "fits", fitsBtn)
slotBox.Add(fitsBtn, 1, wx.ALIGN_CENTER)
fitsBtn.Bind(wx.EVT_TOGGLEBUTTON, self.toggleSlotButton)
fitsBtn.filterType = "fits"
# Fits button starts deselected (checkbox, off by default)
fitsBtn.setUserSelection(False)
self.slotButtons.append(fitsBtn)
# High, Med, Low, Rig buttons
slotMap = {
FittingSlot.HIGH: "High",
FittingSlot.MED: "Med",
FittingSlot.LOW: "Low",
FittingSlot.RIG: "Rig"
}
for slot, label in slotMap.items():
slotBtn = MetaButton(p, wx.ID_ANY, label, style=wx.BU_EXACTFIT)
setattr(self, "slot_%s" % label.lower(), slotBtn)
slotBox.Add(slotBtn, 1, wx.ALIGN_CENTER)
slotBtn.Bind(wx.EVT_TOGGLEBUTTON, self.toggleSlotButton)
slotBtn.filterType = "slot"
slotBtn.slotType = slot
# Slot buttons start deselected (unlike meta buttons which start selected)
slotBtn.setUserSelection(False)
self.slotButtons.append(slotBtn)
# Make itemview to set toggles according to list contents
self.itemView.setToggles()
p.SetMinSize((wx.SIZE_AUTO_WIDTH, btn.GetSize()[1] * 2 + 10))
p.SetMinSize((wx.SIZE_AUTO_WIDTH, btn.GetSize()[1] + 5))
def toggleMetaButton(self, event):
"""Process clicks on toggle buttons"""
@@ -140,21 +100,6 @@ class MarketBrowser(wx.Panel):
self.itemView.filterItemStore()
def toggleSlotButton(self, event):
"""Process clicks on slot/fits filter buttons"""
clickedBtn = event.EventObject
# All buttons (Fits, High, Med, Low, Rig) work as checkboxes (independent toggles)
clickedBtn.setUserSelection(clickedBtn.GetValue())
self.itemView.filterItemStore()
def getFitsFilter(self):
"""Check if Fits button is active"""
for btn in self.slotButtons:
if btn.filterType == "fits" and btn.userSelected:
return True
return False
def jump(self, item):
self.mode = 'normal'
self.marketView.jump(item)
@@ -196,9 +141,6 @@ class MarketBrowser(wx.Panel):
self.__normalBtnMap.clear()
for btn in self.metaButtons:
self.__normalBtnMap[btn] = btn.userSelected
self.__normalSlotBtnMap.clear()
for btn in self.slotButtons:
self.__normalSlotBtnMap[btn] = btn.userSelected
if newMode == 'search':
self.marketView.UnselectAll()
setting = self.settings.get('marketMGSearchMode')
@@ -207,16 +149,12 @@ class MarketBrowser(wx.Panel):
if newMode in ('search', 'recent', 'charges'):
for btn in self.metaButtons:
btn.setUserSelection(True)
# Clear slot button selections when searching (search can return any item type)
for btn in self.slotButtons:
btn.setUserSelection(False)
if newMode == 'normal':
for btn, state in self.__normalBtnMap.items():
btn.setUserSelection(state)
for btn, state in self.__normalSlotBtnMap.items():
btn.setUserSelection(state)
# We turn on all meta buttons permanently
if setting == 2:
for btn in self.metaButtons:
btn.setUserSelection(True)
self.__mode = newMode

View File

@@ -77,14 +77,6 @@ msgstr ""
msgid "&Export Skills Needed"
msgstr ""
#: gui/mainMenuBar.py:120
msgid "&Copy Skills Needed"
msgstr ""
#: gui/mainMenuBar.py:120
msgid "Copy skills needed for this fitting to clipboard"
msgstr ""
#: gui/mainMenuBar.py:66 gui/propertyEditor.py:42
msgid "&File"
msgstr ""

BIN
oleacc.dll LFS

Binary file not shown.

View File

@@ -1,28 +0,0 @@
;
; Pyfa mod Darkmode settings
;
; ActiveThemePalette [OPTIONAL, Boolean, Default=1]
; Indicate which of the available color themes to use. (ex. "ActiveThemePalette = 3" to use the LicoriceBlue color theme)
; Available color themes: 1 = BlackBeauty, 2 = Licorice, 3 = LicoriceBlue, 4 = BlackBeauty
;
; OverrideThemePalette [OPTIONAL, Comma separated string]
; Specify a string of (5) comma separated RGB hex colors to use as theme palette, ordered from darkest to lightest.
; Valid RGB hex format prefix are #, 0x or nothing.
; (ex. OverrideThemePalette = #521ecc, #e68ca1, #1a2070, #a85294, #aaccb5)
;
; EnableCustomControls[OPTIONAL, Boolean, Default = true]
; Indicates if the standard windows controls will be colored by the active theme palette.
;
; UseExperimentalDarkmode [OPTIONAL, Boolean, Default = true]
; Implementation of some undocumented windows api call, to force certain apps into a darkmode state.
;
; EnableLogging [OPTIONAL, Boolean, Default = false]
; Write log output to a .log file.
;
[settings]
ActiveThemePalette = 1
OverrideThemePalette = #521ecc, #EE3460, #1a2070, #a85294, #aaccb5
EnableCustomControls = true
UseExperimentalDarkmode = true
EnableLogging = false

View File

@@ -1,24 +0,0 @@
[project]
name = "pyfa"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"beautifulsoup4==4.12.2",
"cryptography==42.0.4",
"logbook==1.7.0.post0",
"markdown2==2.4.11",
"matplotlib==3.8.2",
"numpy==1.26.2",
"packaging==23.2",
"python-dateutil==2.8.2",
"python-jose==3.3.0",
"pyyaml==6.0.1",
"requests==2.31.0",
"requests-cache==1.1.1",
"roman==4.1",
"ruff>=0.14.8",
"sqlalchemy==1.4.50",
"wxpython==4.2.1",
]

View File

@@ -1,60 +0,0 @@
#!/bin/bash
set -e
echo "Figuring out the tag..."
TAG=$(git describe --tags --exact-match 2>/dev/null || echo "")
if [ -z "$TAG" ]; then
# Get the latest tag
LATEST_TAG=$(git describe --tags $(git rev-list --tags --max-count=1) 2>/dev/null || echo "v0.0.0")
# Remove 'v' prefix if present
LATEST_TAG=${LATEST_TAG#v}
# Increment the patch version
IFS='.' read -r -a VERSION_PARTS <<< "$LATEST_TAG"
VERSION_PARTS[2]=$((VERSION_PARTS[2]+1))
TAG="v${VERSION_PARTS[0]}.${VERSION_PARTS[1]}.${VERSION_PARTS[2]}"
# Create a new tag
git tag $TAG
git push origin $TAG
fi
echo "Tag: $TAG"
echo "Building the binary..."
./build.sh
echo "Creating release zip..."
ZIP="pyfa-${TAG}-win.zip"
7z a "${ZIP}" dist/pyfa/*
echo "Creating a release..."
TOKEN="$GITEA_API_KEY"
GITEA="https://git.site.quack-lab.dev"
REPO="dave/pyfa"
# Create a release
RELEASE_RESPONSE=$(curl -s -X POST \
-H "Authorization: token $TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"tag_name": "'"$TAG"'",
"name": "'"$TAG"'",
"draft": false,
"prerelease": false
}' \
$GITEA/api/v1/repos/$REPO/releases)
# Extract the release ID
echo $RELEASE_RESPONSE
RELEASE_ID=$(echo $RELEASE_RESPONSE | awk -F'"id":' '{print $2+0; exit}')
echo "Release ID: $RELEASE_ID"
echo "Uploading the zip..."
curl -X POST \
-H "Authorization: token $TOKEN" \
-F "attachment=@${ZIP}" \
"$GITEA/api/v1/repos/$REPO/releases/${RELEASE_ID}/assets?name=${ZIP}"
rm "${ZIP}"
echo "Release complete! ${ZIP} uploaded to ${TAG}"

View File

@@ -49213,5 +49213,74 @@
"name": "shipRoleBonusPerseveranceIceMiningCriticalHitChance",
"published": 0,
"stackable": 1
},
"6067": {
"attributeID": 6067,
"categoryID": 9,
"dataType": 5,
"defaultValue": 5.0,
"description": "",
"displayWhenZero": 0,
"highIsGood": 1,
"name": "shipBonus1AF",
"published": 0,
"stackable": 1
},
"6078": {
"attributeID": 6078,
"categoryID": 30,
"dataType": 5,
"defaultValue": 0.0,
"description": "Increase in Light Missile velocity",
"displayWhenZero": 0,
"highIsGood": 0,
"name": "modeLightMissileMaxVelocityBonusPostDivSkua",
"published": 0,
"stackable": 1
},
"6079": {
"attributeID": 6079,
"categoryID": 30,
"dataType": 5,
"defaultValue": 0.0,
"description": "Increase in Rocket velocity",
"displayWhenZero": 0,
"highIsGood": 0,
"name": "modeRocketMissileMaxVelocityBonusPostDivSkua",
"published": 0,
"stackable": 1
},
"6080": {
"attributeID": 6080,
"categoryID": 30,
"dataType": 5,
"defaultValue": 0.0,
"displayWhenZero": 0,
"highIsGood": 0,
"name": "modeAnhingaMissileFlightTimePostDiv",
"published": 0,
"stackable": 1
},
"6081": {
"attributeID": 6081,
"categoryID": 30,
"dataType": 5,
"defaultValue": 0.0,
"displayWhenZero": 0,
"highIsGood": 0,
"name": "modeAnhingaMissileMaxVelocityPostDiv",
"published": 0,
"stackable": 1
},
"6082": {
"attributeID": 6082,
"categoryID": 30,
"dataType": 5,
"defaultValue": 0.0,
"displayWhenZero": 0,
"highIsGood": 0,
"name": "modeAnhingaCruiseLauncherTorpedoLauncherRapidHeavyLauncherROFPostDiv",
"published": 0,
"stackable": 1
}
}

View File

@@ -99671,15 +99671,15 @@
"rangeChance": 0
},
"12758": {
"description_de": "Automatically generated effect",
"description_de": "Automatisch erzeugter Effekt",
"description_en-us": "Automatically generated effect",
"description_es": "Automatically generated effect",
"description_fr": "Automatically generated effect",
"description_es": "Efecto generado automáticamente.",
"description_fr": "Effet généré automatiquement",
"description_it": "Automatically generated effect",
"description_ja": "Automatically generated effect",
"description_ko": "Automatically generated effect",
"description_ru": "Automatically generated effect",
"description_zh": "Automatically generated effect",
"description_ja": "自動生成効果",
"description_ko": "자동 생성 효과",
"description_ru": "Автоматически созданный эффект",
"description_zh": "自动生成效果",
"descriptionID": 1022818,
"disallowAutoRepeat": 0,
"effectCategory": 0,
@@ -100069,6 +100069,30 @@
"published": 0,
"rangeChance": 0
},
"12781": {
"disallowAutoRepeat": 0,
"effectCategory": 0,
"effectID": 12781,
"effectName": "shipETOptimalRange1AF",
"electronicChance": 0,
"isAssistance": 0,
"isOffensive": 0,
"isWarpSafe": 0,
"modifierInfo": [
{
"domain": "shipID",
"func": "LocationRequiredSkillModifier",
"modifiedAttributeID": 54,
"modifyingAttributeID": 464,
"operation": 6,
"skillTypeID": 3303
}
],
"propulsionChance": 0,
"published": 0,
"rangeAttributeID": 54,
"rangeChance": 0
},
"12790": {
"disallowAutoRepeat": 0,
"effectCategory": 0,
@@ -100100,5 +100124,183 @@
"published": 0,
"rangeAttributeID": 54,
"rangeChance": 0
},
"12794": {
"disallowAutoRepeat": 0,
"effectCategory": 0,
"effectID": 12794,
"effectName": "shipRocketMaxVelocityBonusPostDivSkua",
"electronicChance": 0,
"isAssistance": 0,
"isOffensive": 0,
"isWarpSafe": 0,
"modifierInfo": [
{
"domain": "charID",
"func": "OwnerRequiredSkillModifier",
"modifiedAttributeID": 37,
"modifyingAttributeID": 6079,
"operation": 5,
"skillTypeID": 3320
}
],
"propulsionChance": 0,
"published": 0,
"rangeChance": 0
},
"12795": {
"disallowAutoRepeat": 0,
"effectCategory": 0,
"effectID": 12795,
"effectName": "shipLightMissileMaxVelocityBonusPostDivSkua",
"electronicChance": 0,
"isAssistance": 0,
"isOffensive": 0,
"isWarpSafe": 0,
"modifierInfo": [
{
"domain": "charID",
"func": "OwnerRequiredSkillModifier",
"modifiedAttributeID": 37,
"modifyingAttributeID": 6078,
"operation": 5,
"skillTypeID": 3321
}
],
"propulsionChance": 0,
"published": 0,
"rangeAttributeID": 54,
"rangeChance": 0
},
"12796": {
"disallowAutoRepeat": 0,
"effectCategory": 0,
"effectID": 12796,
"effectName": "shipModeMissileFlightTimePostDiv",
"electronicChance": 0,
"isAssistance": 0,
"isOffensive": 0,
"isWarpSafe": 0,
"modifierInfo": [
{
"domain": "charID",
"func": "OwnerRequiredSkillModifier",
"modifiedAttributeID": 281,
"modifyingAttributeID": 6080,
"operation": 5,
"skillTypeID": 3319
}
],
"propulsionChance": 0,
"published": 0,
"rangeChance": 0
},
"12798": {
"disallowAutoRepeat": 0,
"effectCategory": 0,
"effectID": 12798,
"effectName": "shipModeMissileVelocityPostDiv",
"electronicChance": 0,
"isAssistance": 0,
"isOffensive": 0,
"isWarpSafe": 0,
"modifierInfo": [
{
"domain": "charID",
"func": "OwnerRequiredSkillModifier",
"modifiedAttributeID": 37,
"modifyingAttributeID": 6081,
"operation": 5,
"skillTypeID": 3319
}
],
"propulsionChance": 0,
"published": 0,
"rangeChance": 0
},
"12799": {
"disallowAutoRepeat": 0,
"effectCategory": 0,
"effectID": 12799,
"effectName": "shipModeAnhingaCruiseLauncherTorpedoLauncherRapidHeavyLauncherROFPostDiv",
"electronicChance": 0,
"isAssistance": 0,
"isOffensive": 0,
"isWarpSafe": 0,
"modifierInfo": [
{
"domain": "shipID",
"func": "LocationGroupModifier",
"groupID": 506,
"modifiedAttributeID": 51,
"modifyingAttributeID": 6082,
"operation": 5
},
{
"domain": "shipID",
"func": "LocationGroupModifier",
"groupID": 1245,
"modifiedAttributeID": 51,
"modifyingAttributeID": 6082,
"operation": 5
},
{
"domain": "shipID",
"func": "LocationGroupModifier",
"groupID": 508,
"modifiedAttributeID": 51,
"modifyingAttributeID": 6082,
"operation": 5
}
],
"propulsionChance": 0,
"published": 0,
"rangeChance": 0
},
"12801": {
"disallowAutoRepeat": 0,
"effectCategory": 0,
"effectID": 12801,
"effectName": "miningAmountMultiplierSkillBonusPreMul",
"electronicChance": 0,
"isAssistance": 0,
"isOffensive": 0,
"isWarpSafe": 0,
"modifierInfo": [
{
"domain": "itemID",
"func": "ItemModifier",
"modifiedAttributeID": 434,
"modifyingAttributeID": 280,
"operation": 0
}
],
"propulsionChance": 0,
"published": 0,
"rangeAttributeID": 54,
"rangeChance": 0
},
"12802": {
"disallowAutoRepeat": 0,
"effectCategory": 0,
"effectID": 12802,
"effectName": "MutatedMiningDroneOperationMiningAmountBonusPostPercentMiningDroneAmountPercentChar",
"electronicChance": 0,
"isAssistance": 0,
"isOffensive": 0,
"isWarpSafe": 0,
"modifierInfo": [
{
"domain": "charID",
"func": "OwnerRequiredSkillModifier",
"modifiedAttributeID": 77,
"modifyingAttributeID": 434,
"operation": 6,
"skillTypeID": 60515
}
],
"propulsionChance": 0,
"published": 0,
"rangeChance": 0
}
}

View File

@@ -825910,7 +825910,7 @@
},
{
"attributeID": 11,
"value": 44.0
"value": 50.0
},
{
"attributeID": 12,
@@ -825958,7 +825958,7 @@
},
{
"attributeID": 76,
"value": 32000.0
"value": 40000.0
},
{
"attributeID": 79,
@@ -826100,17 +826100,13 @@
"attributeID": 422,
"value": 1.0
},
{
"attributeID": 464,
"value": 7.5
},
{
"attributeID": 479,
"value": 625000.0
},
{
"attributeID": 482,
"value": 450.0
"value": 525.0
},
{
"attributeID": 484,
@@ -826240,6 +826236,10 @@
"attributeID": 1768,
"value": 11349.0
},
{
"attributeID": 1822,
"value": -50.0
},
{
"attributeID": 2045,
"value": 1.0
@@ -826270,6 +826270,10 @@
"effectID": 3489,
"isDefault": 0
},
{
"effectID": 4990,
"isDefault": 0
},
{
"effectID": 5813,
"isDefault": 0

View File

@@ -123141,6 +123141,10 @@
"attributeID": 479,
"value": 1250000.0
},
{
"attributeID": 481,
"value": 0.0
},
{
"attributeID": 482,
"value": 1800.0
@@ -306148,6 +306152,14 @@
{
"effectID": 1730,
"isDefault": 0
},
{
"effectID": 12801,
"isDefault": 0
},
{
"effectID": 12802,
"isDefault": 0
}
]
},
@@ -325618,6 +325630,10 @@
{
"attributeID": 2711,
"value": 46677.0
},
{
"attributeID": 3236,
"value": 0.0
}
],
"dogmaEffects": []
@@ -627622,11 +627638,11 @@
},
{
"attributeID": 1261,
"value": 0.76
"value": 0.79
},
{
"attributeID": 1262,
"value": 0.5
"value": 0.63
},
{
"attributeID": 1271,
@@ -628000,11 +628016,11 @@
},
{
"attributeID": 1259,
"value": 0.76
"value": 0.79
},
{
"attributeID": 1261,
"value": 0.71
"value": 0.76
},
{
"attributeID": 1262,
@@ -630860,22 +630876,10 @@
"attributeID": 422,
"value": 1.0
},
{
"attributeID": 501,
"value": -25.0
},
{
"attributeID": 633,
"value": 0.0
},
{
"attributeID": 793,
"value": -33.3
},
{
"attributeID": 1688,
"value": 1000.0
},
{
"attributeID": 1991,
"value": 0.2
@@ -630899,32 +630903,36 @@
{
"attributeID": 2001,
"value": 1.5
},
{
"attributeID": 6080,
"value": 0.0909
},
{
"attributeID": 6081,
"value": 1.5
},
{
"attributeID": 6082,
"value": 1.333
}
],
"dogmaEffects": [
{
"effectID": 1230,
"isDefault": 0
},
{
"effectID": 1885,
"isDefault": 0
},
{
"effectID": 1886,
"isDefault": 0
},
{
"effectID": 5618,
"isDefault": 0
},
{
"effectID": 5867,
"isDefault": 0
},
{
"effectID": 6010,
"isDefault": 0
},
{
"effectID": 12796,
"isDefault": 0
},
{
"effectID": 12798,
"isDefault": 0
},
{
"effectID": 12799,
"isDefault": 0
}
]
},
@@ -630972,42 +630980,26 @@
"attributeID": 422,
"value": 1.0
},
{
"attributeID": 501,
"value": -50.0
},
{
"attributeID": 633,
"value": 0.0
},
{
"attributeID": 1688,
"value": -50.0
"attributeID": 6080,
"value": 2.0
},
{
"attributeID": 2002,
"value": 3.0
},
{
"attributeID": 2003,
"value": 0.75
"attributeID": 6082,
"value": 2.0
}
],
"dogmaEffects": [
{
"effectID": 1885,
"effectID": 12796,
"isDefault": 0
},
{
"effectID": 1886,
"isDefault": 0
},
{
"effectID": 5618,
"isDefault": 0
},
{
"effectID": 5867,
"effectID": 12799,
"isDefault": 0
}
]
@@ -631026,14 +631018,6 @@
"attributeID": 633,
"value": 0.0
},
{
"attributeID": 1862,
"value": 66.6
},
{
"attributeID": 1863,
"value": 250.0
},
{
"attributeID": 1990,
"value": 0.6
@@ -631053,17 +631037,17 @@
{
"attributeID": 2590,
"value": 3.0
},
{
"attributeID": 6078,
"value": 0.6
},
{
"attributeID": 6079,
"value": 0.2857
}
],
"dogmaEffects": [
{
"effectID": 5213,
"isDefault": 0
},
{
"effectID": 5214,
"isDefault": 0
},
{
"effectID": 6010,
"isDefault": 0
@@ -631079,6 +631063,14 @@
{
"effectID": 6800,
"isDefault": 0
},
{
"effectID": 12794,
"isDefault": 0
},
{
"effectID": 12795,
"isDefault": 0
}
]
},
@@ -631092,78 +631084,42 @@
"attributeID": 422,
"value": 1.0
},
{
"attributeID": 501,
"value": -25.0
},
{
"attributeID": 598,
"value": 50.0
},
{
"attributeID": 633,
"value": 0.0
},
{
"attributeID": 657,
"value": 50.0
},
{
"attributeID": 811,
"value": -25.0
},
{
"attributeID": 1923,
"value": -90.0
},
{
"attributeID": 1990,
"value": 0.6
"attributeID": 2002,
"value": 1.333
},
{
"attributeID": 1991,
"value": 0.5
"attributeID": 6081,
"value": 0.667
},
{
"attributeID": 1995,
"value": 0.5
},
{
"attributeID": 2589,
"value": 0.75
"attributeID": 6082,
"value": 1.333
}
],
"dogmaEffects": [
{
"effectID": 891,
"isDefault": 0
},
{
"effectID": 892,
"isDefault": 0
},
{
"effectID": 1024,
"isDefault": 0
},
{
"effectID": 1885,
"isDefault": 0
},
{
"effectID": 1886,
"isDefault": 0
},
{
"effectID": 5468,
"isDefault": 0
},
{
"effectID": 5560,
"isDefault": 0
},
{
"effectID": 5618,
"effectID": 6016,
"isDefault": 0
},
{
"effectID": 12798,
"isDefault": 0
},
{
"effectID": 12799,
"isDefault": 0
}
]

View File

@@ -172396,15 +172396,15 @@
"28256": {
"basePrice": 0.0,
"capacity": 0.0,
"description_de": "Der prachtvolle Pokal des Allianzturniers wandert nach jedem Turnier an den neuen Sieger und ist vielleicht der begehrteste Preis in New Eden. Ruhm und Ehre erwarten die Besitzer, welche ihre Gegner  Elite-Kampfteams  in einem der zermürbendsten, blutigsten und aufregendsten Turniere aller Zeiten besiegen mussten. <div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url> Jahr 107  Gewinner des 1. Allianzturniers</div> <div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url> Jahr 107  Gewinner des 2. Allianzturniers</div> <div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url> Jahr 108  Gewinner des 3. Allianzturniers</div> <div style=\"text-align:center;\"><url=showinfo:16159//1399057309>HUN Reloaded</url> Jahr 109  Gewinner des 4. Allianzturniers</div> <div style=\"text-align:center;\"><url=showinfo:16159//1438160193>Ev0ke</url> Jahr 110  Gewinner des 5. Allianzturniers</div> <div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> Jahr 111  Gewinner des 6. Allianzturniers</div> <div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> Jahr 111  Gewinner des 7. Allianzturniers</div> <div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> Jahr 112  Gewinner des 8. Allianzturniers</div> <div style=\"text-align:center;\"><url=showinfo:16159//551692893>HYDRA RELOADED</url> Jahr 113  Gewinner des 9. Allianzturniers</div> <div style=\"text-align:center;\"><url=showinfo:16159//99001968>Verge of Collapse</url> Jahr 114  Gewinner des 10. Allianzturniers</div> <div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> Jahr 115  Gewinner des 11. Allianzturniers</div> <div style=\"text-align:center;\"><url=showinfo:16159//99004300>The Camel Empire</url> Jahr 116  Gewinner des 12. Allianzturniers</div> <div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> Jahr 117  Gewinner des 13. Allianzturniers</div> <div style=\"text-align:center;\"><url=showinfo:16159//99004357>The Tuskers Co.</url> Jahr 118  Gewinner des 14. Allianzturniers</div> <div style=\"text-align:center;\"><url=showinfo:16159//99006468>VYDRA RELOLDED</url> Jahr 119  Gewinner des 15. Allianzturniers</div> <div style=\"text-align:center;\"><url=showinfo:16159//99006468>VYDRA RELOLDED</url> Jahr 120  Gewinner des 16. Allianzturniers</div> <div style=\"text-align:center;\"><url=showinfo:16159//551692893>HYDRA RELOADED</url> Jahr 123  Gewinner des 17. Allianzturniers</div> <div style=\"text-align:center;\"><url=showinfo:16159//99011706>TRUTH. HONOR. LIGHT.</url> Jahr 124  Gewinner des 18. Allianzturniers</div> <div style=\"text-align:center;\"><url=showinfo:16159//99003581>Fraternity.</url> Jahr 125  Gewinner des 19. Allianzturniers</div> <div style=\"text-align:center;\"><url=showinfo:16159//99004357>The Tuskers Co.</url> Jahr 126  Gewinner des 20. Allianzturniers</div>",
"description_de": "Der prachtvolle Pokal des Allianzturniers wandert nach jedem Turnier an den neuen Sieger und ist vielleicht der begehrteste Preis in New Eden. Ruhm und Ehre erwarten die Besitzer, welche ihre Gegner  Elite-Kampfteams  in einem der zermürbendsten, blutigsten und aufregendsten Turniere aller Zeiten besiegen mussten. <div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url> Jahr 107  Gewinner des 1. Allianzturniers</div> <div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url> Jahr 107  Gewinner des 2. Allianzturniers</div> <div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url> Jahr 108  Gewinner des 3. Allianzturniers</div> <div style=\"text-align:center;\"><url=showinfo:16159//1399057309>HUN Reloaded</url> Jahr 109  Gewinner des 4. Allianzturniers</div> <div style=\"text-align:center;\"><url=showinfo:16159//1438160193>Ev0ke</url> Jahr 110  Gewinner des 5. Allianzturniers</div> <div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> Jahr 111  Gewinner des 6. Allianzturniers</div> <div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> Jahr 111  Gewinner des 7. Allianzturniers</div> <div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> Jahr 112  Gewinner des 8. Allianzturniers</div> <div style=\"text-align:center;\"><url=showinfo:16159//551692893>HYDRA RELOADED</url> Jahr 113  Gewinner des 9. Allianzturniers</div> <div style=\"text-align:center;\"><url=showinfo:16159//99001968>Verge of Collapse</url> Jahr 114  Gewinner des 10. Allianzturniers</div> <div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> Jahr 115  Gewinner des 11. Allianzturniers</div> <div style=\"text-align:center;\"><url=showinfo:16159//99004300>The Camel Empire</url> Jahr 116  Gewinner des 12. Allianzturniers</div> <div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> Jahr 117  Gewinner des 13. Allianzturniers</div> <div style=\"text-align:center;\"><url=showinfo:16159//99004357>The Tuskers Co.</url> Jahr 118  Gewinner des 14. Allianzturniers</div> <div style=\"text-align:center;\"><url=showinfo:16159//99006468>VYDRA RELOLDED</url> Jahr 119  Gewinner des 15. Allianzturniers</div> <div style=\"text-align:center;\"><url=showinfo:16159//99006468>VYDRA RELOLDED</url> Jahr 120  Gewinner des 16. Allianzturniers</div> <div style=\"text-align:center;\"><url=showinfo:16159//551692893>HYDRA RELOADED</url> Jahr 123  Gewinner des 17. Allianzturniers</div> <div style=\"text-align:center;\"><url=showinfo:16159//99011706>TRUTH. HONOR. LIGHT.</url> Jahr 124  Gewinner des 18. Allianzturniers</div> <div style=\"text-align:center;\"><url=showinfo:16159//99003581>Fraternity.</div>Jahr 125 Gewinner des 19. Allianzturniers</div> <div style=\"text-align:center;\"><url=showinfo:16159//99004357>The Tuskers Co.</url> Jahr 126  Gewinner des 20. Allianzturniers</div> <div style=\"text-align:center;\"><url=showinfo:16159//99004357>The Tuskers Co.</url> Jahr 127  Gewinner des 21. Allianzturniers</div>",
"description_en-us": "Passed on to the winners after every tournament, the magnificent Alliance Tournament cup is perhaps the most coveted prize in New Eden.\r\n\r\nGlory and fame await the holders, who had to defeat the competition posed by the elite combat teams of their opponents in the one of the most gruelling, bloody and exciting tournaments in existence. \r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url> Year 107 - 1st Alliance Tournament Winners</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url> Year 107 - 2nd Alliance Tournament Winners</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url> Year 108 - 3rd Alliance Tournament Winners</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//1399057309>HUN Reloaded</url> Year 109 - 4th Alliance Tournament Winners</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//1438160193>Ev0ke</url> Year 110 - 5th Alliance Tournament Winners</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> Year 111 - 6th Alliance Tournament Winners</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> Year 111 - 7th Alliance Tournament Winners</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> Year 112 - 8th Alliance Tournament Winners</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//551692893>HYDRA RELOADED</url> Year 113 - 9th Alliance Tournament Winners</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99001968>Verge of Collapse</url> Year 114 - 10th Alliance Tournament Winners</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> Year 115 - 11th Alliance Tournament Winners</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99004300>The Camel Empire</url> Year 116 - 12th Alliance Tournament Winners</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> Year 117 - 13th Alliance Tournament Winners</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99004357>The Tuskers Co.</url> Year 118 - 14th Alliance Tournament Winners</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99006468>VYDRA RELOLDED</url> Year 119 - 15th Alliance Tournament Winners</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99006468>VYDRA RELOLDED</url> Year 120 - 16th Alliance Tournament Winners</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//551692893>HYDRA RELOADED</url> Year 123 - 17th Alliance Tournament Winners</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99011706>TRUTH. HONOR. LIGHT.</url> Year 124 - 18th Alliance Tournament Winners</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99003581>Fraternity.</url> Year 125 - 19th Alliance Tournament Winners</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99004357>The Tuskers Co.</url> Year 126 - 20th Alliance Tournament Winners</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99004357>The Tuskers Co.</url> Year 127 - 21st Alliance Tournament Winners</div>",
"description_es": "Entregada a los ganadores después de cada torneo, la magnífica copa del Torneo de Alianzas es quizás el premio más codiciado de Nuevo Edén.\r\n\r\nLa gloria y la fama aguardan a los ganadores que tuvieron que derrotar a los equipos de combate de élite de sus oponentes en uno de los torneos más agotadores, sangrientos y emocionantes que existen. \r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url> Año 107: Ganadores del I Torneo de Alianzas</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url> Año 107: Ganadores del II Torneo de Alianzas</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url> Año 108: Ganadores del III Torneo de Alianzas</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//1399057309>HUN Reloaded</url> Año 109: Ganadores del IV Torneo de Alianzas</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//1438160193>Ev0ke</url> Año 110: Ganadores del V Torneo de Alianzas</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> Año 111: Ganadores del VI Torneo de Alianzas</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> Año 111: Ganadores del VII Torneo de Alianzas</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> Año 112: Ganadores del VIII Torneo de Alianzas</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//551692893>HYDRA RELOADED</url> Año 113: Ganadores del IX Torneo de Alianzas</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99001968>Verge of Collapse</url> Año 114: Ganadores del X Torneo de Alianzas</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> Año 115: Ganadores del XI Torneo de Alianzas</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99004300>The Camel Empire</url> Año 116: Ganadores del XII Torneo de Alianzas</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> Año 117: Ganadores del XIII Torneo de Alianzas</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99004357>The Tuskers Co.</url> Año 118: Ganadores del XIV Torneo de Alianzas</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99006468>VYDRA RELOLDED</url> Año 119: Ganadores del XV Torneo de Alianzas</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99006468>VYDRA RELOLDED</url> Año 120: Ganadores del XVI Torneo de Alianzas</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//551692893>HYDRA RELOADED</url> Año 123: Ganadores del XVII Torneo de Alianzas</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99011706>TRUTH. HONOR. LIGHT.</url> Año 124: Ganadores del XVIII Torneo de Alianzas</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99003581>Fraternity</url> Año 125: Ganadores del XIX Torneo de Alianzas</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99004357>The Tuskers Co.</url> Año 126: Ganadores del XX Torneo de Alianzas</div>",
"description_fr": "Convoitée entre toutes, cette splendide coupe est remise aux vainqueurs du Tournoi des alliances de New Eden. Pour mériter ce symbole de gloire et de notoriété, les concurrents doivent triompher des équipes de combattants d'élite adverses dans l'un des tournois les plus sanglants et les plus passionnants qui soient. <div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url> Année 107 - Vainqueurs du 1er Alliance Tournament</div> <div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url> Année 107 - Vainqueurs du 2e Alliance Tournament</div> <div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url> Année 108 - Vainqueurs du 3e Alliance Tournament</div> <div style=\"text-align:center;\"><url=showinfo:16159//1399057309>HUN Reloaded</url> Année 109 - Vainqueurs du 4e Alliance Tournament</div> <div style=\"text-align:center;\"><url=showinfo:16159//1438160193>Ev0ke</url> Année 110 - Vainqueurs du 5e Alliance Tournament</div> <div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> Année 111 - Vainqueurs du 6e Alliance Tournament</div> <div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> Année 111 - Vainqueurs du 7e Alliance Tournament</div> <div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> Année 112 - Vainqueurs du 8e Alliance Tournament</div> <div style=\"text-align:center;\"><url=showinfo:16159//551692893>HYDRA RELOADED</url> Année 113 - Vainqueurs du 9e Alliance Tournament</div> <div style=\"text-align:center;\"><url=showinfo:16159//99001968>Verge of Collapse</url> Année 114 - Vainqueurs du 10e Alliance Tournament</div> <div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> Année 115 - Vainqueurs du 11e Alliance Tournament</div> <div style=\"text-align:center;\"><url=showinfo:16159//99004300>The Camel Empire</url> Année 116 - Vainqueurs du 12e Alliance Tournament</div> <div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> Année 117 - Vainqueurs du 13e Alliance Tournament</div> <div style=\"text-align:center;\"><url=showinfo:16159//99004357>The Tuskers Co.</url> Année 118 - Vainqueurs du 14e Alliance Tournament</div> <div style=\"text-align:center;\"><url=showinfo:16159//99006468>VYDRA RELOLDED</url> Année 119 - Vainqueurs du 15e Alliance Tournament</div> <div style=\"text-align:center;\"><url=showinfo:16159//99006468>VYDRA RELOLDED</url> Année 120 - Vainqueurs du 16e Alliance Tournament</div> <div style=\"text-align:center;\"><url=showinfo:16159//551692893>HYDRA RELOADED</url> Année 123 - Vainqueurs du 17e Alliance Tournament</div> <div style=\"text-align:center;\"><url=showinfo:16159//99011706>TRUTH. HONOR. LIGHT.</url> Année 124 - Vainqueurs du 18e Alliance Tournament</div> <div style=\"text-align:center;\"><url=showinfo:16159//99003581>Fraternity.</url> Année 125 - Vainqueurs du 19e Alliance Tournament</div> <div style=\"text-align:center;\"><url=showinfo:16159//99004357>The Tuskers Co.</url> Année 126 - Vainqueurs du 20e Alliance Tournament</div>",
"description_es": "Entregada a los ganadores después de cada torneo, la magnífica copa del Torneo de Alianzas es quizás el premio más codiciado de Nuevo Edén.\r\n\r\nLa gloria y la fama aguardan a los ganadores que tuvieron que derrotar a los equipos de combate de élite de sus oponentes en uno de los torneos más agotadores, sangrientos y emocionantes que existen. \r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url> Año 107: Ganadores del I Torneo de Alianzas</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url> Año 107: Ganadores del II Torneo de Alianzas</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url> Año 108: Ganadores del III Torneo de Alianzas</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//1399057309>HUN Reloaded</url> Año 109: Ganadores del IV Torneo de Alianzas</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//1438160193>Ev0ke</url> Año 110: Ganadores del V Torneo de Alianzas</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> Año 111: Ganadores del VI Torneo de Alianzas</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> Año 111: Ganadores del VII Torneo de Alianzas</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> Año 112: Ganadores del VIII Torneo de Alianzas</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//551692893>HYDRA RELOADED</url> Año 113: Ganadores del IX Torneo de Alianzas</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99001968>Verge of Collapse</url> Año 114: Ganadores del X Torneo de Alianzas</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> Año 115: Ganadores del XI Torneo de Alianzas</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99004300>The Camel Empire</url> Año 116: Ganadores del XII Torneo de Alianzas</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> Año 117: Ganadores del XIII Torneo de Alianzas</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99004357>The Tuskers Co.</url> Año 118: Ganadores del XIV Torneo de Alianzas</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99006468>VYDRA RELOLDED</url> Año 119: Ganadores del XV Torneo de Alianzas</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99006468>VYDRA RELOLDED</url> Año 120: Ganadores del XVI Torneo de Alianzas</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//551692893>HYDRA RELOADED</url> Año 123: Ganadores del XVII Torneo de Alianzas</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99011706>TRUTH. HONOR. LIGHT.</url> Año 124: Ganadores del XVIII Torneo de Alianzas</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99003581>Fraternity</url> Año 125: Ganadores del XIX Torneo de Alianzas</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99004357>The Tuskers Co.</url> Año 126: Ganadores del XX Torneo de Alianzas</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99004357>The Tuskers Co.</url> Año 127: Ganadores del XXI Torneo de Alianzas</div>",
"description_fr": "Convoitée entre toutes, cette splendide coupe est remise aux vainqueurs de l'Alliance Tournament de New Eden. Pour mériter ce symbole de gloire et de notoriété, les concurrents doivent triompher des équipes de combattants d'élite adverses dans l'un des tournois les plus sanglants et les plus passionnants qui soient. <div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url> Année 107 - Vainqueurs du 1er Alliance Tournament</div> <div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url> Année 107 - Vainqueurs du 2e Alliance Tournament</div> <div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url> Année 108 - Vainqueurs du 3e Alliance Tournament</div> <div style=\"text-align:center;\"><url=showinfo:16159//1399057309>HUN Reloaded</url> Année 109 - Vainqueurs du 4e Alliance Tournament</div> <div style=\"text-align:center;\"><url=showinfo:16159//1438160193>Ev0ke</url> Année 110 - Vainqueurs du 5e Alliance Tournament</div> <div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> Année 111 - Vainqueurs du 6e Alliance Tournament</div> <div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> Année 111 - Vainqueurs du 7e Alliance Tournament</div> <div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> Année 112 - Vainqueurs du 8e Alliance Tournament</div> <div style=\"text-align:center;\"><url=showinfo:16159//551692893>HYDRA RELOADED</url> Année 113 - Vainqueurs du 9e Alliance Tournament</div> <div style=\"text-align:center;\"><url=showinfo:16159//99001968>Verge of Collapse</url> Année 114 - Vainqueurs du 10e Alliance Tournament</div> <div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> Année 115 - Vainqueurs du 11e Alliance Tournament</div> <div style=\"text-align:center;\"><url=showinfo:16159//99004300>The Camel Empire</url> Année 116 - Vainqueurs du 12e Alliance Tournament</div> <div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> Année 117 - Vainqueurs du 13e Alliance Tournament</div> <div style=\"text-align:center;\"><url=showinfo:16159//99004357>The Tuskers Co.</url> Année 118 - Vainqueurs du 14e Alliance Tournament</div> <div style=\"text-align:center;\"><url=showinfo:16159//99006468>VYDRA RELOLDED</url> Année 119 - Vainqueurs du 15e Alliance Tournament</div> <div style=\"text-align:center;\"><url=showinfo:16159//99006468>VYDRA RELOLDED</url> Année 120 - Vainqueurs du 16e Alliance Tournament</div> <div style=\"text-align:center;\"><url=showinfo:16159//551692893>HYDRA RELOADED</url> Année 123 - Vainqueurs du 17e Alliance Tournament</div> <div style=\"text-align:center;\"><url=showinfo:16159//99011706>TRUTH. HONOR. LIGHT.</url> Année 124 - Vainqueurs du 18e Alliance Tournament</div> <div style=\"text-align:center;\"><url=showinfo:16159//99003581>Fraternity.</url> Année 125 - Vainqueurs du 19e Alliance Tournament</div> <div style=\"text-align:center;\"><url=showinfo:16159//99004357>The Tuskers Co.</url> Année 126 - Vainqueurs du 20e Alliance Tournament</div> <div style=\"text-align:center;\"><url=showinfo:16159//99004357>The Tuskers Co.</url> Année 127 - Vainqueurs du 21e Alliance Tournament</div>",
"description_it": "Passed on to the winners after every tournament, the magnificent Alliance Tournament cup is perhaps the most coveted prize in New Eden.\r\n\r\nGlory and fame await the holders, who had to defeat the competition posed by the elite combat teams of their opponents in the one of the most gruelling, bloody and exciting tournaments in existence. \r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url> Year 107 - 1st Alliance Tournament Winners</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url> Year 107 - 2nd Alliance Tournament Winners</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url> Year 108 - 3rd Alliance Tournament Winners</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//1399057309>HUN Reloaded</url> Year 109 - 4th Alliance Tournament Winners</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//1438160193>Ev0ke</url> Year 110 - 5th Alliance Tournament Winners</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> Year 111 - 6th Alliance Tournament Winners</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> Year 111 - 7th Alliance Tournament Winners</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> Year 112 - 8th Alliance Tournament Winners</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//551692893>HYDRA RELOADED</url> Year 113 - 9th Alliance Tournament Winners</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99001968>Verge of Collapse</url> Year 114 - 10th Alliance Tournament Winners</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> Year 115 - 11th Alliance Tournament Winners</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99004300>The Camel Empire</url> Year 116 - 12th Alliance Tournament Winners</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> Year 117 - 13th Alliance Tournament Winners</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99004357>The Tuskers Co.</url> Year 118 - 14th Alliance Tournament Winners</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99006468>VYDRA RELOLDED</url> Year 119 - 15th Alliance Tournament Winners</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99006468>VYDRA RELOLDED</url> Year 120 - 16th Alliance Tournament Winners</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//551692893>HYDRA RELOADED</url> Year 123 - 17th Alliance Tournament Winners</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99011706>TRUTH. HONOR. LIGHT.</url> Year 124 - 18th Alliance Tournament Winners</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99003581>Fraternity.</url> Year 125 - 19th Alliance Tournament Winners</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99004357>The Tuskers Co.</url> Year 126 - 20th Alliance Tournament Winners</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99004357>The Tuskers Co.</url> Year 127 - 21st Alliance Tournament Winners</div>",
"description_ja": "トーナメントの優勝者に引き継がれる、権威あるアライアンス優勝杯。ニューエデンで多くの人々が手にしたいと願っている最高の褒章かもしれない。\r\n\r\n手にした者には栄光と名声が待っているが、これを手に入れるためには極めて過酷で残忍で激しいこのトーナメントで、立ちはだかるエリートコンバットチームの数々に勝利しなければならない。 \r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url>YC 107年 - 第1回アライアンストーナメント優勝</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url>YC 107年 - 第2回アライアンストーナメント優勝</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url>YC 108年 - 第3回アライアンストーナメント優勝</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//1399057309>HUN Reloaded</url>YC 109年 - 第4回アライアンストーナメント優勝</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//1438160193>Ev0ke</url>YC 110年 - 第5回アライアンストーナメント優勝</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url>YC 111年 - 第6回アライアンストーナメント優勝</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url>YC 111年 - 第7回アライアンストーナメント優勝</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url>YC 112年 - 第8回アライアンストーナメント優勝</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//551692893>HYDRA RELOADED</url>YC 113年 - 第9回アライアンストーナメント優勝</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99001968>Verge of Collapse</url>YC 114年 - 第10回アライアンストーナメント優勝</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url>YC 115年 - 第11回アライアンストーナメント優勝</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99004300>The Camel Empire</url>YC 116年 - 第12回アライアンストーナメント優勝</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url>YC 117年 - 第13回アライアンストーナメント優勝</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99004357>The Tuskers Co.</url>YC 118年 - 第14回アライアンストーナメント優勝</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99006468>VYDRA RELOLDED</url>YC 119年 - 第15回アライアンストーナメント優勝</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99006468>VYDRA RELOLDED</url>YC 120年 - 第16回アライアンストーナメント優勝</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//551692893>HYDRA RELOADED</url>YC 123年 - 第17回アライアンストーナメント優勝</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99011706>TRUTH. HONOUR. LIGHT.</url>YC 124年 - 第18回アライアンス・トーナメントの勝者</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99003581>Fraternity</url>YC 125年 - 第19回アライアンス・トーナメント優勝</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99004357>The Tuskers Co.</url>YC 126年 - 第20回アライアンストーナメント優勝</div>",
"description_ko": "매 토너먼트마다 승자에게 쥐어지는 얼라이언스 토너먼트 우승컵은 뉴에덴의 파일럿들이 가장 탐내는 상품일 것입니다.\r\n\r\n역사상 가장 가혹하면서도 흥분되는 이 토너먼트에서 벌어지는 치열한 경쟁에서 승리한 팀만이 이 우승컵을 쥘 수 있는 명예와 영광을 누릴 수 있습니다.\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url> 107년 - 제1회 얼라이언스 토너먼트 우승팀</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url> 107년 - 제2회 얼라이언스 토너먼트 우승팀</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url> 108년 - 제3회 얼라이언스 토너먼트 우승팀</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//1399057309>HUN Reloaded</url> 109년 - 제4회 얼라이언스 토너먼트 우승팀</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//1438160193>Ev0ke</url> 110년 - 제5회 얼라이언스 토너먼트 우승팀</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> 111년 - 제6회 얼라이언스 토너먼트 우승팀</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> 111년 - 제7회 얼라이언스 토너먼트 우승팀</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> 112년 - 제8회 얼라이언스 토너먼트 우승팀</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//551692893>HYDRA RELOADED</url> 113년 - 제9회 얼라이언스 토너먼트 우승팀</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99001968>Verge of Collapse</url> 114년 - 제10회 얼라이언스 토너먼트 우승팀</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> 115년 - 제11회 얼라이언스 토너먼트 우승팀</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99004300>The Camel Empire</url> 116년 - 제12회 얼라이언스 토너먼트 우승팀</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> 117년 - 제13회 얼라이언스 토너먼트 우승팀</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99004357>The Tuskers Co.</url> 118년 - 제14회 얼라이언스 토너먼트 우승팀</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99006468>VYDRA RELOLDED</url> 119년 - 제15회 얼라이언스 토너먼트 우승팀</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99006468>VYDRA RELOLDED</url> 120년 - 제16회 얼라이언스 토너먼트 우승팀</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//551692893>HYDRA RELOADED</url> 123년 - 제17회 얼라이언스 토너먼트 우승팀</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99011706>TRUTH. HONOR. LIGHT.</url> 124년 - 제18회 얼라이언스 토너먼트 우승팀</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99003581>Fraternity.</url> 125년 - 제19회 얼라이언스 토너먼트 우승팀</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99004357>The Tuskers Co.</url> 126년 - 제20회 얼라이언스 토너먼트 우승팀</div>",
"description_ru": "Кубок Турнира альянсов достаётся победителю последнего турнира. Из всех наград в Новом Эдеме эта — самая желанная. Обладателей кубка ждёт заслуженная слава, ведь для победы в этом жестоком, но увлекательном турнире нужно одолеть элитные боевые отряды весьма грозных противников. <div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url> 107 г. — победители 1-го Турнира альянсов</div> <div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url> 107 г. — победители 2-го Турнира альянсов</div> <div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url> 108 г. — победители 3-го Турнира альянсов</div> <div style=\"text-align:center;\"><url=showinfo:16159//1399057309>HUN Reloaded</url> 109 г. — победители 4-го Турнира альянсов</div> <div style=\"text-align:center;\"><url=showinfo:16159//1438160193>Ev0ke</url> 110 г. — победители 5-го Турнира альянсов</div> <div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> 111 г. — победители 6-го Турнира альянсов</div> <div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> 111 г. — победители 7-го Турнира альянсов</div> <div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> 112 г. — победители 8-го Турнира альянсов</div> <div style=\"text-align:center;\"><url=showinfo:16159//551692893>HYDRA RELOADED</url> 113 г. — победители 9-го Турнира альянсов</div> <div style=\"text-align:center;\"><url=showinfo:16159//99001968>Verge of Collapse</url> 114 г. — победители 10-го Турнира альянсов</div> <div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> 115 г. — победители 11-го Турнира альянсов</div> <div style=\"text-align:center;\"><url=showinfo:16159//99004300>The Camel Empire</url> 116 г. — победители 12-го Турнира альянсов</div> <div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> 117 г. — победители 13-го Турнира альянсов</div> <div style=\"text-align:center;\"><url=showinfo:16159//99004357>The Tuskers Co.</url> 118 г. — победители 14-го Турнира альянсов</div> <div style=\"text-align:center;\"><url=showinfo:16159//99006468>VYDRA RELOLDED</url> 119 г. — победители 15-го Турнира альянсов</div> <div style=\"text-align:center;\"><url=showinfo:16159//99006468>VYDRA RELOLDED</url> 120 г. — победители 16-го Турнира альянсов</div> <div style=\"text-align:center;\"><url=showinfo:16159//551692893>HYDRA RELOADED</url> 123 г. — победители 17-го Турнира альянсов</div> <div style=\"text-align:center;\"><url=showinfo:16159//99011706>TRUTH. HONOR. LIGHT.</url> 124 г. — победители 18-го Турнира альянсов</div> <div style=\"text-align:center;\"><url=showinfo:16159//99003581>Fraternity.</url> 125 г. — победители 19-го Турнира альянсов</div> <div style=\"text-align:center;\"><url=showinfo:16159//99004357>The Tuskers Co.</url> 126 г. — победители 20-го Турнира альянсов</div>",
"description_zh": "每届联赛过后将由上一届的冠军传递给新一届的冠军。阿西娜杯可以说是新伊甸中最为有价值的奖励了。荣耀和名誉都将尽收于它的获得者手中,想要拿到这个奖杯就必须同对手们在有史以来最血腥,残酷和刺激的联赛战场上一决雌雄。<div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url>YC107年第一届联盟锦标赛冠军</div><div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url>YC107年第二届联盟锦标赛冠军</div><div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url>YC108年第三届联盟锦标赛冠军</div><div style=\"text-align:center;\"><url=showinfo:16159//1399057309>HUN Reloaded</url>YC109年第四届联盟锦标赛冠军</div><div style=\"text-align:center;\"><url=showinfo:16159//1438160193>Ev0ke</url>YC110年第五届联盟锦标赛冠军</div><div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url>YC111年第六届联盟锦标赛冠军</div><div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url>YC111年第七届联盟锦标赛冠军</div><div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url>YC112年第八届联盟锦标赛冠军</div><div style=\"text-align:center;\"><url=showinfo:16159//551692893>HYDRA RELOADED</url>YC113年第九届联盟锦标赛冠军</div><div style=\"text-align:center;\"><url=showinfo:16159//99001968>Verge of Collapse</url>YC114年第十届联盟锦标赛冠军</div><div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url>YC115年第十一届联盟锦标赛冠军</div><div style=\"text-align:center;\"><url=showinfo:16159//99004300>The Camel Empire</url>YC116 年第十二届联盟锦标赛冠军</div><div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url>YC117年第十三届联盟锦标赛冠军</div><div style=\"text-align:center;\"><url=showinfo:16159//99004357>The Tuskers Co.</url>YC118年第十四届联盟锦标赛冠军</div><div style=\"text-align:center;\"><url=showinfo:16159//99006468>VYDRA RELOLDED</url>YC119年第十五届联盟锦标赛冠军</div><div style=\"text-align:center;\"><url=showinfo:16159//99006468>VYDRA RELOLDED</url>YC120年第十六届联盟锦标赛冠军</div><div style=\"text-align:center;\"><url=showinfo:16159//551692893>HYDRA RELOADED</url>YC123年第十七届联盟锦标赛冠军</div><div style=\"text-align:center;\"><url=showinfo:16159//99011706>TRUTH.HONOR.LIGHT.</url>YC124年第十八届联盟锦标赛冠军</div> <div style=\"text-align:center;\"><url=showinfo:16159//99003581>Fraternity.</url>YC125年第十九届联盟锦标赛冠军</div><div style=\"text-align:center;\"><url=showinfo:16159//99004357>The Tuskers Co.</url>YC126年第二十届联盟锦标赛冠军</div>",
"description_ja": "トーナメントの優勝者に引き継がれる、権威あるアライアンス優勝杯。ニューエデンで多くの人々が手にしたいと願っている最高の褒章かもしれない。\r\n\r\n手にした者には栄光と名声が待っているが、これを手に入れるためには極めて過酷で残忍で激しいこのトーナメントで、立ちはだかるエリートコンバットチームの数々に勝利しなければならない。 \r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url>YC 107年 - 第1回アライアンストーナメント優勝</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url>YC 107年 - 第2回アライアンストーナメント優勝</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url>YC 108年 - 第3回アライアンストーナメント優勝</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//1399057309>HUN Reloaded</url>YC 109年 - 第4回アライアンストーナメント優勝</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//1438160193>Ev0ke</url>YC 110年 - 第5回アライアンストーナメント優勝</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url>YC 111年 - 第6回アライアンストーナメント優勝</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url>YC 111年 - 第7回アライアンストーナメント優勝</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url>YC 112年 - 第8回アライアンストーナメント優勝</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//551692893>HYDRA RELOADED</url>YC 113年 - 第9回アライアンストーナメント優勝</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99001968>Verge of Collapse</url>YC 114年 - 第10回アライアンストーナメント優勝</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url>YC 115年 - 第11回アライアンストーナメント優勝</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99004300>The Camel Empire</url>YC 116年 - 第12回アライアンストーナメント優勝</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url>YC 117年 - 第13回アライアンストーナメント優勝</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99004357>The Tuskers Co.</url>YC 118年 - 第14回アライアンストーナメント優勝</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99006468>VYDRA RELOLDED</url>YC 119年 - 第15回アライアンストーナメント優勝</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99006468>VYDRA RELOLDED</url>YC 120年 - 第16回アライアンストーナメント優勝</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//551692893>HYDRA RELOADED</url>YC 123年 - 第17回アライアンストーナメント優勝</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99011706>TRUTH. HONOUR. LIGHT.</url>YC 124年 - 第18回アライアンス・トーナメントの勝者</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99003581>Fraternity</url>YC 125年 - 第19回アライアンス・トーナメント優勝</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99004357>The Tuskers Co.</url>YC 126年 - 第20回アライアンストーナメント優勝</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99004357>The Tuskers Co.</url>YC 127年 - 第21回アライアンストーナメント優勝</div>",
"description_ko": "매 토너먼트마다 승자에게 쥐어지는 얼라이언스 토너먼트 우승컵은 뉴에덴의 파일럿들이 가장 탐내는 상품일 것입니다.\r\n\r\n역사상 가장 가혹하면서도 흥분되는 이 토너먼트에서 벌어지는 치열한 경쟁에서 승리한 팀만이 이 우승컵을 쥘 수 있는 명예와 영광을 누릴 수 있습니다.\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url> 107년 - 제1회 얼라이언스 토너먼트 우승팀</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url> 107년 - 제2회 얼라이언스 토너먼트 우승팀</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url> 108년 - 제3회 얼라이언스 토너먼트 우승팀</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//1399057309>HUN Reloaded</url> 109년 - 제4회 얼라이언스 토너먼트 우승팀</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//1438160193>Ev0ke</url> 110년 - 제5회 얼라이언스 토너먼트 우승팀</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> 111년 - 제6회 얼라이언스 토너먼트 우승팀</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> 111년 - 제7회 얼라이언스 토너먼트 우승팀</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> 112년 - 제8회 얼라이언스 토너먼트 우승팀</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//551692893>HYDRA RELOADED</url> 113년 - 제9회 얼라이언스 토너먼트 우승팀</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99001968>Verge of Collapse</url> 114년 - 제10회 얼라이언스 토너먼트 우승팀</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> 115년 - 제11회 얼라이언스 토너먼트 우승팀</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99004300>The Camel Empire</url> 116년 - 제12회 얼라이언스 토너먼트 우승팀</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> 117년 - 제13회 얼라이언스 토너먼트 우승팀</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99004357>The Tuskers Co.</url> 118년 - 제14회 얼라이언스 토너먼트 우승팀</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99006468>VYDRA RELOLDED</url> 119년 - 제15회 얼라이언스 토너먼트 우승팀</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99006468>VYDRA RELOLDED</url> 120년 - 제16회 얼라이언스 토너먼트 우승팀</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//551692893>HYDRA RELOADED</url> 123년 - 제17회 얼라이언스 토너먼트 우승팀</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99011706>TRUTH. HONOR. LIGHT.</url> 124년 - 제18회 얼라이언스 토너먼트 우승팀</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99003581>Fraternity.</url> 125년 - 제19회 얼라이언스 토너먼트 우승팀</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99004357>The Tuskers Co.</url> 126년 - 제20회 얼라이언스 토너먼트 우승팀</div>\r\n\r\n<div style=\"text-align:center;\"><url=showinfo:16159//99004357>The Tuskers Co.</url> 127년 - 제21회 얼라이언스 토너먼트 우승팀</div>",
"description_ru": "Кубок Турнира альянсов достаётся победителю последнего турнира. Из всех наград в Новом Эдеме эта — самая желанная. Обладателей кубка ждёт заслуженная слава, ведь для победы в этом жестоком, но увлекательном состязании нужно одолеть элитные боевые отряды весьма грозных противников. <div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url> 107 г. — победители 1-го Турнира альянсов</div> <div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url> 107 г. — победители 2-го Турнира альянсов</div> <div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url> 108 г. — победители 3-го Турнира альянсов</div> <div style=\"text-align:center;\"><url=showinfo:16159//1399057309>HUN Reloaded</url> 109 г. — победители 4-го Турнира альянсов</div> <div style=\"text-align:center;\"><url=showinfo:16159//1438160193>Ev0ke</url> 110 г. — победители 5-го Турнира альянсов</div> <div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> 111 г. — победители 6-го Турнира альянсов</div> <div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> 111 г. — победители 7-го Турнира альянсов</div> <div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> 112 г. — победители 8-го Турнира альянсов</div> <div style=\"text-align:center;\"><url=showinfo:16159//551692893>HYDRA RELOADED</url> 113 г. — победители 9-го Турнира альянсов</div> <div style=\"text-align:center;\"><url=showinfo:16159//99001968>Verge of Collapse</url> 114 г. — победители 10-го Турнира альянсов</div> <div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> 115 г. — победители 11-го Турнира альянсов</div> <div style=\"text-align:center;\"><url=showinfo:16159//99004300>The Camel Empire</url> 116 г. — победители 12-го Турнира альянсов</div> <div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url> 117 г. — победители 13-го Турнира альянсов</div> <div style=\"text-align:center;\"><url=showinfo:16159//99004357>The Tuskers Co.</url> 118 г. — победители 14-го Турнира альянсов</div> <div style=\"text-align:center;\"><url=showinfo:16159//99006468>VYDRA RELOLDED</url> 119 г. — победители 15-го Турнира альянсов</div> <div style=\"text-align:center;\"><url=showinfo:16159//99006468>VYDRA RELOLDED</url> 120 г. — победители 16-го Турнира альянсов</div> <div style=\"text-align:center;\"><url=showinfo:16159//551692893>HYDRA RELOADED</url> 123 г. — победители 17-го Турнира альянсов</div> <div style=\"text-align:center;\"><url=showinfo:16159//99011706>TRUTH. HONOR. LIGHT.</url> 124 г. — победители 18-го Турнира альянсов</div> <div style=\"text-align:center;\"><url=showinfo:16159//99003581>Fraternity.</div> 125 г. — победители 19-го Турнира альянсов</div> <div style=\"text-align:center;\"><url=showinfo:16159//99004357>The Tuskers Co.</url> 126 г. — победители 20-го Турнира альянсов</div> <div style=\"text-align:center;\"><url=showinfo:16159//99004357>The Tuskers Co.</url> 127 г. — победители 21-го Турнира альянсов</div>",
"description_zh": "每届联赛过后将由上一届的冠军传递给新一届的冠军。阿西娜杯可以说是新伊甸中最为有价值的奖励了。荣耀和名誉都将尽收于它的获得者手中,想要拿到这个奖杯就必须同对手们在有史以来最血腥,残酷和刺激的联赛战场上一决雌雄。<div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url>YC107年第一届联盟锦标赛冠军</div><div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url>YC107年第二届联盟锦标赛冠军</div><div style=\"text-align:center;\"><url=showinfo:16159//632866070>Band of Brothers</url>YC108年第三届联盟锦标赛冠军</div><div style=\"text-align:center;\"><url=showinfo:16159//1399057309>HUN Reloaded</url>YC109年第四届联盟锦标赛冠军</div><div style=\"text-align:center;\"><url=showinfo:16159//1438160193>Ev0ke</url>YC110年第五届联盟锦标赛冠军</div><div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url>YC111年第六届联盟锦标赛冠军</div><div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url>YC111年第七届联盟锦标赛冠军</div><div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url>YC112年第八届联盟锦标赛冠军</div><div style=\"text-align:center;\"><url=showinfo:16159//551692893>HYDRA RELOADED</url>YC113年第九届联盟锦标赛冠军</div><div style=\"text-align:center;\"><url=showinfo:16159//99001968>Verge of Collapse</url>YC114年第十届联盟锦标赛冠军</div><div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url>YC115年第十一届联盟锦标赛冠军</div><div style=\"text-align:center;\"><url=showinfo:16159//99004300>The Camel Empire</url>YC116 年第十二届联盟锦标赛冠军</div><div style=\"text-align:center;\"><url=showinfo:16159//386292982>Pandemic Legion</url>YC117年第十三届联盟锦标赛冠军</div><div style=\"text-align:center;\"><url=showinfo:16159//99004357>The Tuskers Co.</url>YC118年第十四届联盟锦标赛冠军</div><div style=\"text-align:center;\"><url=showinfo:16159//99006468>VYDRA RELOLDED</url>YC119年第十五届联盟锦标赛冠军</div><div style=\"text-align:center;\"><url=showinfo:16159//99006468>VYDRA RELOLDED</url>YC120年第十六届联盟锦标赛冠军</div><div style=\"text-align:center;\"><url=showinfo:16159//551692893>HYDRA RELOADED</url>YC123年第十七届联盟锦标赛冠军</div><div style=\"text-align:center;\"><url=showinfo:16159//99011706>TRUTH.HONOR.LIGHT.</url>YC124年第十八届联盟锦标赛冠军</div> <div style=\"text-align:center;\"><url=showinfo:16159//99003581>Fraternity.</url>YC125年第十九届联盟锦标赛冠军</div><div style=\"text-align:center;\"><url=showinfo:16159//99004357>The Tuskers Co.</url>YC126年第二十届联盟锦标赛冠军</div><div style=\"text-align:center;\"><url=showinfo:16159//99004357>The Tuskers Co.</url>YC127年第二十一届联盟锦标赛冠军</div>",
"descriptionID": 91436,
"groupID": 314,
"iconID": 1656,

View File

@@ -133896,10 +133896,10 @@
"radius": 131.0,
"typeID": 54005,
"typeName_de": "Scout Imperial Navy Pilgrim",
"typeName_en-us": "Scout Imperial Navy Pilgrim",
"typeName_en-us": "Scout Imperial Navy Pilgrim",
"typeName_es": "Pilgrim de reconocimiento de la Armada Imperial",
"typeName_fr": "Pilgrim éclaireur de la Navy impériale",
"typeName_it": "Scout Imperial Navy Pilgrim",
"typeName_it": "Scout Imperial Navy Pilgrim",
"typeName_ja": "偵察帝国海軍ピルグリム",
"typeName_ko": "스카우트 제국 해군 필그림",
"typeName_ru": "Scout Imperial Navy Pilgrim",
@@ -249971,10 +249971,10 @@
"radius": 200.0,
"typeID": 60337,
"typeName_de": "Non-Interactable Minmatar Junction (Do not translate)",
"typeName_en-us": "Non-Interactable Minmatar Junction (Do not translate)",
"typeName_en-us": "Non-Interactable Minmatar Junction (Do not translate)",
"typeName_es": "Non-Interactable Minmatar Junction (Do not translate)",
"typeName_fr": "Non-Interactable Minmatar Junction (Do not translate)",
"typeName_it": "Non-Interactable Minmatar Junction (Do not translate)",
"typeName_it": "Non-Interactable Minmatar Junction (Do not translate)",
"typeName_ja": "Non-Interactable Minmatar Junction (Do not translate)",
"typeName_ko": "Non-Interactable Minmatar Junction (Do not translate)",
"typeName_ru": "Non-Interactable Minmatar Junction (Do not translate)",
@@ -275151,15 +275151,15 @@
"raceID": 4,
"radius": 1.0,
"typeID": 62563,
"typeName_de": "Compressed Crokite IV-Grade",
"typeName_en-us": "Compressed Crokite IV-Grade",
"typeName_es": "Compressed Crokite IV-Grade",
"typeName_fr": "Compressed Crokite IV-Grade",
"typeName_it": "Compressed Crokite IV-Grade",
"typeName_ja": "Compressed Crokite IV-Grade",
"typeName_ko": "Compressed Crokite IV-Grade",
"typeName_ru": "Compressed Crokite IV-Grade",
"typeName_zh": "Compressed Crokite IV-Grade",
"typeName_de": "Compressed Crokite IV-Grade",
"typeName_en-us": "Compressed Crokite IV-Grade",
"typeName_es": "Compressed Crokite IV-Grade",
"typeName_fr": "Compressed Crokite IV-Grade",
"typeName_it": "Compressed Crokite IV-Grade",
"typeName_ja": "Compressed Crokite IV-Grade",
"typeName_ko": "Compressed Crokite IV-Grade",
"typeName_ru": "Compressed Crokite IV-Grade",
"typeName_zh": "Compressed Crokite IV-Grade",
"typeNameID": 1031080,
"volume": 0.16
},
@@ -300685,10 +300685,10 @@
"radius": 1.0,
"typeID": 63979,
"typeName_de": "CD 19 Concord H Wave Spawner (DO NOT TRANSLATE)",
"typeName_en-us": "CD 19 Concord H Wave Spawner (DO NOT TRANSLATE)",
"typeName_en-us": "CD 19 Concord H Wave Spawner (DO NOT TRANSLATE)",
"typeName_es": "CD 19 Concord H Wave Spawner (DO NOT TRANSLATE)",
"typeName_fr": "CD 19 Concord H Wave Spawner (DO NOT TRANSLATE)",
"typeName_it": "CD 19 Concord H Wave Spawner (DO NOT TRANSLATE)",
"typeName_it": "CD 19 Concord H Wave Spawner (DO NOT TRANSLATE)",
"typeName_ja": "CD 19 Concord H Wave Spawner (DO NOT TRANSLATE)",
"typeName_ko": "CD 19 Concord H Wave Spawner",
"typeName_ru": "CD 19 Concord H Wave Spawner (DO NOT TRANSLATE)",

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,190 @@
{
"364784": {
"basePrice": 10575.0,
"capacity": 0.0,
"description_de": "Ein Drop-Uplink ist ein Slave-Transponder, ein Kommunikationsgerät mit kurzer Reichweite, das die exakten Raumkoordinaten erzeugt, die zur Generierung eines lokalisierten Wurmlochs benötigt werden. Eine Durchquerung dieses Wurmlochs ermöglicht die unmittelbare Überbrückung kurzer Distanzen. Der ausgesprochen experimentelle Vorgang ist entsetzlich schmerzhaft und setzt das organische Gewebe übermäßiger Strahlung aus. Dies hat ein beschleunigtes Absterben der Zellen und schließlich den Tod zur Folge.",
"description_en-us": "The drop uplink is a slave transponder, a short-range tether that produces the precise spatial coordinates necessary to generate a localized wormhole, traversal of which allows the user to travel short distances instantly. Highly experimental, the process is excruciatingly painful and exposes organic tissue to excessive radiation, resulting in accelerated cellular decay and, ultimately, death.",
"description_es": "El enlace de salto es un transpondedor esclavo, un anclaje de corto alcance que genera las coordenadas espaciales exactas necesarias para generar un agujero de gusano en un punto específico, permitiendo al usuario viajar distancias cortas al instante. El proceso, aún en fase puramente experimental, produce un dolor muy agudo y expone el tejido orgánico a una radiación excesiva que resulta en un deterioro celular acelerado y, en última instancia, la muerte.",
"description_fr": "Le portail est un transpondeur secondaire, un lien de courte portée qui génère des coordonnées spatiales précises nécessaires pour créer un trou de ver localisé, grâce auquel l'utilisateur peut parcourir instantanément de courtes distances. Ce processus expérimental est horriblement douloureux et expose les tissus organiques à de fortes radiations, provoquant une décomposition cellulaire accélérée et, au bout du compte, la mort.",
"description_it": "Il portale di schieramento è un transponder secondario, un dispositivo di tethering a breve raggio che produce le esatte coordinate spaziali necessarie per generare una galleria gravitazionale circoscritta che consente all'utente di percorrere istantaneamente brevi distanze. Questo processo altamente sperimentale è incredibilmente doloroso ed espone i tessuti organici a un eccesso di radiazioni che comporta un decadimento cellulare accelerato e infine la morte.",
"description_ja": "地上戦アップリンクは奴隷輸送船の一種で、短距離テザーとして正確な空間座標を発信することで局地的ワームホールの生成を可能にし、利用者が現地まで瞬時に移動できるようにする。技術的にはごく初期の実験段階であり、その移動過程は極度の苦痛を伴ううえに生体組織を過剰な量の放射線にさらす。結果として細胞の劣化を早め、最終的には死に至る。",
"description_ko": "노예용 트랜스폰더로 분류되는 이동식 업링크는 단거리 좌표를 산출하여 웜홀을 생성하는 장치입니다. 웜홀을 통해 짧은 거리 이동이 가능합니다. 장치는 미완성품으로 웜홀 이용 시 사용자는 극심한 고통을 느낍니다. 또한 방사능 노출로 인해 세포가 붕괴하며 추후 사망에 이를 수 있습니다.",
"description_ru": "Десантный маяк — это ведомый приемопередатчик с малым радиусом действия, передающий точные пространственные координаты своего местонахождения. Эти координаты применяются для генерации локализованной червоточины, позволяющей пользователю мгновенно перемещаться на короткие расстояния. Этот процесс находится на самых начальных стадиях разработки, и, как следствие, он чрезвычайно болезнен. Кроме того, в процессе перемещения ткани организма подвергаются воздействию больших доз облучения, что ускоряет процесс разрушения клеток и в конечном итоге приводит к смертельному исходу.",
"description_zh": "上行链路是一个从属收发器,它可以提供一种短程驻留,通过产出精确的空间坐标在本地生成一个虫洞,而使用者穿过虫洞即可穿越短程时空。此过程具有高度实验性,会带来极端痛苦,有机组织会被暴露在高强度的辐射下,导致细胞加速腐烂,并最终致死。",
"descriptionID": 287798,
"groupID": 351844,
"mass": 0.0,
"portionSize": 1,
"published": 0,
"radius": 1.0,
"typeID": 364784,
"typeName_de": "Imperialer Flux-Drop-Uplink",
"typeName_en-us": "Viziam Flux Drop Uplink",
"typeName_es": "Enlace de salto de flujo Imperial",
"typeName_fr": "Portail Flux Impérial",
"typeName_it": "Portale di schieramento flusso Imperial",
"typeName_ja": "帝国フラックス降下アップリンク",
"typeName_ko": "비지암 플럭스 이동식 업링크",
"typeName_ru": "Десантный силовой маяк производства 'Imperial'",
"typeName_zh": "维鲜通量上行链路",
"typeNameID": 287797,
"volume": 0.01
},
"364785": {
"basePrice": 10575.0,
"capacity": 0.0,
"description_de": "Ein Drop-Uplink ist ein Slave-Transponder, ein Kommunikationsgerät mit kurzer Reichweite, das die exakten Raumkoordinaten erzeugt, die zur Generierung eines lokalisierten Wurmlochs benötigt werden. Eine Durchquerung dieses Wurmlochs ermöglicht die unmittelbare Überbrückung kurzer Distanzen. Der ausgesprochen experimentelle Vorgang ist entsetzlich schmerzhaft und setzt das organische Gewebe übermäßiger Strahlung aus. Dies hat ein beschleunigtes Absterben der Zellen und schließlich den Tod zur Folge.",
"description_en-us": "The drop uplink is a slave transponder, a short-range tether that produces the precise spatial coordinates necessary to generate a localized wormhole, traversal of which allows the user to travel short distances instantly. Highly experimental, the process is excruciatingly painful and exposes organic tissue to excessive radiation, resulting in accelerated cellular decay and, ultimately, death.",
"description_es": "El teletransportador es un transpondedor de esclavos, un punto de amarre de corto alcance que produce las coordenadas espaciales precisas necesarias para generar un agujero de gusano localizado que permite al usuario viajar a distancias cortas al instante. El proceso es muy experimental, terriblemente doloroso, y expone el tejido orgánico a una radiación excesiva, lo que provoca una descomposición celular acelerada y, en última instancia, la muerte.",
"description_fr": "Le portail est un transpondeur secondaire, un lien de courte portée qui génère des coordonnées spatiales précises nécessaires pour créer un trou de ver localisé, grâce auquel l'utilisateur peut parcourir instantanément de courtes distances. Ce processus expérimental est horriblement douloureux et expose les tissus organiques à de fortes radiations, provoquant une décomposition cellulaire accélérée et, au bout du compte, la mort.",
"description_it": "Il portale di schieramento è un transponder secondario, un dispositivo di tethering a breve raggio che produce le esatte coordinate spaziali necessarie per generare una galleria gravitazionale circoscritta che consente all'utente di percorrere istantaneamente brevi distanze. Questo processo altamente sperimentale è incredibilmente doloroso ed espone i tessuti organici a un eccesso di radiazioni che comporta un decadimento cellulare accelerato e infine la morte.",
"description_ja": "地上戦アップリンクは奴隷輸送船の一種で、短距離テザーとして正確な空間座標を発信することで局地的ワームホールの生成を可能にし、利用者が現地まで瞬時に移動できるようにする。技術的にはごく初期の実験段階であり、その移動過程は極度の苦痛を伴ううえに生体組織を過剰な量の放射線にさらす。結果として細胞の劣化を早め、最終的には死に至る。",
"description_ko": "노예용 트랜스폰더로 분류되는 이동식 업링크는 단거리 좌표를 산출하여 웜홀을 생성하는 장치입니다. 웜홀을 통해 짧은 거리 이동이 가능합니다. 장치는 미완성품으로 웜홀 이용 시 사용자는 극심한 고통을 느낍니다. 또한 방사능 노출로 인해 세포가 붕괴하며 추후 사망에 이를 수 있습니다.",
"description_ru": "Десантный маяк — это ведомый приемопередатчик с малым радиусом действия, передающий точные пространственные координаты своего местонахождения. Эти координаты применяются для генерации локализованной червоточины, позволяющей пользователю мгновенно перемещаться на короткие расстояния. Этот процесс находится на самых начальных стадиях разработки, и, как следствие, он чрезвычайно болезнен. Кроме того, в процессе перемещения ткани организма подвергаются воздействию больших доз облучения, что ускоряет процесс разрушения клеток и в конечном итоге приводит к смертельному исходу.",
"description_zh": "上行链路是一个从属收发器,它可以提供一种短程驻留,通过产出精确的空间坐标在本地生成一个虫洞,而使用者穿过虫洞即可穿越短程时空。此过程具有高度实验性,会带来极端痛苦,有机组织会被暴露在高强度的辐射下,导致细胞加速腐烂,并最终致死。",
"descriptionID": 287800,
"groupID": 351844,
"mass": 0.0,
"portionSize": 1,
"published": 0,
"radius": 1.0,
"typeID": 364785,
"typeName_de": "Allotek-Quantum-Drop-Uplink",
"typeName_en-us": "Viziam Quantum Drop Uplink",
"typeName_es": "Enlace de salto cuántico Allotek",
"typeName_fr": "Portail Quantum Allotek",
"typeName_it": "Portale di schieramento quantico Allotek",
"typeName_ja": "アローテッククアンタム地上戦アップリンク",
"typeName_ko": "비지암 양자 이동식 업링크",
"typeName_ru": "Десантный маяк 'Quantum' производства 'Allotek'",
"typeName_zh": "维鲜量子上行链路",
"typeNameID": 287799,
"volume": 0.01
},
"364786": {
"basePrice": 1815.0,
"capacity": 0.0,
"description_de": "Das Nova-Messer ist eine Nahkampfwaffe und einer der tödlichsten Ausrüstungsgegenstände auf dem Schlachtfeld. Der Name leitet sich von der glühenden Plasmaklinge ab, die von einem Thermalzünder mit linearem Schwerkraftkondensator erzeugt wird. In fähigen Händen kann das Messer selbst die stärkste Dropsuitpanzerung durchdringen.",
"description_en-us": "A close-quarters melee weapon, the nova knife is as deadly a weapon as anything on the battlefield. Its name derives from the heated plasma edge of the blade formed by a thermic igniter and linear gravity condenser that, in skilled hands, can be used to carve through even the thickest dropsuit armor.",
"description_es": "El cuchillo Nova, un arma cuerpo a cuerpo, es de lo más letal que hay en el campo de batalla. Su nombre se inspira en el filo de plasma caliente de la hoja, formado por un ignitor térmico y un condensador de gravedad lineal que, en manos hábiles, puede perforar incluso los trajes con el blindaje más grueso.",
"description_fr": "Excellente arme de mêlée, le couteau Nova est aussi mortel que n'importe quelle autre arme sur le champ de bataille. Son nom vient du bord plasma chauffé de la lame (générée par un allumeur thermique et un condensateur de gravité linéaire) qui, lorsqu'elle est manipulée par des mains expertes, peut être utilisée pour perforer les armures de combinaison les plus épaisses.",
"description_it": "Arma corpo a corpo per combattimenti ravvicinati, il coltello Nova è l'arma più letale presente sul campo di battaglia. Il suo nome deriva dal filo della lama riscaldata al plasma, formata da un accenditore termico e un condensatore di gravità lineare che, in buone mani, è in grado di fendere le armature più resistenti.",
"description_ja": "接近戦向けの乱闘兵器、ノヴァナイフは戦場のどの兵器にも劣らない危険な兵器だ。その名は、加熱プラズマブレードの刃、すなわちサーミック点火器とライナー重力コンデンサーにより形成―に由来する。熟練した者の手にかかれば、いかに重厚な降下スーツのアーマーでさえも貫通させることが可能。",
"description_ko": "전장의 그 어떤 강력한 무기에도 버금가는 근거리 무기입니다. 노바 나이프라는 이름은 점화장치와 선형 중력 응축기로 제련하여 가열된 플라즈마 칼날에서 따왔습니다. 숙련자가 사용할 시 가장 두꺼운 강하슈트 장갑까지도 뚫을 수 있습니다.",
"description_ru": "Плазменные ножи, предназначенные для ведения рукопашного боя, не менее опасны, чем высокотехнологичное оружие. Свое название они получили от плазменной кромки лезвия, формирующейся при взаимодействии термического запала и линейного гравитационного конденсора. В умелых руках такой нож способен проткнуть даже самую толстую броню десантного скафандра.",
"description_zh": "新星刀是一种近身近战武器,在战场上的杀伤力丝毫不逊色于其他武器。名字灵感来源于等离子刀刃受热后,经热力点火器和线性重力冷凝器铸造出来的形状。如果使用者手法熟练,甚至能用它击穿最厚的作战服装甲。",
"descriptionID": 287821,
"groupID": 350858,
"mass": 0.0,
"portionSize": 1,
"published": 0,
"radius": 1.0,
"typeID": 364786,
"typeName_de": "Nova-Messer 'Scorchtalon'",
"typeName_en-us": "'Scorchtalon' Nova Knives",
"typeName_es": "Cuchillos Nova \"Scorchtalon\"",
"typeName_fr": "Couteaux Nova 'Pyroserre'",
"typeName_it": "Coltelli Nova \"Scorchtalon\"",
"typeName_ja": "「スコーチタロン」ノヴァナイフ",
"typeName_ko": "'스코치탈론' 노바 나이프",
"typeName_ru": "Плазменные ножи 'Scorchtalon'",
"typeName_zh": "“焦爪”级新星刀",
"typeNameID": 287820,
"volume": 0.01
},
"364787": {
"basePrice": 4845.0,
"capacity": 0.0,
"description_de": "Das Nova-Messer ist eine Nahkampfwaffe und einer der tödlichsten Ausrüstungsgegenstände auf dem Schlachtfeld. Der Name leitet sich von der glühenden Plasmaklinge ab, die von einem Thermalzünder mit linearem Schwerkraftkondensator erzeugt wird. In fähigen Händen kann das Messer selbst die stärkste Dropsuitpanzerung durchdringen.",
"description_en-us": "A close-quarters melee weapon, the nova knife is as deadly a weapon as anything on the battlefield. Its name derives from the heated plasma edge of the blade formed by a thermic igniter and linear gravity condenser that, in skilled hands, can be used to carve through even the thickest dropsuit armor.",
"description_es": "El cuchillo Nova, un arma cuerpo a cuerpo, es de lo más letal que hay en el campo de batalla. Su nombre se inspira en el filo de plasma caliente de la hoja, formado por un ignitor térmico y un condensador de gravedad lineal que, en manos hábiles, puede perforar incluso los trajes con el blindaje más grueso.",
"description_fr": "Excellente arme de mêlée, le couteau Nova est aussi mortel que n'importe quelle autre arme sur le champ de bataille. Son nom vient du bord plasma chauffé de la lame (générée par un allumeur thermique et un condensateur de gravité linéaire) qui, lorsqu'elle est manipulée par des mains expertes, peut être utilisée pour perforer les armures de combinaison les plus épaisses.",
"description_it": "Arma corpo a corpo per combattimenti ravvicinati, il coltello Nova è l'arma più letale presente sul campo di battaglia. Il suo nome deriva dal filo della lama riscaldata al plasma, formata da un accenditore termico e un condensatore di gravità lineare che, in buone mani, è in grado di fendere le armature più resistenti.",
"description_ja": "接近戦向けの乱闘兵器、ノヴァナイフは戦場のどの兵器にも劣らない危険な兵器だ。その名は、加熱プラズマブレードの刃、すなわちサーミック点火器とライナー重力コンデンサーにより形成―に由来する。熟練した者の手にかかれば、いかに重厚な降下スーツのアーマーでさえも貫通させることが可能。",
"description_ko": "전장의 그 어떤 강력한 무기에도 버금가는 근거리 무기입니다. 노바 나이프라는 이름은 점화장치와 선형 중력 응축기로 제련하여 가열된 플라즈마 칼날에서 따왔습니다. 숙련자가 사용할 시 가장 두꺼운 강하슈트 장갑까지도 뚫을 수 있습니다.",
"description_ru": "Плазменные ножи, предназначенные для ведения рукопашного боя, не менее опасны, чем высокотехнологичное оружие. Свое название они получили от плазменной кромки лезвия, формирующейся при взаимодействии термического запала и линейного гравитационного конденсора. В умелых руках такой нож способен проткнуть даже самую толстую броню десантного скафандра.",
"description_zh": "新星刀是一种近身近战武器,在战场上的杀伤力丝毫不逊色于其他武器。名字灵感来源于等离子刀刃受热后,经热力点火器和线性重力冷凝器铸造出来的形状。如果使用者手法熟练,甚至能用它击穿最厚的作战服装甲。",
"descriptionID": 287823,
"groupID": 350858,
"mass": 0.0,
"portionSize": 1,
"published": 0,
"radius": 1.0,
"typeID": 364787,
"typeName_de": "ZN-28 Nova-Messer 'Blackprey'",
"typeName_en-us": "'Blackprey' ZN-28 Nova Knives",
"typeName_es": "Cuchillos Nova ZN-28 \"Blackprey\"",
"typeName_fr": "Couteaux Nova ZN-28 'Sombre proie'",
"typeName_it": "Coltelli Nova ZN-28 \"Blackprey\"",
"typeName_ja": "「ブラックプレイ」ZN-28ヴァナイフ",
"typeName_ko": "'블랙프레이' ZN-28 노바 나이프",
"typeName_ru": "Плазменные ножи 'Blackprey' ZN-28",
"typeName_zh": "“黑猎”级ZN-28新星刀",
"typeNameID": 287822,
"volume": 0.01
},
"364788": {
"basePrice": 12975.0,
"capacity": 0.0,
"description_de": "Das Nova-Messer ist eine Nahkampfwaffe und einer der tödlichsten Ausrüstungsgegenstände auf dem Schlachtfeld. Der Name leitet sich von der glühenden Plasmaklinge ab, die von einem Thermalzünder mit linearem Schwerkraftkondensator erzeugt wird. In fähigen Händen kann das Messer selbst die stärkste Dropsuitpanzerung durchdringen.",
"description_en-us": "A close-quarters melee weapon, the nova knife is as deadly a weapon as anything on the battlefield. Its name derives from the heated plasma edge of the blade formed by a thermic igniter and linear gravity condenser that, in skilled hands, can be used to carve through even the thickest dropsuit armor.",
"description_es": "El cuchillo Nova, un arma cuerpo a cuerpo, es de lo más letal que hay en el campo de batalla. Su nombre se inspira en el filo de plasma caliente de la hoja, formado por un ignitor térmico y un condensador de gravedad lineal que, en manos hábiles, puede perforar incluso los trajes con el blindaje más grueso.",
"description_fr": "Excellente arme de mêlée, le couteau Nova est aussi mortel que n'importe quelle autre arme sur le champ de bataille. Son nom vient du bord plasma chauffé de la lame (générée par un allumeur thermique et un condensateur de gravité linéaire) qui, lorsqu'elle est manipulée par des mains expertes, peut être utilisée pour perforer les armures de combinaison les plus épaisses.",
"description_it": "Arma corpo a corpo per combattimenti ravvicinati, il coltello Nova è l'arma più letale presente sul campo di battaglia. Il suo nome deriva dal filo della lama riscaldata al plasma, formata da un accenditore termico e un condensatore di gravità lineare che, in buone mani, è in grado di fendere le armature più resistenti.",
"description_ja": "接近戦向けの乱闘兵器、ノヴァナイフは戦場のどの兵器にも劣らない危険な兵器だ。その名は、加熱プラズマブレードの刃、すなわちサーミック点火器とライナー重力コンデンサーにより形成―に由来する。熟練した者の手にかかれば、いかに重厚な降下スーツのアーマーでさえも貫通させることが可能。",
"description_ko": "전장의 그 어떤 강력한 무기에도 버금가는 근거리 무기입니다. 노바 나이프라는 이름은 점화장치와 선형 중력 응축기로 제련하여 가열된 플라즈마 칼날에서 따왔습니다. 숙련자가 사용할 시 가장 두꺼운 강하슈트 장갑까지도 뚫을 수 있습니다.",
"description_ru": "Плазменные ножи, предназначенные для ведения рукопашного боя, не менее опасны, чем высокотехнологичное оружие. Свое название они получили от плазменной кромки лезвия, формирующейся при взаимодействии термического запала и линейного гравитационного конденсора. В умелых руках такой нож способен проткнуть даже самую толстую броню десантного скафандра.",
"description_zh": "新星刀是一种近身近战武器,在战场上的杀伤力丝毫不逊色于其他武器。名字灵感来源于等离子刀刃受热后,经热力点火器和线性重力冷凝器铸造出来的形状。如果使用者手法熟练,甚至能用它击穿最厚的作战服装甲。",
"descriptionID": 287825,
"groupID": 350858,
"mass": 0.0,
"portionSize": 1,
"published": 0,
"radius": 1.0,
"typeID": 364788,
"typeName_de": "Ishukone-Nova-Messer 'Fleshriver'",
"typeName_en-us": "'Fleshriver' Ishukone Nova Knives",
"typeName_es": "Cuchillos Nova Ishukone \"Fleshriver\"",
"typeName_fr": "Couteaux Nova Ishukone 'Décharneur'",
"typeName_it": "Coltelli Nova Ishukone \"Fleshriver\"",
"typeName_ja": "「フレッシュリバー」イシュコネノヴァナイフ",
"typeName_ko": "'플레시리버' 이슈콘 노바 나이프",
"typeName_ru": "Плазменные ножи 'Fleshriver' производства 'Ishukone'",
"typeName_zh": "“食肉”级异株湖新星刀",
"typeNameID": 287824,
"volume": 0.01
},
"364789": {
"basePrice": 4020.0,
"capacity": 0.0,
"description_de": "Fernsprengsätze der F/41-Reihe gehören zu den stärksten manuell gezündeten Sprengsätzen in New Eden. Jede Einheit ist zuverlässig und effektiv und verwendet eine Mischung aus drei Sprengstoffen, um Mehrfachpanzerungen zu durchschlagen, befestigte Gebäude zu zerstören und Infanterie zu vernichten.\n\nDiese Sprengsätze werden manuell platziert und über eine verschlüsselte Frequenz gezündet, die vom Holographischen Kortex-Interface generiert wird, das eine Datenbank mit einzigartigen Aktivierungscodes für jede platzierte Ladung unterhält. Die Produktreihe F/41 verfügt zusätzlich über weitere fortschrittliche Features wie gehärtete EM-Schaltkreise, einen verschlüsselten Multifrequenzempfänger und einen leichten Hybridkeramikrahmen.",
"description_en-us": "The F/41 series of remote explosives are among the most powerful manually triggered demolitions devices available in New Eden. Each unit is reliable and effective, using a mix of three volatile materials to produce a yield high enough to penetrate layered armor, shatter reinforced structures, and decimate infantry units.\n\nThese explosives are deployed by hand and detonated using a coded frequency generated by the Cortex Holographic Interface, which maintains a database of unique activation ciphers for every charge placed. The F/41 product line also boasts several other advanced features, such as EM hardened circuits, an encrypted multi-frequency receiver, and a lightweight hybrid ceramic frame.",
"description_es": "Los explosivos remotos de la serie F/41 son unos de los dispositivos de demolición por activación manual más potentes que existen en Nuevo Edén. Cada unidad es eficaz, segura y emplea una mezcla de tres materiales volátiles tanto para mejorar el rendimiento como para penetrar el blindaje, hecho de capas, destrozar las estructuras reforzadas y diezmar a las unidades de infantería.\n\nEstos explosivos se despliegan manualmente y se detonan mediante una frecuencia codificada, generada por la interfaz holográfica del córtex, que mantiene una base de datos con los códigos de activación individuales de cada carga colocada. La línea de productos F/41 también posee otras características avanzadas, como circuitos electromagnéticos endurecidos, un receptor multifrecuencia encriptado y un armazón cerámico híbrido ligero.",
"description_fr": "La série F/41 d'explosifs télécommandés fait partie des engins explosifs à déclenchement manuel parmi les plus puissants qui soient disponibles sur New Eden. Fiable et efficace, chaque unité utilise un mélange de trois matériaux instables afin de produire une explosion assez puissante pour pénétrer un blindage à plusieurs épaisseurs, démolir des structures renforcées et décimer des unités d'infanterie.\n\nCes explosifs sont déployés manuellement et détonnés à l'aide d'une fréquence codée générée par l'interface holographique Cortex, qui maintient une base de données des chiffres d'activation uniques pour chaque charge placée. La ligne de produits F/41 propose également d'autres caractéristiques avancées, telles que des circuits EM renforcés, un récepteur multifréquences encrypté et un châssis hybride léger en céramique.",
"description_it": "Gli esplosivi a controllo remoto della serie F/41 sono tra i dispositivi di distruzione manuale più potenti disponibili in New Eden. Ciascuna unità è affidabile ed efficace e sfrutta una combinazione di tre materiali volatili in grado di generare una potenza sufficiente a perforare armature rivestite, demolire strutture rinforzate e decimare unità di fanteria.\n\nQuesti esplosivi vengono lanciati manualmente e fatti esplodere usando una frequenza cifrata generata dall'interfaccia olografica della corteccia, la quale conserva un database di cifre di attivazione singole per ciascuna carica piazzata. Inoltre, la linea di prodotti F/41 offre altre soluzioni avanzate quali i circuiti EM rinforzati, un ricevitore multifrequenza criptato e un telaio in ceramica ibrida leggera.",
"description_ja": "リモート爆弾F/41シリーズは、ニューエデンで利用可能な最も強力な手動操作できる破壊装置の一つである。各ユニットは、3つの揮発性物質の混合物を使用して幾重にも重なる装甲を貫通し、強化構造物をも粉砕するに足る力を生み出し、確実に歩兵ユニットを全滅させる。\n\nこれらの爆弾は手動で配置され、コルテックスホログラフィックインターフェースによって生成されたコード化済み周波数を使用して爆発させる。このインターフェースは、すべての装薬のためにユニークな活性化球体のデータベースを保持したものである。またF/41製品ラインは、EMハードナー回路、暗号化された多周波受信機、軽量ハイブリッドセラミックフレームと他のいくつかの高度な機能を誇っている。",
"description_ko": "F/41 시리즈의 원격 폭발물은 뉴에덴에서 구할 수 있는 수동 점화 폭발물 중 가장 강력합니다. 폭발성 물질의 혼합으로 안정성 및 화력이 뛰어나 중첩 장갑, 강화 구조물, 그리고 보병을 대상으로 막대한 양의 피해를 입힙니다. <br><br>사용자가 손으로 직접 전개해야 하는 이 폭발물은 코르텍스 홀로그래픽 인터페이스가 생성하는 암호화된 주파수를 통해 점화됩니다. 개별로 전개된 폭발물은 각각의 특수한 활성화 데이터베이스 코드가 존재합니다. F/41 기종은 첨단 기술 도입을 통해 EM 강화 회로, 암호화된 다중 주파수 수신기, 경량 하이브리드 세라믹 구조와 같은 기능을 적극 탑재하였습니다.",
"description_ru": "Серия радиоуправляемых взрывных устройств F/41 относится к наиболее разрушительным неавтоматическим орудиям уничтожения Нового Эдема. Каждый из компонентов устройства отличается как надежностью, так и высоким взрывным потенциалом, а их сочетание вызывает взрыв, способный пробить многослойную броню, расколоть армированные структуры и уничтожить пехоту.\n\nЭти взрывные устройства устанавливаются вручную, а детонация производится путем передачи сигнала на закодированной частоте, генерируемой кортексным голографическим интерфейсом, который сохраняет в своей базе данных уникальные активационные коды для каждого из размещенных зарядов. В устройствах серии F/41 имеется еще ряд высокотехнологичных элементов, таких как укрепленные электромагнитные контуры, многочастотный ресивер с системой шифрования и облегченный гибридокерамический каркас.",
"description_zh": "F/41系列远距爆炸物是新伊甸中威力最大的手动触发式爆炸装置。每个爆炸装置性能稳定且威力巨大混合三种挥发性材料其威力足以穿透多层装甲、击碎强化结构并消灭步兵部队。这种炸药需要手动部署并通过皮层全息接口生成的编码频率引爆确保每次安放炸药时都有唯一的激活密码数据库。此外F/41产品线还有一些其他的高级功能比如电磁强化电路、加密多频接收器和轻型混合陶瓷结构。",
"descriptionID": 287827,
"groupID": 351844,
"mass": 0.0,
"portionSize": 1,
"published": 0,
"radius": 1.0,
"typeID": 364789,
"typeName_de": "Fernsprengsatz 'Hateshard'",
"typeName_en-us": "'Hateshard' Remote Explosive",
"typeName_es": "Explosivo remoto \"Hateshard\"",
"typeName_fr": "Explosif télécommandé « Hateshard »",
"typeName_it": "Esplosivo a controllo remoto \"Hateshard\"",
"typeName_ja": "「ヘイトシャード」リモート爆弾",
"typeName_ko": "'헤이트샤드' 원격 폭발물",
"typeName_ru": "Радиоуправляемое взрывное устройство 'Hateshard'",
"typeName_zh": "“憎恨”级远距爆炸物",
"typeNameID": 287826,
"volume": 0.01
},
"364790": {
"basePrice": 10770.0,
"capacity": 0.0,

View File

@@ -1,10 +1,10 @@
[
{
"field_name": "client_build",
"field_value": 3137986
"field_value": 3161404
},
{
"field_name": "dump_time",
"field_value": 1765458681
"field_value": 1768139181
}
]

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,7 @@ passenv = CI TRAVIS TRAVIS_*
deps =
-rrequirements.txt
-rrequirements_test.txt
basepython = python3.8
basepython = python3.11
commands = py.test -vv --cov Pyfa tests2/
[testenv:pep8]

863
uv.lock generated
View File

@@ -1,863 +0,0 @@
version = 1
revision = 3
requires-python = ">=3.12"
[[package]]
name = "attrs"
version = "25.4.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/6b/5c/685e6633917e101e5dcb62b9dd76946cbb57c26e133bae9e0cd36033c0a9/attrs-25.4.0.tar.gz", hash = "sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11", size = 934251, upload-time = "2025-10-06T13:54:44.725Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl", hash = "sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373", size = 67615, upload-time = "2025-10-06T13:54:43.17Z" },
]
[[package]]
name = "beautifulsoup4"
version = "4.12.2"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "soupsieve" },
]
sdist = { url = "https://files.pythonhosted.org/packages/af/0b/44c39cf3b18a9280950ad63a579ce395dda4c32193ee9da7ff0aed547094/beautifulsoup4-4.12.2.tar.gz", hash = "sha256:492bbc69dca35d12daac71c4db1bfff0c876c00ef4a2ffacce226d4638eb72da", size = 505113, upload-time = "2023-04-07T15:02:49.038Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/57/f4/a69c20ee4f660081a7dedb1ac57f29be9378e04edfcb90c526b923d4bebc/beautifulsoup4-4.12.2-py3-none-any.whl", hash = "sha256:bd2520ca0d9d7d12694a53d44ac482d181b4ec1888909b035a3dbf40d0f57d4a", size = 142979, upload-time = "2023-04-07T15:02:50.77Z" },
]
[[package]]
name = "cattrs"
version = "25.3.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "attrs" },
{ name = "typing-extensions" },
]
sdist = { url = "https://files.pythonhosted.org/packages/6e/00/2432bb2d445b39b5407f0a90e01b9a271475eea7caf913d7a86bcb956385/cattrs-25.3.0.tar.gz", hash = "sha256:1ac88d9e5eda10436c4517e390a4142d88638fe682c436c93db7ce4a277b884a", size = 509321, upload-time = "2025-10-07T12:26:08.737Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/d8/2b/a40e1488fdfa02d3f9a653a61a5935ea08b3c2225ee818db6a76c7ba9695/cattrs-25.3.0-py3-none-any.whl", hash = "sha256:9896e84e0a5bf723bc7b4b68f4481785367ce07a8a02e7e9ee6eb2819bc306ff", size = 70738, upload-time = "2025-10-07T12:26:06.603Z" },
]
[[package]]
name = "certifi"
version = "2025.11.12"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/a2/8c/58f469717fa48465e4a50c014a0400602d3c437d7c0c468e17ada824da3a/certifi-2025.11.12.tar.gz", hash = "sha256:d8ab5478f2ecd78af242878415affce761ca6bc54a22a27e026d7c25357c3316", size = 160538, upload-time = "2025-11-12T02:54:51.517Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl", hash = "sha256:97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b", size = 159438, upload-time = "2025-11-12T02:54:49.735Z" },
]
[[package]]
name = "cffi"
version = "2.0.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pycparser", marker = "implementation_name != 'PyPy'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/ea/47/4f61023ea636104d4f16ab488e268b93008c3d0bb76893b1b31db1f96802/cffi-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d", size = 185271, upload-time = "2025-09-08T23:22:44.795Z" },
{ url = "https://files.pythonhosted.org/packages/df/a2/781b623f57358e360d62cdd7a8c681f074a71d445418a776eef0aadb4ab4/cffi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c", size = 181048, upload-time = "2025-09-08T23:22:45.938Z" },
{ url = "https://files.pythonhosted.org/packages/ff/df/a4f0fbd47331ceeba3d37c2e51e9dfc9722498becbeec2bd8bc856c9538a/cffi-2.0.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe", size = 212529, upload-time = "2025-09-08T23:22:47.349Z" },
{ url = "https://files.pythonhosted.org/packages/d5/72/12b5f8d3865bf0f87cf1404d8c374e7487dcf097a1c91c436e72e6badd83/cffi-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062", size = 220097, upload-time = "2025-09-08T23:22:48.677Z" },
{ url = "https://files.pythonhosted.org/packages/c2/95/7a135d52a50dfa7c882ab0ac17e8dc11cec9d55d2c18dda414c051c5e69e/cffi-2.0.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e", size = 207983, upload-time = "2025-09-08T23:22:50.06Z" },
{ url = "https://files.pythonhosted.org/packages/3a/c8/15cb9ada8895957ea171c62dc78ff3e99159ee7adb13c0123c001a2546c1/cffi-2.0.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037", size = 206519, upload-time = "2025-09-08T23:22:51.364Z" },
{ url = "https://files.pythonhosted.org/packages/78/2d/7fa73dfa841b5ac06c7b8855cfc18622132e365f5b81d02230333ff26e9e/cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba", size = 219572, upload-time = "2025-09-08T23:22:52.902Z" },
{ url = "https://files.pythonhosted.org/packages/07/e0/267e57e387b4ca276b90f0434ff88b2c2241ad72b16d31836adddfd6031b/cffi-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94", size = 222963, upload-time = "2025-09-08T23:22:54.518Z" },
{ url = "https://files.pythonhosted.org/packages/b6/75/1f2747525e06f53efbd878f4d03bac5b859cbc11c633d0fb81432d98a795/cffi-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187", size = 221361, upload-time = "2025-09-08T23:22:55.867Z" },
{ url = "https://files.pythonhosted.org/packages/7b/2b/2b6435f76bfeb6bbf055596976da087377ede68df465419d192acf00c437/cffi-2.0.0-cp312-cp312-win32.whl", hash = "sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18", size = 172932, upload-time = "2025-09-08T23:22:57.188Z" },
{ url = "https://files.pythonhosted.org/packages/f8/ed/13bd4418627013bec4ed6e54283b1959cf6db888048c7cf4b4c3b5b36002/cffi-2.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5", size = 183557, upload-time = "2025-09-08T23:22:58.351Z" },
{ url = "https://files.pythonhosted.org/packages/95/31/9f7f93ad2f8eff1dbc1c3656d7ca5bfd8fb52c9d786b4dcf19b2d02217fa/cffi-2.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6", size = 177762, upload-time = "2025-09-08T23:22:59.668Z" },
{ url = "https://files.pythonhosted.org/packages/4b/8d/a0a47a0c9e413a658623d014e91e74a50cdd2c423f7ccfd44086ef767f90/cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb", size = 185230, upload-time = "2025-09-08T23:23:00.879Z" },
{ url = "https://files.pythonhosted.org/packages/4a/d2/a6c0296814556c68ee32009d9c2ad4f85f2707cdecfd7727951ec228005d/cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca", size = 181043, upload-time = "2025-09-08T23:23:02.231Z" },
{ url = "https://files.pythonhosted.org/packages/b0/1e/d22cc63332bd59b06481ceaac49d6c507598642e2230f201649058a7e704/cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b", size = 212446, upload-time = "2025-09-08T23:23:03.472Z" },
{ url = "https://files.pythonhosted.org/packages/a9/f5/a2c23eb03b61a0b8747f211eb716446c826ad66818ddc7810cc2cc19b3f2/cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b", size = 220101, upload-time = "2025-09-08T23:23:04.792Z" },
{ url = "https://files.pythonhosted.org/packages/f2/7f/e6647792fc5850d634695bc0e6ab4111ae88e89981d35ac269956605feba/cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2", size = 207948, upload-time = "2025-09-08T23:23:06.127Z" },
{ url = "https://files.pythonhosted.org/packages/cb/1e/a5a1bd6f1fb30f22573f76533de12a00bf274abcdc55c8edab639078abb6/cffi-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3", size = 206422, upload-time = "2025-09-08T23:23:07.753Z" },
{ url = "https://files.pythonhosted.org/packages/98/df/0a1755e750013a2081e863e7cd37e0cdd02664372c754e5560099eb7aa44/cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26", size = 219499, upload-time = "2025-09-08T23:23:09.648Z" },
{ url = "https://files.pythonhosted.org/packages/50/e1/a969e687fcf9ea58e6e2a928ad5e2dd88cc12f6f0ab477e9971f2309b57c/cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c", size = 222928, upload-time = "2025-09-08T23:23:10.928Z" },
{ url = "https://files.pythonhosted.org/packages/36/54/0362578dd2c9e557a28ac77698ed67323ed5b9775ca9d3fe73fe191bb5d8/cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b", size = 221302, upload-time = "2025-09-08T23:23:12.42Z" },
{ url = "https://files.pythonhosted.org/packages/eb/6d/bf9bda840d5f1dfdbf0feca87fbdb64a918a69bca42cfa0ba7b137c48cb8/cffi-2.0.0-cp313-cp313-win32.whl", hash = "sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27", size = 172909, upload-time = "2025-09-08T23:23:14.32Z" },
{ url = "https://files.pythonhosted.org/packages/37/18/6519e1ee6f5a1e579e04b9ddb6f1676c17368a7aba48299c3759bbc3c8b3/cffi-2.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75", size = 183402, upload-time = "2025-09-08T23:23:15.535Z" },
{ url = "https://files.pythonhosted.org/packages/cb/0e/02ceeec9a7d6ee63bb596121c2c8e9b3a9e150936f4fbef6ca1943e6137c/cffi-2.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91", size = 177780, upload-time = "2025-09-08T23:23:16.761Z" },
{ url = "https://files.pythonhosted.org/packages/92/c4/3ce07396253a83250ee98564f8d7e9789fab8e58858f35d07a9a2c78de9f/cffi-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5", size = 185320, upload-time = "2025-09-08T23:23:18.087Z" },
{ url = "https://files.pythonhosted.org/packages/59/dd/27e9fa567a23931c838c6b02d0764611c62290062a6d4e8ff7863daf9730/cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13", size = 181487, upload-time = "2025-09-08T23:23:19.622Z" },
{ url = "https://files.pythonhosted.org/packages/d6/43/0e822876f87ea8a4ef95442c3d766a06a51fc5298823f884ef87aaad168c/cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b", size = 220049, upload-time = "2025-09-08T23:23:20.853Z" },
{ url = "https://files.pythonhosted.org/packages/b4/89/76799151d9c2d2d1ead63c2429da9ea9d7aac304603de0c6e8764e6e8e70/cffi-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c", size = 207793, upload-time = "2025-09-08T23:23:22.08Z" },
{ url = "https://files.pythonhosted.org/packages/bb/dd/3465b14bb9e24ee24cb88c9e3730f6de63111fffe513492bf8c808a3547e/cffi-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef", size = 206300, upload-time = "2025-09-08T23:23:23.314Z" },
{ url = "https://files.pythonhosted.org/packages/47/d9/d83e293854571c877a92da46fdec39158f8d7e68da75bf73581225d28e90/cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775", size = 219244, upload-time = "2025-09-08T23:23:24.541Z" },
{ url = "https://files.pythonhosted.org/packages/2b/0f/1f177e3683aead2bb00f7679a16451d302c436b5cbf2505f0ea8146ef59e/cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205", size = 222828, upload-time = "2025-09-08T23:23:26.143Z" },
{ url = "https://files.pythonhosted.org/packages/c6/0f/cafacebd4b040e3119dcb32fed8bdef8dfe94da653155f9d0b9dc660166e/cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1", size = 220926, upload-time = "2025-09-08T23:23:27.873Z" },
{ url = "https://files.pythonhosted.org/packages/3e/aa/df335faa45b395396fcbc03de2dfcab242cd61a9900e914fe682a59170b1/cffi-2.0.0-cp314-cp314-win32.whl", hash = "sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f", size = 175328, upload-time = "2025-09-08T23:23:44.61Z" },
{ url = "https://files.pythonhosted.org/packages/bb/92/882c2d30831744296ce713f0feb4c1cd30f346ef747b530b5318715cc367/cffi-2.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25", size = 185650, upload-time = "2025-09-08T23:23:45.848Z" },
{ url = "https://files.pythonhosted.org/packages/9f/2c/98ece204b9d35a7366b5b2c6539c350313ca13932143e79dc133ba757104/cffi-2.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad", size = 180687, upload-time = "2025-09-08T23:23:47.105Z" },
{ url = "https://files.pythonhosted.org/packages/3e/61/c768e4d548bfa607abcda77423448df8c471f25dbe64fb2ef6d555eae006/cffi-2.0.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9", size = 188773, upload-time = "2025-09-08T23:23:29.347Z" },
{ url = "https://files.pythonhosted.org/packages/2c/ea/5f76bce7cf6fcd0ab1a1058b5af899bfbef198bea4d5686da88471ea0336/cffi-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d", size = 185013, upload-time = "2025-09-08T23:23:30.63Z" },
{ url = "https://files.pythonhosted.org/packages/be/b4/c56878d0d1755cf9caa54ba71e5d049479c52f9e4afc230f06822162ab2f/cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c", size = 221593, upload-time = "2025-09-08T23:23:31.91Z" },
{ url = "https://files.pythonhosted.org/packages/e0/0d/eb704606dfe8033e7128df5e90fee946bbcb64a04fcdaa97321309004000/cffi-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8", size = 209354, upload-time = "2025-09-08T23:23:33.214Z" },
{ url = "https://files.pythonhosted.org/packages/d8/19/3c435d727b368ca475fb8742ab97c9cb13a0de600ce86f62eab7fa3eea60/cffi-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc", size = 208480, upload-time = "2025-09-08T23:23:34.495Z" },
{ url = "https://files.pythonhosted.org/packages/d0/44/681604464ed9541673e486521497406fadcc15b5217c3e326b061696899a/cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592", size = 221584, upload-time = "2025-09-08T23:23:36.096Z" },
{ url = "https://files.pythonhosted.org/packages/25/8e/342a504ff018a2825d395d44d63a767dd8ebc927ebda557fecdaca3ac33a/cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512", size = 224443, upload-time = "2025-09-08T23:23:37.328Z" },
{ url = "https://files.pythonhosted.org/packages/e1/5e/b666bacbbc60fbf415ba9988324a132c9a7a0448a9a8f125074671c0f2c3/cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4", size = 223437, upload-time = "2025-09-08T23:23:38.945Z" },
{ url = "https://files.pythonhosted.org/packages/a0/1d/ec1a60bd1a10daa292d3cd6bb0b359a81607154fb8165f3ec95fe003b85c/cffi-2.0.0-cp314-cp314t-win32.whl", hash = "sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e", size = 180487, upload-time = "2025-09-08T23:23:40.423Z" },
{ url = "https://files.pythonhosted.org/packages/bf/41/4c1168c74fac325c0c8156f04b6749c8b6a8f405bbf91413ba088359f60d/cffi-2.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6", size = 191726, upload-time = "2025-09-08T23:23:41.742Z" },
{ url = "https://files.pythonhosted.org/packages/ae/3a/dbeec9d1ee0844c679f6bb5d6ad4e9f198b1224f4e7a32825f47f6192b0c/cffi-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9", size = 184195, upload-time = "2025-09-08T23:23:43.004Z" },
]
[[package]]
name = "charset-normalizer"
version = "3.4.4"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/13/69/33ddede1939fdd074bce5434295f38fae7136463422fe4fd3e0e89b98062/charset_normalizer-3.4.4.tar.gz", hash = "sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a", size = 129418, upload-time = "2025-10-14T04:42:32.879Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/f3/85/1637cd4af66fa687396e757dec650f28025f2a2f5a5531a3208dc0ec43f2/charset_normalizer-3.4.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394", size = 208425, upload-time = "2025-10-14T04:40:53.353Z" },
{ url = "https://files.pythonhosted.org/packages/9d/6a/04130023fef2a0d9c62d0bae2649b69f7b7d8d24ea5536feef50551029df/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25", size = 148162, upload-time = "2025-10-14T04:40:54.558Z" },
{ url = "https://files.pythonhosted.org/packages/78/29/62328d79aa60da22c9e0b9a66539feae06ca0f5a4171ac4f7dc285b83688/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef", size = 144558, upload-time = "2025-10-14T04:40:55.677Z" },
{ url = "https://files.pythonhosted.org/packages/86/bb/b32194a4bf15b88403537c2e120b817c61cd4ecffa9b6876e941c3ee38fe/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d", size = 161497, upload-time = "2025-10-14T04:40:57.217Z" },
{ url = "https://files.pythonhosted.org/packages/19/89/a54c82b253d5b9b111dc74aca196ba5ccfcca8242d0fb64146d4d3183ff1/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8", size = 159240, upload-time = "2025-10-14T04:40:58.358Z" },
{ url = "https://files.pythonhosted.org/packages/c0/10/d20b513afe03acc89ec33948320a5544d31f21b05368436d580dec4e234d/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86", size = 153471, upload-time = "2025-10-14T04:40:59.468Z" },
{ url = "https://files.pythonhosted.org/packages/61/fa/fbf177b55bdd727010f9c0a3c49eefa1d10f960e5f09d1d887bf93c2e698/charset_normalizer-3.4.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a", size = 150864, upload-time = "2025-10-14T04:41:00.623Z" },
{ url = "https://files.pythonhosted.org/packages/05/12/9fbc6a4d39c0198adeebbde20b619790e9236557ca59fc40e0e3cebe6f40/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f", size = 150647, upload-time = "2025-10-14T04:41:01.754Z" },
{ url = "https://files.pythonhosted.org/packages/ad/1f/6a9a593d52e3e8c5d2b167daf8c6b968808efb57ef4c210acb907c365bc4/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc", size = 145110, upload-time = "2025-10-14T04:41:03.231Z" },
{ url = "https://files.pythonhosted.org/packages/30/42/9a52c609e72471b0fc54386dc63c3781a387bb4fe61c20231a4ebcd58bdd/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf", size = 162839, upload-time = "2025-10-14T04:41:04.715Z" },
{ url = "https://files.pythonhosted.org/packages/c4/5b/c0682bbf9f11597073052628ddd38344a3d673fda35a36773f7d19344b23/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15", size = 150667, upload-time = "2025-10-14T04:41:05.827Z" },
{ url = "https://files.pythonhosted.org/packages/e4/24/a41afeab6f990cf2daf6cb8c67419b63b48cf518e4f56022230840c9bfb2/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9", size = 160535, upload-time = "2025-10-14T04:41:06.938Z" },
{ url = "https://files.pythonhosted.org/packages/2a/e5/6a4ce77ed243c4a50a1fecca6aaaab419628c818a49434be428fe24c9957/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0", size = 154816, upload-time = "2025-10-14T04:41:08.101Z" },
{ url = "https://files.pythonhosted.org/packages/a8/ef/89297262b8092b312d29cdb2517cb1237e51db8ecef2e9af5edbe7b683b1/charset_normalizer-3.4.4-cp312-cp312-win32.whl", hash = "sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26", size = 99694, upload-time = "2025-10-14T04:41:09.23Z" },
{ url = "https://files.pythonhosted.org/packages/3d/2d/1e5ed9dd3b3803994c155cd9aacb60c82c331bad84daf75bcb9c91b3295e/charset_normalizer-3.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525", size = 107131, upload-time = "2025-10-14T04:41:10.467Z" },
{ url = "https://files.pythonhosted.org/packages/d0/d9/0ed4c7098a861482a7b6a95603edce4c0d9db2311af23da1fb2b75ec26fc/charset_normalizer-3.4.4-cp312-cp312-win_arm64.whl", hash = "sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3", size = 100390, upload-time = "2025-10-14T04:41:11.915Z" },
{ url = "https://files.pythonhosted.org/packages/97/45/4b3a1239bbacd321068ea6e7ac28875b03ab8bc0aa0966452db17cd36714/charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794", size = 208091, upload-time = "2025-10-14T04:41:13.346Z" },
{ url = "https://files.pythonhosted.org/packages/7d/62/73a6d7450829655a35bb88a88fca7d736f9882a27eacdca2c6d505b57e2e/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed", size = 147936, upload-time = "2025-10-14T04:41:14.461Z" },
{ url = "https://files.pythonhosted.org/packages/89/c5/adb8c8b3d6625bef6d88b251bbb0d95f8205831b987631ab0c8bb5d937c2/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72", size = 144180, upload-time = "2025-10-14T04:41:15.588Z" },
{ url = "https://files.pythonhosted.org/packages/91/ed/9706e4070682d1cc219050b6048bfd293ccf67b3d4f5a4f39207453d4b99/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328", size = 161346, upload-time = "2025-10-14T04:41:16.738Z" },
{ url = "https://files.pythonhosted.org/packages/d5/0d/031f0d95e4972901a2f6f09ef055751805ff541511dc1252ba3ca1f80cf5/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede", size = 158874, upload-time = "2025-10-14T04:41:17.923Z" },
{ url = "https://files.pythonhosted.org/packages/f5/83/6ab5883f57c9c801ce5e5677242328aa45592be8a00644310a008d04f922/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894", size = 153076, upload-time = "2025-10-14T04:41:19.106Z" },
{ url = "https://files.pythonhosted.org/packages/75/1e/5ff781ddf5260e387d6419959ee89ef13878229732732ee73cdae01800f2/charset_normalizer-3.4.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1", size = 150601, upload-time = "2025-10-14T04:41:20.245Z" },
{ url = "https://files.pythonhosted.org/packages/d7/57/71be810965493d3510a6ca79b90c19e48696fb1ff964da319334b12677f0/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490", size = 150376, upload-time = "2025-10-14T04:41:21.398Z" },
{ url = "https://files.pythonhosted.org/packages/e5/d5/c3d057a78c181d007014feb7e9f2e65905a6c4ef182c0ddf0de2924edd65/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44", size = 144825, upload-time = "2025-10-14T04:41:22.583Z" },
{ url = "https://files.pythonhosted.org/packages/e6/8c/d0406294828d4976f275ffbe66f00266c4b3136b7506941d87c00cab5272/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133", size = 162583, upload-time = "2025-10-14T04:41:23.754Z" },
{ url = "https://files.pythonhosted.org/packages/d7/24/e2aa1f18c8f15c4c0e932d9287b8609dd30ad56dbe41d926bd846e22fb8d/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3", size = 150366, upload-time = "2025-10-14T04:41:25.27Z" },
{ url = "https://files.pythonhosted.org/packages/e4/5b/1e6160c7739aad1e2df054300cc618b06bf784a7a164b0f238360721ab86/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e", size = 160300, upload-time = "2025-10-14T04:41:26.725Z" },
{ url = "https://files.pythonhosted.org/packages/7a/10/f882167cd207fbdd743e55534d5d9620e095089d176d55cb22d5322f2afd/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc", size = 154465, upload-time = "2025-10-14T04:41:28.322Z" },
{ url = "https://files.pythonhosted.org/packages/89/66/c7a9e1b7429be72123441bfdbaf2bc13faab3f90b933f664db506dea5915/charset_normalizer-3.4.4-cp313-cp313-win32.whl", hash = "sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac", size = 99404, upload-time = "2025-10-14T04:41:29.95Z" },
{ url = "https://files.pythonhosted.org/packages/c4/26/b9924fa27db384bdcd97ab83b4f0a8058d96ad9626ead570674d5e737d90/charset_normalizer-3.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14", size = 107092, upload-time = "2025-10-14T04:41:31.188Z" },
{ url = "https://files.pythonhosted.org/packages/af/8f/3ed4bfa0c0c72a7ca17f0380cd9e4dd842b09f664e780c13cff1dcf2ef1b/charset_normalizer-3.4.4-cp313-cp313-win_arm64.whl", hash = "sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2", size = 100408, upload-time = "2025-10-14T04:41:32.624Z" },
{ url = "https://files.pythonhosted.org/packages/2a/35/7051599bd493e62411d6ede36fd5af83a38f37c4767b92884df7301db25d/charset_normalizer-3.4.4-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd", size = 207746, upload-time = "2025-10-14T04:41:33.773Z" },
{ url = "https://files.pythonhosted.org/packages/10/9a/97c8d48ef10d6cd4fcead2415523221624bf58bcf68a802721a6bc807c8f/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb", size = 147889, upload-time = "2025-10-14T04:41:34.897Z" },
{ url = "https://files.pythonhosted.org/packages/10/bf/979224a919a1b606c82bd2c5fa49b5c6d5727aa47b4312bb27b1734f53cd/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e", size = 143641, upload-time = "2025-10-14T04:41:36.116Z" },
{ url = "https://files.pythonhosted.org/packages/ba/33/0ad65587441fc730dc7bd90e9716b30b4702dc7b617e6ba4997dc8651495/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14", size = 160779, upload-time = "2025-10-14T04:41:37.229Z" },
{ url = "https://files.pythonhosted.org/packages/67/ed/331d6b249259ee71ddea93f6f2f0a56cfebd46938bde6fcc6f7b9a3d0e09/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191", size = 159035, upload-time = "2025-10-14T04:41:38.368Z" },
{ url = "https://files.pythonhosted.org/packages/67/ff/f6b948ca32e4f2a4576aa129d8bed61f2e0543bf9f5f2b7fc3758ed005c9/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838", size = 152542, upload-time = "2025-10-14T04:41:39.862Z" },
{ url = "https://files.pythonhosted.org/packages/16/85/276033dcbcc369eb176594de22728541a925b2632f9716428c851b149e83/charset_normalizer-3.4.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6", size = 149524, upload-time = "2025-10-14T04:41:41.319Z" },
{ url = "https://files.pythonhosted.org/packages/9e/f2/6a2a1f722b6aba37050e626530a46a68f74e63683947a8acff92569f979a/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e", size = 150395, upload-time = "2025-10-14T04:41:42.539Z" },
{ url = "https://files.pythonhosted.org/packages/60/bb/2186cb2f2bbaea6338cad15ce23a67f9b0672929744381e28b0592676824/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c", size = 143680, upload-time = "2025-10-14T04:41:43.661Z" },
{ url = "https://files.pythonhosted.org/packages/7d/a5/bf6f13b772fbb2a90360eb620d52ed8f796f3c5caee8398c3b2eb7b1c60d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090", size = 162045, upload-time = "2025-10-14T04:41:44.821Z" },
{ url = "https://files.pythonhosted.org/packages/df/c5/d1be898bf0dc3ef9030c3825e5d3b83f2c528d207d246cbabe245966808d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152", size = 149687, upload-time = "2025-10-14T04:41:46.442Z" },
{ url = "https://files.pythonhosted.org/packages/a5/42/90c1f7b9341eef50c8a1cb3f098ac43b0508413f33affd762855f67a410e/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828", size = 160014, upload-time = "2025-10-14T04:41:47.631Z" },
{ url = "https://files.pythonhosted.org/packages/76/be/4d3ee471e8145d12795ab655ece37baed0929462a86e72372fd25859047c/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec", size = 154044, upload-time = "2025-10-14T04:41:48.81Z" },
{ url = "https://files.pythonhosted.org/packages/b0/6f/8f7af07237c34a1defe7defc565a9bc1807762f672c0fde711a4b22bf9c0/charset_normalizer-3.4.4-cp314-cp314-win32.whl", hash = "sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9", size = 99940, upload-time = "2025-10-14T04:41:49.946Z" },
{ url = "https://files.pythonhosted.org/packages/4b/51/8ade005e5ca5b0d80fb4aff72a3775b325bdc3d27408c8113811a7cbe640/charset_normalizer-3.4.4-cp314-cp314-win_amd64.whl", hash = "sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c", size = 107104, upload-time = "2025-10-14T04:41:51.051Z" },
{ url = "https://files.pythonhosted.org/packages/da/5f/6b8f83a55bb8278772c5ae54a577f3099025f9ade59d0136ac24a0df4bde/charset_normalizer-3.4.4-cp314-cp314-win_arm64.whl", hash = "sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2", size = 100743, upload-time = "2025-10-14T04:41:52.122Z" },
{ url = "https://files.pythonhosted.org/packages/0a/4c/925909008ed5a988ccbb72dcc897407e5d6d3bd72410d69e051fc0c14647/charset_normalizer-3.4.4-py3-none-any.whl", hash = "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f", size = 53402, upload-time = "2025-10-14T04:42:31.76Z" },
]
[[package]]
name = "contourpy"
version = "1.3.3"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "numpy" },
]
sdist = { url = "https://files.pythonhosted.org/packages/58/01/1253e6698a07380cd31a736d248a3f2a50a7c88779a1813da27503cadc2a/contourpy-1.3.3.tar.gz", hash = "sha256:083e12155b210502d0bca491432bb04d56dc3432f95a979b429f2848c3dbe880", size = 13466174, upload-time = "2025-07-26T12:03:12.549Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/be/45/adfee365d9ea3d853550b2e735f9d66366701c65db7855cd07621732ccfc/contourpy-1.3.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b08a32ea2f8e42cf1d4be3169a98dd4be32bafe4f22b6c4cb4ba810fa9e5d2cb", size = 293419, upload-time = "2025-07-26T12:01:21.16Z" },
{ url = "https://files.pythonhosted.org/packages/53/3e/405b59cfa13021a56bba395a6b3aca8cec012b45bf177b0eaf7a202cde2c/contourpy-1.3.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:556dba8fb6f5d8742f2923fe9457dbdd51e1049c4a43fd3986a0b14a1d815fc6", size = 273979, upload-time = "2025-07-26T12:01:22.448Z" },
{ url = "https://files.pythonhosted.org/packages/d4/1c/a12359b9b2ca3a845e8f7f9ac08bdf776114eb931392fcad91743e2ea17b/contourpy-1.3.3-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92d9abc807cf7d0e047b95ca5d957cf4792fcd04e920ca70d48add15c1a90ea7", size = 332653, upload-time = "2025-07-26T12:01:24.155Z" },
{ url = "https://files.pythonhosted.org/packages/63/12/897aeebfb475b7748ea67b61e045accdfcf0d971f8a588b67108ed7f5512/contourpy-1.3.3-cp312-cp312-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b2e8faa0ed68cb29af51edd8e24798bb661eac3bd9f65420c1887b6ca89987c8", size = 379536, upload-time = "2025-07-26T12:01:25.91Z" },
{ url = "https://files.pythonhosted.org/packages/43/8a/a8c584b82deb248930ce069e71576fc09bd7174bbd35183b7943fb1064fd/contourpy-1.3.3-cp312-cp312-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:626d60935cf668e70a5ce6ff184fd713e9683fb458898e4249b63be9e28286ea", size = 384397, upload-time = "2025-07-26T12:01:27.152Z" },
{ url = "https://files.pythonhosted.org/packages/cc/8f/ec6289987824b29529d0dfda0d74a07cec60e54b9c92f3c9da4c0ac732de/contourpy-1.3.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4d00e655fcef08aba35ec9610536bfe90267d7ab5ba944f7032549c55a146da1", size = 362601, upload-time = "2025-07-26T12:01:28.808Z" },
{ url = "https://files.pythonhosted.org/packages/05/0a/a3fe3be3ee2dceb3e615ebb4df97ae6f3828aa915d3e10549ce016302bd1/contourpy-1.3.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:451e71b5a7d597379ef572de31eeb909a87246974d960049a9848c3bc6c41bf7", size = 1331288, upload-time = "2025-07-26T12:01:31.198Z" },
{ url = "https://files.pythonhosted.org/packages/33/1d/acad9bd4e97f13f3e2b18a3977fe1b4a37ecf3d38d815333980c6c72e963/contourpy-1.3.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:459c1f020cd59fcfe6650180678a9993932d80d44ccde1fa1868977438f0b411", size = 1403386, upload-time = "2025-07-26T12:01:33.947Z" },
{ url = "https://files.pythonhosted.org/packages/cf/8f/5847f44a7fddf859704217a99a23a4f6417b10e5ab1256a179264561540e/contourpy-1.3.3-cp312-cp312-win32.whl", hash = "sha256:023b44101dfe49d7d53932be418477dba359649246075c996866106da069af69", size = 185018, upload-time = "2025-07-26T12:01:35.64Z" },
{ url = "https://files.pythonhosted.org/packages/19/e8/6026ed58a64563186a9ee3f29f41261fd1828f527dd93d33b60feca63352/contourpy-1.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:8153b8bfc11e1e4d75bcb0bff1db232f9e10b274e0929de9d608027e0d34ff8b", size = 226567, upload-time = "2025-07-26T12:01:36.804Z" },
{ url = "https://files.pythonhosted.org/packages/d1/e2/f05240d2c39a1ed228d8328a78b6f44cd695f7ef47beb3e684cf93604f86/contourpy-1.3.3-cp312-cp312-win_arm64.whl", hash = "sha256:07ce5ed73ecdc4a03ffe3e1b3e3c1166db35ae7584be76f65dbbe28a7791b0cc", size = 193655, upload-time = "2025-07-26T12:01:37.999Z" },
{ url = "https://files.pythonhosted.org/packages/68/35/0167aad910bbdb9599272bd96d01a9ec6852f36b9455cf2ca67bd4cc2d23/contourpy-1.3.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:177fb367556747a686509d6fef71d221a4b198a3905fe824430e5ea0fda54eb5", size = 293257, upload-time = "2025-07-26T12:01:39.367Z" },
{ url = "https://files.pythonhosted.org/packages/96/e4/7adcd9c8362745b2210728f209bfbcf7d91ba868a2c5f40d8b58f54c509b/contourpy-1.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d002b6f00d73d69333dac9d0b8d5e84d9724ff9ef044fd63c5986e62b7c9e1b1", size = 274034, upload-time = "2025-07-26T12:01:40.645Z" },
{ url = "https://files.pythonhosted.org/packages/73/23/90e31ceeed1de63058a02cb04b12f2de4b40e3bef5e082a7c18d9c8ae281/contourpy-1.3.3-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:348ac1f5d4f1d66d3322420f01d42e43122f43616e0f194fc1c9f5d830c5b286", size = 334672, upload-time = "2025-07-26T12:01:41.942Z" },
{ url = "https://files.pythonhosted.org/packages/ed/93/b43d8acbe67392e659e1d984700e79eb67e2acb2bd7f62012b583a7f1b55/contourpy-1.3.3-cp313-cp313-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:655456777ff65c2c548b7c454af9c6f33f16c8884f11083244b5819cc214f1b5", size = 381234, upload-time = "2025-07-26T12:01:43.499Z" },
{ url = "https://files.pythonhosted.org/packages/46/3b/bec82a3ea06f66711520f75a40c8fc0b113b2a75edb36aa633eb11c4f50f/contourpy-1.3.3-cp313-cp313-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:644a6853d15b2512d67881586bd03f462c7ab755db95f16f14d7e238f2852c67", size = 385169, upload-time = "2025-07-26T12:01:45.219Z" },
{ url = "https://files.pythonhosted.org/packages/4b/32/e0f13a1c5b0f8572d0ec6ae2f6c677b7991fafd95da523159c19eff0696a/contourpy-1.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4debd64f124ca62069f313a9cb86656ff087786016d76927ae2cf37846b006c9", size = 362859, upload-time = "2025-07-26T12:01:46.519Z" },
{ url = "https://files.pythonhosted.org/packages/33/71/e2a7945b7de4e58af42d708a219f3b2f4cff7386e6b6ab0a0fa0033c49a9/contourpy-1.3.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a15459b0f4615b00bbd1e91f1b9e19b7e63aea7483d03d804186f278c0af2659", size = 1332062, upload-time = "2025-07-26T12:01:48.964Z" },
{ url = "https://files.pythonhosted.org/packages/12/fc/4e87ac754220ccc0e807284f88e943d6d43b43843614f0a8afa469801db0/contourpy-1.3.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ca0fdcd73925568ca027e0b17ab07aad764be4706d0a925b89227e447d9737b7", size = 1403932, upload-time = "2025-07-26T12:01:51.979Z" },
{ url = "https://files.pythonhosted.org/packages/a6/2e/adc197a37443f934594112222ac1aa7dc9a98faf9c3842884df9a9d8751d/contourpy-1.3.3-cp313-cp313-win32.whl", hash = "sha256:b20c7c9a3bf701366556e1b1984ed2d0cedf999903c51311417cf5f591d8c78d", size = 185024, upload-time = "2025-07-26T12:01:53.245Z" },
{ url = "https://files.pythonhosted.org/packages/18/0b/0098c214843213759692cc638fce7de5c289200a830e5035d1791d7a2338/contourpy-1.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:1cadd8b8969f060ba45ed7c1b714fe69185812ab43bd6b86a9123fe8f99c3263", size = 226578, upload-time = "2025-07-26T12:01:54.422Z" },
{ url = "https://files.pythonhosted.org/packages/8a/9a/2f6024a0c5995243cd63afdeb3651c984f0d2bc727fd98066d40e141ad73/contourpy-1.3.3-cp313-cp313-win_arm64.whl", hash = "sha256:fd914713266421b7536de2bfa8181aa8c699432b6763a0ea64195ebe28bff6a9", size = 193524, upload-time = "2025-07-26T12:01:55.73Z" },
{ url = "https://files.pythonhosted.org/packages/c0/b3/f8a1a86bd3298513f500e5b1f5fd92b69896449f6cab6a146a5d52715479/contourpy-1.3.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:88df9880d507169449d434c293467418b9f6cbe82edd19284aa0409e7fdb933d", size = 306730, upload-time = "2025-07-26T12:01:57.051Z" },
{ url = "https://files.pythonhosted.org/packages/3f/11/4780db94ae62fc0c2053909b65dc3246bd7cecfc4f8a20d957ad43aa4ad8/contourpy-1.3.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:d06bb1f751ba5d417047db62bca3c8fde202b8c11fb50742ab3ab962c81e8216", size = 287897, upload-time = "2025-07-26T12:01:58.663Z" },
{ url = "https://files.pythonhosted.org/packages/ae/15/e59f5f3ffdd6f3d4daa3e47114c53daabcb18574a26c21f03dc9e4e42ff0/contourpy-1.3.3-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e4e6b05a45525357e382909a4c1600444e2a45b4795163d3b22669285591c1ae", size = 326751, upload-time = "2025-07-26T12:02:00.343Z" },
{ url = "https://files.pythonhosted.org/packages/0f/81/03b45cfad088e4770b1dcf72ea78d3802d04200009fb364d18a493857210/contourpy-1.3.3-cp313-cp313t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ab3074b48c4e2cf1a960e6bbeb7f04566bf36b1861d5c9d4d8ac04b82e38ba20", size = 375486, upload-time = "2025-07-26T12:02:02.128Z" },
{ url = "https://files.pythonhosted.org/packages/0c/ba/49923366492ffbdd4486e970d421b289a670ae8cf539c1ea9a09822b371a/contourpy-1.3.3-cp313-cp313t-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6c3d53c796f8647d6deb1abe867daeb66dcc8a97e8455efa729516b997b8ed99", size = 388106, upload-time = "2025-07-26T12:02:03.615Z" },
{ url = "https://files.pythonhosted.org/packages/9f/52/5b00ea89525f8f143651f9f03a0df371d3cbd2fccd21ca9b768c7a6500c2/contourpy-1.3.3-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:50ed930df7289ff2a8d7afeb9603f8289e5704755c7e5c3bbd929c90c817164b", size = 352548, upload-time = "2025-07-26T12:02:05.165Z" },
{ url = "https://files.pythonhosted.org/packages/32/1d/a209ec1a3a3452d490f6b14dd92e72280c99ae3d1e73da74f8277d4ee08f/contourpy-1.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4feffb6537d64b84877da813a5c30f1422ea5739566abf0bd18065ac040e120a", size = 1322297, upload-time = "2025-07-26T12:02:07.379Z" },
{ url = "https://files.pythonhosted.org/packages/bc/9e/46f0e8ebdd884ca0e8877e46a3f4e633f6c9c8c4f3f6e72be3fe075994aa/contourpy-1.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:2b7e9480ffe2b0cd2e787e4df64270e3a0440d9db8dc823312e2c940c167df7e", size = 1391023, upload-time = "2025-07-26T12:02:10.171Z" },
{ url = "https://files.pythonhosted.org/packages/b9/70/f308384a3ae9cd2209e0849f33c913f658d3326900d0ff5d378d6a1422d2/contourpy-1.3.3-cp313-cp313t-win32.whl", hash = "sha256:283edd842a01e3dcd435b1c5116798d661378d83d36d337b8dde1d16a5fc9ba3", size = 196157, upload-time = "2025-07-26T12:02:11.488Z" },
{ url = "https://files.pythonhosted.org/packages/b2/dd/880f890a6663b84d9e34a6f88cded89d78f0091e0045a284427cb6b18521/contourpy-1.3.3-cp313-cp313t-win_amd64.whl", hash = "sha256:87acf5963fc2b34825e5b6b048f40e3635dd547f590b04d2ab317c2619ef7ae8", size = 240570, upload-time = "2025-07-26T12:02:12.754Z" },
{ url = "https://files.pythonhosted.org/packages/80/99/2adc7d8ffead633234817ef8e9a87115c8a11927a94478f6bb3d3f4d4f7d/contourpy-1.3.3-cp313-cp313t-win_arm64.whl", hash = "sha256:3c30273eb2a55024ff31ba7d052dde990d7d8e5450f4bbb6e913558b3d6c2301", size = 199713, upload-time = "2025-07-26T12:02:14.4Z" },
{ url = "https://files.pythonhosted.org/packages/72/8b/4546f3ab60f78c514ffb7d01a0bd743f90de36f0019d1be84d0a708a580a/contourpy-1.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fde6c716d51c04b1c25d0b90364d0be954624a0ee9d60e23e850e8d48353d07a", size = 292189, upload-time = "2025-07-26T12:02:16.095Z" },
{ url = "https://files.pythonhosted.org/packages/fd/e1/3542a9cb596cadd76fcef413f19c79216e002623158befe6daa03dbfa88c/contourpy-1.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:cbedb772ed74ff5be440fa8eee9bd49f64f6e3fc09436d9c7d8f1c287b121d77", size = 273251, upload-time = "2025-07-26T12:02:17.524Z" },
{ url = "https://files.pythonhosted.org/packages/b1/71/f93e1e9471d189f79d0ce2497007731c1e6bf9ef6d1d61b911430c3db4e5/contourpy-1.3.3-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:22e9b1bd7a9b1d652cd77388465dc358dafcd2e217d35552424aa4f996f524f5", size = 335810, upload-time = "2025-07-26T12:02:18.9Z" },
{ url = "https://files.pythonhosted.org/packages/91/f9/e35f4c1c93f9275d4e38681a80506b5510e9327350c51f8d4a5a724d178c/contourpy-1.3.3-cp314-cp314-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a22738912262aa3e254e4f3cb079a95a67132fc5a063890e224393596902f5a4", size = 382871, upload-time = "2025-07-26T12:02:20.418Z" },
{ url = "https://files.pythonhosted.org/packages/b5/71/47b512f936f66a0a900d81c396a7e60d73419868fba959c61efed7a8ab46/contourpy-1.3.3-cp314-cp314-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:afe5a512f31ee6bd7d0dda52ec9864c984ca3d66664444f2d72e0dc4eb832e36", size = 386264, upload-time = "2025-07-26T12:02:21.916Z" },
{ url = "https://files.pythonhosted.org/packages/04/5f/9ff93450ba96b09c7c2b3f81c94de31c89f92292f1380261bd7195bea4ea/contourpy-1.3.3-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f64836de09927cba6f79dcd00fdd7d5329f3fccc633468507079c829ca4db4e3", size = 363819, upload-time = "2025-07-26T12:02:23.759Z" },
{ url = "https://files.pythonhosted.org/packages/3e/a6/0b185d4cc480ee494945cde102cb0149ae830b5fa17bf855b95f2e70ad13/contourpy-1.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1fd43c3be4c8e5fd6e4f2baeae35ae18176cf2e5cced681cca908addf1cdd53b", size = 1333650, upload-time = "2025-07-26T12:02:26.181Z" },
{ url = "https://files.pythonhosted.org/packages/43/d7/afdc95580ca56f30fbcd3060250f66cedbde69b4547028863abd8aa3b47e/contourpy-1.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6afc576f7b33cf00996e5c1102dc2a8f7cc89e39c0b55df93a0b78c1bd992b36", size = 1404833, upload-time = "2025-07-26T12:02:28.782Z" },
{ url = "https://files.pythonhosted.org/packages/e2/e2/366af18a6d386f41132a48f033cbd2102e9b0cf6345d35ff0826cd984566/contourpy-1.3.3-cp314-cp314-win32.whl", hash = "sha256:66c8a43a4f7b8df8b71ee1840e4211a3c8d93b214b213f590e18a1beca458f7d", size = 189692, upload-time = "2025-07-26T12:02:30.128Z" },
{ url = "https://files.pythonhosted.org/packages/7d/c2/57f54b03d0f22d4044b8afb9ca0e184f8b1afd57b4f735c2fa70883dc601/contourpy-1.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:cf9022ef053f2694e31d630feaacb21ea24224be1c3ad0520b13d844274614fd", size = 232424, upload-time = "2025-07-26T12:02:31.395Z" },
{ url = "https://files.pythonhosted.org/packages/18/79/a9416650df9b525737ab521aa181ccc42d56016d2123ddcb7b58e926a42c/contourpy-1.3.3-cp314-cp314-win_arm64.whl", hash = "sha256:95b181891b4c71de4bb404c6621e7e2390745f887f2a026b2d99e92c17892339", size = 198300, upload-time = "2025-07-26T12:02:32.956Z" },
{ url = "https://files.pythonhosted.org/packages/1f/42/38c159a7d0f2b7b9c04c64ab317042bb6952b713ba875c1681529a2932fe/contourpy-1.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:33c82d0138c0a062380332c861387650c82e4cf1747aaa6938b9b6516762e772", size = 306769, upload-time = "2025-07-26T12:02:34.2Z" },
{ url = "https://files.pythonhosted.org/packages/c3/6c/26a8205f24bca10974e77460de68d3d7c63e282e23782f1239f226fcae6f/contourpy-1.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ea37e7b45949df430fe649e5de8351c423430046a2af20b1c1961cae3afcda77", size = 287892, upload-time = "2025-07-26T12:02:35.807Z" },
{ url = "https://files.pythonhosted.org/packages/66/06/8a475c8ab718ebfd7925661747dbb3c3ee9c82ac834ccb3570be49d129f4/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d304906ecc71672e9c89e87c4675dc5c2645e1f4269a5063b99b0bb29f232d13", size = 326748, upload-time = "2025-07-26T12:02:37.193Z" },
{ url = "https://files.pythonhosted.org/packages/b4/a3/c5ca9f010a44c223f098fccd8b158bb1cb287378a31ac141f04730dc49be/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ca658cd1a680a5c9ea96dc61cdbae1e85c8f25849843aa799dfd3cb370ad4fbe", size = 375554, upload-time = "2025-07-26T12:02:38.894Z" },
{ url = "https://files.pythonhosted.org/packages/80/5b/68bd33ae63fac658a4145088c1e894405e07584a316738710b636c6d0333/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ab2fd90904c503739a75b7c8c5c01160130ba67944a7b77bbf36ef8054576e7f", size = 388118, upload-time = "2025-07-26T12:02:40.642Z" },
{ url = "https://files.pythonhosted.org/packages/40/52/4c285a6435940ae25d7410a6c36bda5145839bc3f0beb20c707cda18b9d2/contourpy-1.3.3-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b7301b89040075c30e5768810bc96a8e8d78085b47d8be6e4c3f5a0b4ed478a0", size = 352555, upload-time = "2025-07-26T12:02:42.25Z" },
{ url = "https://files.pythonhosted.org/packages/24/ee/3e81e1dd174f5c7fefe50e85d0892de05ca4e26ef1c9a59c2a57e43b865a/contourpy-1.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:2a2a8b627d5cc6b7c41a4beff6c5ad5eb848c88255fda4a8745f7e901b32d8e4", size = 1322295, upload-time = "2025-07-26T12:02:44.668Z" },
{ url = "https://files.pythonhosted.org/packages/3c/b2/6d913d4d04e14379de429057cd169e5e00f6c2af3bb13e1710bcbdb5da12/contourpy-1.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:fd6ec6be509c787f1caf6b247f0b1ca598bef13f4ddeaa126b7658215529ba0f", size = 1391027, upload-time = "2025-07-26T12:02:47.09Z" },
{ url = "https://files.pythonhosted.org/packages/93/8a/68a4ec5c55a2971213d29a9374913f7e9f18581945a7a31d1a39b5d2dfe5/contourpy-1.3.3-cp314-cp314t-win32.whl", hash = "sha256:e74a9a0f5e3fff48fb5a7f2fd2b9b70a3fe014a67522f79b7cca4c0c7e43c9ae", size = 202428, upload-time = "2025-07-26T12:02:48.691Z" },
{ url = "https://files.pythonhosted.org/packages/fa/96/fd9f641ffedc4fa3ace923af73b9d07e869496c9cc7a459103e6e978992f/contourpy-1.3.3-cp314-cp314t-win_amd64.whl", hash = "sha256:13b68d6a62db8eafaebb8039218921399baf6e47bf85006fd8529f2a08ef33fc", size = 250331, upload-time = "2025-07-26T12:02:50.137Z" },
{ url = "https://files.pythonhosted.org/packages/ae/8c/469afb6465b853afff216f9528ffda78a915ff880ed58813ba4faf4ba0b6/contourpy-1.3.3-cp314-cp314t-win_arm64.whl", hash = "sha256:b7448cb5a725bb1e35ce88771b86fba35ef418952474492cf7c764059933ff8b", size = 203831, upload-time = "2025-07-26T12:02:51.449Z" },
]
[[package]]
name = "cryptography"
version = "42.0.4"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "cffi", marker = "platform_python_implementation != 'PyPy'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/81/d8/214d25515bf6034dce99aba22eeb47443b14c82160114e3d3f33067c6d3b/cryptography-42.0.4.tar.gz", hash = "sha256:831a4b37accef30cccd34fcb916a5d7b5be3cbbe27268a02832c3e450aea39cb", size = 670311, upload-time = "2024-02-21T03:07:29.752Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/08/87/58a38f8f4d0fe388aaceec8d4b91644cc1edfe4fd3b9ccf5dad414f60738/cryptography-42.0.4-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:ffc73996c4fca3d2b6c1c8c12bfd3ad00def8621da24f547626bf06441400449", size = 5874004, upload-time = "2024-02-21T03:06:15.711Z" },
{ url = "https://files.pythonhosted.org/packages/ec/3a/2138a6246804d5d0b588031ad9795c7672317591a9ec2c5962cb65a912c3/cryptography-42.0.4-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:db4b65b02f59035037fde0998974d84244a64c3265bdef32a827ab9b63d61b18", size = 3098630, upload-time = "2024-02-21T03:07:08.813Z" },
{ url = "https://files.pythonhosted.org/packages/84/3d/f4e69dd3773826c12a7eeb7e7550616c0932e7c4cc3c677023964f137b46/cryptography-42.0.4-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad9c385ba8ee025bb0d856714f71d7840020fe176ae0229de618f14dae7a6e2", size = 4371589, upload-time = "2024-02-21T03:06:56.874Z" },
{ url = "https://files.pythonhosted.org/packages/2f/d1/6ca412147384b0b02cb343a3e8b7d3fde7ac6833c29fee9ca91f59ab5fdf/cryptography-42.0.4-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:69b22ab6506a3fe483d67d1ed878e1602bdd5912a134e6202c1ec672233241c1", size = 4561822, upload-time = "2024-02-21T03:06:41.423Z" },
{ url = "https://files.pythonhosted.org/packages/ba/c8/df35ce0519febdf46ebfab1a6ef1278c95a45b060a613fac57de64aa727e/cryptography-42.0.4-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:e09469a2cec88fb7b078e16d4adec594414397e8879a4341c6ace96013463d5b", size = 4355915, upload-time = "2024-02-21T03:06:34.924Z" },
{ url = "https://files.pythonhosted.org/packages/35/ed/e8ad5637b8ac1fd1b48fadb11dcf3649083af5c4298dfdc81d0382de9191/cryptography-42.0.4-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3e970a2119507d0b104f0a8e281521ad28fc26f2820687b3436b8c9a5fcf20d1", size = 4573394, upload-time = "2024-02-21T03:07:06.381Z" },
{ url = "https://files.pythonhosted.org/packages/27/98/c4a7fd53fd27619d5baa6102af7833543a8428479b81959942aeb98b278e/cryptography-42.0.4-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:e53dc41cda40b248ebc40b83b31516487f7db95ab8ceac1f042626bc43a2f992", size = 4471747, upload-time = "2024-02-21T03:06:18.099Z" },
{ url = "https://files.pythonhosted.org/packages/4a/dc/9beb49116370d8086a10d1dd0b5cbe7816efeebdfda414f3fd09a95b8525/cryptography-42.0.4-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:c3a5cbc620e1e17009f30dd34cb0d85c987afd21c41a74352d1719be33380885", size = 4646204, upload-time = "2024-02-21T03:06:50.63Z" },
{ url = "https://files.pythonhosted.org/packages/c0/a8/200e5afdb96ac3ebd4025dcc18cc43e73b1e4f6d839b7f2c9f1eb1a6a6c6/cryptography-42.0.4-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:6bfadd884e7280df24d26f2186e4e07556a05d37393b0f220a840b083dc6a824", size = 4444931, upload-time = "2024-02-21T03:07:13.485Z" },
{ url = "https://files.pythonhosted.org/packages/9d/74/3bbe47d186ed91e3fa7ffb4426f39cb63d299842a9c600f4834530599bd4/cryptography-42.0.4-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:01911714117642a3f1792c7f376db572aadadbafcd8d75bb527166009c9f1d1b", size = 4645892, upload-time = "2024-02-21T03:06:37.021Z" },
{ url = "https://files.pythonhosted.org/packages/3b/32/6d4907f82d2870959ad3dfc21f0a20b6501c143034d249df852281ae3543/cryptography-42.0.4-cp37-abi3-win32.whl", hash = "sha256:fb0cef872d8193e487fc6bdb08559c3aa41b659a7d9be48b2e10747f47863925", size = 2430337, upload-time = "2024-02-21T03:06:43.879Z" },
{ url = "https://files.pythonhosted.org/packages/d3/70/08b9cc6690e252541286fcfda770023a27aa0e1a1f8a1df52ee052c0494b/cryptography-42.0.4-cp37-abi3-win_amd64.whl", hash = "sha256:c1f25b252d2c87088abc8bbc4f1ecbf7c919e05508a7e8628e6875c40bc70923", size = 2885772, upload-time = "2024-02-21T03:07:19.763Z" },
{ url = "https://files.pythonhosted.org/packages/ba/71/b9ed937252fad47d8d24746b876ca6f2dc31bd495e78f5b77a5082d73ae2/cryptography-42.0.4-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:15a1fb843c48b4a604663fa30af60818cd28f895572386e5f9b8a665874c26e7", size = 5873636, upload-time = "2024-02-21T03:06:55.038Z" },
{ url = "https://files.pythonhosted.org/packages/44/61/644e21048102cd72a13325fd6443db741746fbf0157e7c5d5c7628afc336/cryptography-42.0.4-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1327f280c824ff7885bdeef8578f74690e9079267c1c8bd7dc5cc5aa065ae52", size = 4372889, upload-time = "2024-02-21T03:06:25.409Z" },
{ url = "https://files.pythonhosted.org/packages/32/c2/4ff3cf950504aa6ccd3db3712f515151536eea0cf6125442015b0532a46d/cryptography-42.0.4-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ffb03d419edcab93b4b19c22ee80c007fb2d708429cecebf1dd3258956a563a", size = 4561544, upload-time = "2024-02-21T03:06:20.715Z" },
{ url = "https://files.pythonhosted.org/packages/4c/e1/18056b2c0e4ba031ea6b9d660bc2bdf491f7ef64ab7ef1a803a03a8b8d26/cryptography-42.0.4-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:1df6fcbf60560d2113b5ed90f072dc0b108d64750d4cbd46a21ec882c7aefce9", size = 4357160, upload-time = "2024-02-21T03:07:22.468Z" },
{ url = "https://files.pythonhosted.org/packages/7e/45/81f378eb85aab14b229c1032ba3694eff85a3d75b35092c3e71abd2d34f6/cryptography-42.0.4-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:44a64043f743485925d3bcac548d05df0f9bb445c5fcca6681889c7c3ab12764", size = 4573002, upload-time = "2024-02-21T03:07:04.598Z" },
{ url = "https://files.pythonhosted.org/packages/ea/a1/04733ecbe1e77a228c738f4ab321ca050e45284997f3e3a1539461cd4bca/cryptography-42.0.4-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:3c6048f217533d89f2f8f4f0fe3044bf0b2090453b7b73d0b77db47b80af8dff", size = 4471962, upload-time = "2024-02-21T03:06:12.027Z" },
{ url = "https://files.pythonhosted.org/packages/41/5d/33f17e40dbb7441ad51e8a6920e726f68443cdbfb388cb8eff53e4b6ffd4/cryptography-42.0.4-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:6d0fbe73728c44ca3a241eff9aefe6496ab2656d6e7a4ea2459865f2e8613257", size = 4646395, upload-time = "2024-02-21T03:06:23.044Z" },
{ url = "https://files.pythonhosted.org/packages/da/56/1b2c8aa8e62bfb568022b68d77ebd2bd9afddea37898350fbfe008dcefa7/cryptography-42.0.4-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:887623fe0d70f48ab3f5e4dbf234986b1329a64c066d719432d0698522749929", size = 4445612, upload-time = "2024-02-21T03:06:58.673Z" },
{ url = "https://files.pythonhosted.org/packages/a2/8e/dac70232d4231c53448e29aa4b768cf82d891fcfd6e0caa7ace242da8c9b/cryptography-42.0.4-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:ce8613beaffc7c14f091497346ef117c1798c202b01153a8cc7b8e2ebaaf41c0", size = 4646026, upload-time = "2024-02-21T03:06:33.094Z" },
{ url = "https://files.pythonhosted.org/packages/a7/d7/8b9d29cf3745b928a71b1f6c3c54366272d8d67181d1f056309992d19640/cryptography-42.0.4-cp39-abi3-win32.whl", hash = "sha256:810bcf151caefc03e51a3d61e53335cd5c7316c0a105cc695f0959f2c638b129", size = 2430620, upload-time = "2024-02-21T03:07:17.818Z" },
{ url = "https://files.pythonhosted.org/packages/af/df/c220c1be23d1f0ee55f4d1589203936cfa221f95ac5d1b1b342109c1143e/cryptography-42.0.4-cp39-abi3-win_amd64.whl", hash = "sha256:a0298bdc6e98ca21382afe914c642620370ce0470a01e1bef6dd9b5354c36854", size = 2887348, upload-time = "2024-02-21T03:06:27.929Z" },
]
[[package]]
name = "cycler"
version = "0.12.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/a9/95/a3dbbb5028f35eafb79008e7522a75244477d2838f38cbb722248dabc2a8/cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c", size = 7615, upload-time = "2023-10-07T05:32:18.335Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30", size = 8321, upload-time = "2023-10-07T05:32:16.783Z" },
]
[[package]]
name = "ecdsa"
version = "0.19.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "six" },
]
sdist = { url = "https://files.pythonhosted.org/packages/c0/1f/924e3caae75f471eae4b26bd13b698f6af2c44279f67af317439c2f4c46a/ecdsa-0.19.1.tar.gz", hash = "sha256:478cba7b62555866fcb3bb3fe985e06decbdb68ef55713c4e5ab98c57d508e61", size = 201793, upload-time = "2025-03-13T11:52:43.25Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/cb/a3/460c57f094a4a165c84a1341c373b0a4f5ec6ac244b998d5021aade89b77/ecdsa-0.19.1-py2.py3-none-any.whl", hash = "sha256:30638e27cf77b7e15c4c4cc1973720149e1033827cfd00661ca5c8cc0cdb24c3", size = 150607, upload-time = "2025-03-13T11:52:41.757Z" },
]
[[package]]
name = "fonttools"
version = "4.61.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/ec/ca/cf17b88a8df95691275a3d77dc0a5ad9907f328ae53acbe6795da1b2f5ed/fonttools-4.61.1.tar.gz", hash = "sha256:6675329885c44657f826ef01d9e4fb33b9158e9d93c537d84ad8399539bc6f69", size = 3565756, upload-time = "2025-12-12T17:31:24.246Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/6f/16/7decaa24a1bd3a70c607b2e29f0adc6159f36a7e40eaba59846414765fd4/fonttools-4.61.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:f3cb4a569029b9f291f88aafc927dd53683757e640081ca8c412781ea144565e", size = 2851593, upload-time = "2025-12-12T17:30:04.225Z" },
{ url = "https://files.pythonhosted.org/packages/94/98/3c4cb97c64713a8cf499b3245c3bf9a2b8fd16a3e375feff2aed78f96259/fonttools-4.61.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:41a7170d042e8c0024703ed13b71893519a1a6d6e18e933e3ec7507a2c26a4b2", size = 2400231, upload-time = "2025-12-12T17:30:06.47Z" },
{ url = "https://files.pythonhosted.org/packages/b7/37/82dbef0f6342eb01f54bca073ac1498433d6ce71e50c3c3282b655733b31/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", size = 4954103, upload-time = "2025-12-12T17:30:08.432Z" },
{ url = "https://files.pythonhosted.org/packages/6c/44/f3aeac0fa98e7ad527f479e161aca6c3a1e47bb6996b053d45226fe37bf2/fonttools-4.61.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:15acc09befd16a0fb8a8f62bc147e1a82817542d72184acca9ce6e0aeda9fa6d", size = 5004295, upload-time = "2025-12-12T17:30:10.56Z" },
{ url = "https://files.pythonhosted.org/packages/14/e8/7424ced75473983b964d09f6747fa09f054a6d656f60e9ac9324cf40c743/fonttools-4.61.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e6bcdf33aec38d16508ce61fd81838f24c83c90a1d1b8c68982857038673d6b8", size = 4944109, upload-time = "2025-12-12T17:30:12.874Z" },
{ url = "https://files.pythonhosted.org/packages/c8/8b/6391b257fa3d0b553d73e778f953a2f0154292a7a7a085e2374b111e5410/fonttools-4.61.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5fade934607a523614726119164ff621e8c30e8fa1ffffbbd358662056ba69f0", size = 5093598, upload-time = "2025-12-12T17:30:15.79Z" },
{ url = "https://files.pythonhosted.org/packages/d9/71/fd2ea96cdc512d92da5678a1c98c267ddd4d8c5130b76d0f7a80f9a9fde8/fonttools-4.61.1-cp312-cp312-win32.whl", hash = "sha256:75da8f28eff26defba42c52986de97b22106cb8f26515b7c22443ebc9c2d3261", size = 2269060, upload-time = "2025-12-12T17:30:18.058Z" },
{ url = "https://files.pythonhosted.org/packages/80/3b/a3e81b71aed5a688e89dfe0e2694b26b78c7d7f39a5ffd8a7d75f54a12a8/fonttools-4.61.1-cp312-cp312-win_amd64.whl", hash = "sha256:497c31ce314219888c0e2fce5ad9178ca83fe5230b01a5006726cdf3ac9f24d9", size = 2319078, upload-time = "2025-12-12T17:30:22.862Z" },
{ url = "https://files.pythonhosted.org/packages/4b/cf/00ba28b0990982530addb8dc3e9e6f2fa9cb5c20df2abdda7baa755e8fe1/fonttools-4.61.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8c56c488ab471628ff3bfa80964372fc13504ece601e0d97a78ee74126b2045c", size = 2846454, upload-time = "2025-12-12T17:30:24.938Z" },
{ url = "https://files.pythonhosted.org/packages/5a/ca/468c9a8446a2103ae645d14fee3f610567b7042aba85031c1c65e3ef7471/fonttools-4.61.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:dc492779501fa723b04d0ab1f5be046797fee17d27700476edc7ee9ae535a61e", size = 2398191, upload-time = "2025-12-12T17:30:27.343Z" },
{ url = "https://files.pythonhosted.org/packages/a3/4b/d67eedaed19def5967fade3297fed8161b25ba94699efc124b14fb68cdbc/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", size = 4928410, upload-time = "2025-12-12T17:30:29.771Z" },
{ url = "https://files.pythonhosted.org/packages/b0/8d/6fb3494dfe61a46258cd93d979cf4725ded4eb46c2a4ca35e4490d84daea/fonttools-4.61.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4c1b526c8d3f615a7b1867f38a9410849c8f4aef078535742198e942fba0e9bd", size = 4984460, upload-time = "2025-12-12T17:30:32.073Z" },
{ url = "https://files.pythonhosted.org/packages/f7/f1/a47f1d30b3dc00d75e7af762652d4cbc3dff5c2697a0dbd5203c81afd9c3/fonttools-4.61.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:41ed4b5ec103bd306bb68f81dc166e77409e5209443e5773cb4ed837bcc9b0d3", size = 4925800, upload-time = "2025-12-12T17:30:34.339Z" },
{ url = "https://files.pythonhosted.org/packages/a7/01/e6ae64a0981076e8a66906fab01539799546181e32a37a0257b77e4aa88b/fonttools-4.61.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b501c862d4901792adaec7c25b1ecc749e2662543f68bb194c42ba18d6eec98d", size = 5067859, upload-time = "2025-12-12T17:30:36.593Z" },
{ url = "https://files.pythonhosted.org/packages/73/aa/28e40b8d6809a9b5075350a86779163f074d2b617c15d22343fce81918db/fonttools-4.61.1-cp313-cp313-win32.whl", hash = "sha256:4d7092bb38c53bbc78e9255a59158b150bcdc115a1e3b3ce0b5f267dc35dd63c", size = 2267821, upload-time = "2025-12-12T17:30:38.478Z" },
{ url = "https://files.pythonhosted.org/packages/1a/59/453c06d1d83dc0951b69ef692d6b9f1846680342927df54e9a1ca91c6f90/fonttools-4.61.1-cp313-cp313-win_amd64.whl", hash = "sha256:21e7c8d76f62ab13c9472ccf74515ca5b9a761d1bde3265152a6dc58700d895b", size = 2318169, upload-time = "2025-12-12T17:30:40.951Z" },
{ url = "https://files.pythonhosted.org/packages/32/8f/4e7bf82c0cbb738d3c2206c920ca34ca74ef9dabde779030145d28665104/fonttools-4.61.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:fff4f534200a04b4a36e7ae3cb74493afe807b517a09e99cb4faa89a34ed6ecd", size = 2846094, upload-time = "2025-12-12T17:30:43.511Z" },
{ url = "https://files.pythonhosted.org/packages/71/09/d44e45d0a4f3a651f23a1e9d42de43bc643cce2971b19e784cc67d823676/fonttools-4.61.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:d9203500f7c63545b4ce3799319fe4d9feb1a1b89b28d3cb5abd11b9dd64147e", size = 2396589, upload-time = "2025-12-12T17:30:45.681Z" },
{ url = "https://files.pythonhosted.org/packages/89/18/58c64cafcf8eb677a99ef593121f719e6dcbdb7d1c594ae5a10d4997ca8a/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", size = 4877892, upload-time = "2025-12-12T17:30:47.709Z" },
{ url = "https://files.pythonhosted.org/packages/8a/ec/9e6b38c7ba1e09eb51db849d5450f4c05b7e78481f662c3b79dbde6f3d04/fonttools-4.61.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:11f35ad7805edba3aac1a3710d104592df59f4b957e30108ae0ba6c10b11dd75", size = 4972884, upload-time = "2025-12-12T17:30:49.656Z" },
{ url = "https://files.pythonhosted.org/packages/5e/87/b5339da8e0256734ba0dbbf5b6cdebb1dd79b01dc8c270989b7bcd465541/fonttools-4.61.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b931ae8f62db78861b0ff1ac017851764602288575d65b8e8ff1963fed419063", size = 4924405, upload-time = "2025-12-12T17:30:51.735Z" },
{ url = "https://files.pythonhosted.org/packages/0b/47/e3409f1e1e69c073a3a6fd8cb886eb18c0bae0ee13db2c8d5e7f8495e8b7/fonttools-4.61.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b148b56f5de675ee16d45e769e69f87623a4944f7443850bf9a9376e628a89d2", size = 5035553, upload-time = "2025-12-12T17:30:54.823Z" },
{ url = "https://files.pythonhosted.org/packages/bf/b6/1f6600161b1073a984294c6c031e1a56ebf95b6164249eecf30012bb2e38/fonttools-4.61.1-cp314-cp314-win32.whl", hash = "sha256:9b666a475a65f4e839d3d10473fad6d47e0a9db14a2f4a224029c5bfde58ad2c", size = 2271915, upload-time = "2025-12-12T17:30:57.913Z" },
{ url = "https://files.pythonhosted.org/packages/52/7b/91e7b01e37cc8eb0e1f770d08305b3655e4f002fc160fb82b3390eabacf5/fonttools-4.61.1-cp314-cp314-win_amd64.whl", hash = "sha256:4f5686e1fe5fce75d82d93c47a438a25bf0d1319d2843a926f741140b2b16e0c", size = 2323487, upload-time = "2025-12-12T17:30:59.804Z" },
{ url = "https://files.pythonhosted.org/packages/39/5c/908ad78e46c61c3e3ed70c3b58ff82ab48437faf84ec84f109592cabbd9f/fonttools-4.61.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:e76ce097e3c57c4bcb67c5aa24a0ecdbd9f74ea9219997a707a4061fbe2707aa", size = 2929571, upload-time = "2025-12-12T17:31:02.574Z" },
{ url = "https://files.pythonhosted.org/packages/bd/41/975804132c6dea64cdbfbaa59f3518a21c137a10cccf962805b301ac6ab2/fonttools-4.61.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:9cfef3ab326780c04d6646f68d4b4742aae222e8b8ea1d627c74e38afcbc9d91", size = 2435317, upload-time = "2025-12-12T17:31:04.974Z" },
{ url = "https://files.pythonhosted.org/packages/b0/5a/aef2a0a8daf1ebaae4cfd83f84186d4a72ee08fd6a8451289fcd03ffa8a4/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", size = 4882124, upload-time = "2025-12-12T17:31:07.456Z" },
{ url = "https://files.pythonhosted.org/packages/80/33/d6db3485b645b81cea538c9d1c9219d5805f0877fda18777add4671c5240/fonttools-4.61.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:91669ccac46bbc1d09e9273546181919064e8df73488ea087dcac3e2968df9ba", size = 5100391, upload-time = "2025-12-12T17:31:09.732Z" },
{ url = "https://files.pythonhosted.org/packages/6c/d6/675ba631454043c75fcf76f0ca5463eac8eb0666ea1d7badae5fea001155/fonttools-4.61.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c33ab3ca9d3ccd581d58e989d67554e42d8d4ded94ab3ade3508455fe70e65f7", size = 4978800, upload-time = "2025-12-12T17:31:11.681Z" },
{ url = "https://files.pythonhosted.org/packages/7f/33/d3ec753d547a8d2bdaedd390d4a814e8d5b45a093d558f025c6b990b554c/fonttools-4.61.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:664c5a68ec406f6b1547946683008576ef8b38275608e1cee6c061828171c118", size = 5006426, upload-time = "2025-12-12T17:31:13.764Z" },
{ url = "https://files.pythonhosted.org/packages/b4/40/cc11f378b561a67bea850ab50063366a0d1dd3f6d0a30ce0f874b0ad5664/fonttools-4.61.1-cp314-cp314t-win32.whl", hash = "sha256:aed04cabe26f30c1647ef0e8fbb207516fd40fe9472e9439695f5c6998e60ac5", size = 2335377, upload-time = "2025-12-12T17:31:16.49Z" },
{ url = "https://files.pythonhosted.org/packages/e4/ff/c9a2b66b39f8628531ea58b320d66d951267c98c6a38684daa8f50fb02f8/fonttools-4.61.1-cp314-cp314t-win_amd64.whl", hash = "sha256:2180f14c141d2f0f3da43f3a81bc8aa4684860f6b0e6f9e165a4831f24e6a23b", size = 2400613, upload-time = "2025-12-12T17:31:18.769Z" },
{ url = "https://files.pythonhosted.org/packages/c7/4e/ce75a57ff3aebf6fc1f4e9d508b8e5810618a33d900ad6c19eb30b290b97/fonttools-4.61.1-py3-none-any.whl", hash = "sha256:17d2bf5d541add43822bcf0c43d7d847b160c9bb01d15d5007d84e2217aaa371", size = 1148996, upload-time = "2025-12-12T17:31:21.03Z" },
]
[[package]]
name = "greenlet"
version = "3.3.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/c7/e5/40dbda2736893e3e53d25838e0f19a2b417dfc122b9989c91918db30b5d3/greenlet-3.3.0.tar.gz", hash = "sha256:a82bb225a4e9e4d653dd2fb7b8b2d36e4fb25bc0165422a11e48b88e9e6f78fb", size = 190651, upload-time = "2025-12-04T14:49:44.05Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/f8/0a/a3871375c7b9727edaeeea994bfff7c63ff7804c9829c19309ba2e058807/greenlet-3.3.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:b01548f6e0b9e9784a2c99c5651e5dc89ffcbe870bc5fb2e5ef864e9cc6b5dcb", size = 276379, upload-time = "2025-12-04T14:23:30.498Z" },
{ url = "https://files.pythonhosted.org/packages/43/ab/7ebfe34dce8b87be0d11dae91acbf76f7b8246bf9d6b319c741f99fa59c6/greenlet-3.3.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:349345b770dc88f81506c6861d22a6ccd422207829d2c854ae2af8025af303e3", size = 597294, upload-time = "2025-12-04T14:50:06.847Z" },
{ url = "https://files.pythonhosted.org/packages/a4/39/f1c8da50024feecd0793dbd5e08f526809b8ab5609224a2da40aad3a7641/greenlet-3.3.0-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e8e18ed6995e9e2c0b4ed264d2cf89260ab3ac7e13555b8032b25a74c6d18655", size = 607742, upload-time = "2025-12-04T14:57:42.349Z" },
{ url = "https://files.pythonhosted.org/packages/77/cb/43692bcd5f7a0da6ec0ec6d58ee7cddb606d055ce94a62ac9b1aa481e969/greenlet-3.3.0-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c024b1e5696626890038e34f76140ed1daf858e37496d33f2af57f06189e70d7", size = 622297, upload-time = "2025-12-04T15:07:13.552Z" },
{ url = "https://files.pythonhosted.org/packages/75/b0/6bde0b1011a60782108c01de5913c588cf51a839174538d266de15e4bf4d/greenlet-3.3.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:047ab3df20ede6a57c35c14bf5200fcf04039d50f908270d3f9a7a82064f543b", size = 609885, upload-time = "2025-12-04T14:26:02.368Z" },
{ url = "https://files.pythonhosted.org/packages/49/0e/49b46ac39f931f59f987b7cd9f34bfec8ef81d2a1e6e00682f55be5de9f4/greenlet-3.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2d9ad37fc657b1102ec880e637cccf20191581f75c64087a549e66c57e1ceb53", size = 1567424, upload-time = "2025-12-04T15:04:23.757Z" },
{ url = "https://files.pythonhosted.org/packages/05/f5/49a9ac2dff7f10091935def9165c90236d8f175afb27cbed38fb1d61ab6b/greenlet-3.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:83cd0e36932e0e7f36a64b732a6f60c2fc2df28c351bae79fbaf4f8092fe7614", size = 1636017, upload-time = "2025-12-04T14:27:29.688Z" },
{ url = "https://files.pythonhosted.org/packages/6c/79/3912a94cf27ec503e51ba493692d6db1e3cd8ac7ac52b0b47c8e33d7f4f9/greenlet-3.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:a7a34b13d43a6b78abf828a6d0e87d3385680eaf830cd60d20d52f249faabf39", size = 301964, upload-time = "2025-12-04T14:36:58.316Z" },
{ url = "https://files.pythonhosted.org/packages/02/2f/28592176381b9ab2cafa12829ba7b472d177f3acc35d8fbcf3673d966fff/greenlet-3.3.0-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:a1e41a81c7e2825822f4e068c48cb2196002362619e2d70b148f20a831c00739", size = 275140, upload-time = "2025-12-04T14:23:01.282Z" },
{ url = "https://files.pythonhosted.org/packages/2c/80/fbe937bf81e9fca98c981fe499e59a3f45df2a04da0baa5c2be0dca0d329/greenlet-3.3.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9f515a47d02da4d30caaa85b69474cec77b7929b2e936ff7fb853d42f4bf8808", size = 599219, upload-time = "2025-12-04T14:50:08.309Z" },
{ url = "https://files.pythonhosted.org/packages/c2/ff/7c985128f0514271b8268476af89aee6866df5eec04ac17dcfbc676213df/greenlet-3.3.0-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7d2d9fd66bfadf230b385fdc90426fcd6eb64db54b40c495b72ac0feb5766c54", size = 610211, upload-time = "2025-12-04T14:57:43.968Z" },
{ url = "https://files.pythonhosted.org/packages/79/07/c47a82d881319ec18a4510bb30463ed6891f2ad2c1901ed5ec23d3de351f/greenlet-3.3.0-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:30a6e28487a790417d036088b3bcb3f3ac7d8babaa7d0139edbaddebf3af9492", size = 624311, upload-time = "2025-12-04T15:07:14.697Z" },
{ url = "https://files.pythonhosted.org/packages/fd/8e/424b8c6e78bd9837d14ff7df01a9829fc883ba2ab4ea787d4f848435f23f/greenlet-3.3.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:087ea5e004437321508a8d6f20efc4cfec5e3c30118e1417ea96ed1d93950527", size = 612833, upload-time = "2025-12-04T14:26:03.669Z" },
{ url = "https://files.pythonhosted.org/packages/b5/ba/56699ff9b7c76ca12f1cdc27a886d0f81f2189c3455ff9f65246780f713d/greenlet-3.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ab97cf74045343f6c60a39913fa59710e4bd26a536ce7ab2397adf8b27e67c39", size = 1567256, upload-time = "2025-12-04T15:04:25.276Z" },
{ url = "https://files.pythonhosted.org/packages/1e/37/f31136132967982d698c71a281a8901daf1a8fbab935dce7c0cf15f942cc/greenlet-3.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5375d2e23184629112ca1ea89a53389dddbffcf417dad40125713d88eb5f96e8", size = 1636483, upload-time = "2025-12-04T14:27:30.804Z" },
{ url = "https://files.pythonhosted.org/packages/7e/71/ba21c3fb8c5dce83b8c01f458a42e99ffdb1963aeec08fff5a18588d8fd7/greenlet-3.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:9ee1942ea19550094033c35d25d20726e4f1c40d59545815e1128ac58d416d38", size = 301833, upload-time = "2025-12-04T14:32:23.929Z" },
{ url = "https://files.pythonhosted.org/packages/d7/7c/f0a6d0ede2c7bf092d00bc83ad5bafb7e6ec9b4aab2fbdfa6f134dc73327/greenlet-3.3.0-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:60c2ef0f578afb3c8d92ea07ad327f9a062547137afe91f38408f08aacab667f", size = 275671, upload-time = "2025-12-04T14:23:05.267Z" },
{ url = "https://files.pythonhosted.org/packages/44/06/dac639ae1a50f5969d82d2e3dd9767d30d6dbdbab0e1a54010c8fe90263c/greenlet-3.3.0-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a5d554d0712ba1de0a6c94c640f7aeba3f85b3a6e1f2899c11c2c0428da9365", size = 646360, upload-time = "2025-12-04T14:50:10.026Z" },
{ url = "https://files.pythonhosted.org/packages/e0/94/0fb76fe6c5369fba9bf98529ada6f4c3a1adf19e406a47332245ef0eb357/greenlet-3.3.0-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3a898b1e9c5f7307ebbde4102908e6cbfcb9ea16284a3abe15cab996bee8b9b3", size = 658160, upload-time = "2025-12-04T14:57:45.41Z" },
{ url = "https://files.pythonhosted.org/packages/93/79/d2c70cae6e823fac36c3bbc9077962105052b7ef81db2f01ec3b9bf17e2b/greenlet-3.3.0-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:dcd2bdbd444ff340e8d6bdf54d2f206ccddbb3ccfdcd3c25bf4afaa7b8f0cf45", size = 671388, upload-time = "2025-12-04T15:07:15.789Z" },
{ url = "https://files.pythonhosted.org/packages/b8/14/bab308fc2c1b5228c3224ec2bf928ce2e4d21d8046c161e44a2012b5203e/greenlet-3.3.0-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5773edda4dc00e173820722711d043799d3adb4f01731f40619e07ea2750b955", size = 660166, upload-time = "2025-12-04T14:26:05.099Z" },
{ url = "https://files.pythonhosted.org/packages/4b/d2/91465d39164eaa0085177f61983d80ffe746c5a1860f009811d498e7259c/greenlet-3.3.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ac0549373982b36d5fd5d30beb8a7a33ee541ff98d2b502714a09f1169f31b55", size = 1615193, upload-time = "2025-12-04T15:04:27.041Z" },
{ url = "https://files.pythonhosted.org/packages/42/1b/83d110a37044b92423084d52d5d5a3b3a73cafb51b547e6d7366ff62eff1/greenlet-3.3.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d198d2d977460358c3b3a4dc844f875d1adb33817f0613f663a656f463764ccc", size = 1683653, upload-time = "2025-12-04T14:27:32.366Z" },
{ url = "https://files.pythonhosted.org/packages/7c/9a/9030e6f9aa8fd7808e9c31ba4c38f87c4f8ec324ee67431d181fe396d705/greenlet-3.3.0-cp314-cp314-win_amd64.whl", hash = "sha256:73f51dd0e0bdb596fb0417e475fa3c5e32d4c83638296e560086b8d7da7c4170", size = 305387, upload-time = "2025-12-04T14:26:51.063Z" },
{ url = "https://files.pythonhosted.org/packages/a0/66/bd6317bc5932accf351fc19f177ffba53712a202f9df10587da8df257c7e/greenlet-3.3.0-cp314-cp314t-macosx_11_0_universal2.whl", hash = "sha256:d6ed6f85fae6cdfdb9ce04c9bf7a08d666cfcfb914e7d006f44f840b46741931", size = 282638, upload-time = "2025-12-04T14:25:20.941Z" },
{ url = "https://files.pythonhosted.org/packages/30/cf/cc81cb030b40e738d6e69502ccbd0dd1bced0588e958f9e757945de24404/greenlet-3.3.0-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d9125050fcf24554e69c4cacb086b87b3b55dc395a8b3ebe6487b045b2614388", size = 651145, upload-time = "2025-12-04T14:50:11.039Z" },
{ url = "https://files.pythonhosted.org/packages/9c/ea/1020037b5ecfe95ca7df8d8549959baceb8186031da83d5ecceff8b08cd2/greenlet-3.3.0-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:87e63ccfa13c0a0f6234ed0add552af24cc67dd886731f2261e46e241608bee3", size = 654236, upload-time = "2025-12-04T14:57:47.007Z" },
{ url = "https://files.pythonhosted.org/packages/69/cc/1e4bae2e45ca2fa55299f4e85854606a78ecc37fead20d69322f96000504/greenlet-3.3.0-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2662433acbca297c9153a4023fe2161c8dcfdcc91f10433171cf7e7d94ba2221", size = 662506, upload-time = "2025-12-04T15:07:16.906Z" },
{ url = "https://files.pythonhosted.org/packages/57/b9/f8025d71a6085c441a7eaff0fd928bbb275a6633773667023d19179fe815/greenlet-3.3.0-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3c6e9b9c1527a78520357de498b0e709fb9e2f49c3a513afd5a249007261911b", size = 653783, upload-time = "2025-12-04T14:26:06.225Z" },
{ url = "https://files.pythonhosted.org/packages/f6/c7/876a8c7a7485d5d6b5c6821201d542ef28be645aa024cfe1145b35c120c1/greenlet-3.3.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:286d093f95ec98fdd92fcb955003b8a3d054b4e2cab3e2707a5039e7b50520fd", size = 1614857, upload-time = "2025-12-04T15:04:28.484Z" },
{ url = "https://files.pythonhosted.org/packages/4f/dc/041be1dff9f23dac5f48a43323cd0789cb798342011c19a248d9c9335536/greenlet-3.3.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c10513330af5b8ae16f023e8ddbfb486ab355d04467c4679c5cfe4659975dd9", size = 1676034, upload-time = "2025-12-04T14:27:33.531Z" },
]
[[package]]
name = "idna"
version = "3.11"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/0703ccc57f3a7233505399edb88de3cbd678da106337b9fcde432b65ed60/idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902", size = 194582, upload-time = "2025-10-12T14:55:20.501Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" },
]
[[package]]
name = "kiwisolver"
version = "1.4.9"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/5c/3c/85844f1b0feb11ee581ac23fe5fce65cd049a200c1446708cc1b7f922875/kiwisolver-1.4.9.tar.gz", hash = "sha256:c3b22c26c6fd6811b0ae8363b95ca8ce4ea3c202d3d0975b2914310ceb1bcc4d", size = 97564, upload-time = "2025-08-10T21:27:49.279Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/86/c9/13573a747838aeb1c76e3267620daa054f4152444d1f3d1a2324b78255b5/kiwisolver-1.4.9-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:ac5a486ac389dddcc5bef4f365b6ae3ffff2c433324fb38dd35e3fab7c957999", size = 123686, upload-time = "2025-08-10T21:26:10.034Z" },
{ url = "https://files.pythonhosted.org/packages/51/ea/2ecf727927f103ffd1739271ca19c424d0e65ea473fbaeea1c014aea93f6/kiwisolver-1.4.9-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f2ba92255faa7309d06fe44c3a4a97efe1c8d640c2a79a5ef728b685762a6fd2", size = 66460, upload-time = "2025-08-10T21:26:11.083Z" },
{ url = "https://files.pythonhosted.org/packages/5b/5a/51f5464373ce2aeb5194508298a508b6f21d3867f499556263c64c621914/kiwisolver-1.4.9-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4a2899935e724dd1074cb568ce7ac0dce28b2cd6ab539c8e001a8578eb106d14", size = 64952, upload-time = "2025-08-10T21:26:12.058Z" },
{ url = "https://files.pythonhosted.org/packages/70/90/6d240beb0f24b74371762873e9b7f499f1e02166a2d9c5801f4dbf8fa12e/kiwisolver-1.4.9-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f6008a4919fdbc0b0097089f67a1eb55d950ed7e90ce2cc3e640abadd2757a04", size = 1474756, upload-time = "2025-08-10T21:26:13.096Z" },
{ url = "https://files.pythonhosted.org/packages/12/42/f36816eaf465220f683fb711efdd1bbf7a7005a2473d0e4ed421389bd26c/kiwisolver-1.4.9-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:67bb8b474b4181770f926f7b7d2f8c0248cbcb78b660fdd41a47054b28d2a752", size = 1276404, upload-time = "2025-08-10T21:26:14.457Z" },
{ url = "https://files.pythonhosted.org/packages/2e/64/bc2de94800adc830c476dce44e9b40fd0809cddeef1fde9fcf0f73da301f/kiwisolver-1.4.9-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2327a4a30d3ee07d2fbe2e7933e8a37c591663b96ce42a00bc67461a87d7df77", size = 1294410, upload-time = "2025-08-10T21:26:15.73Z" },
{ url = "https://files.pythonhosted.org/packages/5f/42/2dc82330a70aa8e55b6d395b11018045e58d0bb00834502bf11509f79091/kiwisolver-1.4.9-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7a08b491ec91b1d5053ac177afe5290adacf1f0f6307d771ccac5de30592d198", size = 1343631, upload-time = "2025-08-10T21:26:17.045Z" },
{ url = "https://files.pythonhosted.org/packages/22/fd/f4c67a6ed1aab149ec5a8a401c323cee7a1cbe364381bb6c9c0d564e0e20/kiwisolver-1.4.9-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d8fc5c867c22b828001b6a38d2eaeb88160bf5783c6cb4a5e440efc981ce286d", size = 2224963, upload-time = "2025-08-10T21:26:18.737Z" },
{ url = "https://files.pythonhosted.org/packages/45/aa/76720bd4cb3713314677d9ec94dcc21ced3f1baf4830adde5bb9b2430a5f/kiwisolver-1.4.9-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:3b3115b2581ea35bb6d1f24a4c90af37e5d9b49dcff267eeed14c3893c5b86ab", size = 2321295, upload-time = "2025-08-10T21:26:20.11Z" },
{ url = "https://files.pythonhosted.org/packages/80/19/d3ec0d9ab711242f56ae0dc2fc5d70e298bb4a1f9dfab44c027668c673a1/kiwisolver-1.4.9-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:858e4c22fb075920b96a291928cb7dea5644e94c0ee4fcd5af7e865655e4ccf2", size = 2487987, upload-time = "2025-08-10T21:26:21.49Z" },
{ url = "https://files.pythonhosted.org/packages/39/e9/61e4813b2c97e86b6fdbd4dd824bf72d28bcd8d4849b8084a357bc0dd64d/kiwisolver-1.4.9-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ed0fecd28cc62c54b262e3736f8bb2512d8dcfdc2bcf08be5f47f96bf405b145", size = 2291817, upload-time = "2025-08-10T21:26:22.812Z" },
{ url = "https://files.pythonhosted.org/packages/a0/41/85d82b0291db7504da3c2defe35c9a8a5c9803a730f297bd823d11d5fb77/kiwisolver-1.4.9-cp312-cp312-win_amd64.whl", hash = "sha256:f68208a520c3d86ea51acf688a3e3002615a7f0238002cccc17affecc86a8a54", size = 73895, upload-time = "2025-08-10T21:26:24.37Z" },
{ url = "https://files.pythonhosted.org/packages/e2/92/5f3068cf15ee5cb624a0c7596e67e2a0bb2adee33f71c379054a491d07da/kiwisolver-1.4.9-cp312-cp312-win_arm64.whl", hash = "sha256:2c1a4f57df73965f3f14df20b80ee29e6a7930a57d2d9e8491a25f676e197c60", size = 64992, upload-time = "2025-08-10T21:26:25.732Z" },
{ url = "https://files.pythonhosted.org/packages/31/c1/c2686cda909742ab66c7388e9a1a8521a59eb89f8bcfbee28fc980d07e24/kiwisolver-1.4.9-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a5d0432ccf1c7ab14f9949eec60c5d1f924f17c037e9f8b33352fa05799359b8", size = 123681, upload-time = "2025-08-10T21:26:26.725Z" },
{ url = "https://files.pythonhosted.org/packages/ca/f0/f44f50c9f5b1a1860261092e3bc91ecdc9acda848a8b8c6abfda4a24dd5c/kiwisolver-1.4.9-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efb3a45b35622bb6c16dbfab491a8f5a391fe0e9d45ef32f4df85658232ca0e2", size = 66464, upload-time = "2025-08-10T21:26:27.733Z" },
{ url = "https://files.pythonhosted.org/packages/2d/7a/9d90a151f558e29c3936b8a47ac770235f436f2120aca41a6d5f3d62ae8d/kiwisolver-1.4.9-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1a12cf6398e8a0a001a059747a1cbf24705e18fe413bc22de7b3d15c67cffe3f", size = 64961, upload-time = "2025-08-10T21:26:28.729Z" },
{ url = "https://files.pythonhosted.org/packages/e9/e9/f218a2cb3a9ffbe324ca29a9e399fa2d2866d7f348ec3a88df87fc248fc5/kiwisolver-1.4.9-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b67e6efbf68e077dd71d1a6b37e43e1a99d0bff1a3d51867d45ee8908b931098", size = 1474607, upload-time = "2025-08-10T21:26:29.798Z" },
{ url = "https://files.pythonhosted.org/packages/d9/28/aac26d4c882f14de59041636292bc838db8961373825df23b8eeb807e198/kiwisolver-1.4.9-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5656aa670507437af0207645273ccdfee4f14bacd7f7c67a4306d0dcaeaf6eed", size = 1276546, upload-time = "2025-08-10T21:26:31.401Z" },
{ url = "https://files.pythonhosted.org/packages/8b/ad/8bfc1c93d4cc565e5069162f610ba2f48ff39b7de4b5b8d93f69f30c4bed/kiwisolver-1.4.9-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:bfc08add558155345129c7803b3671cf195e6a56e7a12f3dde7c57d9b417f525", size = 1294482, upload-time = "2025-08-10T21:26:32.721Z" },
{ url = "https://files.pythonhosted.org/packages/da/f1/6aca55ff798901d8ce403206d00e033191f63d82dd708a186e0ed2067e9c/kiwisolver-1.4.9-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:40092754720b174e6ccf9e845d0d8c7d8e12c3d71e7fc35f55f3813e96376f78", size = 1343720, upload-time = "2025-08-10T21:26:34.032Z" },
{ url = "https://files.pythonhosted.org/packages/d1/91/eed031876c595c81d90d0f6fc681ece250e14bf6998c3d7c419466b523b7/kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:497d05f29a1300d14e02e6441cf0f5ee81c1ff5a304b0d9fb77423974684e08b", size = 2224907, upload-time = "2025-08-10T21:26:35.824Z" },
{ url = "https://files.pythonhosted.org/packages/e9/ec/4d1925f2e49617b9cca9c34bfa11adefad49d00db038e692a559454dfb2e/kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:bdd1a81a1860476eb41ac4bc1e07b3f07259e6d55bbf739b79c8aaedcf512799", size = 2321334, upload-time = "2025-08-10T21:26:37.534Z" },
{ url = "https://files.pythonhosted.org/packages/43/cb/450cd4499356f68802750c6ddc18647b8ea01ffa28f50d20598e0befe6e9/kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:e6b93f13371d341afee3be9f7c5964e3fe61d5fa30f6a30eb49856935dfe4fc3", size = 2488313, upload-time = "2025-08-10T21:26:39.191Z" },
{ url = "https://files.pythonhosted.org/packages/71/67/fc76242bd99f885651128a5d4fa6083e5524694b7c88b489b1b55fdc491d/kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d75aa530ccfaa593da12834b86a0724f58bff12706659baa9227c2ccaa06264c", size = 2291970, upload-time = "2025-08-10T21:26:40.828Z" },
{ url = "https://files.pythonhosted.org/packages/75/bd/f1a5d894000941739f2ae1b65a32892349423ad49c2e6d0771d0bad3fae4/kiwisolver-1.4.9-cp313-cp313-win_amd64.whl", hash = "sha256:dd0a578400839256df88c16abddf9ba14813ec5f21362e1fe65022e00c883d4d", size = 73894, upload-time = "2025-08-10T21:26:42.33Z" },
{ url = "https://files.pythonhosted.org/packages/95/38/dce480814d25b99a391abbddadc78f7c117c6da34be68ca8b02d5848b424/kiwisolver-1.4.9-cp313-cp313-win_arm64.whl", hash = "sha256:d4188e73af84ca82468f09cadc5ac4db578109e52acb4518d8154698d3a87ca2", size = 64995, upload-time = "2025-08-10T21:26:43.889Z" },
{ url = "https://files.pythonhosted.org/packages/e2/37/7d218ce5d92dadc5ebdd9070d903e0c7cf7edfe03f179433ac4d13ce659c/kiwisolver-1.4.9-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:5a0f2724dfd4e3b3ac5a82436a8e6fd16baa7d507117e4279b660fe8ca38a3a1", size = 126510, upload-time = "2025-08-10T21:26:44.915Z" },
{ url = "https://files.pythonhosted.org/packages/23/b0/e85a2b48233daef4b648fb657ebbb6f8367696a2d9548a00b4ee0eb67803/kiwisolver-1.4.9-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:1b11d6a633e4ed84fc0ddafd4ebfd8ea49b3f25082c04ad12b8315c11d504dc1", size = 67903, upload-time = "2025-08-10T21:26:45.934Z" },
{ url = "https://files.pythonhosted.org/packages/44/98/f2425bc0113ad7de24da6bb4dae1343476e95e1d738be7c04d31a5d037fd/kiwisolver-1.4.9-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61874cdb0a36016354853593cffc38e56fc9ca5aa97d2c05d3dcf6922cd55a11", size = 66402, upload-time = "2025-08-10T21:26:47.101Z" },
{ url = "https://files.pythonhosted.org/packages/98/d8/594657886df9f34c4177cc353cc28ca7e6e5eb562d37ccc233bff43bbe2a/kiwisolver-1.4.9-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:60c439763a969a6af93b4881db0eed8fadf93ee98e18cbc35bc8da868d0c4f0c", size = 1582135, upload-time = "2025-08-10T21:26:48.665Z" },
{ url = "https://files.pythonhosted.org/packages/5c/c6/38a115b7170f8b306fc929e166340c24958347308ea3012c2b44e7e295db/kiwisolver-1.4.9-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92a2f997387a1b79a75e7803aa7ded2cfbe2823852ccf1ba3bcf613b62ae3197", size = 1389409, upload-time = "2025-08-10T21:26:50.335Z" },
{ url = "https://files.pythonhosted.org/packages/bf/3b/e04883dace81f24a568bcee6eb3001da4ba05114afa622ec9b6fafdc1f5e/kiwisolver-1.4.9-cp313-cp313t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a31d512c812daea6d8b3be3b2bfcbeb091dbb09177706569bcfc6240dcf8b41c", size = 1401763, upload-time = "2025-08-10T21:26:51.867Z" },
{ url = "https://files.pythonhosted.org/packages/9f/80/20ace48e33408947af49d7d15c341eaee69e4e0304aab4b7660e234d6288/kiwisolver-1.4.9-cp313-cp313t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:52a15b0f35dad39862d376df10c5230155243a2c1a436e39eb55623ccbd68185", size = 1453643, upload-time = "2025-08-10T21:26:53.592Z" },
{ url = "https://files.pythonhosted.org/packages/64/31/6ce4380a4cd1f515bdda976a1e90e547ccd47b67a1546d63884463c92ca9/kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a30fd6fdef1430fd9e1ba7b3398b5ee4e2887783917a687d86ba69985fb08748", size = 2330818, upload-time = "2025-08-10T21:26:55.051Z" },
{ url = "https://files.pythonhosted.org/packages/fa/e9/3f3fcba3bcc7432c795b82646306e822f3fd74df0ee81f0fa067a1f95668/kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:cc9617b46837c6468197b5945e196ee9ca43057bb7d9d1ae688101e4e1dddf64", size = 2419963, upload-time = "2025-08-10T21:26:56.421Z" },
{ url = "https://files.pythonhosted.org/packages/99/43/7320c50e4133575c66e9f7dadead35ab22d7c012a3b09bb35647792b2a6d/kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:0ab74e19f6a2b027ea4f845a78827969af45ce790e6cb3e1ebab71bdf9f215ff", size = 2594639, upload-time = "2025-08-10T21:26:57.882Z" },
{ url = "https://files.pythonhosted.org/packages/65/d6/17ae4a270d4a987ef8a385b906d2bdfc9fce502d6dc0d3aea865b47f548c/kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dba5ee5d3981160c28d5490f0d1b7ed730c22470ff7f6cc26cfcfaacb9896a07", size = 2391741, upload-time = "2025-08-10T21:26:59.237Z" },
{ url = "https://files.pythonhosted.org/packages/2a/8f/8f6f491d595a9e5912971f3f863d81baddccc8a4d0c3749d6a0dd9ffc9df/kiwisolver-1.4.9-cp313-cp313t-win_arm64.whl", hash = "sha256:0749fd8f4218ad2e851e11cc4dc05c7cbc0cbc4267bdfdb31782e65aace4ee9c", size = 68646, upload-time = "2025-08-10T21:27:00.52Z" },
{ url = "https://files.pythonhosted.org/packages/6b/32/6cc0fbc9c54d06c2969faa9c1d29f5751a2e51809dd55c69055e62d9b426/kiwisolver-1.4.9-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:9928fe1eb816d11ae170885a74d074f57af3a0d65777ca47e9aeb854a1fba386", size = 123806, upload-time = "2025-08-10T21:27:01.537Z" },
{ url = "https://files.pythonhosted.org/packages/b2/dd/2bfb1d4a4823d92e8cbb420fe024b8d2167f72079b3bb941207c42570bdf/kiwisolver-1.4.9-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:d0005b053977e7b43388ddec89fa567f43d4f6d5c2c0affe57de5ebf290dc552", size = 66605, upload-time = "2025-08-10T21:27:03.335Z" },
{ url = "https://files.pythonhosted.org/packages/f7/69/00aafdb4e4509c2ca6064646cba9cd4b37933898f426756adb2cb92ebbed/kiwisolver-1.4.9-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:2635d352d67458b66fd0667c14cb1d4145e9560d503219034a18a87e971ce4f3", size = 64925, upload-time = "2025-08-10T21:27:04.339Z" },
{ url = "https://files.pythonhosted.org/packages/43/dc/51acc6791aa14e5cb6d8a2e28cefb0dc2886d8862795449d021334c0df20/kiwisolver-1.4.9-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:767c23ad1c58c9e827b649a9ab7809fd5fd9db266a9cf02b0e926ddc2c680d58", size = 1472414, upload-time = "2025-08-10T21:27:05.437Z" },
{ url = "https://files.pythonhosted.org/packages/3d/bb/93fa64a81db304ac8a246f834d5094fae4b13baf53c839d6bb6e81177129/kiwisolver-1.4.9-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:72d0eb9fba308b8311685c2268cf7d0a0639a6cd027d8128659f72bdd8a024b4", size = 1281272, upload-time = "2025-08-10T21:27:07.063Z" },
{ url = "https://files.pythonhosted.org/packages/70/e6/6df102916960fb8d05069d4bd92d6d9a8202d5a3e2444494e7cd50f65b7a/kiwisolver-1.4.9-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f68e4f3eeca8fb22cc3d731f9715a13b652795ef657a13df1ad0c7dc0e9731df", size = 1298578, upload-time = "2025-08-10T21:27:08.452Z" },
{ url = "https://files.pythonhosted.org/packages/7c/47/e142aaa612f5343736b087864dbaebc53ea8831453fb47e7521fa8658f30/kiwisolver-1.4.9-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d84cd4061ae292d8ac367b2c3fa3aad11cb8625a95d135fe93f286f914f3f5a6", size = 1345607, upload-time = "2025-08-10T21:27:10.125Z" },
{ url = "https://files.pythonhosted.org/packages/54/89/d641a746194a0f4d1a3670fb900d0dbaa786fb98341056814bc3f058fa52/kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a60ea74330b91bd22a29638940d115df9dc00af5035a9a2a6ad9399ffb4ceca5", size = 2230150, upload-time = "2025-08-10T21:27:11.484Z" },
{ url = "https://files.pythonhosted.org/packages/aa/6b/5ee1207198febdf16ac11f78c5ae40861b809cbe0e6d2a8d5b0b3044b199/kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:ce6a3a4e106cf35c2d9c4fa17c05ce0b180db622736845d4315519397a77beaf", size = 2325979, upload-time = "2025-08-10T21:27:12.917Z" },
{ url = "https://files.pythonhosted.org/packages/fc/ff/b269eefd90f4ae14dcc74973d5a0f6d28d3b9bb1afd8c0340513afe6b39a/kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:77937e5e2a38a7b48eef0585114fe7930346993a88060d0bf886086d2aa49ef5", size = 2491456, upload-time = "2025-08-10T21:27:14.353Z" },
{ url = "https://files.pythonhosted.org/packages/fc/d4/10303190bd4d30de547534601e259a4fbf014eed94aae3e5521129215086/kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:24c175051354f4a28c5d6a31c93906dc653e2bf234e8a4bbfb964892078898ce", size = 2294621, upload-time = "2025-08-10T21:27:15.808Z" },
{ url = "https://files.pythonhosted.org/packages/28/e0/a9a90416fce5c0be25742729c2ea52105d62eda6c4be4d803c2a7be1fa50/kiwisolver-1.4.9-cp314-cp314-win_amd64.whl", hash = "sha256:0763515d4df10edf6d06a3c19734e2566368980d21ebec439f33f9eb936c07b7", size = 75417, upload-time = "2025-08-10T21:27:17.436Z" },
{ url = "https://files.pythonhosted.org/packages/1f/10/6949958215b7a9a264299a7db195564e87900f709db9245e4ebdd3c70779/kiwisolver-1.4.9-cp314-cp314-win_arm64.whl", hash = "sha256:0e4e2bf29574a6a7b7f6cb5fa69293b9f96c928949ac4a53ba3f525dffb87f9c", size = 66582, upload-time = "2025-08-10T21:27:18.436Z" },
{ url = "https://files.pythonhosted.org/packages/ec/79/60e53067903d3bc5469b369fe0dfc6b3482e2133e85dae9daa9527535991/kiwisolver-1.4.9-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:d976bbb382b202f71c67f77b0ac11244021cfa3f7dfd9e562eefcea2df711548", size = 126514, upload-time = "2025-08-10T21:27:19.465Z" },
{ url = "https://files.pythonhosted.org/packages/25/d1/4843d3e8d46b072c12a38c97c57fab4608d36e13fe47d47ee96b4d61ba6f/kiwisolver-1.4.9-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2489e4e5d7ef9a1c300a5e0196e43d9c739f066ef23270607d45aba368b91f2d", size = 67905, upload-time = "2025-08-10T21:27:20.51Z" },
{ url = "https://files.pythonhosted.org/packages/8c/ae/29ffcbd239aea8b93108de1278271ae764dfc0d803a5693914975f200596/kiwisolver-1.4.9-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:e2ea9f7ab7fbf18fffb1b5434ce7c69a07582f7acc7717720f1d69f3e806f90c", size = 66399, upload-time = "2025-08-10T21:27:21.496Z" },
{ url = "https://files.pythonhosted.org/packages/a1/ae/d7ba902aa604152c2ceba5d352d7b62106bedbccc8e95c3934d94472bfa3/kiwisolver-1.4.9-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b34e51affded8faee0dfdb705416153819d8ea9250bbbf7ea1b249bdeb5f1122", size = 1582197, upload-time = "2025-08-10T21:27:22.604Z" },
{ url = "https://files.pythonhosted.org/packages/f2/41/27c70d427eddb8bc7e4f16420a20fefc6f480312122a59a959fdfe0445ad/kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d8aacd3d4b33b772542b2e01beb50187536967b514b00003bdda7589722d2a64", size = 1390125, upload-time = "2025-08-10T21:27:24.036Z" },
{ url = "https://files.pythonhosted.org/packages/41/42/b3799a12bafc76d962ad69083f8b43b12bf4fe78b097b12e105d75c9b8f1/kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7cf974dd4e35fa315563ac99d6287a1024e4dc2077b8a7d7cd3d2fb65d283134", size = 1402612, upload-time = "2025-08-10T21:27:25.773Z" },
{ url = "https://files.pythonhosted.org/packages/d2/b5/a210ea073ea1cfaca1bb5c55a62307d8252f531beb364e18aa1e0888b5a0/kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:85bd218b5ecfbee8c8a82e121802dcb519a86044c9c3b2e4aef02fa05c6da370", size = 1453990, upload-time = "2025-08-10T21:27:27.089Z" },
{ url = "https://files.pythonhosted.org/packages/5f/ce/a829eb8c033e977d7ea03ed32fb3c1781b4fa0433fbadfff29e39c676f32/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:0856e241c2d3df4efef7c04a1e46b1936b6120c9bcf36dd216e3acd84bc4fb21", size = 2331601, upload-time = "2025-08-10T21:27:29.343Z" },
{ url = "https://files.pythonhosted.org/packages/e0/4b/b5e97eb142eb9cd0072dacfcdcd31b1c66dc7352b0f7c7255d339c0edf00/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:9af39d6551f97d31a4deebeac6f45b156f9755ddc59c07b402c148f5dbb6482a", size = 2422041, upload-time = "2025-08-10T21:27:30.754Z" },
{ url = "https://files.pythonhosted.org/packages/40/be/8eb4cd53e1b85ba4edc3a9321666f12b83113a178845593307a3e7891f44/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:bb4ae2b57fc1d8cbd1cf7b1d9913803681ffa903e7488012be5b76dedf49297f", size = 2594897, upload-time = "2025-08-10T21:27:32.803Z" },
{ url = "https://files.pythonhosted.org/packages/99/dd/841e9a66c4715477ea0abc78da039832fbb09dac5c35c58dc4c41a407b8a/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:aedff62918805fb62d43a4aa2ecd4482c380dc76cd31bd7c8878588a61bd0369", size = 2391835, upload-time = "2025-08-10T21:27:34.23Z" },
{ url = "https://files.pythonhosted.org/packages/0c/28/4b2e5c47a0da96896fdfdb006340ade064afa1e63675d01ea5ac222b6d52/kiwisolver-1.4.9-cp314-cp314t-win_amd64.whl", hash = "sha256:1fa333e8b2ce4d9660f2cda9c0e1b6bafcfb2457a9d259faa82289e73ec24891", size = 79988, upload-time = "2025-08-10T21:27:35.587Z" },
{ url = "https://files.pythonhosted.org/packages/80/be/3578e8afd18c88cdf9cb4cffde75a96d2be38c5a903f1ed0ceec061bd09e/kiwisolver-1.4.9-cp314-cp314t-win_arm64.whl", hash = "sha256:4a48a2ce79d65d363597ef7b567ce3d14d68783d2b2263d98db3d9477805ba32", size = 70260, upload-time = "2025-08-10T21:27:36.606Z" },
]
[[package]]
name = "logbook"
version = "1.7.0.post0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/cc/98/c1d93c1d7593f58515333a6217aa4ae647d9ee9c1aa2dfdf77b28b7bb7c7/Logbook-1.7.0.post0.tar.gz", hash = "sha256:a5e8016701ca3beea6a390b0ba1541037f663543ca508ccd36cfdc841639cdd7", size = 367964, upload-time = "2023-11-10T23:33:29.292Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/c7/d0/0d9e4f08333189547ffa85257c3053a07a4c1a431dcbfbe9a49eaedc33dc/Logbook-1.7.0.post0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b1e0b8c3d25a7cf539340c299a8a1fd37d19809a158c8849f6e73a6304f583c7", size = 201359, upload-time = "2023-11-10T23:32:57.454Z" },
{ url = "https://files.pythonhosted.org/packages/62/f3/8c2146de5f2179cb7d8727b8e150def2db3dfa74e0a6341a3921557aff28/Logbook-1.7.0.post0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3f2928505d528fb2efa5c4c7e63bd0a3d5ded4d96db8e056ab61a69313739072", size = 134941, upload-time = "2023-11-10T23:32:58.901Z" },
{ url = "https://files.pythonhosted.org/packages/64/70/26a766173b212b003149b5899cd6616f415a82f11b86a5c5628494cd44cf/Logbook-1.7.0.post0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5f891dc3f60a18f85d09698d1ea429b2effb06bfd42a1835493efde5eb6ea08b", size = 130611, upload-time = "2023-11-10T23:33:00.794Z" },
{ url = "https://files.pythonhosted.org/packages/07/d1/0be80be60881e2b5d8747a64558a858c759443ad2d2b7e036272e87cb9f4/Logbook-1.7.0.post0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c7d7a39dbfa9c2793569691c719c6f0269a21b01583f33dfcc6052b3312fc5f2", size = 518536, upload-time = "2023-11-10T23:33:02.461Z" },
{ url = "https://files.pythonhosted.org/packages/38/fa/4c717b80b59496010c9fc5d6a372df0215d0c480548baae1c36f443075db/Logbook-1.7.0.post0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:40a8e1b4fc0d2fdf8e662fabd8a933ba1ce91a355c755ab7a1d13469ec0e590e", size = 527547, upload-time = "2023-11-10T23:33:04.341Z" },
{ url = "https://files.pythonhosted.org/packages/e4/a9/78983454f4b638e9875b783bebce92a634829f3ea50743f9275e4db2a8d3/Logbook-1.7.0.post0-cp312-cp312-win32.whl", hash = "sha256:faf156af8a8954a227f141ffedf7ac1d9ba573b0066f19033ab2240329f94793", size = 115785, upload-time = "2023-11-10T23:33:05.875Z" },
{ url = "https://files.pythonhosted.org/packages/99/34/3bc539cdeffc55e4be527c205b11f7f1f43b665fed8175558dff8c8afa7d/Logbook-1.7.0.post0-cp312-cp312-win_amd64.whl", hash = "sha256:6316fa5eb09b375980a9ee3fd8c72cf9020b532d4c73fd7cbfd7a1a74694739e", size = 122823, upload-time = "2023-11-10T23:33:07.313Z" },
]
[[package]]
name = "markdown2"
version = "2.4.11"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/a7/b7/0ba8568968673ba5bcd221525ec364820b46dea9da441146d72cae4df18a/markdown2-2.4.11.tar.gz", hash = "sha256:c04841d0f9df37457396b9d73c54846ddb097a73e7eb7c81d1589e0bba566cda", size = 128610, upload-time = "2023-12-03T18:52:01.29Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/c9/38/183d3c253b9dc884c9d698dd5d68f258d0f853726260362f0fa49400279d/markdown2-2.4.11-py2.py3-none-any.whl", hash = "sha256:2fff5d8e9283218797c5db0e9caad14c4307839919297c5be6ae507d4eeaddbc", size = 41072, upload-time = "2023-12-03T18:51:59.111Z" },
]
[[package]]
name = "matplotlib"
version = "3.8.2"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "contourpy" },
{ name = "cycler" },
{ name = "fonttools" },
{ name = "kiwisolver" },
{ name = "numpy" },
{ name = "packaging" },
{ name = "pillow" },
{ name = "pyparsing" },
{ name = "python-dateutil" },
]
sdist = { url = "https://files.pythonhosted.org/packages/fb/ab/38a0e94cb01dacb50f06957c2bed1c83b8f9dac6618988a37b2487862944/matplotlib-3.8.2.tar.gz", hash = "sha256:01a978b871b881ee76017152f1f1a0cbf6bd5f7b8ff8c96df0df1bd57d8755a1", size = 35866957, upload-time = "2023-11-17T21:16:40.15Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/e4/1b/864d28d5a72d586ac137f4ca54d5afc8b869720e30d508dbd9adcce4d231/matplotlib-3.8.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:4c318c1e95e2f5926fba326f68177dee364aa791d6df022ceb91b8221bd0a627", size = 7590988, upload-time = "2023-11-17T21:19:01.119Z" },
{ url = "https://files.pythonhosted.org/packages/9a/b0/dd2b60f2dd90fbc21d1d3129c36a453c322d7995d5e3589f5b3c59ee528d/matplotlib-3.8.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:091275d18d942cf1ee9609c830a1bc36610607d8223b1b981c37d5c9fc3e46a4", size = 7483594, upload-time = "2023-11-17T21:19:09.865Z" },
{ url = "https://files.pythonhosted.org/packages/33/da/9942533ad9f96753bde0e5a5d48eacd6c21de8ea1ad16570e31bda8a017f/matplotlib-3.8.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b0f3b8ea0e99e233a4bcc44590f01604840d833c280ebb8fe5554fd3e6cfe8d", size = 11380843, upload-time = "2023-11-17T21:19:20.46Z" },
{ url = "https://files.pythonhosted.org/packages/fc/52/bfd36eb4745a3b21b3946c2c3a15679b620e14574fe2b98e9451b65ef578/matplotlib-3.8.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7b1704a530395aaf73912be741c04d181f82ca78084fbd80bc737be04848331", size = 11604608, upload-time = "2023-11-17T21:19:31.363Z" },
{ url = "https://files.pythonhosted.org/packages/6d/8c/0cdfbf604d4ea3dfa77435176c51e233cc408ad8f3efbf8d2c9f57cbdafb/matplotlib-3.8.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:533b0e3b0c6768eef8cbe4b583731ce25a91ab54a22f830db2b031e83cca9213", size = 9545252, upload-time = "2023-11-17T21:19:42.271Z" },
{ url = "https://files.pythonhosted.org/packages/2e/51/c77a14869b7eb9d6fb440e811b754fc3950d6868c38ace57d0632b674415/matplotlib-3.8.2-cp312-cp312-win_amd64.whl", hash = "sha256:0f4fc5d72b75e2c18e55eb32292659cf731d9d5b312a6eb036506304f4675630", size = 7645067, upload-time = "2023-11-17T21:19:50.091Z" },
]
[[package]]
name = "numpy"
version = "1.26.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/dd/2b/205ddff2314d4eea852e31d53b8e55eb3f32b292efc3dd86bd827ab9019d/numpy-1.26.2.tar.gz", hash = "sha256:f65738447676ab5777f11e6bbbdb8ce11b785e105f690bc45966574816b6d3ea", size = 15664248, upload-time = "2023-11-12T23:17:31.386Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/b1/97/6694e0855b11be0fd8598d484c09edd876ec738a8741025dee072f026c33/numpy-1.26.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a4cd6ed4a339c21f1d1b0fdf13426cb3b284555c27ac2f156dfdaaa7e16bfab0", size = 20323012, upload-time = "2023-11-12T23:02:57.091Z" },
{ url = "https://files.pythonhosted.org/packages/2a/17/1fdc154e75d24d8c20c42b71bae1b5cf752453f0fc3a2504bbb810293dd1/numpy-1.26.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5d5244aabd6ed7f312268b9247be47343a654ebea52a60f002dc70c769048e75", size = 13675818, upload-time = "2023-11-12T23:03:32.823Z" },
{ url = "https://files.pythonhosted.org/packages/a1/42/a2819c5b77fe6506662ffc13b767e0c216c02f75ae840219013ab822a473/numpy-1.26.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a3cdb4d9c70e6b8c0814239ead47da00934666f668426fc6e94cce869e13fd7", size = 13917117, upload-time = "2023-11-12T23:03:59.013Z" },
{ url = "https://files.pythonhosted.org/packages/04/89/3b831e2b50c9364069609d1335f46c488a149d5f2be14a08741c92a60009/numpy-1.26.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa317b2325f7aa0a9471663e6093c210cb2ae9c0ad824732b307d2c51983d5b6", size = 17938212, upload-time = "2023-11-12T23:04:32.896Z" },
{ url = "https://files.pythonhosted.org/packages/02/51/f078f1e7f658022150e7c8d5f99d505b40812840349d54667f98bb915b26/numpy-1.26.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:174a8880739c16c925799c018f3f55b8130c1f7c8e75ab0a6fa9d41cab092fd6", size = 13564269, upload-time = "2023-11-12T23:05:31.101Z" },
{ url = "https://files.pythonhosted.org/packages/8c/9f/2f5c6b5f63cf006e6190bf750ade791d1fee353bab654bbde2f83a3ab92e/numpy-1.26.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:f79b231bf5c16b1f39c7f4875e1ded36abee1591e98742b05d8a0fb55d8a3eec", size = 17774512, upload-time = "2023-11-12T23:06:03.941Z" },
{ url = "https://files.pythonhosted.org/packages/51/7d/6181c8778cdb15ba0a4959bb72dcc1854c89ca4824481f224c6faf7024e1/numpy-1.26.2-cp312-cp312-win32.whl", hash = "sha256:4a06263321dfd3598cacb252f51e521a8cb4b6df471bb12a7ee5cbab20ea9167", size = 19962368, upload-time = "2023-11-12T23:06:51.561Z" },
{ url = "https://files.pythonhosted.org/packages/28/75/3b679b41713bb60e2e8f6e2f87be72c971c9e718b1c17b8f8749240ddca8/numpy-1.26.2-cp312-cp312-win_amd64.whl", hash = "sha256:b04f5dc6b3efdaab541f7857351aac359e6ae3c126e2edb376929bd3b7f92d7e", size = 15504951, upload-time = "2023-11-12T23:07:33.828Z" },
]
[[package]]
name = "packaging"
version = "23.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/fb/2b/9b9c33ffed44ee921d0967086d653047286054117d584f1b1a7c22ceaf7b/packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5", size = 146714, upload-time = "2023-10-01T13:50:05.279Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/ec/1a/610693ac4ee14fcdf2d9bf3c493370e4f2ef7ae2e19217d7a237ff42367d/packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7", size = 53011, upload-time = "2023-10-01T13:50:03.745Z" },
]
[[package]]
name = "pillow"
version = "12.0.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/5a/b0/cace85a1b0c9775a9f8f5d5423c8261c858760e2466c79b2dd184638b056/pillow-12.0.0.tar.gz", hash = "sha256:87d4f8125c9988bfbed67af47dd7a953e2fc7b0cc1e7800ec6d2080d490bb353", size = 47008828, upload-time = "2025-10-15T18:24:14.008Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/2c/90/4fcce2c22caf044e660a198d740e7fbc14395619e3cb1abad12192c0826c/pillow-12.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:53561a4ddc36facb432fae7a9d8afbfaf94795414f5cdc5fc52f28c1dca90371", size = 5249377, upload-time = "2025-10-15T18:22:05.993Z" },
{ url = "https://files.pythonhosted.org/packages/fd/e0/ed960067543d080691d47d6938ebccbf3976a931c9567ab2fbfab983a5dd/pillow-12.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:71db6b4c1653045dacc1585c1b0d184004f0d7e694c7b34ac165ca70c0838082", size = 4650343, upload-time = "2025-10-15T18:22:07.718Z" },
{ url = "https://files.pythonhosted.org/packages/e7/a1/f81fdeddcb99c044bf7d6faa47e12850f13cee0849537a7d27eeab5534d4/pillow-12.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:2fa5f0b6716fc88f11380b88b31fe591a06c6315e955c096c35715788b339e3f", size = 6232981, upload-time = "2025-10-15T18:22:09.287Z" },
{ url = "https://files.pythonhosted.org/packages/88/e1/9098d3ce341a8750b55b0e00c03f1630d6178f38ac191c81c97a3b047b44/pillow-12.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:82240051c6ca513c616f7f9da06e871f61bfd7805f566275841af15015b8f98d", size = 8041399, upload-time = "2025-10-15T18:22:10.872Z" },
{ url = "https://files.pythonhosted.org/packages/a7/62/a22e8d3b602ae8cc01446d0c57a54e982737f44b6f2e1e019a925143771d/pillow-12.0.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:55f818bd74fe2f11d4d7cbc65880a843c4075e0ac7226bc1a23261dbea531953", size = 6347740, upload-time = "2025-10-15T18:22:12.769Z" },
{ url = "https://files.pythonhosted.org/packages/4f/87/424511bdcd02c8d7acf9f65caa09f291a519b16bd83c3fb3374b3d4ae951/pillow-12.0.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b87843e225e74576437fd5b6a4c2205d422754f84a06942cfaf1dc32243e45a8", size = 7040201, upload-time = "2025-10-15T18:22:14.813Z" },
{ url = "https://files.pythonhosted.org/packages/dc/4d/435c8ac688c54d11755aedfdd9f29c9eeddf68d150fe42d1d3dbd2365149/pillow-12.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c607c90ba67533e1b2355b821fef6764d1dd2cbe26b8c1005ae84f7aea25ff79", size = 6462334, upload-time = "2025-10-15T18:22:16.375Z" },
{ url = "https://files.pythonhosted.org/packages/2b/f2/ad34167a8059a59b8ad10bc5c72d4d9b35acc6b7c0877af8ac885b5f2044/pillow-12.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:21f241bdd5080a15bc86d3466a9f6074a9c2c2b314100dd896ac81ee6db2f1ba", size = 7134162, upload-time = "2025-10-15T18:22:17.996Z" },
{ url = "https://files.pythonhosted.org/packages/0c/b1/a7391df6adacf0a5c2cf6ac1cf1fcc1369e7d439d28f637a847f8803beb3/pillow-12.0.0-cp312-cp312-win32.whl", hash = "sha256:dd333073e0cacdc3089525c7df7d39b211bcdf31fc2824e49d01c6b6187b07d0", size = 6298769, upload-time = "2025-10-15T18:22:19.923Z" },
{ url = "https://files.pythonhosted.org/packages/a2/0b/d87733741526541c909bbf159e338dcace4f982daac6e5a8d6be225ca32d/pillow-12.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:9fe611163f6303d1619bbcb653540a4d60f9e55e622d60a3108be0d5b441017a", size = 7001107, upload-time = "2025-10-15T18:22:21.644Z" },
{ url = "https://files.pythonhosted.org/packages/bc/96/aaa61ce33cc98421fb6088af2a03be4157b1e7e0e87087c888e2370a7f45/pillow-12.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:7dfb439562f234f7d57b1ac6bc8fe7f838a4bd49c79230e0f6a1da93e82f1fad", size = 2436012, upload-time = "2025-10-15T18:22:23.621Z" },
{ url = "https://files.pythonhosted.org/packages/62/f2/de993bb2d21b33a98d031ecf6a978e4b61da207bef02f7b43093774c480d/pillow-12.0.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:0869154a2d0546545cde61d1789a6524319fc1897d9ee31218eae7a60ccc5643", size = 4045493, upload-time = "2025-10-15T18:22:25.758Z" },
{ url = "https://files.pythonhosted.org/packages/0e/b6/bc8d0c4c9f6f111a783d045310945deb769b806d7574764234ffd50bc5ea/pillow-12.0.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:a7921c5a6d31b3d756ec980f2f47c0cfdbce0fc48c22a39347a895f41f4a6ea4", size = 4120461, upload-time = "2025-10-15T18:22:27.286Z" },
{ url = "https://files.pythonhosted.org/packages/5d/57/d60d343709366a353dc56adb4ee1e7d8a2cc34e3fbc22905f4167cfec119/pillow-12.0.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:1ee80a59f6ce048ae13cda1abf7fbd2a34ab9ee7d401c46be3ca685d1999a399", size = 3576912, upload-time = "2025-10-15T18:22:28.751Z" },
{ url = "https://files.pythonhosted.org/packages/a4/a4/a0a31467e3f83b94d37568294b01d22b43ae3c5d85f2811769b9c66389dd/pillow-12.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c50f36a62a22d350c96e49ad02d0da41dbd17ddc2e29750dbdba4323f85eb4a5", size = 5249132, upload-time = "2025-10-15T18:22:30.641Z" },
{ url = "https://files.pythonhosted.org/packages/83/06/48eab21dd561de2914242711434c0c0eb992ed08ff3f6107a5f44527f5e9/pillow-12.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5193fde9a5f23c331ea26d0cf171fbf67e3f247585f50c08b3e205c7aeb4589b", size = 4650099, upload-time = "2025-10-15T18:22:32.73Z" },
{ url = "https://files.pythonhosted.org/packages/fc/bd/69ed99fd46a8dba7c1887156d3572fe4484e3f031405fcc5a92e31c04035/pillow-12.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:bde737cff1a975b70652b62d626f7785e0480918dece11e8fef3c0cf057351c3", size = 6230808, upload-time = "2025-10-15T18:22:34.337Z" },
{ url = "https://files.pythonhosted.org/packages/ea/94/8fad659bcdbf86ed70099cb60ae40be6acca434bbc8c4c0d4ef356d7e0de/pillow-12.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a6597ff2b61d121172f5844b53f21467f7082f5fb385a9a29c01414463f93b07", size = 8037804, upload-time = "2025-10-15T18:22:36.402Z" },
{ url = "https://files.pythonhosted.org/packages/20/39/c685d05c06deecfd4e2d1950e9a908aa2ca8bc4e6c3b12d93b9cafbd7837/pillow-12.0.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0b817e7035ea7f6b942c13aa03bb554fc44fea70838ea21f8eb31c638326584e", size = 6345553, upload-time = "2025-10-15T18:22:38.066Z" },
{ url = "https://files.pythonhosted.org/packages/38/57/755dbd06530a27a5ed74f8cb0a7a44a21722ebf318edbe67ddbd7fb28f88/pillow-12.0.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f4f1231b7dec408e8670264ce63e9c71409d9583dd21d32c163e25213ee2a344", size = 7037729, upload-time = "2025-10-15T18:22:39.769Z" },
{ url = "https://files.pythonhosted.org/packages/ca/b6/7e94f4c41d238615674d06ed677c14883103dce1c52e4af16f000338cfd7/pillow-12.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6e51b71417049ad6ab14c49608b4a24d8fb3fe605e5dfabfe523b58064dc3d27", size = 6459789, upload-time = "2025-10-15T18:22:41.437Z" },
{ url = "https://files.pythonhosted.org/packages/9c/14/4448bb0b5e0f22dd865290536d20ec8a23b64e2d04280b89139f09a36bb6/pillow-12.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d120c38a42c234dc9a8c5de7ceaaf899cf33561956acb4941653f8bdc657aa79", size = 7130917, upload-time = "2025-10-15T18:22:43.152Z" },
{ url = "https://files.pythonhosted.org/packages/dd/ca/16c6926cc1c015845745d5c16c9358e24282f1e588237a4c36d2b30f182f/pillow-12.0.0-cp313-cp313-win32.whl", hash = "sha256:4cc6b3b2efff105c6a1656cfe59da4fdde2cda9af1c5e0b58529b24525d0a098", size = 6302391, upload-time = "2025-10-15T18:22:44.753Z" },
{ url = "https://files.pythonhosted.org/packages/6d/2a/dd43dcfd6dae9b6a49ee28a8eedb98c7d5ff2de94a5d834565164667b97b/pillow-12.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:4cf7fed4b4580601c4345ceb5d4cbf5a980d030fd5ad07c4d2ec589f95f09905", size = 7007477, upload-time = "2025-10-15T18:22:46.838Z" },
{ url = "https://files.pythonhosted.org/packages/77/f0/72ea067f4b5ae5ead653053212af05ce3705807906ba3f3e8f58ddf617e6/pillow-12.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:9f0b04c6b8584c2c193babcccc908b38ed29524b29dd464bc8801bf10d746a3a", size = 2435918, upload-time = "2025-10-15T18:22:48.399Z" },
{ url = "https://files.pythonhosted.org/packages/f5/5e/9046b423735c21f0487ea6cb5b10f89ea8f8dfbe32576fe052b5ba9d4e5b/pillow-12.0.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:7fa22993bac7b77b78cae22bad1e2a987ddf0d9015c63358032f84a53f23cdc3", size = 5251406, upload-time = "2025-10-15T18:22:49.905Z" },
{ url = "https://files.pythonhosted.org/packages/12/66/982ceebcdb13c97270ef7a56c3969635b4ee7cd45227fa707c94719229c5/pillow-12.0.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:f135c702ac42262573fe9714dfe99c944b4ba307af5eb507abef1667e2cbbced", size = 4653218, upload-time = "2025-10-15T18:22:51.587Z" },
{ url = "https://files.pythonhosted.org/packages/16/b3/81e625524688c31859450119bf12674619429cab3119eec0e30a7a1029cb/pillow-12.0.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c85de1136429c524e55cfa4e033b4a7940ac5c8ee4d9401cc2d1bf48154bbc7b", size = 6266564, upload-time = "2025-10-15T18:22:53.215Z" },
{ url = "https://files.pythonhosted.org/packages/98/59/dfb38f2a41240d2408096e1a76c671d0a105a4a8471b1871c6902719450c/pillow-12.0.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:38df9b4bfd3db902c9c2bd369bcacaf9d935b2fff73709429d95cc41554f7b3d", size = 8069260, upload-time = "2025-10-15T18:22:54.933Z" },
{ url = "https://files.pythonhosted.org/packages/dc/3d/378dbea5cd1874b94c312425ca77b0f47776c78e0df2df751b820c8c1d6c/pillow-12.0.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7d87ef5795da03d742bf49439f9ca4d027cde49c82c5371ba52464aee266699a", size = 6379248, upload-time = "2025-10-15T18:22:56.605Z" },
{ url = "https://files.pythonhosted.org/packages/84/b0/d525ef47d71590f1621510327acec75ae58c721dc071b17d8d652ca494d8/pillow-12.0.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:aff9e4d82d082ff9513bdd6acd4f5bd359f5b2c870907d2b0a9c5e10d40c88fe", size = 7066043, upload-time = "2025-10-15T18:22:58.53Z" },
{ url = "https://files.pythonhosted.org/packages/61/2c/aced60e9cf9d0cde341d54bf7932c9ffc33ddb4a1595798b3a5150c7ec4e/pillow-12.0.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:8d8ca2b210ada074d57fcee40c30446c9562e542fc46aedc19baf758a93532ee", size = 6490915, upload-time = "2025-10-15T18:23:00.582Z" },
{ url = "https://files.pythonhosted.org/packages/ef/26/69dcb9b91f4e59f8f34b2332a4a0a951b44f547c4ed39d3e4dcfcff48f89/pillow-12.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:99a7f72fb6249302aa62245680754862a44179b545ded638cf1fef59befb57ef", size = 7157998, upload-time = "2025-10-15T18:23:02.627Z" },
{ url = "https://files.pythonhosted.org/packages/61/2b/726235842220ca95fa441ddf55dd2382b52ab5b8d9c0596fe6b3f23dafe8/pillow-12.0.0-cp313-cp313t-win32.whl", hash = "sha256:4078242472387600b2ce8d93ade8899c12bf33fa89e55ec89fe126e9d6d5d9e9", size = 6306201, upload-time = "2025-10-15T18:23:04.709Z" },
{ url = "https://files.pythonhosted.org/packages/c0/3d/2afaf4e840b2df71344ababf2f8edd75a705ce500e5dc1e7227808312ae1/pillow-12.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:2c54c1a783d6d60595d3514f0efe9b37c8808746a66920315bfd34a938d7994b", size = 7013165, upload-time = "2025-10-15T18:23:06.46Z" },
{ url = "https://files.pythonhosted.org/packages/6f/75/3fa09aa5cf6ed04bee3fa575798ddf1ce0bace8edb47249c798077a81f7f/pillow-12.0.0-cp313-cp313t-win_arm64.whl", hash = "sha256:26d9f7d2b604cd23aba3e9faf795787456ac25634d82cd060556998e39c6fa47", size = 2437834, upload-time = "2025-10-15T18:23:08.194Z" },
{ url = "https://files.pythonhosted.org/packages/54/2a/9a8c6ba2c2c07b71bec92cf63e03370ca5e5f5c5b119b742bcc0cde3f9c5/pillow-12.0.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:beeae3f27f62308f1ddbcfb0690bf44b10732f2ef43758f169d5e9303165d3f9", size = 4045531, upload-time = "2025-10-15T18:23:10.121Z" },
{ url = "https://files.pythonhosted.org/packages/84/54/836fdbf1bfb3d66a59f0189ff0b9f5f666cee09c6188309300df04ad71fa/pillow-12.0.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:d4827615da15cd59784ce39d3388275ec093ae3ee8d7f0c089b76fa87af756c2", size = 4120554, upload-time = "2025-10-15T18:23:12.14Z" },
{ url = "https://files.pythonhosted.org/packages/0d/cd/16aec9f0da4793e98e6b54778a5fbce4f375c6646fe662e80600b8797379/pillow-12.0.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:3e42edad50b6909089750e65c91aa09aaf1e0a71310d383f11321b27c224ed8a", size = 3576812, upload-time = "2025-10-15T18:23:13.962Z" },
{ url = "https://files.pythonhosted.org/packages/f6/b7/13957fda356dc46339298b351cae0d327704986337c3c69bb54628c88155/pillow-12.0.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:e5d8efac84c9afcb40914ab49ba063d94f5dbdf5066db4482c66a992f47a3a3b", size = 5252689, upload-time = "2025-10-15T18:23:15.562Z" },
{ url = "https://files.pythonhosted.org/packages/fc/f5/eae31a306341d8f331f43edb2e9122c7661b975433de5e447939ae61c5da/pillow-12.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:266cd5f2b63ff316d5a1bba46268e603c9caf5606d44f38c2873c380950576ad", size = 4650186, upload-time = "2025-10-15T18:23:17.379Z" },
{ url = "https://files.pythonhosted.org/packages/86/62/2a88339aa40c4c77e79108facbd307d6091e2c0eb5b8d3cf4977cfca2fe6/pillow-12.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:58eea5ebe51504057dd95c5b77d21700b77615ab0243d8152793dc00eb4faf01", size = 6230308, upload-time = "2025-10-15T18:23:18.971Z" },
{ url = "https://files.pythonhosted.org/packages/c7/33/5425a8992bcb32d1cb9fa3dd39a89e613d09a22f2c8083b7bf43c455f760/pillow-12.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f13711b1a5ba512d647a0e4ba79280d3a9a045aaf7e0cc6fbe96b91d4cdf6b0c", size = 8039222, upload-time = "2025-10-15T18:23:20.909Z" },
{ url = "https://files.pythonhosted.org/packages/d8/61/3f5d3b35c5728f37953d3eec5b5f3e77111949523bd2dd7f31a851e50690/pillow-12.0.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6846bd2d116ff42cba6b646edf5bf61d37e5cbd256425fa089fee4ff5c07a99e", size = 6346657, upload-time = "2025-10-15T18:23:23.077Z" },
{ url = "https://files.pythonhosted.org/packages/3a/be/ee90a3d79271227e0f0a33c453531efd6ed14b2e708596ba5dd9be948da3/pillow-12.0.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c98fa880d695de164b4135a52fd2e9cd7b7c90a9d8ac5e9e443a24a95ef9248e", size = 7038482, upload-time = "2025-10-15T18:23:25.005Z" },
{ url = "https://files.pythonhosted.org/packages/44/34/a16b6a4d1ad727de390e9bd9f19f5f669e079e5826ec0f329010ddea492f/pillow-12.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:fa3ed2a29a9e9d2d488b4da81dcb54720ac3104a20bf0bd273f1e4648aff5af9", size = 6461416, upload-time = "2025-10-15T18:23:27.009Z" },
{ url = "https://files.pythonhosted.org/packages/b6/39/1aa5850d2ade7d7ba9f54e4e4c17077244ff7a2d9e25998c38a29749eb3f/pillow-12.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d034140032870024e6b9892c692fe2968493790dd57208b2c37e3fb35f6df3ab", size = 7131584, upload-time = "2025-10-15T18:23:29.752Z" },
{ url = "https://files.pythonhosted.org/packages/bf/db/4fae862f8fad0167073a7733973bfa955f47e2cac3dc3e3e6257d10fab4a/pillow-12.0.0-cp314-cp314-win32.whl", hash = "sha256:1b1b133e6e16105f524a8dec491e0586d072948ce15c9b914e41cdadd209052b", size = 6400621, upload-time = "2025-10-15T18:23:32.06Z" },
{ url = "https://files.pythonhosted.org/packages/2b/24/b350c31543fb0107ab2599464d7e28e6f856027aadda995022e695313d94/pillow-12.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:8dc232e39d409036af549c86f24aed8273a40ffa459981146829a324e0848b4b", size = 7142916, upload-time = "2025-10-15T18:23:34.71Z" },
{ url = "https://files.pythonhosted.org/packages/0f/9b/0ba5a6fd9351793996ef7487c4fdbde8d3f5f75dbedc093bb598648fddf0/pillow-12.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:d52610d51e265a51518692045e372a4c363056130d922a7351429ac9f27e70b0", size = 2523836, upload-time = "2025-10-15T18:23:36.967Z" },
{ url = "https://files.pythonhosted.org/packages/f5/7a/ceee0840aebc579af529b523d530840338ecf63992395842e54edc805987/pillow-12.0.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:1979f4566bb96c1e50a62d9831e2ea2d1211761e5662afc545fa766f996632f6", size = 5255092, upload-time = "2025-10-15T18:23:38.573Z" },
{ url = "https://files.pythonhosted.org/packages/44/76/20776057b4bfd1aef4eeca992ebde0f53a4dce874f3ae693d0ec90a4f79b/pillow-12.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b2e4b27a6e15b04832fe9bf292b94b5ca156016bbc1ea9c2c20098a0320d6cf6", size = 4653158, upload-time = "2025-10-15T18:23:40.238Z" },
{ url = "https://files.pythonhosted.org/packages/82/3f/d9ff92ace07be8836b4e7e87e6a4c7a8318d47c2f1463ffcf121fc57d9cb/pillow-12.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fb3096c30df99fd01c7bf8e544f392103d0795b9f98ba71a8054bcbf56b255f1", size = 6267882, upload-time = "2025-10-15T18:23:42.434Z" },
{ url = "https://files.pythonhosted.org/packages/9f/7a/4f7ff87f00d3ad33ba21af78bfcd2f032107710baf8280e3722ceec28cda/pillow-12.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7438839e9e053ef79f7112c881cef684013855016f928b168b81ed5835f3e75e", size = 8071001, upload-time = "2025-10-15T18:23:44.29Z" },
{ url = "https://files.pythonhosted.org/packages/75/87/fcea108944a52dad8cca0715ae6247e271eb80459364a98518f1e4f480c1/pillow-12.0.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5d5c411a8eaa2299322b647cd932586b1427367fd3184ffbb8f7a219ea2041ca", size = 6380146, upload-time = "2025-10-15T18:23:46.065Z" },
{ url = "https://files.pythonhosted.org/packages/91/52/0d31b5e571ef5fd111d2978b84603fce26aba1b6092f28e941cb46570745/pillow-12.0.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d7e091d464ac59d2c7ad8e7e08105eaf9dafbc3883fd7265ffccc2baad6ac925", size = 7067344, upload-time = "2025-10-15T18:23:47.898Z" },
{ url = "https://files.pythonhosted.org/packages/7b/f4/2dd3d721f875f928d48e83bb30a434dee75a2531bca839bb996bb0aa5a91/pillow-12.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:792a2c0be4dcc18af9d4a2dfd8a11a17d5e25274a1062b0ec1c2d79c76f3e7f8", size = 6491864, upload-time = "2025-10-15T18:23:49.607Z" },
{ url = "https://files.pythonhosted.org/packages/30/4b/667dfcf3d61fc309ba5a15b141845cece5915e39b99c1ceab0f34bf1d124/pillow-12.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:afbefa430092f71a9593a99ab6a4e7538bc9eabbf7bf94f91510d3503943edc4", size = 7158911, upload-time = "2025-10-15T18:23:51.351Z" },
{ url = "https://files.pythonhosted.org/packages/a2/2f/16cabcc6426c32218ace36bf0d55955e813f2958afddbf1d391849fee9d1/pillow-12.0.0-cp314-cp314t-win32.whl", hash = "sha256:3830c769decf88f1289680a59d4f4c46c72573446352e2befec9a8512104fa52", size = 6408045, upload-time = "2025-10-15T18:23:53.177Z" },
{ url = "https://files.pythonhosted.org/packages/35/73/e29aa0c9c666cf787628d3f0dcf379f4791fba79f4936d02f8b37165bdf8/pillow-12.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:905b0365b210c73afb0ebe9101a32572152dfd1c144c7e28968a331b9217b94a", size = 7148282, upload-time = "2025-10-15T18:23:55.316Z" },
{ url = "https://files.pythonhosted.org/packages/c1/70/6b41bdcddf541b437bbb9f47f94d2db5d9ddef6c37ccab8c9107743748a4/pillow-12.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:99353a06902c2e43b43e8ff74ee65a7d90307d82370604746738a1e0661ccca7", size = 2525630, upload-time = "2025-10-15T18:23:57.149Z" },
]
[[package]]
name = "platformdirs"
version = "4.5.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/cf/86/0248f086a84f01b37aaec0fa567b397df1a119f73c16f6c7a9aac73ea309/platformdirs-4.5.1.tar.gz", hash = "sha256:61d5cdcc6065745cdd94f0f878977f8de9437be93de97c1c12f853c9c0cdcbda", size = 21715, upload-time = "2025-12-05T13:52:58.638Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/cb/28/3bfe2fa5a7b9c46fe7e13c97bda14c895fb10fa2ebf1d0abb90e0cea7ee1/platformdirs-4.5.1-py3-none-any.whl", hash = "sha256:d03afa3963c806a9bed9d5125c8f4cb2fdaf74a55ab60e5d59b3fde758104d31", size = 18731, upload-time = "2025-12-05T13:52:56.823Z" },
]
[[package]]
name = "pyasn1"
version = "0.6.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/ba/e9/01f1a64245b89f039897cb0130016d79f77d52669aae6ee7b159a6c4c018/pyasn1-0.6.1.tar.gz", hash = "sha256:6f580d2bdd84365380830acf45550f2511469f673cb4a5ae3857a3170128b034", size = 145322, upload-time = "2024-09-10T22:41:42.55Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/c8/f1/d6a797abb14f6283c0ddff96bbdd46937f64122b8c925cab503dd37f8214/pyasn1-0.6.1-py3-none-any.whl", hash = "sha256:0d632f46f2ba09143da3a8afe9e33fb6f92fa2320ab7e886e2d0f7672af84629", size = 83135, upload-time = "2024-09-11T16:00:36.122Z" },
]
[[package]]
name = "pycparser"
version = "2.23"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/fe/cf/d2d3b9f5699fb1e4615c8e32ff220203e43b248e1dfcc6736ad9057731ca/pycparser-2.23.tar.gz", hash = "sha256:78816d4f24add8f10a06d6f05b4d424ad9e96cfebf68a4ddc99c65c0720d00c2", size = 173734, upload-time = "2025-09-09T13:23:47.91Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/a0/e3/59cd50310fc9b59512193629e1984c1f95e5c8ae6e5d8c69532ccc65a7fe/pycparser-2.23-py3-none-any.whl", hash = "sha256:e5c6e8d3fbad53479cab09ac03729e0a9faf2bee3db8208a550daf5af81a5934", size = 118140, upload-time = "2025-09-09T13:23:46.651Z" },
]
[[package]]
name = "pyfa"
version = "0.1.0"
source = { virtual = "." }
dependencies = [
{ name = "beautifulsoup4" },
{ name = "cryptography" },
{ name = "logbook" },
{ name = "markdown2" },
{ name = "matplotlib" },
{ name = "numpy" },
{ name = "packaging" },
{ name = "python-dateutil" },
{ name = "python-jose" },
{ name = "pyyaml" },
{ name = "requests" },
{ name = "requests-cache" },
{ name = "roman" },
{ name = "ruff" },
{ name = "sqlalchemy" },
{ name = "wxpython" },
]
[package.metadata]
requires-dist = [
{ name = "beautifulsoup4", specifier = "==4.12.2" },
{ name = "cryptography", specifier = "==42.0.4" },
{ name = "logbook", specifier = "==1.7.0.post0" },
{ name = "markdown2", specifier = "==2.4.11" },
{ name = "matplotlib", specifier = "==3.8.2" },
{ name = "numpy", specifier = "==1.26.2" },
{ name = "packaging", specifier = "==23.2" },
{ name = "python-dateutil", specifier = "==2.8.2" },
{ name = "python-jose", specifier = "==3.3.0" },
{ name = "pyyaml", specifier = "==6.0.1" },
{ name = "requests", specifier = "==2.31.0" },
{ name = "requests-cache", specifier = "==1.1.1" },
{ name = "roman", specifier = "==4.1" },
{ name = "ruff", specifier = ">=0.14.8" },
{ name = "sqlalchemy", specifier = "==1.4.50" },
{ name = "wxpython", specifier = "==4.2.1" },
]
[[package]]
name = "pyparsing"
version = "3.3.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/33/c1/1d9de9aeaa1b89b0186e5fe23294ff6517fce1bc69149185577cd31016b2/pyparsing-3.3.1.tar.gz", hash = "sha256:47fad0f17ac1e2cad3de3b458570fbc9b03560aa029ed5e16ee5554da9a2251c", size = 1550512, upload-time = "2025-12-23T03:14:04.391Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/8b/40/2614036cdd416452f5bf98ec037f38a1afb17f327cb8e6b652d4729e0af8/pyparsing-3.3.1-py3-none-any.whl", hash = "sha256:023b5e7e5520ad96642e2c6db4cb683d3970bd640cdf7115049a6e9c3682df82", size = 121793, upload-time = "2025-12-23T03:14:02.103Z" },
]
[[package]]
name = "python-dateutil"
version = "2.8.2"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "six" },
]
sdist = { url = "https://files.pythonhosted.org/packages/4c/c4/13b4776ea2d76c115c1d1b84579f3764ee6d57204f6be27119f13a61d0a9/python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86", size = 357324, upload-time = "2021-07-14T08:19:19.783Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/36/7a/87837f39d0296e723bb9b62bbb257d0355c7f6128853c78955f57342a56d/python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9", size = 247702, upload-time = "2021-07-14T08:19:18.161Z" },
]
[[package]]
name = "python-jose"
version = "3.3.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "ecdsa" },
{ name = "pyasn1" },
{ name = "rsa" },
]
sdist = { url = "https://files.pythonhosted.org/packages/e4/19/b2c86504116dc5f0635d29f802da858404d77d930a25633d2e86a64a35b3/python-jose-3.3.0.tar.gz", hash = "sha256:55779b5e6ad599c6336191246e95eb2293a9ddebd555f796a65f838f07e5d78a", size = 129068, upload-time = "2021-06-05T03:30:40.895Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/bd/2d/e94b2f7bab6773c70efc70a61d66e312e1febccd9e0db6b9e0adf58cbad1/python_jose-3.3.0-py2.py3-none-any.whl", hash = "sha256:9b1376b023f8b298536eedd47ae1089bcdb848f1535ab30555cd92002d78923a", size = 33530, upload-time = "2021-06-05T03:30:38.099Z" },
]
[[package]]
name = "pyyaml"
version = "6.0.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/cd/e5/af35f7ea75cf72f2cd079c95ee16797de7cd71f29ea7c68ae5ce7be1eda0/PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43", size = 125201, upload-time = "2023-07-18T00:00:23.308Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/bc/06/1b305bf6aa704343be85444c9d011f626c763abb40c0edc1cad13bfd7f86/PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28", size = 178692, upload-time = "2023-08-28T18:43:24.924Z" },
{ url = "https://files.pythonhosted.org/packages/84/02/404de95ced348b73dd84f70e15a41843d817ff8c1744516bf78358f2ffd2/PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9", size = 165622, upload-time = "2023-08-28T18:43:26.54Z" },
{ url = "https://files.pythonhosted.org/packages/c7/4c/4a2908632fc980da6d918b9de9c1d9d7d7e70b2672b1ad5166ed27841ef7/PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef", size = 696937, upload-time = "2024-01-18T20:40:22.92Z" },
{ url = "https://files.pythonhosted.org/packages/b4/33/720548182ffa8344418126017aa1d4ab4aeec9a2275f04ce3f3573d8ace8/PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0", size = 724969, upload-time = "2023-08-28T18:43:28.56Z" },
{ url = "https://files.pythonhosted.org/packages/4f/78/77b40157b6cb5f2d3d31a3d9b2efd1ba3505371f76730d267e8b32cf4b7f/PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4", size = 712604, upload-time = "2023-08-28T18:43:30.206Z" },
{ url = "https://files.pythonhosted.org/packages/2e/97/3e0e089ee85e840f4b15bfa00e4e63d84a3691ababbfea92d6f820ea6f21/PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54", size = 126098, upload-time = "2023-08-28T18:43:31.835Z" },
{ url = "https://files.pythonhosted.org/packages/2b/9f/fbade56564ad486809c27b322d0f7e6a89c01f6b4fe208402e90d4443a99/PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df", size = 138675, upload-time = "2023-08-28T18:43:33.613Z" },
]
[[package]]
name = "requests"
version = "2.31.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "certifi" },
{ name = "charset-normalizer" },
{ name = "idna" },
{ name = "urllib3" },
]
sdist = { url = "https://files.pythonhosted.org/packages/9d/be/10918a2eac4ae9f02f6cfe6414b7a155ccd8f7f9d4380d62fd5b955065c3/requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1", size = 110794, upload-time = "2023-05-22T15:12:44.175Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f", size = 62574, upload-time = "2023-05-22T15:12:42.313Z" },
]
[[package]]
name = "requests-cache"
version = "1.1.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "attrs" },
{ name = "cattrs" },
{ name = "platformdirs" },
{ name = "requests" },
{ name = "url-normalize" },
{ name = "urllib3" },
]
sdist = { url = "https://files.pythonhosted.org/packages/4d/b6/24aeda90d94fb1fd2cd755d6ce176e526ef61d407f87fd77de6ab0d03157/requests_cache-1.1.1.tar.gz", hash = "sha256:764f93d3fa860be72125a568c2cc8eafb151cf29b4dc2515433a56ee657e1c60", size = 2876425, upload-time = "2023-11-19T07:20:24.744Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/12/67/9ee2d8d8cca30f2cdc1048a4cd7dac10db2b49ec1eeca31f15a0160b71a0/requests_cache-1.1.1-py3-none-any.whl", hash = "sha256:c8420cf096f3aafde13c374979c21844752e2694ffd8710e6764685bb577ac90", size = 60260, upload-time = "2023-11-19T07:20:22.593Z" },
]
[[package]]
name = "roman"
version = "4.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/32/0c/10c242792e9c857d5d8df19780abec0f241c8a3d9631cccbce16d0f1c769/roman-4.1.tar.gz", hash = "sha256:4da8a200529a730822a27f1704b3ac70bc907141d3bc558115fb8e36af13b412", size = 7005, upload-time = "2023-05-26T08:25:31.645Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/b3/e7/533d5082852a3e0001392b421172d1659a8dc81dad9c41d378adf891d689/roman-4.1-py3-none-any.whl", hash = "sha256:f131fd5eee3510f6173b825404eb97875a6c1925f73a2d7d48cfc67823a67c3c", size = 5490, upload-time = "2023-05-26T08:25:29.342Z" },
]
[[package]]
name = "rsa"
version = "4.9.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pyasn1" },
]
sdist = { url = "https://files.pythonhosted.org/packages/da/8a/22b7beea3ee0d44b1916c0c1cb0ee3af23b700b6da9f04991899d0c555d4/rsa-4.9.1.tar.gz", hash = "sha256:e7bdbfdb5497da4c07dfd35530e1a902659db6ff241e39d9953cad06ebd0ae75", size = 29034, upload-time = "2025-04-16T09:51:18.218Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/64/8d/0133e4eb4beed9e425d9a98ed6e081a55d195481b7632472be1af08d2f6b/rsa-4.9.1-py3-none-any.whl", hash = "sha256:68635866661c6836b8d39430f97a996acbd61bfa49406748ea243539fe239762", size = 34696, upload-time = "2025-04-16T09:51:17.142Z" },
]
[[package]]
name = "ruff"
version = "0.14.8"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/ed/d9/f7a0c4b3a2bf2556cd5d99b05372c29980249ef71e8e32669ba77428c82c/ruff-0.14.8.tar.gz", hash = "sha256:774ed0dd87d6ce925e3b8496feb3a00ac564bea52b9feb551ecd17e0a23d1eed", size = 5765385, upload-time = "2025-12-04T15:06:17.669Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/48/b8/9537b52010134b1d2b72870cc3f92d5fb759394094741b09ceccae183fbe/ruff-0.14.8-py3-none-linux_armv6l.whl", hash = "sha256:ec071e9c82eca417f6111fd39f7043acb53cd3fde9b1f95bbed745962e345afb", size = 13441540, upload-time = "2025-12-04T15:06:14.896Z" },
{ url = "https://files.pythonhosted.org/packages/24/00/99031684efb025829713682012b6dd37279b1f695ed1b01725f85fd94b38/ruff-0.14.8-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:8cdb162a7159f4ca36ce980a18c43d8f036966e7f73f866ac8f493b75e0c27e9", size = 13669384, upload-time = "2025-12-04T15:06:51.809Z" },
{ url = "https://files.pythonhosted.org/packages/72/64/3eb5949169fc19c50c04f28ece2c189d3b6edd57e5b533649dae6ca484fe/ruff-0.14.8-py3-none-macosx_11_0_arm64.whl", hash = "sha256:2e2fcbefe91f9fad0916850edf0854530c15bd1926b6b779de47e9ab619ea38f", size = 12806917, upload-time = "2025-12-04T15:06:08.925Z" },
{ url = "https://files.pythonhosted.org/packages/c4/08/5250babb0b1b11910f470370ec0cbc67470231f7cdc033cee57d4976f941/ruff-0.14.8-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9d70721066a296f45786ec31916dc287b44040f553da21564de0ab4d45a869b", size = 13256112, upload-time = "2025-12-04T15:06:23.498Z" },
{ url = "https://files.pythonhosted.org/packages/78/4c/6c588e97a8e8c2d4b522c31a579e1df2b4d003eddfbe23d1f262b1a431ff/ruff-0.14.8-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2c87e09b3cd9d126fc67a9ecd3b5b1d3ded2b9c7fce3f16e315346b9d05cfb52", size = 13227559, upload-time = "2025-12-04T15:06:33.432Z" },
{ url = "https://files.pythonhosted.org/packages/23/ce/5f78cea13eda8eceac71b5f6fa6e9223df9b87bb2c1891c166d1f0dce9f1/ruff-0.14.8-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d62cb310c4fbcb9ee4ac023fe17f984ae1e12b8a4a02e3d21489f9a2a5f730c", size = 13896379, upload-time = "2025-12-04T15:06:02.687Z" },
{ url = "https://files.pythonhosted.org/packages/cf/79/13de4517c4dadce9218a20035b21212a4c180e009507731f0d3b3f5df85a/ruff-0.14.8-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:1af35c2d62633d4da0521178e8a2641c636d2a7153da0bac1b30cfd4ccd91344", size = 15372786, upload-time = "2025-12-04T15:06:29.828Z" },
{ url = "https://files.pythonhosted.org/packages/00/06/33df72b3bb42be8a1c3815fd4fae83fa2945fc725a25d87ba3e42d1cc108/ruff-0.14.8-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:25add4575ffecc53d60eed3f24b1e934493631b48ebbc6ebaf9d8517924aca4b", size = 14990029, upload-time = "2025-12-04T15:06:36.812Z" },
{ url = "https://files.pythonhosted.org/packages/64/61/0f34927bd90925880394de0e081ce1afab66d7b3525336f5771dcf0cb46c/ruff-0.14.8-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4c943d847b7f02f7db4201a0600ea7d244d8a404fbb639b439e987edcf2baf9a", size = 14407037, upload-time = "2025-12-04T15:06:39.979Z" },
{ url = "https://files.pythonhosted.org/packages/96/bc/058fe0aefc0fbf0d19614cb6d1a3e2c048f7dc77ca64957f33b12cfdc5ef/ruff-0.14.8-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb6e8bf7b4f627548daa1b69283dac5a296bfe9ce856703b03130732e20ddfe2", size = 14102390, upload-time = "2025-12-04T15:06:46.372Z" },
{ url = "https://files.pythonhosted.org/packages/af/a4/e4f77b02b804546f4c17e8b37a524c27012dd6ff05855d2243b49a7d3cb9/ruff-0.14.8-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:7aaf2974f378e6b01d1e257c6948207aec6a9b5ba53fab23d0182efb887a0e4a", size = 14230793, upload-time = "2025-12-04T15:06:20.497Z" },
{ url = "https://files.pythonhosted.org/packages/3f/52/bb8c02373f79552e8d087cedaffad76b8892033d2876c2498a2582f09dcf/ruff-0.14.8-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:e5758ca513c43ad8a4ef13f0f081f80f08008f410790f3611a21a92421ab045b", size = 13160039, upload-time = "2025-12-04T15:06:49.06Z" },
{ url = "https://files.pythonhosted.org/packages/1f/ad/b69d6962e477842e25c0b11622548df746290cc6d76f9e0f4ed7456c2c31/ruff-0.14.8-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:f74f7ba163b6e85a8d81a590363bf71618847e5078d90827749bfda1d88c9cdf", size = 13205158, upload-time = "2025-12-04T15:06:54.574Z" },
{ url = "https://files.pythonhosted.org/packages/06/63/54f23da1315c0b3dfc1bc03fbc34e10378918a20c0b0f086418734e57e74/ruff-0.14.8-py3-none-musllinux_1_2_i686.whl", hash = "sha256:eed28f6fafcc9591994c42254f5a5c5ca40e69a30721d2ab18bb0bb3baac3ab6", size = 13469550, upload-time = "2025-12-04T15:05:59.209Z" },
{ url = "https://files.pythonhosted.org/packages/70/7d/a4d7b1961e4903bc37fffb7ddcfaa7beb250f67d97cfd1ee1d5cddb1ec90/ruff-0.14.8-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:21d48fa744c9d1cb8d71eb0a740c4dd02751a5de9db9a730a8ef75ca34cf138e", size = 14211332, upload-time = "2025-12-04T15:06:06.027Z" },
{ url = "https://files.pythonhosted.org/packages/5d/93/2a5063341fa17054e5c86582136e9895db773e3c2ffb770dde50a09f35f0/ruff-0.14.8-py3-none-win32.whl", hash = "sha256:15f04cb45c051159baebb0f0037f404f1dc2f15a927418f29730f411a79bc4e7", size = 13151890, upload-time = "2025-12-04T15:06:11.668Z" },
{ url = "https://files.pythonhosted.org/packages/02/1c/65c61a0859c0add13a3e1cbb6024b42de587456a43006ca2d4fd3d1618fe/ruff-0.14.8-py3-none-win_amd64.whl", hash = "sha256:9eeb0b24242b5bbff3011409a739929f497f3fb5fe3b5698aba5e77e8c833097", size = 14537826, upload-time = "2025-12-04T15:06:26.409Z" },
{ url = "https://files.pythonhosted.org/packages/6d/63/8b41cea3afd7f58eb64ac9251668ee0073789a3bc9ac6f816c8c6fef986d/ruff-0.14.8-py3-none-win_arm64.whl", hash = "sha256:965a582c93c63fe715fd3e3f8aa37c4b776777203d8e1d8aa3cc0c14424a4b99", size = 13634522, upload-time = "2025-12-04T15:06:43.212Z" },
]
[[package]]
name = "six"
version = "1.17.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" },
]
[[package]]
name = "soupsieve"
version = "2.8.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/89/23/adf3796d740536d63a6fbda113d07e60c734b6ed5d3058d1e47fc0495e47/soupsieve-2.8.1.tar.gz", hash = "sha256:4cf733bc50fa805f5df4b8ef4740fc0e0fa6218cf3006269afd3f9d6d80fd350", size = 117856, upload-time = "2025-12-18T13:50:34.655Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/48/f3/b67d6ea49ca9154453b6d70b34ea22f3996b9fa55da105a79d8732227adc/soupsieve-2.8.1-py3-none-any.whl", hash = "sha256:a11fe2a6f3d76ab3cf2de04eb339c1be5b506a8a47f2ceb6d139803177f85434", size = 36710, upload-time = "2025-12-18T13:50:33.267Z" },
]
[[package]]
name = "sqlalchemy"
version = "1.4.50"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "greenlet", marker = "platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/5a/0a/dabe332c40afebb0a979d3e66b34570fce2f8611bae19b186f0c69f54643/SQLAlchemy-1.4.50.tar.gz", hash = "sha256:3b97ddf509fc21e10b09403b5219b06c5b558b27fc2453150274fa4e70707dbf", size = 8517526, upload-time = "2023-10-29T20:32:00.003Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/5e/ff/72d6f3261ed05b76f7d4127cfc2e5e6590cf16bd87061331ece5066cdfe8/SQLAlchemy-1.4.50-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:77fde9bf74f4659864c8e26ac08add8b084e479b9a18388e7db377afc391f926", size = 1581064, upload-time = "2024-01-11T19:15:51.104Z" },
{ url = "https://files.pythonhosted.org/packages/b8/e5/eb51bcc247017e4630bb107b15d1ceb8490f588da92b3449905231a61519/SQLAlchemy-1.4.50-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4cb501d585aa74a0f86d0ea6263b9c5e1d1463f8f9071392477fd401bd3c7cc", size = 1620671, upload-time = "2023-10-29T20:56:37.27Z" },
{ url = "https://files.pythonhosted.org/packages/b7/cf/4bf87f387b5360d14ef6cbcca64decf5a37ed2f6aa734724825d5146f821/SQLAlchemy-1.4.50-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a7a66297e46f85a04d68981917c75723e377d2e0599d15fbe7a56abed5e2d75", size = 1619718, upload-time = "2023-10-29T20:56:32.552Z" },
{ url = "https://files.pythonhosted.org/packages/57/3b/eff9b34517b4db4eadd95e86a79791deae505d18e19ea50af8ef8d1ea7a6/SQLAlchemy-1.4.50-cp312-cp312-win32.whl", hash = "sha256:e86c920b7d362cfa078c8b40e7765cbc34efb44c1007d7557920be9ddf138ec7", size = 1581637, upload-time = "2024-01-11T19:20:19.837Z" },
{ url = "https://files.pythonhosted.org/packages/f9/24/59bf0b94a619e16743e5bf51ebd10cbe97b8c946b6bd57dbf37189bd38dc/SQLAlchemy-1.4.50-cp312-cp312-win_amd64.whl", hash = "sha256:6b3df20fbbcbcd1c1d43f49ccf3eefb370499088ca251ded632b8cbaee1d497d", size = 1583598, upload-time = "2024-01-11T19:19:03.839Z" },
]
[[package]]
name = "typing-extensions"
version = "4.15.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" },
]
[[package]]
name = "url-normalize"
version = "2.2.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "idna" },
]
sdist = { url = "https://files.pythonhosted.org/packages/80/31/febb777441e5fcdaacb4522316bf2a527c44551430a4873b052d545e3279/url_normalize-2.2.1.tar.gz", hash = "sha256:74a540a3b6eba1d95bdc610c24f2c0141639f3ba903501e61a52a8730247ff37", size = 18846, upload-time = "2025-04-26T20:37:58.553Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/bc/d9/5ec15501b675f7bc07c5d16aa70d8d778b12375686b6efd47656efdc67cd/url_normalize-2.2.1-py3-none-any.whl", hash = "sha256:3deb687587dc91f7b25c9ae5162ffc0f057ae85d22b1e15cf5698311247f567b", size = 14728, upload-time = "2025-04-26T20:37:57.217Z" },
]
[[package]]
name = "urllib3"
version = "2.6.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/1e/24/a2a2ed9addd907787d7aa0355ba36a6cadf1768b934c652ea78acbd59dcd/urllib3-2.6.2.tar.gz", hash = "sha256:016f9c98bb7e98085cb2b4b17b87d2c702975664e4f060c6532e64d1c1a5e797", size = 432930, upload-time = "2025-12-11T15:56:40.252Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/6d/b9/4095b668ea3678bf6a0af005527f39de12fb026516fb3df17495a733b7f8/urllib3-2.6.2-py3-none-any.whl", hash = "sha256:ec21cddfe7724fc7cb4ba4bea7aa8e2ef36f607a4bab81aa6ce42a13dc3f03dd", size = 131182, upload-time = "2025-12-11T15:56:38.584Z" },
]
[[package]]
name = "wxpython"
version = "4.2.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pillow" },
{ name = "six" },
]
sdist = { url = "https://files.pythonhosted.org/packages/aa/64/d749e767a8ce7bdc3d533334e03bb1106fc4e4803d16f931fada9007ee13/wxPython-4.2.1.tar.gz", hash = "sha256:e48de211a6606bf072ec3fa778771d6b746c00b7f4b970eb58728ddf56d13d5c", size = 73724359, upload-time = "2023-06-08T01:26:49.508Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/52/5b/55e826723af15e1d9b537c15c4e329a2921e119779aaeb2c0e792bbc5684/wxPython-4.2.1-cp312-cp312-macosx_10_10_universal2.whl", hash = "sha256:957a6e7cc68a8e4d7ca49c72a691b6efd5684040f4f03b112d0122e7ab470497", size = 31534250, upload-time = "2023-06-08T01:24:47.215Z" },
{ url = "https://files.pythonhosted.org/packages/ee/7c/e7bff7c8d17e279386364214189d8a93ae4ef11f9a2660d4d79b536e1fcb/wxPython-4.2.1-cp312-cp312-win32.whl", hash = "sha256:8d846a785cd33c31e7eb42038eb159c88977d38208496b8322d14aef107f3eec", size = 15433640, upload-time = "2023-06-08T01:24:54.956Z" },
{ url = "https://files.pythonhosted.org/packages/b7/a4/5b4e30005b0bcf2811537869645aa8a0165fee3de9f387089e34265ca412/wxPython-4.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:1ca327c877f276b33e2c4b6cb8417964305ee505e2509fb2000851d48b82328f", size = 17838517, upload-time = "2023-06-08T01:25:01.8Z" },
]

View File

@@ -1 +1 @@
version: v2.65.2
version: v2.65.4