implement cli for benchmarking and evilnkode

This commit is contained in:
2025-09-09 13:21:27 -05:00
parent aa2e949938
commit 68c79467e4
7 changed files with 793 additions and 211 deletions

View File

@@ -1,36 +1,90 @@
# Evil nKode # Evilnkode Project
Simulated nKode Cracker This README provides instructions for setting up and running the `evilnkode` project using Conda, activating the environment, and executing the provided CLI scripts. It also covers how to access help for command-line options.
## Installation ## Prerequisites
- Python version 3.10 or greater is required - **Conda**: Ensure you have Conda installed (Miniconda or Anaconda). Download from [conda.io](https://conda.io).
- Install anaconda (or your preferred tool for environment management)
### Using conda ## Setting Up the Environment
To set up the project environment using the provided `environment.yaml` file, follow these steps:
1. **Install the environment**:
- Ensure you are in the project root directory where `environment.yaml` is located.
- Run the following command to create the `evilnkode` environment:
```bash ```bash
conda env create -f environment.yml conda env create -f environment.yaml
conda activate pynkode ```
- This will install all dependencies specified in `environment.yaml`.
## Activating the Environment
To activate the `evilnkode` environment, run:
```bash
conda activate evilnkode
``` ```
## Starting a Jupyter Notebook Once activated, your terminal prompt should change to include `(evilnkode)`, indicating the environment is active.
## Running CLI Scripts
The project includes two main CLI scripts: `cli.visualnkode` and `cli.benchmark_histogram`. Below are instructions to run each.
### Running `cli.visualnkode`
To execute the `visualnkode` CLI script:
### Option 1: Using classic Jupyter Notebook
```bash ```bash
# Ensure your environment is activated python -m cli.visualnkode
# For conda: conda activate pynkode
# For pyenv: (should be automatic if in the directory)
# Start the Jupyter Notebook server
jupyter notebook
``` ```
### Option 2: Using JupyterLab - This command runs the `visualnkode` module from the `cli` package.
- To view available options and arguments, use the `-help` flag:
```bash ```bash
# Ensure your environment is activated python -m cli.visualnkode -help
# Start JupyterLab
jupyter lab
``` ```
## Notebooks ### Running `cli.benchmark_histogram`
- [evilnkode](notebooks/evilnkode.ipynb)
To execute the `benchmark_histogram` CLI script:
```bash
python -m cli.benchmark_histogram
```
- This command runs the `benchmark_histogram` module, which may generate output such as benchmark results or histograms. For example, it might produce output like:
```
File exists: output/slidingtowershufflekeypad-6-8-4-5-4-4-10000/benchmark/slidingtowershufflekeypad-6-8-4-5-4-4-10000.pkl
Bench SlidingTowerShuffle Break 5
Bench SlidingTowerShuffle Replay 5
```
- To view available options and arguments, use the `-help` flag:
```bash
python -m cli.benchmark_histogram -help
```
## Using the `-help` Flag
Both CLI scripts (`cli.visualnkode` and `cli.benchmark_histogram`) support a `-help` flag to display available command-line options and their descriptions. Run the following to explore options for each script:
```bash
python -m cli.visualnkode -help
python -m cli.benchmark_histogram -help
```
This will provide detailed information about parameters, flags, and usage for each script.
## Project Structure
Key files and directories in the project:
- `environment.yaml`: Conda environment configuration file.
- `cli/`: Contains CLI scripts (`visualnkode` and `benchmark_histogram`).
- `output/`: Directory where script outputs, such as benchmark results, are stored.
- `src/`: Source code for the project.
- `tests/`: Test scripts for the project.
- `requirements.txt`: Additional dependencies (if needed outside Conda).
For further details, explore the project documentation in the `docs/` directory.

0
cli/__init__.py Normal file
View File

115
cli/benchmark_histogram.py Normal file
View File

@@ -0,0 +1,115 @@
import argparse
from src.benchmark import benchmark
import matplotlib.pyplot as plt
from pathlib import Path
from statistics import mean
from src.keypad.keypad import (
RandomSplitShuffleKeypad,
RandomShuffleKeypad,
SlidingSplitShuffleKeypad,
SlidingTowerShuffleKeypad,
)
def bench_histogram(data, title, number_of_keys, properties_per_key, passcode_len, max_tries_before_lockout, complexity,
disparity, run_count, save_path: Path = None):
min_val = min(data)
max_val = max(data)
bins = range(min_val, max_val + 2)
plt.hist(data, bins=bins, edgecolor='black')
plt.title(title)
plt.xlabel('# of Login Observations')
plt.ylabel('Simulations')
text = (f"number_of_keys={number_of_keys}\n"
f"properties_per_key={properties_per_key}\n"
f"passcode_len={passcode_len}\n"
f"max_tries_before_lockout={max_tries_before_lockout}\n"
f"complexity={complexity}\n"
f"disparity={disparity}\n"
f"run_count={run_count}")
plt.text(0.95, 0.95, text, transform=plt.gca().transAxes, fontsize=10,
verticalalignment='top', horizontalalignment='right', bbox=dict(facecolor='white', alpha=0.5))
if save_path:
save_path = save_path / "histogram"
save_path.mkdir(parents=True, exist_ok=True)
filename = (f"{title.replace(' ', '_')}_keys{number_of_keys}_"
f"props{properties_per_key}_pass{passcode_len}_tries{max_tries_before_lockout}_"
f"comp{complexity}_disp{disparity}_runs{run_count}.png")
plt.savefig(save_path / filename, bbox_inches='tight', dpi=300)
plt.close()
def main():
parser = argparse.ArgumentParser(description='Benchmark Keypad Shuffle')
parser.add_argument('--shuffle_type', type=str,
choices=['RandomSplitShuffle', 'RandomShuffle', 'SlidingSplitShuffle', 'SlidingTowerShuffle'],
default='SlidingTowerShuffle', help='Type of keypad shuffle')
parser.add_argument('--number_of_keys', type=int, default=6, help='Number of keys')
parser.add_argument('--properties_per_key', type=int, default=8, help='Properties per key')
parser.add_argument('--passcode_len', type=int, default=4, help='Passcode length')
parser.add_argument('--max_tries_before_lockout', type=int, default=5, help='Max tries before lockout')
parser.add_argument('--complexity', type=int, default=4, help='Complexity')
parser.add_argument('--disparity', type=int, default=4, help='Disparity')
parser.add_argument('--run_count', type=int, default=10000, help='Number of runs')
parser.add_argument('--output_dir', type=str, default='./output',
help='Output directory for histograms')
args = parser.parse_args()
shuffle_classes = {
'RandomSplitShuffle': RandomSplitShuffleKeypad,
'RandomShuffle': RandomShuffleKeypad,
'SlidingSplitShuffle': SlidingSplitShuffleKeypad,
'SlidingTowerShuffle': SlidingTowerShuffleKeypad
}
keypad_class = shuffle_classes[args.shuffle_type]
keypad = keypad_class.new_keypad(args.number_of_keys, args.properties_per_key)
shuffle_type = str(type(keypad)).lower().split('.')[-1].replace("'>", "")
run_name = f"{shuffle_type}-{args.number_of_keys}-{args.properties_per_key}-{args.passcode_len}-{args.max_tries_before_lockout}-{args.complexity}-{args.disparity}-{args.run_count}"
save_path = Path(args.output_dir) / run_name
bench_result = benchmark(
number_of_keys=args.number_of_keys,
properties_per_key=args.properties_per_key,
passcode_len=args.passcode_len,
max_tries_before_lockout=args.max_tries_before_lockout,
run_count=args.run_count,
complexity=args.complexity,
disparity=args.disparity,
keypad=keypad,
file_path=save_path,
)
print(f"Bench {args.shuffle_type} Break {mean(bench_result.iterations_to_break)}")
print(f"Bench {args.shuffle_type} Replay {mean(bench_result.iterations_to_replay)}")
bench_histogram(
bench_result.iterations_to_break,
f"{args.shuffle_type} Break",
args.number_of_keys,
args.properties_per_key,
args.passcode_len,
args.max_tries_before_lockout,
args.complexity,
args.disparity,
args.run_count,
save_path
)
bench_histogram(
bench_result.iterations_to_replay,
f"{args.shuffle_type} Replay",
args.number_of_keys,
args.properties_per_key,
args.passcode_len,
args.max_tries_before_lockout,
args.complexity,
args.disparity,
args.run_count,
save_path,
)
if __name__ == "__main__":
main()

View File

@@ -1,16 +1,18 @@
import json import json
from typing import Iterable from typing import Iterable
from dataclasses import dataclass, asdict from dataclasses import dataclass, asdict
from evilnkode import Observation from src.evilnkode import Observation
from utils import observations, passcode_generator from src.utils import observations, passcode_generator
from pathlib import Path from pathlib import Path
from PIL import Image, ImageDraw, ImageFont from PIL import Image, ImageDraw, ImageFont
from src.keypad.keypad import BaseKeypad, SlidingTowerShuffleKeypad from src.keypad.keypad import (
BaseKeypad,
# Project root = parent of *this* file's directory SlidingSplitShuffleKeypad,
PROJECT_ROOT = Path(__file__).resolve().parent.parent SlidingTowerShuffleKeypad,
BASE_DIR = PROJECT_ROOT / "output" RandomShuffleKeypad,
PNG_DIR = PROJECT_ROOT / "output" / "obs_png" RandomSplitShuffleKeypad,
)
import argparse
@dataclass @dataclass
@@ -46,18 +48,7 @@ def _next_json_filename(base_dir: Path) -> Path:
def save_observation_sequence_to_json(seq: ObservationSequence, def save_observation_sequence_to_json(seq: ObservationSequence,
shuffle_name: str, filename: Path) -> None:
filename: Path | None = None) -> None:
"""
Save ObservationSequence to JSON.
- If filename is None, put it under PROJECT_ROOT/output/obs_json/ as observation_{n}.json
- Creates directory if needed
"""
if filename is None:
base_dir = BASE_DIR / shuffle_name / "obs_json"
base_dir.mkdir(parents=True, exist_ok=True)
filename = _next_json_filename(base_dir)
else:
filename.parent.mkdir(parents=True, exist_ok=True) filename.parent.mkdir(parents=True, exist_ok=True)
with filename.open("w", encoding="utf-8") as f: with filename.open("w", encoding="utf-8") as f:
@@ -227,25 +218,36 @@ def _next_run_dir(base_dir: Path) -> Path:
counter += 1 counter += 1
def render_sequence_to_pngs(seq: ObservationSequence, shuffle_name: str, out_dir: Path | None = None) -> None: def render_sequence_to_pngs(seq: ObservationSequence, out_dir: Path) -> None:
""" out_dir.mkdir(parents=True, exist_ok=True)
Render each observation to its own PNG inside a fresh run directory. run_dir = _next_run_dir(out_dir)
Default: PROJECT_ROOT/output/obs_png/run_XXX/observation_001.png
"""
base_dir = BASE_DIR / shuffle_name / "obs_png" if out_dir is None else out_dir
base_dir.mkdir(parents=True, exist_ok=True)
# Create a fresh run dir
run_dir = _next_run_dir(base_dir)
for i, obs in enumerate(seq.observations, start=1): for i, obs in enumerate(seq.observations, start=1):
filename = run_dir / f"observation_{i:03d}.png" filename = run_dir / f"observation_{i:03d}.png"
render_observation_to_png(seq.target_passcode, obs, filename) render_observation_to_png(seq.target_passcode, obs, filename)
if __name__ == "__main__": if __name__ == "__main__":
shuffle_name = "tower_shuffle" shuffle_classes = {
keypad = SlidingTowerShuffleKeypad.new_keypad(6, 9) 'RandomSplitShuffle': RandomSplitShuffleKeypad,
'RandomShuffle': RandomShuffleKeypad,
'SlidingSplitShuffle': SlidingSplitShuffleKeypad,
'SlidingTowerShuffle': SlidingTowerShuffleKeypad
}
parser = argparse.ArgumentParser(description="Generate and save observation sequences with optional PNG rendering.")
parser.add_argument("--number-of-keys", type=int, default=6, help="Number of keys in the keypad (default: 6)")
parser.add_argument("--properties-per-key", type=int, default=9, help="Properties per key (default: 9)")
parser.add_argument("--passcode-length", type=int, default=4, help="Length of the passcode (default: 4)")
parser.add_argument("--complexity", type=int, default=0, help="Complexity of the passcode (default: 0)")
parser.add_argument("--disparity", type=int, default=0, help="Disparity of the passcode (default: 0)")
parser.add_argument("--num-runs", type=int, default=50, help="Number of observations to generate (default: 50)")
parser.add_argument("--shuffle-type", type=str, default="SlidingTowerShuffle", choices=list(shuffle_classes.keys()),
help="Keypad shuffle type: 'RandomShuffle' or 'SlidingTowerShuffle' (default: SlidingTowerShuffle)")
parser.add_argument("--output-dir", type=str, default="./output",
help="Custom output directory for JSON and PNG files")
args = parser.parse_args()
keypad = shuffle_classes[args.shuffle_type].new_keypad(6, 9)
obs_seq = new_observation_sequence(keypad, 4, 0, 0, numb_runs=50) obs_seq = new_observation_sequence(keypad, 4, 0, 0, numb_runs=50)
save_observation_sequence_to_json(obs_seq, shuffle_name) shuffle_type = str(type(keypad)).lower().split('.')[-1].replace("'>", "")
render_sequence_to_pngs(obs_seq, shuffle_name) output_dir = Path(args.output_dir)
save_observation_sequence_to_json(obs_seq, output_dir / "obs.json")
render_sequence_to_pngs(obs_seq, output_dir / "obs_png")

544
environment.yaml Normal file
View File

@@ -0,0 +1,544 @@
name: base
channels:
- defaults
dependencies:
- _anaconda_depends=2024.10=py312_openblas_0
- aiobotocore=2.12.3=py312hca03da5_0
- aiohappyeyeballs=2.4.3=py312hca03da5_0
- aiohttp=3.10.5=py312h80987f9_0
- aioitertools=0.7.1=pyhd3eb1b0_0
- aiosignal=1.2.0=pyhd3eb1b0_0
- alabaster=0.7.16=py312hca03da5_0
- altair=5.0.1=py312hca03da5_0
- anaconda-anon-usage=0.5.0=py312hd6b623d_100
- anaconda-catalogs=0.2.0=py312hca03da5_1
- anaconda-cli-base=0.4.1=py312hca03da5_1
- anaconda-client=1.13.0=py312hca03da5_0
- anaconda-cloud-auth=0.7.2=py312hca03da5_0
- anaconda-navigator=2.6.4=py312hca03da5_0
- anaconda-project=0.11.1=py312hca03da5_0
- annotated-types=0.6.0=py312hca03da5_0
- anyio=4.6.2=py312hca03da5_0
- aom=3.6.0=h313beb8_0
- appdirs=1.4.4=pyhd3eb1b0_0
- applaunchservices=0.3.0=py312hca03da5_0
- appnope=0.1.3=py312hca03da5_1001
- appscript=1.2.5=py312h80987f9_0
- archspec=0.2.3=pyhd3eb1b0_0
- argon2-cffi=21.3.0=pyhd3eb1b0_0
- argon2-cffi-bindings=21.2.0=py312h80987f9_0
- arrow=1.3.0=py312hca03da5_0
- arrow-cpp=16.1.0=hbc20fb2_0
- astroid=3.2.4=py312hca03da5_0
- astropy=6.1.3=py312h80987f9_0
- astropy-iers-data=0.2024.9.2.0.33.23=py312hca03da5_0
- asttokens=2.0.5=pyhd3eb1b0_0
- async-lru=2.0.4=py312hca03da5_0
- asyncssh=2.17.0=py312hca03da5_0
- atomicwrites=1.4.0=py_0
- attrs=24.2.0=py312hca03da5_0
- automat=20.2.0=py_0
- autopep8=2.0.4=pyhd3eb1b0_0
- aws-c-auth=0.6.19=h80987f9_0
- aws-c-cal=0.5.20=h80987f9_0
- aws-c-common=0.8.5=h80987f9_0
- aws-c-compression=0.2.16=h80987f9_0
- aws-c-event-stream=0.2.15=h313beb8_0
- aws-c-http=0.6.25=h80987f9_0
- aws-c-io=0.13.10=h80987f9_0
- aws-c-mqtt=0.7.13=h80987f9_0
- aws-c-s3=0.1.51=h80987f9_0
- aws-c-sdkutils=0.1.6=h80987f9_0
- aws-checksums=0.1.13=h80987f9_0
- aws-crt-cpp=0.18.16=h313beb8_0
- aws-sdk-cpp=1.10.55=h313beb8_0
- babel=2.11.0=py312hca03da5_0
- backports=1.1=pyhd3eb1b0_1
- backports.functools_lru_cache=1.6.4=pyhd3eb1b0_0
- backports.tempfile=1.0=pyhd3eb1b0_1
- backports.weakref=1.0.post1=py_1
- bcrypt=3.2.0=py312h80987f9_1
- beautifulsoup4=4.12.3=py312hca03da5_0
- binaryornot=0.4.4=pyhd3eb1b0_1
- black=24.8.0=py312hca03da5_0
- blas=1.0=openblas
- bleach=6.2.0=py312hca03da5_0
- blinker=1.6.2=py312hca03da5_0
- blosc=1.21.3=h313beb8_0
- bokeh=3.6.0=py312hca03da5_0
- boltons=23.0.0=py312hca03da5_0
- boost-cpp=1.82.0=h48ca7d4_2
- botocore=1.34.69=py312hca03da5_0
- bottleneck=1.4.2=py312ha86b861_0
- brotli=1.0.9=h80987f9_8
- brotli-bin=1.0.9=h80987f9_8
- brotli-python=1.0.9=py312h313beb8_8
- brunsli=0.1=hc377ac9_1
- bzip2=1.0.8=h80987f9_6
- c-ares=1.19.1=h80987f9_0
- c-blosc2=2.12.0=h7df6c2f_0
- ca-certificates=2024.11.26=hca03da5_0
- cachetools=5.3.3=py312hca03da5_0
- cctools=949.0.1=hc179dcd_25
- cctools_osx-arm64=949.0.1=h332cad3_25
- certifi=2024.8.30=py312hca03da5_0
- cffi=1.17.1=py312h3eb5a62_0
- cfitsio=3.470=h7f6438f_7
- chardet=4.0.0=py312hca03da5_1003
- charls=2.2.0=hc377ac9_0
- charset-normalizer=3.3.2=pyhd3eb1b0_0
- click=8.1.7=py312hca03da5_0
- cloudpickle=3.0.0=py312hca03da5_0
- colorama=0.4.6=py312hca03da5_0
- colorcet=3.1.0=py312hca03da5_0
- comm=0.2.1=py312hca03da5_0
- conda=24.11.0=py312hca03da5_0
- conda-build=24.11.2=py312hca03da5_0
- conda-content-trust=0.2.0=py312hca03da5_1
- conda-index=0.5.0=py312hca03da5_0
- conda-libmamba-solver=24.9.0=pyhd3eb1b0_0
- conda-pack=0.6.0=pyhd3eb1b0_0
- conda-package-handling=2.4.0=py312hca03da5_0
- conda-package-streaming=0.11.0=py312hca03da5_0
- conda-repo-cli=1.0.114=py312hca03da5_0
- conda-token=0.4.0=pyhd3eb1b0_0
- conda-verify=3.4.2=py_1
- constantly=23.10.4=py312hca03da5_0
- contourpy=1.3.1=py312h48ca7d4_0
- cookiecutter=2.6.0=py312hca03da5_0
- cryptography=43.0.3=py312h8026fc7_1
- cssselect=1.2.0=py312hca03da5_0
- curl=8.9.1=h02f6b3c_0
- cycler=0.11.0=pyhd3eb1b0_0
- cyrus-sasl=2.1.28=h9131b1a_1
- cytoolz=0.12.2=py312h80987f9_0
- dask=2024.8.2=py312hca03da5_0
- dask-core=2024.8.2=py312hca03da5_0
- dask-expr=1.1.13=py312hca03da5_0
- datasets=2.19.1=py312hca03da5_0
- datashader=0.16.3=py312hca03da5_0
- dav1d=1.2.1=h80987f9_0
- debugpy=1.6.7=py312h313beb8_0
- decorator=5.1.1=pyhd3eb1b0_0
- defusedxml=0.7.1=pyhd3eb1b0_0
- deprecated=1.2.13=py312hca03da5_0
- diff-match-patch=20200713=pyhd3eb1b0_0
- dill=0.3.8=py312hca03da5_0
- distributed=2024.8.2=py312hca03da5_0
- distro=1.9.0=py312hca03da5_0
- dmglib=0.9.5=py312hca03da5_0
- docstring-to-markdown=0.11=py312hca03da5_0
- docutils=0.18.1=py312hca03da5_3
- et_xmlfile=1.1.0=py312hca03da5_1
- executing=0.8.3=pyhd3eb1b0_0
- expat=2.6.3=h313beb8_0
- filelock=3.13.1=py312hca03da5_0
- flake8=7.1.1=py312hca03da5_0
- flask=3.0.3=py312hca03da5_0
- fmt=9.1.0=h48ca7d4_1
- fonttools=4.51.0=py312h80987f9_0
- freetype=2.12.1=h1192e45_0
- frozendict=2.4.2=py312hca03da5_0
- frozenlist=1.5.0=py312h80987f9_0
- fsspec=2024.3.1=py312hca03da5_0
- future=1.0.0=py312hca03da5_0
- gensim=4.3.3=py312hd77ebd4_0
- gettext=0.21.0=hbdbcc25_2
- gflags=2.2.2=h313beb8_1
- giflib=5.2.2=h80987f9_0
- gitdb=4.0.7=pyhd3eb1b0_0
- gitpython=3.1.43=py312hca03da5_0
- glib=2.78.4=h313beb8_0
- glib-tools=2.78.4=h313beb8_0
- glog=0.5.0=h313beb8_1
- gmp=6.2.1=hc377ac9_3
- greenlet=3.0.1=py312h313beb8_0
- gst-plugins-base=1.14.1=h313beb8_1
- gstreamer=1.14.1=h80987f9_1
- h11=0.14.0=py312hca03da5_0
- h5py=3.12.1=py312h8456320_0
- hdf5=1.12.1=h05c076b_3
- heapdict=1.0.1=pyhd3eb1b0_0
- holoviews=1.20.0=py312hca03da5_0
- httpcore=1.0.2=py312hca03da5_0
- httpx=0.27.0=py312hca03da5_0
- huggingface_hub=0.24.6=py312hca03da5_0
- hvplot=0.11.1=py312hca03da5_0
- hyperlink=21.0.0=pyhd3eb1b0_0
- icu=73.1=h313beb8_0
- idna=3.7=py312hca03da5_0
- imagecodecs=2023.1.23=py312h75b721f_1
- imageio=2.33.1=py312hca03da5_0
- imagesize=1.4.1=py312hca03da5_0
- imbalanced-learn=0.12.3=py312hca03da5_1
- importlib-metadata=8.5.0=py312hca03da5_0
- importlib_metadata=8.5.0=hd3eb1b0_0
- incremental=22.10.0=pyhd3eb1b0_0
- inflection=0.5.1=py312hca03da5_1
- iniconfig=1.1.1=pyhd3eb1b0_0
- intake=2.0.7=py312hca03da5_0
- intervaltree=3.1.0=pyhd3eb1b0_0
- ipykernel=6.29.5=py312hca03da5_0
- ipython=8.27.0=py312hca03da5_0
- ipython_genutils=0.2.0=pyhd3eb1b0_1
- ipywidgets=7.8.1=py312hca03da5_0
- isort=5.13.2=py312hca03da5_0
- itemadapter=0.3.0=pyhd3eb1b0_0
- itemloaders=1.1.0=py312hca03da5_0
- itsdangerous=2.2.0=py312hca03da5_0
- jaraco.classes=3.2.1=pyhd3eb1b0_0
- jedi=0.19.1=py312hca03da5_0
- jellyfish=1.0.1=py312h1bd1ac0_1
- jinja2=3.1.4=py312hca03da5_1
- jmespath=1.0.1=py312hca03da5_0
- joblib=1.4.2=py312hca03da5_0
- jpeg=9e=h80987f9_3
- jq=1.7.1=h80987f9_0
- json5=0.9.25=py312hca03da5_0
- jsonpatch=1.33=py312hca03da5_1
- jsonpointer=2.1=pyhd3eb1b0_0
- jsonschema=4.23.0=py312hca03da5_0
- jsonschema-specifications=2023.7.1=py312hca03da5_0
- jupyter=1.0.0=py312hca03da5_9
- jupyter-lsp=2.2.0=py312hca03da5_0
- jupyter_client=8.6.0=py312hca03da5_0
- jupyter_console=6.6.3=py312hca03da5_1
- jupyter_core=5.7.2=py312hca03da5_0
- jupyter_events=0.10.0=py312hca03da5_0
- jupyter_server=2.14.1=py312hca03da5_0
- jupyter_server_terminals=0.4.4=py312hca03da5_1
- jupyterlab=4.2.5=py312hca03da5_0
- jupyterlab-variableinspector=3.1.0=py312hca03da5_0
- jupyterlab_pygments=0.1.2=py_0
- jupyterlab_server=2.27.3=py312hca03da5_0
- jupyterlab_widgets=1.0.0=pyhd3eb1b0_1
- jxrlib=1.1=h1a28f6b_2
- keyring=24.3.1=py312hca03da5_0
- kiwisolver=1.4.4=py312h313beb8_0
- krb5=1.20.1=hf3e1bf2_1
- lazy_loader=0.4=py312hca03da5_0
- lcms2=2.12=hba8e193_0
- ld64=530=hb29bf3f_25
- ld64_osx-arm64=530=h001ce53_25
- ldid=2.1.5=h20b2a84_3
- lerc=3.0=hc377ac9_0
- libabseil=20240116.2=cxx17_h313beb8_0
- libaec=1.0.4=hc377ac9_1
- libarchive=3.7.4=h8f13d7a_0
- libavif=0.11.1=h80987f9_0
- libboost=1.82.0=h0bc93f9_2
- libbrotlicommon=1.0.9=h80987f9_8
- libbrotlidec=1.0.9=h80987f9_8
- libbrotlienc=1.0.9=h80987f9_8
- libclang=14.0.6=default_h1b80db6_1
- libclang13=14.0.6=default_h24352ff_1
- libcurl=8.9.1=h3e2b118_0
- libcxx=14.0.6=h848a8c0_0
- libdeflate=1.17=h80987f9_1
- libedit=3.1.20230828=h80987f9_0
- libev=4.33=h1a28f6b_1
- libevent=2.1.12=h02f6b3c_1
- libffi=3.4.4=hca03da5_1
- libgfortran=5.0.0=11_3_0_hca03da5_28
- libgfortran5=11.3.0=h009349e_28
- libglib=2.78.4=h0a96307_0
- libgrpc=1.62.2=h62f6fdd_0
- libiconv=1.16=h80987f9_3
- liblief=0.12.3=h313beb8_0
- libllvm14=14.0.6=h19fdd8a_4
- libmamba=1.5.11=haeffa04_0
- libmambapy=1.5.11=py312h15e39b3_0
- libnghttp2=1.57.0=h62f6fdd_0
- libopenblas=0.3.21=h269037a_0
- libpng=1.6.39=h80987f9_0
- libpq=17.0=h02f6b3c_0
- libprotobuf=4.25.3=h514c7bf_0
- libsodium=1.0.18=h1a28f6b_0
- libsolv=0.7.24=h514c7bf_1
- libspatialindex=1.9.3=hc377ac9_0
- libssh2=1.11.1=h3e2b118_0
- libthrift=0.15.0=h73c2103_2
- libtiff=4.5.1=h313beb8_0
- libwebp-base=1.3.2=h80987f9_1
- libxml2=2.13.5=h0b34f26_0
- libxslt=1.1.41=hf4d3faa_0
- libzopfli=1.0.3=hc377ac9_0
- linkify-it-py=2.0.0=py312hca03da5_0
- llvm-openmp=14.0.6=hc6e5704_0
- llvmlite=0.43.0=py312h313beb8_0
- locket=1.0.0=py312hca03da5_0
- lxml=5.3.0=py312h1d4350b_0
- lz4=4.3.2=py312h80987f9_0
- lz4-c=1.9.4=h313beb8_1
- lzo=2.10=h1a28f6b_2
- markdown=3.4.1=py312hca03da5_0
- markdown-it-py=2.2.0=py312hca03da5_1
- markupsafe=2.1.3=py312h80987f9_0
- matplotlib=3.9.2=py312hca03da5_1
- matplotlib-base=3.9.2=py312h7ef442a_1
- matplotlib-inline=0.1.6=py312hca03da5_0
- mccabe=0.7.0=pyhd3eb1b0_0
- mdit-py-plugins=0.3.0=py312hca03da5_0
- mdurl=0.1.0=py312hca03da5_0
- menuinst=2.2.0=py312hca03da5_0
- mistune=2.0.4=py312hca03da5_0
- more-itertools=10.3.0=py312hca03da5_0
- mpc=1.1.0=h8c48613_1
- mpfr=4.0.2=h695f6f0_1
- mpmath=1.3.0=py312hca03da5_0
- msgpack-python=1.0.3=py312h48ca7d4_0
- multidict=6.1.0=py312h80987f9_0
- multipledispatch=0.6.0=py312hca03da5_0
- multiprocess=0.70.15=py312hca03da5_0
- mypy=1.11.2=py312h80987f9_0
- mypy_extensions=1.0.0=py312hca03da5_0
- mysql=8.4.0=h3a6587f_1
- navigator-updater=0.5.1=py312hca03da5_0
- nbclassic=1.1.0=py312hca03da5_0
- nbclient=0.8.0=py312hca03da5_0
- nbconvert=7.16.4=py312hca03da5_0
- nbformat=5.10.4=py312hca03da5_0
- ncurses=6.4=h313beb8_0
- nest-asyncio=1.6.0=py312hca03da5_0
- networkx=3.3=py312hca03da5_0
- nltk=3.9.1=py312hca03da5_0
- notebook=7.2.2=py312hca03da5_1
- notebook-shim=0.2.3=py312hca03da5_0
- numba=0.60.0=py312hd77ebd4_0
- numexpr=2.10.1=py312h5d9532f_0
- numpy=1.26.4=py312h7f4fdc5_0
- numpy-base=1.26.4=py312he047099_0
- numpydoc=1.7.0=py312hca03da5_0
- oniguruma=6.9.7.1=h1a28f6b_0
- openjpeg=2.5.2=h54b8e55_0
- openldap=2.6.4=he7ef289_0
- openpyxl=3.1.5=py312h80987f9_0
- openssl=3.0.15=h80987f9_0
- orc=2.0.1=h937ddfc_0
- overrides=7.4.0=py312hca03da5_0
- packaging=24.1=py312hca03da5_0
- pandas=2.2.3=py312hcf29cfe_0
- pandocfilters=1.5.0=pyhd3eb1b0_0
- panel=1.5.3=py312hca03da5_0
- param=2.1.1=py312hca03da5_0
- parsel=1.8.1=py312hca03da5_0
- parso=0.8.3=pyhd3eb1b0_0
- partd=1.4.1=py312hca03da5_0
- patch=2.7.6=h1a28f6b_1001
- pathspec=0.10.3=py312hca03da5_0
- patsy=0.5.6=py312hca03da5_0
- pcre2=10.42=hb066dcc_1
- pexpect=4.8.0=pyhd3eb1b0_3
- pickleshare=0.7.5=pyhd3eb1b0_1003
- pillow=11.0.0=py312hfaf4e14_0
- pip=24.2=py312hca03da5_0
- pkce=1.0.3=py312hca03da5_0
- pkginfo=1.11.2=py312hca03da5_0
- platformdirs=3.10.0=py312hca03da5_0
- plotly=5.24.1=py312h989b03a_0
- pluggy=1.5.0=py312hca03da5_0
- ply=3.11=py312hca03da5_1
- prometheus_client=0.21.0=py312hca03da5_0
- prompt-toolkit=3.0.43=py312hca03da5_0
- prompt_toolkit=3.0.43=hd3eb1b0_0
- propcache=0.2.0=py312h80987f9_0
- protego=0.1.16=py_0
- protobuf=4.25.3=py312h8472c4a_0
- psutil=5.9.0=py312h80987f9_0
- ptyprocess=0.7.0=pyhd3eb1b0_2
- pure_eval=0.2.2=pyhd3eb1b0_0
- py-cpuinfo=9.0.0=py312hca03da5_0
- py-lief=0.12.3=py312h313beb8_0
- pyarrow=16.1.0=py312hd77ebd4_0
- pyasn1=0.4.8=pyhd3eb1b0_0
- pyasn1-modules=0.2.8=py_0
- pybind11-abi=5=hd3eb1b0_0
- pycodestyle=2.12.1=py312hca03da5_0
- pycosat=0.6.6=py312h80987f9_1
- pycparser=2.21=pyhd3eb1b0_0
- pyct=0.5.0=py312hca03da5_0
- pycurl=7.45.3=py312h02f6b3c_0
- pydantic=2.8.2=py312hca03da5_0
- pydantic-core=2.20.1=py312hf0e4da2_0
- pydantic-settings=2.6.1=py312hca03da5_0
- pydeck=0.8.0=py312hca03da5_2
- pydispatcher=2.0.5=py312hca03da5_3
- pydocstyle=6.3.0=py312hca03da5_0
- pyerfa=2.0.1.4=py312ha86b861_0
- pyflakes=3.2.0=py312hca03da5_0
- pygithub=2.4.0=py312hca03da5_0
- pygments=2.15.1=py312hca03da5_1
- pyjwt=2.9.0=py312hca03da5_0
- pylint=3.2.7=py312hca03da5_0
- pylint-venv=3.0.3=py312hca03da5_0
- pyls-spyder=0.4.0=pyhd3eb1b0_0
- pynacl=1.5.0=py312h80987f9_0
- pyobjc-core=10.1=py312h80987f9_0
- pyobjc-framework-cocoa=10.1=py312hb094c41_0
- pyobjc-framework-coreservices=10.1=py312hdd8dd1f_0
- pyobjc-framework-fsevents=10.1=py312hca03da5_0
- pyodbc=5.1.0=py312h313beb8_0
- pyopenssl=24.2.1=py312hca03da5_0
- pyparsing=3.2.0=py312hca03da5_0
- pyqt=5.15.10=py312h313beb8_0
- pyqt5-sip=12.13.0=py312h80987f9_0
- pyqtwebengine=5.15.10=py312h313beb8_0
- pysocks=1.7.1=py312hca03da5_0
- pytables=3.10.1=py312h905a39b_0
- pytest=7.4.4=py312hca03da5_0
- python=3.12.7=h99e199e_0
- python-dateutil=2.9.0post0=py312hca03da5_2
- python-dotenv=0.21.0=py312hca03da5_0
- python-fastjsonschema=2.20.0=py312hca03da5_0
- python-json-logger=2.0.7=py312hca03da5_0
- python-libarchive-c=5.1=pyhd3eb1b0_0
- python-lmdb=1.4.1=py312h313beb8_0
- python-lsp-black=2.0.0=py312hca03da5_0
- python-lsp-jsonrpc=1.1.2=pyhd3eb1b0_0
- python-lsp-server=1.12.0=py312h989b03a_0
- python-slugify=5.0.2=pyhd3eb1b0_0
- python-tzdata=2023.3=pyhd3eb1b0_0
- python-xxhash=2.0.2=py312h80987f9_1
- python.app=3=py312h80987f9_1
- pytoolconfig=1.2.6=py312hca03da5_0
- pytz=2024.1=py312hca03da5_0
- pyuca=1.2=py312hca03da5_1
- pyviz_comms=3.0.2=py312hca03da5_0
- pywavelets=1.7.0=py312h80987f9_0
- pyyaml=6.0.2=py312h80987f9_0
- pyzmq=25.1.2=py312h313beb8_0
- qdarkstyle=3.2.3=pyhd3eb1b0_0
- qstylizer=0.2.2=py312hca03da5_0
- qt-main=5.15.2=h0917680_11
- qt-webengine=5.15.9=h2903aaf_7
- qtawesome=1.3.1=py312hca03da5_0
- qtconsole=5.6.0=py312hca03da5_0
- qtpy=2.4.1=py312hca03da5_0
- queuelib=1.6.2=py312hca03da5_0
- re2=2022.04.01=hc377ac9_0
- readchar=4.0.5=py312hca03da5_0
- readline=8.2=h1a28f6b_0
- referencing=0.30.2=py312hca03da5_0
- regex=2024.9.11=py312h80987f9_0
- reproc=14.2.4=h313beb8_2
- reproc-cpp=14.2.4=h313beb8_2
- requests=2.32.3=py312hca03da5_1
- requests-file=1.5.1=pyhd3eb1b0_0
- requests-toolbelt=1.0.0=py312hca03da5_0
- responses=0.13.3=pyhd3eb1b0_0
- rfc3339-validator=0.1.4=py312hca03da5_0
- rfc3986-validator=0.1.1=py312hca03da5_0
- rich=13.9.4=py312hca03da5_0
- rope=1.12.0=py312hca03da5_0
- rpds-py=0.10.6=py312h2aea54e_1
- rtree=1.0.1=py312hca03da5_0
- ruamel.yaml=0.18.6=py312h80987f9_0
- ruamel.yaml.clib=0.2.8=py312h80987f9_0
- ruamel_yaml=0.17.21=py312h80987f9_0
- s3fs=2024.3.1=py312hca03da5_0
- safetensors=0.4.5=py312h7805bc0_1
- scikit-image=0.24.0=py312hd77ebd4_0
- scikit-learn=1.5.1=py312hd77ebd4_0
- scipy=1.13.1=py312ha409365_0
- scrapy=2.12.0=py312hca03da5_0
- seaborn=0.13.2=py312hca03da5_0
- semver=3.0.2=py312hca03da5_0
- send2trash=1.8.2=py312hca03da5_0
- service_identity=18.1.0=pyhd3eb1b0_1
- setuptools=75.1.0=py312hca03da5_0
- shellingham=1.5.0=py312hca03da5_0
- sip=6.7.12=py312h313beb8_0
- six=1.16.0=pyhd3eb1b0_1
- smart_open=5.2.1=py312hca03da5_0
- smmap=4.0.0=pyhd3eb1b0_0
- snappy=1.2.1=h313beb8_0
- sniffio=1.3.0=py312hca03da5_0
- snowballstemmer=2.2.0=pyhd3eb1b0_0
- sortedcontainers=2.4.0=pyhd3eb1b0_0
- soupsieve=2.5=py312hca03da5_0
- sphinx=7.3.7=py312hca03da5_0
- sphinxcontrib-applehelp=1.0.2=pyhd3eb1b0_0
- sphinxcontrib-devhelp=1.0.2=pyhd3eb1b0_0
- sphinxcontrib-htmlhelp=2.0.0=pyhd3eb1b0_0
- sphinxcontrib-jsmath=1.0.1=pyhd3eb1b0_0
- sphinxcontrib-qthelp=1.0.3=pyhd3eb1b0_0
- sphinxcontrib-serializinghtml=1.1.10=py312hca03da5_0
- spyder=6.0.1=py312hca03da5_0
- spyder-kernels=3.0.0=py312h989b03a_0
- sqlalchemy=2.0.34=py312hbe2cdee_0
- sqlite=3.45.3=h80987f9_0
- stack_data=0.2.0=pyhd3eb1b0_0
- statsmodels=0.14.2=py312ha86b861_0
- streamlit=1.40.1=py312hca03da5_0
- superqt=0.6.7=py312h989b03a_0
- sympy=1.13.2=py312hca03da5_0
- tabulate=0.9.0=py312hca03da5_0
- tapi=1100.0.11=h8754e6a_1
- tbb=2021.8.0=h48ca7d4_0
- tblib=1.7.0=pyhd3eb1b0_0
- tenacity=9.0.0=py312hca03da5_0
- terminado=0.17.1=py312hca03da5_0
- text-unidecode=1.3=pyhd3eb1b0_0
- textdistance=4.6.3=py312h989b03a_0
- threadpoolctl=3.5.0=py312h989b03a_0
- three-merge=0.1.1=pyhd3eb1b0_0
- tifffile=2023.4.12=py312hca03da5_0
- tinycss2=1.2.1=py312hca03da5_0
- tk=8.6.14=h6ba3021_0
- tldextract=5.1.2=py312hca03da5_0
- tokenizers=0.20.1=py312he2d9c3e_1
- toml=0.10.2=pyhd3eb1b0_0
- tomli=2.0.1=py312hca03da5_1
- tomlkit=0.13.2=py312hca03da5_0
- toolz=0.12.0=py312hca03da5_0
- tornado=6.4.1=py312h80987f9_0
- tqdm=4.66.5=py312h989b03a_0
- traitlets=5.14.3=py312hca03da5_0
- transformers=4.45.2=py312hca03da5_0
- truststore=0.8.0=py312hca03da5_0
- twisted=23.10.0=py312hca03da5_0
- typer=0.9.0=py312hca03da5_0
- typing-extensions=4.11.0=py312hca03da5_0
- typing_extensions=4.11.0=py312hca03da5_0
- tzdata=2024b=h04d1e81_0
- uc-micro-py=1.0.1=py312hca03da5_0
- ujson=5.10.0=py312h313beb8_0
- unicodedata2=15.1.0=py312h80987f9_0
- unidecode=1.3.8=py312hca03da5_0
- unixodbc=2.3.11=h1a28f6b_0
- urllib3=2.2.3=py312hca03da5_0
- utf8proc=2.6.1=h80987f9_1
- w3lib=2.1.2=py312hca03da5_0
- watchdog=4.0.1=py312h80987f9_0
- wcwidth=0.2.5=pyhd3eb1b0_0
- webencodings=0.5.1=py312hca03da5_2
- websocket-client=1.8.0=py312hca03da5_0
- werkzeug=3.0.6=py312hca03da5_0
- whatthepatch=1.0.2=py312hca03da5_0
- wheel=0.44.0=py312hca03da5_0
- widgetsnbextension=3.6.6=py312hca03da5_0
- wrapt=1.14.1=py312h80987f9_0
- wurlitzer=3.0.2=py312hca03da5_0
- xarray=2023.6.0=py312hca03da5_0
- xlwings=0.32.1=py312hca03da5_0
- xxhash=0.8.0=h1a28f6b_3
- xyzservices=2022.9.0=py312hca03da5_1
- xz=5.4.6=h80987f9_1
- yaml=0.2.5=h1a28f6b_0
- yaml-cpp=0.8.0=h313beb8_1
- yapf=0.40.2=py312hca03da5_0
- yarl=1.18.0=py312h80987f9_0
- zeromq=4.3.5=h313beb8_0
- zfp=1.0.0=h313beb8_0
- zict=3.0.0=py312hca03da5_0
- zipp=3.21.0=py312hca03da5_0
- zlib=1.2.13=h18a0788_1
- zlib-ng=2.0.7=h80987f9_0
- zope=1.0=py312hca03da5_1
- zope.interface=7.1.1=py312h80987f9_0
- zstandard=0.23.0=py312h1a4646a_1
- zstd=1.5.6=hfb09047_0
- pip:
- svgpathtools==1.7.0
- svgwrite==1.4.3
prefix: /opt/homebrew/anaconda3

View File

@@ -1,125 +0,0 @@
name: evilnkode
channels:
- defaults
dependencies:
- anyio=4.6.2=py312hca03da5_0
- appnope=0.1.3=py312hca03da5_1001
- argon2-cffi=21.3.0=pyhd3eb1b0_0
- argon2-cffi-bindings=21.2.0=py312h80987f9_0
- asttokens=2.0.5=pyhd3eb1b0_0
- async-lru=2.0.4=py312hca03da5_0
- attrs=24.2.0=py312hca03da5_0
- babel=2.11.0=py312hca03da5_0
- beautifulsoup4=4.12.3=py312hca03da5_0
- bleach=6.2.0=py312hca03da5_0
- brotli-python=1.0.9=py312h313beb8_8
- bzip2=1.0.8=h80987f9_6
- ca-certificates=2024.12.31=hca03da5_0
- certifi=2024.12.14=py312hca03da5_0
- cffi=1.17.1=py312h3eb5a62_0
- charset-normalizer=3.3.2=pyhd3eb1b0_0
- comm=0.2.1=py312hca03da5_0
- debugpy=1.6.7=py312h313beb8_0
- decorator=5.1.1=pyhd3eb1b0_0
- defusedxml=0.7.1=pyhd3eb1b0_0
- executing=0.8.3=pyhd3eb1b0_0
- expat=2.6.3=h313beb8_0
- h11=0.14.0=py312hca03da5_0
- httpcore=1.0.2=py312hca03da5_0
- httpx=0.27.0=py312hca03da5_0
- idna=3.7=py312hca03da5_0
- ipykernel=6.29.5=py312hca03da5_0
- ipython=8.27.0=py312hca03da5_0
- jedi=0.19.1=py312hca03da5_0
- jinja2=3.1.4=py312hca03da5_1
- json5=0.9.25=py312hca03da5_0
- jsonschema=4.23.0=py312hca03da5_0
- jsonschema-specifications=2023.7.1=py312hca03da5_0
- jupyter-lsp=2.2.0=py312hca03da5_0
- jupyter_client=8.6.0=py312hca03da5_0
- jupyter_core=5.7.2=py312hca03da5_0
- jupyter_events=0.10.0=py312hca03da5_0
- jupyter_server=2.14.1=py312hca03da5_0
- jupyter_server_terminals=0.4.4=py312hca03da5_1
- jupyterlab=4.2.5=py312hca03da5_0
- jupyterlab_pygments=0.1.2=py_0
- jupyterlab_server=2.27.3=py312hca03da5_0
- libcxx=14.0.6=h848a8c0_0
- libffi=3.4.4=hca03da5_1
- libsodium=1.0.18=h1a28f6b_0
- markupsafe=2.1.3=py312h80987f9_0
- matplotlib-inline=0.1.6=py312hca03da5_0
- mistune=2.0.4=py312hca03da5_0
- nbclient=0.8.0=py312hca03da5_0
- nbconvert=7.16.4=py312hca03da5_0
- nbformat=5.10.4=py312hca03da5_0
- ncurses=6.4=h313beb8_0
- nest-asyncio=1.6.0=py312hca03da5_0
- notebook=7.2.2=py312hca03da5_1
- notebook-shim=0.2.3=py312hca03da5_0
- openssl=3.0.15=h80987f9_0
- overrides=7.4.0=py312hca03da5_0
- packaging=24.1=py312hca03da5_0
- pandocfilters=1.5.0=pyhd3eb1b0_0
- parso=0.8.3=pyhd3eb1b0_0
- pexpect=4.8.0=pyhd3eb1b0_3
- pip=24.2=py312hca03da5_0
- platformdirs=3.10.0=py312hca03da5_0
- prometheus_client=0.21.0=py312hca03da5_0
- prompt-toolkit=3.0.43=py312hca03da5_0
- prompt_toolkit=3.0.43=hd3eb1b0_0
- psutil=5.9.0=py312h80987f9_0
- ptyprocess=0.7.0=pyhd3eb1b0_2
- pure_eval=0.2.2=pyhd3eb1b0_0
- pycparser=2.21=pyhd3eb1b0_0
- pygments=2.15.1=py312hca03da5_1
- pysocks=1.7.1=py312hca03da5_0
- python=3.12.7=h99e199e_0
- python-dateutil=2.9.0post0=py312hca03da5_2
- python-fastjsonschema=2.20.0=py312hca03da5_0
- python-json-logger=2.0.7=py312hca03da5_0
- pytz=2024.1=py312hca03da5_0
- pyyaml=6.0.2=py312h80987f9_0
- pyzmq=25.1.2=py312h313beb8_0
- readline=8.2=h1a28f6b_0
- referencing=0.30.2=py312hca03da5_0
- requests=2.32.3=py312hca03da5_1
- rfc3339-validator=0.1.4=py312hca03da5_0
- rfc3986-validator=0.1.1=py312hca03da5_0
- rpds-py=0.10.6=py312h2aea54e_1
- send2trash=1.8.2=py312hca03da5_0
- setuptools=75.1.0=py312hca03da5_0
- six=1.16.0=pyhd3eb1b0_1
- sniffio=1.3.0=py312hca03da5_0
- soupsieve=2.5=py312hca03da5_0
- sqlite=3.45.3=h80987f9_0
- stack_data=0.2.0=pyhd3eb1b0_0
- terminado=0.17.1=py312hca03da5_0
- tinycss2=1.2.1=py312hca03da5_0
- tk=8.6.14=h6ba3021_0
- tornado=6.4.1=py312h80987f9_0
- traitlets=5.14.3=py312hca03da5_0
- typing-extensions=4.11.0=py312hca03da5_0
- typing_extensions=4.11.0=py312hca03da5_0
- tzdata=2024b=h04d1e81_0
- urllib3=2.2.3=py312hca03da5_0
- wcwidth=0.2.5=pyhd3eb1b0_0
- webencodings=0.5.1=py312hca03da5_2
- websocket-client=1.8.0=py312hca03da5_0
- wheel=0.44.0=py312hca03da5_0
- xz=5.4.6=h80987f9_1
- yaml=0.2.5=h1a28f6b_0
- zeromq=4.3.5=h313beb8_0
- zlib=1.2.13=h18a0788_1
- pip:
- contourpy==1.3.1
- cycler==0.12.1
- fonttools==4.55.3
- iniconfig==2.0.0
- kiwisolver==1.4.7
- matplotlib==3.9.3
- numpy==2.1.3
- pillow==11.0.0
- pluggy==1.5.0
- pyparsing==3.2.0
- pytest==8.3.4

View File

@@ -1,9 +1,10 @@
from tqdm import tqdm
from src.evilnkode import EvilNKode from src.evilnkode import EvilNKode
from dataclasses import dataclass from dataclasses import dataclass
from src.utils import observations, passcode_generator from src.utils import observations, passcode_generator
from src.keypad.keypad import BaseKeypad from src.keypad.keypad import BaseKeypad
from pathlib import Path from pathlib import Path
import pickle
@dataclass @dataclass
@@ -21,31 +22,20 @@ def benchmark(
complexity: int, complexity: int,
disparity: int, disparity: int,
keypad: BaseKeypad, keypad: BaseKeypad,
file_path: str = '../output', file_path: Path = '../output',
overwrite: bool = False overwrite: bool = False
) -> Benchmark: ) -> Benchmark:
shuffle_type = str(type(keypad)) shuffle_type = str(type(keypad)).lower().split('.')[-1].replace("'>", "")
file_name_break = f"{shuffle_type.lower()}-{number_of_keys}-{properties_per_key}-{passcode_len}-{max_tries_before_lockout}-{complexity}-{disparity}-{run_count}.txt" file_name = f"{shuffle_type}-{number_of_keys}-{properties_per_key}-{passcode_len}-{max_tries_before_lockout}-{complexity}-{disparity}-{run_count}.pkl"
full_path_iter_break = Path(file_path) / "iterations_to_break" / file_name_break full_path = Path(file_path) / "benchmark" / file_name
file_name_replay = f"{shuffle_type.lower()}-{number_of_keys}-{properties_per_key}-{passcode_len}-{max_tries_before_lockout}-{complexity}-{disparity}-{run_count}.txt" if not overwrite and full_path.exists():
full_path_iter_replay = Path(file_path) / "iterations_to_replay" / file_name_replay print(f"File exists: {full_path}")
with open(full_path, "rb") as fp:
return pickle.load(fp)
iterations_to_break = [] iterations_to_break = []
iterations_to_replay = [] iterations_to_replay = []
if not overwrite and full_path_iter_break.exists() and full_path_iter_replay.exists(): for _ in tqdm(range(run_count)):
print(f"file exists {file_path}")
with open(full_path_iter_break, "r") as fp:
iterations_to_break = fp.readline()
iterations_to_break = iterations_to_break.split(',')
iterations_to_break = [int(i) for i in iterations_to_break]
with open(full_path_iter_replay, "r") as fp:
iterations_to_replay = fp.readline()
iterations_to_replay = iterations_to_replay.split(',')
iterations_to_replay = [int(i) for i in iterations_to_replay]
return Benchmark(
iterations_to_break=iterations_to_break,
iterations_to_replay=iterations_to_replay
)
for _ in range(run_count):
passcode = passcode_generator(number_of_keys, properties_per_key, passcode_len, complexity, disparity) passcode = passcode_generator(number_of_keys, properties_per_key, passcode_len, complexity, disparity)
evilnkode = EvilNKode( evilnkode = EvilNKode(
observations=observations( observations=observations(
@@ -61,12 +51,14 @@ def benchmark(
iterations_to_break.append(evilout.iterations_to_break) iterations_to_break.append(evilout.iterations_to_break)
iterations_to_replay.append(evilout.iterations_to_replay) iterations_to_replay.append(evilout.iterations_to_replay)
if not file_path == "": benchmark_result = Benchmark(
full_path_iter_break.parent.mkdir(parents=True, exist_ok=True)
with open(full_path_iter_break, "w") as fp:
fp.write(",".join([str(i) for i in iterations_to_break])),
return Benchmark(
iterations_to_break=iterations_to_break, iterations_to_break=iterations_to_break,
iterations_to_replay=iterations_to_replay iterations_to_replay=iterations_to_replay
) )
if file_path:
full_path.parent.mkdir(parents=True, exist_ok=True)
with open(full_path, "wb") as fp:
pickle.dump(benchmark_result, fp)
return benchmark_result