From eddf482d088d924a2bb6cc9bae299e90842abf18 Mon Sep 17 00:00:00 2001 From: Benedikt Ziemons Date: Sun, 28 Jan 2024 14:12:46 +0100 Subject: [PATCH] Initial project files --- .gitignore | 1 + Pipfile | 16 ++ Pipfile.lock | 145 ++++++++++++++++++ factorygame/__init__.py | 0 .../calculator/SatisfactoryCalculator.py | 129 ++++++++++++++++ factorygame/calculator/__init__.py | 0 factorygame/calculator/__main__.py | 3 + 7 files changed, 294 insertions(+) create mode 100644 .gitignore create mode 100644 Pipfile create mode 100644 Pipfile.lock create mode 100644 factorygame/__init__.py create mode 100644 factorygame/calculator/SatisfactoryCalculator.py create mode 100644 factorygame/calculator/__init__.py create mode 100644 factorygame/calculator/__main__.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..485dee6 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea diff --git a/Pipfile b/Pipfile new file mode 100644 index 0000000..4381c84 --- /dev/null +++ b/Pipfile @@ -0,0 +1,16 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] +selenium = "*" +click = "*" + +[dev-packages] + +[requires] +python_version = "3.11" + +[scripts] +calc = {call = "factorygame.calculator.SatisfactoryCalculator:main()"} diff --git a/Pipfile.lock b/Pipfile.lock new file mode 100644 index 0000000..455fbf9 --- /dev/null +++ b/Pipfile.lock @@ -0,0 +1,145 @@ +{ + "_meta": { + "hash": { + "sha256": "763880094219b49a3e429352d48f700c9965f22616711a5c42aa97d137dedadb" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.11" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "attrs": { + "hashes": [ + "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30", + "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1" + ], + "markers": "python_version >= '3.7'", + "version": "==23.2.0" + }, + "certifi": { + "hashes": [ + "sha256:9b469f3a900bf28dc19b8cfbf8019bf47f7fdd1a65a1d4ffb98fc14166beb4d1", + "sha256:e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474" + ], + "markers": "python_version >= '3.6'", + "version": "==2023.11.17" + }, + "click": { + "hashes": [ + "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28", + "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de" + ], + "index": "pypi", + "markers": "python_version >= '3.7'", + "version": "==8.1.7" + }, + "h11": { + "hashes": [ + "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d", + "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761" + ], + "markers": "python_version >= '3.7'", + "version": "==0.14.0" + }, + "idna": { + "hashes": [ + "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca", + "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f" + ], + "markers": "python_version >= '3.5'", + "version": "==3.6" + }, + "outcome": { + "hashes": [ + "sha256:9dcf02e65f2971b80047b377468e72a268e15c0af3cf1238e6ff14f7f91143b8", + "sha256:e771c5ce06d1415e356078d3bdd68523f284b4ce5419828922b6871e65eda82b" + ], + "markers": "python_version >= '3.7'", + "version": "==1.3.0.post0" + }, + "pysocks": { + "hashes": [ + "sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299", + "sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5", + "sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0" + ], + "version": "==1.7.1" + }, + "selenium": { + "hashes": [ + "sha256:5aee79026c07985dc1b0c909f34084aa996dfe5b307602de9016d7a621a473f2", + "sha256:d43d6972e516855fb242ef9ce4ce759057b115070e702e7b1c1032fe7b38d87b" + ], + "index": "pypi", + "markers": "python_version >= '3.8'", + "version": "==4.17.2" + }, + "sniffio": { + "hashes": [ + "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101", + "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384" + ], + "markers": "python_version >= '3.7'", + "version": "==1.3.0" + }, + "sortedcontainers": { + "hashes": [ + "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88", + "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0" + ], + "version": "==2.4.0" + }, + "trio": { + "hashes": [ + "sha256:c3bd3a4e3e3025cd9a2241eae75637c43fe0b9e88b4c97b9161a55b9e54cd72c", + "sha256:ffa09a74a6bf81b84f8613909fb0beaee84757450183a7a2e0b47b455c0cac5d" + ], + "markers": "python_version >= '3.8'", + "version": "==0.24.0" + }, + "trio-websocket": { + "hashes": [ + "sha256:18c11793647703c158b1f6e62de638acada927344d534e3c7628eedcb746839f", + "sha256:520d046b0d030cf970b8b2b2e00c4c2245b3807853ecd44214acd33d74581638" + ], + "markers": "python_version >= '3.7'", + "version": "==0.11.1" + }, + "typing-extensions": { + "hashes": [ + "sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783", + "sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd" + ], + "markers": "python_version >= '3.8'", + "version": "==4.9.0" + }, + "urllib3": { + "extras": [ + "socks" + ], + "hashes": [ + "sha256:55901e917a5896a349ff771be919f8bd99aff50b79fe58fec595eb37bbc56bb3", + "sha256:df7aa8afb0148fa78488e7899b2c59b5f4ffcfa82e6c54ccb9dd37c1d7b52d54" + ], + "markers": "python_version >= '3.8'", + "version": "==2.1.0" + }, + "wsproto": { + "hashes": [ + "sha256:ad565f26ecb92588a3e43bc3d96164de84cd9902482b130d0ddbaa9664a85065", + "sha256:b9acddd652b585d75b20477888c56642fdade28bdfd3579aa24a4d2c037dd736" + ], + "markers": "python_full_version >= '3.7.0'", + "version": "==1.2.0" + } + }, + "develop": {} +} diff --git a/factorygame/__init__.py b/factorygame/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/factorygame/calculator/SatisfactoryCalculator.py b/factorygame/calculator/SatisfactoryCalculator.py new file mode 100644 index 0000000..1f77c18 --- /dev/null +++ b/factorygame/calculator/SatisfactoryCalculator.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python3 +import time +from collections import namedtuple + +import click +from selenium.webdriver import Firefox +from selenium.webdriver.common.by import By +from selenium.webdriver.firefox.options import Options + +Recipe = namedtuple("Recipe", ["result_count", "ingredients", "time"]) +Ingredient = namedtuple("Ingredient", ["count", "name"]) + + +@click.command() +@click.option("--result", type=str, required=True) +@click.option("--debug", is_flag=True, default=False, required=False) +def main(result: str, debug: bool): + if result: + firefox_options = Options() + if not debug: + firefox_options.add_argument("--headless") + browser = Firefox(options=firefox_options) + try: + browser.get("https://wiki.kyrium.space/") + browser.set_window_size(1600, 1015) + search_bar = browser.find_element( + By.CSS_SELECTOR, "nav input[placeholder='Search for an item...']" + ) + search_bar.click() + search_bar.send_keys(result) + search_button = browser.find_element(By.CSS_SELECTOR, "nav button[type='submit']") + search_button.click() + browser.implicitly_wait(3) + choices = browser.find_elements( + By.CSS_SELECTOR, "body > div > .container:nth-child(1) a.items-center" + ) + if not choices: + print("No wiki entries found for this result") + return + elif len(choices) > 1: + default_choice = 1 + for choice_idx in range(1, len(choices) + 1): + recipe_choice = choices[choice_idx - 1] + name = recipe_choice.find_element(By.TAG_NAME, "img").get_attribute("alt") + if name.casefold() == result.casefold(): + default_choice = choice_idx + print(f"{choice_idx}: {name}") + user_choice = input(f"Chose a recipe to continue… (default: {default_choice}) ") + if not user_choice: + user_choice = default_choice + else: + user_choice = int(user_choice) + choices[user_choice - 1].click() + else: + choices[0].click() + + browser.find_element(By.CSS_SELECTOR, "button#\\3Ar1\\3A-tab-0").click() + + recipes = browser.find_elements(By.CSS_SELECTOR, "#\\3Ar1\\3A-tabpanel-0 > div > div") + for recipe_idx in range(len(recipes)): + recipe = recipes[recipe_idx] + print( + "recipe", + recipe_idx, + "produced in:", + recipe.find_element(By.CSS_SELECTOR, ".flex-col > span > a").text, + ) + + ingredients = recipe.find_elements( + By.CSS_SELECTOR, f".flex-row > div:nth-child(1) > div:has(> a)" + ) + for ingredient_idx in range(len(ingredients)): + ingredient = ingredients[ingredient_idx] + print( + "recipe", + recipe_idx, + "ingredient", + ingredient_idx, + "name:", + ingredient.find_element(By.TAG_NAME, "img").get_attribute("alt"), + ) + print( + "recipe", + recipe_idx, + "ingredient", + ingredient_idx, + "count:", + ingredient.find_element(By.CSS_SELECTOR, ".text-xs:nth-child(2)").text, + ) + print( + "recipe", + recipe_idx, + "ingredient", + ingredient_idx, + "time:", + ingredient.find_element(By.CSS_SELECTOR, ".text-xs:nth-child(3)").text, + ) + results = recipe.find_elements( + By.CSS_SELECTOR, f".flex-row > div:nth-child(3) > div:has(> a)" + ) + for result_idx in range(len(results)): + result = results[result_idx] + print( + "recipe", + recipe_idx, + "result", + result_idx, + "name:", + result.find_element(By.TAG_NAME, "img").get_attribute("alt"), + ) + print( + "recipe", + recipe_idx, + "result", + result_idx, + "count:", + result.find_element(By.CSS_SELECTOR, ".text-xs:nth-child(2)").text, + ) + print( + "recipe", + recipe_idx, + "result", + result_idx, + "time:", + result.find_element(By.CSS_SELECTOR, ".text-xs:nth-child(3)").text, + ) + finally: + if not debug: + browser.quit() diff --git a/factorygame/calculator/__init__.py b/factorygame/calculator/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/factorygame/calculator/__main__.py b/factorygame/calculator/__main__.py new file mode 100644 index 0000000..dd4a6af --- /dev/null +++ b/factorygame/calculator/__main__.py @@ -0,0 +1,3 @@ +from .SatisfactoryCalculator import main + +main()