diff --git a/.idea/dictionaries/project.xml b/.idea/dictionaries/project.xml deleted file mode 100644 index 1b2c7e6..0000000 --- a/.idea/dictionaries/project.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - deadzone - - - \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml deleted file mode 100644 index 105ce2d..0000000 --- a/.idea/inspectionProfiles/profiles_settings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 19d3eab..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 6128e1f..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/vts-gamepad-input.iml b/.idea/vts-gamepad-input.iml deleted file mode 100644 index af5c8dd..0000000 --- a/.idea/vts-gamepad-input.iml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml deleted file mode 100644 index 0c61893..0000000 --- a/.idea/workspace.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - - - - - { - "associatedIndex": 6 -} - - - - - - - { - "keyToString": { - "ModuleVcsDetector.initialDetectionPerformed": "true", - "RunOnceActivity.ShowReadmeOnStart": "true", - "RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252": "true", - "RunOnceActivity.git.unshallow": "true", - "git-widget-placeholder": "main", - "insyncwithfoo.ryecharm.ruff.caching.ruleNameToCodeMap": "{\"result\":{\"airflow-variable-name-task-id-mismatch\":\"AIR001\",\"airflow-dag-no-schedule-argument\":\"AIR002\",\"airflow3-removal\":\"AIR301\",\"airflow3-moved-to-provider\":\"AIR302\",\"airflow3-suggested-update\":\"AIR311\",\"airflow3-suggested-to-move-to-provider\":\"AIR312\",\"commented-out-code\":\"ERA001\",\"fast-api-redundant-response-model\":\"FAST001\",\"fast-api-non-annotated-dependency\":\"FAST002\",\"fast-api-unused-path-parameter\":\"FAST003\",\"sys-version-slice3\":\"YTT101\",\"sys-version2\":\"YTT102\",\"sys-version-cmp-str3\":\"YTT103\",\"sys-version-info0-eq3\":\"YTT201\",\"six-py3\":\"YTT202\",\"sys-version-info1-cmp-int\":\"YTT203\",\"sys-version-info-minor-cmp-int\":\"YTT204\",\"sys-version0\":\"YTT301\",\"sys-version-cmp-str10\":\"YTT302\",\"sys-version-slice1\":\"YTT303\",\"missing-type-function-argument\":\"ANN001\",\"missing-type-args\":\"ANN002\",\"missing-type-kwargs\":\"ANN003\",\"missing-type-self\":\"ANN101\",\"missing-type-cls\":\"ANN102\",\"missing-return-type-undocumented-public-function\":\"ANN201\",\"missing-return-type-private-function\":\"ANN202\",\"missing-return-type-special-method\":\"ANN204\",\"missing-return-type-static-method\":\"ANN205\",\"missing-return-type-class-method\":\"ANN206\",\"any-type\":\"ANN401\",\"cancel-scope-no-checkpoint\":\"ASYNC100\",\"trio-sync-call\":\"ASYNC105\",\"async-function-with-timeout\":\"ASYNC109\",\"async-busy-wait\":\"ASYNC110\",\"async-zero-sleep\":\"ASYNC115\",\"long-sleep-not-forever\":\"ASYNC116\",\"blocking-http-call-in-async-function\":\"ASYNC210\",\"blocking-http-call-httpx-in-async-function\":\"ASYNC212\",\"create-subprocess-in-async-function\":\"ASYNC220\",\"run-process-in-async-function\":\"ASYNC221\",\"wait-for-process-in-async-function\":\"ASYNC222\",\"blocking-open-call-in-async-function\":\"ASYNC230\",\"blocking-path-method-in-async-function\":\"ASYNC240\",\"blocking-input-in-async-function\":\"ASYNC250\",\"blocking-sleep-in-async-function\":\"ASYNC251\",\"assert\":\"S101\",\"exec-builtin\":\"S102\",\"bad-file-permissions\":\"S103\",\"hardcoded-bind-all-interfaces\":\"S104\",\"hardcoded-password-string\":\"S105\",\"hardcoded-password-func-arg\":\"S106\",\"hardcoded-password-default\":\"S107\",\"hardcoded-temp-file\":\"S108\",\"try-except-pass\":\"S110\",\"try-except-continue\":\"S112\",\"request-without-timeout\":\"S113\",\"flask-debug-true\":\"S201\",\"tarfile-unsafe-members\":\"S202\",\"suspicious-pickle-usage\":\"S301\",\"suspicious-marshal-usage\":\"S302\",\"suspicious-insecure-hash-usage\":\"S303\",\"suspicious-insecure-cipher-usage\":\"S304\",\"suspicious-insecure-cipher-mode-usage\":\"S305\",\"suspicious-mktemp-usage\":\"S306\",\"suspicious-eval-usage\":\"S307\",\"suspicious-mark-safe-usage\":\"S308\",\"suspicious-url-open-usage\":\"S310\",\"suspicious-non-cryptographic-random-usage\":\"S311\",\"suspicious-telnet-usage\":\"S312\",\"suspicious-xmlc-element-tree-usage\":\"S313\",\"suspicious-xml-element-tree-usage\":\"S314\",\"suspicious-xml-expat-reader-usage\":\"S315\",\"suspicious-xml-expat-builder-usage\":\"S316\",\"suspicious-xml-sax-usage\":\"S317\",\"suspicious-xml-mini-dom-usage\":\"S318\",\"suspicious-xml-pull-dom-usage\":\"S319\",\"suspicious-xmle-tree-usage\":\"S320\",\"suspicious-ftp-lib-usage\":\"S321\",\"suspicious-unverified-context-usage\":\"S323\",\"hashlib-insecure-hash-function\":\"S324\",\"suspicious-telnetlib-import\":\"S401\",\"suspicious-ftplib-import\":\"S402\",\"suspicious-pickle-import\":\"S403\",\"suspicious-subprocess-import\":\"S404\",\"suspicious-xml-etree-import\":\"S405\",\"suspicious-xml-sax-import\":\"S406\",\"suspicious-xml-expat-import\":\"S407\",\"suspicious-xml-minidom-import\":\"S408\",\"suspicious-xml-pulldom-import\":\"S409\",\"suspicious-lxml-import\":\"S410\",\"suspicious-xmlrpc-import\":\"S411\",\"suspicious-httpoxy-import\":\"S412\",\"suspicious-pycrypto-import\":\"S413\",\"suspicious-pyghmi-import\":\"S415\",\"request-with-no-cert-validation\":\"S501\",\"ssl-insecure-version\":\"S502\",\"ssl-with-bad-defaults\":\"S503\",\"ssl-with-no-version\":\"S504\",\"weak-cryptographic-key\":\"S505\",\"unsafe-yaml-load\":\"S506\",\"ssh-no-host-key-verification\":\"S507\",\"snmp-insecure-version\":\"S508\",\"snmp-weak-cryptography\":\"S509\",\"paramiko-call\":\"S601\",\"subprocess-popen-with-shell-equals-true\":\"S602\",\"subprocess-without-shell-equals-true\":\"S603\",\"call-with-shell-equals-true\":\"S604\",\"start-process-with-a-shell\":\"S605\",\"start-process-with-no-shell\":\"S606\",\"start-process-with-partial-path\":\"S607\",\"hardcoded-sql-expression\":\"S608\",\"unix-command-wildcard-injection\":\"S609\",\"django-extra\":\"S610\",\"django-raw-sql\":\"S611\",\"logging-config-insecure-listen\":\"S612\",\"jinja2-autoescape-false\":\"S701\",\"mako-templates\":\"S702\",\"unsafe-markup-use\":\"S704\",\"blind-except\":\"BLE001\",\"boolean-type-hint-positional-argument\":\"FBT001\",\"boolean-default-value-positional-argument\":\"FBT002\",\"boolean-positional-value-in-call\":\"FBT003\",\"unary-prefix-increment-decrement\":\"B002\",\"assignment-to-os-environ\":\"B003\",\"unreliable-callable-check\":\"B004\",\"strip-with-multi-characters\":\"B005\",\"mutable-argument-default\":\"B006\",\"unused-loop-control-variable\":\"B007\",\"function-call-in-default-argument\":\"B008\",\"get-attr-with-constant\":\"B009\",\"set-attr-with-constant\":\"B010\",\"assert-false\":\"B011\",\"jump-statement-in-finally\":\"B012\",\"redundant-tuple-in-exception-handler\":\"B013\",\"duplicate-handler-exception\":\"B014\",\"useless-comparison\":\"B015\",\"raise-literal\":\"B016\",\"assert-raises-exception\":\"B017\",\"useless-expression\":\"B018\",\"cached-instance-method\":\"B019\",\"loop-variable-overrides-iterator\":\"B020\",\"f-string-docstring\":\"B021\",\"useless-contextlib-suppress\":\"B022\",\"function-uses-loop-variable\":\"B023\",\"abstract-base-class-without-abstract-method\":\"B024\",\"duplicate-try-block-exception\":\"B025\",\"star-arg-unpacking-after-keyword-arg\":\"B026\",\"empty-method-without-abstract-decorator\":\"B027\",\"no-explicit-stacklevel\":\"B028\",\"except-with-empty-tuple\":\"B029\",\"except-with-non-exception-classes\":\"B030\",\"reuse-of-groupby-generator\":\"B031\",\"unintentional-type-annotation\":\"B032\",\"duplicate-value\":\"B033\",\"re-sub-positional-args\":\"B034\",\"static-key-dict-comprehension\":\"B035\",\"mutable-contextvar-default\":\"B039\",\"return-in-generator\":\"B901\",\"class-as-data-structure\":\"B903\",\"raise-without-from-inside-except\":\"B904\",\"zip-without-explicit-strict\":\"B905\",\"loop-iterator-mutation\":\"B909\",\"batched-without-explicit-strict\":\"B911\",\"map-without-explicit-strict\":\"B912\",\"builtin-variable-shadowing\":\"A001\",\"builtin-argument-shadowing\":\"A002\",\"builtin-attribute-shadowing\":\"A003\",\"builtin-import-shadowing\":\"A004\",\"stdlib-module-shadowing\":\"A005\",\"builtin-lambda-argument-shadowing\":\"A006\",\"missing-trailing-comma\":\"COM812\",\"trailing-comma-on-bare-tuple\":\"COM818\",\"prohibited-trailing-comma\":\"COM819\",\"unnecessary-generator-list\":\"C400\",\"unnecessary-generator-set\":\"C401\",\"unnecessary-generator-dict\":\"C402\",\"unnecessary-list-comprehension-set\":\"C403\",\"unnecessary-list-comprehension-dict\":\"C404\",\"unnecessary-literal-set\":\"C405\",\"unnecessary-literal-dict\":\"C406\",\"unnecessary-collection-call\":\"C408\",\"unnecessary-literal-within-tuple-call\":\"C409\",\"unnecessary-literal-within-list-call\":\"C410\",\"unnecessary-list-call\":\"C411\",\"unnecessary-call-around-sorted\":\"C413\",\"unnecessary-double-cast-or-process\":\"C414\",\"unnecessary-subscript-reversal\":\"C415\",\"unnecessary-comprehension\":\"C416\",\"unnecessary-map\":\"C417\",\"unnecessary-literal-within-dict-call\":\"C418\",\"unnecessary-comprehension-in-call\":\"C419\",\"unnecessary-dict-comprehension-for-iterable\":\"C420\",\"missing-copyright-notice\":\"CPY001\",\"call-datetime-without-tzinfo\":\"DTZ001\",\"call-datetime-today\":\"DTZ002\",\"call-datetime-utcnow\":\"DTZ003\",\"call-datetime-utcfromtimestamp\":\"DTZ004\",\"call-datetime-now-without-tzinfo\":\"DTZ005\",\"call-datetime-fromtimestamp\":\"DTZ006\",\"call-datetime-strptime-without-zone\":\"DTZ007\",\"call-date-today\":\"DTZ011\",\"call-date-fromtimestamp\":\"DTZ012\",\"datetime-min-max\":\"DTZ901\",\"debugger\":\"T100\",\"django-nullable-model-string-field\":\"DJ001\",\"django-locals-in-render-function\":\"DJ003\",\"django-exclude-with-model-form\":\"DJ006\",\"django-all-with-model-form\":\"DJ007\",\"django-model-without-dunder-str\":\"DJ008\",\"django-unordered-body-content-in-model\":\"DJ012\",\"django-non-leading-receiver-decorator\":\"DJ013\",\"raw-string-in-exception\":\"EM101\",\"f-string-in-exception\":\"EM102\",\"dot-format-in-exception\":\"EM103\",\"shebang-not-executable\":\"EXE001\",\"shebang-missing-executable-file\":\"EXE002\",\"shebang-missing-python\":\"EXE003\",\"shebang-leading-whitespace\":\"EXE004\",\"shebang-not-first-line\":\"EXE005\",\"line-contains-fixme\":\"FIX001\",\"line-contains-todo\":\"FIX002\",\"line-contains-xxx\":\"FIX003\",\"line-contains-hack\":\"FIX004\",\"future-rewritable-type-annotation\":\"FA100\",\"future-required-type-annotation\":\"FA102\",\"f-string-in-get-text-func-call\":\"INT001\",\"format-in-get-text-func-call\":\"INT002\",\"printf-in-get-text-func-call\":\"INT003\",\"single-line-implicit-string-concatenation\":\"ISC001\",\"multi-line-implicit-string-concatenation\":\"ISC002\",\"explicit-string-concatenation\":\"ISC003\",\"unconventional-import-alias\":\"ICN001\",\"banned-import-alias\":\"ICN002\",\"banned-import-from\":\"ICN003\",\"direct-logger-instantiation\":\"LOG001\",\"invalid-get-logger-argument\":\"LOG002\",\"log-exception-outside-except-handler\":\"LOG004\",\"exception-without-exc-info\":\"LOG007\",\"undocumented-warn\":\"LOG009\",\"exc-info-outside-except-handler\":\"LOG014\",\"root-logger-call\":\"LOG015\",\"logging-string-format\":\"G001\",\"logging-percent-format\":\"G002\",\"logging-string-concat\":\"G003\",\"logging-f-string\":\"G004\",\"logging-warn\":\"G010\",\"logging-extra-attr-clash\":\"G101\",\"logging-exc-info\":\"G201\",\"logging-redundant-exc-info\":\"G202\",\"implicit-namespace-package\":\"INP001\",\"unnecessary-placeholder\":\"PIE790\",\"duplicate-class-field-definition\":\"PIE794\",\"non-unique-enums\":\"PIE796\",\"unnecessary-spread\":\"PIE800\",\"unnecessary-dict-kwargs\":\"PIE804\",\"reimplemented-container-builtin\":\"PIE807\",\"unnecessary-range-start\":\"PIE808\",\"multiple-starts-ends-with\":\"PIE810\",\"print\":\"T201\",\"p-print\":\"T203\",\"unprefixed-type-param\":\"PYI001\",\"complex-if-statement-in-stub\":\"PYI002\",\"unrecognized-version-info-check\":\"PYI003\",\"patch-version-comparison\":\"PYI004\",\"wrong-tuple-length-version-comparison\":\"PYI005\",\"bad-version-info-comparison\":\"PYI006\",\"unrecognized-platform-check\":\"PYI007\",\"unrecognized-platform-name\":\"PYI008\",\"pass-statement-stub-body\":\"PYI009\",\"non-empty-stub-body\":\"PYI010\",\"typed-argument-default-in-stub\":\"PYI011\",\"pass-in-class-body\":\"PYI012\",\"ellipsis-in-non-empty-class-body\":\"PYI013\",\"argument-default-in-stub\":\"PYI014\",\"assignment-default-in-stub\":\"PYI015\",\"duplicate-union-member\":\"PYI016\",\"complex-assignment-in-stub\":\"PYI017\",\"unused-private-type-var\":\"PYI018\",\"custom-type-var-for-self\":\"PYI019\",\"quoted-annotation-in-stub\":\"PYI020\",\"docstring-in-stub\":\"PYI021\",\"collections-named-tuple\":\"PYI024\",\"unaliased-collections-abc-set-import\":\"PYI025\",\"type-alias-without-annotation\":\"PYI026\",\"str-or-repr-defined-in-stub\":\"PYI029\",\"unnecessary-literal-union\":\"PYI030\",\"any-eq-ne-annotation\":\"PYI032\",\"type-comment-in-stub\":\"PYI033\",\"non-self-return-type\":\"PYI034\",\"unassigned-special-variable-in-stub\":\"PYI035\",\"bad-exit-annotation\":\"PYI036\",\"redundant-numeric-union\":\"PYI041\",\"snake-case-type-alias\":\"PYI042\",\"t-suffixed-type-alias\":\"PYI043\",\"future-annotations-in-stub\":\"PYI044\",\"iter-method-return-iterable\":\"PYI045\",\"unused-private-protocol\":\"PYI046\",\"unused-private-type-alias\":\"PYI047\",\"stub-body-multiple-statements\":\"PYI048\",\"unused-private-typed-dict\":\"PYI049\",\"no-return-argument-annotation-in-stub\":\"PYI050\",\"redundant-literal-union\":\"PYI051\",\"unannotated-assignment-in-stub\":\"PYI052\",\"string-or-bytes-too-long\":\"PYI053\",\"numeric-literal-too-long\":\"PYI054\",\"unnecessary-type-union\":\"PYI055\",\"unsupported-method-call-on-all\":\"PYI056\",\"byte-string-usage\":\"PYI057\",\"generator-return-from-iter-method\":\"PYI058\",\"generic-not-last-base-class\":\"PYI059\",\"redundant-none-literal\":\"PYI061\",\"duplicate-literal-member\":\"PYI062\",\"pep484-style-positional-only-parameter\":\"PYI063\",\"redundant-final-literal\":\"PYI064\",\"bad-version-info-order\":\"PYI066\",\"pytest-fixture-incorrect-parentheses-style\":\"PT001\",\"pytest-fixture-positional-args\":\"PT002\",\"pytest-extraneous-scope-function\":\"PT003\",\"pytest-missing-fixture-name-underscore\":\"PT004\",\"pytest-incorrect-fixture-name-underscore\":\"PT005\",\"pytest-parametrize-names-wrong-type\":\"PT006\",\"pytest-parametrize-values-wrong-type\":\"PT007\",\"pytest-patch-with-lambda\":\"PT008\",\"pytest-unittest-assertion\":\"PT009\",\"pytest-raises-without-exception\":\"PT010\",\"pytest-raises-too-broad\":\"PT011\",\"pytest-raises-with-multiple-statements\":\"PT012\",\"pytest-incorrect-pytest-import\":\"PT013\",\"pytest-duplicate-parametrize-test-cases\":\"PT014\",\"pytest-assert-always-false\":\"PT015\",\"pytest-fail-without-message\":\"PT016\",\"pytest-assert-in-except\":\"PT017\",\"pytest-composite-assertion\":\"PT018\",\"pytest-fixture-param-without-value\":\"PT019\",\"pytest-deprecated-yield-fixture\":\"PT020\",\"pytest-fixture-finalizer-callback\":\"PT021\",\"pytest-useless-yield-fixture\":\"PT022\",\"pytest-incorrect-mark-parentheses-style\":\"PT023\",\"pytest-unnecessary-asyncio-mark-on-fixture\":\"PT024\",\"pytest-erroneous-use-fixtures-on-fixture\":\"PT025\",\"pytest-use-fixtures-without-parameters\":\"PT026\",\"pytest-unittest-raises-assertion\":\"PT027\",\"pytest-parameter-with-default-argument\":\"PT028\",\"pytest-warns-without-warning\":\"PT029\",\"pytest-warns-too-broad\":\"PT030\",\"pytest-warns-with-multiple-statements\":\"PT031\",\"bad-quotes-inline-string\":\"Q000\",\"bad-quotes-multiline-string\":\"Q001\",\"bad-quotes-docstring\":\"Q002\",\"avoidable-escaped-quote\":\"Q003\",\"unnecessary-escaped-quote\":\"Q004\",\"unnecessary-paren-on-raise-exception\":\"RSE102\",\"unnecessary-return-none\":\"RET501\",\"implicit-return-value\":\"RET502\",\"implicit-return\":\"RET503\",\"unnecessary-assign\":\"RET504\",\"superfluous-else-return\":\"RET505\",\"superfluous-else-raise\":\"RET506\",\"superfluous-else-continue\":\"RET507\",\"superfluous-else-break\":\"RET508\",\"private-member-access\":\"SLF001\",\"duplicate-isinstance-call\":\"SIM101\",\"collapsible-if\":\"SIM102\",\"needless-bool\":\"SIM103\",\"suppressible-exception\":\"SIM105\",\"return-in-try-except-finally\":\"SIM107\",\"if-else-block-instead-of-if-exp\":\"SIM108\",\"compare-with-tuple\":\"SIM109\",\"reimplemented-builtin\":\"SIM110\",\"uncapitalized-environment-variables\":\"SIM112\",\"enumerate-for-loop\":\"SIM113\",\"if-with-same-arms\":\"SIM114\",\"open-file-with-context-handler\":\"SIM115\",\"if-else-block-instead-of-dict-lookup\":\"SIM116\",\"multiple-with-statements\":\"SIM117\",\"in-dict-keys\":\"SIM118\",\"negate-equal-op\":\"SIM201\",\"negate-not-equal-op\":\"SIM202\",\"double-negation\":\"SIM208\",\"if-expr-with-true-false\":\"SIM210\",\"if-expr-with-false-true\":\"SIM211\",\"if-expr-with-twisted-arms\":\"SIM212\",\"expr-and-not-expr\":\"SIM220\",\"expr-or-not-expr\":\"SIM221\",\"expr-or-true\":\"SIM222\",\"expr-and-false\":\"SIM223\",\"yoda-conditions\":\"SIM300\",\"if-else-block-instead-of-dict-get\":\"SIM401\",\"split-static-string\":\"SIM905\",\"dict-get-with-none-default\":\"SIM910\",\"zip-dict-keys-and-values\":\"SIM911\",\"no-slots-in-str-subclass\":\"SLOT000\",\"no-slots-in-tuple-subclass\":\"SLOT001\",\"no-slots-in-namedtuple-subclass\":\"SLOT002\",\"banned-api\":\"TID251\",\"relative-imports\":\"TID252\",\"banned-module-level-imports\":\"TID253\",\"invalid-todo-tag\":\"TD001\",\"missing-todo-author\":\"TD002\",\"missing-todo-link\":\"TD003\",\"missing-todo-colon\":\"TD004\",\"missing-todo-description\":\"TD005\",\"invalid-todo-capitalization\":\"TD006\",\"missing-space-after-todo-colon\":\"TD007\",\"typing-only-first-party-import\":\"TC001\",\"typing-only-third-party-import\":\"TC002\",\"typing-only-standard-library-import\":\"TC003\",\"runtime-import-in-type-checking-block\":\"TC004\",\"empty-type-checking-block\":\"TC005\",\"runtime-cast-value\":\"TC006\",\"unquoted-type-alias\":\"TC007\",\"quoted-type-alias\":\"TC008\",\"runtime-string-union\":\"TC010\",\"unused-function-argument\":\"ARG001\",\"unused-method-argument\":\"ARG002\",\"unused-class-method-argument\":\"ARG003\",\"unused-static-method-argument\":\"ARG004\",\"unused-lambda-argument\":\"ARG005\",\"os-path-abspath\":\"PTH100\",\"os-chmod\":\"PTH101\",\"os-mkdir\":\"PTH102\",\"os-makedirs\":\"PTH103\",\"os-rename\":\"PTH104\",\"os-replace\":\"PTH105\",\"os-rmdir\":\"PTH106\",\"os-remove\":\"PTH107\",\"os-unlink\":\"PTH108\",\"os-getcwd\":\"PTH109\",\"os-path-exists\":\"PTH110\",\"os-path-expanduser\":\"PTH111\",\"os-path-isdir\":\"PTH112\",\"os-path-isfile\":\"PTH113\",\"os-path-islink\":\"PTH114\",\"os-readlink\":\"PTH115\",\"os-stat\":\"PTH116\",\"os-path-isabs\":\"PTH117\",\"os-path-join\":\"PTH118\",\"os-path-basename\":\"PTH119\",\"os-path-dirname\":\"PTH120\",\"os-path-samefile\":\"PTH121\",\"os-path-splitext\":\"PTH122\",\"builtin-open\":\"PTH123\",\"py-path\":\"PTH124\",\"path-constructor-current-directory\":\"PTH201\",\"os-path-getsize\":\"PTH202\",\"os-path-getatime\":\"PTH203\",\"os-path-getmtime\":\"PTH204\",\"os-path-getctime\":\"PTH205\",\"os-sep-split\":\"PTH206\",\"glob\":\"PTH207\",\"os-listdir\":\"PTH208\",\"invalid-pathlib-with-suffix\":\"PTH210\",\"os-symlink\":\"PTH211\",\"static-join-to-f-string\":\"FLY002\",\"unsorted-imports\":\"I001\",\"missing-required-import\":\"I002\",\"complex-structure\":\"C901\",\"numpy-deprecated-type-alias\":\"NPY001\",\"numpy-legacy-random\":\"NPY002\",\"numpy-deprecated-function\":\"NPY003\",\"numpy2-deprecation\":\"NPY201\",\"invalid-class-name\":\"N801\",\"invalid-function-name\":\"N802\",\"invalid-argument-name\":\"N803\",\"invalid-first-argument-name-for-class-method\":\"N804\",\"invalid-first-argument-name-for-method\":\"N805\",\"non-lowercase-variable-in-function\":\"N806\",\"dunder-function-name\":\"N807\",\"constant-imported-as-non-constant\":\"N811\",\"lowercase-imported-as-non-lowercase\":\"N812\",\"camelcase-imported-as-lowercase\":\"N813\",\"camelcase-imported-as-constant\":\"N814\",\"mixed-case-variable-in-class-scope\":\"N815\",\"mixed-case-variable-in-global-scope\":\"N816\",\"camelcase-imported-as-acronym\":\"N817\",\"error-suffix-on-exception-name\":\"N818\",\"invalid-module-name\":\"N999\",\"pandas-use-of-inplace-argument\":\"PD002\",\"pandas-use-of-dot-is-null\":\"PD003\",\"pandas-use-of-dot-not-null\":\"PD004\",\"pandas-use-of-dot-ix\":\"PD007\",\"pandas-use-of-dot-at\":\"PD008\",\"pandas-use-of-dot-iat\":\"PD009\",\"pandas-use-of-dot-pivot-or-unstack\":\"PD010\",\"pandas-use-of-dot-values\":\"PD011\",\"pandas-use-of-dot-read-table\":\"PD012\",\"pandas-use-of-dot-stack\":\"PD013\",\"pandas-use-of-pd-merge\":\"PD015\",\"pandas-nunique-constant-series-check\":\"PD101\",\"pandas-df-variable-name\":\"PD901\",\"unnecessary-list-cast\":\"PERF101\",\"incorrect-dict-iterator\":\"PERF102\",\"try-except-in-loop\":\"PERF203\",\"manual-list-comprehension\":\"PERF401\",\"manual-list-copy\":\"PERF402\",\"manual-dict-comprehension\":\"PERF403\",\"mixed-spaces-and-tabs\":\"E101\",\"indentation-with-invalid-multiple\":\"E111\",\"no-indented-block\":\"E112\",\"unexpected-indentation\":\"E113\",\"indentation-with-invalid-multiple-comment\":\"E114\",\"no-indented-block-comment\":\"E115\",\"unexpected-indentation-comment\":\"E116\",\"over-indented\":\"E117\",\"whitespace-after-open-bracket\":\"E201\",\"whitespace-before-close-bracket\":\"E202\",\"whitespace-before-punctuation\":\"E203\",\"whitespace-after-decorator\":\"E204\",\"whitespace-before-parameters\":\"E211\",\"multiple-spaces-before-operator\":\"E221\",\"multiple-spaces-after-operator\":\"E222\",\"tab-before-operator\":\"E223\",\"tab-after-operator\":\"E224\",\"missing-whitespace-around-operator\":\"E225\",\"missing-whitespace-around-arithmetic-operator\":\"E226\",\"missing-whitespace-around-bitwise-or-shift-operator\":\"E227\",\"missing-whitespace-around-modulo-operator\":\"E228\",\"missing-whitespace\":\"E231\",\"multiple-spaces-after-comma\":\"E241\",\"tab-after-comma\":\"E242\",\"unexpected-spaces-around-keyword-parameter-equals\":\"E251\",\"missing-whitespace-around-parameter-equals\":\"E252\",\"too-few-spaces-before-inline-comment\":\"E261\",\"no-space-after-inline-comment\":\"E262\",\"no-space-after-block-comment\":\"E265\",\"multiple-leading-hashes-for-block-comment\":\"E266\",\"multiple-spaces-after-keyword\":\"E271\",\"multiple-spaces-before-keyword\":\"E272\",\"tab-after-keyword\":\"E273\",\"tab-before-keyword\":\"E274\",\"missing-whitespace-after-keyword\":\"E275\",\"blank-line-between-methods\":\"E301\",\"blank-lines-top-level\":\"E302\",\"too-many-blank-lines\":\"E303\",\"blank-line-after-decorator\":\"E304\",\"blank-lines-after-function-or-class\":\"E305\",\"blank-lines-before-nested-definition\":\"E306\",\"multiple-imports-on-one-line\":\"E401\",\"module-import-not-at-top-of-file\":\"E402\",\"line-too-long\":\"E501\",\"redundant-backslash\":\"E502\",\"multiple-statements-on-one-line-colon\":\"E701\",\"multiple-statements-on-one-line-semicolon\":\"E702\",\"useless-semicolon\":\"E703\",\"none-comparison\":\"E711\",\"true-false-comparison\":\"E712\",\"not-in-test\":\"E713\",\"not-is-test\":\"E714\",\"type-comparison\":\"E721\",\"bare-except\":\"E722\",\"lambda-assignment\":\"E731\",\"ambiguous-variable-name\":\"E741\",\"ambiguous-class-name\":\"E742\",\"ambiguous-function-name\":\"E743\",\"io-error\":\"E902\",\"syntax-error\":\"E999\",\"tab-indentation\":\"W191\",\"trailing-whitespace\":\"W291\",\"missing-newline-at-end-of-file\":\"W292\",\"blank-line-with-whitespace\":\"W293\",\"too-many-newlines-at-end-of-file\":\"W391\",\"doc-line-too-long\":\"W505\",\"invalid-escape-sequence\":\"W605\",\"docstring-extraneous-parameter\":\"DOC102\",\"docstring-missing-returns\":\"DOC201\",\"docstring-extraneous-returns\":\"DOC202\",\"docstring-missing-yields\":\"DOC402\",\"docstring-extraneous-yields\":\"DOC403\",\"docstring-missing-exception\":\"DOC501\",\"docstring-extraneous-exception\":\"DOC502\",\"undocumented-public-module\":\"D100\",\"undocumented-public-class\":\"D101\",\"undocumented-public-method\":\"D102\",\"undocumented-public-function\":\"D103\",\"undocumented-public-package\":\"D104\",\"undocumented-magic-method\":\"D105\",\"undocumented-public-nested-class\":\"D106\",\"undocumented-public-init\":\"D107\",\"unnecessary-multiline-docstring\":\"D200\",\"blank-line-before-function\":\"D201\",\"blank-line-after-function\":\"D202\",\"incorrect-blank-line-before-class\":\"D203\",\"incorrect-blank-line-after-class\":\"D204\",\"missing-blank-line-after-summary\":\"D205\",\"docstring-tab-indentation\":\"D206\",\"under-indentation\":\"D207\",\"over-indentation\":\"D208\",\"new-line-after-last-paragraph\":\"D209\",\"surrounding-whitespace\":\"D210\",\"blank-line-before-class\":\"D211\",\"multi-line-summary-first-line\":\"D212\",\"multi-line-summary-second-line\":\"D213\",\"overindented-section\":\"D214\",\"overindented-section-underline\":\"D215\",\"triple-single-quotes\":\"D300\",\"escape-sequence-in-docstring\":\"D301\",\"missing-trailing-period\":\"D400\",\"non-imperative-mood\":\"D401\",\"signature-in-docstring\":\"D402\",\"first-word-uncapitalized\":\"D403\",\"docstring-starts-with-this\":\"D404\",\"non-capitalized-section-name\":\"D405\",\"missing-new-line-after-section-name\":\"D406\",\"missing-dashed-underline-after-section\":\"D407\",\"missing-section-underline-after-name\":\"D408\",\"mismatched-section-underline-length\":\"D409\",\"no-blank-line-after-section\":\"D410\",\"no-blank-line-before-section\":\"D411\",\"blank-lines-between-header-and-content\":\"D412\",\"missing-blank-line-after-last-section\":\"D413\",\"empty-docstring-section\":\"D414\",\"missing-terminal-punctuation\":\"D415\",\"missing-section-name-colon\":\"D416\",\"undocumented-param\":\"D417\",\"overload-with-docstring\":\"D418\",\"empty-docstring\":\"D419\",\"unused-import\":\"F401\",\"import-shadowed-by-loop-var\":\"F402\",\"undefined-local-with-import-star\":\"F403\",\"late-future-import\":\"F404\",\"undefined-local-with-import-star-usage\":\"F405\",\"undefined-local-with-nested-import-star-usage\":\"F406\",\"future-feature-not-defined\":\"F407\",\"percent-format-invalid-format\":\"F501\",\"percent-format-expected-mapping\":\"F502\",\"percent-format-expected-sequence\":\"F503\",\"percent-format-extra-named-arguments\":\"F504\",\"percent-format-missing-argument\":\"F505\",\"percent-format-mixed-positional-and-named\":\"F506\",\"percent-format-positional-count-mismatch\":\"F507\",\"percent-format-star-requires-sequence\":\"F508\",\"percent-format-unsupported-format-character\":\"F509\",\"string-dot-format-invalid-format\":\"F521\",\"string-dot-format-extra-named-arguments\":\"F522\",\"string-dot-format-extra-positional-arguments\":\"F523\",\"string-dot-format-missing-arguments\":\"F524\",\"string-dot-format-mixing-automatic\":\"F525\",\"f-string-missing-placeholders\":\"F541\",\"multi-value-repeated-key-literal\":\"F601\",\"multi-value-repeated-key-variable\":\"F602\",\"expressions-in-star-assignment\":\"F621\",\"multiple-starred-expressions\":\"F622\",\"assert-tuple\":\"F631\",\"is-literal\":\"F632\",\"invalid-print-syntax\":\"F633\",\"if-tuple\":\"F634\",\"break-outside-loop\":\"F701\",\"continue-outside-loop\":\"F702\",\"yield-outside-function\":\"F704\",\"return-outside-function\":\"F706\",\"default-except-not-last\":\"F707\",\"forward-annotation-syntax-error\":\"F722\",\"redefined-while-unused\":\"F811\",\"undefined-name\":\"F821\",\"undefined-export\":\"F822\",\"undefined-local\":\"F823\",\"unused-variable\":\"F841\",\"unused-annotation\":\"F842\",\"raise-not-implemented\":\"F901\",\"eval\":\"PGH001\",\"deprecated-log-warn\":\"PGH002\",\"blanket-type-ignore\":\"PGH003\",\"blanket-noqa\":\"PGH004\",\"invalid-mock-access\":\"PGH005\",\"type-name-incorrect-variance\":\"PLC0105\",\"type-bivariance\":\"PLC0131\",\"type-param-name-mismatch\":\"PLC0132\",\"single-string-slots\":\"PLC0205\",\"dict-index-missing-items\":\"PLC0206\",\"missing-maxsplit-arg\":\"PLC0207\",\"iteration-over-set\":\"PLC0208\",\"useless-import-alias\":\"PLC0414\",\"import-outside-top-level\":\"PLC0415\",\"len-test\":\"PLC1802\",\"compare-to-empty-string\":\"PLC1901\",\"non-ascii-name\":\"PLC2401\",\"non-ascii-import-name\":\"PLC2403\",\"import-private-name\":\"PLC2701\",\"unnecessary-dunder-call\":\"PLC2801\",\"unnecessary-direct-lambda-call\":\"PLC3002\",\"yield-in-init\":\"PLE0100\",\"return-in-init\":\"PLE0101\",\"nonlocal-and-global\":\"PLE0115\",\"continue-in-finally\":\"PLE0116\",\"nonlocal-without-binding\":\"PLE0117\",\"load-before-global-declaration\":\"PLE0118\",\"non-slot-assignment\":\"PLE0237\",\"duplicate-bases\":\"PLE0241\",\"unexpected-special-method-signature\":\"PLE0302\",\"invalid-length-return-type\":\"PLE0303\",\"invalid-bool-return-type\":\"PLE0304\",\"invalid-index-return-type\":\"PLE0305\",\"invalid-str-return-type\":\"PLE0307\",\"invalid-bytes-return-type\":\"PLE0308\",\"invalid-hash-return-type\":\"PLE0309\",\"invalid-all-object\":\"PLE0604\",\"invalid-all-format\":\"PLE0605\",\"potential-index-error\":\"PLE0643\",\"misplaced-bare-raise\":\"PLE0704\",\"repeated-keyword-argument\":\"PLE1132\",\"dict-iter-missing-items\":\"PLE1141\",\"await-outside-async\":\"PLE1142\",\"logging-too-many-args\":\"PLE1205\",\"logging-too-few-args\":\"PLE1206\",\"bad-string-format-character\":\"PLE1300\",\"bad-string-format-type\":\"PLE1307\",\"bad-str-strip-call\":\"PLE1310\",\"invalid-envvar-value\":\"PLE1507\",\"singledispatch-method\":\"PLE1519\",\"singledispatchmethod-function\":\"PLE1520\",\"yield-from-in-async-function\":\"PLE1700\",\"bidirectional-unicode\":\"PLE2502\",\"invalid-character-backspace\":\"PLE2510\",\"invalid-character-sub\":\"PLE2512\",\"invalid-character-esc\":\"PLE2513\",\"invalid-character-nul\":\"PLE2514\",\"invalid-character-zero-width-space\":\"PLE2515\",\"modified-iterating-set\":\"PLE4703\",\"comparison-with-itself\":\"PLR0124\",\"comparison-of-constant\":\"PLR0133\",\"no-classmethod-decorator\":\"PLR0202\",\"no-staticmethod-decorator\":\"PLR0203\",\"property-with-parameters\":\"PLR0206\",\"manual-from-import\":\"PLR0402\",\"too-many-public-methods\":\"PLR0904\",\"too-many-return-statements\":\"PLR0911\",\"too-many-branches\":\"PLR0912\",\"too-many-arguments\":\"PLR0913\",\"too-many-locals\":\"PLR0914\",\"too-many-statements\":\"PLR0915\",\"too-many-boolean-expressions\":\"PLR0916\",\"too-many-positional-arguments\":\"PLR0917\",\"repeated-isinstance-calls\":\"PLR1701\",\"too-many-nested-blocks\":\"PLR1702\",\"redefined-argument-from-local\":\"PLR1704\",\"and-or-ternary\":\"PLR1706\",\"stop-iteration-return\":\"PLR1708\",\"useless-return\":\"PLR1711\",\"repeated-equality-comparison\":\"PLR1714\",\"boolean-chained-comparison\":\"PLR1716\",\"sys-exit-alias\":\"PLR1722\",\"if-stmt-min-max\":\"PLR1730\",\"unnecessary-dict-index-lookup\":\"PLR1733\",\"unnecessary-list-index-lookup\":\"PLR1736\",\"magic-value-comparison\":\"PLR2004\",\"empty-comment\":\"PLR2044\",\"collapsible-else-if\":\"PLR5501\",\"non-augmented-assignment\":\"PLR6104\",\"literal-membership\":\"PLR6201\",\"no-self-use\":\"PLR6301\",\"unnecessary-lambda\":\"PLW0108\",\"useless-else-on-loop\":\"PLW0120\",\"self-assigning-variable\":\"PLW0127\",\"redeclared-assigned-name\":\"PLW0128\",\"assert-on-string-literal\":\"PLW0129\",\"named-expr-without-context\":\"PLW0131\",\"useless-exception-statement\":\"PLW0133\",\"nan-comparison\":\"PLW0177\",\"bad-staticmethod-argument\":\"PLW0211\",\"redefined-slots-in-subclass\":\"PLW0244\",\"super-without-brackets\":\"PLW0245\",\"import-self\":\"PLW0406\",\"global-variable-not-assigned\":\"PLW0602\",\"global-statement\":\"PLW0603\",\"global-at-module-level\":\"PLW0604\",\"self-or-cls-assignment\":\"PLW0642\",\"binary-op-exception\":\"PLW0711\",\"bad-open-mode\":\"PLW1501\",\"shallow-copy-environ\":\"PLW1507\",\"invalid-envvar-default\":\"PLW1508\",\"subprocess-popen-preexec-fn\":\"PLW1509\",\"subprocess-run-without-check\":\"PLW1510\",\"unspecified-encoding\":\"PLW1514\",\"eq-without-hash\":\"PLW1641\",\"useless-with-lock\":\"PLW2101\",\"redefined-loop-name\":\"PLW2901\",\"bad-dunder-method-name\":\"PLW3201\",\"nested-min-max\":\"PLW3301\",\"useless-metaclass-type\":\"UP001\",\"type-of-primitive\":\"UP003\",\"useless-object-inheritance\":\"UP004\",\"deprecated-unittest-alias\":\"UP005\",\"non-pep585-annotation\":\"UP006\",\"non-pep604-annotation-union\":\"UP007\",\"super-call-with-parameters\":\"UP008\",\"utf8-encoding-declaration\":\"UP009\",\"unnecessary-future-import\":\"UP010\",\"lru-cache-without-parameters\":\"UP011\",\"unnecessary-encode-utf8\":\"UP012\",\"convert-typed-dict-functional-to-class\":\"UP013\",\"convert-named-tuple-functional-to-class\":\"UP014\",\"redundant-open-modes\":\"UP015\",\"datetime-timezone-utc\":\"UP017\",\"native-literals\":\"UP018\",\"typing-text-str-alias\":\"UP019\",\"open-alias\":\"UP020\",\"replace-universal-newlines\":\"UP021\",\"replace-stdout-stderr\":\"UP022\",\"deprecated-c-element-tree\":\"UP023\",\"os-error-alias\":\"UP024\",\"unicode-kind-prefix\":\"UP025\",\"deprecated-mock-import\":\"UP026\",\"unpacked-list-comprehension\":\"UP027\",\"yield-in-for-loop\":\"UP028\",\"unnecessary-builtin-import\":\"UP029\",\"format-literals\":\"UP030\",\"printf-string-formatting\":\"UP031\",\"f-string\":\"UP032\",\"lru-cache-with-maxsize-none\":\"UP033\",\"extraneous-parentheses\":\"UP034\",\"deprecated-import\":\"UP035\",\"outdated-version-block\":\"UP036\",\"quoted-annotation\":\"UP037\",\"non-pep604-isinstance\":\"UP038\",\"unnecessary-class-parentheses\":\"UP039\",\"non-pep695-type-alias\":\"UP040\",\"timeout-error-alias\":\"UP041\",\"replace-str-enum\":\"UP042\",\"unnecessary-default-type-args\":\"UP043\",\"non-pep646-unpack\":\"UP044\",\"non-pep604-annotation-optional\":\"UP045\",\"non-pep695-generic-class\":\"UP046\",\"non-pep695-generic-function\":\"UP047\",\"private-type-parameter\":\"UP049\",\"useless-class-metaclass-type\":\"UP050\",\"read-whole-file\":\"FURB101\",\"write-whole-file\":\"FURB103\",\"print-empty-string\":\"FURB105\",\"if-exp-instead-of-or-operator\":\"FURB110\",\"repeated-append\":\"FURB113\",\"f-string-number-format\":\"FURB116\",\"reimplemented-operator\":\"FURB118\",\"for-loop-writes\":\"FURB122\",\"readlines-in-for\":\"FURB129\",\"delete-full-slice\":\"FURB131\",\"check-and-remove-from-set\":\"FURB132\",\"if-expr-min-max\":\"FURB136\",\"reimplemented-starmap\":\"FURB140\",\"for-loop-set-mutations\":\"FURB142\",\"slice-copy\":\"FURB145\",\"unnecessary-enumerate\":\"FURB148\",\"math-constant\":\"FURB152\",\"repeated-global\":\"FURB154\",\"hardcoded-string-charset\":\"FURB156\",\"verbose-decimal-constructor\":\"FURB157\",\"bit-count\":\"FURB161\",\"fromisoformat-replace-z\":\"FURB162\",\"redundant-log-base\":\"FURB163\",\"unnecessary-from-float\":\"FURB164\",\"int-on-sliced-str\":\"FURB166\",\"regex-flag-alias\":\"FURB167\",\"isinstance-type-none\":\"FURB168\",\"type-none-comparison\":\"FURB169\",\"single-item-membership-test\":\"FURB171\",\"implicit-cwd\":\"FURB177\",\"meta-class-abc-meta\":\"FURB180\",\"hashlib-digest-hex\":\"FURB181\",\"list-reverse-copy\":\"FURB187\",\"slice-to-remove-prefix-or-suffix\":\"FURB188\",\"subclass-builtin\":\"FURB189\",\"sorted-min-max\":\"FURB192\",\"ambiguous-unicode-character-string\":\"RUF001\",\"ambiguous-unicode-character-docstring\":\"RUF002\",\"ambiguous-unicode-character-comment\":\"RUF003\",\"collection-literal-concatenation\":\"RUF005\",\"asyncio-dangling-task\":\"RUF006\",\"zip-instead-of-pairwise\":\"RUF007\",\"mutable-dataclass-default\":\"RUF008\",\"function-call-in-dataclass-default-argument\":\"RUF009\",\"explicit-f-string-type-conversion\":\"RUF010\",\"ruff-static-key-dict-comprehension\":\"RUF011\",\"mutable-class-default\":\"RUF012\",\"implicit-optional\":\"RUF013\",\"unnecessary-iterable-allocation-for-first-element\":\"RUF015\",\"invalid-index-type\":\"RUF016\",\"quadratic-list-summation\":\"RUF017\",\"assignment-in-assert\":\"RUF018\",\"unnecessary-key-check\":\"RUF019\",\"never-union\":\"RUF020\",\"parenthesize-chained-operators\":\"RUF021\",\"unsorted-dunder-all\":\"RUF022\",\"unsorted-dunder-slots\":\"RUF023\",\"mutable-fromkeys-value\":\"RUF024\",\"default-factory-kwarg\":\"RUF026\",\"missing-f-string-syntax\":\"RUF027\",\"invalid-formatter-suppression-comment\":\"RUF028\",\"unused-async\":\"RUF029\",\"assert-with-print-message\":\"RUF030\",\"incorrectly-parenthesized-tuple-in-subscript\":\"RUF031\",\"decimal-from-float-literal\":\"RUF032\",\"post-init-default\":\"RUF033\",\"useless-if-else\":\"RUF034\",\"ruff-unsafe-markup-use\":\"RUF035\",\"none-not-at-end-of-union\":\"RUF036\",\"unnecessary-empty-iterable-within-deque-call\":\"RUF037\",\"redundant-bool-literal\":\"RUF038\",\"unraw-re-pattern\":\"RUF039\",\"invalid-assert-message-literal-argument\":\"RUF040\",\"unnecessary-nested-literal\":\"RUF041\",\"pytest-raises-ambiguous-pattern\":\"RUF043\",\"implicit-class-var-in-dataclass\":\"RUF045\",\"unnecessary-cast-to-int\":\"RUF046\",\"needless-else\":\"RUF047\",\"map-int-version-parsing\":\"RUF048\",\"dataclass-enum\":\"RUF049\",\"if-key-in-dict-del\":\"RUF051\",\"used-dummy-variable\":\"RUF052\",\"class-with-mixed-type-vars\":\"RUF053\",\"indented-form-feed\":\"RUF054\",\"unnecessary-regular-expression\":\"RUF055\",\"falsy-dict-get-fallback\":\"RUF056\",\"unnecessary-round\":\"RUF057\",\"starmap-zip\":\"RUF058\",\"unused-unpacked-variable\":\"RUF059\",\"in-empty-collection\":\"RUF060\",\"legacy-form-pytest-raises\":\"RUF061\",\"access-annotations-from-class-dict\":\"RUF063\",\"non-octal-permissions\":\"RUF064\",\"logging-eager-conversion\":\"RUF065\",\"property-without-return\":\"RUF066\",\"unused-noqa\":\"RUF100\",\"redirected-noqa\":\"RUF101\",\"invalid-rule-code\":\"RUF102\",\"invalid-pyproject-toml\":\"RUF200\",\"raise-vanilla-class\":\"TRY002\",\"raise-vanilla-args\":\"TRY003\",\"type-check-without-type-error\":\"TRY004\",\"reraise-no-cause\":\"TRY200\",\"verbose-raise\":\"TRY201\",\"useless-try-except\":\"TRY203\",\"try-consider-else\":\"TRY300\",\"raise-within-try\":\"TRY301\",\"error-instead-of-exception\":\"TRY400\",\"verbose-log-message\":\"TRY401\"},\"executable\":\"/usr/bin/ruff\",\"timestamp\":1764870647}" - } -} - - - - - - - - - - - - - - - 1765408336190 - - - - \ No newline at end of file diff --git a/src/vts-gampad-input/main.py b/src/vts-gampad-input/main.py index b0ce1a7..2f4a53b 100755 --- a/src/vts-gampad-input/main.py +++ b/src/vts-gampad-input/main.py @@ -1,10 +1,34 @@ #! /usr/bin/env python import asyncio +import time + import inquirer from inputs import GamePad, devices from vts_connection import VTSConnection +# initiate gamepad buttons +dpad_up, dpad_down, dpad_left, dpad_right = (0.0, 0.0, 0.0, 0.0) +action_up, action_down, action_left, action_right = (0.0, 0.0, 0.0, 0.0) +button_start, button_select = (0.0, 0.0) +button_l1, button_l2, button_l3 = (0.0, 0.0, 0.0) +button_r1, button_r2, button_r3 = (0.0, 0.0, 0.0) +left_stick_x_axis, left_stick_y_axis, right_stick_x_axis, right_stick_y_axis = ( + 0.0, + 0.0, + 0.0, + 0.0, +) +left_button_pressed, right_button_pressed, left_button_hold, right_button_hold = ( + 0.0, + 0.0, + 0.0, + 0.0, +) +left_thumb_stick, right_thumb_stick = (0.0, 0.0) +left_thumb_X, right_thumb_X, left_thumb_Y, right_thumb_Y = (0.0, 0.0, 0.0, 0.0) +left_index, right_index = (0.0, 0.0) + def _get_gamepads() -> list[GamePad]: """Get list of connected gamepad""" @@ -39,14 +63,8 @@ def select_gamepad() -> GamePad | None: return gamepads[0] -def _in_deadzone(analog_value: int, percentage: float = 10) -> bool: - center: float = 255 / 2 - dead_range = center * (percentage / 100) - - if center - dead_range < analog_value < center + dead_range: - return True - else: - return False +def _deadzone(analog_value: float, deadzone: float = 0.1) -> float: + return 0 if abs(analog_value) < deadzone else analog_value def _normalize_analog_sticks(analog_value: float) -> float: @@ -64,31 +82,194 @@ def _normalize_analog_trigger(analog_value: float) -> float: return formula -def main() -> None: +def set_inputs(code: str, state: float) -> None: + global dpad_up, dpad_down, dpad_left, dpad_right + global action_up, action_down, action_left, action_right + global left_stick_x_axis, left_stick_y_axis, right_stick_x_axis, right_stick_y_axis + global button_start, button_l1, button_l2, button_l3 + global button_select, button_r1, button_r2, button_r3 + global left_thumb_stick, right_thumb_stick + global left_thumb_X, right_thumb_X, left_thumb_Y, right_thumb_Y + global left_index, right_index + global \ + left_button_pressed, \ + right_button_pressed, \ + left_button_hold, \ + right_button_hold + + if code == "ABS_HAT0Y": + dpad_up = state * -1 if state < 0 else 0 + dpad_down = state if state > 0 else 0 + + elif code == "ABS_HAT0X": + dpad_left = state * -1 if state < 0 else 0 + dpad_right = state if state > 0 else 0 + + elif code == "ABS_X": + left_stick_x_axis = state + + elif code == "ABS_Y": + left_stick_y_axis = state * -1 + + elif code == "ABS_RX": + right_stick_x_axis = state + + elif code == "ABS_RY": + right_stick_y_axis = state * -1 + + elif code == "ABS_Z": + button_l2 = state + + elif code == "ABS_RZ": + button_r2 = state + + elif code == "BTN_TL": + button_l1 = state + + elif code == "BTN_TR": + button_r1 = state + + elif code == "BTN_SOUTH": + action_down = state + + elif code == "BTN_WEST": + action_left = state + + elif code == "BTN_EAST": + action_right = state + + elif code == "BTN_NORTH": + action_up = state + + elif code == "BTN_THUMBL": + button_l3 = state + + elif code == "BTN_THUMBR": + button_r3 = state + + elif code == "BTN_START": + button_start = state + + elif code == "BTN_SELECT": + button_select = state + + left_button_pressed = dpad_left + dpad_up + dpad_down + dpad_right + right_button_pressed = action_left + action_right + action_up + action_down + + left_thumb_X = dpad_right - dpad_left if left_button_pressed >= 1 else 0 + left_thumb_Y = dpad_up - dpad_down if left_button_pressed >= 1 else 0 + right_thumb_X = action_right - action_left if right_button_pressed >= 1 else 0 + right_thumb_Y = action_up - action_down if right_button_pressed >= 1 else 0 + + left_thumb_stick = ( + 1 + if dpad_down == dpad_up == dpad_left == dpad_right == 0 or button_l3 == 1 + else 0 + ) + right_thumb_stick = ( + 1 + if action_up == action_down == action_left == action_right == 0 + or button_r3 == 1 + else 0 + ) + + left_index = 1 if button_l1 == 0 else 0 + right_index = 1 if button_r1 == 0 else 0 + + +def create_vts_input_request() -> list[dict]: + params = [ + {"id": "NP_ON", "value": 1.0, "weight": 1.0}, + {"id": "NP_DPadDown", "value": dpad_down, "weight": 1.0}, + {"id": "NP_DPadUp", "value": dpad_up, "weight": 1.0}, + {"id": "NP_DPadLeft", "value": dpad_left, "weight": 1.0}, + {"id": "NP_DPadRight", "value": dpad_right, "weight": 1.0}, + {"id": "NP_ButtonA", "value": action_down, "weight": 1.0}, + {"id": "NP_ButtonB", "value": action_right, "weight": 1.0}, + {"id": "NP_ButtonX", "value": action_left, "weight": 1.0}, + {"id": "NP_ButtonY", "value": action_up, "weight": 1.0}, + {"id": "NP_StartDown", "value": button_start, "weight": 1.0}, + {"id": "NP_SelectDown", "value": button_select, "weight": 1.0}, + {"id": "NP_ButtonLS", "value": button_l3, "weight": 1.0}, + {"id": "NP_ButtonRS", "value": button_r3, "weight": 1.0}, + {"id": "NP_L1", "value": button_l1, "weight": 1.0}, + {"id": "NP_R1", "value": button_r1, "weight": 1.0}, + {"id": "NP_L2", "value": button_l2, "weight": 1.0}, + {"id": "NP_R2", "value": button_r2, "weight": 1.0}, + {"id": "NP_LStickX", "value": left_stick_x_axis, "weight": 1.0}, + {"id": "NP_LStickY", "value": left_stick_y_axis, "weight": 1.0}, + {"id": "NP_RStickX", "value": right_stick_x_axis, "weight": 1.0}, + {"id": "NP_RStickY", "value": right_stick_y_axis, "weight": 1.0}, + {"id": "NP_LButtonDown", "value": left_button_pressed, "weight": 1.0}, + {"id": "NP_RButtonDown", "value": right_button_pressed, "weight": 1.0}, + {"id": "NP_LButtonPress", "value": left_button_pressed, "weight": 1.0}, + {"id": "NP_RButtonPress", "value": right_button_pressed, "weight": 1.0}, + {"id": "NP_LThumbX", "value": left_thumb_X, "weight": 1.0}, + {"id": "NP_LThumbY", "value": left_thumb_Y, "weight": 1.0}, + {"id": "NP_RThumbX", "value": right_thumb_X, "weight": 1.0}, + {"id": "NP_RThumbY", "value": right_thumb_Y, "weight": 1.0}, + {"id": "NP_LOnStick", "value": left_thumb_stick, "weight": 1.0}, + {"id": "NP_ROnStick", "value": right_thumb_stick, "weight": 1.0}, + {"id": "NP_LIndexPos", "value": left_index, "weight": 1.0}, + {"id": "NP_RIndexPos", "value": right_index, "weight": 1.0}, + ] + + return params + + +async def main() -> None: gamepad = select_gamepad() - connection = VTSConnection() + vts = VTSConnection() + try: + await vts.connect() + except asyncio.CancelledError: + await vts.close() + + axis_states = { + "ABS_X": 0.0, + "ABS_Y": 0.0, + "ABS_RX": 0.0, + "ABS_RY": 0.0, + } + + trigger_states = { + "ABS_Z": 0.0, + "ABS_RZ": 0.0, + } + + last_time = time.monotonic() + frequency = 1 / 30 while True: for event in gamepad.read(): if event.code != "SYN_REPORT": - # Add some deadzone of about 5% to analog stick + # Add some deadzone of about 10% to analog stick if event.code in ["ABS_X", "ABS_Y", "ABS_RX", "ABS_RY"]: - if not _in_deadzone(analog_value=event.state): - print( - f"{event.ev_type} {event.code} {_normalize_analog_sticks(analog_value=event.state)}" - ) - elif event.code in ["ABS_Z", "ABS_RZ"]: - print( - f"{event.ev_type} {event.code} {_normalize_analog_trigger(event.state)}" + axis_states[event.code] = _deadzone( + _normalize_analog_sticks(event.state) ) + elif event.code in ["ABS_Z", "ABS_RZ"]: + trigger_states[event.code] = _normalize_analog_trigger(event.state) else: - print(event.ev_type, event.code, event.state) + set_inputs(event.code, event.state) - asyncio.run(connection.update_parameters(event.code, event.state)) + now = time.monotonic() + if now - last_time >= frequency: + last_time = now + + for key in trigger_states: + set_inputs(key, trigger_states[key]) + for key in axis_states: + set_inputs(key, axis_states[key]) + + input_data = create_vts_input_request() + await vts.update_parameters(input_data) + + await asyncio.sleep(0.001) if __name__ == "__main__": try: - main() + asyncio.run(main()) except KeyboardInterrupt: exit(0) diff --git a/src/vts-gampad-input/vts_connection.py b/src/vts-gampad-input/vts_connection.py index 4a57aa9..0d5fd98 100755 --- a/src/vts-gampad-input/vts_connection.py +++ b/src/vts-gampad-input/vts_connection.py @@ -4,21 +4,57 @@ import asyncio import os import pyvts +AUTHOR = "Melody LaFae" +PLUGIN_NAME = "VTS Gamepad Input" + +token_path = f"{os.environ['HOME']}/.vts-gamepad-input-token" +ip_path = f"{os.environ['HOME']}/.vts-gamepad-input-ip" + plugin_info = { - "plugin_name": "vts-gampad-input", - "developer": "Melody LaFae", - "authentication_token_path": f"{os.environ['HOME']}/.vts-gampad-authentication-token", + "plugin_name": PLUGIN_NAME, + "developer": AUTHOR, + "authentication_token_path": token_path, } class VTSConnection: def __init__(self): - self.vts = pyvts.vts(plugin_info=plugin_info) + self.vts = pyvts.vts( + plugin_info=plugin_info, vts_api_info=self._get_vts_api_info() + ) self.request = pyvts.VTSRequest(plugin_info=plugin_info) - if asyncio.run(self._connect()): - asyncio.run(self._create_vts_params()) - async def _connect(self) -> bool: + async def connect(self): + conn_success = await self._connect_to_api() + if conn_success: + await self._create_vts_params() + await self.close() + + async def close(self): + await self.vts.close() + + @staticmethod + def _get_vts_api_info() -> dict[str, str]: + host_uri = "ws://localhost:8001" + vts_api_info: dict[str, str] = {} + + if os.path.exists(ip_path) and os.path.isfile(ip_path): + with open(ip_path, "r") as file: + host_uri = file.read() + else: + with open(ip_path, "w") as file: + file.write(host_uri) + + host_url = host_uri.split(":")[1].replace("//", "") + host_port = host_uri.split(":")[2] + vts_api_info["host"] = host_url + vts_api_info["port"] = host_port + vts_api_info["name"] = "VTubeStudioPublicAPI" + vts_api_info["version"] = "1.0" + + return vts_api_info + + async def _connect_to_api(self) -> bool: try: await self.vts.connect() except OSError: @@ -27,7 +63,14 @@ class VTSConnection: await self.vts.request_authenticate_token() await self.vts.request_authenticate() - connection_success = await self.vts.request( + if not self.vts.get_connection_status(): + raise ConnectionError("Connection failed") + else: + return True + + async def _create_vts_params(self) -> None: + # Param to enable or disable inputs + await self.vts.request( self.request.requestCustomParameter( parameter="NP_ON", info="VTS Gamepad Input Enabled", @@ -36,37 +79,327 @@ class VTSConnection: default_value=0.0, ) ) - - if not connection_success: - raise ConnectionError("Connection failed") - else: - return True - - async def _create_vts_params(self): - params: list[dict] = [ + # DPad params + await self.vts.request( self.request.requestCustomParameter( - parameter="NP_LButtonDown", - info="Left side face buttons down", + parameter="NP_DPadDown", + info="DPad Down pressed", + min=0.0, + max=1.0, + default_value=0.0, + ) + ) + await self.vts.request( + self.request.requestCustomParameter( + parameter="NP_DPadLeft", + info="DPad Left pressed", min=0.0, max=1.0, default_value=0.0, ), + ) + await self.vts.request( self.request.requestCustomParameter( - parameter="NP_LButtonDown", - info="Left side face buttons down", + parameter="NP_DPadUp", + info="DPad Up pressed", min=0.0, max=1.0, default_value=0.0, ), - ] + ) + await self.vts.request( + self.request.requestCustomParameter( + parameter="NP_DPadRight", + info="DPad Right pressed", + min=0.0, + max=1.0, + default_value=0.0, + ), + ) + # Action Buttons params + await self.vts.request( + self.request.requestCustomParameter( + parameter="NP_ButtonA", + info="Down Action button pressed (XBox A, PS Cross)", + min=0.0, + max=1.0, + default_value=0.0, + ), + ) + await self.vts.request( + self.request.requestCustomParameter( + parameter="NP_ButtonB", + info="Right Action button pressed (XBox B, PS Circle)", + min=0.0, + max=1.0, + default_value=0.0, + ), + ) + await self.vts.request( + self.request.requestCustomParameter( + parameter="NP_ButtonY", + info="Up Action button pressed (XBox Y, PS Triangle)", + min=0.0, + max=1.0, + default_value=0.0, + ), + ) + await self.vts.request( + self.request.requestCustomParameter( + parameter="NP_ButtonX", + info="Left Action button pressed (XBox X, PS Square)", + min=0.0, + max=1.0, + default_value=0.0, + ), + ) + # Shoulder buttons params + await self.vts.request( + self.request.requestCustomParameter( + parameter="NP_L1", + info="Left front shoulder button pressed (XBox LB, PS L1, Switch L)", + min=0.0, + max=1.0, + default_value=0.0, + ), + ) + await self.vts.request( + self.request.requestCustomParameter( + parameter="NP_L2", + info="Left back shoulder button pressed (XBox LT, PS L2, Switch ZL)", + min=0.0, + max=1.0, + default_value=0.0, + ), + ) + await self.vts.request( + self.request.requestCustomParameter( + parameter="NP_R1", + info="Right front shoulder button pressed (XBox RB, PS R1, Switch R)", + min=0.0, + max=1.0, + default_value=0.0, + ), + ) + await self.vts.request( + self.request.requestCustomParameter( + parameter="NP_R2", + info="Right back shoulder button pressed (XBox RT, PS R2, Switch ZR)", + min=0.0, + max=1.0, + default_value=0.0, + ), + ) + # Start and select params + await self.vts.request( + self.request.requestCustomParameter( + parameter="NP_StartDown", + info="Start button pressed", + min=0.0, + max=1.0, + default_value=0.0, + ), + ) + await self.vts.request( + self.request.requestCustomParameter( + parameter="NP_SelectDown", + info="Select button pressed", + min=0.0, + max=1.0, + default_value=0.0, + ), + ) + # Left Analog stick param + await self.vts.request( + self.request.requestCustomParameter( + parameter="NP_LStickX", + info="Left stick moved on X axis", + min=-1.0, + max=1.0, + default_value=0.0, + ), + ) + await self.vts.request( + self.request.requestCustomParameter( + parameter="NP_LStickY", + info="Left stick moved on Y axis", + min=-1.0, + max=1.0, + default_value=0.0, + ), + ) + await self.vts.request( + self.request.requestCustomParameter( + parameter="NP_ButtonLS", + info="Left analog stick pressed", + min=0.0, + max=1.0, + default_value=0.0, + ), + ) + # Right Analog stick params + await self.vts.request( + self.request.requestCustomParameter( + parameter="NP_RStickX", + info="Right stick moved on X axis", + min=-1.0, + max=1.0, + default_value=0.0, + ), + ) + await self.vts.request( + self.request.requestCustomParameter( + parameter="NP_RStickY", + info="Right stick moved on Y axis", + min=-1.0, + max=1.0, + default_value=0.0, + ), + ) + await self.vts.request( + self.request.requestCustomParameter( + parameter="NP_ButtonRS", + info="Right analog stick pressed", + min=0.0, + max=1.0, + default_value=0.0, + ), + ) + ## Rigging Logic params + # Thumb on sticks if no buttons are pressed + await self.vts.request( + self.request.requestCustomParameter( + parameter="NP_LOnStick", + info="Left thumb on left analog stick", + min=0.0, + max=1.0, + default_value=0.0, + ), + ) + await self.vts.request( + self.request.requestCustomParameter( + parameter="NP_ROnStick", + info="Right thumb on right analog stick", + min=0.0, + max=1.0, + default_value=0.0, + ), + ) + # Thumb locations + await self.vts.request( + self.request.requestCustomParameter( + parameter="NP_LThumbX", + info="Left thumb movement on X axis", + min=-1.0, + max=1.0, + default_value=0.0, + ), + ) + await self.vts.request( + self.request.requestCustomParameter( + parameter="NP_LThumbY", + info="Left thumb movement on Y axis", + min=-1.0, + max=1.0, + default_value=0.0, + ), + ) + await self.vts.request( + self.request.requestCustomParameter( + parameter="NP_RThumbX", + info="Right thumb movement on X axis", + min=-1.0, + max=1.0, + default_value=0.0, + ), + ) + await self.vts.request( + self.request.requestCustomParameter( + parameter="NP_RThumbY", + info="Right thumb movement on Y axis", + min=-1.0, + max=1.0, + default_value=0.0, + ), + ) + # Index finger location + await self.vts.request( + self.request.requestCustomParameter( + parameter="NP_LIndexPos", + info="Left index finger position (on L2/LT/ZL if L1 not pressed)", + min=0.0, + max=1.0, + default_value=0.0, + ), + ) + await self.vts.request( + self.request.requestCustomParameter( + parameter="NP_RIndexPos", + info="Right index finger position (on R2/RT/ZR if R1 not pressed)", + min=0.0, + max=1.0, + default_value=0.0, + ), + ) + # Button pressed or hold params + await self.vts.request( + self.request.requestCustomParameter( + parameter="NP_LButtonPress", + info="Left button pressed", + min=0.0, + max=1.0, + default_value=0.0, + ), + ) + await self.vts.request( + self.request.requestCustomParameter( + parameter="NP_RButtonPress", + info="Right button pressed", + min=0.0, + max=1.0, + default_value=0.0, + ), + ) + await self.vts.request( + self.request.requestCustomParameter( + parameter="NP_LButtonDown", + info="Left button hold", + min=0.0, + max=1.0, + default_value=0.0, + ), + ) + await self.vts.request( + self.request.requestCustomParameter( + parameter="NP_RButtonDown", + info="Right button hold", + min=0.0, + max=1.0, + default_value=0.0, + ) + ) - async def update_parameters(self, button: str, value: float) -> None: - pass + async def update_parameters(self, parameters: list[dict]) -> None: + await self._connect_to_api() + request = self.request.BaseRequest( + data={ + "faceFound": False, + "mode": "set", + "parameterValues": parameters, + }, + message_type="InjectParameterDataRequest", + ) + await self.vts.request(request) + await self.close() -def main(): - VTSConnection() +async def main(): + vts_conn = VTSConnection() + await vts_conn.vts.connect() + await vts_conn.vts.request_authenticate_token() + # await vts_conn.vts.request_authenticate() + # await vts_conn.connect() if __name__ == "__main__": - main() + asyncio.run(main())