This is the multi-page printable view of this section. Click here to print.
Docs
- 1: Projects
- 1.1: ActivityWatch ingester Android
- 1.1.1:
- 1.1.1.1: head
- 1.2: Agents
- 1.3: Al
- 1.3.1: Command and plugin lifecycle
- 1.3.2: Releases
- 1.3.2.1: head
- 1.3.3: Rules
- 1.3.3.1: Bzl
- 1.3.3.1.1: al_config
- 1.3.3.1.2: al_toolchain
- 1.3.3.1.3: al_toolchain_resolved
- 1.4: Alwaldend.com
- 1.5: Android launcher
- 1.6: Ansible collection
- 1.6.1: Playbooks
- 1.6.2: Roles
- 1.6.2.1: Adguard
- 1.6.2.1.1: Defaults
- 1.6.2.2: Caddy
- 1.6.2.2.1: Defaults
- 1.6.2.3: CIFS
- 1.6.2.3.1: Defaults
- 1.6.2.4: Consul
- 1.6.2.4.1: Defaults
- 1.6.2.5: Consul
- 1.6.2.5.1: Defaults
- 1.6.2.6: Consul envoy
- 1.6.2.6.1: Defaults
- 1.6.2.7: Dev VM
- 1.6.2.7.1: Defaults
- 1.6.2.8: DNS
- 1.6.2.8.1: Defaults
- 1.6.2.9: Docker
- 1.6.2.9.1: Defaults
- 1.6.2.10: Facts
- 1.6.2.10.1: Defaults
- 1.6.2.11: Filesystem
- 1.6.2.11.1: Defaults
- 1.6.2.12: Firewall
- 1.6.2.12.1: Defaults
- 1.6.2.13: Forgejo
- 1.6.2.13.1: Defaults
- 1.6.2.14: Forgejo
- 1.6.2.14.1: Defaults
- 1.6.2.15: Forgejo runner
- 1.6.2.15.1: Defaults
- 1.6.2.16: Gpg
- 1.6.2.16.1: Defaults
- 1.6.2.17: Harboer
- 1.6.2.17.1: Defaults
- 1.6.2.18: Hermes
- 1.6.2.18.1: Defaults
- 1.6.2.19: Hiddify manager
- 1.6.2.19.1: Defaults
- 1.6.2.20: Hiddify manager with host
- 1.6.2.20.1: Defaults
- 1.6.2.21: Host
- 1.6.2.21.1: Defaults
- 1.6.2.22: Install CA
- 1.6.2.22.1: Defaults
- 1.6.2.23: K3s
- 1.6.2.23.1: Defaults
- 1.6.2.24: K3s bootstrap
- 1.6.2.24.1: Defaults
- 1.6.2.25: K3s cluster
- 1.6.2.25.1: Defaults
- 1.6.2.26: K3s kubeconfig
- 1.6.2.26.1: Defaults
- 1.6.2.27: lvg
- 1.6.2.27.1: Defaults
- 1.6.2.28: lvol
- 1.6.2.28.1: Defaults
- 1.6.2.29: Mount
- 1.6.2.29.1: Defaults
- 1.6.2.30: Opencode
- 1.6.2.30.1: Defaults
- 1.6.2.31: OpenHands automation
- 1.6.2.31.1: Defaults
- 1.6.2.32: OpenHands canvas
- 1.6.2.32.1: Defaults
- 1.6.2.33: Openhands server
- 1.6.2.33.1: Defaults
- 1.6.2.34: OS
- 1.6.2.34.1: Defaults
- 1.6.2.35: Posgresql
- 1.6.2.35.1: Defaults
- 1.6.2.36: Pve
- 1.6.2.36.1: Defaults
- 1.6.2.37: PVE cluster
- 1.6.2.37.1: Defaults
- 1.6.2.38: PVE VM
- 1.6.2.38.1: Defaults
- 1.6.2.39: PVE VM remove
- 1.6.2.39.1: Defaults
- 1.6.2.40: Raspberry pi
- 1.6.2.40.1: Defaults
- 1.6.2.41: SSH
- 1.6.2.41.1: Defaults
- 1.6.2.42: SSH port forwarding
- 1.6.2.42.1: Defaults
- 1.6.2.43: SSH update known hosts
- 1.6.2.43.1: Defaults
- 1.6.2.44: T3 Code
- 1.6.2.44.1: Defaults
- 1.6.2.45: Traefik
- 1.6.2.45.1: Defaults
- 1.6.2.46: Traefik (old)
- 1.6.2.46.1: Defaults
- 1.6.2.47: Update all packages
- 1.6.2.47.1: Defaults
- 1.6.2.48: Users
- 1.6.2.48.1: Defaults
- 1.6.2.49: Vault
- 1.6.2.49.1: Defaults
- 1.6.2.50: Wireguard
- 1.6.2.50.1: Defaults
- 1.6.2.51: Xray
- 1.6.2.51.1: Defaults
- 1.7: Autoscroll
- 1.8: Bazel agent
- 1.9: Ci platform
- 1.10: Dotfiles
- 1.11: Infinitime
- 1.12: Kustomization
- 1.13: Leetcode downloader
- 1.13.1: Bzl
- 1.13.1.1: al_leetcode_submissions
- 1.13.2: Proto
- 1.13.2.1: contracts
- 1.13.3: Releases
- 1.13.3.1: head
- 1.14: MCP Cordis
- 1.15: Nexus security plugin
- 1.16: Renders
- 1.17: Sri
- 1.18: Tf modules
- 1.18.1:
- 1.18.2:
- 1.18.3:
- 1.18.4: Backup bucket
- 1.18.5: DNS records
- 1.18.5.1: DNS normalization
- 1.18.5.2: DNS test providers
- 1.18.5.3: Global DNS records
- 1.18.6: Pve vm qemu
- 1.18.7: Releases
- 1.18.7.1: head
- 1.18.8: Terraform backend
- 1.18.9: Vault approle
- 1.18.10: Vault approle
- 1.18.11: Vault OIDC provider
- 1.18.12: Vault pki server
- 1.18.13: Vault ssh server role
- 1.18.14: Vault transit key
- 1.18.15: Yc folder
- 1.19: Useless QT GUI
- 2: Infra
- 2.1: Architecture
- 2.2: Ceph
- 2.3: Cloud-init
- 2.4: Dns
- 2.4.1:
- 2.4.2: Cloudflare DNS
- 2.4.3: Mikrotik DNS
- 2.4.4: Shared DNS Terraform
- 2.5: flux
- 2.6: forgejo
- 2.7: Forgejo runner
- 2.7.1:
- 2.7.2:
- 2.7.3: Ansible
- 2.7.4: Terraform setup
- 2.8: GitHub
- 2.8.1:
- 2.8.2: GitHub Terraform
- 2.9: GitLab
- 2.9.1: GitLab Terraform
- 2.10: harbor
- 2.11: ingress
- 2.12: Mikrotik
- 2.13: Nas
- 2.14: OpenHands
- 2.15: Pve
- 2.16: Repositories
- 2.16.1:
- 2.16.2: Repository catalog module
- 2.17: Source repository
- 2.18: threexui
- 2.19: Vault
- 2.20: XCP-ng
- 2.20.1:
- 2.20.2:
- 2.20.3: Terraform
- 2.20.4: Xen Orchestra certificates
- 2.21: Yandex Cloud
- 3: Tools
- 3.1:
- 3.2:
- 3.3: Android
- 3.4: Android cmdtools
- 3.5: Ansible
- 3.6: Ast-grep
- 3.7: Bazel configs
- 3.8: Bazel shell worker
- 3.8.1: Bzl
- 3.8.1.1: al_genrule
- 3.8.1.2: al_genrule_rule
- 3.9: Bazelrc
- 3.10: Black
- 3.11: Blender
- 3.12: Buf
- 3.13: Buildifier
- 3.14: Bzl
- 3.14.1: Bzl
- 3.14.1.1: al_alias_map
- 3.14.1.2: al_bzl_generate_repository
- 3.14.1.3: al_bzl_library_map
- 3.14.1.4: al_bzl_target_doc
- 3.14.1.5: al_genquery_write_to_source_file
- 3.15: Bzlenv
- 3.15.1: Bzl
- 3.15.1.1: al_bzlenv_binary
- 3.16: Cc
- 3.17: Cloc
- 3.18: Cmctl
- 3.19: Consul
- 3.19.1: Gen gossip key
- 3.20: Dart Sass
- 3.21: Dnscontrol
- 3.22: Drawio
- 3.22.1: Bzl
- 3.22.1.1: al_drawio_run_binary
- 3.22.1.2: al_drawio_toolchain
- 3.23: F-Droid
- 3.24: File installer
- 3.25: fj
- 3.26: Flake8
- 3.27: flux
- 3.28: Flux operator
- 3.29: Forgejo
- 3.30: Gazelle
- 3.31: Gh
- 3.32: Git
- 3.32.1: Bzl
- 3.32.1.1: al_git_binary
- 3.32.1.2: al_git_changelog
- 3.32.1.3: al_git_current_state
- 3.32.1.4: al_git_extension
- 3.32.1.5: al_git_info_file
- 3.32.1.6: al_git_repo
- 3.32.1.7: al_git_resolved_toolchain
- 3.32.1.8: al_git_run_binary
- 3.32.1.9: al_git_toolchain
- 3.32.2: Proto
- 3.32.2.1: contracts
- 3.33: Git filter repo
- 3.34: Gitea
- 3.35: Glab
- 3.36: Go
- 3.36.1: Bzl
- 3.36.1.1: al_go_repository
- 3.37: go_mod
- 3.38: Gzip
- 3.38.1: Bzl
- 3.38.1.1: al_gzip_extension
- 3.38.1.2: al_gzip_repo
- 3.39: Harbor
- 3.40: Helm
- 3.40.1: Bzl
- 3.40.1.1: al_helm_binary
- 3.40.1.2: al_helm_chart
- 3.40.1.3: al_helm_chart_info
- 3.40.1.4: al_helm_chart_lock
- 3.40.1.5: al_helm_cmds
- 3.40.1.6: al_helm_deps
- 3.40.1.7: al_helm_deps_repo
- 3.40.1.8: al_helm_toolchain
- 3.41: Hermes install
- 3.42: Hooks
- 3.43: Http server
- 3.43.1: Bzl
- 3.43.1.1: al_http_server_binary
- 3.44: Hugo
- 3.45: Install file
- 3.45.1: Bzl
- 3.45.1.1: al_install_file
- 3.46: Isort
- 3.47: Js
- 3.48: Kt
- 3.49: kubectl
- 3.50: Lua
- 3.50.1: Bzl
- 3.50.1.1: al_lua_library
- 3.51: Make install
- 3.51.1: Bzl
- 3.51.1.1: al_make_install
- 3.51.1.2: al_make_install_binary
- 3.51.1.3: al_make_install_filegroup
- 3.51.1.4: al_make_install_filegroup_info
- 3.52: Maven Install Gradle Converter
- 3.53: Md
- 3.53.1: Bzl
- 3.53.1.1: al_md_data
- 3.54: Mermaid
- 3.55: Minisign
- 3.56: Mypy
- 3.57: Nc
- 3.58: Nmap
- 3.59: Nogo
- 3.60: Nping
- 3.61: Oci
- 3.62: openbao
- 3.63: Opencode
- 3.64: OpenSpec
- 3.65: Ops
- 3.66: Oras
- 3.67: Patch
- 3.67.1: Bzl
- 3.67.1.1: al_apply_patches
- 3.68: Pkg
- 3.68.1: Bzl
- 3.68.1.1: al_genrule_src
- 3.68.1.2: al_pkg_basic_naming
- 3.68.1.3: al_pkg_extract_dir
- 3.68.1.4: al_pkg_tar_combined
- 3.68.1.5: al_unpack_archives
- 3.69: Pkgsite
- 3.70: Pnpm
- 3.71: Postcss
- 3.72: Prettier
- 3.73: Print deps
- 3.73.1: Bzl
- 3.73.1.1: al_print_deps
- 3.74: Proto
- 3.74.1: Bzl
- 3.74.1.1: al_proto_docs
- 3.75: Py
- 3.75.1: Bzl
- 3.75.1.1: al_compile_pip_requirements_combined
- 3.75.1.2: al_genrule_with_wheels
- 3.75.1.3: al_py_binary_shell
- 3.75.1.4: al_py_checker
- 3.75.1.5: al_py_checkers
- 3.76: Qt
- 3.76.1: Bzl
- 3.77: Rclone
- 3.78: Readme tree
- 3.79: Release
- 3.79.1: Bzl
- 3.79.1.1: al_release
- 3.79.1.2: al_release_binary
- 3.79.1.3: al_release_deployment
- 3.79.1.4: al_release_deployment_info
- 3.79.1.5: al_release_deps
- 3.79.1.6: al_release_files
- 3.79.1.7: al_release_files_info
- 3.79.1.8: al_release_info
- 3.79.2: Proto
- 3.79.2.1: contracts
- 3.80: Replace section
- 3.81: Repo map
- 3.81.1: Bzl
- 3.81.1.1: al_repo_map
- 3.82: Repository AL configuration
- 3.83: Repository delivery
- 3.84: Repository quality
- 3.85: Resolved toolchain
- 3.85.1: Bzl
- 3.85.1.1: al_resolved_toolchain
- 3.86: Rfc
- 3.86.1: Bzl
- 3.86.1.1: al_rfc_extension
- 3.86.1.2: al_rfc_repo
- 3.87: Root Bazel module
- 3.88: Rules binary toolchain
- 3.88.1:
- 3.88.2:
- 3.88.3: Bzl
- 3.89: Rules Dnscontrol
- 3.90: Rules docs
- 3.91: Rules docs Gazelle
- 3.92: Rules Hugo
- 3.93: Rules Promptfoo
- 3.94: Rules Promptfoo Gazelle
- 3.95: Rules skill
- 3.96: Rules skill Gazelle
- 3.97: Rules template
- 3.97.1:
- 3.97.2:
- 3.97.3: Bzl
- 3.98: Rules Terraform
- 3.98.1:
- 3.98.2: Terraform launcher
- 3.99: rules_iso
- 3.100: Run tool
- 3.100.1: Bzl
- 3.100.1.1: al_run_tool
- 3.101: Selene
- 3.102: Sh
- 3.102.1: Bzl
- 3.102.1.1: al_sh_library
- 3.102.1.2: al_write_script
- 3.103: Shellcheck
- 3.104: Shfmt
- 3.105: Sops
- 3.106: Stylua
- 3.107: Taplo
- 3.108: Toml
- 3.108.1: Bzl
- 3.108.1.1: al_toml_data
- 3.108.1.2: al_toml_info
- 3.108.1.3: al_toml_validate
- 3.109: Tomlv
- 3.110: Traefik
- 3.111: Transitive sources
- 3.111.1: Bzl
- 3.111.1.1: al_transitive_sources
- 3.112: Trufflehog
- 3.113: Twine
- 3.114: Txt
- 3.114.1: Bzl
- 3.114.1.1: al_combine_files
- 3.114.1.2: al_txt_data
- 3.115: Vault
- 3.115.1: Backup
- 3.115.2: Forgejo login
- 3.115.2.1: api
- 3.115.3: Gen client cert
- 3.115.4: Gen root token
- 3.115.5: Harbor login
- 3.115.5.1: api
- 3.115.6: Injector
- 3.115.6.1: api
- 3.115.7: Login
- 3.115.8: PVE login
- 3.115.8.1: api
- 3.115.9: Tf backend
- 3.115.9.1: api
- 3.115.10: Unseal
- 3.116: Versioning
- 3.117: Vial
- 3.117.1: Bzl
- 3.117.1.1: al_vial_configs
- 3.118: Word lists
- 3.119: Workspace status
- 3.120: Ykman
- 4: Misc
- 4.1: Android
- 4.2: Bazel
- 4.3: Books
- 4.4: Glossary
- 4.5: Gnome boxes
- 4.6: Hugo
- 4.7: Leetcode submissions
- 4.7.1: 2026-04-11 20:57:04 +0300 MSK
- 4.7.2: 2026-04-10 21:12:54 +0300 MSK
- 4.7.3: 2026-04-09 22:31:40 +0300 MSK
- 4.7.4: 2026-04-08 20:09:31 +0300 MSK
- 4.7.5: 2026-04-07 20:43:50 +0300 MSK
- 4.7.6: 2026-04-06 20:15:21 +0300 MSK
- 4.7.7: 2026-04-06 20:14:55 +0300 MSK
- 4.7.8: 2026-04-04 20:41:56 +0300 MSK
- 4.7.9: 2026-04-03 22:48:45 +0300 MSK
- 4.7.10: 2026-04-02 19:46:57 +0300 MSK
- 4.7.11: 2026-04-01 20:54:07 +0300 MSK
- 4.7.12: 2026-03-31 23:43:31 +0300 MSK
- 4.7.13: 2026-03-30 19:50:10 +0300 MSK
- 4.7.14: 2026-03-29 23:45:59 +0300 MSK
- 4.7.15: 2026-03-28 19:49:17 +0300 MSK
- 4.7.16: 2026-03-27 09:35:17 +0300 MSK
- 4.7.17: 2026-03-26 21:00:59 +0300 MSK
- 4.7.18: 2026-03-25 23:26:40 +0300 MSK
- 4.7.19: 2026-03-25 23:26:14 +0300 MSK
- 4.7.20: 2026-03-23 21:09:09 +0300 MSK
- 4.7.21: 2026-03-22 15:36:46 +0300 MSK
- 4.7.22: 2026-03-21 19:43:30 +0300 MSK
- 4.7.23: 2026-03-20 19:36:10 +0300 MSK
- 4.7.24: 2026-03-19 23:36:34 +0300 MSK
- 4.7.25: 2026-03-18 20:01:58 +0300 MSK
- 4.7.26: 2026-03-17 21:22:16 +0300 MSK
- 4.7.27: 2026-03-16 21:13:19 +0300 MSK
- 4.7.28: 2026-03-15 16:53:42 +0300 MSK
- 4.7.29: 2026-03-14 21:37:31 +0300 MSK
- 4.7.30: 2026-03-13 20:46:12 +0300 MSK
- 4.7.31: 2026-03-12 19:11:46 +0300 MSK
- 4.7.32: 2026-03-11 21:48:29 +0300 MSK
- 4.7.33: 2026-03-10 21:15:05 +0300 MSK
- 4.7.34: 2026-03-09 19:32:26 +0300 MSK
- 4.7.35: 2026-03-08 19:12:47 +0300 MSK
- 4.7.36: 2026-03-07 13:13:17 +0300 MSK
- 4.7.37: 2026-03-06 19:47:33 +0300 MSK
- 4.7.38: 2026-03-05 21:05:59 +0300 MSK
- 4.7.39: 2026-03-04 20:10:10 +0300 MSK
- 4.7.40: 2026-03-03 20:16:05 +0300 MSK
- 4.7.41: 2026-03-03 09:50:42 +0300 MSK
- 4.7.42: 2026-03-03 09:49:36 +0300 MSK
- 4.7.43: 2026-03-03 09:49:19 +0300 MSK
- 4.7.44: 2026-03-01 18:20:27 +0300 MSK
- 4.7.45: 2026-03-01 18:20:02 +0300 MSK
- 4.7.46: 2026-02-28 10:54:54 +0300 MSK
- 4.7.47: 2026-02-27 21:53:34 +0300 MSK
- 4.7.48: 2026-02-26 20:44:53 +0300 MSK
- 4.7.49: 2026-02-25 21:05:52 +0300 MSK
- 4.7.50: 2026-02-24 19:51:26 +0300 MSK
- 4.7.51: 2026-02-23 18:14:19 +0300 MSK
- 4.7.52: 2026-02-22 17:40:07 +0300 MSK
- 4.7.53: 2026-02-21 18:56:25 +0300 MSK
- 4.7.54: 2026-02-21 18:55:40 +0300 MSK
- 4.7.55: 2026-02-19 20:42:48 +0300 MSK
- 4.7.56: 2026-02-18 20:35:40 +0300 MSK
- 4.7.57: 2026-02-17 20:18:33 +0300 MSK
- 4.7.58: 2026-02-16 19:40:12 +0300 MSK
- 4.7.59: 2026-02-15 20:58:12 +0300 MSK
- 4.7.60: 2026-02-14 12:54:19 +0300 MSK
- 4.7.61: 2026-02-13 09:19:20 +0300 MSK
- 4.7.62: 2026-02-12 19:02:27 +0300 MSK
- 4.7.63: 2026-02-11 20:12:38 +0300 MSK
- 4.7.64: 2026-02-10 13:02:01 +0300 MSK
- 4.7.65: 2026-02-09 20:09:17 +0300 MSK
- 4.7.66: 2026-02-08 13:23:59 +0300 MSK
- 4.7.67: 2026-02-07 18:17:37 +0300 MSK
- 4.7.68: 2026-02-06 20:36:14 +0300 MSK
- 4.7.69: 2026-02-05 15:26:43 +0300 MSK
- 4.7.70: 2026-02-04 18:39:04 +0300 MSK
- 4.7.71: 2026-02-03 21:24:01 +0300 MSK
- 4.7.72: 2026-02-03 14:14:39 +0300 MSK
- 4.7.73: 2026-02-03 14:11:12 +0300 MSK
- 4.7.74: 2026-02-03 14:06:32 +0300 MSK
- 4.7.75: 2026-02-03 13:54:07 +0300 MSK
- 4.7.76: 2026-02-03 12:24:12 +0300 MSK
- 4.7.77: 2026-02-02 18:52:16 +0300 MSK
- 4.7.78: 2026-02-01 19:46:21 +0300 MSK
- 4.7.79: 2026-02-01 19:45:22 +0300 MSK
- 4.7.80: 2026-01-31 21:17:17 +0300 MSK
- 4.7.81: 2026-01-30 20:30:09 +0300 MSK
- 4.7.82: 2026-01-29 22:21:59 +0300 MSK
- 4.7.83: 2026-01-28 20:51:42 +0300 MSK
- 4.7.84: 2026-01-27 22:11:38 +0300 MSK
- 4.7.85: 2026-01-26 20:02:52 +0300 MSK
- 4.7.86: 2026-01-25 21:10:14 +0300 MSK
- 4.7.87: 2026-01-24 19:43:56 +0300 MSK
- 4.7.88: 2026-01-23 20:09:20 +0300 MSK
- 4.7.89: 2026-01-22 19:21:03 +0300 MSK
- 4.7.90: 2026-01-22 18:45:34 +0300 MSK
- 4.7.91: 2026-01-22 18:41:51 +0300 MSK
- 4.7.92: 2026-01-22 18:07:41 +0300 MSK
- 4.7.93: 2026-01-22 10:20:58 +0300 MSK
- 4.7.94: 2026-01-20 11:39:04 +0300 MSK
- 4.7.95: 2026-01-19 12:02:06 +0300 MSK
- 4.7.96: 2026-01-18 17:30:31 +0300 MSK
- 4.7.97: 2026-01-18 16:48:45 +0300 MSK
- 4.7.98: 2026-01-16 19:37:40 +0300 MSK
- 4.7.99: 2026-01-15 17:40:29 +0300 MSK
- 4.7.100: 2026-01-14 22:52:51 +0300 MSK
- 4.7.101: 2026-01-13 19:03:15 +0300 MSK
- 4.7.102: 2026-01-12 10:11:59 +0300 MSK
- 4.7.103: 2026-01-11 13:52:04 +0300 MSK
- 4.7.104: 2026-01-11 08:25:47 +0300 MSK
- 4.7.105: 2026-01-10 14:26:29 +0300 MSK
- 4.7.106: 2026-01-10 14:23:41 +0300 MSK
- 4.7.107: 2026-01-10 14:04:15 +0300 MSK
- 4.7.108: 2026-01-10 12:50:38 +0300 MSK
- 4.7.109: 2026-01-10 12:34:56 +0300 MSK
- 4.7.110: 2026-01-10 12:32:09 +0300 MSK
- 4.7.111: 2026-01-10 12:31:07 +0300 MSK
- 4.7.112: 2026-01-10 12:28:57 +0300 MSK
- 4.7.113: 2026-01-09 15:34:38 +0300 MSK
- 4.7.114: 2026-01-09 13:31:31 +0300 MSK
- 4.7.115: 2026-01-09 11:15:58 +0300 MSK
- 4.7.116: 2026-01-08 22:11:32 +0300 MSK
- 4.7.117: 2026-01-08 19:05:53 +0300 MSK
- 4.7.118: 2026-01-08 17:17:32 +0300 MSK
- 4.7.119: 2026-01-08 15:42:20 +0300 MSK
- 4.7.120: 2026-01-07 21:40:08 +0300 MSK
- 4.7.121: 2026-01-07 19:46:02 +0300 MSK
- 4.7.122: 2026-01-07 18:35:43 +0300 MSK
- 4.7.123: 2026-01-07 15:39:17 +0300 MSK
- 4.7.124: 2026-01-07 15:23:44 +0300 MSK
- 4.7.125: 2026-01-07 14:29:52 +0300 MSK
- 4.7.126: 2026-01-07 13:23:43 +0300 MSK
- 4.7.127: 2026-01-07 13:23:17 +0300 MSK
- 4.7.128: 2026-01-07 12:50:50 +0300 MSK
- 4.7.129: 2026-01-07 11:11:18 +0300 MSK
- 4.7.130: 2026-01-06 23:04:34 +0300 MSK
- 4.7.131: 2026-01-06 22:19:43 +0300 MSK
- 4.7.132: 2026-01-06 21:39:35 +0300 MSK
- 4.7.133: 2026-01-06 21:10:32 +0300 MSK
- 4.7.134: 2026-01-06 19:37:48 +0300 MSK
- 4.7.135: 2026-01-06 12:16:09 +0300 MSK
- 4.7.136: 2026-01-06 10:05:37 +0300 MSK
- 4.7.137: 2026-01-05 18:58:31 +0300 MSK
- 4.7.138: 2026-01-05 14:24:49 +0300 MSK
- 4.7.139: 2026-01-05 12:30:08 +0300 MSK
- 4.7.140: 2026-01-04 21:18:13 +0300 MSK
- 4.7.141: 2026-01-03 13:57:12 +0300 MSK
- 4.7.142: 2026-01-02 16:54:09 +0300 MSK
- 4.7.143: 2026-01-02 16:49:02 +0300 MSK
- 4.7.144: 2026-01-02 10:21:34 +0300 MSK
- 4.7.145: 2026-01-01 13:06:44 +0300 MSK
- 4.7.146: 2026-01-01 13:05:15 +0300 MSK
- 4.7.147: 2026-01-01 12:27:10 +0300 MSK
- 4.7.148: 2025-12-31 18:07:08 +0300 MSK
- 4.7.149: 2025-12-30 21:07:43 +0300 MSK
- 4.7.150: 2025-12-29 19:39:26 +0300 MSK
- 4.7.151: 2025-12-28 16:38:30 +0300 MSK
- 4.7.152: 2025-12-27 17:07:34 +0300 MSK
- 4.7.153: 2025-12-27 16:57:55 +0300 MSK
- 4.7.154: 2025-12-27 16:45:10 +0300 MSK
- 4.7.155: 2025-12-26 21:12:54 +0300 MSK
- 4.7.156: 2025-12-26 14:01:28 +0300 MSK
- 4.7.157: 2025-12-25 20:08:37 +0300 MSK
- 4.7.158: 2025-12-25 20:05:52 +0300 MSK
- 4.7.159: 2025-12-24 15:28:01 +0300 MSK
- 4.7.160: 2025-12-24 14:24:51 +0300 MSK
- 4.7.161: 2025-12-24 13:58:01 +0300 MSK
- 4.7.162: 2025-12-24 13:51:10 +0300 MSK
- 4.7.163: 2025-12-24 13:44:07 +0300 MSK
- 4.7.164: 2025-12-24 12:18:23 +0300 MSK
- 4.7.165: 2025-12-23 19:29:34 +0300 MSK
- 4.7.166: 2025-12-23 18:39:29 +0300 MSK
- 4.7.167: 2025-12-22 19:27:46 +0300 MSK
- 4.7.168: 2025-12-22 16:40:19 +0300 MSK
- 4.7.169: 2025-12-22 16:34:47 +0300 MSK
- 4.7.170: 2025-12-21 20:30:45 +0300 MSK
- 4.7.171: 2025-12-20 19:15:02 +0300 MSK
- 4.7.172: 2025-12-20 19:14:25 +0300 MSK
- 4.7.173: 2025-12-18 21:06:02 +0300 MSK
- 4.7.174: 2025-12-17 08:08:52 +0300 MSK
- 4.7.175: 2025-12-16 20:00:23 +0300 MSK
- 4.7.176: 2025-12-16 19:58:35 +0300 MSK
- 4.7.177: 2025-12-16 19:57:10 +0300 MSK
- 4.7.178: 2025-12-16 19:53:04 +0300 MSK
- 4.7.179: 2025-12-16 19:48:24 +0300 MSK
- 4.7.180: 2025-12-16 19:46:51 +0300 MSK
- 4.7.181: 2025-12-16 19:33:50 +0300 MSK
- 4.7.182: 2025-12-16 19:32:04 +0300 MSK
- 4.7.183: 2025-12-16 19:29:16 +0300 MSK
- 4.7.184: 2025-12-16 19:26:34 +0300 MSK
- 4.7.185: 2025-12-16 19:23:42 +0300 MSK
- 4.7.186: 2025-12-16 19:02:03 +0300 MSK
- 4.7.187: 2025-12-15 21:33:29 +0300 MSK
- 4.7.188: 2025-12-14 20:42:06 +0300 MSK
- 4.7.189: 2025-12-13 20:21:05 +0300 MSK
- 4.7.190: 2025-12-13 20:20:09 +0300 MSK
- 4.7.191: 2025-12-11 14:20:50 +0300 MSK
- 4.7.192: 2025-12-10 20:14:13 +0300 MSK
- 4.7.193: 2025-12-09 20:31:56 +0300 MSK
- 4.7.194: 2025-12-08 20:20:12 +0300 MSK
- 4.7.195: 2025-12-07 19:27:13 +0300 MSK
- 4.7.196: 2025-12-06 19:08:58 +0300 MSK
- 4.7.197: 2025-12-06 19:07:24 +0300 MSK
- 4.7.198: 2025-12-04 19:31:16 +0300 MSK
- 4.7.199: 2025-12-03 21:01:12 +0300 MSK
- 4.7.200: 2025-12-02 19:36:01 +0300 MSK
- 4.7.201: 2025-12-01 19:36:43 +0300 MSK
- 4.7.202: 2025-11-30 20:53:29 +0300 MSK
- 4.7.203: 2025-11-29 21:07:28 +0300 MSK
- 4.7.204: 2025-11-28 20:52:48 +0300 MSK
- 4.7.205: 2025-11-27 17:52:11 +0300 MSK
- 4.7.206: 2025-11-26 18:06:00 +0300 MSK
- 4.7.207: 2025-11-25 19:49:04 +0300 MSK
- 4.7.208: 2025-11-24 18:58:12 +0300 MSK
- 4.7.209: 2025-11-23 18:20:29 +0300 MSK
- 4.7.210: 2025-11-22 17:51:32 +0300 MSK
- 4.7.211: 2025-11-21 17:40:54 +0300 MSK
- 4.7.212: 2025-11-20 18:30:09 +0300 MSK
- 4.7.213: 2025-11-19 18:01:12 +0300 MSK
- 4.7.214: 2025-11-18 19:16:52 +0300 MSK
- 4.7.215: 2025-11-17 18:59:11 +0300 MSK
- 4.7.216: 2025-11-16 18:07:29 +0300 MSK
- 4.7.217: 2025-11-15 18:41:02 +0300 MSK
- 4.7.218: 2025-11-14 15:39:54 +0300 MSK
- 4.7.219: 2025-11-14 15:39:21 +0300 MSK
- 4.7.220: 2025-11-14 15:38:45 +0300 MSK
- 4.7.221: 2025-11-11 19:43:26 +0300 MSK
- 4.7.222: 2025-11-10 19:49:56 +0300 MSK
- 4.7.223: 2025-11-09 17:05:22 +0300 MSK
- 4.7.224: 2025-11-08 22:09:46 +0300 MSK
- 4.7.225: 2025-11-07 20:28:33 +0300 MSK
- 4.7.226: 2025-11-06 20:39:45 +0300 MSK
- 4.7.227: 2025-11-05 20:31:23 +0300 MSK
- 4.7.228: 2025-11-04 17:04:32 +0300 MSK
- 4.7.229: 2025-11-03 17:26:21 +0300 MSK
- 4.7.230: 2025-11-02 19:37:10 +0300 MSK
- 4.7.231: 2025-11-02 19:36:12 +0300 MSK
- 4.7.232: 2025-11-02 19:35:07 +0300 MSK
- 4.7.233: 2025-10-31 21:10:44 +0300 MSK
- 4.7.234: 2025-10-30 20:34:31 +0300 MSK
- 4.7.235: 2025-10-29 19:40:08 +0300 MSK
- 4.7.236: 2025-10-28 17:46:01 +0300 MSK
- 4.7.237: 2025-10-28 17:19:30 +0300 MSK
- 4.7.238: 2025-10-27 20:43:34 +0300 MSK
- 4.7.239: 2025-10-27 12:49:36 +0300 MSK
- 4.7.240: 2025-10-27 12:48:19 +0300 MSK
- 4.7.241: 2025-10-25 13:13:55 +0300 MSK
- 4.7.242: 2025-10-24 19:02:20 +0300 MSK
- 4.7.243: 2025-10-23 19:12:54 +0300 MSK
- 4.7.244: 2025-10-22 16:36:23 +0300 MSK
- 4.7.245: 2025-10-21 20:51:47 +0300 MSK
- 4.7.246: 2025-10-20 21:06:38 +0300 MSK
- 4.7.247: 2025-10-19 18:18:20 +0300 MSK
- 4.7.248: 2025-10-18 20:20:30 +0300 MSK
- 4.7.249: 2025-10-17 20:03:35 +0300 MSK
- 4.7.250: 2025-10-16 21:12:42 +0300 MSK
- 4.7.251: 2025-10-15 21:05:53 +0300 MSK
- 4.7.252: 2025-10-14 21:36:00 +0300 MSK
- 4.7.253: 2025-10-13 21:06:28 +0300 MSK
- 4.7.254: 2025-10-12 18:25:03 +0300 MSK
- 4.7.255: 2025-10-11 21:08:12 +0300 MSK
- 4.7.256: 2025-10-10 19:31:54 +0300 MSK
- 4.7.257: 2025-10-09 21:03:44 +0300 MSK
- 4.7.258: 2025-10-08 20:28:20 +0300 MSK
- 4.7.259: 2025-10-07 19:48:34 +0300 MSK
- 4.7.260: 2025-10-06 20:51:45 +0300 MSK
- 4.7.261: 2025-10-05 19:06:52 +0300 MSK
- 4.7.262: 2025-10-05 18:56:55 +0300 MSK
- 4.7.263: 2025-10-04 21:18:06 +0300 MSK
- 4.7.264: 2025-10-03 16:57:28 +0300 MSK
- 4.7.265: 2025-10-02 17:45:08 +0300 MSK
- 4.7.266: 2025-10-01 09:21:36 +0300 MSK
- 4.7.267: 2025-10-01 09:19:12 +0300 MSK
- 4.7.268: 2025-10-01 08:50:51 +0300 MSK
- 4.7.269: 2025-10-01 08:48:37 +0300 MSK
- 4.7.270: 2025-10-01 08:46:25 +0300 MSK
- 4.7.271: 2025-10-01 08:43:05 +0300 MSK
- 4.7.272: 2025-09-30 19:51:05 +0300 MSK
- 4.7.273: 2025-09-29 18:59:55 +0300 MSK
- 4.7.274: 2025-09-28 17:19:33 +0300 MSK
- 4.7.275: 2025-09-27 17:16:05 +0300 MSK
- 4.7.276: 2025-09-27 10:04:38 +0300 MSK
- 4.7.277: 2025-09-26 19:59:24 +0300 MSK
- 4.7.278: 2025-09-25 17:15:32 +0300 MSK
- 4.7.279: 2025-09-24 18:51:01 +0300 MSK
- 4.7.280: 2025-09-23 16:55:31 +0300 MSK
- 4.7.281: 2025-09-22 19:34:44 +0300 MSK
- 4.7.282: 2025-09-21 19:30:58 +0300 MSK
- 4.7.283: 2025-09-20 19:25:16 +0300 MSK
- 4.7.284: 2025-09-19 18:44:46 +0300 MSK
- 4.7.285: 2025-09-18 19:58:25 +0300 MSK
- 4.7.286: 2025-09-17 20:39:54 +0300 MSK
- 4.7.287: 2025-09-16 18:41:40 +0300 MSK
- 4.7.288: 2025-09-15 18:04:52 +0300 MSK
- 4.7.289: 2025-09-14 19:11:43 +0300 MSK
- 4.7.290: 2025-09-13 18:48:49 +0300 MSK
- 4.7.291: 2025-09-12 21:22:49 +0300 MSK
- 4.7.292: 2025-09-11 20:29:02 +0300 MSK
- 4.7.293: 2025-09-10 18:11:04 +0300 MSK
- 4.7.294: 2025-09-09 18:44:51 +0300 MSK
- 4.7.295: 2025-09-08 18:09:53 +0300 MSK
- 4.7.296: 2025-09-07 11:16:52 +0300 MSK
- 4.7.297: 2025-09-07 11:00:41 +0300 MSK
- 4.7.298: 2025-09-06 17:38:19 +0300 MSK
- 4.7.299: 2025-09-05 19:23:51 +0300 MSK
- 4.7.300: 2025-09-04 22:15:30 +0300 MSK
- 4.7.301: 2025-09-03 18:20:51 +0300 MSK
- 4.7.302: 2025-09-02 20:18:23 +0300 MSK
- 4.7.303: 2025-09-01 17:35:05 +0300 MSK
- 4.7.304: 2025-08-31 15:07:32 +0300 MSK
- 4.7.305: 2025-08-31 14:18:46 +0300 MSK
- 4.7.306: 2025-08-31 14:13:40 +0300 MSK
- 4.7.307: 2025-08-30 20:16:00 +0300 MSK
- 4.7.308: 2025-08-29 19:59:52 +0300 MSK
- 4.7.309: 2025-08-28 16:59:23 +0300 MSK
- 4.7.310: 2025-08-27 16:22:50 +0300 MSK
- 4.7.311: 2025-08-26 09:10:25 +0300 MSK
- 4.7.312: 2025-08-26 08:16:39 +0300 MSK
- 4.7.313: 2025-08-26 08:11:15 +0300 MSK
- 4.7.314: 2025-08-25 17:00:38 +0300 MSK
- 4.7.315: 2025-08-25 11:40:44 +0300 MSK
- 4.7.316: 2025-08-24 20:51:14 +0300 MSK
- 4.7.317: 2025-08-24 19:54:22 +0300 MSK
- 4.7.318: 2025-08-24 19:38:13 +0300 MSK
- 4.7.319: 2025-08-24 19:30:45 +0300 MSK
- 4.7.320: 2025-08-24 19:28:22 +0300 MSK
- 4.7.321: 2025-08-24 19:26:17 +0300 MSK
- 4.7.322: 2025-08-24 19:18:26 +0300 MSK
- 4.7.323: 2025-08-24 19:07:06 +0300 MSK
- 4.7.324: 2025-08-24 19:02:12 +0300 MSK
- 4.7.325: 2025-08-24 18:57:13 +0300 MSK
- 4.7.326: 2025-08-24 18:52:47 +0300 MSK
- 4.7.327: 2025-08-24 18:50:32 +0300 MSK
- 4.7.328: 2025-08-24 18:39:15 +0300 MSK
- 4.7.329: 2025-08-24 18:38:15 +0300 MSK
- 4.7.330: 2025-08-24 18:22:04 +0300 MSK
- 4.7.331: 2025-08-24 18:15:48 +0300 MSK
- 4.7.332: 2025-08-24 18:07:04 +0300 MSK
- 4.7.333: 2025-08-24 18:01:04 +0300 MSK
- 4.7.334: 2025-08-24 17:55:59 +0300 MSK
- 4.7.335: 2025-08-24 17:54:29 +0300 MSK
- 4.7.336: 2025-08-24 17:52:40 +0300 MSK
- 4.7.337: 2025-08-24 17:46:18 +0300 MSK
- 4.7.338: 2025-08-24 17:42:32 +0300 MSK
- 4.7.339: 2025-08-24 17:41:29 +0300 MSK
- 4.7.340: 2025-08-24 17:40:23 +0300 MSK
- 4.7.341: 2025-08-24 17:38:35 +0300 MSK
- 4.7.342: 2025-08-24 17:36:34 +0300 MSK
- 4.7.343: 2025-08-24 17:22:24 +0300 MSK
- 4.7.344: 2025-08-24 17:12:42 +0300 MSK
- 4.7.345: 2025-08-24 17:10:49 +0300 MSK
- 4.7.346: 2025-08-24 17:08:09 +0300 MSK
- 4.7.347: 2025-08-24 17:02:11 +0300 MSK
- 4.7.348: 2025-08-24 16:02:46 +0300 MSK
- 4.7.349: 2025-08-24 16:00:53 +0300 MSK
- 4.7.350: 2025-08-24 15:55:14 +0300 MSK
- 4.7.351: 2025-08-24 15:40:47 +0300 MSK
- 4.7.352: 2025-08-24 15:35:22 +0300 MSK
- 4.7.353: 2025-08-24 15:32:58 +0300 MSK
- 4.7.354: 2025-08-24 15:21:21 +0300 MSK
- 4.7.355: 2025-08-24 15:17:24 +0300 MSK
- 4.7.356: 2025-08-24 15:14:50 +0300 MSK
- 4.7.357: 2025-08-24 15:11:09 +0300 MSK
- 4.7.358: 2025-08-24 15:07:53 +0300 MSK
- 4.7.359: 2025-08-24 15:06:30 +0300 MSK
- 4.7.360: 2025-08-24 15:00:31 +0300 MSK
- 4.7.361: 2025-08-24 14:57:30 +0300 MSK
- 4.7.362: 2025-08-24 14:47:52 +0300 MSK
- 4.7.363: 2025-08-24 14:42:38 +0300 MSK
- 4.7.364: 2025-08-24 14:38:49 +0300 MSK
- 4.7.365: 2025-08-24 14:36:54 +0300 MSK
- 4.7.366: 2025-08-24 14:33:39 +0300 MSK
- 4.7.367: 2025-08-24 14:28:25 +0300 MSK
- 4.7.368: 2025-08-24 14:25:47 +0300 MSK
- 4.7.369: 2025-08-24 14:09:37 +0300 MSK
- 4.7.370: 2025-08-24 14:03:51 +0300 MSK
- 4.7.371: 2025-08-24 13:57:16 +0300 MSK
- 4.7.372: 2025-08-24 13:46:58 +0300 MSK
- 4.7.373: 2025-08-24 13:33:19 +0300 MSK
- 4.7.374: 2025-08-24 13:31:22 +0300 MSK
- 4.7.375: 2025-08-24 13:27:05 +0300 MSK
- 4.7.376: 2025-08-24 13:21:47 +0300 MSK
- 4.7.377: 2025-08-24 13:10:51 +0300 MSK
- 4.7.378: 2025-08-24 13:05:10 +0300 MSK
- 4.7.379: 2025-08-24 12:59:57 +0300 MSK
- 4.7.380: 2025-08-24 12:47:23 +0300 MSK
- 4.7.381: 2025-08-24 12:44:46 +0300 MSK
- 4.7.382: 2025-08-24 12:44:03 +0300 MSK
- 4.7.383: 2025-08-24 12:38:10 +0300 MSK
- 4.7.384: 2025-08-24 12:34:32 +0300 MSK
- 4.7.385: 2025-08-24 12:31:27 +0300 MSK
- 4.7.386: 2025-08-24 12:29:48 +0300 MSK
- 4.7.387: 2025-08-24 12:20:45 +0300 MSK
- 4.7.388: 2025-08-24 11:46:23 +0300 MSK
- 4.7.389: 2025-08-24 11:43:54 +0300 MSK
- 4.7.390: 2025-08-24 10:55:08 +0300 MSK
- 4.7.391: 2025-08-23 20:17:19 +0300 MSK
- 4.7.392: 2025-08-23 19:28:34 +0300 MSK
- 4.7.393: 2025-08-23 18:30:08 +0300 MSK
- 4.7.394: 2025-08-22 21:36:17 +0300 MSK
- 4.7.395: 2025-08-22 21:29:25 +0300 MSK
- 4.7.396: 2025-08-22 21:16:52 +0300 MSK
- 4.7.397: 2025-08-22 21:13:56 +0300 MSK
- 4.7.398: 2025-08-22 21:08:45 +0300 MSK
- 4.7.399: 2025-08-22 21:06:36 +0300 MSK
- 4.7.400: 2025-08-22 21:05:07 +0300 MSK
- 4.7.401: 2025-08-22 21:02:15 +0300 MSK
- 4.7.402: 2025-08-22 20:53:33 +0300 MSK
- 4.7.403: 2025-08-22 20:44:21 +0300 MSK
- 4.7.404: 2025-08-22 20:41:37 +0300 MSK
- 4.7.405: 2025-08-22 20:34:34 +0300 MSK
- 4.7.406: 2025-08-22 20:29:48 +0300 MSK
- 4.7.407: 2025-08-22 20:27:37 +0300 MSK
- 4.7.408: 2025-08-22 20:25:28 +0300 MSK
- 4.7.409: 2025-08-22 20:22:48 +0300 MSK
- 4.7.410: 2025-08-22 20:20:58 +0300 MSK
- 4.7.411: 2025-08-22 20:15:56 +0300 MSK
- 4.7.412: 2025-08-22 20:12:59 +0300 MSK
- 4.7.413: 2025-08-22 20:03:50 +0300 MSK
- 4.7.414: 2025-08-22 19:58:17 +0300 MSK
- 4.7.415: 2025-08-22 19:49:07 +0300 MSK
- 4.7.416: 2025-08-22 19:43:35 +0300 MSK
- 4.7.417: 2025-08-22 19:42:24 +0300 MSK
- 4.7.418: 2025-08-22 19:24:16 +0300 MSK
- 4.7.419: 2025-08-22 19:19:46 +0300 MSK
- 4.7.420: 2025-08-22 19:14:44 +0300 MSK
- 4.7.421: 2025-08-22 19:10:19 +0300 MSK
- 4.7.422: 2025-08-22 19:03:00 +0300 MSK
- 4.7.423: 2025-08-22 18:58:03 +0300 MSK
- 4.7.424: 2025-08-22 18:56:27 +0300 MSK
- 4.7.425: 2025-08-22 18:53:34 +0300 MSK
- 4.7.426: 2025-08-22 18:48:54 +0300 MSK
- 4.7.427: 2025-08-22 18:46:45 +0300 MSK
- 4.7.428: 2025-08-22 18:44:22 +0300 MSK
- 4.7.429: 2025-08-22 18:43:10 +0300 MSK
- 4.7.430: 2025-08-22 18:39:40 +0300 MSK
- 4.7.431: 2025-08-22 18:38:14 +0300 MSK
- 4.7.432: 2025-08-22 18:36:52 +0300 MSK
- 4.7.433: 2025-08-22 18:30:44 +0300 MSK
- 4.7.434: 2025-08-22 18:25:20 +0300 MSK
- 4.7.435: 2025-08-22 18:22:55 +0300 MSK
- 4.7.436: 2025-08-22 18:19:44 +0300 MSK
- 4.7.437: 2025-08-22 17:02:28 +0300 MSK
- 4.7.438: 2025-08-22 16:56:33 +0300 MSK
- 4.7.439: 2025-08-22 14:49:18 +0300 MSK
- 4.7.440: 2025-08-22 14:41:39 +0300 MSK
- 4.7.441: 2025-08-22 14:33:33 +0300 MSK
- 4.7.442: 2025-08-22 14:30:04 +0300 MSK
- 4.7.443: 2025-08-22 14:28:05 +0300 MSK
- 4.7.444: 2025-08-22 14:23:13 +0300 MSK
- 4.7.445: 2025-08-22 14:20:44 +0300 MSK
- 4.7.446: 2025-08-22 14:19:56 +0300 MSK
- 4.7.447: 2025-08-22 14:06:34 +0300 MSK
- 4.7.448: 2025-08-22 13:59:13 +0300 MSK
- 4.7.449: 2025-08-22 13:58:21 +0300 MSK
- 4.7.450: 2025-08-22 13:53:08 +0300 MSK
- 4.7.451: 2025-08-22 13:44:20 +0300 MSK
- 4.7.452: 2025-08-22 13:37:11 +0300 MSK
- 4.7.453: 2025-08-22 09:54:03 +0300 MSK
- 4.7.454: 2025-08-21 19:04:22 +0300 MSK
- 4.7.455: 2025-08-21 19:01:40 +0300 MSK
- 4.7.456: 2025-08-21 18:59:14 +0300 MSK
- 4.7.457: 2025-08-21 18:58:06 +0300 MSK
- 4.7.458: 2025-08-21 18:57:41 +0300 MSK
- 4.7.459: 2025-08-21 18:50:35 +0300 MSK
- 4.7.460: 2025-08-21 18:50:21 +0300 MSK
- 4.7.461: 2025-08-21 18:45:02 +0300 MSK
- 4.7.462: 2025-08-21 18:35:19 +0300 MSK
- 4.7.463: 2025-08-21 18:35:00 +0300 MSK
- 4.7.464: 2025-08-21 18:34:31 +0300 MSK
- 4.7.465: 2025-08-21 18:30:25 +0300 MSK
- 4.7.466: 2025-08-21 18:30:11 +0300 MSK
- 4.7.467: 2025-08-21 18:24:42 +0300 MSK
- 4.7.468: 2025-08-21 18:24:23 +0300 MSK
- 4.7.469: 2025-08-21 18:18:09 +0300 MSK
- 4.7.470: 2025-08-21 18:17:44 +0300 MSK
- 4.7.471: 2025-08-21 18:17:05 +0300 MSK
- 4.7.472: 2025-08-21 18:16:46 +0300 MSK
- 4.7.473: 2025-08-21 18:16:25 +0300 MSK
- 4.7.474: 2025-08-21 18:16:06 +0300 MSK
- 4.7.475: 2025-08-21 18:15:24 +0300 MSK
- 4.7.476: 2025-08-21 17:56:20 +0300 MSK
- 4.7.477: 2025-08-21 17:51:03 +0300 MSK
- 4.7.478: 2025-08-21 17:41:49 +0300 MSK
- 4.7.479: 2025-08-21 17:35:46 +0300 MSK
- 4.7.480: 2025-08-21 17:31:03 +0300 MSK
- 4.7.481: 2025-08-21 17:26:29 +0300 MSK
- 4.7.482: 2025-08-21 17:15:57 +0300 MSK
- 4.7.483: 2025-08-21 17:07:52 +0300 MSK
- 4.7.484: 2025-08-21 17:05:33 +0300 MSK
- 4.7.485: 2025-08-21 17:00:40 +0300 MSK
- 4.7.486: 2025-08-21 16:51:13 +0300 MSK
- 4.7.487: 2025-08-21 16:50:01 +0300 MSK
- 4.7.488: 2025-08-21 16:46:44 +0300 MSK
- 4.7.489: 2025-08-21 16:44:37 +0300 MSK
- 4.7.490: 2025-08-21 16:42:44 +0300 MSK
- 4.7.491: 2025-08-21 16:38:20 +0300 MSK
- 4.7.492: 2025-08-21 16:26:55 +0300 MSK
- 4.7.493: 2025-08-21 16:19:42 +0300 MSK
- 4.7.494: 2025-08-21 16:16:56 +0300 MSK
- 4.7.495: 2025-08-21 16:07:01 +0300 MSK
- 4.7.496: 2025-08-21 16:06:09 +0300 MSK
- 4.7.497: 2025-08-21 16:01:02 +0300 MSK
- 4.7.498: 2025-08-21 15:58:36 +0300 MSK
- 4.7.499: 2025-08-21 15:55:14 +0300 MSK
- 4.7.500: 2025-08-21 15:49:02 +0300 MSK
- 4.7.501: 2025-08-21 15:45:35 +0300 MSK
- 4.7.502: 2025-08-21 15:42:45 +0300 MSK
- 4.7.503: 2025-08-21 15:40:49 +0300 MSK
- 4.7.504: 2025-08-21 15:37:36 +0300 MSK
- 4.7.505: 2025-08-21 15:33:15 +0300 MSK
- 4.7.506: 2025-08-21 15:32:49 +0300 MSK
- 4.7.507: 2025-08-21 15:03:03 +0300 MSK
- 4.7.508: 2025-08-21 14:57:54 +0300 MSK
- 4.7.509: 2025-08-21 14:56:18 +0300 MSK
- 4.7.510: 2025-08-21 14:52:44 +0300 MSK
- 4.7.511: 2025-08-21 14:47:10 +0300 MSK
- 4.7.512: 2025-08-21 14:44:56 +0300 MSK
- 4.7.513: 2025-08-21 14:42:42 +0300 MSK
- 4.7.514: 2025-08-21 14:32:28 +0300 MSK
- 4.7.515: 2025-08-21 14:31:55 +0300 MSK
- 4.7.516: 2025-08-21 14:30:46 +0300 MSK
- 4.7.517: 2025-08-21 14:28:11 +0300 MSK
- 4.7.518: 2025-08-21 14:14:45 +0300 MSK
- 4.7.519: 2025-08-21 14:03:34 +0300 MSK
- 4.7.520: 2025-08-21 13:59:45 +0300 MSK
- 4.7.521: 2025-08-21 13:58:37 +0300 MSK
- 4.7.522: 2025-08-21 13:56:09 +0300 MSK
- 4.7.523: 2025-08-21 13:42:53 +0300 MSK
- 4.7.524: 2025-08-21 13:40:48 +0300 MSK
- 4.7.525: 2025-08-21 13:31:24 +0300 MSK
- 4.7.526: 2025-08-21 13:26:07 +0300 MSK
- 4.7.527: 2025-08-21 12:41:54 +0300 MSK
- 4.7.528: 2025-08-21 12:07:22 +0300 MSK
- 4.7.529: 2025-08-21 11:45:30 +0300 MSK
- 4.7.530: 2025-08-21 11:32:12 +0300 MSK
- 4.7.531: 2025-08-21 11:29:38 +0300 MSK
- 4.7.532: 2025-08-21 11:16:33 +0300 MSK
- 4.7.533: 2025-08-21 11:08:30 +0300 MSK
- 4.7.534: 2025-08-21 08:52:21 +0300 MSK
- 4.7.535: 2025-08-20 20:41:08 +0300 MSK
- 4.7.536: 2025-08-20 20:38:27 +0300 MSK
- 4.7.537: 2025-08-20 20:36:18 +0300 MSK
- 4.7.538: 2025-08-20 20:31:33 +0300 MSK
- 4.7.539: 2025-08-20 20:28:21 +0300 MSK
- 4.7.540: 2025-08-20 20:26:57 +0300 MSK
- 4.7.541: 2025-08-20 20:25:45 +0300 MSK
- 4.7.542: 2025-08-20 20:20:02 +0300 MSK
- 4.7.543: 2025-08-20 20:15:03 +0300 MSK
- 4.7.544: 2025-08-20 20:10:18 +0300 MSK
- 4.7.545: 2025-08-20 19:48:54 +0300 MSK
- 4.7.546: 2025-08-20 19:41:49 +0300 MSK
- 4.7.547: 2025-08-20 19:24:46 +0300 MSK
- 4.7.548: 2025-08-20 19:22:34 +0300 MSK
- 4.7.549: 2025-08-20 19:11:13 +0300 MSK
- 4.7.550: 2025-08-20 19:07:59 +0300 MSK
- 4.7.551: 2025-08-20 19:05:44 +0300 MSK
- 4.7.552: 2025-08-20 19:01:55 +0300 MSK
- 4.7.553: 2025-08-20 18:54:48 +0300 MSK
- 4.7.554: 2025-08-20 18:49:12 +0300 MSK
- 4.7.555: 2025-08-20 18:45:47 +0300 MSK
- 4.7.556: 2025-08-20 18:44:00 +0300 MSK
- 4.7.557: 2025-08-20 18:28:35 +0300 MSK
- 4.7.558: 2025-08-20 18:24:20 +0300 MSK
- 4.7.559: 2025-08-20 18:23:07 +0300 MSK
- 4.7.560: 2025-08-20 18:22:39 +0300 MSK
- 4.7.561: 2025-08-20 17:57:07 +0300 MSK
- 4.7.562: 2025-08-20 17:48:38 +0300 MSK
- 4.7.563: 2025-08-20 17:47:52 +0300 MSK
- 4.7.564: 2025-08-20 17:43:24 +0300 MSK
- 4.7.565: 2025-08-20 17:23:29 +0300 MSK
- 4.7.566: 2025-08-20 17:18:47 +0300 MSK
- 4.7.567: 2025-08-20 15:09:02 +0300 MSK
- 4.7.568: 2025-08-20 13:48:16 +0300 MSK
- 4.7.569: 2025-08-20 13:45:38 +0300 MSK
- 4.7.570: 2025-08-20 13:41:05 +0300 MSK
- 4.7.571: 2025-08-20 13:36:58 +0300 MSK
- 4.7.572: 2025-08-20 13:29:30 +0300 MSK
- 4.7.573: 2025-08-20 13:16:55 +0300 MSK
- 4.7.574: 2025-08-20 13:13:48 +0300 MSK
- 4.7.575: 2025-08-20 13:06:17 +0300 MSK
- 4.7.576: 2025-08-20 12:43:09 +0300 MSK
- 4.7.577: 2025-08-20 12:38:03 +0300 MSK
- 4.7.578: 2025-08-20 12:08:13 +0300 MSK
- 4.7.579: 2025-08-19 20:23:46 +0300 MSK
- 4.7.580: 2025-08-19 20:13:25 +0300 MSK
- 4.7.581: 2025-08-19 20:11:33 +0300 MSK
- 4.7.582: 2025-08-19 20:00:15 +0300 MSK
- 4.7.583: 2025-08-19 19:47:47 +0300 MSK
- 4.7.584: 2025-08-19 16:10:29 +0300 MSK
- 4.7.585: 2025-08-19 15:27:24 +0300 MSK
- 4.7.586: 2025-08-19 15:24:40 +0300 MSK
- 4.7.587: 2025-08-19 15:04:21 +0300 MSK
- 4.7.588: 2025-08-19 14:58:59 +0300 MSK
- 4.7.589: 2025-08-19 14:42:34 +0300 MSK
- 4.7.590: 2025-08-19 14:37:35 +0300 MSK
- 4.7.591: 2025-08-19 14:29:00 +0300 MSK
- 4.7.592: 2025-08-19 14:04:31 +0300 MSK
- 4.7.593: 2025-08-19 13:54:21 +0300 MSK
- 4.7.594: 2025-08-19 13:40:19 +0300 MSK
- 4.7.595: 2025-08-19 13:37:47 +0300 MSK
- 4.7.596: 2025-08-19 13:11:40 +0300 MSK
- 4.7.597: 2025-08-19 11:34:12 +0300 MSK
- 4.7.598: 2025-08-19 09:58:54 +0300 MSK
- 4.7.599: 2025-08-19 08:52:54 +0300 MSK
- 4.7.600: 2025-08-19 08:18:09 +0300 MSK
- 4.7.601: 2025-08-18 21:10:17 +0300 MSK
- 4.7.602: 2025-08-18 21:06:45 +0300 MSK
- 4.7.603: 2025-08-18 20:23:18 +0300 MSK
- 4.7.604: 2025-08-18 20:18:16 +0300 MSK
- 4.7.605: 2025-08-18 20:07:07 +0300 MSK
- 4.7.606: 2025-08-18 20:04:04 +0300 MSK
- 4.7.607: 2025-08-18 19:52:53 +0300 MSK
- 4.7.608: 2025-08-18 19:41:27 +0300 MSK
- 4.7.609: 2025-08-18 19:36:10 +0300 MSK
- 4.7.610: 2025-08-18 19:26:10 +0300 MSK
- 4.7.611: 2025-08-18 19:21:41 +0300 MSK
- 4.7.612: 2025-08-18 19:16:20 +0300 MSK
- 4.7.613: 2025-08-18 19:11:33 +0300 MSK
- 4.7.614: 2025-08-18 19:02:01 +0300 MSK
- 4.7.615: 2025-08-18 18:43:22 +0300 MSK
- 4.7.616: 2025-08-18 15:12:00 +0300 MSK
- 4.7.617: 2025-08-18 15:03:06 +0300 MSK
- 4.7.618: 2025-08-18 14:55:52 +0300 MSK
- 4.7.619: 2025-08-18 14:48:14 +0300 MSK
- 4.7.620: 2025-08-18 14:43:36 +0300 MSK
- 4.7.621: 2025-08-18 13:44:46 +0300 MSK
- 4.7.622: 2025-08-18 13:40:40 +0300 MSK
- 4.7.623: 2025-08-18 13:34:09 +0300 MSK
- 4.7.624: 2025-08-18 10:06:49 +0300 MSK
- 4.7.625: 2025-08-17 20:02:56 +0300 MSK
- 4.7.626: 2025-08-17 19:56:52 +0300 MSK
- 4.7.627: 2025-08-17 19:54:48 +0300 MSK
- 4.7.628: 2025-08-17 19:44:55 +0300 MSK
- 4.7.629: 2025-08-17 19:21:20 +0300 MSK
- 4.7.630: 2025-08-17 19:15:00 +0300 MSK
- 4.7.631: 2025-08-17 19:10:32 +0300 MSK
- 4.7.632: 2025-08-17 19:08:02 +0300 MSK
- 4.7.633: 2025-08-17 18:51:40 +0300 MSK
- 4.7.634: 2025-08-17 18:46:10 +0300 MSK
- 4.7.635: 2025-08-17 18:44:14 +0300 MSK
- 4.7.636: 2025-08-17 18:40:15 +0300 MSK
- 4.7.637: 2025-08-17 18:38:02 +0300 MSK
- 4.7.638: 2025-08-17 18:25:12 +0300 MSK
- 4.7.639: 2025-08-17 18:16:02 +0300 MSK
- 4.7.640: 2025-08-17 18:06:00 +0300 MSK
- 4.7.641: 2025-08-17 17:56:42 +0300 MSK
- 4.7.642: 2025-08-17 17:28:49 +0300 MSK
- 4.7.643: 2025-08-17 17:16:59 +0300 MSK
- 4.7.644: 2025-08-17 17:04:01 +0300 MSK
- 4.7.645: 2025-08-17 16:00:07 +0300 MSK
- 4.7.646: 2025-08-17 13:53:56 +0300 MSK
- 4.7.647: 2025-08-17 13:41:15 +0300 MSK
- 4.7.648: 2025-08-17 13:38:02 +0300 MSK
- 4.7.649: 2025-08-17 13:36:24 +0300 MSK
- 4.7.650: 2025-08-17 13:34:11 +0300 MSK
- 4.7.651: 2025-08-17 13:25:54 +0300 MSK
- 4.7.652: 2025-08-17 13:10:43 +0300 MSK
- 4.7.653: 2025-08-17 12:55:05 +0300 MSK
- 4.7.654: 2025-08-17 12:47:03 +0300 MSK
- 4.7.655: 2025-08-17 12:39:05 +0300 MSK
- 4.7.656: 2025-08-17 11:54:12 +0300 MSK
- 4.7.657: 2025-08-17 09:23:21 +0300 MSK
- 4.7.658: 2025-08-16 18:43:20 +0300 MSK
- 4.7.659: 2025-08-16 16:51:28 +0300 MSK
- 4.7.660: 2025-08-16 16:11:23 +0300 MSK
- 4.7.661: 2025-08-16 14:42:51 +0300 MSK
- 4.7.662: 2025-08-16 14:31:57 +0300 MSK
- 4.7.663: 2025-08-16 14:30:59 +0300 MSK
- 4.7.664: 2025-08-16 14:27:06 +0300 MSK
- 4.7.665: 2025-08-16 14:19:48 +0300 MSK
- 4.7.666: 2025-08-16 14:16:53 +0300 MSK
- 4.7.667: 2025-08-16 14:14:34 +0300 MSK
- 4.7.668: 2025-08-16 14:05:37 +0300 MSK
- 4.7.669: 2025-08-16 14:04:12 +0300 MSK
- 4.7.670: 2025-08-16 13:53:07 +0300 MSK
- 4.7.671: 2025-08-16 13:39:08 +0300 MSK
- 4.7.672: 2025-08-16 13:35:39 +0300 MSK
- 4.7.673: 2025-08-16 13:22:50 +0300 MSK
- 4.7.674: 2025-08-16 13:15:31 +0300 MSK
- 4.7.675: 2025-08-16 13:13:30 +0300 MSK
- 4.7.676: 2025-08-16 12:59:52 +0300 MSK
- 4.7.677: 2025-08-16 12:54:52 +0300 MSK
- 4.7.678: 2025-08-16 12:42:27 +0300 MSK
- 4.7.679: 2025-08-16 12:24:35 +0300 MSK
- 4.7.680: 2025-08-16 12:19:08 +0300 MSK
- 4.7.681: 2025-08-16 12:12:54 +0300 MSK
- 4.7.682: 2025-08-16 12:11:17 +0300 MSK
- 4.7.683: 2025-08-16 12:07:23 +0300 MSK
- 4.7.684: 2025-08-16 12:06:11 +0300 MSK
- 4.7.685: 2025-08-16 11:58:38 +0300 MSK
- 4.7.686: 2025-08-16 11:50:13 +0300 MSK
- 4.7.687: 2025-08-16 11:32:58 +0300 MSK
- 4.7.688: 2025-08-16 11:14:35 +0300 MSK
- 4.7.689: 2025-08-16 11:13:51 +0300 MSK
- 4.7.690: 2025-08-16 11:09:17 +0300 MSK
- 4.7.691: 2025-08-16 10:49:39 +0300 MSK
- 4.7.692: 2025-08-16 10:22:08 +0300 MSK
- 4.7.693: 2025-08-16 10:19:18 +0300 MSK
- 4.7.694: 2025-08-16 10:09:43 +0300 MSK
- 4.7.695: 2025-08-15 17:31:44 +0300 MSK
- 4.7.696: 2025-08-15 16:57:42 +0300 MSK
- 4.7.697: 2025-08-15 16:43:07 +0300 MSK
- 4.7.698: 2025-08-15 16:35:39 +0300 MSK
- 4.7.699: 2025-08-15 16:30:08 +0300 MSK
- 4.7.700: 2025-08-15 16:25:44 +0300 MSK
- 4.7.701: 2025-08-15 16:20:07 +0300 MSK
- 4.7.702: 2025-08-15 16:13:25 +0300 MSK
- 4.7.703: 2025-08-15 16:11:57 +0300 MSK
- 4.7.704: 2025-08-15 16:11:03 +0300 MSK
- 4.7.705: 2025-08-15 16:06:24 +0300 MSK
- 4.7.706: 2025-08-15 16:05:32 +0300 MSK
- 4.7.707: 2025-08-15 16:03:03 +0300 MSK
- 4.7.708: 2025-08-15 15:54:30 +0300 MSK
- 4.7.709: 2025-08-15 15:47:22 +0300 MSK
- 4.7.710: 2025-08-15 15:44:11 +0300 MSK
- 4.7.711: 2025-08-15 15:38:40 +0300 MSK
- 4.7.712: 2025-08-15 15:32:17 +0300 MSK
- 4.7.713: 2025-08-15 15:28:53 +0300 MSK
- 4.7.714: 2025-08-15 15:12:21 +0300 MSK
- 4.7.715: 2025-08-15 15:04:18 +0300 MSK
- 4.7.716: 2025-08-15 15:03:12 +0300 MSK
- 4.7.717: 2025-08-15 14:37:22 +0300 MSK
- 4.7.718: 2025-08-15 14:34:58 +0300 MSK
- 4.7.719: 2025-08-15 14:33:22 +0300 MSK
- 4.7.720: 2025-08-15 14:31:10 +0300 MSK
- 4.7.721: 2025-08-15 14:21:42 +0300 MSK
- 4.7.722: 2025-08-15 14:17:27 +0300 MSK
- 4.7.723: 2025-08-15 14:14:49 +0300 MSK
- 4.7.724: 2025-08-15 13:38:16 +0300 MSK
- 4.7.725: 2025-08-15 13:31:41 +0300 MSK
- 4.7.726: 2025-08-15 13:23:40 +0300 MSK
- 4.7.727: 2025-08-15 13:09:22 +0300 MSK
- 4.7.728: 2025-08-15 13:07:52 +0300 MSK
- 4.7.729: 2025-08-15 12:54:27 +0300 MSK
- 4.7.730: 2025-08-15 12:49:02 +0300 MSK
- 4.7.731: 2025-08-15 12:36:30 +0300 MSK
- 4.7.732: 2025-08-15 12:28:46 +0300 MSK
- 4.7.733: 2025-08-15 12:22:34 +0300 MSK
- 4.7.734: 2025-08-15 11:52:01 +0300 MSK
- 4.7.735: 2025-08-15 11:51:01 +0300 MSK
- 4.7.736: 2025-08-14 20:09:09 +0300 MSK
- 4.7.737: 2025-08-13 17:56:30 +0300 MSK
- 4.7.738: 2025-08-13 17:55:25 +0300 MSK
- 4.7.739: 2025-08-12 17:49:12 +0300 MSK
- 4.7.740: 2025-08-11 18:03:04 +0300 MSK
- 4.7.741: 2025-08-10 13:14:07 +0300 MSK
- 4.7.742: 2025-08-10 13:10:37 +0300 MSK
- 4.7.743: 2025-08-10 13:08:24 +0300 MSK
- 4.7.744: 2025-08-10 13:03:22 +0300 MSK
- 4.7.745: 2025-08-10 12:56:18 +0300 MSK
- 4.7.746: 2025-08-10 12:52:07 +0300 MSK
- 4.7.747: 2025-08-10 12:45:06 +0300 MSK
- 4.7.748: 2025-08-10 12:15:52 +0300 MSK
- 4.7.749: 2025-08-10 11:45:24 +0300 MSK
- 4.7.750: 2025-08-10 11:25:09 +0300 MSK
- 4.7.751: 2025-08-10 11:14:30 +0300 MSK
- 4.7.752: 2025-08-10 11:02:20 +0300 MSK
- 4.7.753: 2025-08-10 10:27:29 +0300 MSK
- 4.7.754: 2025-08-09 16:43:21 +0300 MSK
- 4.7.755: 2025-08-09 16:34:28 +0300 MSK
- 4.7.756: 2025-08-09 16:31:49 +0300 MSK
- 4.7.757: 2025-08-09 16:17:16 +0300 MSK
- 4.7.758: 2025-08-09 15:53:09 +0300 MSK
- 4.7.759: 2025-08-09 11:14:40 +0300 MSK
- 4.7.760: 2025-08-08 18:19:33 +0300 MSK
- 4.7.761: 2025-08-07 17:57:34 +0300 MSK
- 4.7.762: 2025-08-07 17:15:08 +0300 MSK
- 4.7.763: 2025-08-06 19:26:47 +0300 MSK
- 4.7.764: 2025-08-06 16:17:09 +0300 MSK
- 4.7.765: 2025-08-05 20:11:10 +0300 MSK
- 4.7.766: 2025-08-04 19:06:02 +0300 MSK
- 4.7.767: 2025-08-03 16:36:16 +0300 MSK
- 4.7.768: 2025-08-03 16:21:01 +0300 MSK
- 4.7.769: 2025-08-03 16:03:54 +0300 MSK
- 4.7.770: 2025-08-03 15:13:16 +0300 MSK
- 4.7.771: 2025-08-03 15:01:18 +0300 MSK
- 4.7.772: 2025-08-03 14:57:57 +0300 MSK
- 4.7.773: 2025-08-03 14:56:16 +0300 MSK
- 4.7.774: 2025-08-03 14:39:49 +0300 MSK
- 4.7.775: 2025-08-03 14:36:46 +0300 MSK
- 4.7.776: 2025-08-03 14:33:50 +0300 MSK
- 4.7.777: 2025-08-03 14:29:35 +0300 MSK
- 4.7.778: 2025-08-03 14:27:36 +0300 MSK
- 4.7.779: 2025-08-03 14:18:22 +0300 MSK
- 4.7.780: 2025-08-03 14:14:27 +0300 MSK
- 4.7.781: 2025-08-03 13:56:55 +0300 MSK
- 4.7.782: 2025-08-03 13:42:44 +0300 MSK
- 4.7.783: 2025-08-03 13:35:23 +0300 MSK
- 4.7.784: 2025-08-03 13:30:55 +0300 MSK
- 4.7.785: 2025-08-03 13:25:11 +0300 MSK
- 4.7.786: 2025-08-03 13:22:53 +0300 MSK
- 4.7.787: 2025-08-03 13:19:10 +0300 MSK
- 4.7.788: 2025-08-03 11:38:37 +0300 MSK
- 4.7.789: 2025-08-03 10:42:15 +0300 MSK
- 4.7.790: 2025-08-03 10:26:28 +0300 MSK
- 4.7.791: 2025-08-02 20:09:46 +0300 MSK
- 4.7.792: 2025-08-02 20:03:30 +0300 MSK
- 4.7.793: 2025-08-02 19:58:48 +0300 MSK
- 4.7.794: 2025-08-02 19:54:21 +0300 MSK
- 4.7.795: 2025-08-02 19:50:44 +0300 MSK
- 4.7.796: 2025-08-02 19:45:12 +0300 MSK
- 4.7.797: 2025-08-02 19:36:06 +0300 MSK
- 4.7.798: 2025-08-02 19:28:39 +0300 MSK
- 4.7.799: 2025-08-02 19:24:42 +0300 MSK
- 4.7.800: 2025-08-02 19:22:20 +0300 MSK
- 4.7.801: 2025-08-02 19:12:42 +0300 MSK
- 4.7.802: 2025-08-02 19:08:24 +0300 MSK
- 4.7.803: 2025-08-02 18:59:52 +0300 MSK
- 4.7.804: 2025-08-02 18:49:48 +0300 MSK
- 4.7.805: 2025-08-02 18:45:57 +0300 MSK
- 4.7.806: 2025-08-02 18:40:13 +0300 MSK
- 4.7.807: 2025-08-02 18:33:48 +0300 MSK
- 4.7.808: 2025-08-02 18:22:51 +0300 MSK
- 4.7.809: 2025-08-02 18:14:37 +0300 MSK
- 4.7.810: 2025-08-02 18:07:54 +0300 MSK
- 4.7.811: 2025-08-02 18:04:04 +0300 MSK
- 4.7.812: 2025-08-02 17:59:03 +0300 MSK
- 4.7.813: 2025-08-02 17:54:14 +0300 MSK
- 4.7.814: 2025-08-02 17:28:54 +0300 MSK
- 4.7.815: 2025-08-02 17:26:28 +0300 MSK
- 4.7.816: 2025-08-02 17:24:46 +0300 MSK
- 4.7.817: 2025-08-02 17:06:00 +0300 MSK
- 4.7.818: 2025-08-02 16:50:59 +0300 MSK
- 4.7.819: 2025-08-02 16:38:17 +0300 MSK
- 4.7.820: 2025-08-02 16:29:04 +0300 MSK
- 4.7.821: 2025-08-02 16:25:49 +0300 MSK
- 4.7.822: 2025-08-02 16:11:25 +0300 MSK
- 4.7.823: 2025-08-02 16:04:47 +0300 MSK
- 4.7.824: 2025-08-02 15:56:06 +0300 MSK
- 4.7.825: 2025-08-02 15:46:47 +0300 MSK
- 4.7.826: 2025-08-02 15:43:09 +0300 MSK
- 4.7.827: 2025-08-02 15:41:03 +0300 MSK
- 4.7.828: 2025-08-02 15:39:53 +0300 MSK
- 4.7.829: 2025-08-02 15:34:16 +0300 MSK
- 4.7.830: 2025-08-02 15:27:49 +0300 MSK
- 4.7.831: 2025-08-02 15:19:46 +0300 MSK
- 4.7.832: 2025-08-02 15:01:25 +0300 MSK
- 4.7.833: 2025-08-02 14:54:02 +0300 MSK
- 4.7.834: 2025-08-02 14:25:28 +0300 MSK
- 4.7.835: 2025-08-02 14:21:50 +0300 MSK
- 4.7.836: 2025-08-02 14:15:20 +0300 MSK
- 4.7.837: 2025-08-02 14:10:21 +0300 MSK
- 4.7.838: 2025-08-02 14:00:42 +0300 MSK
- 4.7.839: 2025-08-02 13:55:22 +0300 MSK
- 4.7.840: 2025-08-02 13:54:26 +0300 MSK
- 4.7.841: 2025-08-02 13:48:16 +0300 MSK
- 4.7.842: 2025-08-02 13:02:23 +0300 MSK
- 4.7.843: 2025-08-02 12:36:15 +0300 MSK
- 4.7.844: 2025-08-02 12:22:49 +0300 MSK
- 4.7.845: 2025-08-02 11:12:11 +0300 MSK
- 4.7.846: 2025-08-02 10:56:41 +0300 MSK
- 4.7.847: 2025-08-02 10:53:44 +0300 MSK
- 4.7.848: 2025-08-02 10:46:44 +0300 MSK
- 4.7.849: 2025-08-02 10:41:17 +0300 MSK
- 4.7.850: 2025-08-02 10:38:33 +0300 MSK
- 4.7.851: 2025-08-02 10:31:09 +0300 MSK
- 4.7.852: 2025-08-02 10:28:21 +0300 MSK
- 4.7.853: 2025-08-02 09:19:39 +0300 MSK
- 4.7.854: 2025-08-02 09:15:14 +0300 MSK
- 4.7.855: 2025-08-02 09:11:31 +0300 MSK
- 4.7.856: 2025-08-02 09:03:11 +0300 MSK
- 4.7.857: 2025-08-02 08:55:10 +0300 MSK
- 4.7.858: 2025-08-02 08:53:28 +0300 MSK
- 4.7.859: 2025-08-02 08:48:51 +0300 MSK
- 4.7.860: 2025-08-02 08:38:26 +0300 MSK
- 4.7.861: 2025-08-02 08:34:40 +0300 MSK
- 4.7.862: 2025-08-01 21:34:49 +0300 MSK
- 4.7.863: 2025-08-01 21:23:46 +0300 MSK
- 4.7.864: 2025-08-01 20:49:53 +0300 MSK
- 4.7.865: 2025-08-01 20:14:01 +0300 MSK
- 4.7.866: 2025-08-01 19:32:18 +0300 MSK
- 4.7.867: 2025-08-01 19:30:30 +0300 MSK
- 4.7.868: 2025-08-01 19:27:17 +0300 MSK
- 4.7.869: 2025-08-01 19:18:48 +0300 MSK
- 4.7.870: 2025-08-01 19:16:55 +0300 MSK
- 4.7.871: 2025-08-01 17:46:26 +0300 MSK
- 4.7.872: 2025-08-01 17:40:59 +0300 MSK
- 4.7.873: 2025-08-01 17:39:13 +0300 MSK
- 4.7.874: 2025-08-01 17:12:58 +0300 MSK
- 4.7.875: 2025-08-01 16:57:25 +0300 MSK
- 4.7.876: 2025-08-01 16:53:59 +0300 MSK
- 4.7.877: 2025-08-01 16:43:05 +0300 MSK
- 4.7.878: 2025-08-01 16:39:51 +0300 MSK
- 4.7.879: 2025-08-01 16:33:40 +0300 MSK
- 4.7.880: 2025-08-01 16:24:11 +0300 MSK
- 4.7.881: 2025-08-01 16:02:30 +0300 MSK
- 4.7.882: 2025-08-01 16:01:56 +0300 MSK
- 4.7.883: 2025-08-01 15:50:58 +0300 MSK
- 4.7.884: 2025-08-01 15:30:00 +0300 MSK
- 4.7.885: 2025-08-01 14:50:20 +0300 MSK
- 4.7.886: 2025-08-01 13:28:24 +0300 MSK
- 4.7.887: 2025-08-01 13:24:00 +0300 MSK
- 4.7.888: 2025-08-01 13:12:38 +0300 MSK
- 4.7.889: 2025-08-01 09:59:43 +0300 MSK
- 4.7.890: 2025-08-01 09:40:56 +0300 MSK
- 4.7.891: 2025-08-01 08:25:54 +0300 MSK
- 4.7.892: 2025-08-01 08:21:20 +0300 MSK
- 4.7.893: 2025-08-01 08:13:47 +0300 MSK
- 4.7.894: 2025-08-01 07:59:37 +0300 MSK
- 4.7.895: 2025-08-01 07:51:03 +0300 MSK
- 4.7.896: 2025-08-01 07:33:33 +0300 MSK
- 4.7.897: 2025-08-01 07:15:40 +0300 MSK
- 4.7.898: 2025-07-31 21:28:35 +0300 MSK
- 4.7.899: 2025-07-31 18:46:45 +0300 MSK
- 4.7.900: 2025-07-31 18:31:00 +0300 MSK
- 4.7.901: 2025-07-31 18:29:59 +0300 MSK
- 4.7.902: 2025-07-31 18:14:30 +0300 MSK
- 4.7.903: 2025-07-31 17:53:16 +0300 MSK
- 4.7.904: 2025-07-31 17:18:00 +0300 MSK
- 4.7.905: 2025-07-31 17:16:38 +0300 MSK
- 4.7.906: 2025-07-31 17:05:37 +0300 MSK
- 4.7.907: 2025-07-31 14:35:36 +0300 MSK
- 4.7.908: 2025-07-31 13:54:58 +0300 MSK
- 4.7.909: 2025-07-31 13:46:42 +0300 MSK
- 4.7.910: 2025-07-31 13:03:46 +0300 MSK
- 4.7.911: 2025-07-31 11:07:49 +0300 MSK
- 4.7.912: 2025-07-31 11:00:20 +0300 MSK
- 4.7.913: 2025-07-31 10:28:31 +0300 MSK
- 4.7.914: 2025-07-31 10:04:49 +0300 MSK
- 4.7.915: 2025-07-30 22:05:38 +0300 MSK
- 4.7.916: 2025-07-30 22:00:12 +0300 MSK
- 4.7.917: 2025-07-30 21:55:12 +0300 MSK
- 4.7.918: 2025-07-30 21:02:37 +0300 MSK
- 4.7.919: 2025-07-30 20:59:49 +0300 MSK
- 4.7.920: 2025-07-30 20:52:44 +0300 MSK
- 4.7.921: 2025-07-30 20:47:51 +0300 MSK
- 4.7.922: 2025-07-30 20:42:31 +0300 MSK
- 4.7.923: 2025-07-30 20:35:12 +0300 MSK
- 4.7.924: 2025-07-30 20:27:09 +0300 MSK
- 4.7.925: 2025-07-30 20:12:39 +0300 MSK
- 4.7.926: 2025-07-30 20:09:55 +0300 MSK
- 4.7.927: 2025-07-30 20:05:18 +0300 MSK
- 4.7.928: 2025-07-30 19:52:43 +0300 MSK
- 4.7.929: 2025-07-30 19:27:05 +0300 MSK
- 4.7.930: 2025-07-30 19:18:29 +0300 MSK
- 4.7.931: 2025-07-30 19:14:46 +0300 MSK
- 4.7.932: 2025-07-30 19:11:57 +0300 MSK
- 4.7.933: 2025-07-30 18:59:58 +0300 MSK
- 4.7.934: 2025-07-30 18:49:52 +0300 MSK
- 4.7.935: 2025-07-30 18:45:39 +0300 MSK
- 4.7.936: 2025-07-30 18:44:00 +0300 MSK
- 4.7.937: 2025-07-30 18:35:45 +0300 MSK
- 4.7.938: 2025-07-30 18:32:15 +0300 MSK
- 4.7.939: 2025-07-30 18:31:28 +0300 MSK
- 4.7.940: 2025-07-30 18:25:43 +0300 MSK
- 4.7.941: 2025-07-30 18:19:10 +0300 MSK
- 4.7.942: 2025-07-30 18:07:19 +0300 MSK
- 4.7.943: 2025-07-30 17:54:50 +0300 MSK
- 4.7.944: 2025-07-30 17:36:45 +0300 MSK
- 4.7.945: 2025-07-30 16:27:11 +0300 MSK
- 4.7.946: 2025-07-30 16:07:35 +0300 MSK
- 4.7.947: 2025-07-30 16:04:16 +0300 MSK
- 4.7.948: 2025-07-30 15:53:02 +0300 MSK
- 4.7.949: 2025-07-30 15:50:06 +0300 MSK
- 4.7.950: 2025-07-30 15:40:51 +0300 MSK
- 4.7.951: 2025-07-30 15:11:27 +0300 MSK
- 4.7.952: 2025-07-30 15:08:16 +0300 MSK
- 4.7.953: 2025-07-30 15:06:29 +0300 MSK
- 4.7.954: 2025-07-30 14:49:28 +0300 MSK
- 4.7.955: 2025-07-29 21:27:41 +0300 MSK
- 4.7.956: 2025-07-29 21:05:02 +0300 MSK
- 4.7.957: 2025-07-29 20:50:01 +0300 MSK
- 4.7.958: 2025-07-29 20:45:22 +0300 MSK
- 4.7.959: 2025-07-29 19:17:54 +0300 MSK
- 4.7.960: 2025-07-29 18:55:38 +0300 MSK
- 4.7.961: 2025-07-29 18:52:23 +0300 MSK
- 4.7.962: 2025-07-29 18:27:23 +0300 MSK
- 4.7.963: 2025-07-29 17:59:54 +0300 MSK
- 4.7.964: 2025-07-29 17:38:44 +0300 MSK
- 4.7.965: 2025-07-29 17:38:31 +0300 MSK
- 4.7.966: 2025-07-29 16:37:09 +0300 MSK
- 4.7.967: 2025-07-29 16:11:49 +0300 MSK
- 4.7.968: 2025-07-29 13:59:48 +0300 MSK
- 4.7.969: 2025-07-28 20:06:14 +0300 MSK
- 4.7.970: 2025-07-28 19:28:55 +0300 MSK
- 4.7.971: 2025-07-28 16:53:12 +0300 MSK
- 4.7.972: 2025-07-28 16:52:43 +0300 MSK
- 4.7.973: 2025-07-28 16:45:20 +0300 MSK
- 4.7.974: 2025-07-28 16:35:55 +0300 MSK
- 4.7.975: 2025-07-28 16:25:34 +0300 MSK
- 4.7.976: 2025-07-27 19:03:38 +0300 MSK
- 4.7.977: 2025-07-26 18:50:49 +0300 MSK
- 4.7.978: 2025-07-26 18:48:20 +0300 MSK
- 4.7.979: 2025-07-25 13:23:28 +0300 MSK
- 4.7.980: 2025-07-25 13:15:13 +0300 MSK
- 4.7.981: 2025-07-25 13:14:11 +0300 MSK
- 4.7.982: 2025-07-25 12:37:39 +0300 MSK
- 4.7.983: 2025-07-25 12:29:53 +0300 MSK
- 4.7.984: 2025-07-25 12:18:12 +0300 MSK
- 4.7.985: 2025-07-25 12:07:53 +0300 MSK
- 4.7.986: 2025-07-25 11:57:05 +0300 MSK
- 4.7.987: 2025-07-25 09:50:01 +0300 MSK
- 4.7.988: 2025-07-24 18:52:24 +0300 MSK
- 4.7.989: 2025-07-24 17:40:53 +0300 MSK
- 4.7.990: 2025-07-20 16:53:28 +0300 MSK
- 4.7.991: 2025-04-15 16:14:06 +0300 MSK
- 4.7.992: 2025-04-14 19:45:07 +0300 MSK
- 4.7.993: 2025-04-13 17:10:23 +0300 MSK
- 4.7.994: 2025-04-12 19:10:13 +0300 MSK
- 4.7.995: 2025-04-11 20:06:54 +0300 MSK
- 4.7.996: 2025-04-10 19:50:16 +0300 MSK
- 4.7.997: 2025-04-09 19:33:13 +0300 MSK
- 4.7.998: 2024-06-28 19:53:30 +0300 MSK
- 4.7.999: 2024-06-26 18:39:14 +0300 MSK
- 4.7.1000: 2024-06-25 20:07:01 +0300 MSK
- 4.7.1001: 2024-06-24 15:55:17 +0300 MSK
- 4.7.1002: 2024-06-23 14:38:18 +0300 MSK
- 4.7.1003: 2024-06-22 16:33:20 +0300 MSK
- 4.7.1004: 2024-06-21 19:21:07 +0300 MSK
- 4.7.1005: 2024-06-19 19:59:31 +0300 MSK
- 4.7.1006: 2024-06-17 15:39:57 +0300 MSK
- 4.7.1007: 2024-06-15 13:32:54 +0300 MSK
- 4.7.1008: 2024-06-14 18:54:35 +0300 MSK
- 4.7.1009: 2024-06-13 10:32:12 +0300 MSK
- 4.7.1010: 2024-06-12 19:59:15 +0300 MSK
- 4.7.1011: 2024-06-11 20:57:06 +0300 MSK
- 4.7.1012: 2024-06-10 13:15:44 +0300 MSK
- 4.7.1013: 2024-06-09 13:56:45 +0300 MSK
- 4.7.1014: 2024-06-08 22:13:27 +0300 MSK
- 4.7.1015: 2024-06-07 18:18:51 +0300 MSK
- 4.7.1016: 2024-06-06 18:22:03 +0300 MSK
- 4.7.1017: 2024-06-05 10:32:36 +0300 MSK
- 4.7.1018: 2024-06-03 15:40:20 +0300 MSK
- 4.7.1019: 2024-06-02 21:31:18 +0300 MSK
- 4.7.1020: 2024-06-01 22:04:19 +0300 MSK
- 4.7.1021: 2024-06-01 22:04:02 +0300 MSK
- 4.7.1022: 2024-06-01 22:03:45 +0300 MSK
- 4.7.1023: 2024-06-01 22:01:30 +0300 MSK
- 4.7.1024: 2024-05-29 12:47:46 +0300 MSK
- 4.7.1025: 2024-05-28 20:05:20 +0300 MSK
- 4.7.1026: 2024-05-27 10:56:18 +0300 MSK
- 4.7.1027: 2024-05-26 20:44:15 +0300 MSK
- 4.7.1028: 2024-05-25 22:59:58 +0300 MSK
- 4.7.1029: 2024-05-21 21:02:08 +0300 MSK
- 4.7.1030: 2024-05-20 13:28:49 +0300 MSK
- 4.7.1031: 2024-05-19 15:08:43 +0300 MSK
- 4.7.1032: 2024-05-18 20:24:14 +0300 MSK
- 4.7.1033: 2024-05-17 21:25:39 +0300 MSK
- 4.7.1034: 2024-05-16 18:11:33 +0300 MSK
- 4.7.1035: 2024-05-14 12:06:07 +0300 MSK
- 4.7.1036: 2024-05-13 10:22:15 +0300 MSK
- 4.7.1037: 2024-05-12 21:39:08 +0300 MSK
- 4.7.1038: 2024-05-08 10:50:28 +0300 MSK
- 4.7.1039: 2024-05-08 10:39:08 +0300 MSK
- 4.7.1040: 2024-05-07 10:56:39 +0300 MSK
- 4.7.1041: 2024-05-06 16:47:26 +0300 MSK
- 4.7.1042: 2024-05-04 18:08:36 +0300 MSK
- 4.7.1043: 2024-05-03 17:41:51 +0300 MSK
- 4.7.1044: 2024-05-02 19:49:20 +0300 MSK
- 4.7.1045: 2024-05-01 12:05:11 +0300 MSK
- 4.7.1046: 2024-05-01 12:04:46 +0300 MSK
- 4.7.1047: 2024-05-01 12:04:24 +0300 MSK
- 4.7.1048: 2024-05-01 12:02:52 +0300 MSK
- 4.7.1049: 2024-04-29 21:04:33 +0300 MSK
- 4.7.1050: 2024-04-26 10:34:22 +0300 MSK
- 4.7.1051: 2024-04-25 20:32:24 +0300 MSK
- 4.7.1052: 2024-04-24 15:06:12 +0300 MSK
- 4.7.1053: 2024-04-23 18:14:09 +0300 MSK
- 4.7.1054: 2024-04-22 10:35:20 +0300 MSK
- 4.7.1055: 2024-04-22 10:16:09 +0300 MSK
- 4.7.1056: 2024-04-20 21:02:52 +0300 MSK
- 4.7.1057: 2024-04-19 10:37:47 +0300 MSK
- 4.7.1058: 2024-04-19 10:37:20 +0300 MSK
- 4.7.1059: 2024-04-17 10:49:35 +0300 MSK
- 4.7.1060: 2024-04-16 22:16:34 +0300 MSK
- 4.7.1061: 2024-04-15 09:51:02 +0300 MSK
- 4.7.1062: 2024-04-15 09:49:56 +0300 MSK
- 4.7.1063: 2024-04-13 18:32:47 +0300 MSK
- 4.7.1064: 2024-04-12 10:40:19 +0300 MSK
- 4.7.1065: 2024-04-11 13:44:41 +0300 MSK
- 4.7.1066: 2024-04-10 13:25:18 +0300 MSK
- 4.7.1067: 2024-04-09 14:21:46 +0300 MSK
- 4.7.1068: 2024-04-08 11:25:34 +0300 MSK
- 4.7.1069: 2024-04-07 11:42:18 +0300 MSK
- 4.7.1070: 2024-04-07 11:41:54 +0300 MSK
- 4.7.1071: 2024-04-05 17:17:39 +0300 MSK
- 4.7.1072: 2024-04-04 16:06:45 +0300 MSK
- 4.7.1073: 2024-04-03 10:52:54 +0300 MSK
- 4.7.1074: 2024-04-02 17:28:57 +0300 MSK
- 4.7.1075: 2024-04-01 18:03:03 +0300 MSK
- 4.7.1076: 2024-03-31 10:58:30 +0300 MSK
- 4.7.1077: 2024-03-30 19:24:47 +0300 MSK
- 4.7.1078: 2024-03-29 14:30:16 +0300 MSK
- 4.7.1079: 2024-03-28 19:02:58 +0300 MSK
- 4.7.1080: 2024-03-27 18:55:43 +0300 MSK
- 4.7.1081: 2024-03-26 10:04:37 +0300 MSK
- 4.7.1082: 2024-03-25 19:23:11 +0300 MSK
- 4.7.1083: 2024-03-24 14:27:34 +0300 MSK
- 4.7.1084: 2024-03-24 14:27:17 +0300 MSK
- 4.7.1085: 2024-03-23 20:51:44 +0300 MSK
- 4.7.1086: 2024-03-22 11:45:00 +0300 MSK
- 4.7.1087: 2024-03-22 11:41:12 +0300 MSK
- 4.7.1088: 2024-03-21 14:09:24 +0300 MSK
- 4.7.1089: 2024-03-21 14:05:27 +0300 MSK
- 4.7.1090: 2024-03-21 13:53:28 +0300 MSK
- 4.7.1091: 2024-03-20 21:13:36 +0300 MSK
- 4.7.1092: 2024-03-20 21:12:54 +0300 MSK
- 4.7.1093: 2024-03-18 19:30:56 +0300 MSK
- 4.7.1094: 2024-03-17 12:32:47 +0300 MSK
- 4.7.1095: 2024-03-17 12:32:06 +0300 MSK
- 4.7.1096: 2024-03-15 20:15:18 +0300 MSK
- 4.7.1097: 2024-03-14 19:06:22 +0300 MSK
- 4.7.1098: 2024-03-13 19:53:19 +0300 MSK
- 4.7.1099: 2024-03-12 19:08:41 +0300 MSK
- 4.7.1100: 2024-03-11 19:30:24 +0300 MSK
- 4.7.1101: 2024-03-10 22:58:44 +0300 MSK
- 4.7.1102: 2024-03-09 19:01:11 +0300 MSK
- 4.7.1103: 2024-03-09 18:59:53 +0300 MSK
- 4.7.1104: 2024-03-07 19:08:46 +0300 MSK
- 4.7.1105: 2024-03-07 19:07:46 +0300 MSK
- 4.7.1106: 2024-03-06 16:05:23 +0300 MSK
- 4.7.1107: 2024-03-05 11:52:38 +0300 MSK
- 4.7.1108: 2024-03-04 16:21:41 +0300 MSK
- 4.7.1109: 2024-03-03 10:57:46 +0300 MSK
- 4.7.1110: 2024-03-02 15:59:13 +0300 MSK
- 4.7.1111: 2024-03-02 15:57:16 +0300 MSK
- 4.7.1112: 2024-03-02 15:56:40 +0300 MSK
- 4.7.1113: 2024-03-01 18:28:31 +0300 MSK
- 4.7.1114: 2024-02-29 17:38:44 +0300 MSK
- 4.7.1115: 2024-02-28 12:31:13 +0300 MSK
- 4.7.1116: 2024-02-27 19:25:53 +0300 MSK
- 4.7.1117: 2024-02-26 19:57:46 +0300 MSK
- 4.7.1118: 2024-02-25 20:04:05 +0300 MSK
- 4.7.1119: 2024-02-24 15:45:37 +0300 MSK
- 4.7.1120: 2024-02-23 12:30:25 +0300 MSK
- 4.7.1121: 2024-02-22 11:20:36 +0300 MSK
- 4.7.1122: 2024-02-21 11:42:07 +0300 MSK
- 4.7.1123: 2024-02-20 18:21:21 +0300 MSK
- 4.7.1124: 2024-02-20 18:19:05 +0300 MSK
- 4.7.1125: 2024-02-20 18:16:37 +0300 MSK
- 4.7.1126: 2024-02-20 15:10:36 +0300 MSK
- 4.7.1127: 2024-02-19 11:56:55 +0300 MSK
- 4.7.1128: 2024-02-18 12:45:46 +0300 MSK
- 4.7.1129: 2024-02-17 15:07:38 +0300 MSK
- 4.7.1130: 2024-02-17 15:03:52 +0300 MSK
- 4.7.1131: 2024-02-16 18:29:09 +0300 MSK
- 4.7.1132: 2024-02-15 12:51:25 +0300 MSK
- 4.7.1133: 2024-02-14 10:48:17 +0300 MSK
- 4.7.1134: 2024-02-13 16:10:55 +0300 MSK
- 4.7.1135: 2024-02-12 12:50:44 +0300 MSK
- 4.7.1136: 2024-02-11 16:20:27 +0300 MSK
- 4.7.1137: 2024-02-10 15:12:54 +0300 MSK
- 4.7.1138: 2024-02-09 19:12:32 +0300 MSK
- 4.7.1139: 2024-02-08 15:50:03 +0300 MSK
- 4.7.1140: 2024-02-07 10:59:44 +0300 MSK
- 4.7.1141: 2024-02-07 10:54:21 +0300 MSK
- 4.7.1142: 2024-02-07 10:52:55 +0300 MSK
- 4.7.1143: 2024-02-07 10:49:08 +0300 MSK
- 4.7.1144: 2024-02-06 09:02:52 +0300 MSK
- 4.7.1145: 2024-02-05 10:12:58 +0300 MSK
- 4.7.1146: 2024-02-04 15:38:07 +0300 MSK
- 4.7.1147: 2024-02-04 15:17:08 +0300 MSK
- 4.7.1148: 2024-02-02 19:53:06 +0300 MSK
- 4.7.1149: 2024-02-02 19:52:11 +0300 MSK
- 4.7.1150: 2024-02-02 19:51:07 +0300 MSK
- 4.7.1151: 2024-01-31 11:09:51 +0300 MSK
- 4.7.1152: 2024-01-30 15:36:53 +0300 MSK
- 4.7.1153: 2024-01-29 09:44:33 +0300 MSK
- 4.7.1154: 2024-01-28 13:34:03 +0300 MSK
- 4.7.1155: 2024-01-27 10:05:52 +0300 MSK
- 4.7.1156: 2024-01-26 11:02:15 +0300 MSK
- 4.7.1157: 2024-01-25 17:31:23 +0300 MSK
- 4.7.1158: 2024-01-24 10:39:27 +0300 MSK
- 4.7.1159: 2024-01-24 10:27:08 +0300 MSK
- 4.7.1160: 2024-01-23 10:54:38 +0300 MSK
- 4.7.1161: 2024-01-22 12:39:06 +0300 MSK
- 4.7.1162: 2024-01-21 21:12:22 +0300 MSK
- 4.7.1163: 2024-01-20 17:21:44 +0300 MSK
- 4.7.1164: 2024-01-19 11:46:22 +0300 MSK
- 4.7.1165: 2024-01-19 11:45:33 +0300 MSK
- 4.7.1166: 2024-01-18 13:27:10 +0300 MSK
- 4.7.1167: 2024-01-17 19:14:04 +0300 MSK
- 4.7.1168: 2024-01-16 11:04:01 +0300 MSK
- 4.7.1169: 2024-01-15 11:45:13 +0300 MSK
- 4.7.1170: 2024-01-14 17:27:29 +0300 MSK
- 4.7.1171: 2024-01-13 17:33:48 +0300 MSK
- 4.7.1172: 2024-01-12 23:55:40 +0300 MSK
- 4.7.1173: 2024-01-11 12:15:51 +0300 MSK
- 4.7.1174: 2024-01-10 11:34:26 +0300 MSK
- 4.7.1175: 2024-01-09 19:45:41 +0300 MSK
- 4.7.1176: 2024-01-08 17:44:21 +0300 MSK
- 4.7.1177: 2024-01-07 12:26:09 +0300 MSK
- 4.7.1178: 2024-01-07 12:23:04 +0300 MSK
- 4.7.1179: 2024-01-05 13:00:49 +0300 MSK
- 4.7.1180: 2024-01-04 14:11:50 +0300 MSK
- 4.7.1181: 2024-01-03 14:46:50 +0300 MSK
- 4.7.1182: 2024-01-02 15:20:19 +0300 MSK
- 4.7.1183: 2024-01-01 16:10:42 +0300 MSK
- 4.7.1184: 2023-12-31 13:19:35 +0300 MSK
- 4.7.1185: 2023-12-30 14:22:38 +0300 MSK
- 4.7.1186: 2023-12-29 10:09:26 +0300 MSK
- 4.7.1187: 2023-12-28 10:12:36 +0300 MSK
- 4.7.1188: 2023-12-27 11:51:17 +0300 MSK
- 4.7.1189: 2023-12-26 11:08:25 +0300 MSK
- 4.7.1190: 2023-12-25 10:53:55 +0300 MSK
- 4.7.1191: 2023-12-24 12:54:15 +0300 MSK
- 4.7.1192: 2023-12-24 00:41:36 +0300 MSK
- 4.7.1193: 2023-12-22 11:52:14 +0300 MSK
- 4.7.1194: 2023-12-21 08:42:34 +0300 MSK
- 4.7.1195: 2023-12-20 14:05:16 +0300 MSK
- 4.7.1196: 2023-12-19 11:24:47 +0300 MSK
- 4.7.1197: 2023-12-18 13:27:09 +0300 MSK
- 4.7.1198: 2023-12-17 12:09:37 +0300 MSK
- 4.7.1199: 2023-12-16 13:01:55 +0300 MSK
- 4.7.1200: 2023-12-15 10:56:18 +0300 MSK
- 4.7.1201: 2023-12-15 10:54:52 +0300 MSK
- 4.7.1202: 2023-12-14 12:30:55 +0300 MSK
- 4.7.1203: 2023-12-13 11:11:00 +0300 MSK
- 4.7.1204: 2023-12-12 10:39:45 +0300 MSK
- 4.7.1205: 2023-12-11 15:30:35 +0300 MSK
- 4.7.1206: 2023-12-11 10:26:55 +0300 MSK
- 4.7.1207: 2023-12-10 13:46:54 +0300 MSK
- 4.7.1208: 2023-12-10 13:46:22 +0300 MSK
- 4.7.1209: 2023-12-10 13:45:46 +0300 MSK
- 4.7.1210: 2023-12-08 21:03:57 +0300 MSK
- 4.7.1211: 2023-12-07 19:20:48 +0300 MSK
- 4.7.1212: 2023-12-06 12:45:40 +0300 MSK
- 4.7.1213: 2023-12-06 09:43:04 +0300 MSK
- 4.7.1214: 2023-12-05 16:12:24 +0300 MSK
- 4.7.1215: 2023-12-04 11:09:00 +0300 MSK
- 4.7.1216: 2023-12-03 17:53:13 +0300 MSK
- 4.7.1217: 2023-12-02 23:40:09 +0300 MSK
- 4.7.1218: 2023-12-01 11:21:29 +0300 MSK
- 4.7.1219: 2023-11-30 10:50:12 +0300 MSK
- 4.7.1220: 2023-11-29 12:01:45 +0300 MSK
- 4.7.1221: 2023-11-28 13:04:41 +0300 MSK
- 4.7.1222: 2023-11-27 10:32:44 +0300 MSK
- 4.7.1223: 2023-11-27 10:32:13 +0300 MSK
- 4.7.1224: 2023-11-25 22:00:45 +0300 MSK
- 4.7.1225: 2023-11-25 22:00:22 +0300 MSK
- 4.7.1226: 2023-11-24 16:49:32 +0300 MSK
- 4.7.1227: 2023-11-24 16:37:41 +0300 MSK
- 4.7.1228: 2023-11-24 16:36:38 +0300 MSK
- 4.7.1229: 2023-11-24 16:32:52 +0300 MSK
- 4.7.1230: 2023-11-24 11:07:37 +0300 MSK
- 4.7.1231: 2023-11-23 13:41:25 +0300 MSK
- 4.7.1232: 2023-11-22 18:49:02 +0300 MSK
- 4.7.1233: 2023-11-21 12:51:21 +0300 MSK
- 4.7.1234: 2023-11-21 12:44:04 +0300 MSK
- 4.7.1235: 2023-11-21 12:33:13 +0300 MSK
- 4.7.1236: 2023-11-20 18:30:57 +0300 MSK
- 4.7.1237: 2023-11-20 14:40:36 +0300 MSK
- 4.7.1238: 2023-11-20 14:38:40 +0300 MSK
- 4.7.1239: 2023-11-20 14:31:25 +0300 MSK
- 4.7.1240: 2023-11-20 14:29:40 +0300 MSK
- 4.7.1241: 2023-11-20 14:27:13 +0300 MSK
- 4.7.1242: 2023-11-20 14:11:47 +0300 MSK
- 4.7.1243: 2023-11-19 11:31:05 +0300 MSK
- 4.7.1244: 2023-11-18 19:23:48 +0300 MSK
- 4.7.1245: 2023-11-17 17:25:22 +0300 MSK
- 4.7.1246: 2023-11-17 16:41:37 +0300 MSK
- 4.7.1247: 2023-11-17 14:05:35 +0300 MSK
- 4.7.1248: 2023-11-17 14:02:06 +0300 MSK
- 4.7.1249: 2023-11-17 13:13:32 +0300 MSK
- 4.7.1250: 2023-11-17 13:12:34 +0300 MSK
- 4.7.1251: 2023-11-17 13:02:26 +0300 MSK
- 4.7.1252: 2023-11-16 16:43:00 +0300 MSK
- 4.7.1253: 2023-11-16 16:22:50 +0300 MSK
- 4.7.1254: 2023-11-16 14:30:47 +0300 MSK
- 4.7.1255: 2023-11-16 14:18:16 +0300 MSK
- 4.7.1256: 2023-11-16 14:15:58 +0300 MSK
- 4.7.1257: 2023-11-16 14:13:23 +0300 MSK
- 4.7.1258: 2023-11-16 14:06:30 +0300 MSK
- 4.7.1259: 2023-11-16 11:22:37 +0300 MSK
- 4.7.1260: 2023-11-15 16:53:47 +0300 MSK
- 4.7.1261: 2023-11-15 16:12:27 +0300 MSK
- 4.7.1262: 2023-11-15 15:18:40 +0300 MSK
- 4.7.1263: 2023-11-15 15:17:30 +0300 MSK
- 4.7.1264: 2023-11-14 15:39:29 +0300 MSK
- 4.7.1265: 2023-11-13 20:24:55 +0300 MSK
- 4.7.1266: 2023-11-13 10:42:13 +0300 MSK
- 4.7.1267: 2023-11-13 10:40:23 +0300 MSK
- 4.7.1268: 2023-11-13 10:38:46 +0300 MSK
- 4.7.1269: 2023-11-12 17:00:22 +0300 MSK
- 4.7.1270: 2023-11-12 16:08:04 +0300 MSK
- 4.7.1271: 2023-11-12 15:43:55 +0300 MSK
- 4.7.1272: 2023-11-12 15:41:26 +0300 MSK
- 4.7.1273: 2023-11-12 11:40:25 +0300 MSK
- 4.7.1274: 2023-11-11 16:10:00 +0300 MSK
- 4.7.1275: 2023-11-11 16:06:23 +0300 MSK
- 4.7.1276: 2023-11-11 16:06:11 +0300 MSK
- 4.7.1277: 2023-11-11 15:52:58 +0300 MSK
- 4.7.1278: 2023-11-11 15:43:36 +0300 MSK
- 4.7.1279: 2023-11-11 15:32:34 +0300 MSK
- 4.7.1280: 2023-11-11 15:18:39 +0300 MSK
- 4.7.1281: 2023-11-11 15:08:55 +0300 MSK
- 4.7.1282: 2023-11-11 15:06:06 +0300 MSK
- 4.7.1283: 2023-11-11 14:51:09 +0300 MSK
- 4.7.1284: 2023-11-10 19:50:03 +0300 MSK
- 4.7.1285: 2023-11-10 19:49:28 +0300 MSK
- 4.7.1286: 2023-11-10 19:47:59 +0300 MSK
- 4.7.1287: 2023-11-10 19:34:50 +0300 MSK
- 4.7.1288: 2023-11-10 19:18:28 +0300 MSK
- 4.7.1289: 2023-11-10 18:37:59 +0300 MSK
- 4.7.1290: 2023-11-10 16:30:33 +0300 MSK
- 4.7.1291: 2023-11-10 13:30:38 +0300 MSK
- 4.7.1292: 2023-11-10 13:24:56 +0300 MSK
- 4.7.1293: 2023-11-09 10:03:41 +0300 MSK
- 4.7.1294: 2023-11-08 11:09:02 +0300 MSK
- 4.7.1295: 2023-11-07 21:56:45 +0300 MSK
- 4.7.1296: 2023-11-07 21:50:49 +0300 MSK
- 4.7.1297: 2023-11-07 19:07:48 +0300 MSK
- 4.7.1298: 2023-11-06 18:41:34 +0300 MSK
- 4.7.1299: 2023-11-06 14:57:33 +0300 MSK
- 4.7.1300: 2023-11-06 14:49:27 +0300 MSK
- 4.7.1301: 2023-11-05 21:02:40 +0300 MSK
- 4.7.1302: 2023-11-05 12:06:04 +0300 MSK
- 4.7.1303: 2023-11-05 12:01:59 +0300 MSK
- 4.7.1304: 2023-11-04 13:31:04 +0300 MSK
- 4.7.1305: 2023-11-04 13:30:46 +0300 MSK
- 4.7.1306: 2023-11-04 13:30:28 +0300 MSK
- 4.7.1307: 2023-11-04 13:30:08 +0300 MSK
- 4.7.1308: 2023-11-04 13:29:52 +0300 MSK
- 4.7.1309: 2023-11-04 13:29:35 +0300 MSK
- 4.7.1310: 2023-11-04 13:29:17 +0300 MSK
- 4.7.1311: 2023-11-04 13:28:50 +0300 MSK
- 4.7.1312: 2023-11-04 13:28:04 +0300 MSK
- 4.7.1313: 2023-11-04 13:27:48 +0300 MSK
- 4.7.1314: 2023-11-04 13:27:29 +0300 MSK
- 4.7.1315: 2023-11-04 13:27:12 +0300 MSK
- 4.7.1316: 2023-11-04 13:26:43 +0300 MSK
- 4.7.1317: 2023-11-04 13:25:42 +0300 MSK
- 4.7.1318: 2023-11-04 13:25:15 +0300 MSK
- 4.7.1319: 2023-11-04 13:24:58 +0300 MSK
- 4.7.1320: 2023-11-04 13:23:30 +0300 MSK
- 4.7.1321: 2023-11-04 13:22:41 +0300 MSK
- 4.7.1322: 2023-11-04 10:36:18 +0300 MSK
- 4.7.1323: 2023-11-04 10:30:12 +0300 MSK
- 4.7.1324: 2023-11-04 10:29:26 +0300 MSK
- 4.7.1325: 2023-11-03 15:20:27 +0300 MSK
- 4.7.1326: 2023-11-03 12:40:06 +0300 MSK
- 4.7.1327: 2023-11-03 12:14:46 +0300 MSK
- 4.7.1328: 2023-11-03 12:13:05 +0300 MSK
- 4.7.1329: 2023-11-02 14:33:34 +0300 MSK
- 4.7.1330: 2023-11-02 13:32:46 +0300 MSK
- 4.7.1331: 2023-11-01 15:59:19 +0300 MSK
- 4.7.1332: 2023-11-01 15:51:19 +0300 MSK
- 4.7.1333: 2023-11-01 15:01:54 +0300 MSK
- 4.7.1334: 2023-11-01 15:00:05 +0300 MSK
- 4.7.1335: 2023-11-01 12:34:06 +0300 MSK
- 4.7.1336: 2023-11-01 12:32:26 +0300 MSK
- 4.7.1337: 2023-11-01 12:28:17 +0300 MSK
- 4.7.1338: 2023-11-01 12:20:58 +0300 MSK
- 4.7.1339: 2023-10-31 19:12:05 +0300 MSK
- 4.7.1340: 2023-10-31 19:11:41 +0300 MSK
- 4.7.1341: 2023-10-31 18:59:17 +0300 MSK
- 4.7.1342: 2023-10-31 18:18:34 +0300 MSK
- 4.7.1343: 2023-10-31 18:15:28 +0300 MSK
- 4.7.1344: 2023-10-31 18:13:57 +0300 MSK
- 4.7.1345: 2023-10-31 11:33:38 +0300 MSK
- 4.7.1346: 2023-10-31 11:32:41 +0300 MSK
- 4.7.1347: 2023-10-30 16:28:30 +0300 MSK
- 4.7.1348: 2023-10-30 16:16:38 +0300 MSK
- 4.7.1349: 2023-10-30 16:03:18 +0300 MSK
- 4.7.1350: 2023-10-30 15:58:41 +0300 MSK
- 4.7.1351: 2023-10-30 14:32:47 +0300 MSK
- 4.7.1352: 2023-10-30 14:31:36 +0300 MSK
- 4.7.1353: 2023-10-30 14:14:48 +0300 MSK
- 4.7.1354: 2023-10-30 13:59:23 +0300 MSK
- 4.7.1355: 2023-10-30 13:51:15 +0300 MSK
- 4.7.1356: 2023-10-30 13:39:35 +0300 MSK
- 4.7.1357: 2023-10-30 13:33:19 +0300 MSK
- 4.7.1358: 2023-10-30 13:26:37 +0300 MSK
- 4.7.1359: 2023-10-30 13:17:08 +0300 MSK
- 4.7.1360: 2023-10-30 13:16:47 +0300 MSK
- 4.7.1361: 2023-10-30 13:16:38 +0300 MSK
- 4.7.1362: 2023-10-30 13:13:00 +0300 MSK
- 4.7.1363: 2023-10-30 12:17:05 +0300 MSK
- 4.7.1364: 2023-10-30 12:10:35 +0300 MSK
- 4.7.1365: 2023-10-30 10:51:12 +0300 MSK
- 4.7.1366: 2023-10-29 19:36:33 +0300 MSK
- 4.7.1367: 2023-10-28 17:51:04 +0300 MSK
- 4.7.1368: 2023-10-27 17:47:50 +0300 MSK
- 4.7.1369: 2023-10-26 23:07:22 +0300 MSK
- 4.7.1370: 2023-10-25 13:37:39 +0300 MSK
- 4.7.1371: 2023-10-25 11:31:06 +0300 MSK
- 4.7.1372: 2023-10-24 14:55:16 +0300 MSK
- 4.7.1373: 2023-10-23 12:26:07 +0300 MSK
- 4.7.1374: 2023-10-22 13:57:47 +0300 MSK
- 4.7.1375: 2023-10-21 14:20:53 +0300 MSK
- 4.7.1376: 2023-10-20 16:11:39 +0300 MSK
- 4.7.1377: 2023-10-20 16:06:36 +0300 MSK
- 4.7.1378: 2023-10-19 17:09:46 +0300 MSK
- 4.7.1379: 2023-10-18 19:38:53 +0300 MSK
- 4.7.1380: 2023-10-17 18:45:21 +0300 MSK
- 4.7.1381: 2023-10-16 20:32:07 +0300 MSK
- 4.7.1382: 2023-10-15 13:05:28 +0300 MSK
- 4.7.1383: 2023-10-14 19:53:26 +0300 MSK
- 4.7.1384: 2023-10-14 10:14:40 +0300 MSK
- 4.7.1385: 2023-10-12 12:09:45 +0300 MSK
- 4.7.1386: 2023-10-11 16:06:35 +0300 MSK
- 4.7.1387: 2023-10-10 08:23:28 +0300 MSK
- 4.7.1388: 2023-10-09 14:15:25 +0300 MSK
- 4.7.1389: 2023-10-08 10:39:44 +0300 MSK
- 4.7.1390: 2023-10-07 19:48:10 +0300 MSK
- 4.7.1391: 2023-10-06 12:24:39 +0300 MSK
- 4.7.1392: 2023-10-06 12:24:09 +0300 MSK
- 4.7.1393: 2023-10-05 09:46:37 +0300 MSK
- 4.7.1394: 2023-10-04 09:00:01 +0300 MSK
- 4.7.1395: 2023-10-04 08:57:26 +0300 MSK
- 4.7.1396: 2023-10-03 09:14:03 +0300 MSK
- 4.7.1397: 2023-10-03 09:13:40 +0300 MSK
- 4.7.1398: 2023-10-03 09:13:11 +0300 MSK
- 4.7.1399: 2023-10-02 15:20:53 +0300 MSK
- 4.7.1400: 2023-10-01 16:29:08 +0300 MSK
- 4.7.1401: 2023-09-30 10:17:26 +0300 MSK
- 4.7.1402: 2023-09-30 10:09:04 +0300 MSK
- 4.7.1403: 2023-09-30 10:05:56 +0300 MSK
- 4.7.1404: 2023-09-29 08:36:09 +0300 MSK
- 4.7.1405: 2023-09-28 10:17:33 +0300 MSK
- 4.7.1406: 2023-09-28 10:13:16 +0300 MSK
- 4.7.1407: 2023-09-27 18:11:20 +0300 MSK
- 4.7.1408: 2023-09-26 13:43:09 +0300 MSK
- 4.7.1409: 2023-09-25 09:17:00 +0300 MSK
- 4.7.1410: 2023-09-25 08:28:38 +0300 MSK
- 4.7.1411: 2023-09-25 08:26:39 +0300 MSK
- 4.7.1412: 2023-09-24 14:37:54 +0300 MSK
- 4.7.1413: 2023-09-24 13:28:55 +0300 MSK
- 4.7.1414: 2023-09-24 13:26:28 +0300 MSK
- 4.7.1415: 2023-09-24 13:00:11 +0300 MSK
- 4.7.1416: 2023-09-24 12:59:51 +0300 MSK
- 4.7.1417: 2023-09-24 12:59:24 +0300 MSK
- 4.7.1418: 2023-09-24 12:56:43 +0300 MSK
- 4.7.1419: 2023-09-24 12:56:22 +0300 MSK
- 4.7.1420: 2023-09-24 12:55:57 +0300 MSK
- 4.7.1421: 2023-09-24 12:55:41 +0300 MSK
- 4.7.1422: 2023-09-24 12:55:19 +0300 MSK
- 4.7.1423: 2023-09-24 12:54:51 +0300 MSK
- 4.7.1424: 2023-09-24 12:53:12 +0300 MSK
- 4.7.1425: 2023-09-24 12:52:56 +0300 MSK
- 4.7.1426: 2023-09-24 12:52:34 +0300 MSK
- 4.7.1427: 2023-09-24 12:52:13 +0300 MSK
- 4.7.1428: 2023-09-24 12:51:48 +0300 MSK
- 4.7.1429: 2023-09-24 12:50:52 +0300 MSK
- 4.7.1430: 2023-09-24 12:50:33 +0300 MSK
- 4.7.1431: 2023-09-24 12:47:07 +0300 MSK
- 4.7.1432: 2023-09-24 12:44:33 +0300 MSK
- 4.7.1433: 2023-09-24 12:41:55 +0300 MSK
- 4.7.1434: 2023-09-24 12:41:37 +0300 MSK
- 4.7.1435: 2023-09-24 12:40:45 +0300 MSK
- 4.7.1436: 2023-09-24 12:40:14 +0300 MSK
- 4.7.1437: 2023-09-24 12:39:52 +0300 MSK
- 4.7.1438: 2023-09-24 12:38:31 +0300 MSK
- 4.7.1439: 2023-09-24 12:09:18 +0300 MSK
- 4.7.1440: 2023-09-23 21:54:59 +0300 MSK
- 4.7.1441: 2023-09-23 18:06:03 +0300 MSK
- 4.7.1442: 2023-09-23 13:19:00 +0300 MSK
- 4.7.1443: 2023-09-22 18:29:58 +0300 MSK
- 4.7.1444: 2023-09-22 13:51:50 +0300 MSK
- 4.7.1445: 2023-09-22 13:49:11 +0300 MSK
- 4.7.1446: 2023-09-22 12:14:22 +0300 MSK
- 4.7.1447: 2023-09-22 11:34:42 +0300 MSK
- 4.7.1448: 2023-09-22 11:27:41 +0300 MSK
- 4.7.1449: 2023-09-22 11:23:55 +0300 MSK
- 4.7.1450: 2023-09-22 10:24:39 +0300 MSK
- 4.7.1451: 2023-09-22 08:57:07 +0300 MSK
- 4.7.1452: 2023-09-22 08:51:25 +0300 MSK
- 4.7.1453: 2023-09-21 19:36:09 +0300 MSK
- 4.7.1454: 2023-09-21 19:11:34 +0300 MSK
- 4.7.1455: 2023-09-21 18:33:03 +0300 MSK
- 4.7.1456: 2023-09-21 09:51:52 +0300 MSK
- 4.7.1457: 2023-09-20 22:32:26 +0300 MSK
- 4.7.1458: 2023-09-20 22:28:16 +0300 MSK
- 4.7.1459: 2023-09-20 22:22:48 +0300 MSK
- 4.7.1460: 2023-09-20 22:20:17 +0300 MSK
- 4.7.1461: 2023-09-20 19:50:56 +0300 MSK
- 4.7.1462: 2023-09-20 19:35:10 +0300 MSK
- 4.7.1463: 2023-09-20 19:07:10 +0300 MSK
- 4.7.1464: 2023-09-20 18:36:36 +0300 MSK
- 4.7.1465: 2023-09-20 18:32:58 +0300 MSK
- 4.7.1466: 2023-09-20 18:32:51 +0300 MSK
- 4.7.1467: 2023-09-20 18:32:34 +0300 MSK
- 4.7.1468: 2023-09-20 18:02:39 +0300 MSK
- 4.7.1469: 2023-09-20 18:01:50 +0300 MSK
- 4.7.1470: 2023-09-20 17:28:42 +0300 MSK
- 4.7.1471: 2023-09-20 17:07:50 +0300 MSK
- 4.7.1472: 2023-09-20 16:31:32 +0300 MSK
- 4.7.1473: 2023-09-20 11:47:24 +0300 MSK
- 4.7.1474: 2023-09-19 21:08:16 +0300 MSK
- 4.7.1475: 2023-09-19 20:00:19 +0300 MSK
- 4.7.1476: 2023-09-19 19:58:37 +0300 MSK
- 4.7.1477: 2023-09-18 15:46:36 +0300 MSK
- 4.7.1478: 2023-09-18 15:46:14 +0300 MSK
- 4.7.1479: 2023-09-18 15:38:04 +0300 MSK
- 4.7.1480: 2023-09-18 15:35:47 +0300 MSK
- 4.7.1481: 2023-09-18 15:12:57 +0300 MSK
- 4.7.1482: 2023-09-18 15:12:07 +0300 MSK
- 4.7.1483: 2023-09-18 15:00:25 +0300 MSK
- 4.7.1484: 2023-09-18 14:59:16 +0300 MSK
- 4.7.1485: 2023-09-18 14:37:29 +0300 MSK
- 4.7.1486: 2023-09-18 14:34:48 +0300 MSK
- 4.7.1487: 2023-09-18 13:54:11 +0300 MSK
- 4.7.1488: 2023-09-18 09:47:53 +0300 MSK
- 4.7.1489: 2023-09-17 16:27:05 +0300 MSK
- 4.7.1490: 2023-09-17 16:16:53 +0300 MSK
- 4.7.1491: 2023-09-17 16:14:59 +0300 MSK
- 4.7.1492: 2023-09-17 16:12:53 +0300 MSK
- 4.7.1493: 2023-09-17 16:08:12 +0300 MSK
- 4.7.1494: 2023-09-17 11:45:39 +0300 MSK
- 4.7.1495: 2023-09-17 11:44:04 +0300 MSK
- 4.7.1496: 2023-09-17 11:40:01 +0300 MSK
- 4.7.1497: 2023-09-16 21:10:06 +0300 MSK
- 4.7.1498: 2023-09-16 21:07:33 +0300 MSK
- 4.7.1499: 2023-09-16 20:44:34 +0300 MSK
- 4.7.1500: 2023-09-16 20:20:21 +0300 MSK
- 4.7.1501: 2023-09-16 20:18:19 +0300 MSK
- 4.7.1502: 2023-09-16 15:46:43 +0300 MSK
- 4.7.1503: 2023-09-16 15:35:37 +0300 MSK
- 4.7.1504: 2023-09-16 15:34:15 +0300 MSK
- 4.7.1505: 2023-09-16 11:35:52 +0300 MSK
- 4.7.1506: 2023-09-16 11:25:54 +0300 MSK
- 4.7.1507: 2023-09-15 19:59:56 +0300 MSK
- 4.7.1508: 2023-09-15 19:53:02 +0300 MSK
- 4.7.1509: 2023-09-15 19:34:44 +0300 MSK
- 4.7.1510: 2023-09-15 19:33:23 +0300 MSK
- 4.7.1511: 2023-09-15 19:12:52 +0300 MSK
- 4.7.1512: 2023-09-15 19:05:16 +0300 MSK
- 4.7.1513: 2023-09-15 19:02:42 +0300 MSK
- 4.7.1514: 2023-09-15 18:53:00 +0300 MSK
- 4.7.1515: 2023-09-15 17:07:59 +0300 MSK
- 4.7.1516: 2023-09-15 12:51:11 +0300 MSK
- 4.7.1517: 2023-09-15 09:59:15 +0300 MSK
- 4.7.1518: 2023-09-14 19:02:15 +0300 MSK
- 4.7.1519: 2023-09-14 18:45:02 +0300 MSK
- 4.7.1520: 2023-09-14 18:44:27 +0300 MSK
- 4.7.1521: 2023-09-14 18:40:55 +0300 MSK
- 4.7.1522: 2023-09-14 18:08:10 +0300 MSK
- 4.7.1523: 2023-09-14 14:41:43 +0300 MSK
- 4.7.1524: 2023-09-13 19:20:05 +0300 MSK
- 4.7.1525: 2023-09-13 11:18:48 +0300 MSK
- 4.7.1526: 2023-09-12 19:36:36 +0300 MSK
- 4.7.1527: 2023-09-12 16:32:10 +0300 MSK
- 4.7.1528: 2023-09-12 15:42:35 +0300 MSK
- 4.7.1529: 2023-09-12 15:27:56 +0300 MSK
- 4.7.1530: 2023-09-12 15:23:56 +0300 MSK
- 4.7.1531: 2023-09-12 15:21:06 +0300 MSK
- 4.7.1532: 2023-09-12 14:23:58 +0300 MSK
- 4.7.1533: 2023-09-12 14:12:53 +0300 MSK
- 4.7.1534: 2023-09-12 14:07:17 +0300 MSK
- 4.7.1535: 2023-09-12 14:05:44 +0300 MSK
- 4.7.1536: 2023-09-12 14:05:12 +0300 MSK
- 4.7.1537: 2023-09-12 14:01:45 +0300 MSK
- 4.7.1538: 2023-09-12 11:17:46 +0300 MSK
- 4.7.1539: 2023-09-12 10:55:04 +0300 MSK
- 4.7.1540: 2023-09-11 19:32:16 +0300 MSK
- 4.7.1541: 2023-09-11 19:31:11 +0300 MSK
- 4.7.1542: 2023-09-11 19:16:39 +0300 MSK
- 4.7.1543: 2023-09-11 19:06:00 +0300 MSK
- 4.7.1544: 2023-09-11 18:58:15 +0300 MSK
- 4.7.1545: 2023-09-11 18:55:49 +0300 MSK
- 4.7.1546: 2023-09-11 18:46:11 +0300 MSK
- 4.7.1547: 2023-09-11 18:31:16 +0300 MSK
- 4.7.1548: 2023-09-11 18:30:56 +0300 MSK
- 4.7.1549: 2023-09-11 15:06:55 +0300 MSK
- 4.7.1550: 2023-09-10 12:48:15 +0300 MSK
- 4.7.1551: 2023-09-10 12:37:39 +0300 MSK
- 4.7.1552: 2023-09-09 20:12:03 +0300 MSK
- 4.7.1553: 2023-09-09 20:11:23 +0300 MSK
- 4.7.1554: 2023-09-09 20:10:19 +0300 MSK
- 4.7.1555: 2023-09-09 16:06:56 +0300 MSK
- 4.7.1556: 2023-09-09 10:20:58 +0300 MSK
- 4.7.1557: 2023-09-09 10:20:26 +0300 MSK
- 4.7.1558: 2023-09-08 13:41:10 +0300 MSK
- 4.7.1559: 2023-09-07 20:09:04 +0300 MSK
- 4.7.1560: 2023-09-07 20:00:09 +0300 MSK
- 4.7.1561: 2023-09-07 19:55:32 +0300 MSK
- 4.7.1562: 2023-09-07 17:13:51 +0300 MSK
- 4.7.1563: 2023-09-07 17:13:34 +0300 MSK
- 4.7.1564: 2023-09-07 17:12:50 +0300 MSK
- 4.7.1565: 2023-09-06 14:59:03 +0300 MSK
- 4.7.1566: 2023-09-05 11:41:23 +0300 MSK
- 4.7.1567: 2023-09-04 15:54:45 +0300 MSK
- 4.7.1568: 2023-09-04 12:44:01 +0300 MSK
- 4.7.1569: 2023-09-04 09:37:09 +0300 MSK
- 4.7.1570: 2023-09-03 20:06:29 +0300 MSK
- 4.7.1571: 2023-09-03 19:49:38 +0300 MSK
- 4.7.1572: 2023-09-03 11:23:58 +0300 MSK
- 4.7.1573: 2023-09-02 16:26:14 +0300 MSK
- 4.7.1574: 2023-09-02 10:50:42 +0300 MSK
- 4.7.1575: 2023-09-01 18:41:17 +0300 MSK
- 4.7.1576: 2023-09-01 18:38:28 +0300 MSK
- 4.7.1577: 2023-09-01 18:37:48 +0300 MSK
- 4.7.1578: 2023-09-01 09:58:21 +0300 MSK
- 4.7.1579: 2023-09-01 09:55:13 +0300 MSK
- 4.7.1580: 2023-08-31 22:14:58 +0300 MSK
- 4.7.1581: 2023-08-31 20:45:02 +0300 MSK
- 4.7.1582: 2023-08-31 20:35:52 +0300 MSK
- 4.7.1583: 2023-08-31 20:35:00 +0300 MSK
- 4.7.1584: 2023-08-31 20:34:31 +0300 MSK
- 4.7.1585: 2023-08-31 15:29:43 +0300 MSK
- 4.7.1586: 2023-08-31 12:14:40 +0300 MSK
- 4.7.1587: 2023-08-30 19:06:25 +0300 MSK
- 4.7.1588: 2023-08-29 19:00:49 +0300 MSK
- 4.7.1589: 2023-08-29 18:48:22 +0300 MSK
- 4.7.1590: 2023-08-29 18:48:09 +0300 MSK
- 4.7.1591: 2023-08-29 18:44:17 +0300 MSK
- 4.7.1592: 2023-08-29 18:43:22 +0300 MSK
- 4.7.1593: 2023-08-29 11:50:54 +0300 MSK
- 4.7.1594: 2023-08-28 13:37:58 +0300 MSK
- 4.7.1595: 2023-08-28 13:35:54 +0300 MSK
- 4.7.1596: 2023-08-27 18:09:36 +0300 MSK
- 4.7.1597: 2023-08-27 18:03:23 +0300 MSK
- 4.7.1598: 2023-08-27 17:55:09 +0300 MSK
- 4.7.1599: 2023-08-26 16:17:44 +0300 MSK
- 4.7.1600: 2023-08-26 16:17:28 +0300 MSK
- 4.7.1601: 2023-08-26 16:16:46 +0300 MSK
- 4.7.1602: 2023-08-26 16:06:04 +0300 MSK
- 4.7.1603: 2023-08-26 15:38:12 +0300 MSK
- 4.7.1604: 2023-08-26 15:24:31 +0300 MSK
- 4.7.1605: 2023-08-26 15:20:18 +0300 MSK
- 4.7.1606: 2023-08-26 15:20:08 +0300 MSK
- 4.7.1607: 2023-08-26 15:19:33 +0300 MSK
- 4.7.1608: 2023-08-26 15:18:57 +0300 MSK
- 4.7.1609: 2023-08-26 12:16:27 +0300 MSK
- 4.7.1610: 2023-08-25 10:04:50 +0300 MSK
- 4.7.1611: 2023-08-24 16:42:07 +0300 MSK
- 4.7.1612: 2023-08-24 13:45:42 +0300 MSK
- 4.7.1613: 2023-08-23 22:56:37 +0300 MSK
- 4.7.1614: 2023-08-23 12:45:05 +0300 MSK
- 4.7.1615: 2023-08-22 10:32:27 +0300 MSK
- 4.7.1616: 2023-08-21 23:38:46 +0300 MSK
- 4.7.1617: 2023-08-21 21:08:48 +0300 MSK
- 4.7.1618: 2023-08-21 21:08:11 +0300 MSK
- 4.7.1619: 2023-08-21 09:29:54 +0300 MSK
- 4.7.1620: 2023-08-20 14:34:41 +0300 MSK
- 4.7.1621: 2023-08-19 18:48:22 +0300 MSK
- 4.7.1622: 2023-08-19 18:13:19 +0300 MSK
- 4.7.1623: 2023-08-19 17:36:50 +0300 MSK
- 4.7.1624: 2023-08-19 17:13:39 +0300 MSK
- 4.7.1625: 2023-08-18 10:52:33 +0300 MSK
- 4.7.1626: 2023-08-17 16:52:59 +0300 MSK
- 4.7.1627: 2023-08-16 14:36:21 +0300 MSK
- 4.7.1628: 2023-08-15 17:06:49 +0300 MSK
- 4.7.1629: 2023-08-15 17:02:49 +0300 MSK
- 4.7.1630: 2023-08-14 11:17:39 +0300 MSK
- 4.7.1631: 2023-08-13 18:35:13 +0300 MSK
- 4.7.1632: 2023-08-12 17:50:41 +0300 MSK
- 4.7.1633: 2023-08-11 17:52:07 +0300 MSK
- 4.7.1634: 2023-08-11 12:05:33 +0300 MSK
- 4.7.1635: 2023-08-11 12:01:50 +0300 MSK
- 4.7.1636: 2023-08-11 11:17:35 +0300 MSK
- 4.7.1637: 2023-08-11 11:12:31 +0300 MSK
- 4.7.1638: 2023-08-10 17:04:38 +0300 MSK
- 4.7.1639: 2023-08-09 15:13:28 +0300 MSK
- 4.7.1640: 2023-08-09 12:05:47 +0300 MSK
- 4.7.1641: 2023-08-08 23:40:50 +0300 MSK
- 4.7.1642: 2023-08-08 23:36:48 +0300 MSK
- 4.7.1643: 2023-08-08 22:57:16 +0300 MSK
- 4.7.1644: 2023-08-08 22:56:36 +0300 MSK
- 4.7.1645: 2023-08-08 21:50:31 +0300 MSK
- 4.7.1646: 2023-08-08 21:27:42 +0300 MSK
- 4.7.1647: 2023-08-08 21:02:11 +0300 MSK
- 4.7.1648: 2023-08-08 20:47:19 +0300 MSK
- 4.7.1649: 2023-08-08 20:31:21 +0300 MSK
- 4.7.1650: 2023-08-08 19:53:50 +0300 MSK
- 4.7.1651: 2023-08-08 19:34:48 +0300 MSK
- 4.7.1652: 2023-08-08 14:36:45 +0300 MSK
- 4.7.1653: 2023-08-08 13:55:40 +0300 MSK
- 4.7.1654: 2023-08-08 13:55:01 +0300 MSK
- 4.7.1655: 2023-08-07 17:24:07 +0300 MSK
- 4.7.1656: 2023-08-07 14:39:05 +0300 MSK
- 4.7.1657: 2023-08-07 14:27:07 +0300 MSK
- 4.7.1658: 2023-08-07 13:27:10 +0300 MSK
- 4.7.1659: 2023-08-07 13:25:04 +0300 MSK
- 4.7.1660: 2023-08-07 13:10:04 +0300 MSK
- 4.7.1661: 2023-08-07 13:07:20 +0300 MSK
- 4.7.1662: 2023-08-07 12:57:18 +0300 MSK
- 4.7.1663: 2023-08-07 12:49:57 +0300 MSK
- 4.7.1664: 2023-08-07 12:45:54 +0300 MSK
- 4.7.1665: 2023-08-07 12:17:58 +0300 MSK
- 4.7.1666: 2023-08-06 18:05:41 +0300 MSK
- 4.7.1667: 2023-08-06 18:00:12 +0300 MSK
- 4.7.1668: 2023-08-06 17:37:57 +0300 MSK
- 4.7.1669: 2023-08-06 17:18:41 +0300 MSK
- 4.7.1670: 2023-08-05 17:53:24 +0300 MSK
- 4.7.1671: 2023-08-05 17:40:38 +0300 MSK
- 4.7.1672: 2023-08-05 12:39:41 +0300 MSK
- 4.7.1673: 2023-08-04 19:40:16 +0300 MSK
- 4.7.1674: 2023-08-04 19:38:00 +0300 MSK
- 4.7.1675: 2023-08-04 19:37:15 +0300 MSK
- 4.7.1676: 2023-08-03 12:33:31 +0300 MSK
- 4.7.1677: 2023-08-03 12:32:00 +0300 MSK
- 4.7.1678: 2023-08-02 19:02:58 +0300 MSK
- 4.7.1679: 2023-08-02 18:11:45 +0300 MSK
- 4.7.1680: 2023-08-02 17:33:24 +0300 MSK
- 4.7.1681: 2023-08-02 11:09:23 +0300 MSK
- 4.7.1682: 2023-08-02 11:07:07 +0300 MSK
- 4.7.1683: 2023-08-02 11:00:07 +0300 MSK
- 4.7.1684: 2023-08-02 10:39:16 +0300 MSK
- 4.7.1685: 2023-08-02 10:26:02 +0300 MSK
- 4.7.1686: 2023-08-01 20:38:09 +0300 MSK
- 4.7.1687: 2023-08-01 20:19:26 +0300 MSK
- 4.7.1688: 2023-08-01 18:39:03 +0300 MSK
- 4.7.1689: 2023-08-01 17:52:16 +0300 MSK
- 4.7.1690: 2023-08-01 17:35:47 +0300 MSK
- 4.7.1691: 2023-08-01 17:33:23 +0300 MSK
- 4.7.1692: 2023-08-01 17:14:55 +0300 MSK
- 4.7.1693: 2023-07-31 19:28:12 +0300 MSK
- 4.7.1694: 2023-07-31 17:17:46 +0300 MSK
- 4.7.1695: 2023-07-31 14:46:40 +0300 MSK
- 4.7.1696: 2023-07-30 20:11:15 +0300 MSK
- 4.7.1697: 2023-07-30 10:12:02 +0300 MSK
- 4.7.1698: 2023-07-29 18:54:20 +0300 MSK
- 4.7.1699: 2023-07-29 18:51:41 +0300 MSK
- 4.7.1700: 2023-07-29 13:24:33 +0300 MSK
- 4.7.1701: 2023-07-27 11:41:11 +0300 MSK
- 4.7.1702: 2023-07-27 11:39:36 +0300 MSK
- 4.7.1703: 2023-07-27 11:28:33 +0300 MSK
- 4.7.1704: 2023-07-26 22:56:56 +0300 MSK
- 4.7.1705: 2023-07-25 16:45:40 +0300 MSK
- 4.7.1706: 2023-07-25 16:38:25 +0300 MSK
- 4.7.1707: 2023-07-24 21:17:10 +0300 MSK
- 4.7.1708: 2023-07-24 21:04:18 +0300 MSK
- 4.7.1709: 2023-07-24 20:07:58 +0300 MSK
- 4.7.1710: 2023-07-24 19:52:59 +0300 MSK
- 4.7.1711: 2023-07-24 19:34:48 +0300 MSK
- 4.7.1712: 2023-07-24 19:02:15 +0300 MSK
- 4.7.1713: 2023-07-24 18:47:17 +0300 MSK
- 4.7.1714: 2023-07-24 16:56:56 +0300 MSK
- 4.7.1715: 2023-07-24 16:56:13 +0300 MSK
- 4.7.1716: 2023-07-24 16:54:39 +0300 MSK
- 4.7.1717: 2023-07-24 16:51:33 +0300 MSK
- 4.7.1718: 2023-07-24 16:49:38 +0300 MSK
- 4.7.1719: 2023-07-24 16:32:14 +0300 MSK
- 4.7.1720: 2023-07-24 16:19:40 +0300 MSK
- 4.7.1721: 2023-07-24 16:17:10 +0300 MSK
- 4.7.1722: 2023-07-24 13:04:29 +0300 MSK
- 4.7.1723: 2023-07-24 13:03:31 +0300 MSK
- 4.7.1724: 2023-07-24 12:58:41 +0300 MSK
- 4.7.1725: 2023-07-24 12:56:22 +0300 MSK
- 4.7.1726: 2023-07-24 12:44:43 +0300 MSK
- 4.7.1727: 2023-07-24 12:40:04 +0300 MSK
- 4.7.1728: 2023-07-24 11:13:00 +0300 MSK
- 4.7.1729: 2023-07-23 21:12:51 +0300 MSK
- 4.7.1730: 2023-07-23 21:01:06 +0300 MSK
- 4.7.1731: 2023-07-23 20:55:57 +0300 MSK
- 4.7.1732: 2023-07-23 20:18:00 +0300 MSK
- 4.7.1733: 2023-07-23 20:03:43 +0300 MSK
- 4.7.1734: 2023-07-23 19:57:13 +0300 MSK
- 4.7.1735: 2023-07-23 19:55:42 +0300 MSK
- 4.7.1736: 2023-07-23 16:50:34 +0300 MSK
- 4.7.1737: 2023-07-22 19:09:00 +0300 MSK
- 4.7.1738: 2023-07-22 17:36:35 +0300 MSK
- 4.7.1739: 2023-07-21 16:55:34 +0300 MSK
- 4.7.1740: 2023-07-21 16:53:22 +0300 MSK
- 4.7.1741: 2023-07-21 16:40:56 +0300 MSK
- 4.7.1742: 2023-07-21 16:40:33 +0300 MSK
- 4.7.1743: 2023-07-21 16:40:14 +0300 MSK
- 4.7.1744: 2023-07-21 16:36:57 +0300 MSK
- 4.7.1745: 2023-07-21 16:30:39 +0300 MSK
- 4.7.1746: 2023-07-21 16:20:49 +0300 MSK
- 4.7.1747: 2023-07-21 16:09:40 +0300 MSK
- 4.7.1748: 2023-07-21 16:06:08 +0300 MSK
- 4.7.1749: 2023-07-21 15:59:33 +0300 MSK
- 4.7.1750: 2023-07-21 15:52:55 +0300 MSK
- 4.7.1751: 2023-07-21 15:33:25 +0300 MSK
- 4.7.1752: 2023-07-21 13:34:45 +0300 MSK
- 4.7.1753: 2023-07-21 13:33:01 +0300 MSK
- 4.7.1754: 2023-07-21 13:26:34 +0300 MSK
- 4.7.1755: 2023-07-21 13:23:06 +0300 MSK
- 4.7.1756: 2023-07-21 13:19:55 +0300 MSK
- 4.7.1757: 2023-07-21 13:18:37 +0300 MSK
- 4.7.1758: 2023-07-21 13:11:37 +0300 MSK
- 4.7.1759: 2023-07-20 12:12:22 +0300 MSK
- 4.7.1760: 2023-07-20 11:41:51 +0300 MSK
- 4.7.1761: 2023-07-19 14:35:52 +0300 MSK
- 4.7.1762: 2023-07-19 14:26:39 +0300 MSK
- 4.7.1763: 2023-07-19 14:19:51 +0300 MSK
- 4.7.1764: 2023-07-19 14:19:26 +0300 MSK
- 4.7.1765: 2023-07-19 13:39:31 +0300 MSK
- 4.7.1766: 2023-07-19 12:33:23 +0300 MSK
- 4.7.1767: 2023-07-19 11:49:03 +0300 MSK
- 4.7.1768: 2023-07-19 11:34:17 +0300 MSK
- 4.7.1769: 2023-07-19 11:26:05 +0300 MSK
- 4.7.1770: 2023-07-19 11:25:19 +0300 MSK
- 4.7.1771: 2023-07-19 11:14:44 +0300 MSK
- 4.7.1772: 2023-07-18 18:51:03 +0300 MSK
- 4.7.1773: 2023-07-18 18:50:17 +0300 MSK
- 4.7.1774: 2023-07-18 18:39:57 +0300 MSK
- 4.7.1775: 2023-07-18 18:25:23 +0300 MSK
- 4.7.1776: 2023-07-18 18:14:47 +0300 MSK
- 4.7.1777: 2023-07-18 18:10:20 +0300 MSK
- 4.7.1778: 2023-07-18 18:02:32 +0300 MSK
- 4.7.1779: 2023-07-18 18:01:12 +0300 MSK
- 4.7.1780: 2023-07-18 17:58:35 +0300 MSK
- 4.7.1781: 2023-07-18 17:57:21 +0300 MSK
- 4.7.1782: 2023-07-18 17:10:30 +0300 MSK
- 4.7.1783: 2023-07-18 16:55:29 +0300 MSK
- 4.7.1784: 2023-07-18 16:41:40 +0300 MSK
- 4.7.1785: 2023-07-18 16:37:43 +0300 MSK
- 4.7.1786: 2023-07-18 16:15:43 +0300 MSK
- 4.7.1787: 2023-07-18 15:49:17 +0300 MSK
- 4.7.1788: 2023-07-18 15:46:05 +0300 MSK
- 4.7.1789: 2023-07-18 15:23:22 +0300 MSK
- 4.7.1790: 2023-07-18 15:15:34 +0300 MSK
- 4.7.1791: 2023-07-18 15:08:44 +0300 MSK
- 4.7.1792: 2023-07-18 14:53:17 +0300 MSK
- 4.7.1793: 2023-07-18 14:46:38 +0300 MSK
- 4.7.1794: 2023-07-18 13:48:20 +0300 MSK
- 4.7.1795: 2023-07-16 19:26:31 +0300 MSK
- 4.7.1796: 2023-07-16 19:19:33 +0300 MSK
- 4.7.1797: 2023-07-16 18:35:46 +0300 MSK
- 4.7.1798: 2023-07-16 15:06:38 +0300 MSK
- 4.7.1799: 2023-07-16 15:04:36 +0300 MSK
- 4.7.1800: 2023-07-16 13:34:50 +0300 MSK
- 4.7.1801: 2023-07-16 12:53:42 +0300 MSK
- 4.7.1802: 2023-07-16 12:51:01 +0300 MSK
- 4.7.1803: 2023-07-16 12:38:36 +0300 MSK
- 4.7.1804: 2023-07-16 12:17:02 +0300 MSK
- 4.7.1805: 2023-07-16 12:16:10 +0300 MSK
- 4.7.1806: 2023-07-16 10:47:21 +0300 MSK
- 4.7.1807: 2023-07-16 10:41:43 +0300 MSK
- 4.7.1808: 2023-07-16 10:41:26 +0300 MSK
- 4.7.1809: 2023-07-15 21:24:48 +0300 MSK
- 4.7.1810: 2023-07-15 21:22:16 +0300 MSK
- 4.7.1811: 2023-07-15 21:11:36 +0300 MSK
- 4.7.1812: 2023-07-15 20:53:31 +0300 MSK
- 4.7.1813: 2023-07-15 20:49:31 +0300 MSK
- 4.7.1814: 2023-07-15 20:05:44 +0300 MSK
- 4.7.1815: 2023-07-15 19:55:32 +0300 MSK
- 4.7.1816: 2023-07-15 19:35:16 +0300 MSK
- 4.7.1817: 2023-07-13 21:11:33 +0300 MSK
- 4.7.1818: 2023-07-13 20:57:51 +0300 MSK
- 4.7.1819: 2023-07-13 20:49:03 +0300 MSK
- 4.7.1820: 2023-07-13 20:34:54 +0300 MSK
- 4.7.1821: 2023-07-13 20:32:03 +0300 MSK
- 4.7.1822: 2023-07-13 20:30:18 +0300 MSK
- 4.7.1823: 2023-07-13 20:19:45 +0300 MSK
- 4.7.1824: 2023-07-13 19:37:36 +0300 MSK
- 4.7.1825: 2023-07-13 19:13:31 +0300 MSK
- 4.7.1826: 2023-07-13 19:03:15 +0300 MSK
- 4.7.1827: 2023-07-13 18:52:44 +0300 MSK
- 4.7.1828: 2023-07-13 18:46:43 +0300 MSK
- 4.7.1829: 2023-07-12 20:34:00 +0300 MSK
- 4.7.1830: 2023-07-11 17:42:28 +0300 MSK
- 4.7.1831: 2023-07-11 17:40:20 +0300 MSK
- 4.7.1832: 2023-07-10 15:59:08 +0300 MSK
- 4.7.1833: 2023-07-10 15:57:30 +0300 MSK
- 4.7.1834: 2023-07-10 15:49:18 +0300 MSK
- 4.7.1835: 2023-07-08 18:57:18 +0300 MSK
- 4.7.1836: 2023-07-08 18:48:01 +0300 MSK
- 4.7.1837: 2023-07-08 18:25:39 +0300 MSK
- 4.7.1838: 2023-07-06 20:44:21 +0300 MSK
- 4.7.1839: 2023-07-06 15:43:40 +0300 MSK
- 4.7.1840: 2023-05-24 13:25:03 +0300 MSK
- 4.7.1841: 2023-05-24 13:11:40 +0300 MSK
- 4.7.1842: 2023-05-24 12:54:30 +0300 MSK
- 4.7.1843: 2023-05-24 12:13:29 +0300 MSK
- 4.7.1844: 2023-05-24 11:52:15 +0300 MSK
- 4.7.1845: 2023-05-24 11:37:01 +0300 MSK
- 4.7.1846: 2023-05-24 11:26:20 +0300 MSK
- 4.7.1847: 2023-05-24 11:15:01 +0300 MSK
- 4.7.1848: 2023-05-23 12:36:30 +0300 MSK
- 4.7.1849: 2023-05-23 12:30:44 +0300 MSK
- 4.7.1850: 2022-05-17 07:59:02 +0300 MSK
- 4.7.1851: 2022-05-15 18:44:33 +0300 MSK
- 4.7.1852: 2022-05-14 15:28:36 +0300 MSK
- 4.7.1853: 2022-05-13 07:19:10 +0300 MSK
- 4.7.1854: 2022-05-13 07:17:45 +0300 MSK
- 4.7.1855: 2022-05-12 18:05:33 +0300 MSK
- 4.7.1856: 2022-05-11 18:03:06 +0300 MSK
- 4.7.1857: 2022-05-08 17:27:21 +0300 MSK
- 4.7.1858: 2022-05-07 13:44:16 +0300 MSK
- 4.7.1859: 2022-05-07 13:05:13 +0300 MSK
- 4.7.1860: 2022-05-06 20:02:58 +0300 MSK
- 4.7.1861: 2022-05-06 19:50:38 +0300 MSK
- 4.7.1862: 2022-05-06 19:25:00 +0300 MSK
- 4.7.1863: 2022-05-05 18:39:53 +0300 MSK
- 4.7.1864: 2022-05-05 18:26:39 +0300 MSK
- 4.7.1865: 2022-05-05 15:37:11 +0300 MSK
- 4.7.1866: 2022-05-05 15:10:54 +0300 MSK
- 4.7.1867: 2022-05-05 13:50:33 +0300 MSK
- 4.7.1868: 2022-05-05 13:43:47 +0300 MSK
- 4.7.1869: 2022-05-05 13:39:30 +0300 MSK
- 4.7.1870: 2022-05-05 13:39:06 +0300 MSK
- 4.7.1871: 2022-05-05 13:38:25 +0300 MSK
- 4.7.1872: 2022-05-05 13:32:58 +0300 MSK
- 4.7.1873: 2022-05-05 13:14:51 +0300 MSK
- 4.7.1874: 2022-05-05 07:01:33 +0300 MSK
- 4.7.1875: 2022-05-04 13:13:54 +0300 MSK
- 4.7.1876: 2022-05-04 12:54:11 +0300 MSK
- 4.7.1877: 2022-05-04 12:36:38 +0300 MSK
- 4.7.1878: 2022-05-04 08:33:36 +0300 MSK
- 4.7.1879: 2022-05-04 08:32:16 +0300 MSK
- 4.7.1880: 2022-05-04 08:30:20 +0300 MSK
- 4.7.1881: 2022-05-04 07:34:24 +0300 MSK
- 4.7.1882: 2022-05-04 07:03:31 +0300 MSK
- 4.7.1883: 2022-05-04 06:39:29 +0300 MSK
- 4.7.1884: 2022-05-04 06:26:24 +0300 MSK
- 4.7.1885: 2022-05-04 05:57:55 +0300 MSK
- 4.7.1886: 2022-05-04 05:49:11 +0300 MSK
- 4.7.1887: 2022-05-03 18:34:04 +0300 MSK
- 4.7.1888: 2022-05-03 17:44:29 +0300 MSK
- 4.7.1889: 2022-05-03 17:39:58 +0300 MSK
- 4.7.1890: 2022-05-03 15:28:52 +0300 MSK
- 4.7.1891: 2022-05-03 15:08:53 +0300 MSK
- 4.7.1892: 2022-05-03 15:05:02 +0300 MSK
- 4.7.1893: 2022-05-03 13:17:41 +0300 MSK
- 4.7.1894: 2022-05-03 13:17:21 +0300 MSK
- 4.7.1895: 2022-05-02 19:07:40 +0300 MSK
- 4.7.1896: 2022-05-02 18:49:07 +0300 MSK
- 4.7.1897: 2022-05-02 18:02:36 +0300 MSK
- 4.7.1898: 2022-05-02 17:51:33 +0300 MSK
- 4.7.1899: 2022-05-02 17:49:22 +0300 MSK
- 4.7.1900: 2022-05-02 17:34:04 +0300 MSK
- 4.7.1901: 2022-05-02 16:35:35 +0300 MSK
- 4.7.1902: 2022-05-02 16:28:49 +0300 MSK
- 4.7.1903: 2022-05-02 14:58:45 +0300 MSK
- 4.7.1904: 2022-05-02 07:24:29 +0300 MSK
- 4.7.1905: 2022-05-01 16:23:58 +0300 MSK
- 4.7.1906: 2022-05-01 15:41:08 +0300 MSK
- 4.7.1907: 2022-05-01 13:28:32 +0300 MSK
- 4.7.1908: 2022-05-01 13:12:45 +0300 MSK
- 4.7.1909: 2022-05-01 09:06:49 +0300 MSK
- 4.7.1910: 2022-04-30 22:06:12 +0300 MSK
- 4.7.1911: 2022-04-30 20:27:04 +0300 MSK
- 4.7.1912: 2022-04-30 18:34:48 +0300 MSK
- 4.7.1913: 2022-04-30 09:12:31 +0300 MSK
- 4.7.1914: 2022-04-30 08:49:48 +0300 MSK
- 4.7.1915: 2022-04-30 08:49:00 +0300 MSK
- 4.7.1916: 2022-04-30 08:30:40 +0300 MSK
- 4.7.1917: 2022-04-30 07:52:06 +0300 MSK
- 4.7.1918: 2022-04-30 06:41:23 +0300 MSK
- 4.7.1919: 2022-04-30 06:29:16 +0300 MSK
- 4.7.1920: 2022-04-30 05:36:04 +0300 MSK
- 4.7.1921: 2022-04-29 22:10:38 +0300 MSK
- 4.7.1922: 2022-04-29 19:52:46 +0300 MSK
- 4.7.1923: 2022-04-29 18:51:04 +0300 MSK
- 4.7.1924: 2022-04-29 18:09:02 +0300 MSK
- 4.7.1925: 2022-04-28 09:04:20 +0300 MSK
- 4.7.1926: 2022-04-28 08:59:35 +0300 MSK
- 4.7.1927: 2022-04-28 08:59:06 +0300 MSK
- 4.7.1928: 2022-04-28 08:55:16 +0300 MSK
- 4.8: Mullvad
- 4.9: Old diagrams
- 4.10: Pgp
- 4.11: Ping
- 4.12: Qubes OS
- 4.13: Repo
- 4.14: Rfc
- 4.14.1: Rfc2119
- 4.15: Shell
- 4.16: Ssh
- 4.17: Ssl
- 4.18: Todo
- 4.19: Vault
- 4.20: Waydroid
- 5: Data
- 5.1: Blender
- 5.2: Books
- 5.3: Countries
- 5.4: Leetcode submissions
- 5.5: License
- 5.6: Mullvad
- 5.7: Pgp
- 5.8: ssh
- 5.9: Ssl
- 5.9.1: Alwaldend.com
- 6: Third party
- 6.1:
- 6.2:
- 6.3: ai_opencode_opencode
- 6.4: com_drawio_desktop_bin
- 6.5: com_github_bazelbuild_bazel_protobuf
- 6.6: com_github_bazelbuild_bazelisk
- 6.7: com_github_georgewfraser_java_language_server
- 6.8: com_nanovms_ops
- 6.9: com_nousresearch_hermes_agent
- 6.10: com_truenas_scale
- 6.11: dev_sanaei_3xui
- 6.12: flux
- 6.13: Gradle
- 6.14: Images
- 6.14.1: Tf
- 6.15: io_cert_manager_cmctl
- 6.16: io_controlplane_flux_operator
- 6.17: io_docker_library_alpine
- 6.18: io_getsops_sops
- 6.19: io_goharbor_harbor_cli
- 6.20: io_goharbor_helm_harbor
- 6.21: io_goharbor_offline_installer
- 6.22: io_k3s_k3s
- 6.23: io_kubernetes_kubectl
- 6.24: io_traefik_traefik
- 6.25: Lego ACME client
- 6.26: net_zlib_zlib
- 6.27: OpenHands canvas UI compatibility module
- 6.28: org_codeberg_forgejo
- 6.29: org_codeberg_forgejo_bin
- 6.30: org_codeberg_forgejo_contrib_forgejo_cli_bin
- 6.31: org_codeberg_forgejo_runner_bin
- 6.32: org_fedora_cloud
- 6.33: org_kernel_headers
- 6.34: org_nmap_nmap
- 6.35: org_openssl_openssl
- 6.36: org_pcre_pcre2
- 6.37: org_xcp_ng
- 6.38: sh_helm_helm
- 6.39: Terraform dependencies
- 6.40: us_nasm_nasm
- 6.41: Xen Orchestra OIDC plugin
- 7: Users
- 7.1: simeonwarren
- 8: Examples
1 - Projects
This tree contains first-party products and reusable project code. All tracked content follows the repository’s public-source policy.
Each project owns its specifications and maintained changes in
<project>/openspec/. Use the pinned OpenSpec workflow
with that project selected. infra/src/ owns repository evolution.
Requirements
- Bazel targets MAY use public visibility when their owner intends external reuse.
- Project artifacts MAY be published through an explicit release workflow.
- Project targets MAY be used by production build targets.
Project sites
Each project has a landing page in the main website at
https://alwaldend.com/projects/<name>/. Sites are published with the main
site rather than as separate Pages repositories, and repository reference
documentation, including each project README, lives under /docs/.
| Project | Description | Landing page |
|---|---|---|
| ActivityWatch ingester Android | Android accessibility collector that sends browser tabs to ActivityWatch | alwaldend.com/projects/activitywatch_ingester_android/ |
| Agents | Repository-wide reusable agent skills | alwaldend.com/projects/agents/ |
| Al | Repository command runner and Bazel configuration rules | alwaldend.com/projects/al/ |
| Alwaldend.com | Main website and project documentation | alwaldend.com |
| Android launcher | Text-only Android launcher built with Kotlin and Jetpack Compose | alwaldend.com/projects/android_launcher/ |
| Ansible collection | Ansible collection alwaldend.main with Bazel source packaging | alwaldend.com/projects/ansible_collection/ |
| Autoscroll | Mouse-driven autoscroll CLI with reloadable configuration | alwaldend.com/projects/autoscroll/ |
| Bazel agent | Bazel runner for repository agents | alwaldend.com/projects/bazel_agent/ |
| Ci platform | Abandoned CI platform with a Go backend and Vue frontend | alwaldend.com/projects/ci_platform/ |
| Dotfiles | Personal configuration files with installation and comparison commands | alwaldend.com/projects/dotfiles/ |
| Infinitime | InfiniTime firmware fork with a text watchface and Pomodoro app | alwaldend.com/projects/infinitime/ |
| Kustomization | Kubernetes resources for Flux, Traefik, and cert-manager | alwaldend.com/projects/kustomization/ |
| Leetcode downloader | LeetCode submission export and documentation tools | alwaldend.com/projects/leetcode_downloader/ |
| MCP Cordis | Workspace-local runtime packages behind a stable MCP server | alwaldend.com/projects/mcp_cordis/ |
| Nexus security plugin | Security plugin for Sonatype Nexus 3 | alwaldend.com/projects/nexus_security_plugin/ |
| Renders | Repository-owned render assets and their acceptance evidence | alwaldend.com/projects/renders/ |
| Sri | Command-line Subresource Integrity calculator using OpenSSL | alwaldend.com/projects/sri/ |
| Tf modules | Reusable Terraform modules for Vault, virtual machines, and storage | alwaldend.com/projects/tf_modules/ |
| Useless QT GUI | Desktop GUI application built with C++ and Qt | alwaldend.com/projects/useless_qt_gui/ |
1.1 - ActivityWatch ingester Android
ActivityWatch ingester Android
An Android collector that reads supported browser address-bar text through Android accessibility and sends it to an ActivityWatch server. The app holds full accessibility permission only to obtain the URL; it never uses that permission for anything else.
How it works
- Enabling accessibility for this app lets it read the focused address bar.
- The accessibility service matches browser view IDs (
url_barand common Chrome-derived variants), extracts the current URL, and sends an ActivityWatch heartbeat for theweb.tab.currentbucket to a configurable server. web.tab.currentheartbeats usepulsetime=1.0; consecutive URLs are sent with the time spent on the previous tab as thedurationfield.- Data goes directly from this app to the ActivityWatch HTTP API; it is not uploaded to any other service.
Configuration
Open the app to configure:
- ActivityWatch server URL — the base URL of the ActivityWatch server.
The default is
http://127.0.0.1:5600for the ActivityWatch Android app on the same device. Changes are saved immediately. - API key (optional) — bearer token sent as
Authorization: Bearer ...when the ActivityWatch server has API authentication enabled.
The INTERNET permission is required to reach the ActivityWatch HTTP API. The
default loopback URL is sent over cleartext HTTP only to 127.0.0.1 and
localhost, so no host data leaves the device.
Supported browsers
Chrome and Chromium-based browsers that expose the url_bar view ID
(including ordinary Chrome and many Chrome-based forks). Firefox, Samsung
Internet, Opera, and Edge do not use that view ID yet.
Build and install
- Build the APK:
bazel build //projects/activitywatch_ingester_android/main/java:ingester_binary - Verify the APK starts on an already running device or emulator:
bazel run //projects/activitywatch_ingester_android/test:ingester_smoke_testThis manual smoke test installs the Bazel-built APK, launches the activity, waits for the process, and confirms it stays alive. It is not a CI test. - Install the APK on the device from
bazel-bin/projects/activitywatch_ingester_android/main/java/ingester_binary.apk. - Start the app and set the ActivityWatch server URL.
- Enable accessibility for the app in Android settings; Android shows the full-access warning, which is the mechanism this collector is built on.
- Open a browser. The current URL is re-sent to ActivityWatch whenever the address bar changes.
Compatibility
- Minimum Android SDK 25 (Android 7.0).
- Tested against the ActivityWatch v0.13 HTTP API (
POST /api/0/bucketsandPOST /api/0/buckets/web.tab.current/heartbeat).
Landing page
The landing page is published at
activitywatch-ingester-android.alwaldend.com,
built from this README by the shared Hugo landing template. The DNS record
lives in dnsconfig.json; the project Terraform stage describes
its configuration and ownership activation workflow.
1.1.1.1 - head
-
Move project landings into the main site
Publish every registered project’s visitor-facing landing page at /projects/
/ from the main site instead of a dedicated subdomain, and retire the per-project Pages repository, CNAME, and Terraform DNS stage that existed only to serve one page derived from the project README. Each project owns its landing content in projects/
/site/content/ as pure content: no layouts, styles, or build rules. The main site packages those directories into content/projects/ / from the registry in projects/projects.bzl, so membership is declared once. The landing is a short hand-written page for visitors while the README keeps its /docs/projects/ / URL for repository reference documentation, and landing front matter now feeds the statuses, languages, and tags taxonomies. Merge the reusable hugo_landing project into the main site: its shared canvas and accent styles and its landing page rules move into the apex tree, and its landing macro, generated configuration, standalone publisher, and repository-relative rewrite layouts are removed. The theme keeps owning the taxonomy and term layouts, which are richer than the heading-only versions the reusable project carried. Remove the now-unused apex deploy_project.sh and deploy_all.sh landing publishers with it.
Retire the per-project publication and DNS ownership: the project landing targets and the landing deployment command, each landing project’s dnsconfig.json and Terraform root, the build plumbing that served only those stages, and the landing repository and Pages membership in the repository catalog. The apex Terraform root is retained because it also declares VM resources, and no Vault configuration is changed.
Replace the provider-snapshot zone files with generated declaration pages, one per destination view, that project the checked-in declarations and are verified for freshness by the DNS offline check. The DNS linter, both destination pages, the apex site, the skills projection, and the repository quality suite pass, and the whole repository builds.
OpenSpec-Change: projects/alwaldend.com/openspec/changes/consolidate-project-landings-into-apex
LLM-disclaimer: This commit was generated by an LLM.
-
Manage forge resources with hermetic Terraform rules
Centralize organization, repository, and named access configuration in infra/repos. Adopt existing GitHub resources, protect master defaults while retaining Pages publication on pages, and preserve existing repository identities. Manage GitLab one-time imports, the F-Droid metadata fork, and default-branch protections through Vault-backed authentication. Forgejo consumes the same catalog. Ongoing repository synchronization is deferred.
Retire the eleven Bazel rule landing sites through their owning Terraform workflows, removing their DNS records, Pages repositories, and landing configuration. Move all twelve existing standalone rule modules into tools/ and retain their public interfaces and documentation on the main site.
Add tools/rules_terraform with verified provider downloads, packed mirrors in runfiles, and reusable Terraform execution rules. Enforce one version per provider source at an extensible resolution boundary. Migrate every Terraform consumer to thirteen shared provider pins in third_party/terraform. Execution and command maps belong to rules_terraform; consumers explicitly select generic AL wrappers for authentication and Vault injection. Remove tools/terraform and all 43 checked-in Terraform provider locks. Validate installed providers against the declared archives before execution.
Validation covers all fourteen workspace builds, all thirteen standalone test suites, Terraform consumers, offline real-provider regressions, rendered documentation, formatting, and semantic lint. The full root test run has 295 passing tests and one skip; its only failure is the historical secret scan, reduced to four pre-existing synthetic fixture matches. Earlier live imports and the exact landing retirement scope have verified postconditions; the Terraform rules migration uses only offline implementation checks.
OpenSpec-Change: infra/repos/openspec/changes/archive/2026-09-13-adopt-shared-repository-catalog OpenSpec-Change: infra/src/openspec/changes/archive/2026-09-13-retire-bazel-rule-landings OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-add-hermetic-terraform-rules OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-correct-terraform-ownership
LLM-disclaimer: This commit was generated by an LLM.
-
Deploy project DNS through Terraform modules
Move DNS ownership into each project’s Terraform state using shared modules. Load dnsconfig.json files at runtime, reject conflicting domain ownership, and render their records as a table. Add missing project AppRoles and scoped DNS policies, and document grouping related Terraform resources in modules.
Deploy all 45 owners sequentially: adopt 155 existing records and create 13 missing OpenHands records. Preserve every pre-existing provider record and verify no-op follow-up plans and DNS answers. Add DNS-scoped plan/show/apply wrappers with a saved-plan guard for roots that also manage services. Allow bounded aggregate path inventories large enough to deliver this migration while retaining truncation refusal in the delivery tool.
Validate runtime ownership, provider imports and preservation with isolated fixtures, Terraform formatting, wrapper builds, repository quality checks, semantic lint, and project documentation/specification builds.
OpenSpec-Change: infra/dns/openspec/changes/archive/2026-09-13-migrate-project-dns-to-terraform
LLM-disclaimer: This commit was generated by an LLM.
-
Fix Android review feedback
Add a shared
androidPluginsversion catalog so both Android apps declare the AGP, Kotlin, Compose, and protobuf plugin versions once, and derive their versions from it instead of duplicating literals per root Gradle file.Align the launcher and ingester app versions with the repository versioning contract: development builds use
0.0.0-devwithversionCode1 in both the Gradle default config and the Bazelmanifest_values.Ignore the whole materialized
.agents/skillsdirectory in Prettier because every entry is either a source-tree symlink or a byte-pinned external archive copy.Apply the ingester’s themed surface background to the main content surface so the status bar area follows the system theme, not a default white surface.
Token: z-ai-glm-flash-latest
LLM-disclaimer: This commit was generated by an LLM.
-
Add spellcheck skill
This commit was generated by an LLM.
-
Restore light and dark site canvases and set the shared accent
The shared Docsy canvas set the same Bootstrap dark palette and the same black page background on
:root,[data-bs-theme="light"], and[data-bs-theme="dark"], so the light/dark toggle changed nothing. The site also rendered Bootstrap’s stock blue instead of its intended accent.Split the shared palette so light mode uses a pure white canvas with the light-mode palette and dark mode uses a pure black canvas with the dark-mode palette, and keep the pre-stylesheet paint and footer on the active mode. Assign
$primaryto#7c3aedbefore Bootstrap compiles, so links, buttons, badges, focus rings, and the dark-mode link tint all derive from one value rather than from a site-local copy.Both files stay in the reusable shell; the apex site consumes them through the existing declared exports and no longer carries the footer’s own blue.
OpenSpec-Change: projects/hugo_landing/openspec/changes/restore-light-dark-canvas-and-accent
LLM-disclaimer: This commit was generated by an LLM.
1.2 - Agents
Repository agent skills
This project owns the reusable cross-repository agent skills. Maintained improvement work lives in this project’s OpenSpec workspace. It does not centralize component facts or runtime state: each fact remains canonical at its natural owner.
Start here
| Document | Purpose |
|---|---|
| OpenSpec changes | Maintained work, acceptance, and preserved goal history |
| Root agent guide | Current repository-wide operating policy |
Dated audits remain in migrated history.
Ownership boundaries
openspec/owns agent-system requirements, changes, and evidence; the migration map locates historical records.- Other components own their specifications and changes under their own
openspec/directory.infra/src/openspec/describes repository evolution. skills/owns reusable cross-product, repository-wide agent procedures and their development-time evaluations. A product-specific procedure belongs with its product; a procedure that no narrower project genuinely owns lives here rather than in a contrived local home.- Product-specific skills remain with their project at
projects/<project>/skills/<name>. Do not split one skill across owners.
Skill packaging and discovery
Every canonical skill is packaged as a skill_library in its owning
directory.
The repository discovery directory .agents/skills/ contains one relative
symlink per skill. Each link points directly to its canonical project-owned
directory. .agents/BUILD.bazel declares the complete discovery set and
generates those links with //.agents:write_skills; its generated
exact-state test verifies them. Bazel ignores the discovery directory and
builds only canonical targets, preventing duplicate packages while allowing
skills from more than one owning project. Each skill grants
//.agents:skill_discovery read access so the owning declaration can reach it.
Skill evaluation data is not part of the runtime skill_library unless a
skill explicitly declares otherwise. Every new or updated skill includes an
offline Promptfoo configuration-validation target. That target checks the eval
harness, not answer correctness. Live behavioral evaluations are manual,
networked tests and must not be included in ordinary wildcard test runs; they
may be omitted when representative coverage requires tool calls or external
state that cannot be provided safely and reproducibly, with the gap documented
beside the eval configuration.
1.3 - Al
AL is a command runner that prepares credentials and environment variables through plugins, runs your command, and cleans up afterward. Its Bazel rules package commands with their configuration and required plugins.
al tool runs tools declared in AL configuration from a source-keyed executable
cache. With no --config, it uses the repository-root al.lua; explicit
--config paths replace that default. Cache misses build the tool’s configured
Bazel label and publish the selected executable under
$XDG_CACHE_HOME/al/tools. AL_TOOL_CACHE or tool --cache-root PATH selects
an alternate cache root.
Repository agent skills are written by bazel run //.agents:write_skills
and checked by //.agents:write_skills_test.
Links
1.3.1 - Command and plugin lifecycle
al run starts selected plugins, passes their environment to a command, and
keeps plugin resources available until that command exits. On cancellation it
asks the command to terminate and waits up to ten seconds before killing it.
Plugin shutdown then drains requests, releases resources in reverse registration
order, and waits for plugin exit. Startup failure cancels sibling starts and
rolls back partially initialized resources. Cleanup errors fail the invocation.
The injector creates secret files with owner-only permissions and removes them
after consumers stop. Vault stores revoke AppRole tokens they issue; failed
AppRole login attempts destroy their unused single-use SecretID. The role’s
bootstrap policy must permit secret-id-accessor/destroy, as declared by
projects/tf_modules/vault_approle. The user’s existing token-helper credential
is never erased or revoked. Secret inputs and remote response bodies are omitted
from diagnostic messages. OIDC authorization uses the configured Vault HTTPS
origin and TLS transport, rejecting alternate origins and redirects.
Explicit config dumps still contain the requested configuration; file outputs
use owner-only permissions and truncate previous contents.
no_auth prevents AL’s Vault client from loading credentials. For environment
injection it clears inherited VAULT_TOKEN; it does not sandbox the command or
prevent a command from independently reading the user’s token helper. Plugins
and invoked commands remain trusted programs with the user’s filesystem access.
Cleanup is observable best effort, not secure erasure. Memory copies are not zeroized. Forced termination, host failure, unresponsive cleanup code, or an unavailable service can prevent deletion or revocation. Subprocess signaling targets direct children, not arbitrary descendants. Credential expiry remains a fallback; service-specific logout requirements are documented with each plugin.
1.3.2 - Releases
head
-
Lay the project index out as a single-column section list
The card grid read as a separate component next to the rest of the site. The
/projects/index now uses the same section list as the documentation index: one entry per project under theProjectsheading, separated by panel lines, each entry carrying its description, status, and tags. The entries stay in alphabetical order.Wrap the list in a section so the theme’s first-section offset applies; without it the
Projectsheading rendered underneath the fixed navbar.LLM-disclaimer: This commit was generated by an LLM.
-
Add a staging publication and refine the project index
Verify the project landing replacement on its own hostname before the apex changes and before any per-project resource is retired, and make the landing index useful to a visitor.
www-staging.alwaldend.comgets a checked-in DNS declaration and a catalog repository, and the apex site gains a staging build that renders the same packaged source with the staging base URL plus a deployment command that publishes it. The publication command now takes its repository and branch as arguments, so staging and production share one publisher, and a repository whose publication branch does not exist yet is created as an orphan instead of failing on clone. A new repository receives a default branch at creation so the managed ruleset can protect it while site content publishes to a separate branch, and GitHub Pages configuration is deferred for a repository until its publication branch exists.The
/projects/index no longer opens with explanatory prose, lists landings alphabetically, and shows each project’s status and tags as links to their taxonomy term pages.Deploy the staging site, verify the landing, documentation, and taxonomy routes there, then deploy the accepted output to the apex and verify the same routes. The per-project hostnames, DNS records, and landing repositories remain in place until their retirement is requested.
OpenSpec-Change: projects/alwaldend.com/openspec/changes/site-staging-environment
LLM-disclaimer: This commit was generated by an LLM.
-
Move project landings into the main site
Publish every registered project’s visitor-facing landing page at /projects/
/ from the main site instead of a dedicated subdomain, and retire the per-project Pages repository, CNAME, and Terraform DNS stage that existed only to serve one page derived from the project README. Each project owns its landing content in projects/
/site/content/ as pure content: no layouts, styles, or build rules. The main site packages those directories into content/projects/ / from the registry in projects/projects.bzl, so membership is declared once. The landing is a short hand-written page for visitors while the README keeps its /docs/projects/ / URL for repository reference documentation, and landing front matter now feeds the statuses, languages, and tags taxonomies. Merge the reusable hugo_landing project into the main site: its shared canvas and accent styles and its landing page rules move into the apex tree, and its landing macro, generated configuration, standalone publisher, and repository-relative rewrite layouts are removed. The theme keeps owning the taxonomy and term layouts, which are richer than the heading-only versions the reusable project carried. Remove the now-unused apex deploy_project.sh and deploy_all.sh landing publishers with it.
Retire the per-project publication and DNS ownership: the project landing targets and the landing deployment command, each landing project’s dnsconfig.json and Terraform root, the build plumbing that served only those stages, and the landing repository and Pages membership in the repository catalog. The apex Terraform root is retained because it also declares VM resources, and no Vault configuration is changed.
Replace the provider-snapshot zone files with generated declaration pages, one per destination view, that project the checked-in declarations and are verified for freshness by the DNS offline check. The DNS linter, both destination pages, the apex site, the skills projection, and the repository quality suite pass, and the whole repository builds.
OpenSpec-Change: projects/alwaldend.com/openspec/changes/consolidate-project-landings-into-apex
LLM-disclaimer: This commit was generated by an LLM.
-
Merge pull request #94 from alwaldend/t3code/fix-hugo-theme-light-dark-accent
Restore light and dark site canvases and set the shared accent
-
Manage forge resources with hermetic Terraform rules
Centralize organization, repository, and named access configuration in infra/repos. Adopt existing GitHub resources, protect master defaults while retaining Pages publication on pages, and preserve existing repository identities. Manage GitLab one-time imports, the F-Droid metadata fork, and default-branch protections through Vault-backed authentication. Forgejo consumes the same catalog. Ongoing repository synchronization is deferred.
Retire the eleven Bazel rule landing sites through their owning Terraform workflows, removing their DNS records, Pages repositories, and landing configuration. Move all twelve existing standalone rule modules into tools/ and retain their public interfaces and documentation on the main site.
Add tools/rules_terraform with verified provider downloads, packed mirrors in runfiles, and reusable Terraform execution rules. Enforce one version per provider source at an extensible resolution boundary. Migrate every Terraform consumer to thirteen shared provider pins in third_party/terraform. Execution and command maps belong to rules_terraform; consumers explicitly select generic AL wrappers for authentication and Vault injection. Remove tools/terraform and all 43 checked-in Terraform provider locks. Validate installed providers against the declared archives before execution.
Validation covers all fourteen workspace builds, all thirteen standalone test suites, Terraform consumers, offline real-provider regressions, rendered documentation, formatting, and semantic lint. The full root test run has 295 passing tests and one skip; its only failure is the historical secret scan, reduced to four pre-existing synthetic fixture matches. Earlier live imports and the exact landing retirement scope have verified postconditions; the Terraform rules migration uses only offline implementation checks.
OpenSpec-Change: infra/repos/openspec/changes/archive/2026-09-13-adopt-shared-repository-catalog OpenSpec-Change: infra/src/openspec/changes/archive/2026-09-13-retire-bazel-rule-landings OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-add-hermetic-terraform-rules OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-correct-terraform-ownership
LLM-disclaimer: This commit was generated by an LLM.
-
Publish the DNS evolution article and update blog workflow
Publish the author’s account of moving DNS management from a central DNSControl configuration to project-owned Terraform records, with examples and directory layouts. Include the author’s clarifications and approved wording corrections, and remove the draft flag for publication.
Tag both blog posts using existing site topics. Require relevant tags and iterative reviews in the blog skill: report findings before validation and delivery, repeat after changes, and finish delivery when the review is clear or the author ends it. Cover both behaviors in the existing evaluation cases.
Validation: local and release Hugo builds, site_test, skill validation and offline Promptfoo configuration test, skill discovery, Buildifier, repository quality, and semantic lint for the affected blog and skill packages.
LLM-disclaimer: This commit was generated by an LLM.
-
Deploy project DNS through Terraform modules
Move DNS ownership into each project’s Terraform state using shared modules. Load dnsconfig.json files at runtime, reject conflicting domain ownership, and render their records as a table. Add missing project AppRoles and scoped DNS policies, and document grouping related Terraform resources in modules.
Deploy all 45 owners sequentially: adopt 155 existing records and create 13 missing OpenHands records. Preserve every pre-existing provider record and verify no-op follow-up plans and DNS answers. Add DNS-scoped plan/show/apply wrappers with a saved-plan guard for roots that also manage services. Allow bounded aggregate path inventories large enough to deliver this migration while retaining truncation refusal in the delivery tool.
Validate runtime ownership, provider imports and preservation with isolated fixtures, Terraform formatting, wrapper builds, repository quality checks, semantic lint, and project documentation/specification builds.
OpenSpec-Change: infra/dns/openspec/changes/archive/2026-09-13-migrate-project-dns-to-terraform
LLM-disclaimer: This commit was generated by an LLM.
-
Record the site hostname decision for alwaldend.com
Record the evaluated options for the apex site’s landing, documentation, and blog sections: one hostname with one build (retained), separate hostnames served from separate GitHub Pages repositories, and one hostname with independently built and merged section outputs. The generated documentation tree is a projection of the repository’s own directory structure across 471 packaged README files, and an earlier commit already combined the misc, docs, and projects sites, so splitting the hostnames would move where the projection is served without decoupling it from its source.
Separate the shared-build failure coupling from the hostname question: the recorded fallback keeps one published tree while splitting the build graph, if panicking on any packaged README warning starts blocking delivery.
Record the search-engine evidence from primary sources. Google’s crawling-and-indexing FAQ states that from an indexing and ranking perspective Google has no preference, and the office-hours answer recorded here addresses the same question. The record explicitly does not claim that subdirectories preserve link equity that a subdomain would forfeit, and it cites a third vendor video by title only because its spoken content could not be retrieved.
This change adds no site behavior, build target, configuration, DNS record, or Terraform resource.
OpenSpec-Change: projects/alwaldend.com/openspec/changes/archive/2026-09-12-record-site-hostname-decision
LLM-disclaimer: This commit was generated by an LLM.
-
Fix Android review feedback
Add a shared
androidPluginsversion catalog so both Android apps declare the AGP, Kotlin, Compose, and protobuf plugin versions once, and derive their versions from it instead of duplicating literals per root Gradle file.Align the launcher and ingester app versions with the repository versioning contract: development builds use
0.0.0-devwithversionCode1 in both the Gradle default config and the Bazelmanifest_values.Ignore the whole materialized
.agents/skillsdirectory in Prettier because every entry is either a source-tree symlink or a byte-pinned external archive copy.Apply the ingester’s themed surface background to the main content surface so the status bar area follows the system theme, not a default white surface.
Token: z-ai-glm-flash-latest
LLM-disclaimer: This commit was generated by an LLM.
-
Add a blog section, a shared site canvas, and standalone nested modules
Publish the Docsy blog section on the apex site with its content package, navigation entry, RSS feed, and draft-safe release flags. The release build excludes drafts so a post stays unpublished from its front matter alone.
Move the reusable project-site procedure to a generic repo-hugo skill that also documents the Hugo theme layout, and add an alwaldend-blog skill that publishes supplied content verbatim and reviews it afterward. Enforce one implementation and one copy of each fact in the root policy, and refine the skill locality rule to prefer local ownership only when it genuinely fits.
Share one black theme between the landing shell and the apex site from a single SCSS source, and let docs_filegroup preserve source paths so packages holding identically named files stop colliding.
Repair every nested Bazel workspace: rules_openspec declared six unused, versionless sibling dependencies whose local_path_override entries never applied outside the root module, which broke standalone resolution for all nested modules. Drop those dependencies, ignore the two nested module directories that lacked an ignore entry, add the missing build_test coverage, and extend the full-repository check to all twelve nested workspaces.
OpenSpec-Change: projects/alwaldend.com/openspec/changes/archive/2026-09-12-add-docsy-blog-section OpenSpec-Change: projects/hugo_landing/openspec/changes/archive/2026-09-12-shared-site-canvas OpenSpec-Change: projects/rules_docs/openspec/changes/archive/2026-09-12-nested-spec-path-collision OpenSpec-Change: infra/src/openspec/changes/archive/2026-09-12-fix-nested-workspace-module-resolution
LLM-disclaimer: This commit was generated by an LLM.
-
Remove the goal component, the agent control tower, and the site link test
Delete projects/goal entirely: its CLI, API package, filesystem store, landing site, disabled skill sources, documentation pages, diagrams, Bazel targets, project-registry entry, and committed DNS record. The goal tool was deprecated by the 2026-09-08 migration to the pinned OpenSpec CLI, which is in active use, and the repository policy already told agents not to create goal records.
Delete tools/agents entirely. It carried repository-internal control contracts, seven catalog compilers, an offline context capsule, and typed admission/control/plan/evidence libraries. The goal tool was their only consumer; no CI or AGENTS.md invocation read the catalogs. Relocate the generic skill-discovery declaration to .agents/BUILD.bazel beside the directory it generates, and repoint the 29 skill visibility labels from //tools/agents:skill_discovery to //.agents:skill_discovery. Skill content, link targets, and the 27 existing symlinks are unchanged. A BUILD.bazel inside .agents/skills/ was rejected because the generated updater rejects a non-symlink there.
Reduce projects/agents to its skills: delete the architecture, current-state, and roadmap documents and the docs package they fed. Documentation describing agent-system composition now belongs with the component that owns the behavior.
Remove //projects/alwaldend.com/test/site:site_test. It has never passed since 894494f4: it fails on unmodified HEAD with 330 missing-file findings because it treats repository source paths and the published URL space as one namespace. Repository-only targets such as BUILD.bazel and playbook YAML are deliberately not packaged, so those links can never resolve in generated output.
Record the removals as three OpenSpec changes: remove-deprecated-goal-component and remove-generated-site-link-test under infra/src and projects/alwaldend.com, and remove-goal-tool-and-contract-tower under projects/agents.
The removed bytes remain retrievable from git history at the parent of this commit; the changes neither copy nor restate them.
Address review feedback before publication:
Point the hugo_landing site example at the surviving //projects/agents:docs target. The copied example referenced //projects/agents/docs:docs, which this change deletes, so the snippet failed label resolution.
Point the new specification links at their real paths. The repository change referenced migration.md one directory too shallow, and the Reimu continuation requirement referenced the process contract from beneath the change directory instead of the project root; neither path existed.
Rewrite projects/renders/assets/reimu_fumo/PROCESS.md so its required stage gates no longer depend on the removed goal tool. That contract was the authoritative process for the still-open Reimu work, and it required goal-tool checkpoints, portable goal plans, and goal state to start, repair, reset, and close attempts. Those mechanics now record into the project’s OpenSpec change and its durable evidence, so every gate stays executable. Acceptance criteria and the blocked continuation state are unchanged. The continuation requirement is recorded in the change spec and its rationale in the change design.
OpenSpec-Change: infra/src/openspec/changes/remove-deprecated-goal-component OpenSpec-Change: projects/agents/openspec/changes/remove-goal-tool-and-contract-tower OpenSpec-Change: projects/alwaldend.com/openspec/changes/remove-generated-site-link-test OpenSpec-Change: projects/renders/openspec/changes/reimu-fumo-finish
LLM-disclaimer: This commit was generated by an LLM.
-
Simplify OpenSpec workspace globs
Collapse OpenSpec source globs to specs and changes, drop redundant package visibility blocks already covered by REPO.bazel, and regenerate the affected catalogs.
LLM-disclaimer: This commit was generated by an LLM.
-
Publish project sites and reproducible infrastructure diagrams
Build and deploy all 30 remaining project sites with the standard Docsy header, project descriptions and a linked documentation directory. Omit the repeated page title and generated language heading. Remove the unused cgit and xray_manager projects and retire their site resources.
Add a repeatable GitHub Pages publisher, staged Terraform bootstrap and direct GitHub Pages DNS records. Preserve repeated publication when pages is the remote default branch, and include Rules ISO in the main documentation. Document site onboarding in a registered, validated skill. Keep AL introduction short with useful links and preserve its lifecycle details in a dedicated documentation page.
Render all 15 existing infrastructure Drawio pages with pinned Drawio and Chrome inputs, sandboxed export actions, an update target and freshness checks, and include the maintained diagrams in infra/arch documentation. Paint an opaque white canvas to preserve readability in dark themes.
Validation covers project and apex builds, rendered pages, publisher tests, diagram repeatability and freshness, DNS configuration, Terraform formatting, semantic lint and repository quality.
Goal-Ref: build-and-deploy-every-project-landing-page-a782b800 Attempt-ID: attempt-00941092c164
LLM-disclaimer: This commit was generated by an LLM.
-
Wait for AL secret cleanup and plugin shutdown
Roll back partial plugin startup, drain requests before releasing resources, and wait for plugin and command processes to exit. Stop independent plugins concurrently while preserving dependency order inside each plugin.
Revoke invocation-owned credentials, remove temporary secret files, and verify Forgejo and Harbor session cleanup. Preserve the user’s existing Vault login. Enforce Vault OIDC origins and no_auth, redact sensitive errors, and restrict config dumps to owner-only files. Add the AppRole SecretID cleanup permission.
Cover normal exit, cancellation, failed startup, credential revocation, and transport cleanup with synthetic unit and real command/plugin regression tests.
Clarify that required formatting-only repairs need no separate approval, and fix the existing blank-line formatting failure in the GitHub AL wrapper.
Goal-Ref: fix-al-secret-lifecycle-and-plugin-shutdown-3137c0b0 Attempt-ID: attempt-0c1353676e2f
LLM-disclaimer: This commit was generated by an LLM.
-
Keep Bazel dependencies lazy and generate the root module
Declare pinned InfiniTime sources and the Hedron extractor through use_repo_rule, retain recursive firmware submodules, and use the official contrib_rules_jvm 0.32.0 release. Keep default toolchain registration convenient for consumers.
Move root tool implementations into owning packages while preserving compatibility labels, visibility, manual tags, Python paths, Terraform working directories, pnpm dependency pins, and documentation archive layout. Guard the load-free root BUILD with a parser-based quality test. Generate root MODULE.bazel directly from owning include files, with an update command and freshness/integration tests.
Cache hermetic agent tests, preserve lint analysis across modes, and build only lint outputs in lint mode. Allow normal agent lockfile updates while retaining strict CI checks. Limit host Bazel scheduling to eight jobs and half its CPUs, with matching checked-in host configuration.
Fix DNSControl command ordering, JSON manifest loading, record filename suffixes, and credential-file wiring through existing Vault environment injection. Add an offline config test. Correct the Git wrapper shebang for direct execution and refresh derived catalogs affected by the Bazel changes.
Validation covers compatibility builds, firmware, documentation outputs, generator freshness, DNS configuration, and a live DNS preview without applying changes. The repository-wide audit also identifies pre-existing test and coverage gaps.
Goal-Ref: avoid-unrelated-bazel-dependency-downloads-638e8329 Attempt-ID: attempt-106ffd5ccaeb
LLM-disclaimer: This commit was generated by an LLM.
-
Repair site navigation and simplify page layout
Show one homepage panel with vertically stacked GitHub and Docs rows using the name: URL format, hiding the protocol and trailing slash in the link text. Center the panel and cap its width at 40rem while allowing it to shrink on mobile. Move it slightly lower on desktop and brighten the footer link. Restore the project assets mount so custom styles load. Reduce the footer to its content height with compact padding. Size the homepage against the visible viewport so mobile browser controls do not hide its footer. Remove the separate Projects page and its header link, while keeping project documentation under Docs. Remove the introductory homepage copy and visible title.
Resolve Markdown links and images from their source locations, package missing documentation and book covers, correct source links, and scope anchors and release controls in combined print pages. Restore the archive-root CNAME explicitly during deployment so replacing the site preserves the custom domain.
Validate generated HTML for missing internal files and fragments, duplicate IDs, image alternatives, and the homepage, Misc source-link, and Goal diagram regressions. Check the production build, repository quality, affected-target semantic lint, desktop and mobile homepage rendering, and deployment output.
Goal-Ref: out/site-fix/goals/fix-local-alwaldend-com-layout-and-links-a2e69a4e Attempt-ID: attempt-165dd5be7d71
LLM-disclaimer: This commit was generated by an LLM.
-
Extract DNSControl setup into rules_dnscontrol
Extract the DNSControl setup into
rules_dnscontrol, generate its Bazel dependency bundle from project-owned record files, and update the DNS guidance. Move Hugo rules and the worker to role-based package paths, and give each non-nested project a locally owned Hugo landing target that reuses the shared README-to-landing macro.Clean all landing and Pages DNS records so GitHub Pages serves each project subdomain directly without Cloudflare proxying. Improve the main site with a three-panel home layout, complete project links, documentation explore links, and current deployment guidance.
All affected root-workspace landing, DNS, and site targets pass, along with the nested
rules_hugotests, Buildifier, and repository quality checks.LLM-disclaimer: This commit was generated by an LLM.
-
Improve the Hugo site and fix the persistent worker
Extract the Hugo build rules into a standalone nested module projects/rules_hugo and add a Go-based persistent Hugo worker with a Dart Sass toolchain, then fix the worker’s empty-destination defect, polish the rules, add per-project landing pages and DNS declarations, and improve the site deploy.
- rules_hugo: standalone nested module with MODULE.bazel, main/bzl rules, tests, and README; no root-workspace labels.
- hugo_worker: persistent worker that resolves execroot-relative paths through the work directory and probes DART_SASS_BINARY, so the site destination is populated with HTML and Sass-compiled CSS.
- sass: Dart Sass 1.103.1 toolchain wired into the site build.
- alwaldend.com: Hugo 0.165.0, Docsy 0.17.0, Bootstrap 5.3.8, Font Awesome 7.3.1, module mounts, and the site build switched to the worker.
- Landing pages: content/projects/_index.md links every project to its docs page; a Projects menu entry is added and the content filegroup is wired.
- DNS: projects/alwaldend.com/dnsconfig.json declares no records (no new subdomains) and is wired into infra/dns/dnsconfig.js.
- Deploy: the genrule clones the pages branch that GitHub Pages serves, clears the previous checkout, writes .nojekyll, stages deletions, skips no-op deploys, and pushes HEAD:pages without a force push; the README deploy section is updated.
- Content: rename the reserved sites taxonomy to websites so the alwaldend.com term renders, and fix main/bzl docs prefix collisions across nested modules.
- Review fixes: document the extension-based toolchain registration in the rules_hugo README, sync the full-repo-check eval rubric to nine nested workspaces and twenty commands, and drop the worker’s unsupported outs attribute.
- Validation: site build produces 3051 HTML pages and Sass CSS; worker, terraform, buildifier, and nested rules_hugo tests pass; git diff –check is clean.
LLM-disclaimer: This commit was generated by an LLM.
-
Complete Phase 1 agent system controls
Close the registered agent-reachable universe with owner-local operation declarations, a report-only completeness checker, shared task-run contracts, task/run-isolated Cordis scratch, explicit Terraform mutations, and bounded Bazel diagnostics. Record numeric resource ceilings and accepted durable-goal evidence for the exact candidate.
Integrate the non-render agent tooling and Blender toolchain changes from PR 24 while retaining the old Blender data package whose move destination is excluded. Direct repository agents to prefer Cordis over shell for supported inspection and to consider bounded Cordis handlers for recurring gaps.
Verification:
- affected Bazel build: 74 targets passed
- affected Bazel tests: 23 of 23 passed
- Phase 1 registered-universe report: valid
- goal validation: valid
- git diff –check HEAD: passed
LLM-disclaimer: This commit was generated by an LLM.
-
docs: define the repository agent system
Make the repository legible as one coherent agent-operated system while preserving one mutation authority per fact.
- add revision-bound current state, target architecture, and phased roadmap
- route root and agent entry points to the canonical model and durable goal
- normalize repository-tree policy and the public-information boundary
- clarify task-private secret scratch and non-obvious tool narration
- correct question and secret skill contracts and stale operator examples
- render source-compatible Markdown links correctly in the documentation site
- retain the complete audit, decision, validation, and acceptance record
Validated with focused skill and Buildifier tests, affected Bazel builds, the full Hugo site, source and rendered link checks, exact label queries, repository-pinned formatting, and goal-record validation.
LLM-disclaimer: This commit was generated by an LLM.
- Complete repository quality coverage
-
Add hermetic repository-wide formatting and linting
Integrate upstream formatters for the repository’s meaningful tracked source and configuration file types through Bazel, and add Buildifier, Ruff, and ShellCheck lint aspects for correctness-oriented repository-wide checks.
Pin all new external tools through Bzlmod or the existing pnpm lock, add thin cache/runfiles adapters where required, expose format and check targets, and wire the checks into the pre-commit workflow. Format the existing tree and fix the correctness defects uncovered by the new checks. Preserve generated sources and exact-content fixtures that are not safely rewritable, and clarify that ordinary infrastructure build output is safe to display.
Validation:
- all 21 repository quality and compatibility formatter tests pass
- Buildifier test passes
- lint aspects analyze all 4,629 ordinary root targets without findings
- the complete 18-command root and nested full-repository audit was exercised; remaining failures are documented environment or pre-existing test limits
LLM-disclaimer: This commit was generated by an LLM.
-
Add global repository versioning
Introduce a Bazel-built Go tool that calculates the repository’s global SemVer-compatible ISO-week calendar versions, creates guarded nightly tags and weekly release branches atomically, advances release patches by first-parent commit, and emits deterministic Bazel workspace-status keys.
Route release stamping through the tool and add a packaged, discoverable versioning skill with offline Promptfoo validation. Cover ISO week boundaries, SemVer formatting, branch and dirty-tree guards, release patch calculation, tag integrity, and stamping output with focused tests.
Provide a clean-checkout bootstrap that builds the Go tool before it launches the stamped Bazel command. Bind ref transactions to the inspected commit, neutralize Git replace/graft/routing inputs, make dry runs validate namespace collisions, validate every published patch tag against its exact first-parent position, reject ambiguous or inconsistent tag states, and require explicit context for detached release calculations. Route detached release-tag selection through those same history-integrity checks. Keep development status cache-safe by emitting Git identity as volatile data while making immutable nightly and release identities stable.
Add a repository-delivery integration regression proving that a failed aggregate whitespace check identifies the offending path exactly once.
Verified with:
- bazel_agent test //tools/versioning/… //tools/repo_delivery/main/go:go_test //:write_skill_links_test //:buildifier_test
- bazel_agent build //tools/versioning/… //tools/repo_delivery/…
- tools/versioning/cmd/versioning/versioning.sh bazel – build –config=release //tools/versioning/cmd/versioning
- real Git integration tests covering ref transactions, SHA-256 repositories, environment isolation, detached contexts, tag ordering, and namespace collisions
LLM-disclaimer: This commit was generated by an LLM.
-
Add standalone documentation rules
Move docs_filegroup into a reusable rules_docs nested Bzlmod workspace and migrate every root and nested consumer to it. Add a module-aware Gazelle language that creates docs targets only for existing README packages while preserving manual mappings.
Wire the workspace into module resolution, documentation aggregation, and the ten-command full-repo-check. Add the bazel-nested-module skill so future nested workspaces follow the repository’s rc, lockfile, docs, toolchain, Gazelle, and validation conventions.
Keep reviewed Gazelle dependency canonicalization, while protecting the hand-maintained Go proto, Python resource, Android, embedded-site, and skill runner definitions that generic language plugins would otherwise break.
This commit was generated by an LLM.
-
Keep embedded site server in target configuration
This commit was generated by an LLM.
-
Fix Bazel build caching and tool configuration
This commit was generated by an LLM.
-
Remove redundant documentation mappings
Inline sources from eight layout-neutral pkg_files wrappers and migrate the remaining legacy Vial docs producer to docs_filegroup. Keep only mappings that perform required renames.\n\nThis commit was generated by an LLM.
-
Complete docs filegroup migration
Pass ordinary documentation sources directly and isolate generated or renamed outputs in semantic pkg_files dependencies. Remove the obsolete renames and strip_prefix surface from docs_filegroup.\n\nThis commit was generated by an LLM.
-
Make release generation hermetic
Add the missing AL and Kustomization release targets and give release actions a declared bare Git snapshot instead of access to the workspace repository.\n\nThis commit was generated by an LLM.
-
Migrate documentation packaging to docs_filegroup
Preserve custom prefixes, renames, strip prefixes, and standalone workspace behavior.\n\nThis commit was generated by an LLM.
-
Make Qt and Maven dependencies hermetic
Align protobuf with the Android build tools and refresh generated locks.\n\nThis commit was generated by an LLM.
-
Make Android SDK setup reproducible
This commit was generated by an LLM.
-
Add agent-friendly Bazel config
This commit was generated by an LLM.
- Use an image from the marketplace, update some locks, add CODEOWNERS
- Finish opencode deploy
- Add //third_party/org_fedora_cloud, fix alwaldend.com roles
- Set up unikernel deploy
- Refactor flux manifests a bit, add //tools/ops
- Add a server to //projects/alwaldend.com
- Add OIDC for k3s, add OIDC fetcher to injector
- Add drawio-desktop, add //infra/arch, update opencode restrictions
- Finish forgejo_login, add org to forgejo tf, remove cl1
- Add //third_party/org_kernel_headers, rename all deps files to include
- Add //third_party/org_nmap_nmap
- Fix ssh key signing
- Add ssh key signing to injector, remove more FP from injector
- Finish the lifecycle manager, intergrate it
- Continue working on the lifecycle manager
- Add a lifecycle manager
- Add WaitCtx to fp.WaitGroupE
- Split startups and shutdowns, add timeouts to shutdowns
- Improve plugin clients and servers
- Improve plugin concurrency, remove FP from tf_backend
- Migrate all state to Vault
- Finish rewriting the injector into a gRPC plugin
- Set up convertation between protobuf json and regular json
- Continue rewriting the secret injector to a plugin
- Continue rewriting the injector to a plugin
- Continue rewriting the vault injector to a plugin
- Add //tools/vault/injector, start migrating resource_handler to it
- Add pipes with error and panic handling, add some more FP stuff
- Fix plugins broken after the refactor, remove main from bazelrc, move FP updates
- Refactor FP to use recursive generics, add some iterator handling
- Add more FP stuff, add plugin configs to al.lua, migrate pve_login and tf_backend to new configs
- Move //tools/al to //projects/al, add Result and Pipe to fp
- Automate root token generation, split the main vault policy into separate ones
- Set up cert authentication
- Add //tools/ykman
- Add //tools/al, remove //tools/secrets, set up proper approle workflow
- Setup Vault token helper using gnome-keyring
- Disable mTLS of the Vault instance, add unsealing information, setup //tools/vault
- Fix some Js and Python CVEs
- Add some information about SSL
- Add new pgp key, rename //data/gpg to //data/pgp, add some info about ssh and pgp
- Add data to //projects/alwaldend.com, add //data/gpg
- Use write_source_files for git_hooks
- Add lvol role, setup LVM volumes on bm3
- Remove //tools/docs, remove .github
- Finalize rules_template refactoring
- Update dns
- Add rules_distroless, add some qubes os info
- Remove al_go_cross_binary, update the setup guide a bit
- Update the setup guide, update android tools, update leetcode, update books
- Update the repo setup doc a bit
- Add //tools/word_lists, update DNS and glossary
- Update leetcode
- Add build_test tests
- Fix urllib vulnerabilities
- Add editing, encryption, decryption
- Start adding secret rules, add badges to books
- Move all the logig out of the screen to the controller
- Add deploy to dockerhub, add //tools/oras
- Remove last modification footer
- Add missing features to the Pomodoro app, update project readmes, add github pages
- Update infinitime patch, start adding trufflehog rules
- Add hugo lock support, add proper hugo toolchain support, improve the ansible lock
- Move all remaining code to main
- Move a portion of tool code to main
- Move the registry to //projects/bazel_registry
- Add minisign rules
- Remove sites taxonomy, start adding xray_manager
- Fix release page rendering
- Move to a light nvim theme, add full git info to releases
- Add release_page generation, remove redundant release templates
- Fix nvim library paths
- Parallelize git info retrieval
- Move links to the config, use list groups
- Remove contracts tree
- Add changelogs
- Allow docs to put content outside of docs, refactor git to just use .git directly
- Add the footer back, add hugo env information
- Move release items to a list group, add item counter
- Add cross-compilation, move leetcode downloader contracts out of //contracts
- Refactor release templates into partials, add release cards
- Add RSS links, rewrite links shortcode to html, improve release tables
- Add file size to releases, add round_float partial
- Write release tool in go, start adding it to projects, add py proto generation
- Add release rules, add gzip rules, add several other tools, remove autoscrool deps from the root
- Add dev_shell rules, add make_install_binary, flatten sh rules, add dotfiles/bin
- Add //tools/make_install, start moving dotfiles to it
- Add label_link shortcode, add todo page
- Move book data to data/books
- Add tools/rfc
- Add bzl snippets to proto docs, add targets for ansible playbooks
- Remove the footer from the docs
- Add dnscontrol rules
- Move book data to the books page, add lazy loading, save some thumbnails locally
- Make tables more compact
- Disable inline partials, add last modified section
- Tweak tables again
- Improve tables on home and books pages
- Improve tables
- Do not use nested tables in docs/misc/books
- Fix book rendering, add arm CI for some reason
- Add git image, split root MODULE.bazel
- Add more taxonomies, remove docs tree, move alwaldend.com to projects
- Initial commit
- Update vulnerable Go dependencies
-
Add spellcheck skill
This commit was generated by an LLM.
-
Consolidate agent policy into owning skills
Reduce the root AGENTS.md from 255 lines to 141 by keeping repository-wide constraints visible and moving execution detail to the skill that owns it.
Make initial reads task-dependent, replace the absolute one-copy rule with one authoritative source, simplify the retry rule to its principle, and fix the generated-file delivery ambiguity. Add a single “When to load a skill” routing table ordered by task phase.
Add the repo-workspace skill so worktree isolation and task-scratch placement are established before the first write rather than when repo-delivery loads. Transfer commit-subject and trailer conventions into a repo-delivery reference and the Go and Bazel-native automation rules into repo-bazel. Reconcile the git-rebase-remote and repo-delivery drift so a task-owned rewrite may change ancestry while preserving every previously remote commit’s reachable progress.
OpenSpec-Change: infra/src/openspec/changes/consolidate-agent-policy-into-skills
LLM-disclaimer: This commit was generated by an LLM.
-
Restore light and dark site canvases and set the shared accent
The shared Docsy canvas set the same Bootstrap dark palette and the same black page background on
:root,[data-bs-theme="light"], and[data-bs-theme="dark"], so the light/dark toggle changed nothing. The site also rendered Bootstrap’s stock blue instead of its intended accent.Split the shared palette so light mode uses a pure white canvas with the light-mode palette and dark mode uses a pure black canvas with the dark-mode palette, and keep the pre-stylesheet paint and footer on the active mode. Assign
$primaryto#7c3aedbefore Bootstrap compiles, so links, buttons, badges, focus rings, and the dark-mode link tint all derive from one value rather than from a site-local copy.Both files stay in the reusable shell; the apex site consumes them through the existing declared exports and no longer carries the footer’s own blue.
OpenSpec-Change: projects/hugo_landing/openspec/changes/restore-light-dark-canvas-and-accent
LLM-disclaimer: This commit was generated by an LLM.
1.3.2.1 - head
-
Lay the project index out as a single-column section list
The card grid read as a separate component next to the rest of the site. The
/projects/index now uses the same section list as the documentation index: one entry per project under theProjectsheading, separated by panel lines, each entry carrying its description, status, and tags. The entries stay in alphabetical order.Wrap the list in a section so the theme’s first-section offset applies; without it the
Projectsheading rendered underneath the fixed navbar.LLM-disclaimer: This commit was generated by an LLM.
-
Add a staging publication and refine the project index
Verify the project landing replacement on its own hostname before the apex changes and before any per-project resource is retired, and make the landing index useful to a visitor.
www-staging.alwaldend.comgets a checked-in DNS declaration and a catalog repository, and the apex site gains a staging build that renders the same packaged source with the staging base URL plus a deployment command that publishes it. The publication command now takes its repository and branch as arguments, so staging and production share one publisher, and a repository whose publication branch does not exist yet is created as an orphan instead of failing on clone. A new repository receives a default branch at creation so the managed ruleset can protect it while site content publishes to a separate branch, and GitHub Pages configuration is deferred for a repository until its publication branch exists.The
/projects/index no longer opens with explanatory prose, lists landings alphabetically, and shows each project’s status and tags as links to their taxonomy term pages.Deploy the staging site, verify the landing, documentation, and taxonomy routes there, then deploy the accepted output to the apex and verify the same routes. The per-project hostnames, DNS records, and landing repositories remain in place until their retirement is requested.
OpenSpec-Change: projects/alwaldend.com/openspec/changes/site-staging-environment
LLM-disclaimer: This commit was generated by an LLM.
-
Move project landings into the main site
Publish every registered project’s visitor-facing landing page at /projects/
/ from the main site instead of a dedicated subdomain, and retire the per-project Pages repository, CNAME, and Terraform DNS stage that existed only to serve one page derived from the project README. Each project owns its landing content in projects/
/site/content/ as pure content: no layouts, styles, or build rules. The main site packages those directories into content/projects/ / from the registry in projects/projects.bzl, so membership is declared once. The landing is a short hand-written page for visitors while the README keeps its /docs/projects/ / URL for repository reference documentation, and landing front matter now feeds the statuses, languages, and tags taxonomies. Merge the reusable hugo_landing project into the main site: its shared canvas and accent styles and its landing page rules move into the apex tree, and its landing macro, generated configuration, standalone publisher, and repository-relative rewrite layouts are removed. The theme keeps owning the taxonomy and term layouts, which are richer than the heading-only versions the reusable project carried. Remove the now-unused apex deploy_project.sh and deploy_all.sh landing publishers with it.
Retire the per-project publication and DNS ownership: the project landing targets and the landing deployment command, each landing project’s dnsconfig.json and Terraform root, the build plumbing that served only those stages, and the landing repository and Pages membership in the repository catalog. The apex Terraform root is retained because it also declares VM resources, and no Vault configuration is changed.
Replace the provider-snapshot zone files with generated declaration pages, one per destination view, that project the checked-in declarations and are verified for freshness by the DNS offline check. The DNS linter, both destination pages, the apex site, the skills projection, and the repository quality suite pass, and the whole repository builds.
OpenSpec-Change: projects/alwaldend.com/openspec/changes/consolidate-project-landings-into-apex
LLM-disclaimer: This commit was generated by an LLM.
-
Merge pull request #94 from alwaldend/t3code/fix-hugo-theme-light-dark-accent
Restore light and dark site canvases and set the shared accent
-
Manage forge resources with hermetic Terraform rules
Centralize organization, repository, and named access configuration in infra/repos. Adopt existing GitHub resources, protect master defaults while retaining Pages publication on pages, and preserve existing repository identities. Manage GitLab one-time imports, the F-Droid metadata fork, and default-branch protections through Vault-backed authentication. Forgejo consumes the same catalog. Ongoing repository synchronization is deferred.
Retire the eleven Bazel rule landing sites through their owning Terraform workflows, removing their DNS records, Pages repositories, and landing configuration. Move all twelve existing standalone rule modules into tools/ and retain their public interfaces and documentation on the main site.
Add tools/rules_terraform with verified provider downloads, packed mirrors in runfiles, and reusable Terraform execution rules. Enforce one version per provider source at an extensible resolution boundary. Migrate every Terraform consumer to thirteen shared provider pins in third_party/terraform. Execution and command maps belong to rules_terraform; consumers explicitly select generic AL wrappers for authentication and Vault injection. Remove tools/terraform and all 43 checked-in Terraform provider locks. Validate installed providers against the declared archives before execution.
Validation covers all fourteen workspace builds, all thirteen standalone test suites, Terraform consumers, offline real-provider regressions, rendered documentation, formatting, and semantic lint. The full root test run has 295 passing tests and one skip; its only failure is the historical secret scan, reduced to four pre-existing synthetic fixture matches. Earlier live imports and the exact landing retirement scope have verified postconditions; the Terraform rules migration uses only offline implementation checks.
OpenSpec-Change: infra/repos/openspec/changes/archive/2026-09-13-adopt-shared-repository-catalog OpenSpec-Change: infra/src/openspec/changes/archive/2026-09-13-retire-bazel-rule-landings OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-add-hermetic-terraform-rules OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-correct-terraform-ownership
LLM-disclaimer: This commit was generated by an LLM.
-
Publish the DNS evolution article and update blog workflow
Publish the author’s account of moving DNS management from a central DNSControl configuration to project-owned Terraform records, with examples and directory layouts. Include the author’s clarifications and approved wording corrections, and remove the draft flag for publication.
Tag both blog posts using existing site topics. Require relevant tags and iterative reviews in the blog skill: report findings before validation and delivery, repeat after changes, and finish delivery when the review is clear or the author ends it. Cover both behaviors in the existing evaluation cases.
Validation: local and release Hugo builds, site_test, skill validation and offline Promptfoo configuration test, skill discovery, Buildifier, repository quality, and semantic lint for the affected blog and skill packages.
LLM-disclaimer: This commit was generated by an LLM.
-
Deploy project DNS through Terraform modules
Move DNS ownership into each project’s Terraform state using shared modules. Load dnsconfig.json files at runtime, reject conflicting domain ownership, and render their records as a table. Add missing project AppRoles and scoped DNS policies, and document grouping related Terraform resources in modules.
Deploy all 45 owners sequentially: adopt 155 existing records and create 13 missing OpenHands records. Preserve every pre-existing provider record and verify no-op follow-up plans and DNS answers. Add DNS-scoped plan/show/apply wrappers with a saved-plan guard for roots that also manage services. Allow bounded aggregate path inventories large enough to deliver this migration while retaining truncation refusal in the delivery tool.
Validate runtime ownership, provider imports and preservation with isolated fixtures, Terraform formatting, wrapper builds, repository quality checks, semantic lint, and project documentation/specification builds.
OpenSpec-Change: infra/dns/openspec/changes/archive/2026-09-13-migrate-project-dns-to-terraform
LLM-disclaimer: This commit was generated by an LLM.
-
Record the site hostname decision for alwaldend.com
Record the evaluated options for the apex site’s landing, documentation, and blog sections: one hostname with one build (retained), separate hostnames served from separate GitHub Pages repositories, and one hostname with independently built and merged section outputs. The generated documentation tree is a projection of the repository’s own directory structure across 471 packaged README files, and an earlier commit already combined the misc, docs, and projects sites, so splitting the hostnames would move where the projection is served without decoupling it from its source.
Separate the shared-build failure coupling from the hostname question: the recorded fallback keeps one published tree while splitting the build graph, if panicking on any packaged README warning starts blocking delivery.
Record the search-engine evidence from primary sources. Google’s crawling-and-indexing FAQ states that from an indexing and ranking perspective Google has no preference, and the office-hours answer recorded here addresses the same question. The record explicitly does not claim that subdirectories preserve link equity that a subdomain would forfeit, and it cites a third vendor video by title only because its spoken content could not be retrieved.
This change adds no site behavior, build target, configuration, DNS record, or Terraform resource.
OpenSpec-Change: projects/alwaldend.com/openspec/changes/archive/2026-09-12-record-site-hostname-decision
LLM-disclaimer: This commit was generated by an LLM.
-
Fix Android review feedback
Add a shared
androidPluginsversion catalog so both Android apps declare the AGP, Kotlin, Compose, and protobuf plugin versions once, and derive their versions from it instead of duplicating literals per root Gradle file.Align the launcher and ingester app versions with the repository versioning contract: development builds use
0.0.0-devwithversionCode1 in both the Gradle default config and the Bazelmanifest_values.Ignore the whole materialized
.agents/skillsdirectory in Prettier because every entry is either a source-tree symlink or a byte-pinned external archive copy.Apply the ingester’s themed surface background to the main content surface so the status bar area follows the system theme, not a default white surface.
Token: z-ai-glm-flash-latest
LLM-disclaimer: This commit was generated by an LLM.
-
Add a blog section, a shared site canvas, and standalone nested modules
Publish the Docsy blog section on the apex site with its content package, navigation entry, RSS feed, and draft-safe release flags. The release build excludes drafts so a post stays unpublished from its front matter alone.
Move the reusable project-site procedure to a generic repo-hugo skill that also documents the Hugo theme layout, and add an alwaldend-blog skill that publishes supplied content verbatim and reviews it afterward. Enforce one implementation and one copy of each fact in the root policy, and refine the skill locality rule to prefer local ownership only when it genuinely fits.
Share one black theme between the landing shell and the apex site from a single SCSS source, and let docs_filegroup preserve source paths so packages holding identically named files stop colliding.
Repair every nested Bazel workspace: rules_openspec declared six unused, versionless sibling dependencies whose local_path_override entries never applied outside the root module, which broke standalone resolution for all nested modules. Drop those dependencies, ignore the two nested module directories that lacked an ignore entry, add the missing build_test coverage, and extend the full-repository check to all twelve nested workspaces.
OpenSpec-Change: projects/alwaldend.com/openspec/changes/archive/2026-09-12-add-docsy-blog-section OpenSpec-Change: projects/hugo_landing/openspec/changes/archive/2026-09-12-shared-site-canvas OpenSpec-Change: projects/rules_docs/openspec/changes/archive/2026-09-12-nested-spec-path-collision OpenSpec-Change: infra/src/openspec/changes/archive/2026-09-12-fix-nested-workspace-module-resolution
LLM-disclaimer: This commit was generated by an LLM.
-
Remove the goal component, the agent control tower, and the site link test
Delete projects/goal entirely: its CLI, API package, filesystem store, landing site, disabled skill sources, documentation pages, diagrams, Bazel targets, project-registry entry, and committed DNS record. The goal tool was deprecated by the 2026-09-08 migration to the pinned OpenSpec CLI, which is in active use, and the repository policy already told agents not to create goal records.
Delete tools/agents entirely. It carried repository-internal control contracts, seven catalog compilers, an offline context capsule, and typed admission/control/plan/evidence libraries. The goal tool was their only consumer; no CI or AGENTS.md invocation read the catalogs. Relocate the generic skill-discovery declaration to .agents/BUILD.bazel beside the directory it generates, and repoint the 29 skill visibility labels from //tools/agents:skill_discovery to //.agents:skill_discovery. Skill content, link targets, and the 27 existing symlinks are unchanged. A BUILD.bazel inside .agents/skills/ was rejected because the generated updater rejects a non-symlink there.
Reduce projects/agents to its skills: delete the architecture, current-state, and roadmap documents and the docs package they fed. Documentation describing agent-system composition now belongs with the component that owns the behavior.
Remove //projects/alwaldend.com/test/site:site_test. It has never passed since 894494f4: it fails on unmodified HEAD with 330 missing-file findings because it treats repository source paths and the published URL space as one namespace. Repository-only targets such as BUILD.bazel and playbook YAML are deliberately not packaged, so those links can never resolve in generated output.
Record the removals as three OpenSpec changes: remove-deprecated-goal-component and remove-generated-site-link-test under infra/src and projects/alwaldend.com, and remove-goal-tool-and-contract-tower under projects/agents.
The removed bytes remain retrievable from git history at the parent of this commit; the changes neither copy nor restate them.
Address review feedback before publication:
Point the hugo_landing site example at the surviving //projects/agents:docs target. The copied example referenced //projects/agents/docs:docs, which this change deletes, so the snippet failed label resolution.
Point the new specification links at their real paths. The repository change referenced migration.md one directory too shallow, and the Reimu continuation requirement referenced the process contract from beneath the change directory instead of the project root; neither path existed.
Rewrite projects/renders/assets/reimu_fumo/PROCESS.md so its required stage gates no longer depend on the removed goal tool. That contract was the authoritative process for the still-open Reimu work, and it required goal-tool checkpoints, portable goal plans, and goal state to start, repair, reset, and close attempts. Those mechanics now record into the project’s OpenSpec change and its durable evidence, so every gate stays executable. Acceptance criteria and the blocked continuation state are unchanged. The continuation requirement is recorded in the change spec and its rationale in the change design.
OpenSpec-Change: infra/src/openspec/changes/remove-deprecated-goal-component OpenSpec-Change: projects/agents/openspec/changes/remove-goal-tool-and-contract-tower OpenSpec-Change: projects/alwaldend.com/openspec/changes/remove-generated-site-link-test OpenSpec-Change: projects/renders/openspec/changes/reimu-fumo-finish
LLM-disclaimer: This commit was generated by an LLM.
-
Simplify OpenSpec workspace globs
Collapse OpenSpec source globs to specs and changes, drop redundant package visibility blocks already covered by REPO.bazel, and regenerate the affected catalogs.
LLM-disclaimer: This commit was generated by an LLM.
-
Publish project sites and reproducible infrastructure diagrams
Build and deploy all 30 remaining project sites with the standard Docsy header, project descriptions and a linked documentation directory. Omit the repeated page title and generated language heading. Remove the unused cgit and xray_manager projects and retire their site resources.
Add a repeatable GitHub Pages publisher, staged Terraform bootstrap and direct GitHub Pages DNS records. Preserve repeated publication when pages is the remote default branch, and include Rules ISO in the main documentation. Document site onboarding in a registered, validated skill. Keep AL introduction short with useful links and preserve its lifecycle details in a dedicated documentation page.
Render all 15 existing infrastructure Drawio pages with pinned Drawio and Chrome inputs, sandboxed export actions, an update target and freshness checks, and include the maintained diagrams in infra/arch documentation. Paint an opaque white canvas to preserve readability in dark themes.
Validation covers project and apex builds, rendered pages, publisher tests, diagram repeatability and freshness, DNS configuration, Terraform formatting, semantic lint and repository quality.
Goal-Ref: build-and-deploy-every-project-landing-page-a782b800 Attempt-ID: attempt-00941092c164
LLM-disclaimer: This commit was generated by an LLM.
-
Wait for AL secret cleanup and plugin shutdown
Roll back partial plugin startup, drain requests before releasing resources, and wait for plugin and command processes to exit. Stop independent plugins concurrently while preserving dependency order inside each plugin.
Revoke invocation-owned credentials, remove temporary secret files, and verify Forgejo and Harbor session cleanup. Preserve the user’s existing Vault login. Enforce Vault OIDC origins and no_auth, redact sensitive errors, and restrict config dumps to owner-only files. Add the AppRole SecretID cleanup permission.
Cover normal exit, cancellation, failed startup, credential revocation, and transport cleanup with synthetic unit and real command/plugin regression tests.
Clarify that required formatting-only repairs need no separate approval, and fix the existing blank-line formatting failure in the GitHub AL wrapper.
Goal-Ref: fix-al-secret-lifecycle-and-plugin-shutdown-3137c0b0 Attempt-ID: attempt-0c1353676e2f
LLM-disclaimer: This commit was generated by an LLM.
-
Keep Bazel dependencies lazy and generate the root module
Declare pinned InfiniTime sources and the Hedron extractor through use_repo_rule, retain recursive firmware submodules, and use the official contrib_rules_jvm 0.32.0 release. Keep default toolchain registration convenient for consumers.
Move root tool implementations into owning packages while preserving compatibility labels, visibility, manual tags, Python paths, Terraform working directories, pnpm dependency pins, and documentation archive layout. Guard the load-free root BUILD with a parser-based quality test. Generate root MODULE.bazel directly from owning include files, with an update command and freshness/integration tests.
Cache hermetic agent tests, preserve lint analysis across modes, and build only lint outputs in lint mode. Allow normal agent lockfile updates while retaining strict CI checks. Limit host Bazel scheduling to eight jobs and half its CPUs, with matching checked-in host configuration.
Fix DNSControl command ordering, JSON manifest loading, record filename suffixes, and credential-file wiring through existing Vault environment injection. Add an offline config test. Correct the Git wrapper shebang for direct execution and refresh derived catalogs affected by the Bazel changes.
Validation covers compatibility builds, firmware, documentation outputs, generator freshness, DNS configuration, and a live DNS preview without applying changes. The repository-wide audit also identifies pre-existing test and coverage gaps.
Goal-Ref: avoid-unrelated-bazel-dependency-downloads-638e8329 Attempt-ID: attempt-106ffd5ccaeb
LLM-disclaimer: This commit was generated by an LLM.
-
Repair site navigation and simplify page layout
Show one homepage panel with vertically stacked GitHub and Docs rows using the name: URL format, hiding the protocol and trailing slash in the link text. Center the panel and cap its width at 40rem while allowing it to shrink on mobile. Move it slightly lower on desktop and brighten the footer link. Restore the project assets mount so custom styles load. Reduce the footer to its content height with compact padding. Size the homepage against the visible viewport so mobile browser controls do not hide its footer. Remove the separate Projects page and its header link, while keeping project documentation under Docs. Remove the introductory homepage copy and visible title.
Resolve Markdown links and images from their source locations, package missing documentation and book covers, correct source links, and scope anchors and release controls in combined print pages. Restore the archive-root CNAME explicitly during deployment so replacing the site preserves the custom domain.
Validate generated HTML for missing internal files and fragments, duplicate IDs, image alternatives, and the homepage, Misc source-link, and Goal diagram regressions. Check the production build, repository quality, affected-target semantic lint, desktop and mobile homepage rendering, and deployment output.
Goal-Ref: out/site-fix/goals/fix-local-alwaldend-com-layout-and-links-a2e69a4e Attempt-ID: attempt-165dd5be7d71
LLM-disclaimer: This commit was generated by an LLM.
-
Extract DNSControl setup into rules_dnscontrol
Extract the DNSControl setup into
rules_dnscontrol, generate its Bazel dependency bundle from project-owned record files, and update the DNS guidance. Move Hugo rules and the worker to role-based package paths, and give each non-nested project a locally owned Hugo landing target that reuses the shared README-to-landing macro.Clean all landing and Pages DNS records so GitHub Pages serves each project subdomain directly without Cloudflare proxying. Improve the main site with a three-panel home layout, complete project links, documentation explore links, and current deployment guidance.
All affected root-workspace landing, DNS, and site targets pass, along with the nested
rules_hugotests, Buildifier, and repository quality checks.LLM-disclaimer: This commit was generated by an LLM.
-
Improve the Hugo site and fix the persistent worker
Extract the Hugo build rules into a standalone nested module projects/rules_hugo and add a Go-based persistent Hugo worker with a Dart Sass toolchain, then fix the worker’s empty-destination defect, polish the rules, add per-project landing pages and DNS declarations, and improve the site deploy.
- rules_hugo: standalone nested module with MODULE.bazel, main/bzl rules, tests, and README; no root-workspace labels.
- hugo_worker: persistent worker that resolves execroot-relative paths through the work directory and probes DART_SASS_BINARY, so the site destination is populated with HTML and Sass-compiled CSS.
- sass: Dart Sass 1.103.1 toolchain wired into the site build.
- alwaldend.com: Hugo 0.165.0, Docsy 0.17.0, Bootstrap 5.3.8, Font Awesome 7.3.1, module mounts, and the site build switched to the worker.
- Landing pages: content/projects/_index.md links every project to its docs page; a Projects menu entry is added and the content filegroup is wired.
- DNS: projects/alwaldend.com/dnsconfig.json declares no records (no new subdomains) and is wired into infra/dns/dnsconfig.js.
- Deploy: the genrule clones the pages branch that GitHub Pages serves, clears the previous checkout, writes .nojekyll, stages deletions, skips no-op deploys, and pushes HEAD:pages without a force push; the README deploy section is updated.
- Content: rename the reserved sites taxonomy to websites so the alwaldend.com term renders, and fix main/bzl docs prefix collisions across nested modules.
- Review fixes: document the extension-based toolchain registration in the rules_hugo README, sync the full-repo-check eval rubric to nine nested workspaces and twenty commands, and drop the worker’s unsupported outs attribute.
- Validation: site build produces 3051 HTML pages and Sass CSS; worker, terraform, buildifier, and nested rules_hugo tests pass; git diff –check is clean.
LLM-disclaimer: This commit was generated by an LLM.
-
Complete Phase 1 agent system controls
Close the registered agent-reachable universe with owner-local operation declarations, a report-only completeness checker, shared task-run contracts, task/run-isolated Cordis scratch, explicit Terraform mutations, and bounded Bazel diagnostics. Record numeric resource ceilings and accepted durable-goal evidence for the exact candidate.
Integrate the non-render agent tooling and Blender toolchain changes from PR 24 while retaining the old Blender data package whose move destination is excluded. Direct repository agents to prefer Cordis over shell for supported inspection and to consider bounded Cordis handlers for recurring gaps.
Verification:
- affected Bazel build: 74 targets passed
- affected Bazel tests: 23 of 23 passed
- Phase 1 registered-universe report: valid
- goal validation: valid
- git diff –check HEAD: passed
LLM-disclaimer: This commit was generated by an LLM.
-
docs: define the repository agent system
Make the repository legible as one coherent agent-operated system while preserving one mutation authority per fact.
- add revision-bound current state, target architecture, and phased roadmap
- route root and agent entry points to the canonical model and durable goal
- normalize repository-tree policy and the public-information boundary
- clarify task-private secret scratch and non-obvious tool narration
- correct question and secret skill contracts and stale operator examples
- render source-compatible Markdown links correctly in the documentation site
- retain the complete audit, decision, validation, and acceptance record
Validated with focused skill and Buildifier tests, affected Bazel builds, the full Hugo site, source and rendered link checks, exact label queries, repository-pinned formatting, and goal-record validation.
LLM-disclaimer: This commit was generated by an LLM.
- Complete repository quality coverage
-
Add hermetic repository-wide formatting and linting
Integrate upstream formatters for the repository’s meaningful tracked source and configuration file types through Bazel, and add Buildifier, Ruff, and ShellCheck lint aspects for correctness-oriented repository-wide checks.
Pin all new external tools through Bzlmod or the existing pnpm lock, add thin cache/runfiles adapters where required, expose format and check targets, and wire the checks into the pre-commit workflow. Format the existing tree and fix the correctness defects uncovered by the new checks. Preserve generated sources and exact-content fixtures that are not safely rewritable, and clarify that ordinary infrastructure build output is safe to display.
Validation:
- all 21 repository quality and compatibility formatter tests pass
- Buildifier test passes
- lint aspects analyze all 4,629 ordinary root targets without findings
- the complete 18-command root and nested full-repository audit was exercised; remaining failures are documented environment or pre-existing test limits
LLM-disclaimer: This commit was generated by an LLM.
-
Add global repository versioning
Introduce a Bazel-built Go tool that calculates the repository’s global SemVer-compatible ISO-week calendar versions, creates guarded nightly tags and weekly release branches atomically, advances release patches by first-parent commit, and emits deterministic Bazel workspace-status keys.
Route release stamping through the tool and add a packaged, discoverable versioning skill with offline Promptfoo validation. Cover ISO week boundaries, SemVer formatting, branch and dirty-tree guards, release patch calculation, tag integrity, and stamping output with focused tests.
Provide a clean-checkout bootstrap that builds the Go tool before it launches the stamped Bazel command. Bind ref transactions to the inspected commit, neutralize Git replace/graft/routing inputs, make dry runs validate namespace collisions, validate every published patch tag against its exact first-parent position, reject ambiguous or inconsistent tag states, and require explicit context for detached release calculations. Route detached release-tag selection through those same history-integrity checks. Keep development status cache-safe by emitting Git identity as volatile data while making immutable nightly and release identities stable.
Add a repository-delivery integration regression proving that a failed aggregate whitespace check identifies the offending path exactly once.
Verified with:
- bazel_agent test //tools/versioning/… //tools/repo_delivery/main/go:go_test //:write_skill_links_test //:buildifier_test
- bazel_agent build //tools/versioning/… //tools/repo_delivery/…
- tools/versioning/cmd/versioning/versioning.sh bazel – build –config=release //tools/versioning/cmd/versioning
- real Git integration tests covering ref transactions, SHA-256 repositories, environment isolation, detached contexts, tag ordering, and namespace collisions
LLM-disclaimer: This commit was generated by an LLM.
-
Add standalone documentation rules
Move docs_filegroup into a reusable rules_docs nested Bzlmod workspace and migrate every root and nested consumer to it. Add a module-aware Gazelle language that creates docs targets only for existing README packages while preserving manual mappings.
Wire the workspace into module resolution, documentation aggregation, and the ten-command full-repo-check. Add the bazel-nested-module skill so future nested workspaces follow the repository’s rc, lockfile, docs, toolchain, Gazelle, and validation conventions.
Keep reviewed Gazelle dependency canonicalization, while protecting the hand-maintained Go proto, Python resource, Android, embedded-site, and skill runner definitions that generic language plugins would otherwise break.
This commit was generated by an LLM.
-
Keep embedded site server in target configuration
This commit was generated by an LLM.
-
Fix Bazel build caching and tool configuration
This commit was generated by an LLM.
-
Remove redundant documentation mappings
Inline sources from eight layout-neutral pkg_files wrappers and migrate the remaining legacy Vial docs producer to docs_filegroup. Keep only mappings that perform required renames.\n\nThis commit was generated by an LLM.
-
Complete docs filegroup migration
Pass ordinary documentation sources directly and isolate generated or renamed outputs in semantic pkg_files dependencies. Remove the obsolete renames and strip_prefix surface from docs_filegroup.\n\nThis commit was generated by an LLM.
-
Make release generation hermetic
Add the missing AL and Kustomization release targets and give release actions a declared bare Git snapshot instead of access to the workspace repository.\n\nThis commit was generated by an LLM.
-
Migrate documentation packaging to docs_filegroup
Preserve custom prefixes, renames, strip prefixes, and standalone workspace behavior.\n\nThis commit was generated by an LLM.
-
Make Qt and Maven dependencies hermetic
Align protobuf with the Android build tools and refresh generated locks.\n\nThis commit was generated by an LLM.
-
Make Android SDK setup reproducible
This commit was generated by an LLM.
-
Add agent-friendly Bazel config
This commit was generated by an LLM.
- Use an image from the marketplace, update some locks, add CODEOWNERS
- Finish opencode deploy
- Add //third_party/org_fedora_cloud, fix alwaldend.com roles
- Set up unikernel deploy
- Refactor flux manifests a bit, add //tools/ops
- Add a server to //projects/alwaldend.com
- Add OIDC for k3s, add OIDC fetcher to injector
- Add drawio-desktop, add //infra/arch, update opencode restrictions
- Finish forgejo_login, add org to forgejo tf, remove cl1
- Add //third_party/org_kernel_headers, rename all deps files to include
- Add //third_party/org_nmap_nmap
- Fix ssh key signing
- Add ssh key signing to injector, remove more FP from injector
- Finish the lifecycle manager, intergrate it
- Continue working on the lifecycle manager
- Add a lifecycle manager
- Add WaitCtx to fp.WaitGroupE
- Split startups and shutdowns, add timeouts to shutdowns
- Improve plugin clients and servers
- Improve plugin concurrency, remove FP from tf_backend
- Migrate all state to Vault
- Finish rewriting the injector into a gRPC plugin
- Set up convertation between protobuf json and regular json
- Continue rewriting the secret injector to a plugin
- Continue rewriting the injector to a plugin
- Continue rewriting the vault injector to a plugin
- Add //tools/vault/injector, start migrating resource_handler to it
- Add pipes with error and panic handling, add some more FP stuff
- Fix plugins broken after the refactor, remove main from bazelrc, move FP updates
- Refactor FP to use recursive generics, add some iterator handling
- Add more FP stuff, add plugin configs to al.lua, migrate pve_login and tf_backend to new configs
- Move //tools/al to //projects/al, add Result and Pipe to fp
- Automate root token generation, split the main vault policy into separate ones
- Set up cert authentication
- Add //tools/ykman
- Add //tools/al, remove //tools/secrets, set up proper approle workflow
- Setup Vault token helper using gnome-keyring
- Disable mTLS of the Vault instance, add unsealing information, setup //tools/vault
- Fix some Js and Python CVEs
- Add some information about SSL
- Add new pgp key, rename //data/gpg to //data/pgp, add some info about ssh and pgp
- Add data to //projects/alwaldend.com, add //data/gpg
- Use write_source_files for git_hooks
- Add lvol role, setup LVM volumes on bm3
- Remove //tools/docs, remove .github
- Finalize rules_template refactoring
- Update dns
- Add rules_distroless, add some qubes os info
- Remove al_go_cross_binary, update the setup guide a bit
- Update the setup guide, update android tools, update leetcode, update books
- Update the repo setup doc a bit
- Add //tools/word_lists, update DNS and glossary
- Update leetcode
- Add build_test tests
- Fix urllib vulnerabilities
- Add editing, encryption, decryption
- Start adding secret rules, add badges to books
- Move all the logig out of the screen to the controller
- Add deploy to dockerhub, add //tools/oras
- Remove last modification footer
- Add missing features to the Pomodoro app, update project readmes, add github pages
- Update infinitime patch, start adding trufflehog rules
- Add hugo lock support, add proper hugo toolchain support, improve the ansible lock
- Move all remaining code to main
- Move a portion of tool code to main
- Move the registry to //projects/bazel_registry
- Add minisign rules
- Remove sites taxonomy, start adding xray_manager
- Fix release page rendering
- Move to a light nvim theme, add full git info to releases
- Add release_page generation, remove redundant release templates
- Fix nvim library paths
- Parallelize git info retrieval
- Move links to the config, use list groups
- Remove contracts tree
- Add changelogs
- Allow docs to put content outside of docs, refactor git to just use .git directly
- Add the footer back, add hugo env information
- Move release items to a list group, add item counter
- Add cross-compilation, move leetcode downloader contracts out of //contracts
- Refactor release templates into partials, add release cards
- Add RSS links, rewrite links shortcode to html, improve release tables
- Add file size to releases, add round_float partial
- Write release tool in go, start adding it to projects, add py proto generation
- Add release rules, add gzip rules, add several other tools, remove autoscrool deps from the root
- Add dev_shell rules, add make_install_binary, flatten sh rules, add dotfiles/bin
- Add //tools/make_install, start moving dotfiles to it
- Add label_link shortcode, add todo page
- Move book data to data/books
- Add tools/rfc
- Add bzl snippets to proto docs, add targets for ansible playbooks
- Remove the footer from the docs
- Add dnscontrol rules
- Move book data to the books page, add lazy loading, save some thumbnails locally
- Make tables more compact
- Disable inline partials, add last modified section
- Tweak tables again
- Improve tables on home and books pages
- Improve tables
- Do not use nested tables in docs/misc/books
- Fix book rendering, add arm CI for some reason
- Add git image, split root MODULE.bazel
- Add more taxonomies, remove docs tree, move alwaldend.com to projects
- Initial commit
- Update vulnerable Go dependencies
-
Add spellcheck skill
This commit was generated by an LLM.
-
Consolidate agent policy into owning skills
Reduce the root AGENTS.md from 255 lines to 141 by keeping repository-wide constraints visible and moving execution detail to the skill that owns it.
Make initial reads task-dependent, replace the absolute one-copy rule with one authoritative source, simplify the retry rule to its principle, and fix the generated-file delivery ambiguity. Add a single “When to load a skill” routing table ordered by task phase.
Add the repo-workspace skill so worktree isolation and task-scratch placement are established before the first write rather than when repo-delivery loads. Transfer commit-subject and trailer conventions into a repo-delivery reference and the Go and Bazel-native automation rules into repo-bazel. Reconcile the git-rebase-remote and repo-delivery drift so a task-owned rewrite may change ancestry while preserving every previously remote commit’s reachable progress.
OpenSpec-Change: infra/src/openspec/changes/consolidate-agent-policy-into-skills
LLM-disclaimer: This commit was generated by an LLM.
-
Restore light and dark site canvases and set the shared accent
The shared Docsy canvas set the same Bootstrap dark palette and the same black page background on
:root,[data-bs-theme="light"], and[data-bs-theme="dark"], so the light/dark toggle changed nothing. The site also rendered Bootstrap’s stock blue instead of its intended accent.Split the shared palette so light mode uses a pure white canvas with the light-mode palette and dark mode uses a pure black canvas with the dark-mode palette, and keep the pre-stylesheet paint and footer on the active mode. Assign
$primaryto#7c3aedbefore Bootstrap compiles, so links, buttons, badges, focus rings, and the dark-mode link tint all derive from one value rather than from a site-local copy.Both files stay in the reusable shell; the apex site consumes them through the existing declared exports and no longer carries the footer’s own blue.
OpenSpec-Change: projects/hugo_landing/openspec/changes/restore-light-dark-canvas-and-accent
LLM-disclaimer: This commit was generated by an LLM.
1.3.3 - Rules
1.3.3.1 - Bzl
1.3.3.1.1 - al_config
al_config
load("@com_alwaldend_src//projects/al/rules/al:al_config.bzl", "al_config")
al_config(name, deps, srcs, data)
Dump al config
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| deps | Al configs (targets) | List of labels | optional | [] |
| srcs | Al configs (source files) | List of labels | optional | [] |
| data | Data | List of labels | optional | [] |
AlConfigInfo
load("@com_alwaldend_src//projects/al/rules/al:al_config.bzl", "AlConfigInfo")
AlConfigInfo(config)
Config info
FIELDS
| Name | Description |
|---|---|
| config | Merged config file |
1.3.3.1.2 - al_toolchain
al_toolchain
load("@com_alwaldend_src//projects/al/rules/al:al_toolchain.bzl", "al_toolchain")
al_toolchain(name, al)
Al toolchain
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| al | Al binary | Label | required |
1.3.3.1.3 - al_toolchain_resolved
al_toolchain_resolved
load("@com_alwaldend_src//projects/al/rules/al:al_toolchain_resolved.bzl", "al_toolchain_resolved")
al_toolchain_resolved(name)
Resolved al toolchain (for genrules)
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required |
1.4 - Alwaldend.com
Alwaldend.com is the repository’s main website and documentation site. It uses Hugo with Docsy to publish project documentation on GitHub Pages.
Links
- Source code: https://github.com/alwaldend/src/tree/master/projects/alwaldend.com
- Github Pages repo: https://github.com/alwaldend/alwaldend.github.io
- Hugo rules: ../../tools/rules_hugo
Features
Local preview and validation
Run from the repository root:
bazel_agent bazel build //projects/alwaldend.com:site
bazel_agent bazel test //projects/alwaldend.com:site_test
bazel_agent bazel run //projects/alwaldend.com:site_serve
The preview serves the local build at http://127.0.0.1:1313.
Blog
The site publishes dated articles from content/blog. Each post is its own
Bazel package with an index.md and a BUILD.bazel declaring its
docs_filegroup; the section package aggregates them. The section publishes
HTML, an RSS feed, and a print edition, and appears in the main navigation.
The section index and its posts carry a github_subdir cascade so the
per-page GitHub links point at the content sources.
A post stays unpublished while its front matter declares draft: true. Local
builds render drafts for review and the release build excludes them, so the
draft state alone withholds a post from the deployed site.
Agent workflow: Add a blog post.
Projects
The site publishes each registered project’s visitor-facing landing page at
/projects/<name>/, with the section index at /projects/. Each project owns
its landing content in projects/<name>/site/content/; this site packages
those directories into content/projects/<name>/ from the registry in
projects/projects.bzl. Landing content carries no layouts,
styles, or build rules, and participates in the shared statuses,
languages, and tags taxonomies.
Repository reference documentation, including each project README, stays under
/docs/projects/<name>/. Because every landing is part of this one build, a
content error in any landing fails the whole site build and the blog
deployment.
Documentation links
Markdown links and images resolve relative to their source directory.
README.md and _index.md links resolve to generated pages; packaged resources
use their published URLs, including when embedded in print pages. Link files
that exist only in the repository with explicit GitHub URLs. Unknown internal
destinations remain unchanged rather than being silently redirected to GitHub.
Print pages scope IDs and their fragment and control references to each source document, keeping anchors distinct when documents are combined.
Deployment
- DNS setup: infra/dns
- This project’s DNS declaration
owns the shared
pagesaddress. Project landing pages are published by this site under/projects/<name>/, so no project owns a CNAME or a dedicated hostname. The project directory links to every landing page. The apex andwwwrecords stay managed centrally. - Deploy to the Github Pages repo (the
pagesbranch ofalwaldend/alwaldend.github.io, which GitHub Pages serves):The deploy script clones thetools/versioning/cmd/versioning/versioning.sh bazel -- \ run --config=release //projects/alwaldend.com:deploypagesbranch, replaces its contents with the built site, writes.nojekyll, and pushes only when the output changed.
Update PVE VMs
bazel run //projects/alwaldend.com/tf # Apply tf
bazel run //projects/alwaldend.com/tf:update_pve_disk # Update the disk
Taxonomy
| Taxonomy | Meaning |
|---|---|
| Categories | General category |
| Languages | Programming language |
| Sites | Sites |
| Statuses | Project status |
| Tags | Generic tags |
Shortcodes
alwaldend/alert
{{< alwaldend/alert >}}
Alert body
{{< /alwaldend/alert >}}
alwaldend/label_link
Create a link using a bazel label
Usage:
{{% alwaldend/label_link "//tools/qt" %}}
alwaldend/links
Render common links
Usage:
{{% alwaldend/links %}}
alwaldend/svg_file
Render a packaged SVG using its published URL. Set alt to describe the image;
the page title is the fallback.
Usage:
{{< alwaldend/svg_file file="local_file.svg" alt="Project architecture" >}}
alwaldend/include_html
Include a local html file
Usage:
{{< alwaldend/include_html "file.html" >}}
alwaldend/docs_misc_books
Render books
Usage:
{{< alwaldend/docs_misc_books >}}
1.4.1 - Releases
head
-
Lay the project index out as a single-column section list
The card grid read as a separate component next to the rest of the site. The
/projects/index now uses the same section list as the documentation index: one entry per project under theProjectsheading, separated by panel lines, each entry carrying its description, status, and tags. The entries stay in alphabetical order.Wrap the list in a section so the theme’s first-section offset applies; without it the
Projectsheading rendered underneath the fixed navbar.LLM-disclaimer: This commit was generated by an LLM.
-
Add a staging publication and refine the project index
Verify the project landing replacement on its own hostname before the apex changes and before any per-project resource is retired, and make the landing index useful to a visitor.
www-staging.alwaldend.comgets a checked-in DNS declaration and a catalog repository, and the apex site gains a staging build that renders the same packaged source with the staging base URL plus a deployment command that publishes it. The publication command now takes its repository and branch as arguments, so staging and production share one publisher, and a repository whose publication branch does not exist yet is created as an orphan instead of failing on clone. A new repository receives a default branch at creation so the managed ruleset can protect it while site content publishes to a separate branch, and GitHub Pages configuration is deferred for a repository until its publication branch exists.The
/projects/index no longer opens with explanatory prose, lists landings alphabetically, and shows each project’s status and tags as links to their taxonomy term pages.Deploy the staging site, verify the landing, documentation, and taxonomy routes there, then deploy the accepted output to the apex and verify the same routes. The per-project hostnames, DNS records, and landing repositories remain in place until their retirement is requested.
OpenSpec-Change: projects/alwaldend.com/openspec/changes/site-staging-environment
LLM-disclaimer: This commit was generated by an LLM.
-
Move project landings into the main site
Publish every registered project’s visitor-facing landing page at /projects/
/ from the main site instead of a dedicated subdomain, and retire the per-project Pages repository, CNAME, and Terraform DNS stage that existed only to serve one page derived from the project README. Each project owns its landing content in projects/
/site/content/ as pure content: no layouts, styles, or build rules. The main site packages those directories into content/projects/ / from the registry in projects/projects.bzl, so membership is declared once. The landing is a short hand-written page for visitors while the README keeps its /docs/projects/ / URL for repository reference documentation, and landing front matter now feeds the statuses, languages, and tags taxonomies. Merge the reusable hugo_landing project into the main site: its shared canvas and accent styles and its landing page rules move into the apex tree, and its landing macro, generated configuration, standalone publisher, and repository-relative rewrite layouts are removed. The theme keeps owning the taxonomy and term layouts, which are richer than the heading-only versions the reusable project carried. Remove the now-unused apex deploy_project.sh and deploy_all.sh landing publishers with it.
Retire the per-project publication and DNS ownership: the project landing targets and the landing deployment command, each landing project’s dnsconfig.json and Terraform root, the build plumbing that served only those stages, and the landing repository and Pages membership in the repository catalog. The apex Terraform root is retained because it also declares VM resources, and no Vault configuration is changed.
Replace the provider-snapshot zone files with generated declaration pages, one per destination view, that project the checked-in declarations and are verified for freshness by the DNS offline check. The DNS linter, both destination pages, the apex site, the skills projection, and the repository quality suite pass, and the whole repository builds.
OpenSpec-Change: projects/alwaldend.com/openspec/changes/consolidate-project-landings-into-apex
LLM-disclaimer: This commit was generated by an LLM.
-
Merge pull request #94 from alwaldend/t3code/fix-hugo-theme-light-dark-accent
Restore light and dark site canvases and set the shared accent
-
Manage forge resources with hermetic Terraform rules
Centralize organization, repository, and named access configuration in infra/repos. Adopt existing GitHub resources, protect master defaults while retaining Pages publication on pages, and preserve existing repository identities. Manage GitLab one-time imports, the F-Droid metadata fork, and default-branch protections through Vault-backed authentication. Forgejo consumes the same catalog. Ongoing repository synchronization is deferred.
Retire the eleven Bazel rule landing sites through their owning Terraform workflows, removing their DNS records, Pages repositories, and landing configuration. Move all twelve existing standalone rule modules into tools/ and retain their public interfaces and documentation on the main site.
Add tools/rules_terraform with verified provider downloads, packed mirrors in runfiles, and reusable Terraform execution rules. Enforce one version per provider source at an extensible resolution boundary. Migrate every Terraform consumer to thirteen shared provider pins in third_party/terraform. Execution and command maps belong to rules_terraform; consumers explicitly select generic AL wrappers for authentication and Vault injection. Remove tools/terraform and all 43 checked-in Terraform provider locks. Validate installed providers against the declared archives before execution.
Validation covers all fourteen workspace builds, all thirteen standalone test suites, Terraform consumers, offline real-provider regressions, rendered documentation, formatting, and semantic lint. The full root test run has 295 passing tests and one skip; its only failure is the historical secret scan, reduced to four pre-existing synthetic fixture matches. Earlier live imports and the exact landing retirement scope have verified postconditions; the Terraform rules migration uses only offline implementation checks.
OpenSpec-Change: infra/repos/openspec/changes/archive/2026-09-13-adopt-shared-repository-catalog OpenSpec-Change: infra/src/openspec/changes/archive/2026-09-13-retire-bazel-rule-landings OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-add-hermetic-terraform-rules OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-correct-terraform-ownership
LLM-disclaimer: This commit was generated by an LLM.
-
Publish the DNS evolution article and update blog workflow
Publish the author’s account of moving DNS management from a central DNSControl configuration to project-owned Terraform records, with examples and directory layouts. Include the author’s clarifications and approved wording corrections, and remove the draft flag for publication.
Tag both blog posts using existing site topics. Require relevant tags and iterative reviews in the blog skill: report findings before validation and delivery, repeat after changes, and finish delivery when the review is clear or the author ends it. Cover both behaviors in the existing evaluation cases.
Validation: local and release Hugo builds, site_test, skill validation and offline Promptfoo configuration test, skill discovery, Buildifier, repository quality, and semantic lint for the affected blog and skill packages.
LLM-disclaimer: This commit was generated by an LLM.
-
Deploy project DNS through Terraform modules
Move DNS ownership into each project’s Terraform state using shared modules. Load dnsconfig.json files at runtime, reject conflicting domain ownership, and render their records as a table. Add missing project AppRoles and scoped DNS policies, and document grouping related Terraform resources in modules.
Deploy all 45 owners sequentially: adopt 155 existing records and create 13 missing OpenHands records. Preserve every pre-existing provider record and verify no-op follow-up plans and DNS answers. Add DNS-scoped plan/show/apply wrappers with a saved-plan guard for roots that also manage services. Allow bounded aggregate path inventories large enough to deliver this migration while retaining truncation refusal in the delivery tool.
Validate runtime ownership, provider imports and preservation with isolated fixtures, Terraform formatting, wrapper builds, repository quality checks, semantic lint, and project documentation/specification builds.
OpenSpec-Change: infra/dns/openspec/changes/archive/2026-09-13-migrate-project-dns-to-terraform
LLM-disclaimer: This commit was generated by an LLM.
-
Record the site hostname decision for alwaldend.com
Record the evaluated options for the apex site’s landing, documentation, and blog sections: one hostname with one build (retained), separate hostnames served from separate GitHub Pages repositories, and one hostname with independently built and merged section outputs. The generated documentation tree is a projection of the repository’s own directory structure across 471 packaged README files, and an earlier commit already combined the misc, docs, and projects sites, so splitting the hostnames would move where the projection is served without decoupling it from its source.
Separate the shared-build failure coupling from the hostname question: the recorded fallback keeps one published tree while splitting the build graph, if panicking on any packaged README warning starts blocking delivery.
Record the search-engine evidence from primary sources. Google’s crawling-and-indexing FAQ states that from an indexing and ranking perspective Google has no preference, and the office-hours answer recorded here addresses the same question. The record explicitly does not claim that subdirectories preserve link equity that a subdomain would forfeit, and it cites a third vendor video by title only because its spoken content could not be retrieved.
This change adds no site behavior, build target, configuration, DNS record, or Terraform resource.
OpenSpec-Change: projects/alwaldend.com/openspec/changes/archive/2026-09-12-record-site-hostname-decision
LLM-disclaimer: This commit was generated by an LLM.
-
Fix Android review feedback
Add a shared
androidPluginsversion catalog so both Android apps declare the AGP, Kotlin, Compose, and protobuf plugin versions once, and derive their versions from it instead of duplicating literals per root Gradle file.Align the launcher and ingester app versions with the repository versioning contract: development builds use
0.0.0-devwithversionCode1 in both the Gradle default config and the Bazelmanifest_values.Ignore the whole materialized
.agents/skillsdirectory in Prettier because every entry is either a source-tree symlink or a byte-pinned external archive copy.Apply the ingester’s themed surface background to the main content surface so the status bar area follows the system theme, not a default white surface.
Token: z-ai-glm-flash-latest
LLM-disclaimer: This commit was generated by an LLM.
-
Add a blog section, a shared site canvas, and standalone nested modules
Publish the Docsy blog section on the apex site with its content package, navigation entry, RSS feed, and draft-safe release flags. The release build excludes drafts so a post stays unpublished from its front matter alone.
Move the reusable project-site procedure to a generic repo-hugo skill that also documents the Hugo theme layout, and add an alwaldend-blog skill that publishes supplied content verbatim and reviews it afterward. Enforce one implementation and one copy of each fact in the root policy, and refine the skill locality rule to prefer local ownership only when it genuinely fits.
Share one black theme between the landing shell and the apex site from a single SCSS source, and let docs_filegroup preserve source paths so packages holding identically named files stop colliding.
Repair every nested Bazel workspace: rules_openspec declared six unused, versionless sibling dependencies whose local_path_override entries never applied outside the root module, which broke standalone resolution for all nested modules. Drop those dependencies, ignore the two nested module directories that lacked an ignore entry, add the missing build_test coverage, and extend the full-repository check to all twelve nested workspaces.
OpenSpec-Change: projects/alwaldend.com/openspec/changes/archive/2026-09-12-add-docsy-blog-section OpenSpec-Change: projects/hugo_landing/openspec/changes/archive/2026-09-12-shared-site-canvas OpenSpec-Change: projects/rules_docs/openspec/changes/archive/2026-09-12-nested-spec-path-collision OpenSpec-Change: infra/src/openspec/changes/archive/2026-09-12-fix-nested-workspace-module-resolution
LLM-disclaimer: This commit was generated by an LLM.
-
Remove the goal component, the agent control tower, and the site link test
Delete projects/goal entirely: its CLI, API package, filesystem store, landing site, disabled skill sources, documentation pages, diagrams, Bazel targets, project-registry entry, and committed DNS record. The goal tool was deprecated by the 2026-09-08 migration to the pinned OpenSpec CLI, which is in active use, and the repository policy already told agents not to create goal records.
Delete tools/agents entirely. It carried repository-internal control contracts, seven catalog compilers, an offline context capsule, and typed admission/control/plan/evidence libraries. The goal tool was their only consumer; no CI or AGENTS.md invocation read the catalogs. Relocate the generic skill-discovery declaration to .agents/BUILD.bazel beside the directory it generates, and repoint the 29 skill visibility labels from //tools/agents:skill_discovery to //.agents:skill_discovery. Skill content, link targets, and the 27 existing symlinks are unchanged. A BUILD.bazel inside .agents/skills/ was rejected because the generated updater rejects a non-symlink there.
Reduce projects/agents to its skills: delete the architecture, current-state, and roadmap documents and the docs package they fed. Documentation describing agent-system composition now belongs with the component that owns the behavior.
Remove //projects/alwaldend.com/test/site:site_test. It has never passed since 894494f4: it fails on unmodified HEAD with 330 missing-file findings because it treats repository source paths and the published URL space as one namespace. Repository-only targets such as BUILD.bazel and playbook YAML are deliberately not packaged, so those links can never resolve in generated output.
Record the removals as three OpenSpec changes: remove-deprecated-goal-component and remove-generated-site-link-test under infra/src and projects/alwaldend.com, and remove-goal-tool-and-contract-tower under projects/agents.
The removed bytes remain retrievable from git history at the parent of this commit; the changes neither copy nor restate them.
Address review feedback before publication:
Point the hugo_landing site example at the surviving //projects/agents:docs target. The copied example referenced //projects/agents/docs:docs, which this change deletes, so the snippet failed label resolution.
Point the new specification links at their real paths. The repository change referenced migration.md one directory too shallow, and the Reimu continuation requirement referenced the process contract from beneath the change directory instead of the project root; neither path existed.
Rewrite projects/renders/assets/reimu_fumo/PROCESS.md so its required stage gates no longer depend on the removed goal tool. That contract was the authoritative process for the still-open Reimu work, and it required goal-tool checkpoints, portable goal plans, and goal state to start, repair, reset, and close attempts. Those mechanics now record into the project’s OpenSpec change and its durable evidence, so every gate stays executable. Acceptance criteria and the blocked continuation state are unchanged. The continuation requirement is recorded in the change spec and its rationale in the change design.
OpenSpec-Change: infra/src/openspec/changes/remove-deprecated-goal-component OpenSpec-Change: projects/agents/openspec/changes/remove-goal-tool-and-contract-tower OpenSpec-Change: projects/alwaldend.com/openspec/changes/remove-generated-site-link-test OpenSpec-Change: projects/renders/openspec/changes/reimu-fumo-finish
LLM-disclaimer: This commit was generated by an LLM.
-
Simplify OpenSpec workspace globs
Collapse OpenSpec source globs to specs and changes, drop redundant package visibility blocks already covered by REPO.bazel, and regenerate the affected catalogs.
LLM-disclaimer: This commit was generated by an LLM.
-
Publish project sites and reproducible infrastructure diagrams
Build and deploy all 30 remaining project sites with the standard Docsy header, project descriptions and a linked documentation directory. Omit the repeated page title and generated language heading. Remove the unused cgit and xray_manager projects and retire their site resources.
Add a repeatable GitHub Pages publisher, staged Terraform bootstrap and direct GitHub Pages DNS records. Preserve repeated publication when pages is the remote default branch, and include Rules ISO in the main documentation. Document site onboarding in a registered, validated skill. Keep AL introduction short with useful links and preserve its lifecycle details in a dedicated documentation page.
Render all 15 existing infrastructure Drawio pages with pinned Drawio and Chrome inputs, sandboxed export actions, an update target and freshness checks, and include the maintained diagrams in infra/arch documentation. Paint an opaque white canvas to preserve readability in dark themes.
Validation covers project and apex builds, rendered pages, publisher tests, diagram repeatability and freshness, DNS configuration, Terraform formatting, semantic lint and repository quality.
Goal-Ref: build-and-deploy-every-project-landing-page-a782b800 Attempt-ID: attempt-00941092c164
LLM-disclaimer: This commit was generated by an LLM.
-
Keep Bazel dependencies lazy and generate the root module
Declare pinned InfiniTime sources and the Hedron extractor through use_repo_rule, retain recursive firmware submodules, and use the official contrib_rules_jvm 0.32.0 release. Keep default toolchain registration convenient for consumers.
Move root tool implementations into owning packages while preserving compatibility labels, visibility, manual tags, Python paths, Terraform working directories, pnpm dependency pins, and documentation archive layout. Guard the load-free root BUILD with a parser-based quality test. Generate root MODULE.bazel directly from owning include files, with an update command and freshness/integration tests.
Cache hermetic agent tests, preserve lint analysis across modes, and build only lint outputs in lint mode. Allow normal agent lockfile updates while retaining strict CI checks. Limit host Bazel scheduling to eight jobs and half its CPUs, with matching checked-in host configuration.
Fix DNSControl command ordering, JSON manifest loading, record filename suffixes, and credential-file wiring through existing Vault environment injection. Add an offline config test. Correct the Git wrapper shebang for direct execution and refresh derived catalogs affected by the Bazel changes.
Validation covers compatibility builds, firmware, documentation outputs, generator freshness, DNS configuration, and a live DNS preview without applying changes. The repository-wide audit also identifies pre-existing test and coverage gaps.
Goal-Ref: avoid-unrelated-bazel-dependency-downloads-638e8329 Attempt-ID: attempt-106ffd5ccaeb
LLM-disclaimer: This commit was generated by an LLM.
-
Repair site navigation and simplify page layout
Show one homepage panel with vertically stacked GitHub and Docs rows using the name: URL format, hiding the protocol and trailing slash in the link text. Center the panel and cap its width at 40rem while allowing it to shrink on mobile. Move it slightly lower on desktop and brighten the footer link. Restore the project assets mount so custom styles load. Reduce the footer to its content height with compact padding. Size the homepage against the visible viewport so mobile browser controls do not hide its footer. Remove the separate Projects page and its header link, while keeping project documentation under Docs. Remove the introductory homepage copy and visible title.
Resolve Markdown links and images from their source locations, package missing documentation and book covers, correct source links, and scope anchors and release controls in combined print pages. Restore the archive-root CNAME explicitly during deployment so replacing the site preserves the custom domain.
Validate generated HTML for missing internal files and fragments, duplicate IDs, image alternatives, and the homepage, Misc source-link, and Goal diagram regressions. Check the production build, repository quality, affected-target semantic lint, desktop and mobile homepage rendering, and deployment output.
Goal-Ref: out/site-fix/goals/fix-local-alwaldend-com-layout-and-links-a2e69a4e Attempt-ID: attempt-165dd5be7d71
LLM-disclaimer: This commit was generated by an LLM.
-
Extract DNSControl setup into rules_dnscontrol
Extract the DNSControl setup into
rules_dnscontrol, generate its Bazel dependency bundle from project-owned record files, and update the DNS guidance. Move Hugo rules and the worker to role-based package paths, and give each non-nested project a locally owned Hugo landing target that reuses the shared README-to-landing macro.Clean all landing and Pages DNS records so GitHub Pages serves each project subdomain directly without Cloudflare proxying. Improve the main site with a three-panel home layout, complete project links, documentation explore links, and current deployment guidance.
All affected root-workspace landing, DNS, and site targets pass, along with the nested
rules_hugotests, Buildifier, and repository quality checks.LLM-disclaimer: This commit was generated by an LLM.
-
Improve the Hugo site and fix the persistent worker
Extract the Hugo build rules into a standalone nested module projects/rules_hugo and add a Go-based persistent Hugo worker with a Dart Sass toolchain, then fix the worker’s empty-destination defect, polish the rules, add per-project landing pages and DNS declarations, and improve the site deploy.
- rules_hugo: standalone nested module with MODULE.bazel, main/bzl rules, tests, and README; no root-workspace labels.
- hugo_worker: persistent worker that resolves execroot-relative paths through the work directory and probes DART_SASS_BINARY, so the site destination is populated with HTML and Sass-compiled CSS.
- sass: Dart Sass 1.103.1 toolchain wired into the site build.
- alwaldend.com: Hugo 0.165.0, Docsy 0.17.0, Bootstrap 5.3.8, Font Awesome 7.3.1, module mounts, and the site build switched to the worker.
- Landing pages: content/projects/_index.md links every project to its docs page; a Projects menu entry is added and the content filegroup is wired.
- DNS: projects/alwaldend.com/dnsconfig.json declares no records (no new subdomains) and is wired into infra/dns/dnsconfig.js.
- Deploy: the genrule clones the pages branch that GitHub Pages serves, clears the previous checkout, writes .nojekyll, stages deletions, skips no-op deploys, and pushes HEAD:pages without a force push; the README deploy section is updated.
- Content: rename the reserved sites taxonomy to websites so the alwaldend.com term renders, and fix main/bzl docs prefix collisions across nested modules.
- Review fixes: document the extension-based toolchain registration in the rules_hugo README, sync the full-repo-check eval rubric to nine nested workspaces and twenty commands, and drop the worker’s unsupported outs attribute.
- Validation: site build produces 3051 HTML pages and Sass CSS; worker, terraform, buildifier, and nested rules_hugo tests pass; git diff –check is clean.
LLM-disclaimer: This commit was generated by an LLM.
-
docs: define the repository agent system
Make the repository legible as one coherent agent-operated system while preserving one mutation authority per fact.
- add revision-bound current state, target architecture, and phased roadmap
- route root and agent entry points to the canonical model and durable goal
- normalize repository-tree policy and the public-information boundary
- clarify task-private secret scratch and non-obvious tool narration
- correct question and secret skill contracts and stale operator examples
- render source-compatible Markdown links correctly in the documentation site
- retain the complete audit, decision, validation, and acceptance record
Validated with focused skill and Buildifier tests, affected Bazel builds, the full Hugo site, source and rendered link checks, exact label queries, repository-pinned formatting, and goal-record validation.
LLM-disclaimer: This commit was generated by an LLM.
- Complete repository quality coverage
-
Add hermetic repository-wide formatting and linting
Integrate upstream formatters for the repository’s meaningful tracked source and configuration file types through Bazel, and add Buildifier, Ruff, and ShellCheck lint aspects for correctness-oriented repository-wide checks.
Pin all new external tools through Bzlmod or the existing pnpm lock, add thin cache/runfiles adapters where required, expose format and check targets, and wire the checks into the pre-commit workflow. Format the existing tree and fix the correctness defects uncovered by the new checks. Preserve generated sources and exact-content fixtures that are not safely rewritable, and clarify that ordinary infrastructure build output is safe to display.
Validation:
- all 21 repository quality and compatibility formatter tests pass
- Buildifier test passes
- lint aspects analyze all 4,629 ordinary root targets without findings
- the complete 18-command root and nested full-repository audit was exercised; remaining failures are documented environment or pre-existing test limits
LLM-disclaimer: This commit was generated by an LLM.
-
Add global repository versioning
Introduce a Bazel-built Go tool that calculates the repository’s global SemVer-compatible ISO-week calendar versions, creates guarded nightly tags and weekly release branches atomically, advances release patches by first-parent commit, and emits deterministic Bazel workspace-status keys.
Route release stamping through the tool and add a packaged, discoverable versioning skill with offline Promptfoo validation. Cover ISO week boundaries, SemVer formatting, branch and dirty-tree guards, release patch calculation, tag integrity, and stamping output with focused tests.
Provide a clean-checkout bootstrap that builds the Go tool before it launches the stamped Bazel command. Bind ref transactions to the inspected commit, neutralize Git replace/graft/routing inputs, make dry runs validate namespace collisions, validate every published patch tag against its exact first-parent position, reject ambiguous or inconsistent tag states, and require explicit context for detached release calculations. Route detached release-tag selection through those same history-integrity checks. Keep development status cache-safe by emitting Git identity as volatile data while making immutable nightly and release identities stable.
Add a repository-delivery integration regression proving that a failed aggregate whitespace check identifies the offending path exactly once.
Verified with:
- bazel_agent test //tools/versioning/… //tools/repo_delivery/main/go:go_test //:write_skill_links_test //:buildifier_test
- bazel_agent build //tools/versioning/… //tools/repo_delivery/…
- tools/versioning/cmd/versioning/versioning.sh bazel – build –config=release //tools/versioning/cmd/versioning
- real Git integration tests covering ref transactions, SHA-256 repositories, environment isolation, detached contexts, tag ordering, and namespace collisions
LLM-disclaimer: This commit was generated by an LLM.
-
Add standalone documentation rules
Move docs_filegroup into a reusable rules_docs nested Bzlmod workspace and migrate every root and nested consumer to it. Add a module-aware Gazelle language that creates docs targets only for existing README packages while preserving manual mappings.
Wire the workspace into module resolution, documentation aggregation, and the ten-command full-repo-check. Add the bazel-nested-module skill so future nested workspaces follow the repository’s rc, lockfile, docs, toolchain, Gazelle, and validation conventions.
Keep reviewed Gazelle dependency canonicalization, while protecting the hand-maintained Go proto, Python resource, Android, embedded-site, and skill runner definitions that generic language plugins would otherwise break.
This commit was generated by an LLM.
-
Keep embedded site server in target configuration
This commit was generated by an LLM.
-
Fix Bazel build caching and tool configuration
This commit was generated by an LLM.
-
Remove redundant documentation mappings
Inline sources from eight layout-neutral pkg_files wrappers and migrate the remaining legacy Vial docs producer to docs_filegroup. Keep only mappings that perform required renames.\n\nThis commit was generated by an LLM.
-
Complete docs filegroup migration
Pass ordinary documentation sources directly and isolate generated or renamed outputs in semantic pkg_files dependencies. Remove the obsolete renames and strip_prefix surface from docs_filegroup.\n\nThis commit was generated by an LLM.
-
Migrate documentation packaging to docs_filegroup
Preserve custom prefixes, renames, strip prefixes, and standalone workspace behavior.\n\nThis commit was generated by an LLM.
-
Make Qt and Maven dependencies hermetic
Align protobuf with the Android build tools and refresh generated locks.\n\nThis commit was generated by an LLM.
-
Make Android SDK setup reproducible
This commit was generated by an LLM.
-
Add agent-friendly Bazel config
This commit was generated by an LLM.
- Use an image from the marketplace, update some locks, add CODEOWNERS
- Finish opencode deploy
- Add //third_party/org_fedora_cloud, fix alwaldend.com roles
- Set up unikernel deploy
- Refactor flux manifests a bit, add //tools/ops
- Add a server to //projects/alwaldend.com
- Add OIDC for k3s, add OIDC fetcher to injector
- Add drawio-desktop, add //infra/arch, update opencode restrictions
- Add //third_party/org_kernel_headers, rename all deps files to include
- Add //third_party/org_nmap_nmap
- Fix ssh key signing
- Automate root token generation, split the main vault policy into separate ones
- Set up cert authentication
- Add //tools/ykman
- Add //tools/al, remove //tools/secrets, set up proper approle workflow
- Setup Vault token helper using gnome-keyring
- Disable mTLS of the Vault instance, add unsealing information, setup //tools/vault
- Fix some Js and Python CVEs
- Add some information about SSL
- Add new pgp key, rename //data/gpg to //data/pgp, add some info about ssh and pgp
- Add data to //projects/alwaldend.com, add //data/gpg
- Use write_source_files for git_hooks
- Add lvol role, setup LVM volumes on bm3
- Remove //tools/docs, remove .github
- Finalize rules_template refactoring
- Update dns
- Add rules_distroless, add some qubes os info
- Remove al_go_cross_binary, update the setup guide a bit
- Update the setup guide, update android tools, update leetcode, update books
- Update the repo setup doc a bit
- Add //tools/word_lists, update DNS and glossary
- Update leetcode
- Add build_test tests
- Fix urllib vulnerabilities
- Add editing, encryption, decryption
- Start adding secret rules, add badges to books
- Move all the logig out of the screen to the controller
- Add deploy to dockerhub, add //tools/oras
- Remove last modification footer
- Add missing features to the Pomodoro app, update project readmes, add github pages
- Update infinitime patch, start adding trufflehog rules
- Add hugo lock support, add proper hugo toolchain support, improve the ansible lock
- Move all remaining code to main
- Move a portion of tool code to main
- Move the registry to //projects/bazel_registry
- Add minisign rules
- Remove sites taxonomy, start adding xray_manager
- Fix release page rendering
- Move to a light nvim theme, add full git info to releases
- Add release_page generation, remove redundant release templates
- Fix nvim library paths
- Parallelize git info retrieval
- Move links to the config, use list groups
- Remove contracts tree
- Add changelogs
- Allow docs to put content outside of docs, refactor git to just use .git directly
- Add the footer back, add hugo env information
- Move release items to a list group, add item counter
- Add cross-compilation, move leetcode downloader contracts out of //contracts
- Refactor release templates into partials, add release cards
- Add RSS links, rewrite links shortcode to html, improve release tables
- Add file size to releases, add round_float partial
- Write release tool in go, start adding it to projects, add py proto generation
- Add release rules, add gzip rules, add several other tools, remove autoscrool deps from the root
- Add dev_shell rules, add make_install_binary, flatten sh rules, add dotfiles/bin
- Add //tools/make_install, start moving dotfiles to it
- Add label_link shortcode, add todo page
- Move book data to data/books
- Add tools/rfc
- Add bzl snippets to proto docs, add targets for ansible playbooks
- Remove the footer from the docs
- Add dnscontrol rules
- Move book data to the books page, add lazy loading, save some thumbnails locally
- Make tables more compact
- Disable inline partials, add last modified section
- Tweak tables again
- Improve tables on home and books pages
- Improve tables
- Do not use nested tables in docs/misc/books
- Fix book rendering, add arm CI for some reason
- Add git image, split root MODULE.bazel
- Add more taxonomies, remove docs tree, move alwaldend.com to projects
- Initial commit
- Update vulnerable Go dependencies
-
Add spellcheck skill
This commit was generated by an LLM.
-
Consolidate agent policy into owning skills
Reduce the root AGENTS.md from 255 lines to 141 by keeping repository-wide constraints visible and moving execution detail to the skill that owns it.
Make initial reads task-dependent, replace the absolute one-copy rule with one authoritative source, simplify the retry rule to its principle, and fix the generated-file delivery ambiguity. Add a single “When to load a skill” routing table ordered by task phase.
Add the repo-workspace skill so worktree isolation and task-scratch placement are established before the first write rather than when repo-delivery loads. Transfer commit-subject and trailer conventions into a repo-delivery reference and the Go and Bazel-native automation rules into repo-bazel. Reconcile the git-rebase-remote and repo-delivery drift so a task-owned rewrite may change ancestry while preserving every previously remote commit’s reachable progress.
OpenSpec-Change: infra/src/openspec/changes/consolidate-agent-policy-into-skills
LLM-disclaimer: This commit was generated by an LLM.
-
Restore light and dark site canvases and set the shared accent
The shared Docsy canvas set the same Bootstrap dark palette and the same black page background on
:root,[data-bs-theme="light"], and[data-bs-theme="dark"], so the light/dark toggle changed nothing. The site also rendered Bootstrap’s stock blue instead of its intended accent.Split the shared palette so light mode uses a pure white canvas with the light-mode palette and dark mode uses a pure black canvas with the dark-mode palette, and keep the pre-stylesheet paint and footer on the active mode. Assign
$primaryto#7c3aedbefore Bootstrap compiles, so links, buttons, badges, focus rings, and the dark-mode link tint all derive from one value rather than from a site-local copy.Both files stay in the reusable shell; the apex site consumes them through the existing declared exports and no longer carries the footer’s own blue.
OpenSpec-Change: projects/hugo_landing/openspec/changes/restore-light-dark-canvas-and-accent
LLM-disclaimer: This commit was generated by an LLM.
1.4.1.1 - head
-
Lay the project index out as a single-column section list
The card grid read as a separate component next to the rest of the site. The
/projects/index now uses the same section list as the documentation index: one entry per project under theProjectsheading, separated by panel lines, each entry carrying its description, status, and tags. The entries stay in alphabetical order.Wrap the list in a section so the theme’s first-section offset applies; without it the
Projectsheading rendered underneath the fixed navbar.LLM-disclaimer: This commit was generated by an LLM.
-
Add a staging publication and refine the project index
Verify the project landing replacement on its own hostname before the apex changes and before any per-project resource is retired, and make the landing index useful to a visitor.
www-staging.alwaldend.comgets a checked-in DNS declaration and a catalog repository, and the apex site gains a staging build that renders the same packaged source with the staging base URL plus a deployment command that publishes it. The publication command now takes its repository and branch as arguments, so staging and production share one publisher, and a repository whose publication branch does not exist yet is created as an orphan instead of failing on clone. A new repository receives a default branch at creation so the managed ruleset can protect it while site content publishes to a separate branch, and GitHub Pages configuration is deferred for a repository until its publication branch exists.The
/projects/index no longer opens with explanatory prose, lists landings alphabetically, and shows each project’s status and tags as links to their taxonomy term pages.Deploy the staging site, verify the landing, documentation, and taxonomy routes there, then deploy the accepted output to the apex and verify the same routes. The per-project hostnames, DNS records, and landing repositories remain in place until their retirement is requested.
OpenSpec-Change: projects/alwaldend.com/openspec/changes/site-staging-environment
LLM-disclaimer: This commit was generated by an LLM.
-
Move project landings into the main site
Publish every registered project’s visitor-facing landing page at /projects/
/ from the main site instead of a dedicated subdomain, and retire the per-project Pages repository, CNAME, and Terraform DNS stage that existed only to serve one page derived from the project README. Each project owns its landing content in projects/
/site/content/ as pure content: no layouts, styles, or build rules. The main site packages those directories into content/projects/ / from the registry in projects/projects.bzl, so membership is declared once. The landing is a short hand-written page for visitors while the README keeps its /docs/projects/ / URL for repository reference documentation, and landing front matter now feeds the statuses, languages, and tags taxonomies. Merge the reusable hugo_landing project into the main site: its shared canvas and accent styles and its landing page rules move into the apex tree, and its landing macro, generated configuration, standalone publisher, and repository-relative rewrite layouts are removed. The theme keeps owning the taxonomy and term layouts, which are richer than the heading-only versions the reusable project carried. Remove the now-unused apex deploy_project.sh and deploy_all.sh landing publishers with it.
Retire the per-project publication and DNS ownership: the project landing targets and the landing deployment command, each landing project’s dnsconfig.json and Terraform root, the build plumbing that served only those stages, and the landing repository and Pages membership in the repository catalog. The apex Terraform root is retained because it also declares VM resources, and no Vault configuration is changed.
Replace the provider-snapshot zone files with generated declaration pages, one per destination view, that project the checked-in declarations and are verified for freshness by the DNS offline check. The DNS linter, both destination pages, the apex site, the skills projection, and the repository quality suite pass, and the whole repository builds.
OpenSpec-Change: projects/alwaldend.com/openspec/changes/consolidate-project-landings-into-apex
LLM-disclaimer: This commit was generated by an LLM.
-
Merge pull request #94 from alwaldend/t3code/fix-hugo-theme-light-dark-accent
Restore light and dark site canvases and set the shared accent
-
Manage forge resources with hermetic Terraform rules
Centralize organization, repository, and named access configuration in infra/repos. Adopt existing GitHub resources, protect master defaults while retaining Pages publication on pages, and preserve existing repository identities. Manage GitLab one-time imports, the F-Droid metadata fork, and default-branch protections through Vault-backed authentication. Forgejo consumes the same catalog. Ongoing repository synchronization is deferred.
Retire the eleven Bazel rule landing sites through their owning Terraform workflows, removing their DNS records, Pages repositories, and landing configuration. Move all twelve existing standalone rule modules into tools/ and retain their public interfaces and documentation on the main site.
Add tools/rules_terraform with verified provider downloads, packed mirrors in runfiles, and reusable Terraform execution rules. Enforce one version per provider source at an extensible resolution boundary. Migrate every Terraform consumer to thirteen shared provider pins in third_party/terraform. Execution and command maps belong to rules_terraform; consumers explicitly select generic AL wrappers for authentication and Vault injection. Remove tools/terraform and all 43 checked-in Terraform provider locks. Validate installed providers against the declared archives before execution.
Validation covers all fourteen workspace builds, all thirteen standalone test suites, Terraform consumers, offline real-provider regressions, rendered documentation, formatting, and semantic lint. The full root test run has 295 passing tests and one skip; its only failure is the historical secret scan, reduced to four pre-existing synthetic fixture matches. Earlier live imports and the exact landing retirement scope have verified postconditions; the Terraform rules migration uses only offline implementation checks.
OpenSpec-Change: infra/repos/openspec/changes/archive/2026-09-13-adopt-shared-repository-catalog OpenSpec-Change: infra/src/openspec/changes/archive/2026-09-13-retire-bazel-rule-landings OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-add-hermetic-terraform-rules OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-correct-terraform-ownership
LLM-disclaimer: This commit was generated by an LLM.
-
Publish the DNS evolution article and update blog workflow
Publish the author’s account of moving DNS management from a central DNSControl configuration to project-owned Terraform records, with examples and directory layouts. Include the author’s clarifications and approved wording corrections, and remove the draft flag for publication.
Tag both blog posts using existing site topics. Require relevant tags and iterative reviews in the blog skill: report findings before validation and delivery, repeat after changes, and finish delivery when the review is clear or the author ends it. Cover both behaviors in the existing evaluation cases.
Validation: local and release Hugo builds, site_test, skill validation and offline Promptfoo configuration test, skill discovery, Buildifier, repository quality, and semantic lint for the affected blog and skill packages.
LLM-disclaimer: This commit was generated by an LLM.
-
Deploy project DNS through Terraform modules
Move DNS ownership into each project’s Terraform state using shared modules. Load dnsconfig.json files at runtime, reject conflicting domain ownership, and render their records as a table. Add missing project AppRoles and scoped DNS policies, and document grouping related Terraform resources in modules.
Deploy all 45 owners sequentially: adopt 155 existing records and create 13 missing OpenHands records. Preserve every pre-existing provider record and verify no-op follow-up plans and DNS answers. Add DNS-scoped plan/show/apply wrappers with a saved-plan guard for roots that also manage services. Allow bounded aggregate path inventories large enough to deliver this migration while retaining truncation refusal in the delivery tool.
Validate runtime ownership, provider imports and preservation with isolated fixtures, Terraform formatting, wrapper builds, repository quality checks, semantic lint, and project documentation/specification builds.
OpenSpec-Change: infra/dns/openspec/changes/archive/2026-09-13-migrate-project-dns-to-terraform
LLM-disclaimer: This commit was generated by an LLM.
-
Record the site hostname decision for alwaldend.com
Record the evaluated options for the apex site’s landing, documentation, and blog sections: one hostname with one build (retained), separate hostnames served from separate GitHub Pages repositories, and one hostname with independently built and merged section outputs. The generated documentation tree is a projection of the repository’s own directory structure across 471 packaged README files, and an earlier commit already combined the misc, docs, and projects sites, so splitting the hostnames would move where the projection is served without decoupling it from its source.
Separate the shared-build failure coupling from the hostname question: the recorded fallback keeps one published tree while splitting the build graph, if panicking on any packaged README warning starts blocking delivery.
Record the search-engine evidence from primary sources. Google’s crawling-and-indexing FAQ states that from an indexing and ranking perspective Google has no preference, and the office-hours answer recorded here addresses the same question. The record explicitly does not claim that subdirectories preserve link equity that a subdomain would forfeit, and it cites a third vendor video by title only because its spoken content could not be retrieved.
This change adds no site behavior, build target, configuration, DNS record, or Terraform resource.
OpenSpec-Change: projects/alwaldend.com/openspec/changes/archive/2026-09-12-record-site-hostname-decision
LLM-disclaimer: This commit was generated by an LLM.
-
Fix Android review feedback
Add a shared
androidPluginsversion catalog so both Android apps declare the AGP, Kotlin, Compose, and protobuf plugin versions once, and derive their versions from it instead of duplicating literals per root Gradle file.Align the launcher and ingester app versions with the repository versioning contract: development builds use
0.0.0-devwithversionCode1 in both the Gradle default config and the Bazelmanifest_values.Ignore the whole materialized
.agents/skillsdirectory in Prettier because every entry is either a source-tree symlink or a byte-pinned external archive copy.Apply the ingester’s themed surface background to the main content surface so the status bar area follows the system theme, not a default white surface.
Token: z-ai-glm-flash-latest
LLM-disclaimer: This commit was generated by an LLM.
-
Add a blog section, a shared site canvas, and standalone nested modules
Publish the Docsy blog section on the apex site with its content package, navigation entry, RSS feed, and draft-safe release flags. The release build excludes drafts so a post stays unpublished from its front matter alone.
Move the reusable project-site procedure to a generic repo-hugo skill that also documents the Hugo theme layout, and add an alwaldend-blog skill that publishes supplied content verbatim and reviews it afterward. Enforce one implementation and one copy of each fact in the root policy, and refine the skill locality rule to prefer local ownership only when it genuinely fits.
Share one black theme between the landing shell and the apex site from a single SCSS source, and let docs_filegroup preserve source paths so packages holding identically named files stop colliding.
Repair every nested Bazel workspace: rules_openspec declared six unused, versionless sibling dependencies whose local_path_override entries never applied outside the root module, which broke standalone resolution for all nested modules. Drop those dependencies, ignore the two nested module directories that lacked an ignore entry, add the missing build_test coverage, and extend the full-repository check to all twelve nested workspaces.
OpenSpec-Change: projects/alwaldend.com/openspec/changes/archive/2026-09-12-add-docsy-blog-section OpenSpec-Change: projects/hugo_landing/openspec/changes/archive/2026-09-12-shared-site-canvas OpenSpec-Change: projects/rules_docs/openspec/changes/archive/2026-09-12-nested-spec-path-collision OpenSpec-Change: infra/src/openspec/changes/archive/2026-09-12-fix-nested-workspace-module-resolution
LLM-disclaimer: This commit was generated by an LLM.
-
Remove the goal component, the agent control tower, and the site link test
Delete projects/goal entirely: its CLI, API package, filesystem store, landing site, disabled skill sources, documentation pages, diagrams, Bazel targets, project-registry entry, and committed DNS record. The goal tool was deprecated by the 2026-09-08 migration to the pinned OpenSpec CLI, which is in active use, and the repository policy already told agents not to create goal records.
Delete tools/agents entirely. It carried repository-internal control contracts, seven catalog compilers, an offline context capsule, and typed admission/control/plan/evidence libraries. The goal tool was their only consumer; no CI or AGENTS.md invocation read the catalogs. Relocate the generic skill-discovery declaration to .agents/BUILD.bazel beside the directory it generates, and repoint the 29 skill visibility labels from //tools/agents:skill_discovery to //.agents:skill_discovery. Skill content, link targets, and the 27 existing symlinks are unchanged. A BUILD.bazel inside .agents/skills/ was rejected because the generated updater rejects a non-symlink there.
Reduce projects/agents to its skills: delete the architecture, current-state, and roadmap documents and the docs package they fed. Documentation describing agent-system composition now belongs with the component that owns the behavior.
Remove //projects/alwaldend.com/test/site:site_test. It has never passed since 894494f4: it fails on unmodified HEAD with 330 missing-file findings because it treats repository source paths and the published URL space as one namespace. Repository-only targets such as BUILD.bazel and playbook YAML are deliberately not packaged, so those links can never resolve in generated output.
Record the removals as three OpenSpec changes: remove-deprecated-goal-component and remove-generated-site-link-test under infra/src and projects/alwaldend.com, and remove-goal-tool-and-contract-tower under projects/agents.
The removed bytes remain retrievable from git history at the parent of this commit; the changes neither copy nor restate them.
Address review feedback before publication:
Point the hugo_landing site example at the surviving //projects/agents:docs target. The copied example referenced //projects/agents/docs:docs, which this change deletes, so the snippet failed label resolution.
Point the new specification links at their real paths. The repository change referenced migration.md one directory too shallow, and the Reimu continuation requirement referenced the process contract from beneath the change directory instead of the project root; neither path existed.
Rewrite projects/renders/assets/reimu_fumo/PROCESS.md so its required stage gates no longer depend on the removed goal tool. That contract was the authoritative process for the still-open Reimu work, and it required goal-tool checkpoints, portable goal plans, and goal state to start, repair, reset, and close attempts. Those mechanics now record into the project’s OpenSpec change and its durable evidence, so every gate stays executable. Acceptance criteria and the blocked continuation state are unchanged. The continuation requirement is recorded in the change spec and its rationale in the change design.
OpenSpec-Change: infra/src/openspec/changes/remove-deprecated-goal-component OpenSpec-Change: projects/agents/openspec/changes/remove-goal-tool-and-contract-tower OpenSpec-Change: projects/alwaldend.com/openspec/changes/remove-generated-site-link-test OpenSpec-Change: projects/renders/openspec/changes/reimu-fumo-finish
LLM-disclaimer: This commit was generated by an LLM.
-
Simplify OpenSpec workspace globs
Collapse OpenSpec source globs to specs and changes, drop redundant package visibility blocks already covered by REPO.bazel, and regenerate the affected catalogs.
LLM-disclaimer: This commit was generated by an LLM.
-
Publish project sites and reproducible infrastructure diagrams
Build and deploy all 30 remaining project sites with the standard Docsy header, project descriptions and a linked documentation directory. Omit the repeated page title and generated language heading. Remove the unused cgit and xray_manager projects and retire their site resources.
Add a repeatable GitHub Pages publisher, staged Terraform bootstrap and direct GitHub Pages DNS records. Preserve repeated publication when pages is the remote default branch, and include Rules ISO in the main documentation. Document site onboarding in a registered, validated skill. Keep AL introduction short with useful links and preserve its lifecycle details in a dedicated documentation page.
Render all 15 existing infrastructure Drawio pages with pinned Drawio and Chrome inputs, sandboxed export actions, an update target and freshness checks, and include the maintained diagrams in infra/arch documentation. Paint an opaque white canvas to preserve readability in dark themes.
Validation covers project and apex builds, rendered pages, publisher tests, diagram repeatability and freshness, DNS configuration, Terraform formatting, semantic lint and repository quality.
Goal-Ref: build-and-deploy-every-project-landing-page-a782b800 Attempt-ID: attempt-00941092c164
LLM-disclaimer: This commit was generated by an LLM.
-
Keep Bazel dependencies lazy and generate the root module
Declare pinned InfiniTime sources and the Hedron extractor through use_repo_rule, retain recursive firmware submodules, and use the official contrib_rules_jvm 0.32.0 release. Keep default toolchain registration convenient for consumers.
Move root tool implementations into owning packages while preserving compatibility labels, visibility, manual tags, Python paths, Terraform working directories, pnpm dependency pins, and documentation archive layout. Guard the load-free root BUILD with a parser-based quality test. Generate root MODULE.bazel directly from owning include files, with an update command and freshness/integration tests.
Cache hermetic agent tests, preserve lint analysis across modes, and build only lint outputs in lint mode. Allow normal agent lockfile updates while retaining strict CI checks. Limit host Bazel scheduling to eight jobs and half its CPUs, with matching checked-in host configuration.
Fix DNSControl command ordering, JSON manifest loading, record filename suffixes, and credential-file wiring through existing Vault environment injection. Add an offline config test. Correct the Git wrapper shebang for direct execution and refresh derived catalogs affected by the Bazel changes.
Validation covers compatibility builds, firmware, documentation outputs, generator freshness, DNS configuration, and a live DNS preview without applying changes. The repository-wide audit also identifies pre-existing test and coverage gaps.
Goal-Ref: avoid-unrelated-bazel-dependency-downloads-638e8329 Attempt-ID: attempt-106ffd5ccaeb
LLM-disclaimer: This commit was generated by an LLM.
-
Repair site navigation and simplify page layout
Show one homepage panel with vertically stacked GitHub and Docs rows using the name: URL format, hiding the protocol and trailing slash in the link text. Center the panel and cap its width at 40rem while allowing it to shrink on mobile. Move it slightly lower on desktop and brighten the footer link. Restore the project assets mount so custom styles load. Reduce the footer to its content height with compact padding. Size the homepage against the visible viewport so mobile browser controls do not hide its footer. Remove the separate Projects page and its header link, while keeping project documentation under Docs. Remove the introductory homepage copy and visible title.
Resolve Markdown links and images from their source locations, package missing documentation and book covers, correct source links, and scope anchors and release controls in combined print pages. Restore the archive-root CNAME explicitly during deployment so replacing the site preserves the custom domain.
Validate generated HTML for missing internal files and fragments, duplicate IDs, image alternatives, and the homepage, Misc source-link, and Goal diagram regressions. Check the production build, repository quality, affected-target semantic lint, desktop and mobile homepage rendering, and deployment output.
Goal-Ref: out/site-fix/goals/fix-local-alwaldend-com-layout-and-links-a2e69a4e Attempt-ID: attempt-165dd5be7d71
LLM-disclaimer: This commit was generated by an LLM.
-
Extract DNSControl setup into rules_dnscontrol
Extract the DNSControl setup into
rules_dnscontrol, generate its Bazel dependency bundle from project-owned record files, and update the DNS guidance. Move Hugo rules and the worker to role-based package paths, and give each non-nested project a locally owned Hugo landing target that reuses the shared README-to-landing macro.Clean all landing and Pages DNS records so GitHub Pages serves each project subdomain directly without Cloudflare proxying. Improve the main site with a three-panel home layout, complete project links, documentation explore links, and current deployment guidance.
All affected root-workspace landing, DNS, and site targets pass, along with the nested
rules_hugotests, Buildifier, and repository quality checks.LLM-disclaimer: This commit was generated by an LLM.
-
Improve the Hugo site and fix the persistent worker
Extract the Hugo build rules into a standalone nested module projects/rules_hugo and add a Go-based persistent Hugo worker with a Dart Sass toolchain, then fix the worker’s empty-destination defect, polish the rules, add per-project landing pages and DNS declarations, and improve the site deploy.
- rules_hugo: standalone nested module with MODULE.bazel, main/bzl rules, tests, and README; no root-workspace labels.
- hugo_worker: persistent worker that resolves execroot-relative paths through the work directory and probes DART_SASS_BINARY, so the site destination is populated with HTML and Sass-compiled CSS.
- sass: Dart Sass 1.103.1 toolchain wired into the site build.
- alwaldend.com: Hugo 0.165.0, Docsy 0.17.0, Bootstrap 5.3.8, Font Awesome 7.3.1, module mounts, and the site build switched to the worker.
- Landing pages: content/projects/_index.md links every project to its docs page; a Projects menu entry is added and the content filegroup is wired.
- DNS: projects/alwaldend.com/dnsconfig.json declares no records (no new subdomains) and is wired into infra/dns/dnsconfig.js.
- Deploy: the genrule clones the pages branch that GitHub Pages serves, clears the previous checkout, writes .nojekyll, stages deletions, skips no-op deploys, and pushes HEAD:pages without a force push; the README deploy section is updated.
- Content: rename the reserved sites taxonomy to websites so the alwaldend.com term renders, and fix main/bzl docs prefix collisions across nested modules.
- Review fixes: document the extension-based toolchain registration in the rules_hugo README, sync the full-repo-check eval rubric to nine nested workspaces and twenty commands, and drop the worker’s unsupported outs attribute.
- Validation: site build produces 3051 HTML pages and Sass CSS; worker, terraform, buildifier, and nested rules_hugo tests pass; git diff –check is clean.
LLM-disclaimer: This commit was generated by an LLM.
-
docs: define the repository agent system
Make the repository legible as one coherent agent-operated system while preserving one mutation authority per fact.
- add revision-bound current state, target architecture, and phased roadmap
- route root and agent entry points to the canonical model and durable goal
- normalize repository-tree policy and the public-information boundary
- clarify task-private secret scratch and non-obvious tool narration
- correct question and secret skill contracts and stale operator examples
- render source-compatible Markdown links correctly in the documentation site
- retain the complete audit, decision, validation, and acceptance record
Validated with focused skill and Buildifier tests, affected Bazel builds, the full Hugo site, source and rendered link checks, exact label queries, repository-pinned formatting, and goal-record validation.
LLM-disclaimer: This commit was generated by an LLM.
- Complete repository quality coverage
-
Add hermetic repository-wide formatting and linting
Integrate upstream formatters for the repository’s meaningful tracked source and configuration file types through Bazel, and add Buildifier, Ruff, and ShellCheck lint aspects for correctness-oriented repository-wide checks.
Pin all new external tools through Bzlmod or the existing pnpm lock, add thin cache/runfiles adapters where required, expose format and check targets, and wire the checks into the pre-commit workflow. Format the existing tree and fix the correctness defects uncovered by the new checks. Preserve generated sources and exact-content fixtures that are not safely rewritable, and clarify that ordinary infrastructure build output is safe to display.
Validation:
- all 21 repository quality and compatibility formatter tests pass
- Buildifier test passes
- lint aspects analyze all 4,629 ordinary root targets without findings
- the complete 18-command root and nested full-repository audit was exercised; remaining failures are documented environment or pre-existing test limits
LLM-disclaimer: This commit was generated by an LLM.
-
Add global repository versioning
Introduce a Bazel-built Go tool that calculates the repository’s global SemVer-compatible ISO-week calendar versions, creates guarded nightly tags and weekly release branches atomically, advances release patches by first-parent commit, and emits deterministic Bazel workspace-status keys.
Route release stamping through the tool and add a packaged, discoverable versioning skill with offline Promptfoo validation. Cover ISO week boundaries, SemVer formatting, branch and dirty-tree guards, release patch calculation, tag integrity, and stamping output with focused tests.
Provide a clean-checkout bootstrap that builds the Go tool before it launches the stamped Bazel command. Bind ref transactions to the inspected commit, neutralize Git replace/graft/routing inputs, make dry runs validate namespace collisions, validate every published patch tag against its exact first-parent position, reject ambiguous or inconsistent tag states, and require explicit context for detached release calculations. Route detached release-tag selection through those same history-integrity checks. Keep development status cache-safe by emitting Git identity as volatile data while making immutable nightly and release identities stable.
Add a repository-delivery integration regression proving that a failed aggregate whitespace check identifies the offending path exactly once.
Verified with:
- bazel_agent test //tools/versioning/… //tools/repo_delivery/main/go:go_test //:write_skill_links_test //:buildifier_test
- bazel_agent build //tools/versioning/… //tools/repo_delivery/…
- tools/versioning/cmd/versioning/versioning.sh bazel – build –config=release //tools/versioning/cmd/versioning
- real Git integration tests covering ref transactions, SHA-256 repositories, environment isolation, detached contexts, tag ordering, and namespace collisions
LLM-disclaimer: This commit was generated by an LLM.
-
Add standalone documentation rules
Move docs_filegroup into a reusable rules_docs nested Bzlmod workspace and migrate every root and nested consumer to it. Add a module-aware Gazelle language that creates docs targets only for existing README packages while preserving manual mappings.
Wire the workspace into module resolution, documentation aggregation, and the ten-command full-repo-check. Add the bazel-nested-module skill so future nested workspaces follow the repository’s rc, lockfile, docs, toolchain, Gazelle, and validation conventions.
Keep reviewed Gazelle dependency canonicalization, while protecting the hand-maintained Go proto, Python resource, Android, embedded-site, and skill runner definitions that generic language plugins would otherwise break.
This commit was generated by an LLM.
-
Keep embedded site server in target configuration
This commit was generated by an LLM.
-
Fix Bazel build caching and tool configuration
This commit was generated by an LLM.
-
Remove redundant documentation mappings
Inline sources from eight layout-neutral pkg_files wrappers and migrate the remaining legacy Vial docs producer to docs_filegroup. Keep only mappings that perform required renames.\n\nThis commit was generated by an LLM.
-
Complete docs filegroup migration
Pass ordinary documentation sources directly and isolate generated or renamed outputs in semantic pkg_files dependencies. Remove the obsolete renames and strip_prefix surface from docs_filegroup.\n\nThis commit was generated by an LLM.
-
Migrate documentation packaging to docs_filegroup
Preserve custom prefixes, renames, strip prefixes, and standalone workspace behavior.\n\nThis commit was generated by an LLM.
-
Make Qt and Maven dependencies hermetic
Align protobuf with the Android build tools and refresh generated locks.\n\nThis commit was generated by an LLM.
-
Make Android SDK setup reproducible
This commit was generated by an LLM.
-
Add agent-friendly Bazel config
This commit was generated by an LLM.
- Use an image from the marketplace, update some locks, add CODEOWNERS
- Finish opencode deploy
- Add //third_party/org_fedora_cloud, fix alwaldend.com roles
- Set up unikernel deploy
- Refactor flux manifests a bit, add //tools/ops
- Add a server to //projects/alwaldend.com
- Add OIDC for k3s, add OIDC fetcher to injector
- Add drawio-desktop, add //infra/arch, update opencode restrictions
- Add //third_party/org_kernel_headers, rename all deps files to include
- Add //third_party/org_nmap_nmap
- Fix ssh key signing
- Automate root token generation, split the main vault policy into separate ones
- Set up cert authentication
- Add //tools/ykman
- Add //tools/al, remove //tools/secrets, set up proper approle workflow
- Setup Vault token helper using gnome-keyring
- Disable mTLS of the Vault instance, add unsealing information, setup //tools/vault
- Fix some Js and Python CVEs
- Add some information about SSL
- Add new pgp key, rename //data/gpg to //data/pgp, add some info about ssh and pgp
- Add data to //projects/alwaldend.com, add //data/gpg
- Use write_source_files for git_hooks
- Add lvol role, setup LVM volumes on bm3
- Remove //tools/docs, remove .github
- Finalize rules_template refactoring
- Update dns
- Add rules_distroless, add some qubes os info
- Remove al_go_cross_binary, update the setup guide a bit
- Update the setup guide, update android tools, update leetcode, update books
- Update the repo setup doc a bit
- Add //tools/word_lists, update DNS and glossary
- Update leetcode
- Add build_test tests
- Fix urllib vulnerabilities
- Add editing, encryption, decryption
- Start adding secret rules, add badges to books
- Move all the logig out of the screen to the controller
- Add deploy to dockerhub, add //tools/oras
- Remove last modification footer
- Add missing features to the Pomodoro app, update project readmes, add github pages
- Update infinitime patch, start adding trufflehog rules
- Add hugo lock support, add proper hugo toolchain support, improve the ansible lock
- Move all remaining code to main
- Move a portion of tool code to main
- Move the registry to //projects/bazel_registry
- Add minisign rules
- Remove sites taxonomy, start adding xray_manager
- Fix release page rendering
- Move to a light nvim theme, add full git info to releases
- Add release_page generation, remove redundant release templates
- Fix nvim library paths
- Parallelize git info retrieval
- Move links to the config, use list groups
- Remove contracts tree
- Add changelogs
- Allow docs to put content outside of docs, refactor git to just use .git directly
- Add the footer back, add hugo env information
- Move release items to a list group, add item counter
- Add cross-compilation, move leetcode downloader contracts out of //contracts
- Refactor release templates into partials, add release cards
- Add RSS links, rewrite links shortcode to html, improve release tables
- Add file size to releases, add round_float partial
- Write release tool in go, start adding it to projects, add py proto generation
- Add release rules, add gzip rules, add several other tools, remove autoscrool deps from the root
- Add dev_shell rules, add make_install_binary, flatten sh rules, add dotfiles/bin
- Add //tools/make_install, start moving dotfiles to it
- Add label_link shortcode, add todo page
- Move book data to data/books
- Add tools/rfc
- Add bzl snippets to proto docs, add targets for ansible playbooks
- Remove the footer from the docs
- Add dnscontrol rules
- Move book data to the books page, add lazy loading, save some thumbnails locally
- Make tables more compact
- Disable inline partials, add last modified section
- Tweak tables again
- Improve tables on home and books pages
- Improve tables
- Do not use nested tables in docs/misc/books
- Fix book rendering, add arm CI for some reason
- Add git image, split root MODULE.bazel
- Add more taxonomies, remove docs tree, move alwaldend.com to projects
- Initial commit
- Update vulnerable Go dependencies
-
Add spellcheck skill
This commit was generated by an LLM.
-
Consolidate agent policy into owning skills
Reduce the root AGENTS.md from 255 lines to 141 by keeping repository-wide constraints visible and moving execution detail to the skill that owns it.
Make initial reads task-dependent, replace the absolute one-copy rule with one authoritative source, simplify the retry rule to its principle, and fix the generated-file delivery ambiguity. Add a single “When to load a skill” routing table ordered by task phase.
Add the repo-workspace skill so worktree isolation and task-scratch placement are established before the first write rather than when repo-delivery loads. Transfer commit-subject and trailer conventions into a repo-delivery reference and the Go and Bazel-native automation rules into repo-bazel. Reconcile the git-rebase-remote and repo-delivery drift so a task-owned rewrite may change ancestry while preserving every previously remote commit’s reachable progress.
OpenSpec-Change: infra/src/openspec/changes/consolidate-agent-policy-into-skills
LLM-disclaimer: This commit was generated by an LLM.
-
Restore light and dark site canvases and set the shared accent
The shared Docsy canvas set the same Bootstrap dark palette and the same black page background on
:root,[data-bs-theme="light"], and[data-bs-theme="dark"], so the light/dark toggle changed nothing. The site also rendered Bootstrap’s stock blue instead of its intended accent.Split the shared palette so light mode uses a pure white canvas with the light-mode palette and dark mode uses a pure black canvas with the dark-mode palette, and keep the pre-stylesheet paint and footer on the active mode. Assign
$primaryto#7c3aedbefore Bootstrap compiles, so links, buttons, badges, focus rings, and the dark-mode link tint all derive from one value rather than from a site-local copy.Both files stay in the reusable shell; the apex site consumes them through the existing declared exports and no longer carries the footer’s own blue.
OpenSpec-Change: projects/hugo_landing/openspec/changes/restore-light-dark-canvas-and-accent
LLM-disclaimer: This commit was generated by an LLM.
1.4.2 - Tf
This service stage consumes the project DNS declaration
through the shared global DNS module.
The DNS workflow uses the project’s AppRole, HTTP state backend, and Cloudflare
credentials. This public-only module does not require RouterOS. Ordinary
service commands retain their tf=main authentication, including PVE login.
Operational commands require the project AppRole and Vault provider fields in
the migration prerequisites.
dns_enabled defaults to true after verified adoption. Keep it enabled to
retain existing records; disabling it would propose deletion. The zone input
remains optional.
The dns.plan, dns.show, and dns.apply targets select only the DNS
workflow in this same root and backend. They use dns=1 to load DNS credentials
without starting PVE login. Apply requires a reviewed saved plan file. Targeted
DNS planning does not establish PVE or other service health.
Follow the DNS migration workflow for continued reconciliation and recovery. The adoption record contains the earlier blocked attempt and completed scoped DNS verification.
Offline formatting is available through
//projects/alwaldend.com/tf:tf_tests.fmt_test.
1.5 - Android launcher
A text-only Android launcher built with Kotlin and Jetpack Compose. It lets you hide apps and runs without ads, tracking, or internet access.
Links
Features
- Android app
- Kotlin, Jetpack Compose
- Only text
- FOSS, no ads, no internet access, no tracking, minimal dependencies
- Allows you to hide apps
1.5.1 - Releases
head
-
Move project landings into the main site
Publish every registered project’s visitor-facing landing page at /projects/
/ from the main site instead of a dedicated subdomain, and retire the per-project Pages repository, CNAME, and Terraform DNS stage that existed only to serve one page derived from the project README. Each project owns its landing content in projects/
/site/content/ as pure content: no layouts, styles, or build rules. The main site packages those directories into content/projects/ / from the registry in projects/projects.bzl, so membership is declared once. The landing is a short hand-written page for visitors while the README keeps its /docs/projects/ / URL for repository reference documentation, and landing front matter now feeds the statuses, languages, and tags taxonomies. Merge the reusable hugo_landing project into the main site: its shared canvas and accent styles and its landing page rules move into the apex tree, and its landing macro, generated configuration, standalone publisher, and repository-relative rewrite layouts are removed. The theme keeps owning the taxonomy and term layouts, which are richer than the heading-only versions the reusable project carried. Remove the now-unused apex deploy_project.sh and deploy_all.sh landing publishers with it.
Retire the per-project publication and DNS ownership: the project landing targets and the landing deployment command, each landing project’s dnsconfig.json and Terraform root, the build plumbing that served only those stages, and the landing repository and Pages membership in the repository catalog. The apex Terraform root is retained because it also declares VM resources, and no Vault configuration is changed.
Replace the provider-snapshot zone files with generated declaration pages, one per destination view, that project the checked-in declarations and are verified for freshness by the DNS offline check. The DNS linter, both destination pages, the apex site, the skills projection, and the repository quality suite pass, and the whole repository builds.
OpenSpec-Change: projects/alwaldend.com/openspec/changes/consolidate-project-landings-into-apex
LLM-disclaimer: This commit was generated by an LLM.
-
Manage forge resources with hermetic Terraform rules
Centralize organization, repository, and named access configuration in infra/repos. Adopt existing GitHub resources, protect master defaults while retaining Pages publication on pages, and preserve existing repository identities. Manage GitLab one-time imports, the F-Droid metadata fork, and default-branch protections through Vault-backed authentication. Forgejo consumes the same catalog. Ongoing repository synchronization is deferred.
Retire the eleven Bazel rule landing sites through their owning Terraform workflows, removing their DNS records, Pages repositories, and landing configuration. Move all twelve existing standalone rule modules into tools/ and retain their public interfaces and documentation on the main site.
Add tools/rules_terraform with verified provider downloads, packed mirrors in runfiles, and reusable Terraform execution rules. Enforce one version per provider source at an extensible resolution boundary. Migrate every Terraform consumer to thirteen shared provider pins in third_party/terraform. Execution and command maps belong to rules_terraform; consumers explicitly select generic AL wrappers for authentication and Vault injection. Remove tools/terraform and all 43 checked-in Terraform provider locks. Validate installed providers against the declared archives before execution.
Validation covers all fourteen workspace builds, all thirteen standalone test suites, Terraform consumers, offline real-provider regressions, rendered documentation, formatting, and semantic lint. The full root test run has 295 passing tests and one skip; its only failure is the historical secret scan, reduced to four pre-existing synthetic fixture matches. Earlier live imports and the exact landing retirement scope have verified postconditions; the Terraform rules migration uses only offline implementation checks.
OpenSpec-Change: infra/repos/openspec/changes/archive/2026-09-13-adopt-shared-repository-catalog OpenSpec-Change: infra/src/openspec/changes/archive/2026-09-13-retire-bazel-rule-landings OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-add-hermetic-terraform-rules OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-correct-terraform-ownership
LLM-disclaimer: This commit was generated by an LLM.
-
Deploy project DNS through Terraform modules
Move DNS ownership into each project’s Terraform state using shared modules. Load dnsconfig.json files at runtime, reject conflicting domain ownership, and render their records as a table. Add missing project AppRoles and scoped DNS policies, and document grouping related Terraform resources in modules.
Deploy all 45 owners sequentially: adopt 155 existing records and create 13 missing OpenHands records. Preserve every pre-existing provider record and verify no-op follow-up plans and DNS answers. Add DNS-scoped plan/show/apply wrappers with a saved-plan guard for roots that also manage services. Allow bounded aggregate path inventories large enough to deliver this migration while retaining truncation refusal in the delivery tool.
Validate runtime ownership, provider imports and preservation with isolated fixtures, Terraform formatting, wrapper builds, repository quality checks, semantic lint, and project documentation/specification builds.
OpenSpec-Change: infra/dns/openspec/changes/archive/2026-09-13-migrate-project-dns-to-terraform
LLM-disclaimer: This commit was generated by an LLM.
-
Fix Android review feedback
Add a shared
androidPluginsversion catalog so both Android apps declare the AGP, Kotlin, Compose, and protobuf plugin versions once, and derive their versions from it instead of duplicating literals per root Gradle file.Align the launcher and ingester app versions with the repository versioning contract: development builds use
0.0.0-devwithversionCode1 in both the Gradle default config and the Bazelmanifest_values.Ignore the whole materialized
.agents/skillsdirectory in Prettier because every entry is either a source-tree symlink or a byte-pinned external archive copy.Apply the ingester’s themed surface background to the main content surface so the status bar area follows the system theme, not a default white surface.
Token: z-ai-glm-flash-latest
LLM-disclaimer: This commit was generated by an LLM.
-
Reorganize Gradle, fdroid, and android skill layout
Collapse the maven_install_gradle_converter and tools/gradle Starlark layers into flat defs.bzl files per the project-layout skill. Replace the fdroid shell wrapper with a Go binary. Rewrite the Android smoke test as a Go test. Move the android skill from the launcher project to tools/android and register it in the skill discovery map.
Token: claude-opus-4-6 LLM-Disclaimer: Generated with Claude, reviewed by Simeon Warren
-
Prefer signed APK in Android smoke test
The android_binary rule produces both a signed and unsigned APK; the smoke test script picked whichever find returned first, which could be the unsigned one and fail installation. Explicitly skip unsigned APKs.
Token: claude-opus-4-6 LLM-Disclaimer: Generated with Claude, reviewed by Simeon Warren
-
Use pinned Gradle and add Android smoke test
Replace the curl-based Gradle wrapper with a Bazel-pinned Gradle archive and the existing rules_java remote JDK, exposed through a Starlark wrapper rule. Add a manual Android launcher instrumentation smoke test for runtime APK verification, and document the test and pinned JDK usage. Exclude Gradle-generated verification metadata from Prettier by filename glob and remove the unnecessary third_party ignore entry.
LLM-disclaimer: This commit was generated by an LLM.
-
Simplify OpenSpec workspace globs
Collapse OpenSpec source globs to specs and changes, drop redundant package visibility blocks already covered by REPO.bazel, and regenerate the affected catalogs.
LLM-disclaimer: This commit was generated by an LLM.
-
Publish project sites and reproducible infrastructure diagrams
Build and deploy all 30 remaining project sites with the standard Docsy header, project descriptions and a linked documentation directory. Omit the repeated page title and generated language heading. Remove the unused cgit and xray_manager projects and retire their site resources.
Add a repeatable GitHub Pages publisher, staged Terraform bootstrap and direct GitHub Pages DNS records. Preserve repeated publication when pages is the remote default branch, and include Rules ISO in the main documentation. Document site onboarding in a registered, validated skill. Keep AL introduction short with useful links and preserve its lifecycle details in a dedicated documentation page.
Render all 15 existing infrastructure Drawio pages with pinned Drawio and Chrome inputs, sandboxed export actions, an update target and freshness checks, and include the maintained diagrams in infra/arch documentation. Paint an opaque white canvas to preserve readability in dark themes.
Validation covers project and apex builds, rendered pages, publisher tests, diagram repeatability and freshness, DNS configuration, Terraform formatting, semantic lint and repository quality.
Goal-Ref: build-and-deploy-every-project-landing-page-a782b800 Attempt-ID: attempt-00941092c164
LLM-disclaimer: This commit was generated by an LLM.
-
Extract DNSControl setup into rules_dnscontrol
Extract the DNSControl setup into
rules_dnscontrol, generate its Bazel dependency bundle from project-owned record files, and update the DNS guidance. Move Hugo rules and the worker to role-based package paths, and give each non-nested project a locally owned Hugo landing target that reuses the shared README-to-landing macro.Clean all landing and Pages DNS records so GitHub Pages serves each project subdomain directly without Cloudflare proxying. Improve the main site with a three-panel home layout, complete project links, documentation explore links, and current deployment guidance.
All affected root-workspace landing, DNS, and site targets pass, along with the nested
rules_hugotests, Buildifier, and repository quality checks.LLM-disclaimer: This commit was generated by an LLM.
-
Add hermetic repository-wide formatting and linting
Integrate upstream formatters for the repository’s meaningful tracked source and configuration file types through Bazel, and add Buildifier, Ruff, and ShellCheck lint aspects for correctness-oriented repository-wide checks.
Pin all new external tools through Bzlmod or the existing pnpm lock, add thin cache/runfiles adapters where required, expose format and check targets, and wire the checks into the pre-commit workflow. Format the existing tree and fix the correctness defects uncovered by the new checks. Preserve generated sources and exact-content fixtures that are not safely rewritable, and clarify that ordinary infrastructure build output is safe to display.
Validation:
- all 21 repository quality and compatibility formatter tests pass
- Buildifier test passes
- lint aspects analyze all 4,629 ordinary root targets without findings
- the complete 18-command root and nested full-repository audit was exercised; remaining failures are documented environment or pre-existing test limits
LLM-disclaimer: This commit was generated by an LLM.
-
Add standalone documentation rules
Move docs_filegroup into a reusable rules_docs nested Bzlmod workspace and migrate every root and nested consumer to it. Add a module-aware Gazelle language that creates docs targets only for existing README packages while preserving manual mappings.
Wire the workspace into module resolution, documentation aggregation, and the ten-command full-repo-check. Add the bazel-nested-module skill so future nested workspaces follow the repository’s rc, lockfile, docs, toolchain, Gazelle, and validation conventions.
Keep reviewed Gazelle dependency canonicalization, while protecting the hand-maintained Go proto, Python resource, Android, embedded-site, and skill runner definitions that generic language plugins would otherwise break.
This commit was generated by an LLM.
-
Migrate documentation packaging to docs_filegroup
Preserve custom prefixes, renames, strip prefixes, and standalone workspace behavior.\n\nThis commit was generated by an LLM.
- Add a server to //projects/alwaldend.com
- Add //third_party/org_kernel_headers, rename all deps files to include
- Remove //tools/docs, remove .github
- Update android_launcher package name
- Bump protobuf and java deps, update leetcode
- Rename go modules to git.alwaldend.com/alwaldend/src
- Move all the logig out of the screen to the controller
- Add deploy to dockerhub, add //tools/oras
- Add missing features to the Pomodoro app, update project readmes, add github pages
- Move all remaining code to main
- Add release_page generation, remove redundant release templates
- Add //tools/bazelrc, move to a bazelrc preset
- Remove contracts tree
- Allow docs to put content outside of docs, refactor git to just use .git directly
- Add cross-compilation, move leetcode downloader contracts out of //contracts
- Refactor release templates into partials, add release cards
- Add more taxonomies, remove docs tree, move alwaldend.com to projects
- Rename proto to contracts, add tools/proto add proto docs
- Remove bazel target docs, add tools/docs, tag projects properly
- Improve doc structure
- Remove changelogs, ignore irrelevant directories in docs
- Move another group of rules to tools/
- Move a group of rules to tools/
- Remove kt tree
- Initial commit
-
Add spellcheck skill
This commit was generated by an LLM.
-
Restore light and dark site canvases and set the shared accent
The shared Docsy canvas set the same Bootstrap dark palette and the same black page background on
:root,[data-bs-theme="light"], and[data-bs-theme="dark"], so the light/dark toggle changed nothing. The site also rendered Bootstrap’s stock blue instead of its intended accent.Split the shared palette so light mode uses a pure white canvas with the light-mode palette and dark mode uses a pure black canvas with the dark-mode palette, and keep the pre-stylesheet paint and footer on the active mode. Assign
$primaryto#7c3aedbefore Bootstrap compiles, so links, buttons, badges, focus rings, and the dark-mode link tint all derive from one value rather than from a site-local copy.Both files stay in the reusable shell; the apex site consumes them through the existing declared exports and no longer carries the footer’s own blue.
OpenSpec-Change: projects/hugo_landing/openspec/changes/restore-light-dark-canvas-and-accent
LLM-disclaimer: This commit was generated by an LLM.
1.5.1.1 - head
-
Move project landings into the main site
Publish every registered project’s visitor-facing landing page at /projects/
/ from the main site instead of a dedicated subdomain, and retire the per-project Pages repository, CNAME, and Terraform DNS stage that existed only to serve one page derived from the project README. Each project owns its landing content in projects/
/site/content/ as pure content: no layouts, styles, or build rules. The main site packages those directories into content/projects/ / from the registry in projects/projects.bzl, so membership is declared once. The landing is a short hand-written page for visitors while the README keeps its /docs/projects/ / URL for repository reference documentation, and landing front matter now feeds the statuses, languages, and tags taxonomies. Merge the reusable hugo_landing project into the main site: its shared canvas and accent styles and its landing page rules move into the apex tree, and its landing macro, generated configuration, standalone publisher, and repository-relative rewrite layouts are removed. The theme keeps owning the taxonomy and term layouts, which are richer than the heading-only versions the reusable project carried. Remove the now-unused apex deploy_project.sh and deploy_all.sh landing publishers with it.
Retire the per-project publication and DNS ownership: the project landing targets and the landing deployment command, each landing project’s dnsconfig.json and Terraform root, the build plumbing that served only those stages, and the landing repository and Pages membership in the repository catalog. The apex Terraform root is retained because it also declares VM resources, and no Vault configuration is changed.
Replace the provider-snapshot zone files with generated declaration pages, one per destination view, that project the checked-in declarations and are verified for freshness by the DNS offline check. The DNS linter, both destination pages, the apex site, the skills projection, and the repository quality suite pass, and the whole repository builds.
OpenSpec-Change: projects/alwaldend.com/openspec/changes/consolidate-project-landings-into-apex
LLM-disclaimer: This commit was generated by an LLM.
-
Manage forge resources with hermetic Terraform rules
Centralize organization, repository, and named access configuration in infra/repos. Adopt existing GitHub resources, protect master defaults while retaining Pages publication on pages, and preserve existing repository identities. Manage GitLab one-time imports, the F-Droid metadata fork, and default-branch protections through Vault-backed authentication. Forgejo consumes the same catalog. Ongoing repository synchronization is deferred.
Retire the eleven Bazel rule landing sites through their owning Terraform workflows, removing their DNS records, Pages repositories, and landing configuration. Move all twelve existing standalone rule modules into tools/ and retain their public interfaces and documentation on the main site.
Add tools/rules_terraform with verified provider downloads, packed mirrors in runfiles, and reusable Terraform execution rules. Enforce one version per provider source at an extensible resolution boundary. Migrate every Terraform consumer to thirteen shared provider pins in third_party/terraform. Execution and command maps belong to rules_terraform; consumers explicitly select generic AL wrappers for authentication and Vault injection. Remove tools/terraform and all 43 checked-in Terraform provider locks. Validate installed providers against the declared archives before execution.
Validation covers all fourteen workspace builds, all thirteen standalone test suites, Terraform consumers, offline real-provider regressions, rendered documentation, formatting, and semantic lint. The full root test run has 295 passing tests and one skip; its only failure is the historical secret scan, reduced to four pre-existing synthetic fixture matches. Earlier live imports and the exact landing retirement scope have verified postconditions; the Terraform rules migration uses only offline implementation checks.
OpenSpec-Change: infra/repos/openspec/changes/archive/2026-09-13-adopt-shared-repository-catalog OpenSpec-Change: infra/src/openspec/changes/archive/2026-09-13-retire-bazel-rule-landings OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-add-hermetic-terraform-rules OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-correct-terraform-ownership
LLM-disclaimer: This commit was generated by an LLM.
-
Deploy project DNS through Terraform modules
Move DNS ownership into each project’s Terraform state using shared modules. Load dnsconfig.json files at runtime, reject conflicting domain ownership, and render their records as a table. Add missing project AppRoles and scoped DNS policies, and document grouping related Terraform resources in modules.
Deploy all 45 owners sequentially: adopt 155 existing records and create 13 missing OpenHands records. Preserve every pre-existing provider record and verify no-op follow-up plans and DNS answers. Add DNS-scoped plan/show/apply wrappers with a saved-plan guard for roots that also manage services. Allow bounded aggregate path inventories large enough to deliver this migration while retaining truncation refusal in the delivery tool.
Validate runtime ownership, provider imports and preservation with isolated fixtures, Terraform formatting, wrapper builds, repository quality checks, semantic lint, and project documentation/specification builds.
OpenSpec-Change: infra/dns/openspec/changes/archive/2026-09-13-migrate-project-dns-to-terraform
LLM-disclaimer: This commit was generated by an LLM.
-
Fix Android review feedback
Add a shared
androidPluginsversion catalog so both Android apps declare the AGP, Kotlin, Compose, and protobuf plugin versions once, and derive their versions from it instead of duplicating literals per root Gradle file.Align the launcher and ingester app versions with the repository versioning contract: development builds use
0.0.0-devwithversionCode1 in both the Gradle default config and the Bazelmanifest_values.Ignore the whole materialized
.agents/skillsdirectory in Prettier because every entry is either a source-tree symlink or a byte-pinned external archive copy.Apply the ingester’s themed surface background to the main content surface so the status bar area follows the system theme, not a default white surface.
Token: z-ai-glm-flash-latest
LLM-disclaimer: This commit was generated by an LLM.
-
Reorganize Gradle, fdroid, and android skill layout
Collapse the maven_install_gradle_converter and tools/gradle Starlark layers into flat defs.bzl files per the project-layout skill. Replace the fdroid shell wrapper with a Go binary. Rewrite the Android smoke test as a Go test. Move the android skill from the launcher project to tools/android and register it in the skill discovery map.
Token: claude-opus-4-6 LLM-Disclaimer: Generated with Claude, reviewed by Simeon Warren
-
Prefer signed APK in Android smoke test
The android_binary rule produces both a signed and unsigned APK; the smoke test script picked whichever find returned first, which could be the unsigned one and fail installation. Explicitly skip unsigned APKs.
Token: claude-opus-4-6 LLM-Disclaimer: Generated with Claude, reviewed by Simeon Warren
-
Use pinned Gradle and add Android smoke test
Replace the curl-based Gradle wrapper with a Bazel-pinned Gradle archive and the existing rules_java remote JDK, exposed through a Starlark wrapper rule. Add a manual Android launcher instrumentation smoke test for runtime APK verification, and document the test and pinned JDK usage. Exclude Gradle-generated verification metadata from Prettier by filename glob and remove the unnecessary third_party ignore entry.
LLM-disclaimer: This commit was generated by an LLM.
-
Simplify OpenSpec workspace globs
Collapse OpenSpec source globs to specs and changes, drop redundant package visibility blocks already covered by REPO.bazel, and regenerate the affected catalogs.
LLM-disclaimer: This commit was generated by an LLM.
-
Publish project sites and reproducible infrastructure diagrams
Build and deploy all 30 remaining project sites with the standard Docsy header, project descriptions and a linked documentation directory. Omit the repeated page title and generated language heading. Remove the unused cgit and xray_manager projects and retire their site resources.
Add a repeatable GitHub Pages publisher, staged Terraform bootstrap and direct GitHub Pages DNS records. Preserve repeated publication when pages is the remote default branch, and include Rules ISO in the main documentation. Document site onboarding in a registered, validated skill. Keep AL introduction short with useful links and preserve its lifecycle details in a dedicated documentation page.
Render all 15 existing infrastructure Drawio pages with pinned Drawio and Chrome inputs, sandboxed export actions, an update target and freshness checks, and include the maintained diagrams in infra/arch documentation. Paint an opaque white canvas to preserve readability in dark themes.
Validation covers project and apex builds, rendered pages, publisher tests, diagram repeatability and freshness, DNS configuration, Terraform formatting, semantic lint and repository quality.
Goal-Ref: build-and-deploy-every-project-landing-page-a782b800 Attempt-ID: attempt-00941092c164
LLM-disclaimer: This commit was generated by an LLM.
-
Extract DNSControl setup into rules_dnscontrol
Extract the DNSControl setup into
rules_dnscontrol, generate its Bazel dependency bundle from project-owned record files, and update the DNS guidance. Move Hugo rules and the worker to role-based package paths, and give each non-nested project a locally owned Hugo landing target that reuses the shared README-to-landing macro.Clean all landing and Pages DNS records so GitHub Pages serves each project subdomain directly without Cloudflare proxying. Improve the main site with a three-panel home layout, complete project links, documentation explore links, and current deployment guidance.
All affected root-workspace landing, DNS, and site targets pass, along with the nested
rules_hugotests, Buildifier, and repository quality checks.LLM-disclaimer: This commit was generated by an LLM.
-
Add hermetic repository-wide formatting and linting
Integrate upstream formatters for the repository’s meaningful tracked source and configuration file types through Bazel, and add Buildifier, Ruff, and ShellCheck lint aspects for correctness-oriented repository-wide checks.
Pin all new external tools through Bzlmod or the existing pnpm lock, add thin cache/runfiles adapters where required, expose format and check targets, and wire the checks into the pre-commit workflow. Format the existing tree and fix the correctness defects uncovered by the new checks. Preserve generated sources and exact-content fixtures that are not safely rewritable, and clarify that ordinary infrastructure build output is safe to display.
Validation:
- all 21 repository quality and compatibility formatter tests pass
- Buildifier test passes
- lint aspects analyze all 4,629 ordinary root targets without findings
- the complete 18-command root and nested full-repository audit was exercised; remaining failures are documented environment or pre-existing test limits
LLM-disclaimer: This commit was generated by an LLM.
-
Add standalone documentation rules
Move docs_filegroup into a reusable rules_docs nested Bzlmod workspace and migrate every root and nested consumer to it. Add a module-aware Gazelle language that creates docs targets only for existing README packages while preserving manual mappings.
Wire the workspace into module resolution, documentation aggregation, and the ten-command full-repo-check. Add the bazel-nested-module skill so future nested workspaces follow the repository’s rc, lockfile, docs, toolchain, Gazelle, and validation conventions.
Keep reviewed Gazelle dependency canonicalization, while protecting the hand-maintained Go proto, Python resource, Android, embedded-site, and skill runner definitions that generic language plugins would otherwise break.
This commit was generated by an LLM.
-
Migrate documentation packaging to docs_filegroup
Preserve custom prefixes, renames, strip prefixes, and standalone workspace behavior.\n\nThis commit was generated by an LLM.
- Add a server to //projects/alwaldend.com
- Add //third_party/org_kernel_headers, rename all deps files to include
- Remove //tools/docs, remove .github
- Update android_launcher package name
- Bump protobuf and java deps, update leetcode
- Rename go modules to git.alwaldend.com/alwaldend/src
- Move all the logig out of the screen to the controller
- Add deploy to dockerhub, add //tools/oras
- Add missing features to the Pomodoro app, update project readmes, add github pages
- Move all remaining code to main
- Add release_page generation, remove redundant release templates
- Add //tools/bazelrc, move to a bazelrc preset
- Remove contracts tree
- Allow docs to put content outside of docs, refactor git to just use .git directly
- Add cross-compilation, move leetcode downloader contracts out of //contracts
- Refactor release templates into partials, add release cards
- Add more taxonomies, remove docs tree, move alwaldend.com to projects
- Rename proto to contracts, add tools/proto add proto docs
- Remove bazel target docs, add tools/docs, tag projects properly
- Improve doc structure
- Remove changelogs, ignore irrelevant directories in docs
- Move another group of rules to tools/
- Move a group of rules to tools/
- Remove kt tree
- Initial commit
-
Add spellcheck skill
This commit was generated by an LLM.
-
Restore light and dark site canvases and set the shared accent
The shared Docsy canvas set the same Bootstrap dark palette and the same black page background on
:root,[data-bs-theme="light"], and[data-bs-theme="dark"], so the light/dark toggle changed nothing. The site also rendered Bootstrap’s stock blue instead of its intended accent.Split the shared palette so light mode uses a pure white canvas with the light-mode palette and dark mode uses a pure black canvas with the dark-mode palette, and keep the pre-stylesheet paint and footer on the active mode. Assign
$primaryto#7c3aedbefore Bootstrap compiles, so links, buttons, badges, focus rings, and the dark-mode link tint all derive from one value rather than from a site-local copy.Both files stay in the reusable shell; the apex site consumes them through the existing declared exports and no longer carries the footer’s own blue.
OpenSpec-Change: projects/hugo_landing/openspec/changes/restore-light-dark-canvas-and-accent
LLM-disclaimer: This commit was generated by an LLM.
1.6 - Ansible collection
alwaldend.main is the repository’s Ansible collection. Bazel packages its
Ansible source for reuse in repository automation.
Links
- Source code: https://github.com/alwaldend/src/tree/master/projects/ansible_collection
- Docs: https://docs.ansible.com/ansible/latest/collections_guide/index.html
Features
- Ansible collection
- Bazel-managed Ansible source packaging.
Galaxy
namespace: alwaldend
name: main
version: 0.0.0
readme: README.md
authors:
- <example@domain.com>
description: main alwaldend ansible collection
license:
- AGPL-3.0-or-later
license_file: LICENSE.txt
tags: []
dependencies:
ansible.posix: 1.5.4
community.crypto: 2.17.0
community.general: 11.3.0
devsec.hardening: 9.0.1
community.docker: 3.11.0
repository: https://git.alwaldend.com/src
documentation: https://collection-main.docs.alwaldend.com
homepage: https://collection-main.docs.alwaldend.com
issues: ""
build_ignore: []
1.6.1 - Playbooks
1.6.2 - Roles
1.6.2.1 - Adguard
1.6.2.1.1 - Defaults
adguard_dir: /etc/adguard
adguard_work_dir: "{{ adguard_dir }}"
adguard_gpg_key_url: https://keys.openpgp.org/vks/v1/by-fingerprint/28645AC9776EC4C00BCE2AFC0FE641E7235E2EC6
adguard_gpg_key_src: files/key.asc
adguard_gpg_key_path: "{{ adguard_dir }}/release-key.asc"
adguard_gpg_key_checksum: "22d78dbacb461667861ee7d2dd13d13240ee003d"
adguard_release_source_url: https://github.com/AdguardTeam/AdGuardHome/releases/download
adguard_release_version: v0.107.48
adguard_release_checksum: "sha512:c0a336212e3792ae6fc6b8de976befce0038c5d6ddde919a00994c43a929349958c7bd65f7fb7fdd471962afa20855ecbf5830cc7a1d26f3037a716db638c101"
adguard_release_distrib: AdGuardHome_linux_amd64.tar.gz
adguard_release_url: "{{ adguard_release_source_url }}/{{ adguard_release_version }}/{{ adguard_release_distrib }}"
adguard_release_archive_dest: "{{ adguard_dir }}/release-{{ adguard_release_version }}-{{ adguard_release_distrib }}"
adguard_release_dest: "{{ adguard_dir }}/release-{{ adguard_release_version }}"
adguard_release_dir: "{{ adguard_release_dest }}/AdGuardHome"
adguard_release_bin: "{{ adguard_release_dir }}/AdGuardHome"
adguard_release_sig: "{{ adguard_release_bin }}.sig"
1.6.2.2 - Caddy
1.6.2.2.1 - Defaults
caddy_enabled: false
caddy_user: caddy
caddy_config_path: /etc/caddy/Caddyfile
caddy_config_dir: /etc/caddy/configs
caddy_config: |
import {{ caddy_config_dir }}/*
1.6.2.3 - CIFS
1.6.2.3.1 - Defaults
cifs_enabled: false
cifs_systemd_dir: /etc/systemd/system
cifs_mounts: []
1.6.2.4 - Consul
1.6.2.4.1 - Defaults
consul_user: consul
consul_user_uid: 4266
consul_dir: "/opt/consul"
consul_data_dir: "{{ consul_dir }}/data"
consul_config_dir: "{{ consul_dir }}/configs"
consul_config_path: "{{ consul_config_dir }}/consul.hcl"
consul_config_local_path: "files/consul.hcl"
consul_log_dir: "{{ consul_dir }}/logs"
consul_tls_dir: "{{ consul_dir }}/tls"
consul_service_path: "/lib/systemd/system/consul.service"
consul_tls_ca_file_local_path: files/pki_ca_servers.crt
consul_tls_ca_file_path: "{{ consul_tls_dir }}/tls_ca_file.crt"
consul_tls_cert_file_path: "{{ consul_tls_dir }}/cert_file.crt"
consul_tls_key_file_path: "{{ consul_tls_dir }}/key_file.crt"
consul_tls_common_name: "{{ inventory_hostname }}"
consul_tls_ttl: "2629746" # month
consul_tls_alt_names: ""
consul_vault_local_path: "{{ role_path }}/files/vault"
consul_bin_local_path: "{{ role_path }}/files/consul"
consul_bin_path: /usr/bin/consul
1.6.2.5 - Consul
1.6.2.5.1 - Defaults
consul_is_server: false
consul_user_name: consul
consul_user_uid:
consul_dir: "/opt/consul"
consul_persistence_dir: "{{ consul_dir }}"
consul_releases_dir: "{{ consul_dir }}/releases"
consul_config_symlink_dir: "{{ consul_configs_dir }}/current"
consul_config_symlink_data_dir: "{{ consul_config_symlink_dir }}/configs"
consul_configs_dir: "{{ consul_persistence_dir }}/configs/{{ inventory_hostname }}"
consul_data_dir: "{{ consul_persistence_dir }}/data/{{ inventory_hostname }}"
consul_config_path: "{{ consul_config_config_dir }}/consul.json"
consul_config_dir: "{{ consul_configs_dir }}/{{ consul_config_dir_name }}"
consul_config_data_dir: "{{ consul_config_dir }}/data"
consul_config_config_dir: "{{ consul_config_dir }}/configs"
consul_config_dir_name: "{{ consul_config_version }}"
consul_config_version: "{{ lookup('ansible.builtin.pipe', 'git rev-parse HEAD') }}"
consul_env: {}
consul_configs: []
consul_env_path: "{{ consul_config_data_dir }}/consul.env"
consul_env_symlink_path: "{{ consul_config_symlink_dir }}/data/consul.env"
consul_release_dir: "{{ consul_releases_dir }}/{{ consul_release_dir_name }}"
consul_release_dir_name: "{{ consul_release_version }}"
consul_release_symlink_path: "{{ consul_releases_dir }}/current"
consul_release_symlink_bin_path: "{{ consul_release_symlink_path }}/consul"
consul_release_version: 1.20.2
consul_release_archive_name: "consul_{{ consul_release_version }}_linux_amd64"
consul_release_archive_fullname: "{{ consul_release_archive_name }}.zip"
consul_release_bin_path: "{{ consul_release_dir }}/consul"
consul_release_url: "https://releases.hashicorp.com/consul/{{ consul_release_version }}/{{ consul_release_archive_fullname }}"
consul_release_checksum: "sha256:1bf7ddf332f02e6e36082b0fdf6c3e8ce12a391e7ec7dafd3237bb12766a7fd5"
consul_agent_ca_cert_path: "{{ consul_config_data_dir }}/agent_ca_cert.pub"
consul_agent_ca_cert:
consul_server_cert_path: "{{ consul_config_data_dir }}/server_cert_{{ inventory_hostname }}.pub"
consul_server_cert:
consul_server_key_path: "{{ consul_config_data_dir }}/server_cert_{{ inventory_hostname }}.key"
consul_server_key:
1.6.2.6 - Consul envoy
1.6.2.6.1 - Defaults
consul_envoy_dir: "/opt/consul_envoy"
consul_envoy_deployments_dir: "{{ consul_envoy_dir }}/deployments"
consul_envoy_releases_dir: "{{ consul_envoy_dir }}/releases"
consul_envoy_deployment_dir: "{{ consul_envoy_deployments_dir }}/{{ consul_envoy_deployment_version }}"
consul_envoy_release_dir: "{{ consul_envoy_releases_dir }}/{{ consul_envoy_release_version }}"
consul_envoy_configs_dir: "{{ consul_envoy_deployment_dir }}/configs"
consul_envoy_bootstrap_config_path: "{{ consul_envoy_configs_dir }}/bootstrap.json"
consul_envoy_deployment_version: "{{ lookup('ansible.builtin.pipe', 'git rev-parse HEAD') }}"
consul_envoy_user_name: consul_envoy
consul_envoy_release_version: 1.31.0
consul_envoy_release_archive_fullname: "envoy_{{ consul_envoy_release_version }}_linux_amd64.zip"
consul_envoy_release_url: "https://releases.hashicorp.com/envoy/{{ consul_envoy_release_version }}/{{ consul_envoy_release_archive_fullname }}"
consul_envoy_release_bin_path: "{{ consul_envoy_release_dir }}/envoy"
consul_envoy_release_symlink_path: "{{ consul_envoy_releases_dir }}/current"
consul_envoy_release_checksum: "sha256:350782275de0fe50699844b4f9096d77a0193a5bcf205e14b8ad964ec429d45e"
1.6.2.7 - Dev VM
The default task entry point configures package repositories and development
packages. It uses the same dev_vm_packages list with either the ordinary
package manager or RPM-OSTree layering. dev_vm_package_backend accepts
auto, package, or rpm_ostree; auto selects RPM-OSTree when
/run/ostree-booted exists. Set dev_vm_install_packages to false to skip
repository and package management entirely.
RPM-OSTree changes are staged for the next boot by default. The role reports a
pending deployment but does not reboot the host. Set
dev_vm_rpm_ostree_apply_live to true only when live application is known to
be safe for the selected packages.
The packaged Fedora mirror and Bazelisk tool currently make this role specific to Linux x86-64 development hosts.
The packages task entry point exposes package management separately from
other role tasks. The bazel task entry point installs a caller-provided Bazel
rc, Bazelisk, and the repository’s bazel_agent runner for one developer
account.
Import the Bazel entry point with tasks_from: bazel and set:
dev_vm_bazel_user: owner of the installed files.dev_vm_bazel_group: group of the installed files; defaults to the user.dev_vm_bazel_home: absolute home directory for the developer account.dev_vm_bazelrc_src: controller-side Bazel rc source; defaults tobazelrc.dev_vm_bazelisk_src: controller-side Bazelisk source; defaults tobazelisk.dev_vm_bazel_agent_src: controller-sidebazel_agentsource; defaults tobazel_agent.
The role packages its default Linux x86-64 Bazelisk and bazel_agent sources.
The calling playbook must package the Bazel rc, plus any overridden binary
sources, in an Ansible file search path. Cache storage and machine-specific
Bazel settings remain the caller’s responsibility.
1.6.2.7.1 - Defaults
---
dev_vm_install_packages: true
dev_vm_package_backend: auto
dev_vm_rpm_ostree_apply_live: false
dev_vm_packages:
- clang
- clang-tools-extra
- java-latest-openjdk-devel
- rust
- cargo
- mesa-libGL-devel
- go
- Xvfb
- python3
- gmp-devel
- patch
- podman
- git
- git-lfs
- fuse
- fuse-libs
- pcsc-lite
- pcsc-lite-devel
- openssl
- gnutls-utils
- opensc
- openssl-pkcs11
- libdnet
- qemu-kvm
- qemu-img
dev_vm_bazel_user: "{{ undefined() }}"
dev_vm_bazel_group: "{{ dev_vm_bazel_user }}"
dev_vm_bazel_home: "{{ undefined() }}"
dev_vm_bazelrc_src: bazelrc
dev_vm_bazelisk_src: bazelisk
dev_vm_bazel_agent_src: bazel_agent
dev_vm_selinux_android_emulation: true
1.6.2.8 - DNS
1.6.2.8.1 - Defaults
dns_records: []
dns_domains: []
dns_njalla_api_url: https://njal.la/api/1/
dns_njalla_token:
1.6.2.9 - Docker
1.6.2.9.1 - Defaults
docker_enabled: false
1.6.2.10 - Facts
1.6.2.10.1 - Defaults
facts_debug: false
1.6.2.11 - Filesystem
1.6.2.11.1 - Defaults
filesystem_setup: []
1.6.2.12 - Firewall
1.6.2.12.1 - Defaults
firewall_state: enabled
firewall_enabled: true
firewall_allow_port_from: []
firewall_allow_forward: []
1.6.2.13 - Forgejo
1.6.2.13.1 - Defaults
forgejo_user: forgejo
forgejo_user_uid: 5157
forgejo_dir: "/opt/forgejo"
forgejo_data_dir: "{{ forgejo_dir }}/data"
forgejo_config_dir: "{{ forgejo_dir }}/configs"
forgejo_work_dir: "{{ forgejo_dir }}/work"
forgejo_config_path: "{{ forgejo_config_dir }}/forgejo.ini"
forgejo_config_local_path: "files/forgejo.ini"
forgejo_disk:
forgejo_log_dir: "{{ forgejo_dir }}/logs"
forgejo_service_path: "/lib/systemd/system/forgejo.service"
forgejo_vault_local_path: "{{ role_path }}/files/vault"
forgejo_bin_local_path: "{{ role_path }}/files/forgejo"
forgejo_bin_path: /usr/bin/forgejo
1.6.2.14 - Forgejo
1.6.2.14.1 - Defaults
threexui_user: threexui
threexui_user_uid: 6468
threexui_dir: "/opt/threexui"
threexui_data_dir: "{{ threexui_dir }}/data"
threexui_work_dir: "{{ threexui_dir }}/work"
threexui_disk:
threexui_log_dir: "{{ threexui_dir }}/logs"
threexui_service_path: "/lib/systemd/system/threexui.service"
threexui_vault_local_path: "{{ role_path }}/files/vault"
threexui_bin_dir: "{{ threexui_dir }}/bin"
threexui_bin_local_dir: "{{ role_path }}/files/threexui_bin"
threexui_config_dir: "{{ threexui_dir }}/configs"
threexui_env_path: "{{ threexui_config_dir }}/threexui.env"
threexui_env_override: {}
threexui_base_path: /
threexui_username: "{{ undefined() }}"
threexui_password: "{{ undefined() }}"
threexui_port: "2053"
threexui_debug: "false"
threexui_env:
# https://docs.sanaei.dev/docs/reference/env-vars/
XUI_DB_TYPE: sqlite
XUI_DB_FOLDER: "{{ threexui_data_dir }}"
XUI_PORT: "{{ threexui_port }}"
XUI_INIT_WEB_BASE_PATH: "{{ threexui_base_path }}"
XUI_ENABLE_FAIL2BAN: "true"
XUI_SKIP_HSTS: "true"
XUI_LOG_LEVEL: info
XUI_DEBUG: "{{ threexui_debug }}"
XUI_LOG_FOLDER: "{{ threexui_log_dir }}"
XUI_BIN_FOLDER: "{{ threexui_bin_dir }}/bin"
XRAY_VMESS_AEAD_FORCED: "false"
XUI_ACCESS_URL: "https://{{ inventory_hostname }}{{ threexui_base_path }}"
XUI_USERNAME: "{{ threexui_username }}"
XUI_PASSWORD: "{{ threexui_password }}"
1.6.2.15 - Forgejo runner
1.6.2.15.1 - Defaults
forgejo_runner_user: forgejo-runner
forgejo_runner_user_uid: 5721
forgejo_runner_dir: /opt/forgejo-runner
forgejo_runner_disk:
forgejo_runner_home_dir: /opt/forgejo-runner/home
forgejo_runner_work_dir: /opt/forgejo-runner/work
forgejo_runner_bin_local_path: "{{ role_path }}/files/forgejo-runner"
forgejo_runner_bin_path: /usr/bin/forgejo-runner
forgejo_runner_service_path: /lib/systemd/system/forgejo-runner.service
forgejo_runner_instance: "{{ undefined() }}"
forgejo_runner_token: "{{ undefined() }}"
forgejo_runner_name: "{{ inventory_hostname }}"
forgejo_runner_labels:
- "self-hosted:host"
1.6.2.16 - Gpg
1.6.2.16.1 - Defaults
gpg_users: []
1.6.2.17.1 - Defaults
harbor_user: harbor
harbor_user_uid: 7049
harbor_dir: "/opt/harbor"
harbor_installer_dir: "{{ harbor_dir }}/installer"
harbor_logs_dir: "{{ harbor_dir }}/logs"
harbor_data_dir: "{{ harbor_dir }}/data"
harbor_installer_local_dir: "{{ role_path }}/files/harbor_installer"
harbor_config_path: "{{ harbor_installer_dir }}/harbor.yml"
harbor_config_local_path: "files/harbor.yaml"
harbor_domain: "{{ undefined() }}"
harbor_ca_local_path: "{{ role_path }}/files/pki_ca_servers.crt"
harbor_ca_path: /etc/docker/certs.d/{{ harbor_domain }}/ca.crt
harbor_root_ca_local_path: "{{ role_path }}/files/pki_ca_root.crt"
1.6.2.18 - Hermes
1.6.2.18.1 - Defaults
hermes_user: hermes
hermes_user_uid: 8150
hermes_dir: /opt/hermes
hermes_home_dir: "{{ hermes_dir }}/home"
hermes_install_dir: "{{ hermes_dir }}/hermes-agent"
hermes_disk:
hermes_port: 8642
hermes_commit: "{{ undefined() }}"
hermes_installer_local_path: "{{ role_path }}/files/install.sh"
hermes_installer_path: "{{ hermes_dir }}/install.sh"
hermes_config_local_path: "files/hermes.yaml"
hermes_config_path: "{{ hermes_home_dir }}/.hermes/config.yaml"
hermes_env_path: "{{ hermes_home_dir }}/.hermes/.env"
hermes_env: {}
hermes_bin_path: "{{ hermes_home_dir }}/.local/bin/hermes"
hermes_dashboard_service_path: /lib/systemd/system/hermes-dashboard.service
1.6.2.19 - Hiddify manager
1.6.2.19.1 - Defaults
hiddify_manager_env:
HIDDIFY_MANAGER_IMAGE: ghcr.io/hiddify/hiddify-manager:main@sha256:d5edef06d2133ffa26f0fcbb67e711f4356dba44c44a41a96570c4e03845a84c
HIDDIFY_MANAGER_REDIS_IMAGE: redis:7.4.1@sha256:bb142a9c18ac18a16713c1491d779697b4e107c22a97266616099d288237ef47
HIDDIFY_MANAGER_MARIADB_IMAGE: mariadb:11.6.2@sha256:a9547599cd87d7242435aea6fda22a9d83e2c06d16c658ef70d2868b3d3f6a80
HIDDIFY_MANAGER_REDIS_PASSWORD: "{{ lookup('ansible.builtin.env', 'HIDDIFY_MANAGER_REDIS_PASSWORD', default=undef()) }}"
HIDDIFY_MANAGER_MYSQL_PASSWORD: "{{ lookup('ansible.builtin.env', 'HIDDIFY_MANAGER_MYSQL_PASSWORD', default=undef()) }}"
HIDDIFY_MANAGER_MARIADB_PASSWORD: "{{ lookup('ansible.builtin.env', 'HIDDIFY_MANAGER_MARIADB_PASSWORD', default=undef()) }}"
hiddify_manager_env_override: {}
hiddify_manager_dir: /opt/hiddify_manager
1.6.2.20 - Hiddify manager with host
1.6.2.20.1 - Defaults
1.6.2.21 - Host
1.6.2.21.1 - Defaults
1.6.2.22 - Install CA
1.6.2.22.1 - Defaults
install_ca:
- path: "{{ role_path }}/files/pki_ca_root.crt"
- path: "{{ role_path }}/files/pki_ca_servers.crt"
1.6.2.23 - K3s
1.6.2.23.1 - Defaults
k3s_data_dir: /srv/k3s_data
k3s_service_name: k3s
k3s_data_disk: /dev/sdb
k3s_storage_dir: /srv/k3s_storage
k3s_storage_disk: /dev/sdc
k3s_config_path: "/etc/rancher/k3s/config.yaml"
k3s_config_local_path: "files/k3s.yaml"
k3s_admission_config_path: "/etc/rancher/k3s/admission.yaml"
k3s_admission_config_local_path: "files/k3s_admission.yaml"
k3s_auth_config_path: "{{ [(k3s_config_path | dirname), 'k3s_auth.yaml'] | path_join }}"
k3s_auth_config_local_path: "files/k3s_auth.yaml"
k3s_manifests_local_path: "files/k3s_manifests.yaml"
k3s_manifests_path: "{{ k3s_data_dir }}/server/manifests/k3s-manifests.yaml"
k3s_bin_local_path: "{{ role_path }}/files/k3s"
k3s_bin_path: /usr/local/bin/k3s
k3s_install_script_local_path: "{{ role_path }}/files/k3s_install"
k3s_install_script_path: /usr/local/bin/k3s_install
1.6.2.24 - K3s bootstrap
1.6.2.24.1 - Defaults
k3s_bootstrap_apply_path:
k3s_bootstrap_token_name: "{{ lookup('ansible.builtin.env', 'USER', default=undef()) }}"
k3s_bootstrap_token_namespace: kube-system
k3s_bootstrap_venv_dir: "/opt/bootstrap-venv"
k3s_bootstrap_venv_bin: "{{ k3s_bootstrap_venv_dir | mandatory }}/bin/python"
k3s_bootstrap_kubeconfig: /etc/rancher/k3s/k3s.yaml
k3s_bootstrap_cluster_name: "{{ inventory_hostname }}"
k3s_bootstrap_cluster_ca_path: "{{ lookup('ansible.builtin.env', 'HOME', default=undef()) }}/.kube/ca-{{ k3s_bootstrap_cluster_name | mandatory }}.ca.crt"
k3s_bootstrap_user_ca_path: "{{ k3s_bootstrap_cluster_ca_path | mandatory | dirname }}/ca-{{ k3s_bootstrap_cluster_name | mandatory }}-{{ k3s_bootstrap_token_name | mandatory }}.ca.crt"
k3s_bootstrap_user_name: "{{ k3s_bootstrap_cluster_name | mandatory }}-{{ k3s_bootstrap_token_name | mandatory }}"
k3s_bootstrap_cluster_port:
1.6.2.25 - K3s cluster
1.6.2.25.1 - Defaults
1.6.2.26 - K3s kubeconfig
1.6.2.26.1 - Defaults
k3s_kubeconfig_secret_path: "{{ undefined() }}"
k3s_kubeconfig_secret_mount: "{{ undefined() }}"
k3s_kubeconfig_path: /etc/rancher/k3s/k3s.yaml
k3s_kubeconfig_vault_bin_local_path: "{{ role_path }}/files/vault"
1.6.2.27 - lvg
lvg_volume_groups describes the complete desired physical-volume list for
each volume group. Extra physical volumes are not removed unless a caller sets
remove_extra_pvs: true.
Creating a volume group initializes every listed device as an LVM physical
volume. Callers must resolve stable device paths and verify that each device is
the intended, unused disk before applying this role; pvcreate may overwrite
an existing disk signature.
1.6.2.27.1 - Defaults
lvg_volume_groups: []
1.6.2.28 - lvol
Each lvol_volumes entry can constrain allocation with pvs, pass creation
arguments with opts, and disable shrinking with shrink: false.
1.6.2.28.1 - Defaults
lvol_volumes: []
1.6.2.29 - Mount
Mount entries can set opts, dump, and passno; state: mounted keeps the
mount active and writes its persistent /etc/fstab entry.
1.6.2.29.1 - Defaults
mount_points: []
1.6.2.30 - Opencode
1.6.2.30.1 - Defaults
opencode_user: opencode
opencode_user_uid: 8149
opencode_dir: "/opt/opencode"
opencode_port: 4096
opencode_domain: "{{ undefined() }}"
opencode_log_dir: "{{ opencode_dir }}/logs"
opencode_work_dir: "{{ opencode_dir }}/work"
opencode_home_dir: "{{ opencode_dir }}/home"
opencode_config_dir: "{{ opencode_home_dir }}/.config/opencode"
opencode_config_path: "{{ opencode_config_dir }}/opencode.json"
opencode_config_local_path: "files/opencode.json"
opencode_disk:
opencode_service_path: "/lib/systemd/system/opencode.service"
opencode_bin_local_path: "{{ role_path }}/files/opencode"
opencode_bin_path: /usr/bin/opencode
opencode_env_path: "{{ opencode_config_dir }}/opencode.env"
opencode_env_override: {}
opencode_ssh_public_key: "{{ undefined() }}"
opencode_ssh_private_key: "{{ undefined() }}"
opencode_server_username: "{{ undefined() }}"
opencode_server_password: "{{ undefined() }}"
opencode_env:
OPENCODE_SERVER_USERNAME: "{{ opencode_server_username }}"
OPENCODE_SERVER_PASSWORD: "{{ opencode_server_password }}"
1.6.2.31 - OpenHands automation
Runs the OpenHands automation server natively from a uv-managed virtual
environment. It stores schedules and event triggers, tracks run lifecycle, and
dispatches conversations to the agent server.
The automation server is not a sandbox. It records which agent server should
run a dispatched conversation and hands that work to
AUTOMATION_AGENT_SERVER_URL; setting that variable selects the agent
server’s local mode, which uses a persistent local agent server instead of
managed OpenHands Cloud sandboxes.
openhands_automation_agent_server_api_key must equal the agent server’s
session API key because both services authenticate the same
X-Session-API-Key value. openhands_automation_local_api_key is the key
browsers present to this service.
The service stores state in SQLite via AUTOMATION_DB_URL by default, which
local mode supports without a separate database role. Set
openhands_automation_database_url to a PostgreSQL URL to use one instead.
openhands_automation_kv_secret enables the automation key-value store and is
required for automations that persist state between runs.
openhands_automation_base_url is the externally reachable origin the service
appends /api/automation to when it builds callback URLs, so it must be the
origin the browser and the dispatched agent server side both use.
1.6.2.31.1 - Defaults
openhands_automation_user: openhands
openhands_automation_user_uid: 8154
openhands_automation_dir: /opt/openhands-automation
openhands_automation_home_dir: "{{ openhands_automation_dir }}/home"
openhands_automation_work_dir: "{{ openhands_automation_dir }}/work"
openhands_automation_state_dir: "{{ openhands_automation_dir }}/state"
openhands_automation_disk:
openhands_automation_packages:
- python3.12
- uv
openhands_automation_host: 127.0.0.1
openhands_automation_port: 18001
openhands_automation_version: "{{ undefined() }}"
openhands_automation_agent_server_version: "{{ undefined() }}"
openhands_automation_agent_server_url: "{{ undefined() }}"
openhands_automation_sandbox_agent_server_url: ""
openhands_automation_agent_server_api_key: "{{ undefined() }}"
openhands_automation_base_url: "{{ undefined() }}"
openhands_automation_local_api_key: "{{ undefined() }}"
openhands_automation_kv_secret: "{{ undefined() }}"
openhands_automation_database_url: "sqlite+aiosqlite:///{{ openhands_automation_state_dir }}/automations.db"
openhands_automation_workspace_base: "{{ openhands_automation_work_dir }}/automations"
openhands_automation_venv_dir: "{{ openhands_automation_dir }}/venv"
openhands_automation_service_path: /lib/systemd/system/openhands-automation.service
openhands_automation_env_path: "{{ openhands_automation_dir }}/.env"
openhands_automation_env:
PYTHONUTF8: "1"
OPENHANDS_REMOTE_WS_READY_REQUIRED: "false"
OPENHANDS_SUPPRESS_BANNER: "1"
openhands_automation_env_override: {}
1.6.2.32 - OpenHands canvas
Runs the OpenHands Agent Canvas browser client from the published npm package.
The service listens on loopback port openhands_canvas_port; TLS, the public
hostname, and routing to the agent server and automation API belong to the
deployment’s Traefik role.
The service runs the package’s scripts/static-server.mjs directly with Node,
an explicit loopback host, and the package’s build/ directory. It serves the
browser client without starting an agent server, an automation server, or the
npm launcher’s additional ingress process. Agent Canvas owns no conversation
or automation state and executes no tools.
The browser starts with no configured backend. The operator adds one with the canvas origin as the host and the agent server’s session key as the credential. The static server receives no session key and injects none into served assets. This configuration does not advertise an embedded VSCode editor.
The npm prefix is installed inside openhands_canvas_dir.
openhands_canvas_package_dir identifies the installed package containing the
static server and browser assets.
1.6.2.32.1 - Defaults
openhands_canvas_user: openhands
openhands_canvas_user_uid: 8153
openhands_canvas_dir: /opt/openhands-canvas
openhands_canvas_home_dir: "{{ openhands_canvas_dir }}/home"
openhands_canvas_work_dir: "{{ openhands_canvas_dir }}/work"
openhands_canvas_state_dir: "{{ openhands_canvas_dir }}/state"
openhands_canvas_package_dir: "{{ openhands_canvas_dir }}/lib/node_modules/@openhands/agent-canvas"
openhands_canvas_disk:
openhands_canvas_packages:
- nodejs24
- nodejs24-npm
openhands_canvas_host: 127.0.0.1
openhands_canvas_port: 8000
openhands_canvas_version: "{{ undefined() }}"
openhands_canvas_service_path: /lib/systemd/system/openhands-canvas.service
openhands_canvas_env_path: "{{ openhands_canvas_dir }}/.env"
openhands_canvas_env:
NODE_ENV: production
openhands_canvas_env_override: {}
1.6.2.33 - Openhands server
Runs the OpenHands agent server natively from a uv-managed virtual
environment. It hosts conversations, executes tools, and streams events for
Agent Canvas. The service binds loopback only; TLS and external reachability
belong to the calling deployment.
Set openhands_server_secure to true to require a session API key. The
unsecured mode omits the session key and is only appropriate where the loopback
boundary is trusted.
The caller can set openhands_server_install_packages to false and install
openhands_server_packages through its host-specific package workflow.
OSTree hosts use the shared dev_vm package entry point and must boot into a
deployment containing those dependencies before installing the service. They
also set openhands_server_service_path under /etc/systemd/system.
1.6.2.33.1 - Defaults
openhands_server_user: openhands
openhands_server_user_uid: 8152
openhands_server_dir: /opt/openhands-server
openhands_server_home_dir: "{{ openhands_server_dir }}/home"
openhands_server_work_dir: "{{ openhands_server_dir }}/work"
openhands_server_state_dir: "{{ openhands_server_dir }}/state"
openhands_server_conversations_dir: "{{ openhands_server_state_dir }}/conversations"
openhands_server_persistence_dir: "{{ openhands_server_state_dir }}/persistence"
openhands_server_workspace_dir: "{{ openhands_server_work_dir }}/project"
openhands_server_bash_events_dir: "{{ openhands_server_state_dir }}/bash_events"
openhands_server_tools_dir: "{{ openhands_server_dir }}/tools"
openhands_server_disk:
openhands_server_secure: true
openhands_server_install_packages: true
openhands_server_packages:
- python3.12
- uv
openhands_server_host: 127.0.0.1
openhands_server_port: 18000
openhands_server_version: "{{ undefined() }}"
openhands_server_session_api_key: "{{ undefined() }}"
openhands_server_secret_key: "{{ undefined() }}"
openhands_server_import_modules: canvas_ui_tool
openhands_server_vscode_port: 8001
openhands_server_vscode_base_path: /vscode
openhands_server_venv_dir: "{{ openhands_server_dir }}/venv"
openhands_server_venv_python: "{{ openhands_server_venv_dir }}/bin/python"
openhands_server_service_path: /lib/systemd/system/openhands-server.service
openhands_server_env_path: "{{ openhands_server_dir }}/.env"
openhands_server_env:
LOG_JSON: "true"
PYTHONUTF8: "1"
OPENHANDS_REMOTE_WS_READY_REQUIRED: "false"
OH_PERSISTENCE_DIR: "{{ openhands_server_persistence_dir }}"
OH_CONVERSATIONS_PATH: "{{ openhands_server_conversations_dir }}"
OH_WORKSPACE_PATH: "{{ openhands_server_workspace_dir }}"
OH_BASH_EVENTS_DIR: "{{ openhands_server_bash_events_dir }}"
OH_SECRET_KEY: "{{ openhands_server_secret_key }}"
1.6.2.34 - OS
1.6.2.34.1 - Defaults
os_hardening_enabled: true
1.6.2.35 - Posgresql
1.6.2.35.1 - Defaults
postgresql_packages:
- postgresql-server
- postgresql-contrib
postgresql_service: postgresql
1.6.2.36.1 - Defaults
pve_repo_keyring_path: /usr/share/keyrings/proxmox-archive-keyring.gpg
pve_repo_path: /etc/apt/sources.list.d/pve-install-repo.sources
pve_repo_keyring_url: https://enterprise.proxmox.com/debian/proxmox-archive-keyring-trixie.gpg
pve_repo_keyring_checksum: "sha256:136673be77aba35dcce385b28737689ad64fd785a797e57897589aed08db6e45"
pve_snippets_dir: /var/lib/vz/snippets
pve_snippets: []
pve_repo_content: |
Types: deb
URIs: http://download.proxmox.com/debian/pve
Suites: trixie
Components: pve-no-subscription
Signed-By: {{ pve_repo_keyring_path }}
1.6.2.37 - PVE cluster
1.6.2.37.1 - Defaults
pve_cluster_remove_repos:
- pve-enterprise.list
- ceph.list
pve_cluster_add_repos:
- name: pve-no-subscription
value: deb http://download.proxmox.com/debian/pve bookworm pve-no-subscription
- name: ceph-squid
value: deb http://download.proxmox.com/debian/ceph-squid bookworm no-subscription
pve_cluster_node_config: []
pve_cluster_admins: []
pve_cluster_cluster_name:
pve_cluster_acme_accounts: []
pve_cluster_acme_plugins: []
pve_cluster_venv_dir: /opt/ansible/pve_cluster_venv
pve_cluster_venv_packages:
- pexpect
pve_cluster_base_image_dir: /var/lib/vz/template
pve_cluster_node_name: "{{ inventory_hostname | mandatory | split('.') | first }}"
pve_cluster_ceph_enabled: false
pve_cluster_ceph_repository: no-subscription
pve_cluster_ceph_osd: []
pve_cluster_ceph_pools: []
pve_cluster_ceph_mon: []
pve_cluster_ceph_mgr: []
pve_cluster_ceph_mds: []
pve_cluster_storages: []
pve_cluster_storage_config_path: /etc/pve/storage.cfg
1.6.2.38 - PVE VM
1.6.2.38.1 - Defaults
pve_vm_agent:
pve_vm_name: "{{ inventory_hostname }}"
pve_vm_delegate_update_known_hosts: localhost
pve_vm_delegate_pve:
pve_vm_set: "{{ pve_vm_set_default + pve_vm_set_additional }}"
pve_vm_set_default: []
pve_vm_set_additional: []
pve_vm_set_creation: "{{ pve_vm_set_creation_default + pve_vm_set_creation_additional }}"
pve_vm_set_creation_default: []
pve_vm_set_creation_additional: []
pve_vm_resize: []
pve_vm_venv_dir: "/opt/ansible/pve_vm_venv"
pve_vm_init_user:
pve_vm_venv_packages:
- proxmoxer
- requests
1.6.2.39 - PVE VM remove
1.6.2.39.1 - Defaults
1.6.2.40 - Raspberry pi
1.6.2.40.1 - Defaults
raspberry_pi_argon_enabled: false
raspberry_pi_containers_enabled: false
raspberry_pi_argon_eeprom_script_path: /usr/local/bin/argon_argon_eeprom.sh
raspberry_pi_argon_argon1_script_path: /usr/local/bin/argon_argon1.sh
raspberry_pi_cmdline_path: /boot/firmware/cmdline.txt
1.6.2.41 - SSH
1.6.2.41.1 - Defaults
ssh_hardening_enabled: true
ssh_vault_mount: ssh/servers
ssh_vault_role: "{{ undefined }}"
ssh_sign_ignore_errors: false
ssh_valid_principals: []
1.6.2.42 - SSH port forwarding
1.6.2.42.1 - Defaults
ssh_port_forward_local_addr: 127.0.0.1
ssh_port_forward_script_path: /usr/local/bin/ssh-port-forward
1.6.2.43 - SSH update known hosts
1.6.2.43.1 - Defaults
ssh_update_known_hosts_hosts: []
1.6.2.44 - T3 Code
1.6.2.44.1 - Defaults
t3code_user: t3code
t3code_user_uid: 8151
t3code_dir: /opt/t3code
t3code_home_dir: "{{ t3code_dir }}/home"
t3code_work_dir: "{{ t3code_dir }}/work"
t3code_disk:
t3code_port: 5120
t3code_version: "{{ undefined() }}"
t3code_state_dir: "{{ t3code_dir }}/state"
t3code_auth_token: "{{ undefined() }}"
t3code_service_path: /lib/systemd/system/t3code.service
t3code_env_path: "{{ t3code_dir }}/.env"
t3code_env: {}
1.6.2.45 - Traefik
1.6.2.45.1 - Defaults
traefik_user: traefik
traefik_no_user: false
traefik_owner: root
traefik_user_uid: 3578
traefik_dir: "/opt/traefik"
traefik_log_dir: "{{ traefik_dir }}/logs"
traefik_data_dir: "{{ traefik_dir }}/data"
traefik_tls_dir: "{{ traefik_dir }}/tls"
traefik_disk:
traefik_mtls_ca_local_path: "{{ role_path }}/files/traefik_mtls_ca.crt"
traefik_mtls_ca_path: "{{ traefik_tls_dir }}/mtls_ca.crt"
traefik_acme_path: "{{ undefined }}"
traefik_config_dir: "{{ traefik_dir }}/configs"
traefik_config_path: "{{ traefik_config_dir }}/traefik.toml"
traefik_disable_eab: false
traefik_config_local_path: "files/traefik.toml"
traefik_dynamic_config_path: "{{ traefik_config_dir }}/traefik_dynamic.toml"
traefik_dynamic_config_local_path: "files/traefik_dynamic.toml"
traefik_service_path: "/lib/systemd/system/traefik.service"
traefik_service_scope: system
traefik_bin_local_path: "{{ role_path }}/files/traefik"
traefik_bin_path: /usr/bin/traefik
traefik_vault_bin_local_path: "{{ role_path }}/files/vault"
1.6.2.46 - Traefik (old)
1.6.2.46.1 - Defaults
traefik_user: traefik
traefik_user_uid: 3653
traefik_env: {}
traefik_data_dir: /mnt/traefik
traefik_log_dir: "/var/log/traefik"
traefik_certificates_dir: "{{ traefik_data_dir }}/certificates"
traefik_configs_dir: "{{ traefik_data_dir }}/configs"
traefik_configs_version: "{{ lookup('ansible.builtin.pipe', 'git rev-parse HEAD') }}"
traefik_configs_dynamic_dir: "{{ traefik_configs_cur_dir }}/dynamic"
traefik_configs_dynamic_dir_symlink: "{{ traefik_configs_symlink }}/dynamic"
traefik_configs_cur_dir_name: "{{ traefik_configs_version }}"
traefik_configs_cur_dir: "{{ traefik_configs_dir }}/{{ traefik_configs_cur_dir_name }}"
traefik_configs_symlink: "{{ traefik_configs_dir }}/current"
traefik_static_config_path: "{{ traefik_configs_symlink }}/traefik.yaml"
traefik_releases_dir: /opt/traefik/releases
traefik_static_config:
traefik_dynamic_configs: []
traefik_release_version: v3.3.1
traefik_release_dir_name: "{{ traefik_release_version }}"
traefik_release_dir: "{{ traefik_releases_dir }}/{{ traefik_release_dir_name }}"
traefik_release_symlink: "{{ traefik_releases_dir }}/current"
traefik_release_symlink_bin: "{{ traefik_release_symlink }}/traefik"
traefik_release_archive_name: "traefik_{{ traefik_release_version }}_linux_amd64"
traefik_release_archive_full: "traefik_{{ traefik_release_version }}_linux_amd64.tar.gz"
traefik_release_bin_path: "{{ traefik_release_dir }}/traefik"
traefik_release_download_url: "https://github.com/traefik/traefik/releases/download/{{ traefik_release_version }}/{{ traefik_release_archive_full }}"
traefik_release_download_checksum: sha256:27fd502a8d80fc81b97faf5cebd7a1cbc1a2c5369d18e0f4471a66d1a8c139ce
1.6.2.47 - Update all packages
1.6.2.47.1 - Defaults
1.6.2.48 - Users
1.6.2.48.1 - Defaults
users_regular: {}
users_remove: {}
users_admins:
ansible:
name: ansible
disable_passwd: true
sudo_no_passwd: true
users_ssh_keys: {}
1.6.2.49 - Vault
1.6.2.49.1 - Defaults
vault_user: vault
vault_user_uid: 3123
vault_dir: "/opt/vault"
vault_data_dir: "{{ vault_dir }}/data"
vault_raft_dir: "{{ vault_dir }}/raft"
vault_config_dir: "{{ vault_dir }}/configs"
vault_config_path: "{{ vault_config_dir }}/vault.hcl"
vault_config_local_path: "files/vault.hcl"
vault_log_dir: "{{ vault_dir }}/logs"
vault_tls_dir: "{{ vault_dir }}/tls"
vault_service_path: "/lib/systemd/system/vault.service"
vault_tls_client_ca_file_local_path: files/tls_client_ca_file.pem
vault_tls_client_ca_file_path: "{{ vault_tls_dir }}/tls_client_ca_file.pem"
vault_tls_cert_file_path: "{{ vault_tls_dir }}/tls_cert_file.pem"
vault_tls_key_file_path: "{{ vault_tls_dir }}/tls_key_file.pem"
vault_tls_issue_path:
vault_tls_alt_names: ""
vault_bin_local_path: "{{ role_path }}/files/vault"
vault_bin_path: /usr/bin/vault
vault_peers_write: false
vault_peers_local_path:
vault_peers_remote_path: "{{ vault_raft_dir }}/raft/peers.json"
1.6.2.50 - Wireguard
1.6.2.50.1 - Defaults
wireguard_dir: "/etc/wireguard"
wireguard_local_config_paths: []
1.6.2.51.1 - Defaults
xray_enabled: false
xray_config_dir: /usr/local/etc/xray
xray_log_dir: /var/log/xray
xray_config_path: "{{ xray_config_dir }}/0-main.json"
xray_client_id:
xray_wireguard_relays: []
xray_wireguard_ipv4_address:
xray_wireguard_ipv6_address:
xray_wireguard_private_key:
xray_config:
xray_configs: {}
xray_user: xray
xray_socket_dir: /var/shm/xray
xray_caddy_config_path: /etc/caddy/configs/xray.Caddyfile
xray_subscriptions_dir: /usr/local/etc/xray-subscriptions
xray_caddy_user: caddy
1.7 - Autoscroll
Autoscroll is a Python and PyQt6 command-line application that turns mouse movement into horizontal and vertical scrolling. It supports configurable buttons, scroll speed, and configuration changes without restarting.
Links
Features
- Platfrom-independent autoscroll
- Config file with hot-reload
- Some argparse tinkering
- Python3, PyQt6
Usage
By default, the icon is disabled, to enable it pass --icon-enable
You can pass file contents as command line arguments using @path/to/the/file syntax.
Arguments in that case can be placed wherever - on one line, on several lines
If you want to dynamically pass runtime arguments (without restarting the process), you can use --config options for it
Once you press --buttons-start, you can scroll vertically or horizontally just by moving your mouse untill you press --buttons-end
If --buttons-hold is set, the srolling ends once you release --buttons-start
Once --buttons-start is pressed, the scroll thread starts looping
Every loop consists of sleeping for an interval, then scrolling for either 0, 1, or -1 pixels on both axis towards the starting point
Starting point is the point where --buttons-start was pressed
Sleep interval is recalculated on every mouse move as such:
100 / (--scrolling-acceleration * max(distance) + --scrolling-speed)
If --scrolling-acceleration is not 0, the speed of scrolling will be faster
the farther away you are from the starting point
If --scrolling-acceleration is 0, the speed of scrolling will be constant
Examples
Use the package
python3 -m venv venv
. venv/bin/activate
pip install autoscroll
autoscroll
Command line options
autoscroll --buttons-start 1 --debug-click --icon-disable
Pass a configuration file once
autoscroll --icon-enable @config.txt
If config.txt is defined like this, its contents will be used as command line arguments - they will be loaded only once
Arguments can be placed wherever - on one line, on several lines
For example,
--buttons-start 1
--buttons-hold --debug-click
Listen for changes in the configuration file
autoscroll --config-enable --config-path config.txt
If config.txt is defined like this, the process will listen for changes in that
file and update itself
Arguments can be placed wherever - on one line, on several lines
The file is checked for changess every --config-interval
For example:
--buttons-start 1 --buttons-hold
--debug_click
--help output
usage: autoscroll [-h] [-ss SCROLLING_SPEED] [-sd SCROLLING_DEAD_AREA]
[-sa SCROLLING_ACCELERATION] [-bh] [-bs BUTTONS_START] [-be BUTTONS_END]
[-ce] [-cp CONFIG_PATH] [-ci CONFIG_INTERVAL] [-ie] [-ip ICON_PATH]
[-is ICON_SIZE] [-df] [-dc] [-ds] [-di]
...
options:
-h, --help show this help message and exit
scrolling:
-ss, --scrolling-speed int
constant part of the scrolling speed
[default: 300]
-sd, --scrolling-dead-area int
size of the square area aroung the starting point where scrolling will stop, in
pixels
[default: 50]
-sa, --scrolling-acceleration int
dynamic part of the scrolling speed, depends on the distance from the point
where the scrolling started, can be set to 0
[default: 10]
buttons:
-bh, --buttons-hold if set, the scrolling will end once you release --buttons-start
-bs, --buttons-start int
button that starts the scrolling
[default: 2]
-be, --buttons-end int
button that ends the scrolling
[default: --buttons-start]
config:
-ce, --config-enable if set, arguments from the configuration file on --config-path will be loaded
every --config-interval
-cp, --config-path str
path to the configuration file
[default: ~/.config/autoscroll/config.txt]
-ci, --config-interval int
how often the config file should be checked for changes, in seconds
[default: 5]
icon:
-ie, --icon-enable if set, the icon will be enabled
-ip, --icon-path str path to the icon
[default: resources/img/icon.svg]
-is, --icon-size int size of the icon, in pixels
[default: 30]
debug:
-df, --debug-file if set, every time the config file is parsed, information will be printed to
stdout
-dc, --debug-click if set, click info will be printed to stdout
-ds, --debug-scroll if set, scroll info will be printed to stdout
-di, --debug-initial if set, startup configuration will be printed to stdout
1.7.1 - Releases
head
-
Move project landings into the main site
Publish every registered project’s visitor-facing landing page at /projects/
/ from the main site instead of a dedicated subdomain, and retire the per-project Pages repository, CNAME, and Terraform DNS stage that existed only to serve one page derived from the project README. Each project owns its landing content in projects/
/site/content/ as pure content: no layouts, styles, or build rules. The main site packages those directories into content/projects/ / from the registry in projects/projects.bzl, so membership is declared once. The landing is a short hand-written page for visitors while the README keeps its /docs/projects/ / URL for repository reference documentation, and landing front matter now feeds the statuses, languages, and tags taxonomies. Merge the reusable hugo_landing project into the main site: its shared canvas and accent styles and its landing page rules move into the apex tree, and its landing macro, generated configuration, standalone publisher, and repository-relative rewrite layouts are removed. The theme keeps owning the taxonomy and term layouts, which are richer than the heading-only versions the reusable project carried. Remove the now-unused apex deploy_project.sh and deploy_all.sh landing publishers with it.
Retire the per-project publication and DNS ownership: the project landing targets and the landing deployment command, each landing project’s dnsconfig.json and Terraform root, the build plumbing that served only those stages, and the landing repository and Pages membership in the repository catalog. The apex Terraform root is retained because it also declares VM resources, and no Vault configuration is changed.
Replace the provider-snapshot zone files with generated declaration pages, one per destination view, that project the checked-in declarations and are verified for freshness by the DNS offline check. The DNS linter, both destination pages, the apex site, the skills projection, and the repository quality suite pass, and the whole repository builds.
OpenSpec-Change: projects/alwaldend.com/openspec/changes/consolidate-project-landings-into-apex
LLM-disclaimer: This commit was generated by an LLM.
-
Manage forge resources with hermetic Terraform rules
Centralize organization, repository, and named access configuration in infra/repos. Adopt existing GitHub resources, protect master defaults while retaining Pages publication on pages, and preserve existing repository identities. Manage GitLab one-time imports, the F-Droid metadata fork, and default-branch protections through Vault-backed authentication. Forgejo consumes the same catalog. Ongoing repository synchronization is deferred.
Retire the eleven Bazel rule landing sites through their owning Terraform workflows, removing their DNS records, Pages repositories, and landing configuration. Move all twelve existing standalone rule modules into tools/ and retain their public interfaces and documentation on the main site.
Add tools/rules_terraform with verified provider downloads, packed mirrors in runfiles, and reusable Terraform execution rules. Enforce one version per provider source at an extensible resolution boundary. Migrate every Terraform consumer to thirteen shared provider pins in third_party/terraform. Execution and command maps belong to rules_terraform; consumers explicitly select generic AL wrappers for authentication and Vault injection. Remove tools/terraform and all 43 checked-in Terraform provider locks. Validate installed providers against the declared archives before execution.
Validation covers all fourteen workspace builds, all thirteen standalone test suites, Terraform consumers, offline real-provider regressions, rendered documentation, formatting, and semantic lint. The full root test run has 295 passing tests and one skip; its only failure is the historical secret scan, reduced to four pre-existing synthetic fixture matches. Earlier live imports and the exact landing retirement scope have verified postconditions; the Terraform rules migration uses only offline implementation checks.
OpenSpec-Change: infra/repos/openspec/changes/archive/2026-09-13-adopt-shared-repository-catalog OpenSpec-Change: infra/src/openspec/changes/archive/2026-09-13-retire-bazel-rule-landings OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-add-hermetic-terraform-rules OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-correct-terraform-ownership
LLM-disclaimer: This commit was generated by an LLM.
-
Deploy project DNS through Terraform modules
Move DNS ownership into each project’s Terraform state using shared modules. Load dnsconfig.json files at runtime, reject conflicting domain ownership, and render their records as a table. Add missing project AppRoles and scoped DNS policies, and document grouping related Terraform resources in modules.
Deploy all 45 owners sequentially: adopt 155 existing records and create 13 missing OpenHands records. Preserve every pre-existing provider record and verify no-op follow-up plans and DNS answers. Add DNS-scoped plan/show/apply wrappers with a saved-plan guard for roots that also manage services. Allow bounded aggregate path inventories large enough to deliver this migration while retaining truncation refusal in the delivery tool.
Validate runtime ownership, provider imports and preservation with isolated fixtures, Terraform formatting, wrapper builds, repository quality checks, semantic lint, and project documentation/specification builds.
OpenSpec-Change: infra/dns/openspec/changes/archive/2026-09-13-migrate-project-dns-to-terraform
LLM-disclaimer: This commit was generated by an LLM.
-
Simplify OpenSpec workspace globs
Collapse OpenSpec source globs to specs and changes, drop redundant package visibility blocks already covered by REPO.bazel, and regenerate the affected catalogs.
LLM-disclaimer: This commit was generated by an LLM.
-
Publish project sites and reproducible infrastructure diagrams
Build and deploy all 30 remaining project sites with the standard Docsy header, project descriptions and a linked documentation directory. Omit the repeated page title and generated language heading. Remove the unused cgit and xray_manager projects and retire their site resources.
Add a repeatable GitHub Pages publisher, staged Terraform bootstrap and direct GitHub Pages DNS records. Preserve repeated publication when pages is the remote default branch, and include Rules ISO in the main documentation. Document site onboarding in a registered, validated skill. Keep AL introduction short with useful links and preserve its lifecycle details in a dedicated documentation page.
Render all 15 existing infrastructure Drawio pages with pinned Drawio and Chrome inputs, sandboxed export actions, an update target and freshness checks, and include the maintained diagrams in infra/arch documentation. Paint an opaque white canvas to preserve readability in dark themes.
Validation covers project and apex builds, rendered pages, publisher tests, diagram repeatability and freshness, DNS configuration, Terraform formatting, semantic lint and repository quality.
Goal-Ref: build-and-deploy-every-project-landing-page-a782b800 Attempt-ID: attempt-00941092c164
LLM-disclaimer: This commit was generated by an LLM.
-
Extract DNSControl setup into rules_dnscontrol
Extract the DNSControl setup into
rules_dnscontrol, generate its Bazel dependency bundle from project-owned record files, and update the DNS guidance. Move Hugo rules and the worker to role-based package paths, and give each non-nested project a locally owned Hugo landing target that reuses the shared README-to-landing macro.Clean all landing and Pages DNS records so GitHub Pages serves each project subdomain directly without Cloudflare proxying. Improve the main site with a three-panel home layout, complete project links, documentation explore links, and current deployment guidance.
All affected root-workspace landing, DNS, and site targets pass, along with the nested
rules_hugotests, Buildifier, and repository quality checks.LLM-disclaimer: This commit was generated by an LLM.
-
Add hermetic repository-wide formatting and linting
Integrate upstream formatters for the repository’s meaningful tracked source and configuration file types through Bazel, and add Buildifier, Ruff, and ShellCheck lint aspects for correctness-oriented repository-wide checks.
Pin all new external tools through Bzlmod or the existing pnpm lock, add thin cache/runfiles adapters where required, expose format and check targets, and wire the checks into the pre-commit workflow. Format the existing tree and fix the correctness defects uncovered by the new checks. Preserve generated sources and exact-content fixtures that are not safely rewritable, and clarify that ordinary infrastructure build output is safe to display.
Validation:
- all 21 repository quality and compatibility formatter tests pass
- Buildifier test passes
- lint aspects analyze all 4,629 ordinary root targets without findings
- the complete 18-command root and nested full-repository audit was exercised; remaining failures are documented environment or pre-existing test limits
LLM-disclaimer: This commit was generated by an LLM.
-
Add standalone documentation rules
Move docs_filegroup into a reusable rules_docs nested Bzlmod workspace and migrate every root and nested consumer to it. Add a module-aware Gazelle language that creates docs targets only for existing README packages while preserving manual mappings.
Wire the workspace into module resolution, documentation aggregation, and the ten-command full-repo-check. Add the bazel-nested-module skill so future nested workspaces follow the repository’s rc, lockfile, docs, toolchain, Gazelle, and validation conventions.
Keep reviewed Gazelle dependency canonicalization, while protecting the hand-maintained Go proto, Python resource, Android, embedded-site, and skill runner definitions that generic language plugins would otherwise break.
This commit was generated by an LLM.
-
Fix remaining repository build failures
This commit was generated by an LLM.
-
Migrate documentation packaging to docs_filegroup
Preserve custom prefixes, renames, strip prefixes, and standalone workspace behavior.\n\nThis commit was generated by an LLM.
- Remove //tools/docs, remove .github
- Add build_test tests
- Fix infinitime python deps, bump python version
- Move all the logig out of the screen to the controller
- Add deploy to dockerhub, add //tools/oras
- Add missing features to the Pomodoro app, update project readmes, add github pages
- Move all remaining code to main
- Move a portion of tool code to main
- Use separate lock files for each golang tool
- Add release_page generation, remove redundant release templates
- Allow docs to put content outside of docs, refactor git to just use .git directly
- Add cross-compilation, move leetcode downloader contracts out of //contracts
- Refactor release templates into partials, add release cards
- Write release tool in go, start adding it to projects, add py proto generation
- Add release rules, add gzip rules, add several other tools, remove autoscrool deps from the root
- Flatten third_party, split tools/bzl a bit
- Add more taxonomies, remove docs tree, move alwaldend.com to projects
- Remove bazel target docs, add tools/docs, tag projects properly
- Remove changelogs, ignore irrelevant directories in docs
- Remove patch tree, remove py tree
- Initial commit
-
Add spellcheck skill
This commit was generated by an LLM.
-
Restore light and dark site canvases and set the shared accent
The shared Docsy canvas set the same Bootstrap dark palette and the same black page background on
:root,[data-bs-theme="light"], and[data-bs-theme="dark"], so the light/dark toggle changed nothing. The site also rendered Bootstrap’s stock blue instead of its intended accent.Split the shared palette so light mode uses a pure white canvas with the light-mode palette and dark mode uses a pure black canvas with the dark-mode palette, and keep the pre-stylesheet paint and footer on the active mode. Assign
$primaryto#7c3aedbefore Bootstrap compiles, so links, buttons, badges, focus rings, and the dark-mode link tint all derive from one value rather than from a site-local copy.Both files stay in the reusable shell; the apex site consumes them through the existing declared exports and no longer carries the footer’s own blue.
OpenSpec-Change: projects/hugo_landing/openspec/changes/restore-light-dark-canvas-and-accent
LLM-disclaimer: This commit was generated by an LLM.
1.7.1.1 - head
-
Move project landings into the main site
Publish every registered project’s visitor-facing landing page at /projects/
/ from the main site instead of a dedicated subdomain, and retire the per-project Pages repository, CNAME, and Terraform DNS stage that existed only to serve one page derived from the project README. Each project owns its landing content in projects/
/site/content/ as pure content: no layouts, styles, or build rules. The main site packages those directories into content/projects/ / from the registry in projects/projects.bzl, so membership is declared once. The landing is a short hand-written page for visitors while the README keeps its /docs/projects/ / URL for repository reference documentation, and landing front matter now feeds the statuses, languages, and tags taxonomies. Merge the reusable hugo_landing project into the main site: its shared canvas and accent styles and its landing page rules move into the apex tree, and its landing macro, generated configuration, standalone publisher, and repository-relative rewrite layouts are removed. The theme keeps owning the taxonomy and term layouts, which are richer than the heading-only versions the reusable project carried. Remove the now-unused apex deploy_project.sh and deploy_all.sh landing publishers with it.
Retire the per-project publication and DNS ownership: the project landing targets and the landing deployment command, each landing project’s dnsconfig.json and Terraform root, the build plumbing that served only those stages, and the landing repository and Pages membership in the repository catalog. The apex Terraform root is retained because it also declares VM resources, and no Vault configuration is changed.
Replace the provider-snapshot zone files with generated declaration pages, one per destination view, that project the checked-in declarations and are verified for freshness by the DNS offline check. The DNS linter, both destination pages, the apex site, the skills projection, and the repository quality suite pass, and the whole repository builds.
OpenSpec-Change: projects/alwaldend.com/openspec/changes/consolidate-project-landings-into-apex
LLM-disclaimer: This commit was generated by an LLM.
-
Manage forge resources with hermetic Terraform rules
Centralize organization, repository, and named access configuration in infra/repos. Adopt existing GitHub resources, protect master defaults while retaining Pages publication on pages, and preserve existing repository identities. Manage GitLab one-time imports, the F-Droid metadata fork, and default-branch protections through Vault-backed authentication. Forgejo consumes the same catalog. Ongoing repository synchronization is deferred.
Retire the eleven Bazel rule landing sites through their owning Terraform workflows, removing their DNS records, Pages repositories, and landing configuration. Move all twelve existing standalone rule modules into tools/ and retain their public interfaces and documentation on the main site.
Add tools/rules_terraform with verified provider downloads, packed mirrors in runfiles, and reusable Terraform execution rules. Enforce one version per provider source at an extensible resolution boundary. Migrate every Terraform consumer to thirteen shared provider pins in third_party/terraform. Execution and command maps belong to rules_terraform; consumers explicitly select generic AL wrappers for authentication and Vault injection. Remove tools/terraform and all 43 checked-in Terraform provider locks. Validate installed providers against the declared archives before execution.
Validation covers all fourteen workspace builds, all thirteen standalone test suites, Terraform consumers, offline real-provider regressions, rendered documentation, formatting, and semantic lint. The full root test run has 295 passing tests and one skip; its only failure is the historical secret scan, reduced to four pre-existing synthetic fixture matches. Earlier live imports and the exact landing retirement scope have verified postconditions; the Terraform rules migration uses only offline implementation checks.
OpenSpec-Change: infra/repos/openspec/changes/archive/2026-09-13-adopt-shared-repository-catalog OpenSpec-Change: infra/src/openspec/changes/archive/2026-09-13-retire-bazel-rule-landings OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-add-hermetic-terraform-rules OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-correct-terraform-ownership
LLM-disclaimer: This commit was generated by an LLM.
-
Deploy project DNS through Terraform modules
Move DNS ownership into each project’s Terraform state using shared modules. Load dnsconfig.json files at runtime, reject conflicting domain ownership, and render their records as a table. Add missing project AppRoles and scoped DNS policies, and document grouping related Terraform resources in modules.
Deploy all 45 owners sequentially: adopt 155 existing records and create 13 missing OpenHands records. Preserve every pre-existing provider record and verify no-op follow-up plans and DNS answers. Add DNS-scoped plan/show/apply wrappers with a saved-plan guard for roots that also manage services. Allow bounded aggregate path inventories large enough to deliver this migration while retaining truncation refusal in the delivery tool.
Validate runtime ownership, provider imports and preservation with isolated fixtures, Terraform formatting, wrapper builds, repository quality checks, semantic lint, and project documentation/specification builds.
OpenSpec-Change: infra/dns/openspec/changes/archive/2026-09-13-migrate-project-dns-to-terraform
LLM-disclaimer: This commit was generated by an LLM.
-
Simplify OpenSpec workspace globs
Collapse OpenSpec source globs to specs and changes, drop redundant package visibility blocks already covered by REPO.bazel, and regenerate the affected catalogs.
LLM-disclaimer: This commit was generated by an LLM.
-
Publish project sites and reproducible infrastructure diagrams
Build and deploy all 30 remaining project sites with the standard Docsy header, project descriptions and a linked documentation directory. Omit the repeated page title and generated language heading. Remove the unused cgit and xray_manager projects and retire their site resources.
Add a repeatable GitHub Pages publisher, staged Terraform bootstrap and direct GitHub Pages DNS records. Preserve repeated publication when pages is the remote default branch, and include Rules ISO in the main documentation. Document site onboarding in a registered, validated skill. Keep AL introduction short with useful links and preserve its lifecycle details in a dedicated documentation page.
Render all 15 existing infrastructure Drawio pages with pinned Drawio and Chrome inputs, sandboxed export actions, an update target and freshness checks, and include the maintained diagrams in infra/arch documentation. Paint an opaque white canvas to preserve readability in dark themes.
Validation covers project and apex builds, rendered pages, publisher tests, diagram repeatability and freshness, DNS configuration, Terraform formatting, semantic lint and repository quality.
Goal-Ref: build-and-deploy-every-project-landing-page-a782b800 Attempt-ID: attempt-00941092c164
LLM-disclaimer: This commit was generated by an LLM.
-
Extract DNSControl setup into rules_dnscontrol
Extract the DNSControl setup into
rules_dnscontrol, generate its Bazel dependency bundle from project-owned record files, and update the DNS guidance. Move Hugo rules and the worker to role-based package paths, and give each non-nested project a locally owned Hugo landing target that reuses the shared README-to-landing macro.Clean all landing and Pages DNS records so GitHub Pages serves each project subdomain directly without Cloudflare proxying. Improve the main site with a three-panel home layout, complete project links, documentation explore links, and current deployment guidance.
All affected root-workspace landing, DNS, and site targets pass, along with the nested
rules_hugotests, Buildifier, and repository quality checks.LLM-disclaimer: This commit was generated by an LLM.
-
Add hermetic repository-wide formatting and linting
Integrate upstream formatters for the repository’s meaningful tracked source and configuration file types through Bazel, and add Buildifier, Ruff, and ShellCheck lint aspects for correctness-oriented repository-wide checks.
Pin all new external tools through Bzlmod or the existing pnpm lock, add thin cache/runfiles adapters where required, expose format and check targets, and wire the checks into the pre-commit workflow. Format the existing tree and fix the correctness defects uncovered by the new checks. Preserve generated sources and exact-content fixtures that are not safely rewritable, and clarify that ordinary infrastructure build output is safe to display.
Validation:
- all 21 repository quality and compatibility formatter tests pass
- Buildifier test passes
- lint aspects analyze all 4,629 ordinary root targets without findings
- the complete 18-command root and nested full-repository audit was exercised; remaining failures are documented environment or pre-existing test limits
LLM-disclaimer: This commit was generated by an LLM.
-
Add standalone documentation rules
Move docs_filegroup into a reusable rules_docs nested Bzlmod workspace and migrate every root and nested consumer to it. Add a module-aware Gazelle language that creates docs targets only for existing README packages while preserving manual mappings.
Wire the workspace into module resolution, documentation aggregation, and the ten-command full-repo-check. Add the bazel-nested-module skill so future nested workspaces follow the repository’s rc, lockfile, docs, toolchain, Gazelle, and validation conventions.
Keep reviewed Gazelle dependency canonicalization, while protecting the hand-maintained Go proto, Python resource, Android, embedded-site, and skill runner definitions that generic language plugins would otherwise break.
This commit was generated by an LLM.
-
Fix remaining repository build failures
This commit was generated by an LLM.
-
Migrate documentation packaging to docs_filegroup
Preserve custom prefixes, renames, strip prefixes, and standalone workspace behavior.\n\nThis commit was generated by an LLM.
- Remove //tools/docs, remove .github
- Add build_test tests
- Fix infinitime python deps, bump python version
- Move all the logig out of the screen to the controller
- Add deploy to dockerhub, add //tools/oras
- Add missing features to the Pomodoro app, update project readmes, add github pages
- Move all remaining code to main
- Move a portion of tool code to main
- Use separate lock files for each golang tool
- Add release_page generation, remove redundant release templates
- Allow docs to put content outside of docs, refactor git to just use .git directly
- Add cross-compilation, move leetcode downloader contracts out of //contracts
- Refactor release templates into partials, add release cards
- Write release tool in go, start adding it to projects, add py proto generation
- Add release rules, add gzip rules, add several other tools, remove autoscrool deps from the root
- Flatten third_party, split tools/bzl a bit
- Add more taxonomies, remove docs tree, move alwaldend.com to projects
- Remove bazel target docs, add tools/docs, tag projects properly
- Remove changelogs, ignore irrelevant directories in docs
- Remove patch tree, remove py tree
- Initial commit
-
Add spellcheck skill
This commit was generated by an LLM.
-
Restore light and dark site canvases and set the shared accent
The shared Docsy canvas set the same Bootstrap dark palette and the same black page background on
:root,[data-bs-theme="light"], and[data-bs-theme="dark"], so the light/dark toggle changed nothing. The site also rendered Bootstrap’s stock blue instead of its intended accent.Split the shared palette so light mode uses a pure white canvas with the light-mode palette and dark mode uses a pure black canvas with the dark-mode palette, and keep the pre-stylesheet paint and footer on the active mode. Assign
$primaryto#7c3aedbefore Bootstrap compiles, so links, buttons, badges, focus rings, and the dark-mode link tint all derive from one value rather than from a site-local copy.Both files stay in the reusable shell; the apex site consumes them through the existing declared exports and no longer carries the footer’s own blue.
OpenSpec-Change: projects/hugo_landing/openspec/changes/restore-light-dark-canvas-and-accent
LLM-disclaimer: This commit was generated by an LLM.
1.8 - Bazel agent
bazel_agent is the repository Bazel entry point for agents. It keeps the
Bazel invocation behind a validated subcommand while consistently applying the
agent configuration:
bazel_agent bazel test //path/to/package:all
->
bazel test --config=agent //path/to/package:all
bazel is the only Bazel entry point, and it is a validated subcommand. The
runner accepts a known Bazel command after the bazel keyword, rejects
arbitrary leading arguments, and places --config=agent after the command.
Targets, command options, and arguments after the -- separator of a
bazel run invocation pass through unchanged. Later options therefore retain
Bazel’s normal precedence and can override settings supplied by the agent
configuration. The runner resolves bazel from PATH and replaces itself
with that process, so signals and the final exit status are not mediated by
another wrapper process. Uses of the persistent Bazel server follow the host
Codex network policy; the host-bot profile allows loopback so the
client-server connection is not blocked.
The runner does not create or inject a host temporary directory. Bazel actions
use declared outputs and Bazel-managed temporary storage, and tests use their
test temporary-directory contract. Repository-updating host tools that need
scratch must accept or derive an explicit task/run path under out/<task>/
instead of relying on ambient TMPDIR, TMP, or TEMP values propagated to
the whole build.
bazel_agent doctor --workspace-root PATH --task-scratch out/<task>/<run> is
a read-only, bounded JSON diagnostic. It reports runner and built-source
identity, Bazelisk pins, platform, rc/profile composition, task scratch
classification, and stale host-install state without dumping the environment.
Installation
Bootstrap the host installation with the underlying Bazel command:
bazel run --config=agent //projects/bazel_agent:install
Once installed, update it with:
bazel_agent bazel run //projects/bazel_agent:install
The install target atomically replaces ~/.local/bin/bazel_agent. After every
code update to this project, rerun the install target; the installed binary is
not updated automatically.
1.9 - Ci platform
An abandoned continuous integration platform with a Go backend and a Vue single-page frontend. The source retains its job, pipeline, and project management components.
Links
Features
- Clean architecture
- Backend: Golang, Gorm, Fiber, Hcl, Postgresql
- Frontend: SPA, VueJS with PrimeVue
Arch
Layout
ci_platform
├── api [Interface Adapters]
│ ├── controller
│ ├── middleware
│ └── presenter
├── cmd (CLI interface)
├── docs (OpenAPI Specification and other documentation)
│ └── diagrams
├── entity [Enterprise Business Rules]
├── infrastructure [Frameworks and Drivers]
│ ├── access
│ ├── branch
│ ├── config
│ ├── job
│ ├── jwt
│ ├── lifecycle
│ ├── pipeline
│ ├── pool
│ ├── project
│ ├── schedule
│ ├── session
│ └── user
├── pkg (Support packages)
│ └── error
└── usecase [Application Business Rules]
│ ├── access
│ ├── branch
│ ├── job
│ ├── jwt
│ ├── lifecycle
│ ├── pipeline
│ ├── pool
│ ├── project
│ ├── schedule
│ ├── session
│ └── user
└── web (Web interface)
Resources
-
architecture
- https://gitlab.com/redhatdemocentral/portfolio-architecture-examples https://redhatdemocentral.gitlab.io/portfolio-architecture-tooling/index.html?#/portfolio-architecture-examples/projects/retail-data-framework.drawio
- https://medium.com/wesionary-team/a-clean-architecture-for-web-application-in-go-lang-4b802dd130bb
- https://8thlight.com/blog/uncle-bob/2012/08/13/the-clean-architecture.html
- https://eltonminetto.dev/en/post/2020-07-06-clean-architecture-2years-later/
- https://manakuro.medium.com/clean-architecture-with-go-bce409427d31
- https://github.com/eminetto/clean-architecture-go
- https://eltonminetto.dev/en/post/2018-03-05-clean-architecture-using-go/
- https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html
- https://proandroiddev.com/why-you-need-use-cases-interactors-142e8a6fe576
- https://itnext.io/golang-and-clean-architecture-19ae9aae5683
- https://hackernoon.com/golang-clean-archithecture-efd6d7c43047
-
golang
- https://www.rudderstack.com/blog/implementing-graceful-shutdown-in-go
- https://github.com/gofiber/recipes
- https://ldej.nl/post/generating-swagger-docs-from-go/
- https://github.com/hashicorp/hcl
- https://github.com/gothinkster/golang-gin-realworld-example-app
- https://github.com/alpody/golang-fiber-realworld-example-app
- https://dev.to/aryaprakasa/serving-single-page-application-in-a-single-binary-file-with-go-12ij
- https://codesahara.com/blog/golang-job-queue-with-redis-streams/
- https://gorm.io/
- https://docs.gofiber.io/
- https://github.com/thomasvvugt/fiber-boilerplate
- https://github.com/ansible-semaphore/semaphore
- https://github.com/spf13/cobra
- https://github.com/spf13/viper
-
security
-
frontend
1.9.1 - Releases
head
-
Move project landings into the main site
Publish every registered project’s visitor-facing landing page at /projects/
/ from the main site instead of a dedicated subdomain, and retire the per-project Pages repository, CNAME, and Terraform DNS stage that existed only to serve one page derived from the project README. Each project owns its landing content in projects/
/site/content/ as pure content: no layouts, styles, or build rules. The main site packages those directories into content/projects/ / from the registry in projects/projects.bzl, so membership is declared once. The landing is a short hand-written page for visitors while the README keeps its /docs/projects/ / URL for repository reference documentation, and landing front matter now feeds the statuses, languages, and tags taxonomies. Merge the reusable hugo_landing project into the main site: its shared canvas and accent styles and its landing page rules move into the apex tree, and its landing macro, generated configuration, standalone publisher, and repository-relative rewrite layouts are removed. The theme keeps owning the taxonomy and term layouts, which are richer than the heading-only versions the reusable project carried. Remove the now-unused apex deploy_project.sh and deploy_all.sh landing publishers with it.
Retire the per-project publication and DNS ownership: the project landing targets and the landing deployment command, each landing project’s dnsconfig.json and Terraform root, the build plumbing that served only those stages, and the landing repository and Pages membership in the repository catalog. The apex Terraform root is retained because it also declares VM resources, and no Vault configuration is changed.
Replace the provider-snapshot zone files with generated declaration pages, one per destination view, that project the checked-in declarations and are verified for freshness by the DNS offline check. The DNS linter, both destination pages, the apex site, the skills projection, and the repository quality suite pass, and the whole repository builds.
OpenSpec-Change: projects/alwaldend.com/openspec/changes/consolidate-project-landings-into-apex
LLM-disclaimer: This commit was generated by an LLM.
-
Manage forge resources with hermetic Terraform rules
Centralize organization, repository, and named access configuration in infra/repos. Adopt existing GitHub resources, protect master defaults while retaining Pages publication on pages, and preserve existing repository identities. Manage GitLab one-time imports, the F-Droid metadata fork, and default-branch protections through Vault-backed authentication. Forgejo consumes the same catalog. Ongoing repository synchronization is deferred.
Retire the eleven Bazel rule landing sites through their owning Terraform workflows, removing their DNS records, Pages repositories, and landing configuration. Move all twelve existing standalone rule modules into tools/ and retain their public interfaces and documentation on the main site.
Add tools/rules_terraform with verified provider downloads, packed mirrors in runfiles, and reusable Terraform execution rules. Enforce one version per provider source at an extensible resolution boundary. Migrate every Terraform consumer to thirteen shared provider pins in third_party/terraform. Execution and command maps belong to rules_terraform; consumers explicitly select generic AL wrappers for authentication and Vault injection. Remove tools/terraform and all 43 checked-in Terraform provider locks. Validate installed providers against the declared archives before execution.
Validation covers all fourteen workspace builds, all thirteen standalone test suites, Terraform consumers, offline real-provider regressions, rendered documentation, formatting, and semantic lint. The full root test run has 295 passing tests and one skip; its only failure is the historical secret scan, reduced to four pre-existing synthetic fixture matches. Earlier live imports and the exact landing retirement scope have verified postconditions; the Terraform rules migration uses only offline implementation checks.
OpenSpec-Change: infra/repos/openspec/changes/archive/2026-09-13-adopt-shared-repository-catalog OpenSpec-Change: infra/src/openspec/changes/archive/2026-09-13-retire-bazel-rule-landings OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-add-hermetic-terraform-rules OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-correct-terraform-ownership
LLM-disclaimer: This commit was generated by an LLM.
-
Deploy project DNS through Terraform modules
Move DNS ownership into each project’s Terraform state using shared modules. Load dnsconfig.json files at runtime, reject conflicting domain ownership, and render their records as a table. Add missing project AppRoles and scoped DNS policies, and document grouping related Terraform resources in modules.
Deploy all 45 owners sequentially: adopt 155 existing records and create 13 missing OpenHands records. Preserve every pre-existing provider record and verify no-op follow-up plans and DNS answers. Add DNS-scoped plan/show/apply wrappers with a saved-plan guard for roots that also manage services. Allow bounded aggregate path inventories large enough to deliver this migration while retaining truncation refusal in the delivery tool.
Validate runtime ownership, provider imports and preservation with isolated fixtures, Terraform formatting, wrapper builds, repository quality checks, semantic lint, and project documentation/specification builds.
OpenSpec-Change: infra/dns/openspec/changes/archive/2026-09-13-migrate-project-dns-to-terraform
LLM-disclaimer: This commit was generated by an LLM.
-
Simplify OpenSpec workspace globs
Collapse OpenSpec source globs to specs and changes, drop redundant package visibility blocks already covered by REPO.bazel, and regenerate the affected catalogs.
LLM-disclaimer: This commit was generated by an LLM.
-
Publish project sites and reproducible infrastructure diagrams
Build and deploy all 30 remaining project sites with the standard Docsy header, project descriptions and a linked documentation directory. Omit the repeated page title and generated language heading. Remove the unused cgit and xray_manager projects and retire their site resources.
Add a repeatable GitHub Pages publisher, staged Terraform bootstrap and direct GitHub Pages DNS records. Preserve repeated publication when pages is the remote default branch, and include Rules ISO in the main documentation. Document site onboarding in a registered, validated skill. Keep AL introduction short with useful links and preserve its lifecycle details in a dedicated documentation page.
Render all 15 existing infrastructure Drawio pages with pinned Drawio and Chrome inputs, sandboxed export actions, an update target and freshness checks, and include the maintained diagrams in infra/arch documentation. Paint an opaque white canvas to preserve readability in dark themes.
Validation covers project and apex builds, rendered pages, publisher tests, diagram repeatability and freshness, DNS configuration, Terraform formatting, semantic lint and repository quality.
Goal-Ref: build-and-deploy-every-project-landing-page-a782b800 Attempt-ID: attempt-00941092c164
LLM-disclaimer: This commit was generated by an LLM.
-
Extract DNSControl setup into rules_dnscontrol
Extract the DNSControl setup into
rules_dnscontrol, generate its Bazel dependency bundle from project-owned record files, and update the DNS guidance. Move Hugo rules and the worker to role-based package paths, and give each non-nested project a locally owned Hugo landing target that reuses the shared README-to-landing macro.Clean all landing and Pages DNS records so GitHub Pages serves each project subdomain directly without Cloudflare proxying. Improve the main site with a three-panel home layout, complete project links, documentation explore links, and current deployment guidance.
All affected root-workspace landing, DNS, and site targets pass, along with the nested
rules_hugotests, Buildifier, and repository quality checks.LLM-disclaimer: This commit was generated by an LLM.
-
Add hermetic repository-wide formatting and linting
Integrate upstream formatters for the repository’s meaningful tracked source and configuration file types through Bazel, and add Buildifier, Ruff, and ShellCheck lint aspects for correctness-oriented repository-wide checks.
Pin all new external tools through Bzlmod or the existing pnpm lock, add thin cache/runfiles adapters where required, expose format and check targets, and wire the checks into the pre-commit workflow. Format the existing tree and fix the correctness defects uncovered by the new checks. Preserve generated sources and exact-content fixtures that are not safely rewritable, and clarify that ordinary infrastructure build output is safe to display.
Validation:
- all 21 repository quality and compatibility formatter tests pass
- Buildifier test passes
- lint aspects analyze all 4,629 ordinary root targets without findings
- the complete 18-command root and nested full-repository audit was exercised; remaining failures are documented environment or pre-existing test limits
LLM-disclaimer: This commit was generated by an LLM.
-
Add standalone documentation rules
Move docs_filegroup into a reusable rules_docs nested Bzlmod workspace and migrate every root and nested consumer to it. Add a module-aware Gazelle language that creates docs targets only for existing README packages while preserving manual mappings.
Wire the workspace into module resolution, documentation aggregation, and the ten-command full-repo-check. Add the bazel-nested-module skill so future nested workspaces follow the repository’s rc, lockfile, docs, toolchain, Gazelle, and validation conventions.
Keep reviewed Gazelle dependency canonicalization, while protecting the hand-maintained Go proto, Python resource, Android, embedded-site, and skill runner definitions that generic language plugins would otherwise break.
This commit was generated by an LLM.
-
Migrate documentation packaging to docs_filegroup
Preserve custom prefixes, renames, strip prefixes, and standalone workspace behavior.\n\nThis commit was generated by an LLM.
- Add uncommitted ci_platform code
- Remove //tools/docs, remove .github
- Add build_test to ci_platform, update leetcode
- Migrate go code of ci_platform
- Add missing features to the Pomodoro app, update project readmes, add github pages
- Move all remaining code to main
- Add label_link shortcode, add todo page
- Initial commit
-
Add spellcheck skill
This commit was generated by an LLM.
-
Restore light and dark site canvases and set the shared accent
The shared Docsy canvas set the same Bootstrap dark palette and the same black page background on
:root,[data-bs-theme="light"], and[data-bs-theme="dark"], so the light/dark toggle changed nothing. The site also rendered Bootstrap’s stock blue instead of its intended accent.Split the shared palette so light mode uses a pure white canvas with the light-mode palette and dark mode uses a pure black canvas with the dark-mode palette, and keep the pre-stylesheet paint and footer on the active mode. Assign
$primaryto#7c3aedbefore Bootstrap compiles, so links, buttons, badges, focus rings, and the dark-mode link tint all derive from one value rather than from a site-local copy.Both files stay in the reusable shell; the apex site consumes them through the existing declared exports and no longer carries the footer’s own blue.
OpenSpec-Change: projects/hugo_landing/openspec/changes/restore-light-dark-canvas-and-accent
LLM-disclaimer: This commit was generated by an LLM.
1.9.1.1 - head
-
Move project landings into the main site
Publish every registered project’s visitor-facing landing page at /projects/
/ from the main site instead of a dedicated subdomain, and retire the per-project Pages repository, CNAME, and Terraform DNS stage that existed only to serve one page derived from the project README. Each project owns its landing content in projects/
/site/content/ as pure content: no layouts, styles, or build rules. The main site packages those directories into content/projects/ / from the registry in projects/projects.bzl, so membership is declared once. The landing is a short hand-written page for visitors while the README keeps its /docs/projects/ / URL for repository reference documentation, and landing front matter now feeds the statuses, languages, and tags taxonomies. Merge the reusable hugo_landing project into the main site: its shared canvas and accent styles and its landing page rules move into the apex tree, and its landing macro, generated configuration, standalone publisher, and repository-relative rewrite layouts are removed. The theme keeps owning the taxonomy and term layouts, which are richer than the heading-only versions the reusable project carried. Remove the now-unused apex deploy_project.sh and deploy_all.sh landing publishers with it.
Retire the per-project publication and DNS ownership: the project landing targets and the landing deployment command, each landing project’s dnsconfig.json and Terraform root, the build plumbing that served only those stages, and the landing repository and Pages membership in the repository catalog. The apex Terraform root is retained because it also declares VM resources, and no Vault configuration is changed.
Replace the provider-snapshot zone files with generated declaration pages, one per destination view, that project the checked-in declarations and are verified for freshness by the DNS offline check. The DNS linter, both destination pages, the apex site, the skills projection, and the repository quality suite pass, and the whole repository builds.
OpenSpec-Change: projects/alwaldend.com/openspec/changes/consolidate-project-landings-into-apex
LLM-disclaimer: This commit was generated by an LLM.
-
Manage forge resources with hermetic Terraform rules
Centralize organization, repository, and named access configuration in infra/repos. Adopt existing GitHub resources, protect master defaults while retaining Pages publication on pages, and preserve existing repository identities. Manage GitLab one-time imports, the F-Droid metadata fork, and default-branch protections through Vault-backed authentication. Forgejo consumes the same catalog. Ongoing repository synchronization is deferred.
Retire the eleven Bazel rule landing sites through their owning Terraform workflows, removing their DNS records, Pages repositories, and landing configuration. Move all twelve existing standalone rule modules into tools/ and retain their public interfaces and documentation on the main site.
Add tools/rules_terraform with verified provider downloads, packed mirrors in runfiles, and reusable Terraform execution rules. Enforce one version per provider source at an extensible resolution boundary. Migrate every Terraform consumer to thirteen shared provider pins in third_party/terraform. Execution and command maps belong to rules_terraform; consumers explicitly select generic AL wrappers for authentication and Vault injection. Remove tools/terraform and all 43 checked-in Terraform provider locks. Validate installed providers against the declared archives before execution.
Validation covers all fourteen workspace builds, all thirteen standalone test suites, Terraform consumers, offline real-provider regressions, rendered documentation, formatting, and semantic lint. The full root test run has 295 passing tests and one skip; its only failure is the historical secret scan, reduced to four pre-existing synthetic fixture matches. Earlier live imports and the exact landing retirement scope have verified postconditions; the Terraform rules migration uses only offline implementation checks.
OpenSpec-Change: infra/repos/openspec/changes/archive/2026-09-13-adopt-shared-repository-catalog OpenSpec-Change: infra/src/openspec/changes/archive/2026-09-13-retire-bazel-rule-landings OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-add-hermetic-terraform-rules OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-correct-terraform-ownership
LLM-disclaimer: This commit was generated by an LLM.
-
Deploy project DNS through Terraform modules
Move DNS ownership into each project’s Terraform state using shared modules. Load dnsconfig.json files at runtime, reject conflicting domain ownership, and render their records as a table. Add missing project AppRoles and scoped DNS policies, and document grouping related Terraform resources in modules.
Deploy all 45 owners sequentially: adopt 155 existing records and create 13 missing OpenHands records. Preserve every pre-existing provider record and verify no-op follow-up plans and DNS answers. Add DNS-scoped plan/show/apply wrappers with a saved-plan guard for roots that also manage services. Allow bounded aggregate path inventories large enough to deliver this migration while retaining truncation refusal in the delivery tool.
Validate runtime ownership, provider imports and preservation with isolated fixtures, Terraform formatting, wrapper builds, repository quality checks, semantic lint, and project documentation/specification builds.
OpenSpec-Change: infra/dns/openspec/changes/archive/2026-09-13-migrate-project-dns-to-terraform
LLM-disclaimer: This commit was generated by an LLM.
-
Simplify OpenSpec workspace globs
Collapse OpenSpec source globs to specs and changes, drop redundant package visibility blocks already covered by REPO.bazel, and regenerate the affected catalogs.
LLM-disclaimer: This commit was generated by an LLM.
-
Publish project sites and reproducible infrastructure diagrams
Build and deploy all 30 remaining project sites with the standard Docsy header, project descriptions and a linked documentation directory. Omit the repeated page title and generated language heading. Remove the unused cgit and xray_manager projects and retire their site resources.
Add a repeatable GitHub Pages publisher, staged Terraform bootstrap and direct GitHub Pages DNS records. Preserve repeated publication when pages is the remote default branch, and include Rules ISO in the main documentation. Document site onboarding in a registered, validated skill. Keep AL introduction short with useful links and preserve its lifecycle details in a dedicated documentation page.
Render all 15 existing infrastructure Drawio pages with pinned Drawio and Chrome inputs, sandboxed export actions, an update target and freshness checks, and include the maintained diagrams in infra/arch documentation. Paint an opaque white canvas to preserve readability in dark themes.
Validation covers project and apex builds, rendered pages, publisher tests, diagram repeatability and freshness, DNS configuration, Terraform formatting, semantic lint and repository quality.
Goal-Ref: build-and-deploy-every-project-landing-page-a782b800 Attempt-ID: attempt-00941092c164
LLM-disclaimer: This commit was generated by an LLM.
-
Extract DNSControl setup into rules_dnscontrol
Extract the DNSControl setup into
rules_dnscontrol, generate its Bazel dependency bundle from project-owned record files, and update the DNS guidance. Move Hugo rules and the worker to role-based package paths, and give each non-nested project a locally owned Hugo landing target that reuses the shared README-to-landing macro.Clean all landing and Pages DNS records so GitHub Pages serves each project subdomain directly without Cloudflare proxying. Improve the main site with a three-panel home layout, complete project links, documentation explore links, and current deployment guidance.
All affected root-workspace landing, DNS, and site targets pass, along with the nested
rules_hugotests, Buildifier, and repository quality checks.LLM-disclaimer: This commit was generated by an LLM.
-
Add hermetic repository-wide formatting and linting
Integrate upstream formatters for the repository’s meaningful tracked source and configuration file types through Bazel, and add Buildifier, Ruff, and ShellCheck lint aspects for correctness-oriented repository-wide checks.
Pin all new external tools through Bzlmod or the existing pnpm lock, add thin cache/runfiles adapters where required, expose format and check targets, and wire the checks into the pre-commit workflow. Format the existing tree and fix the correctness defects uncovered by the new checks. Preserve generated sources and exact-content fixtures that are not safely rewritable, and clarify that ordinary infrastructure build output is safe to display.
Validation:
- all 21 repository quality and compatibility formatter tests pass
- Buildifier test passes
- lint aspects analyze all 4,629 ordinary root targets without findings
- the complete 18-command root and nested full-repository audit was exercised; remaining failures are documented environment or pre-existing test limits
LLM-disclaimer: This commit was generated by an LLM.
-
Add standalone documentation rules
Move docs_filegroup into a reusable rules_docs nested Bzlmod workspace and migrate every root and nested consumer to it. Add a module-aware Gazelle language that creates docs targets only for existing README packages while preserving manual mappings.
Wire the workspace into module resolution, documentation aggregation, and the ten-command full-repo-check. Add the bazel-nested-module skill so future nested workspaces follow the repository’s rc, lockfile, docs, toolchain, Gazelle, and validation conventions.
Keep reviewed Gazelle dependency canonicalization, while protecting the hand-maintained Go proto, Python resource, Android, embedded-site, and skill runner definitions that generic language plugins would otherwise break.
This commit was generated by an LLM.
-
Migrate documentation packaging to docs_filegroup
Preserve custom prefixes, renames, strip prefixes, and standalone workspace behavior.\n\nThis commit was generated by an LLM.
- Add uncommitted ci_platform code
- Remove //tools/docs, remove .github
- Add build_test to ci_platform, update leetcode
- Migrate go code of ci_platform
- Add missing features to the Pomodoro app, update project readmes, add github pages
- Move all remaining code to main
- Add label_link shortcode, add todo page
- Initial commit
-
Add spellcheck skill
This commit was generated by an LLM.
-
Restore light and dark site canvases and set the shared accent
The shared Docsy canvas set the same Bootstrap dark palette and the same black page background on
:root,[data-bs-theme="light"], and[data-bs-theme="dark"], so the light/dark toggle changed nothing. The site also rendered Bootstrap’s stock blue instead of its intended accent.Split the shared palette so light mode uses a pure white canvas with the light-mode palette and dark mode uses a pure black canvas with the dark-mode palette, and keep the pre-stylesheet paint and footer on the active mode. Assign
$primaryto#7c3aedbefore Bootstrap compiles, so links, buttons, badges, focus rings, and the dark-mode link tint all derive from one value rather than from a site-local copy.Both files stay in the reusable shell; the apex site consumes them through the existing declared exports and no longer carries the footer’s own blue.
OpenSpec-Change: projects/hugo_landing/openspec/changes/restore-light-dark-canvas-and-accent
LLM-disclaimer: This commit was generated by an LLM.
1.10 - Dotfiles
This project packages personal configuration files into an installable archive. Make and Bazel entry points compare the packaged files with the local system and install selected configurations.
Links
Features
- Archive with dotfiles that can be installed using make
Bazel usage
bazel run //projects/dotfiles:help # Show help
bazel run //projects/dotfiles:diff # Show diff
bazel run //projects/dotfiles:install # Install files
Archive usage
oras pull --output "${PWD}" docker.io/alwaldend/src:projects_dotfiles_dotfiles_tar_head
cd releases/projects/dotfiles/head/files
tar -xf dotfiles.tar
cd dotfiles
make help # Show help
make diff # Check diff between system files and those from the archive
make diff/nvim # Check diff for all nvim files
make diff/nvim/.config/nvim/lazy-lock.json # Diff specific file
make install # Install all files from the archive
make install/nvim # Install nvim files
make install/nvim/.config/nvim/lazy-lock.json # Install a specific file
Help
help: Show help
install: Install files from the archive
diff: Show diff between archive files and system files
install/bin: Install bin files
diff/bin: Diff bin files
install/home: Install home files
diff/home: Diff home files
install/nvim: Install nvim files
diff/nvim: Diff nvim files
make: Nothing to be done for 'help'.
1.10.1 - Releases
head
-
Move project landings into the main site
Publish every registered project’s visitor-facing landing page at /projects/
/ from the main site instead of a dedicated subdomain, and retire the per-project Pages repository, CNAME, and Terraform DNS stage that existed only to serve one page derived from the project README. Each project owns its landing content in projects/
/site/content/ as pure content: no layouts, styles, or build rules. The main site packages those directories into content/projects/ / from the registry in projects/projects.bzl, so membership is declared once. The landing is a short hand-written page for visitors while the README keeps its /docs/projects/ / URL for repository reference documentation, and landing front matter now feeds the statuses, languages, and tags taxonomies. Merge the reusable hugo_landing project into the main site: its shared canvas and accent styles and its landing page rules move into the apex tree, and its landing macro, generated configuration, standalone publisher, and repository-relative rewrite layouts are removed. The theme keeps owning the taxonomy and term layouts, which are richer than the heading-only versions the reusable project carried. Remove the now-unused apex deploy_project.sh and deploy_all.sh landing publishers with it.
Retire the per-project publication and DNS ownership: the project landing targets and the landing deployment command, each landing project’s dnsconfig.json and Terraform root, the build plumbing that served only those stages, and the landing repository and Pages membership in the repository catalog. The apex Terraform root is retained because it also declares VM resources, and no Vault configuration is changed.
Replace the provider-snapshot zone files with generated declaration pages, one per destination view, that project the checked-in declarations and are verified for freshness by the DNS offline check. The DNS linter, both destination pages, the apex site, the skills projection, and the repository quality suite pass, and the whole repository builds.
OpenSpec-Change: projects/alwaldend.com/openspec/changes/consolidate-project-landings-into-apex
LLM-disclaimer: This commit was generated by an LLM.
-
Manage forge resources with hermetic Terraform rules
Centralize organization, repository, and named access configuration in infra/repos. Adopt existing GitHub resources, protect master defaults while retaining Pages publication on pages, and preserve existing repository identities. Manage GitLab one-time imports, the F-Droid metadata fork, and default-branch protections through Vault-backed authentication. Forgejo consumes the same catalog. Ongoing repository synchronization is deferred.
Retire the eleven Bazel rule landing sites through their owning Terraform workflows, removing their DNS records, Pages repositories, and landing configuration. Move all twelve existing standalone rule modules into tools/ and retain their public interfaces and documentation on the main site.
Add tools/rules_terraform with verified provider downloads, packed mirrors in runfiles, and reusable Terraform execution rules. Enforce one version per provider source at an extensible resolution boundary. Migrate every Terraform consumer to thirteen shared provider pins in third_party/terraform. Execution and command maps belong to rules_terraform; consumers explicitly select generic AL wrappers for authentication and Vault injection. Remove tools/terraform and all 43 checked-in Terraform provider locks. Validate installed providers against the declared archives before execution.
Validation covers all fourteen workspace builds, all thirteen standalone test suites, Terraform consumers, offline real-provider regressions, rendered documentation, formatting, and semantic lint. The full root test run has 295 passing tests and one skip; its only failure is the historical secret scan, reduced to four pre-existing synthetic fixture matches. Earlier live imports and the exact landing retirement scope have verified postconditions; the Terraform rules migration uses only offline implementation checks.
OpenSpec-Change: infra/repos/openspec/changes/archive/2026-09-13-adopt-shared-repository-catalog OpenSpec-Change: infra/src/openspec/changes/archive/2026-09-13-retire-bazel-rule-landings OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-add-hermetic-terraform-rules OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-correct-terraform-ownership
LLM-disclaimer: This commit was generated by an LLM.
-
Deploy project DNS through Terraform modules
Move DNS ownership into each project’s Terraform state using shared modules. Load dnsconfig.json files at runtime, reject conflicting domain ownership, and render their records as a table. Add missing project AppRoles and scoped DNS policies, and document grouping related Terraform resources in modules.
Deploy all 45 owners sequentially: adopt 155 existing records and create 13 missing OpenHands records. Preserve every pre-existing provider record and verify no-op follow-up plans and DNS answers. Add DNS-scoped plan/show/apply wrappers with a saved-plan guard for roots that also manage services. Allow bounded aggregate path inventories large enough to deliver this migration while retaining truncation refusal in the delivery tool.
Validate runtime ownership, provider imports and preservation with isolated fixtures, Terraform formatting, wrapper builds, repository quality checks, semantic lint, and project documentation/specification builds.
OpenSpec-Change: infra/dns/openspec/changes/archive/2026-09-13-migrate-project-dns-to-terraform
LLM-disclaimer: This commit was generated by an LLM.
-
Simplify OpenSpec workspace globs
Collapse OpenSpec source globs to specs and changes, drop redundant package visibility blocks already covered by REPO.bazel, and regenerate the affected catalogs.
LLM-disclaimer: This commit was generated by an LLM.
-
Publish project sites and reproducible infrastructure diagrams
Build and deploy all 30 remaining project sites with the standard Docsy header, project descriptions and a linked documentation directory. Omit the repeated page title and generated language heading. Remove the unused cgit and xray_manager projects and retire their site resources.
Add a repeatable GitHub Pages publisher, staged Terraform bootstrap and direct GitHub Pages DNS records. Preserve repeated publication when pages is the remote default branch, and include Rules ISO in the main documentation. Document site onboarding in a registered, validated skill. Keep AL introduction short with useful links and preserve its lifecycle details in a dedicated documentation page.
Render all 15 existing infrastructure Drawio pages with pinned Drawio and Chrome inputs, sandboxed export actions, an update target and freshness checks, and include the maintained diagrams in infra/arch documentation. Paint an opaque white canvas to preserve readability in dark themes.
Validation covers project and apex builds, rendered pages, publisher tests, diagram repeatability and freshness, DNS configuration, Terraform formatting, semantic lint and repository quality.
Goal-Ref: build-and-deploy-every-project-landing-page-a782b800 Attempt-ID: attempt-00941092c164
LLM-disclaimer: This commit was generated by an LLM.
-
Extract DNSControl setup into rules_dnscontrol
Extract the DNSControl setup into
rules_dnscontrol, generate its Bazel dependency bundle from project-owned record files, and update the DNS guidance. Move Hugo rules and the worker to role-based package paths, and give each non-nested project a locally owned Hugo landing target that reuses the shared README-to-landing macro.Clean all landing and Pages DNS records so GitHub Pages serves each project subdomain directly without Cloudflare proxying. Improve the main site with a three-panel home layout, complete project links, documentation explore links, and current deployment guidance.
All affected root-workspace landing, DNS, and site targets pass, along with the nested
rules_hugotests, Buildifier, and repository quality checks.LLM-disclaimer: This commit was generated by an LLM.
-
Add hermetic repository-wide formatting and linting
Integrate upstream formatters for the repository’s meaningful tracked source and configuration file types through Bazel, and add Buildifier, Ruff, and ShellCheck lint aspects for correctness-oriented repository-wide checks.
Pin all new external tools through Bzlmod or the existing pnpm lock, add thin cache/runfiles adapters where required, expose format and check targets, and wire the checks into the pre-commit workflow. Format the existing tree and fix the correctness defects uncovered by the new checks. Preserve generated sources and exact-content fixtures that are not safely rewritable, and clarify that ordinary infrastructure build output is safe to display.
Validation:
- all 21 repository quality and compatibility formatter tests pass
- Buildifier test passes
- lint aspects analyze all 4,629 ordinary root targets without findings
- the complete 18-command root and nested full-repository audit was exercised; remaining failures are documented environment or pre-existing test limits
LLM-disclaimer: This commit was generated by an LLM.
-
Add standalone documentation rules
Move docs_filegroup into a reusable rules_docs nested Bzlmod workspace and migrate every root and nested consumer to it. Add a module-aware Gazelle language that creates docs targets only for existing README packages while preserving manual mappings.
Wire the workspace into module resolution, documentation aggregation, and the ten-command full-repo-check. Add the bazel-nested-module skill so future nested workspaces follow the repository’s rc, lockfile, docs, toolchain, Gazelle, and validation conventions.
Keep reviewed Gazelle dependency canonicalization, while protecting the hand-maintained Go proto, Python resource, Android, embedded-site, and skill runner definitions that generic language plugins would otherwise break.
This commit was generated by an LLM.
-
Migrate documentation packaging to docs_filegroup
Preserve custom prefixes, renames, strip prefixes, and standalone workspace behavior.\n\nThis commit was generated by an LLM.
- Start setting up cloud resources
- Enable IdentitiesOnly for ssh
- Add ssh support to gpg, add the public key for the old pgp key
- Add new pgp key, rename //data/gpg to //data/pgp, add some info about ssh and pgp
- Remove //tools/docs, remove .github
- Add macos switch to the keyboard
- Update the setup guide, update android tools, update leetcode, update books
- Add qubes_os to dotfiles
- Add harper to neovim
- Add build_test tests
- Actualize udev rules
- Add middle mouse button to vial
- Move all the logig out of the screen to the controller
- Add deploy to dockerhub, add //tools/oras
- Add missing features to the Pomodoro app, update project readmes, add github pages
- Move all remaining code to main
- Move a portion of tool code to main
- Switch to a dark theme, add cname for rancher
- Fix release page rendering
- Fix lsp config, fix JAVA_HOME
- Move to a light nvim theme, add full git info to releases
- Add release_page generation, remove redundant release templates
- Add //tools/bazelrc, move to a bazelrc preset
- Fix nvim library paths
- Allow docs to put content outside of docs, refactor git to just use .git directly
- Add cross-compilation, move leetcode downloader contracts out of //contracts
- Refactor release templates into partials, add release cards
- Add RSS links, rewrite links shortcode to html, improve release tables
- Add file size to releases, add round_float partial
- Write release tool in go, start adding it to projects, add py proto generation
- Add release rules, add gzip rules, add several other tools, remove autoscrool deps from the root
- Refactor dev_shell into bzlenv, add deactivation, make it functional
- Add dev_shell rules, add make_install_binary, flatten sh rules, add dotfiles/bin
- Make functional make_install archive
- Add //tools/make_install, start moving dotfiles to it
- Add more taxonomies, remove docs tree, move alwaldend.com to projects
- Remove bazel target docs, add tools/docs, tag projects properly
- Remove cfg tree, add projects/dotfiles
- Initial commit
-
Add spellcheck skill
This commit was generated by an LLM.
-
Restore light and dark site canvases and set the shared accent
The shared Docsy canvas set the same Bootstrap dark palette and the same black page background on
:root,[data-bs-theme="light"], and[data-bs-theme="dark"], so the light/dark toggle changed nothing. The site also rendered Bootstrap’s stock blue instead of its intended accent.Split the shared palette so light mode uses a pure white canvas with the light-mode palette and dark mode uses a pure black canvas with the dark-mode palette, and keep the pre-stylesheet paint and footer on the active mode. Assign
$primaryto#7c3aedbefore Bootstrap compiles, so links, buttons, badges, focus rings, and the dark-mode link tint all derive from one value rather than from a site-local copy.Both files stay in the reusable shell; the apex site consumes them through the existing declared exports and no longer carries the footer’s own blue.
OpenSpec-Change: projects/hugo_landing/openspec/changes/restore-light-dark-canvas-and-accent
LLM-disclaimer: This commit was generated by an LLM.
1.10.1.1 - head
-
Move project landings into the main site
Publish every registered project’s visitor-facing landing page at /projects/
/ from the main site instead of a dedicated subdomain, and retire the per-project Pages repository, CNAME, and Terraform DNS stage that existed only to serve one page derived from the project README. Each project owns its landing content in projects/
/site/content/ as pure content: no layouts, styles, or build rules. The main site packages those directories into content/projects/ / from the registry in projects/projects.bzl, so membership is declared once. The landing is a short hand-written page for visitors while the README keeps its /docs/projects/ / URL for repository reference documentation, and landing front matter now feeds the statuses, languages, and tags taxonomies. Merge the reusable hugo_landing project into the main site: its shared canvas and accent styles and its landing page rules move into the apex tree, and its landing macro, generated configuration, standalone publisher, and repository-relative rewrite layouts are removed. The theme keeps owning the taxonomy and term layouts, which are richer than the heading-only versions the reusable project carried. Remove the now-unused apex deploy_project.sh and deploy_all.sh landing publishers with it.
Retire the per-project publication and DNS ownership: the project landing targets and the landing deployment command, each landing project’s dnsconfig.json and Terraform root, the build plumbing that served only those stages, and the landing repository and Pages membership in the repository catalog. The apex Terraform root is retained because it also declares VM resources, and no Vault configuration is changed.
Replace the provider-snapshot zone files with generated declaration pages, one per destination view, that project the checked-in declarations and are verified for freshness by the DNS offline check. The DNS linter, both destination pages, the apex site, the skills projection, and the repository quality suite pass, and the whole repository builds.
OpenSpec-Change: projects/alwaldend.com/openspec/changes/consolidate-project-landings-into-apex
LLM-disclaimer: This commit was generated by an LLM.
-
Manage forge resources with hermetic Terraform rules
Centralize organization, repository, and named access configuration in infra/repos. Adopt existing GitHub resources, protect master defaults while retaining Pages publication on pages, and preserve existing repository identities. Manage GitLab one-time imports, the F-Droid metadata fork, and default-branch protections through Vault-backed authentication. Forgejo consumes the same catalog. Ongoing repository synchronization is deferred.
Retire the eleven Bazel rule landing sites through their owning Terraform workflows, removing their DNS records, Pages repositories, and landing configuration. Move all twelve existing standalone rule modules into tools/ and retain their public interfaces and documentation on the main site.
Add tools/rules_terraform with verified provider downloads, packed mirrors in runfiles, and reusable Terraform execution rules. Enforce one version per provider source at an extensible resolution boundary. Migrate every Terraform consumer to thirteen shared provider pins in third_party/terraform. Execution and command maps belong to rules_terraform; consumers explicitly select generic AL wrappers for authentication and Vault injection. Remove tools/terraform and all 43 checked-in Terraform provider locks. Validate installed providers against the declared archives before execution.
Validation covers all fourteen workspace builds, all thirteen standalone test suites, Terraform consumers, offline real-provider regressions, rendered documentation, formatting, and semantic lint. The full root test run has 295 passing tests and one skip; its only failure is the historical secret scan, reduced to four pre-existing synthetic fixture matches. Earlier live imports and the exact landing retirement scope have verified postconditions; the Terraform rules migration uses only offline implementation checks.
OpenSpec-Change: infra/repos/openspec/changes/archive/2026-09-13-adopt-shared-repository-catalog OpenSpec-Change: infra/src/openspec/changes/archive/2026-09-13-retire-bazel-rule-landings OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-add-hermetic-terraform-rules OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-correct-terraform-ownership
LLM-disclaimer: This commit was generated by an LLM.
-
Deploy project DNS through Terraform modules
Move DNS ownership into each project’s Terraform state using shared modules. Load dnsconfig.json files at runtime, reject conflicting domain ownership, and render their records as a table. Add missing project AppRoles and scoped DNS policies, and document grouping related Terraform resources in modules.
Deploy all 45 owners sequentially: adopt 155 existing records and create 13 missing OpenHands records. Preserve every pre-existing provider record and verify no-op follow-up plans and DNS answers. Add DNS-scoped plan/show/apply wrappers with a saved-plan guard for roots that also manage services. Allow bounded aggregate path inventories large enough to deliver this migration while retaining truncation refusal in the delivery tool.
Validate runtime ownership, provider imports and preservation with isolated fixtures, Terraform formatting, wrapper builds, repository quality checks, semantic lint, and project documentation/specification builds.
OpenSpec-Change: infra/dns/openspec/changes/archive/2026-09-13-migrate-project-dns-to-terraform
LLM-disclaimer: This commit was generated by an LLM.
-
Simplify OpenSpec workspace globs
Collapse OpenSpec source globs to specs and changes, drop redundant package visibility blocks already covered by REPO.bazel, and regenerate the affected catalogs.
LLM-disclaimer: This commit was generated by an LLM.
-
Publish project sites and reproducible infrastructure diagrams
Build and deploy all 30 remaining project sites with the standard Docsy header, project descriptions and a linked documentation directory. Omit the repeated page title and generated language heading. Remove the unused cgit and xray_manager projects and retire their site resources.
Add a repeatable GitHub Pages publisher, staged Terraform bootstrap and direct GitHub Pages DNS records. Preserve repeated publication when pages is the remote default branch, and include Rules ISO in the main documentation. Document site onboarding in a registered, validated skill. Keep AL introduction short with useful links and preserve its lifecycle details in a dedicated documentation page.
Render all 15 existing infrastructure Drawio pages with pinned Drawio and Chrome inputs, sandboxed export actions, an update target and freshness checks, and include the maintained diagrams in infra/arch documentation. Paint an opaque white canvas to preserve readability in dark themes.
Validation covers project and apex builds, rendered pages, publisher tests, diagram repeatability and freshness, DNS configuration, Terraform formatting, semantic lint and repository quality.
Goal-Ref: build-and-deploy-every-project-landing-page-a782b800 Attempt-ID: attempt-00941092c164
LLM-disclaimer: This commit was generated by an LLM.
-
Extract DNSControl setup into rules_dnscontrol
Extract the DNSControl setup into
rules_dnscontrol, generate its Bazel dependency bundle from project-owned record files, and update the DNS guidance. Move Hugo rules and the worker to role-based package paths, and give each non-nested project a locally owned Hugo landing target that reuses the shared README-to-landing macro.Clean all landing and Pages DNS records so GitHub Pages serves each project subdomain directly without Cloudflare proxying. Improve the main site with a three-panel home layout, complete project links, documentation explore links, and current deployment guidance.
All affected root-workspace landing, DNS, and site targets pass, along with the nested
rules_hugotests, Buildifier, and repository quality checks.LLM-disclaimer: This commit was generated by an LLM.
-
Add hermetic repository-wide formatting and linting
Integrate upstream formatters for the repository’s meaningful tracked source and configuration file types through Bazel, and add Buildifier, Ruff, and ShellCheck lint aspects for correctness-oriented repository-wide checks.
Pin all new external tools through Bzlmod or the existing pnpm lock, add thin cache/runfiles adapters where required, expose format and check targets, and wire the checks into the pre-commit workflow. Format the existing tree and fix the correctness defects uncovered by the new checks. Preserve generated sources and exact-content fixtures that are not safely rewritable, and clarify that ordinary infrastructure build output is safe to display.
Validation:
- all 21 repository quality and compatibility formatter tests pass
- Buildifier test passes
- lint aspects analyze all 4,629 ordinary root targets without findings
- the complete 18-command root and nested full-repository audit was exercised; remaining failures are documented environment or pre-existing test limits
LLM-disclaimer: This commit was generated by an LLM.
-
Add standalone documentation rules
Move docs_filegroup into a reusable rules_docs nested Bzlmod workspace and migrate every root and nested consumer to it. Add a module-aware Gazelle language that creates docs targets only for existing README packages while preserving manual mappings.
Wire the workspace into module resolution, documentation aggregation, and the ten-command full-repo-check. Add the bazel-nested-module skill so future nested workspaces follow the repository’s rc, lockfile, docs, toolchain, Gazelle, and validation conventions.
Keep reviewed Gazelle dependency canonicalization, while protecting the hand-maintained Go proto, Python resource, Android, embedded-site, and skill runner definitions that generic language plugins would otherwise break.
This commit was generated by an LLM.
-
Migrate documentation packaging to docs_filegroup
Preserve custom prefixes, renames, strip prefixes, and standalone workspace behavior.\n\nThis commit was generated by an LLM.
- Start setting up cloud resources
- Enable IdentitiesOnly for ssh
- Add ssh support to gpg, add the public key for the old pgp key
- Add new pgp key, rename //data/gpg to //data/pgp, add some info about ssh and pgp
- Remove //tools/docs, remove .github
- Add macos switch to the keyboard
- Update the setup guide, update android tools, update leetcode, update books
- Add qubes_os to dotfiles
- Add harper to neovim
- Add build_test tests
- Actualize udev rules
- Add middle mouse button to vial
- Move all the logig out of the screen to the controller
- Add deploy to dockerhub, add //tools/oras
- Add missing features to the Pomodoro app, update project readmes, add github pages
- Move all remaining code to main
- Move a portion of tool code to main
- Switch to a dark theme, add cname for rancher
- Fix release page rendering
- Fix lsp config, fix JAVA_HOME
- Move to a light nvim theme, add full git info to releases
- Add release_page generation, remove redundant release templates
- Add //tools/bazelrc, move to a bazelrc preset
- Fix nvim library paths
- Allow docs to put content outside of docs, refactor git to just use .git directly
- Add cross-compilation, move leetcode downloader contracts out of //contracts
- Refactor release templates into partials, add release cards
- Add RSS links, rewrite links shortcode to html, improve release tables
- Add file size to releases, add round_float partial
- Write release tool in go, start adding it to projects, add py proto generation
- Add release rules, add gzip rules, add several other tools, remove autoscrool deps from the root
- Refactor dev_shell into bzlenv, add deactivation, make it functional
- Add dev_shell rules, add make_install_binary, flatten sh rules, add dotfiles/bin
- Make functional make_install archive
- Add //tools/make_install, start moving dotfiles to it
- Add more taxonomies, remove docs tree, move alwaldend.com to projects
- Remove bazel target docs, add tools/docs, tag projects properly
- Remove cfg tree, add projects/dotfiles
- Initial commit
-
Add spellcheck skill
This commit was generated by an LLM.
-
Restore light and dark site canvases and set the shared accent
The shared Docsy canvas set the same Bootstrap dark palette and the same black page background on
:root,[data-bs-theme="light"], and[data-bs-theme="dark"], so the light/dark toggle changed nothing. The site also rendered Bootstrap’s stock blue instead of its intended accent.Split the shared palette so light mode uses a pure white canvas with the light-mode palette and dark mode uses a pure black canvas with the dark-mode palette, and keep the pre-stylesheet paint and footer on the active mode. Assign
$primaryto#7c3aedbefore Bootstrap compiles, so links, buttons, badges, focus rings, and the dark-mode link tint all derive from one value rather than from a site-local copy.Both files stay in the reusable shell; the apex site consumes them through the existing declared exports and no longer carries the footer’s own blue.
OpenSpec-Change: projects/hugo_landing/openspec/changes/restore-light-dark-canvas-and-accent
LLM-disclaimer: This commit was generated by an LLM.
1.11 - Infinitime
This InfiniTime firmware fork adds a text watchface and a Pomodoro app. The repository packages the pinned firmware source and its build dependencies.
Links
- Source code: https://github.com/alwaldend/src/tree/master/projects/infinitime
- Fork code: https://github.com/alwaldend/com_github_infinitimeorg_infinitime
- Upstream code: https://github.com/InfiniTimeOrg/InfiniTime
Features
- Extra Watchface:
Text - Extra app:
Pomodoro - C++, embedded
Usage
The root workspace declares the pinned firmware with use_repo_rule in
include.MODULE.bazel, preserving recursive Git submodules and the CMake
toolchain patch. Firmware source is fetched when referenced, rather than
during module resolution. Its Python/npm lockfiles and SDK archives retain
the upstream pins; Python and Node runtimes use the root workspace toolchains.
The project re-exports pip and npm with separate extension identities so
unrelated Python/npm targets do not fetch firmware to read those lockfiles.
The isolated pip extension declares the Linux x86_64 host platform used by
the pinned ARM compiler archive.
bazel mod deps deliberately evaluates all extensions and can still fetch it.
Validate the firmware with bazel test //projects/infinitime:build_test.
- Install Gadgetbridge
- Download the firmware:
oras pull docker.io/alwaldend/src:projects_infinitime_pinetime_mcuboot_app_dfu_1_15_0_zip_head - Pair the watch in
Gadgetbridge - Install the firmware
1.11.1 - Releases
head
-
Move project landings into the main site
Publish every registered project’s visitor-facing landing page at /projects/
/ from the main site instead of a dedicated subdomain, and retire the per-project Pages repository, CNAME, and Terraform DNS stage that existed only to serve one page derived from the project README. Each project owns its landing content in projects/
/site/content/ as pure content: no layouts, styles, or build rules. The main site packages those directories into content/projects/ / from the registry in projects/projects.bzl, so membership is declared once. The landing is a short hand-written page for visitors while the README keeps its /docs/projects/ / URL for repository reference documentation, and landing front matter now feeds the statuses, languages, and tags taxonomies. Merge the reusable hugo_landing project into the main site: its shared canvas and accent styles and its landing page rules move into the apex tree, and its landing macro, generated configuration, standalone publisher, and repository-relative rewrite layouts are removed. The theme keeps owning the taxonomy and term layouts, which are richer than the heading-only versions the reusable project carried. Remove the now-unused apex deploy_project.sh and deploy_all.sh landing publishers with it.
Retire the per-project publication and DNS ownership: the project landing targets and the landing deployment command, each landing project’s dnsconfig.json and Terraform root, the build plumbing that served only those stages, and the landing repository and Pages membership in the repository catalog. The apex Terraform root is retained because it also declares VM resources, and no Vault configuration is changed.
Replace the provider-snapshot zone files with generated declaration pages, one per destination view, that project the checked-in declarations and are verified for freshness by the DNS offline check. The DNS linter, both destination pages, the apex site, the skills projection, and the repository quality suite pass, and the whole repository builds.
OpenSpec-Change: projects/alwaldend.com/openspec/changes/consolidate-project-landings-into-apex
LLM-disclaimer: This commit was generated by an LLM.
-
Manage forge resources with hermetic Terraform rules
Centralize organization, repository, and named access configuration in infra/repos. Adopt existing GitHub resources, protect master defaults while retaining Pages publication on pages, and preserve existing repository identities. Manage GitLab one-time imports, the F-Droid metadata fork, and default-branch protections through Vault-backed authentication. Forgejo consumes the same catalog. Ongoing repository synchronization is deferred.
Retire the eleven Bazel rule landing sites through their owning Terraform workflows, removing their DNS records, Pages repositories, and landing configuration. Move all twelve existing standalone rule modules into tools/ and retain their public interfaces and documentation on the main site.
Add tools/rules_terraform with verified provider downloads, packed mirrors in runfiles, and reusable Terraform execution rules. Enforce one version per provider source at an extensible resolution boundary. Migrate every Terraform consumer to thirteen shared provider pins in third_party/terraform. Execution and command maps belong to rules_terraform; consumers explicitly select generic AL wrappers for authentication and Vault injection. Remove tools/terraform and all 43 checked-in Terraform provider locks. Validate installed providers against the declared archives before execution.
Validation covers all fourteen workspace builds, all thirteen standalone test suites, Terraform consumers, offline real-provider regressions, rendered documentation, formatting, and semantic lint. The full root test run has 295 passing tests and one skip; its only failure is the historical secret scan, reduced to four pre-existing synthetic fixture matches. Earlier live imports and the exact landing retirement scope have verified postconditions; the Terraform rules migration uses only offline implementation checks.
OpenSpec-Change: infra/repos/openspec/changes/archive/2026-09-13-adopt-shared-repository-catalog OpenSpec-Change: infra/src/openspec/changes/archive/2026-09-13-retire-bazel-rule-landings OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-add-hermetic-terraform-rules OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-correct-terraform-ownership
LLM-disclaimer: This commit was generated by an LLM.
-
Deploy project DNS through Terraform modules
Move DNS ownership into each project’s Terraform state using shared modules. Load dnsconfig.json files at runtime, reject conflicting domain ownership, and render their records as a table. Add missing project AppRoles and scoped DNS policies, and document grouping related Terraform resources in modules.
Deploy all 45 owners sequentially: adopt 155 existing records and create 13 missing OpenHands records. Preserve every pre-existing provider record and verify no-op follow-up plans and DNS answers. Add DNS-scoped plan/show/apply wrappers with a saved-plan guard for roots that also manage services. Allow bounded aggregate path inventories large enough to deliver this migration while retaining truncation refusal in the delivery tool.
Validate runtime ownership, provider imports and preservation with isolated fixtures, Terraform formatting, wrapper builds, repository quality checks, semantic lint, and project documentation/specification builds.
OpenSpec-Change: infra/dns/openspec/changes/archive/2026-09-13-migrate-project-dns-to-terraform
LLM-disclaimer: This commit was generated by an LLM.
-
Simplify OpenSpec workspace globs
Collapse OpenSpec source globs to specs and changes, drop redundant package visibility blocks already covered by REPO.bazel, and regenerate the affected catalogs.
LLM-disclaimer: This commit was generated by an LLM.
-
Publish project sites and reproducible infrastructure diagrams
Build and deploy all 30 remaining project sites with the standard Docsy header, project descriptions and a linked documentation directory. Omit the repeated page title and generated language heading. Remove the unused cgit and xray_manager projects and retire their site resources.
Add a repeatable GitHub Pages publisher, staged Terraform bootstrap and direct GitHub Pages DNS records. Preserve repeated publication when pages is the remote default branch, and include Rules ISO in the main documentation. Document site onboarding in a registered, validated skill. Keep AL introduction short with useful links and preserve its lifecycle details in a dedicated documentation page.
Render all 15 existing infrastructure Drawio pages with pinned Drawio and Chrome inputs, sandboxed export actions, an update target and freshness checks, and include the maintained diagrams in infra/arch documentation. Paint an opaque white canvas to preserve readability in dark themes.
Validation covers project and apex builds, rendered pages, publisher tests, diagram repeatability and freshness, DNS configuration, Terraform formatting, semantic lint and repository quality.
Goal-Ref: build-and-deploy-every-project-landing-page-a782b800 Attempt-ID: attempt-00941092c164
LLM-disclaimer: This commit was generated by an LLM.
-
Keep Bazel dependencies lazy and generate the root module
Declare pinned InfiniTime sources and the Hedron extractor through use_repo_rule, retain recursive firmware submodules, and use the official contrib_rules_jvm 0.32.0 release. Keep default toolchain registration convenient for consumers.
Move root tool implementations into owning packages while preserving compatibility labels, visibility, manual tags, Python paths, Terraform working directories, pnpm dependency pins, and documentation archive layout. Guard the load-free root BUILD with a parser-based quality test. Generate root MODULE.bazel directly from owning include files, with an update command and freshness/integration tests.
Cache hermetic agent tests, preserve lint analysis across modes, and build only lint outputs in lint mode. Allow normal agent lockfile updates while retaining strict CI checks. Limit host Bazel scheduling to eight jobs and half its CPUs, with matching checked-in host configuration.
Fix DNSControl command ordering, JSON manifest loading, record filename suffixes, and credential-file wiring through existing Vault environment injection. Add an offline config test. Correct the Git wrapper shebang for direct execution and refresh derived catalogs affected by the Bazel changes.
Validation covers compatibility builds, firmware, documentation outputs, generator freshness, DNS configuration, and a live DNS preview without applying changes. The repository-wide audit also identifies pre-existing test and coverage gaps.
Goal-Ref: avoid-unrelated-bazel-dependency-downloads-638e8329 Attempt-ID: attempt-106ffd5ccaeb
LLM-disclaimer: This commit was generated by an LLM.
-
Extract DNSControl setup into rules_dnscontrol
Extract the DNSControl setup into
rules_dnscontrol, generate its Bazel dependency bundle from project-owned record files, and update the DNS guidance. Move Hugo rules and the worker to role-based package paths, and give each non-nested project a locally owned Hugo landing target that reuses the shared README-to-landing macro.Clean all landing and Pages DNS records so GitHub Pages serves each project subdomain directly without Cloudflare proxying. Improve the main site with a three-panel home layout, complete project links, documentation explore links, and current deployment guidance.
All affected root-workspace landing, DNS, and site targets pass, along with the nested
rules_hugotests, Buildifier, and repository quality checks.LLM-disclaimer: This commit was generated by an LLM.
-
Add standalone documentation rules
Move docs_filegroup into a reusable rules_docs nested Bzlmod workspace and migrate every root and nested consumer to it. Add a module-aware Gazelle language that creates docs targets only for existing README packages while preserving manual mappings.
Wire the workspace into module resolution, documentation aggregation, and the ten-command full-repo-check. Add the bazel-nested-module skill so future nested workspaces follow the repository’s rc, lockfile, docs, toolchain, Gazelle, and validation conventions.
Keep reviewed Gazelle dependency canonicalization, while protecting the hand-maintained Go proto, Python resource, Android, embedded-site, and skill runner definitions that generic language plugins would otherwise break.
This commit was generated by an LLM.
-
Fix Bazel build caching and tool configuration
This commit was generated by an LLM.
-
Migrate documentation packaging to docs_filegroup
Preserve custom prefixes, renames, strip prefixes, and standalone workspace behavior.\n\nThis commit was generated by an LLM.
- Remove //tools/docs, remove .github
- Migrate the infinitime build to bazel 9
- Add build_test tests
- Fix infinitime python deps, bump python version
- Fix infinitime alarm update
- Move all the logig out of the screen to the controller
- Add deploy to dockerhub, add //tools/oras
- Add missing features to the Pomodoro app, update project readmes, add github pages
- Update infinitime patch, start adding trufflehog rules
- Move all remaining code to main
- Add disk cache, fix infinitime build, add infinitime release
- Build infinitime in a separate repository
- Start refactoring the infinitime build
- Add more taxonomies, remove docs tree, move alwaldend.com to projects
- Remove bazel target docs, add tools/docs, tag projects properly
- Remove changelogs, ignore irrelevant directories in docs
- Remove bzl tree
- Move another group of rules to tools/
- Move a group of rules to tools/
- Remove c and cpp trees
- Initial commit
-
Add spellcheck skill
This commit was generated by an LLM.
-
Restore light and dark site canvases and set the shared accent
The shared Docsy canvas set the same Bootstrap dark palette and the same black page background on
:root,[data-bs-theme="light"], and[data-bs-theme="dark"], so the light/dark toggle changed nothing. The site also rendered Bootstrap’s stock blue instead of its intended accent.Split the shared palette so light mode uses a pure white canvas with the light-mode palette and dark mode uses a pure black canvas with the dark-mode palette, and keep the pre-stylesheet paint and footer on the active mode. Assign
$primaryto#7c3aedbefore Bootstrap compiles, so links, buttons, badges, focus rings, and the dark-mode link tint all derive from one value rather than from a site-local copy.Both files stay in the reusable shell; the apex site consumes them through the existing declared exports and no longer carries the footer’s own blue.
OpenSpec-Change: projects/hugo_landing/openspec/changes/restore-light-dark-canvas-and-accent
LLM-disclaimer: This commit was generated by an LLM.
1.11.1.1 - head
-
Move project landings into the main site
Publish every registered project’s visitor-facing landing page at /projects/
/ from the main site instead of a dedicated subdomain, and retire the per-project Pages repository, CNAME, and Terraform DNS stage that existed only to serve one page derived from the project README. Each project owns its landing content in projects/
/site/content/ as pure content: no layouts, styles, or build rules. The main site packages those directories into content/projects/ / from the registry in projects/projects.bzl, so membership is declared once. The landing is a short hand-written page for visitors while the README keeps its /docs/projects/ / URL for repository reference documentation, and landing front matter now feeds the statuses, languages, and tags taxonomies. Merge the reusable hugo_landing project into the main site: its shared canvas and accent styles and its landing page rules move into the apex tree, and its landing macro, generated configuration, standalone publisher, and repository-relative rewrite layouts are removed. The theme keeps owning the taxonomy and term layouts, which are richer than the heading-only versions the reusable project carried. Remove the now-unused apex deploy_project.sh and deploy_all.sh landing publishers with it.
Retire the per-project publication and DNS ownership: the project landing targets and the landing deployment command, each landing project’s dnsconfig.json and Terraform root, the build plumbing that served only those stages, and the landing repository and Pages membership in the repository catalog. The apex Terraform root is retained because it also declares VM resources, and no Vault configuration is changed.
Replace the provider-snapshot zone files with generated declaration pages, one per destination view, that project the checked-in declarations and are verified for freshness by the DNS offline check. The DNS linter, both destination pages, the apex site, the skills projection, and the repository quality suite pass, and the whole repository builds.
OpenSpec-Change: projects/alwaldend.com/openspec/changes/consolidate-project-landings-into-apex
LLM-disclaimer: This commit was generated by an LLM.
-
Manage forge resources with hermetic Terraform rules
Centralize organization, repository, and named access configuration in infra/repos. Adopt existing GitHub resources, protect master defaults while retaining Pages publication on pages, and preserve existing repository identities. Manage GitLab one-time imports, the F-Droid metadata fork, and default-branch protections through Vault-backed authentication. Forgejo consumes the same catalog. Ongoing repository synchronization is deferred.
Retire the eleven Bazel rule landing sites through their owning Terraform workflows, removing their DNS records, Pages repositories, and landing configuration. Move all twelve existing standalone rule modules into tools/ and retain their public interfaces and documentation on the main site.
Add tools/rules_terraform with verified provider downloads, packed mirrors in runfiles, and reusable Terraform execution rules. Enforce one version per provider source at an extensible resolution boundary. Migrate every Terraform consumer to thirteen shared provider pins in third_party/terraform. Execution and command maps belong to rules_terraform; consumers explicitly select generic AL wrappers for authentication and Vault injection. Remove tools/terraform and all 43 checked-in Terraform provider locks. Validate installed providers against the declared archives before execution.
Validation covers all fourteen workspace builds, all thirteen standalone test suites, Terraform consumers, offline real-provider regressions, rendered documentation, formatting, and semantic lint. The full root test run has 295 passing tests and one skip; its only failure is the historical secret scan, reduced to four pre-existing synthetic fixture matches. Earlier live imports and the exact landing retirement scope have verified postconditions; the Terraform rules migration uses only offline implementation checks.
OpenSpec-Change: infra/repos/openspec/changes/archive/2026-09-13-adopt-shared-repository-catalog OpenSpec-Change: infra/src/openspec/changes/archive/2026-09-13-retire-bazel-rule-landings OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-add-hermetic-terraform-rules OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-correct-terraform-ownership
LLM-disclaimer: This commit was generated by an LLM.
-
Deploy project DNS through Terraform modules
Move DNS ownership into each project’s Terraform state using shared modules. Load dnsconfig.json files at runtime, reject conflicting domain ownership, and render their records as a table. Add missing project AppRoles and scoped DNS policies, and document grouping related Terraform resources in modules.
Deploy all 45 owners sequentially: adopt 155 existing records and create 13 missing OpenHands records. Preserve every pre-existing provider record and verify no-op follow-up plans and DNS answers. Add DNS-scoped plan/show/apply wrappers with a saved-plan guard for roots that also manage services. Allow bounded aggregate path inventories large enough to deliver this migration while retaining truncation refusal in the delivery tool.
Validate runtime ownership, provider imports and preservation with isolated fixtures, Terraform formatting, wrapper builds, repository quality checks, semantic lint, and project documentation/specification builds.
OpenSpec-Change: infra/dns/openspec/changes/archive/2026-09-13-migrate-project-dns-to-terraform
LLM-disclaimer: This commit was generated by an LLM.
-
Simplify OpenSpec workspace globs
Collapse OpenSpec source globs to specs and changes, drop redundant package visibility blocks already covered by REPO.bazel, and regenerate the affected catalogs.
LLM-disclaimer: This commit was generated by an LLM.
-
Publish project sites and reproducible infrastructure diagrams
Build and deploy all 30 remaining project sites with the standard Docsy header, project descriptions and a linked documentation directory. Omit the repeated page title and generated language heading. Remove the unused cgit and xray_manager projects and retire their site resources.
Add a repeatable GitHub Pages publisher, staged Terraform bootstrap and direct GitHub Pages DNS records. Preserve repeated publication when pages is the remote default branch, and include Rules ISO in the main documentation. Document site onboarding in a registered, validated skill. Keep AL introduction short with useful links and preserve its lifecycle details in a dedicated documentation page.
Render all 15 existing infrastructure Drawio pages with pinned Drawio and Chrome inputs, sandboxed export actions, an update target and freshness checks, and include the maintained diagrams in infra/arch documentation. Paint an opaque white canvas to preserve readability in dark themes.
Validation covers project and apex builds, rendered pages, publisher tests, diagram repeatability and freshness, DNS configuration, Terraform formatting, semantic lint and repository quality.
Goal-Ref: build-and-deploy-every-project-landing-page-a782b800 Attempt-ID: attempt-00941092c164
LLM-disclaimer: This commit was generated by an LLM.
-
Keep Bazel dependencies lazy and generate the root module
Declare pinned InfiniTime sources and the Hedron extractor through use_repo_rule, retain recursive firmware submodules, and use the official contrib_rules_jvm 0.32.0 release. Keep default toolchain registration convenient for consumers.
Move root tool implementations into owning packages while preserving compatibility labels, visibility, manual tags, Python paths, Terraform working directories, pnpm dependency pins, and documentation archive layout. Guard the load-free root BUILD with a parser-based quality test. Generate root MODULE.bazel directly from owning include files, with an update command and freshness/integration tests.
Cache hermetic agent tests, preserve lint analysis across modes, and build only lint outputs in lint mode. Allow normal agent lockfile updates while retaining strict CI checks. Limit host Bazel scheduling to eight jobs and half its CPUs, with matching checked-in host configuration.
Fix DNSControl command ordering, JSON manifest loading, record filename suffixes, and credential-file wiring through existing Vault environment injection. Add an offline config test. Correct the Git wrapper shebang for direct execution and refresh derived catalogs affected by the Bazel changes.
Validation covers compatibility builds, firmware, documentation outputs, generator freshness, DNS configuration, and a live DNS preview without applying changes. The repository-wide audit also identifies pre-existing test and coverage gaps.
Goal-Ref: avoid-unrelated-bazel-dependency-downloads-638e8329 Attempt-ID: attempt-106ffd5ccaeb
LLM-disclaimer: This commit was generated by an LLM.
-
Extract DNSControl setup into rules_dnscontrol
Extract the DNSControl setup into
rules_dnscontrol, generate its Bazel dependency bundle from project-owned record files, and update the DNS guidance. Move Hugo rules and the worker to role-based package paths, and give each non-nested project a locally owned Hugo landing target that reuses the shared README-to-landing macro.Clean all landing and Pages DNS records so GitHub Pages serves each project subdomain directly without Cloudflare proxying. Improve the main site with a three-panel home layout, complete project links, documentation explore links, and current deployment guidance.
All affected root-workspace landing, DNS, and site targets pass, along with the nested
rules_hugotests, Buildifier, and repository quality checks.LLM-disclaimer: This commit was generated by an LLM.
-
Add standalone documentation rules
Move docs_filegroup into a reusable rules_docs nested Bzlmod workspace and migrate every root and nested consumer to it. Add a module-aware Gazelle language that creates docs targets only for existing README packages while preserving manual mappings.
Wire the workspace into module resolution, documentation aggregation, and the ten-command full-repo-check. Add the bazel-nested-module skill so future nested workspaces follow the repository’s rc, lockfile, docs, toolchain, Gazelle, and validation conventions.
Keep reviewed Gazelle dependency canonicalization, while protecting the hand-maintained Go proto, Python resource, Android, embedded-site, and skill runner definitions that generic language plugins would otherwise break.
This commit was generated by an LLM.
-
Fix Bazel build caching and tool configuration
This commit was generated by an LLM.
-
Migrate documentation packaging to docs_filegroup
Preserve custom prefixes, renames, strip prefixes, and standalone workspace behavior.\n\nThis commit was generated by an LLM.
- Remove //tools/docs, remove .github
- Migrate the infinitime build to bazel 9
- Add build_test tests
- Fix infinitime python deps, bump python version
- Fix infinitime alarm update
- Move all the logig out of the screen to the controller
- Add deploy to dockerhub, add //tools/oras
- Add missing features to the Pomodoro app, update project readmes, add github pages
- Update infinitime patch, start adding trufflehog rules
- Move all remaining code to main
- Add disk cache, fix infinitime build, add infinitime release
- Build infinitime in a separate repository
- Start refactoring the infinitime build
- Add more taxonomies, remove docs tree, move alwaldend.com to projects
- Remove bazel target docs, add tools/docs, tag projects properly
- Remove changelogs, ignore irrelevant directories in docs
- Remove bzl tree
- Move another group of rules to tools/
- Move a group of rules to tools/
- Remove c and cpp trees
- Initial commit
-
Add spellcheck skill
This commit was generated by an LLM.
-
Restore light and dark site canvases and set the shared accent
The shared Docsy canvas set the same Bootstrap dark palette and the same black page background on
:root,[data-bs-theme="light"], and[data-bs-theme="dark"], so the light/dark toggle changed nothing. The site also rendered Bootstrap’s stock blue instead of its intended accent.Split the shared palette so light mode uses a pure white canvas with the light-mode palette and dark mode uses a pure black canvas with the dark-mode palette, and keep the pre-stylesheet paint and footer on the active mode. Assign
$primaryto#7c3aedbefore Bootstrap compiles, so links, buttons, badges, focus rings, and the dark-mode link tint all derive from one value rather than from a site-local copy.Both files stay in the reusable shell; the apex site consumes them through the existing declared exports and no longer carries the footer’s own blue.
OpenSpec-Change: projects/hugo_landing/openspec/changes/restore-light-dark-canvas-and-accent
LLM-disclaimer: This commit was generated by an LLM.
1.12 - Kustomization
This project contains Kubernetes Kustomization resources for Flux, Traefik, and cert-manager. It is still in progress.
Links
1.12.1 -
project-dns Specification
Purpose
Record the retirement of this project’s landing DNS infrastructure while preserving its repository documentation and builds.
Requirements
Requirement: Keep landing infrastructure retired
The project SHALL have no dedicated landing DNS declaration, Terraform root, or
operational source export. Its landing page SHALL be published by the main site
under /projects/kustomization/ instead of a dedicated hostname.
Scenario: Inspect the project after landing retirement
- WHEN the project tree is consumed
- THEN it contains no landing DNS declaration, Terraform DNS stage, or landing build target, and the main site owns its landing page.
1.12.2 -
Kustomization Specification
Purpose
Provide in-progress Kubernetes resource definitions for Flux, Traefik, and
cert-manager. This baseline records declared resources at revision
550d7e79b1f5fdbc2b6017b75178471d6914082f, observed on 2026-09-08. It does not
assert successful rendering, reconciliation, or a deployed cluster state.
Sources: project README, Flux source, Traefik release, Traefik remote resources, and cert-manager release.
Requirements
Requirement: Scoped Flux repository source
The Flux GitRepository declaration SHALL select the repository’s master
branch, refer to the flux-git-src credential secret, and include only infra
and projects/kustomization from the repository through its ignore rules.
Scenario: Inspect repository source scope
- WHEN the checked-in Flux GitRepository is inspected
- THEN its branch, secret reference, and inclusion paths SHALL match the declared source scope.
Requirement: Traefik Gateway API configuration
The Traefik definitions SHALL declare an OCI chart source and HelmRelease that enable the Kubernetes Gateway provider, disable the Kubernetes Ingress provider, and configure HTTP redirection to HTTPS with a named TLS certificate secret.
Scenario: Inspect gateway configuration
- WHEN the Traefik HelmRelease values are inspected
- THEN they SHALL enable HTTP and HTTPS gateway listeners and reference
traefik-gateway-websecure-tlsfor HTTPS termination.
Requirement: cert-manager reconciliation configuration
The cert-manager definitions SHALL declare an OCI chart source and HelmRelease with Gateway API support, CRD installation, Helm tests, and drift detection enabled.
Scenario: Inspect certificate controller configuration
- WHEN the cert-manager HelmRelease is inspected
- THEN its values SHALL enable Gateway API support and CRDs, and its release settings SHALL enable tests and drift detection.
1.12.3 - Releases
head
-
Move project landings into the main site
Publish every registered project’s visitor-facing landing page at /projects/
/ from the main site instead of a dedicated subdomain, and retire the per-project Pages repository, CNAME, and Terraform DNS stage that existed only to serve one page derived from the project README. Each project owns its landing content in projects/
/site/content/ as pure content: no layouts, styles, or build rules. The main site packages those directories into content/projects/ / from the registry in projects/projects.bzl, so membership is declared once. The landing is a short hand-written page for visitors while the README keeps its /docs/projects/ / URL for repository reference documentation, and landing front matter now feeds the statuses, languages, and tags taxonomies. Merge the reusable hugo_landing project into the main site: its shared canvas and accent styles and its landing page rules move into the apex tree, and its landing macro, generated configuration, standalone publisher, and repository-relative rewrite layouts are removed. The theme keeps owning the taxonomy and term layouts, which are richer than the heading-only versions the reusable project carried. Remove the now-unused apex deploy_project.sh and deploy_all.sh landing publishers with it.
Retire the per-project publication and DNS ownership: the project landing targets and the landing deployment command, each landing project’s dnsconfig.json and Terraform root, the build plumbing that served only those stages, and the landing repository and Pages membership in the repository catalog. The apex Terraform root is retained because it also declares VM resources, and no Vault configuration is changed.
Replace the provider-snapshot zone files with generated declaration pages, one per destination view, that project the checked-in declarations and are verified for freshness by the DNS offline check. The DNS linter, both destination pages, the apex site, the skills projection, and the repository quality suite pass, and the whole repository builds.
OpenSpec-Change: projects/alwaldend.com/openspec/changes/consolidate-project-landings-into-apex
LLM-disclaimer: This commit was generated by an LLM.
-
Manage forge resources with hermetic Terraform rules
Centralize organization, repository, and named access configuration in infra/repos. Adopt existing GitHub resources, protect master defaults while retaining Pages publication on pages, and preserve existing repository identities. Manage GitLab one-time imports, the F-Droid metadata fork, and default-branch protections through Vault-backed authentication. Forgejo consumes the same catalog. Ongoing repository synchronization is deferred.
Retire the eleven Bazel rule landing sites through their owning Terraform workflows, removing their DNS records, Pages repositories, and landing configuration. Move all twelve existing standalone rule modules into tools/ and retain their public interfaces and documentation on the main site.
Add tools/rules_terraform with verified provider downloads, packed mirrors in runfiles, and reusable Terraform execution rules. Enforce one version per provider source at an extensible resolution boundary. Migrate every Terraform consumer to thirteen shared provider pins in third_party/terraform. Execution and command maps belong to rules_terraform; consumers explicitly select generic AL wrappers for authentication and Vault injection. Remove tools/terraform and all 43 checked-in Terraform provider locks. Validate installed providers against the declared archives before execution.
Validation covers all fourteen workspace builds, all thirteen standalone test suites, Terraform consumers, offline real-provider regressions, rendered documentation, formatting, and semantic lint. The full root test run has 295 passing tests and one skip; its only failure is the historical secret scan, reduced to four pre-existing synthetic fixture matches. Earlier live imports and the exact landing retirement scope have verified postconditions; the Terraform rules migration uses only offline implementation checks.
OpenSpec-Change: infra/repos/openspec/changes/archive/2026-09-13-adopt-shared-repository-catalog OpenSpec-Change: infra/src/openspec/changes/archive/2026-09-13-retire-bazel-rule-landings OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-add-hermetic-terraform-rules OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-correct-terraform-ownership
LLM-disclaimer: This commit was generated by an LLM.
-
Deploy project DNS through Terraform modules
Move DNS ownership into each project’s Terraform state using shared modules. Load dnsconfig.json files at runtime, reject conflicting domain ownership, and render their records as a table. Add missing project AppRoles and scoped DNS policies, and document grouping related Terraform resources in modules.
Deploy all 45 owners sequentially: adopt 155 existing records and create 13 missing OpenHands records. Preserve every pre-existing provider record and verify no-op follow-up plans and DNS answers. Add DNS-scoped plan/show/apply wrappers with a saved-plan guard for roots that also manage services. Allow bounded aggregate path inventories large enough to deliver this migration while retaining truncation refusal in the delivery tool.
Validate runtime ownership, provider imports and preservation with isolated fixtures, Terraform formatting, wrapper builds, repository quality checks, semantic lint, and project documentation/specification builds.
OpenSpec-Change: infra/dns/openspec/changes/archive/2026-09-13-migrate-project-dns-to-terraform
LLM-disclaimer: This commit was generated by an LLM.
-
Simplify OpenSpec workspace globs
Collapse OpenSpec source globs to specs and changes, drop redundant package visibility blocks already covered by REPO.bazel, and regenerate the affected catalogs.
LLM-disclaimer: This commit was generated by an LLM.
-
Provision XCP-ng with isolated AppRole access and deploy Forgejo
Create one Xen Orchestra resource set and OIDC user per Vault AppRole. Bind access by trusted issuer and immutable Vault entity ID. Forgejo uses its own short-lived login and has access only to its resource set and VM. Resolve pools, templates, storage, networks and existing VMs by name. Manage pool and VM ACLs natively in Terraform; retain the XO API helper only for unsupported OIDC configuration, identity discovery and bootstrap.
Deploy Forgejo at git.alwaldend.com through Ansible. Install the official XO OIDC plugin and Vault ACME certificates on XO and XCP-ng with managed renewal. Move PVE cloud-init into infra/cloud_init and derive Xen settings from that foundation using a repository Go template. Move XCP-ng Terraform to tf and retain one labeled AL configuration for administration.
Discover Forgejo accounts and team access from Vault groups, adopting existing OIDC accounts without replacement. Reuse PVE’s group/entity lookup policies and remove the bespoke user_entities policy.
Require checked-in IaC for infrastructure and approval for exceptions. Include all configured formatter changes as requested.
Goal-Ref: refine-shared-cloud-init-and-group-driven-infrastructu-b9aba214 Attempt-ID: attempt-8c0d942b05f3
LLM-disclaimer: This commit was generated by an LLM.
-
Publish project sites and reproducible infrastructure diagrams
Build and deploy all 30 remaining project sites with the standard Docsy header, project descriptions and a linked documentation directory. Omit the repeated page title and generated language heading. Remove the unused cgit and xray_manager projects and retire their site resources.
Add a repeatable GitHub Pages publisher, staged Terraform bootstrap and direct GitHub Pages DNS records. Preserve repeated publication when pages is the remote default branch, and include Rules ISO in the main documentation. Document site onboarding in a registered, validated skill. Keep AL introduction short with useful links and preserve its lifecycle details in a dedicated documentation page.
Render all 15 existing infrastructure Drawio pages with pinned Drawio and Chrome inputs, sandboxed export actions, an update target and freshness checks, and include the maintained diagrams in infra/arch documentation. Paint an opaque white canvas to preserve readability in dark themes.
Validation covers project and apex builds, rendered pages, publisher tests, diagram repeatability and freshness, DNS configuration, Terraform formatting, semantic lint and repository quality.
Goal-Ref: build-and-deploy-every-project-landing-page-a782b800 Attempt-ID: attempt-00941092c164
LLM-disclaimer: This commit was generated by an LLM.
-
Extract DNSControl setup into rules_dnscontrol
Extract the DNSControl setup into
rules_dnscontrol, generate its Bazel dependency bundle from project-owned record files, and update the DNS guidance. Move Hugo rules and the worker to role-based package paths, and give each non-nested project a locally owned Hugo landing target that reuses the shared README-to-landing macro.Clean all landing and Pages DNS records so GitHub Pages serves each project subdomain directly without Cloudflare proxying. Improve the main site with a three-panel home layout, complete project links, documentation explore links, and current deployment guidance.
All affected root-workspace landing, DNS, and site targets pass, along with the nested
rules_hugotests, Buildifier, and repository quality checks.LLM-disclaimer: This commit was generated by an LLM.
-
Add hermetic repository-wide formatting and linting
Integrate upstream formatters for the repository’s meaningful tracked source and configuration file types through Bazel, and add Buildifier, Ruff, and ShellCheck lint aspects for correctness-oriented repository-wide checks.
Pin all new external tools through Bzlmod or the existing pnpm lock, add thin cache/runfiles adapters where required, expose format and check targets, and wire the checks into the pre-commit workflow. Format the existing tree and fix the correctness defects uncovered by the new checks. Preserve generated sources and exact-content fixtures that are not safely rewritable, and clarify that ordinary infrastructure build output is safe to display.
Validation:
- all 21 repository quality and compatibility formatter tests pass
- Buildifier test passes
- lint aspects analyze all 4,629 ordinary root targets without findings
- the complete 18-command root and nested full-repository audit was exercised; remaining failures are documented environment or pre-existing test limits
LLM-disclaimer: This commit was generated by an LLM.
-
Add standalone documentation rules
Move docs_filegroup into a reusable rules_docs nested Bzlmod workspace and migrate every root and nested consumer to it. Add a module-aware Gazelle language that creates docs targets only for existing README packages while preserving manual mappings.
Wire the workspace into module resolution, documentation aggregation, and the ten-command full-repo-check. Add the bazel-nested-module skill so future nested workspaces follow the repository’s rc, lockfile, docs, toolchain, Gazelle, and validation conventions.
Keep reviewed Gazelle dependency canonicalization, while protecting the hand-maintained Go proto, Python resource, Android, embedded-site, and skill runner definitions that generic language plugins would otherwise break.
This commit was generated by an LLM.
-
Make release generation hermetic
Add the missing AL and Kustomization release targets and give release actions a declared bare Git snapshot instead of access to the workspace repository.\n\nThis commit was generated by an LLM.
- Move traefik into a separate kustomization
- Fix ca.crt path
- Move cert-manager into a reusable kustomization
- Fix CA path
- Update ca path
- Create //projects/kustomization
- Initial commit
-
Add spellcheck skill
This commit was generated by an LLM.
-
Restore light and dark site canvases and set the shared accent
The shared Docsy canvas set the same Bootstrap dark palette and the same black page background on
:root,[data-bs-theme="light"], and[data-bs-theme="dark"], so the light/dark toggle changed nothing. The site also rendered Bootstrap’s stock blue instead of its intended accent.Split the shared palette so light mode uses a pure white canvas with the light-mode palette and dark mode uses a pure black canvas with the dark-mode palette, and keep the pre-stylesheet paint and footer on the active mode. Assign
$primaryto#7c3aedbefore Bootstrap compiles, so links, buttons, badges, focus rings, and the dark-mode link tint all derive from one value rather than from a site-local copy.Both files stay in the reusable shell; the apex site consumes them through the existing declared exports and no longer carries the footer’s own blue.
OpenSpec-Change: projects/hugo_landing/openspec/changes/restore-light-dark-canvas-and-accent
LLM-disclaimer: This commit was generated by an LLM.
1.12.3.1 - head
-
Move project landings into the main site
Publish every registered project’s visitor-facing landing page at /projects/
/ from the main site instead of a dedicated subdomain, and retire the per-project Pages repository, CNAME, and Terraform DNS stage that existed only to serve one page derived from the project README. Each project owns its landing content in projects/
/site/content/ as pure content: no layouts, styles, or build rules. The main site packages those directories into content/projects/ / from the registry in projects/projects.bzl, so membership is declared once. The landing is a short hand-written page for visitors while the README keeps its /docs/projects/ / URL for repository reference documentation, and landing front matter now feeds the statuses, languages, and tags taxonomies. Merge the reusable hugo_landing project into the main site: its shared canvas and accent styles and its landing page rules move into the apex tree, and its landing macro, generated configuration, standalone publisher, and repository-relative rewrite layouts are removed. The theme keeps owning the taxonomy and term layouts, which are richer than the heading-only versions the reusable project carried. Remove the now-unused apex deploy_project.sh and deploy_all.sh landing publishers with it.
Retire the per-project publication and DNS ownership: the project landing targets and the landing deployment command, each landing project’s dnsconfig.json and Terraform root, the build plumbing that served only those stages, and the landing repository and Pages membership in the repository catalog. The apex Terraform root is retained because it also declares VM resources, and no Vault configuration is changed.
Replace the provider-snapshot zone files with generated declaration pages, one per destination view, that project the checked-in declarations and are verified for freshness by the DNS offline check. The DNS linter, both destination pages, the apex site, the skills projection, and the repository quality suite pass, and the whole repository builds.
OpenSpec-Change: projects/alwaldend.com/openspec/changes/consolidate-project-landings-into-apex
LLM-disclaimer: This commit was generated by an LLM.
-
Manage forge resources with hermetic Terraform rules
Centralize organization, repository, and named access configuration in infra/repos. Adopt existing GitHub resources, protect master defaults while retaining Pages publication on pages, and preserve existing repository identities. Manage GitLab one-time imports, the F-Droid metadata fork, and default-branch protections through Vault-backed authentication. Forgejo consumes the same catalog. Ongoing repository synchronization is deferred.
Retire the eleven Bazel rule landing sites through their owning Terraform workflows, removing their DNS records, Pages repositories, and landing configuration. Move all twelve existing standalone rule modules into tools/ and retain their public interfaces and documentation on the main site.
Add tools/rules_terraform with verified provider downloads, packed mirrors in runfiles, and reusable Terraform execution rules. Enforce one version per provider source at an extensible resolution boundary. Migrate every Terraform consumer to thirteen shared provider pins in third_party/terraform. Execution and command maps belong to rules_terraform; consumers explicitly select generic AL wrappers for authentication and Vault injection. Remove tools/terraform and all 43 checked-in Terraform provider locks. Validate installed providers against the declared archives before execution.
Validation covers all fourteen workspace builds, all thirteen standalone test suites, Terraform consumers, offline real-provider regressions, rendered documentation, formatting, and semantic lint. The full root test run has 295 passing tests and one skip; its only failure is the historical secret scan, reduced to four pre-existing synthetic fixture matches. Earlier live imports and the exact landing retirement scope have verified postconditions; the Terraform rules migration uses only offline implementation checks.
OpenSpec-Change: infra/repos/openspec/changes/archive/2026-09-13-adopt-shared-repository-catalog OpenSpec-Change: infra/src/openspec/changes/archive/2026-09-13-retire-bazel-rule-landings OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-add-hermetic-terraform-rules OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-correct-terraform-ownership
LLM-disclaimer: This commit was generated by an LLM.
-
Deploy project DNS through Terraform modules
Move DNS ownership into each project’s Terraform state using shared modules. Load dnsconfig.json files at runtime, reject conflicting domain ownership, and render their records as a table. Add missing project AppRoles and scoped DNS policies, and document grouping related Terraform resources in modules.
Deploy all 45 owners sequentially: adopt 155 existing records and create 13 missing OpenHands records. Preserve every pre-existing provider record and verify no-op follow-up plans and DNS answers. Add DNS-scoped plan/show/apply wrappers with a saved-plan guard for roots that also manage services. Allow bounded aggregate path inventories large enough to deliver this migration while retaining truncation refusal in the delivery tool.
Validate runtime ownership, provider imports and preservation with isolated fixtures, Terraform formatting, wrapper builds, repository quality checks, semantic lint, and project documentation/specification builds.
OpenSpec-Change: infra/dns/openspec/changes/archive/2026-09-13-migrate-project-dns-to-terraform
LLM-disclaimer: This commit was generated by an LLM.
-
Simplify OpenSpec workspace globs
Collapse OpenSpec source globs to specs and changes, drop redundant package visibility blocks already covered by REPO.bazel, and regenerate the affected catalogs.
LLM-disclaimer: This commit was generated by an LLM.
-
Provision XCP-ng with isolated AppRole access and deploy Forgejo
Create one Xen Orchestra resource set and OIDC user per Vault AppRole. Bind access by trusted issuer and immutable Vault entity ID. Forgejo uses its own short-lived login and has access only to its resource set and VM. Resolve pools, templates, storage, networks and existing VMs by name. Manage pool and VM ACLs natively in Terraform; retain the XO API helper only for unsupported OIDC configuration, identity discovery and bootstrap.
Deploy Forgejo at git.alwaldend.com through Ansible. Install the official XO OIDC plugin and Vault ACME certificates on XO and XCP-ng with managed renewal. Move PVE cloud-init into infra/cloud_init and derive Xen settings from that foundation using a repository Go template. Move XCP-ng Terraform to tf and retain one labeled AL configuration for administration.
Discover Forgejo accounts and team access from Vault groups, adopting existing OIDC accounts without replacement. Reuse PVE’s group/entity lookup policies and remove the bespoke user_entities policy.
Require checked-in IaC for infrastructure and approval for exceptions. Include all configured formatter changes as requested.
Goal-Ref: refine-shared-cloud-init-and-group-driven-infrastructu-b9aba214 Attempt-ID: attempt-8c0d942b05f3
LLM-disclaimer: This commit was generated by an LLM.
-
Publish project sites and reproducible infrastructure diagrams
Build and deploy all 30 remaining project sites with the standard Docsy header, project descriptions and a linked documentation directory. Omit the repeated page title and generated language heading. Remove the unused cgit and xray_manager projects and retire their site resources.
Add a repeatable GitHub Pages publisher, staged Terraform bootstrap and direct GitHub Pages DNS records. Preserve repeated publication when pages is the remote default branch, and include Rules ISO in the main documentation. Document site onboarding in a registered, validated skill. Keep AL introduction short with useful links and preserve its lifecycle details in a dedicated documentation page.
Render all 15 existing infrastructure Drawio pages with pinned Drawio and Chrome inputs, sandboxed export actions, an update target and freshness checks, and include the maintained diagrams in infra/arch documentation. Paint an opaque white canvas to preserve readability in dark themes.
Validation covers project and apex builds, rendered pages, publisher tests, diagram repeatability and freshness, DNS configuration, Terraform formatting, semantic lint and repository quality.
Goal-Ref: build-and-deploy-every-project-landing-page-a782b800 Attempt-ID: attempt-00941092c164
LLM-disclaimer: This commit was generated by an LLM.
-
Extract DNSControl setup into rules_dnscontrol
Extract the DNSControl setup into
rules_dnscontrol, generate its Bazel dependency bundle from project-owned record files, and update the DNS guidance. Move Hugo rules and the worker to role-based package paths, and give each non-nested project a locally owned Hugo landing target that reuses the shared README-to-landing macro.Clean all landing and Pages DNS records so GitHub Pages serves each project subdomain directly without Cloudflare proxying. Improve the main site with a three-panel home layout, complete project links, documentation explore links, and current deployment guidance.
All affected root-workspace landing, DNS, and site targets pass, along with the nested
rules_hugotests, Buildifier, and repository quality checks.LLM-disclaimer: This commit was generated by an LLM.
-
Add hermetic repository-wide formatting and linting
Integrate upstream formatters for the repository’s meaningful tracked source and configuration file types through Bazel, and add Buildifier, Ruff, and ShellCheck lint aspects for correctness-oriented repository-wide checks.
Pin all new external tools through Bzlmod or the existing pnpm lock, add thin cache/runfiles adapters where required, expose format and check targets, and wire the checks into the pre-commit workflow. Format the existing tree and fix the correctness defects uncovered by the new checks. Preserve generated sources and exact-content fixtures that are not safely rewritable, and clarify that ordinary infrastructure build output is safe to display.
Validation:
- all 21 repository quality and compatibility formatter tests pass
- Buildifier test passes
- lint aspects analyze all 4,629 ordinary root targets without findings
- the complete 18-command root and nested full-repository audit was exercised; remaining failures are documented environment or pre-existing test limits
LLM-disclaimer: This commit was generated by an LLM.
-
Add standalone documentation rules
Move docs_filegroup into a reusable rules_docs nested Bzlmod workspace and migrate every root and nested consumer to it. Add a module-aware Gazelle language that creates docs targets only for existing README packages while preserving manual mappings.
Wire the workspace into module resolution, documentation aggregation, and the ten-command full-repo-check. Add the bazel-nested-module skill so future nested workspaces follow the repository’s rc, lockfile, docs, toolchain, Gazelle, and validation conventions.
Keep reviewed Gazelle dependency canonicalization, while protecting the hand-maintained Go proto, Python resource, Android, embedded-site, and skill runner definitions that generic language plugins would otherwise break.
This commit was generated by an LLM.
-
Make release generation hermetic
Add the missing AL and Kustomization release targets and give release actions a declared bare Git snapshot instead of access to the workspace repository.\n\nThis commit was generated by an LLM.
- Move traefik into a separate kustomization
- Fix ca.crt path
- Move cert-manager into a reusable kustomization
- Fix CA path
- Update ca path
- Create //projects/kustomization
- Initial commit
-
Add spellcheck skill
This commit was generated by an LLM.
-
Restore light and dark site canvases and set the shared accent
The shared Docsy canvas set the same Bootstrap dark palette and the same black page background on
:root,[data-bs-theme="light"], and[data-bs-theme="dark"], so the light/dark toggle changed nothing. The site also rendered Bootstrap’s stock blue instead of its intended accent.Split the shared palette so light mode uses a pure white canvas with the light-mode palette and dark mode uses a pure black canvas with the dark-mode palette, and keep the pre-stylesheet paint and footer on the active mode. Assign
$primaryto#7c3aedbefore Bootstrap compiles, so links, buttons, badges, focus rings, and the dark-mode link tint all derive from one value rather than from a site-local copy.Both files stay in the reusable shell; the apex site consumes them through the existing declared exports and no longer carries the footer’s own blue.
OpenSpec-Change: projects/hugo_landing/openspec/changes/restore-light-dark-canvas-and-accent
LLM-disclaimer: This commit was generated by an LLM.
1.13 - Leetcode downloader
This project exports LeetCode submissions and generates documentation from submission files using a CLI and Bazel rules. A Tampermonkey script provides a browser-based download path; direct CLI downloads are currently blocked by LeetCode bot protection.
Links
Features
- CLI and bzl code to generate submission docs
- Tampermonkey script to download submissions
- CLI to download submissions (Doesn’t work because of bot protection)
Usage
Generate submission from a submission file
bazel run //projects/leetcode_downloader -- \
--submissions-file "${PWD}/out/submissions.json" \
--root-dir "${PWD}" \
generate
Help
Usage of flags:
-base_url string
(default "https://leetcode.com")
-cookie string
-limit uint
(default 20)
-offset uint
-root-dir string
(default "${PWD}")
-submissions-file string
1.13.1 - Bzl
1.13.1.1 - al_leetcode_submissions
al_leetcode_submissions
load("@com_alwaldend_src//projects/leetcode_downloader/main/bzl:al_leetcode_submissions.bzl", "al_leetcode_submissions")
al_leetcode_submissions(name, srcs, visibility, **kwargs)
Generate leetcode submission targets
PARAMETERS
| Name | Description | Default Value |
|---|---|---|
| name | generated md archive name | none |
| srcs | leetcode submission configs | none |
| visibility | visibility | None |
| kwargs | kwargs for template_files | none |
1.13.2 - Proto
1.13.2.1 - contracts
Java
load("@rules_java//java:defs.bzl", "java_library")
java_library(
name = "name",
deps = [
"@com_alwaldend_src//projects/leetcode_downloader/main/proto/contracts:contracts_java_library",
],
)
Golang
load("@rules_go//go:def.bzl", "go_library")
go_library(
name = "name",
deps = [
"@com_alwaldend_src//projects/leetcode_downloader/main/proto/contracts:contracts",
],
)
Proto
syntax = "proto3";
option go_package = "git.alwaldend.com/alwaldend/src/projects/leetcode_downloader/main/proto/contracts";
enum CliAction {
DOWNLOAD = 0;
GENERATE = 1;
UPDATE = 2;
}
message Config {
string base_url = 1;
string cookie = 2;
repeated string action_args = 4;
CliAction action = 5;
uint64 offset = 6;
uint64 limit = 7;
map<string, SubmissionConfig> submissions = 8;
string root_dir = 9;
map<string, string> headers = 11;
string submissions_file = 12;
bool write_code = 13;
}
message SubmissionConfig {
string dir = 1;
string extension = 2;
repeated string types = 3;
}
message Submission {
uint64 id = 1;
string status_display = 2;
string lang = 3;
uint64 question_id = 4;
string title_slug = 5;
string code = 6;
string title = 7;
string url = 8;
string lang_name = 9;
// string time = 10;
uint64 timestamp = 11;
uint64 status = 12;
string runtime = 13;
string is_pending = 14;
string memory = 15;
string compare_result = 16;
bool has_notes = 17;
uint64 flag_type = 18;
}
message SubmissonsResponse {
repeated Submission submissions_dump = 1;
bool has_next = 2;
string last_key = 3;
}
message SubmissonsStorage {
repeated Submission submissions = 1;
}
1.13.3 - Releases
head
-
Move project landings into the main site
Publish every registered project’s visitor-facing landing page at /projects/
/ from the main site instead of a dedicated subdomain, and retire the per-project Pages repository, CNAME, and Terraform DNS stage that existed only to serve one page derived from the project README. Each project owns its landing content in projects/
/site/content/ as pure content: no layouts, styles, or build rules. The main site packages those directories into content/projects/ / from the registry in projects/projects.bzl, so membership is declared once. The landing is a short hand-written page for visitors while the README keeps its /docs/projects/ / URL for repository reference documentation, and landing front matter now feeds the statuses, languages, and tags taxonomies. Merge the reusable hugo_landing project into the main site: its shared canvas and accent styles and its landing page rules move into the apex tree, and its landing macro, generated configuration, standalone publisher, and repository-relative rewrite layouts are removed. The theme keeps owning the taxonomy and term layouts, which are richer than the heading-only versions the reusable project carried. Remove the now-unused apex deploy_project.sh and deploy_all.sh landing publishers with it.
Retire the per-project publication and DNS ownership: the project landing targets and the landing deployment command, each landing project’s dnsconfig.json and Terraform root, the build plumbing that served only those stages, and the landing repository and Pages membership in the repository catalog. The apex Terraform root is retained because it also declares VM resources, and no Vault configuration is changed.
Replace the provider-snapshot zone files with generated declaration pages, one per destination view, that project the checked-in declarations and are verified for freshness by the DNS offline check. The DNS linter, both destination pages, the apex site, the skills projection, and the repository quality suite pass, and the whole repository builds.
OpenSpec-Change: projects/alwaldend.com/openspec/changes/consolidate-project-landings-into-apex
LLM-disclaimer: This commit was generated by an LLM.
-
Manage forge resources with hermetic Terraform rules
Centralize organization, repository, and named access configuration in infra/repos. Adopt existing GitHub resources, protect master defaults while retaining Pages publication on pages, and preserve existing repository identities. Manage GitLab one-time imports, the F-Droid metadata fork, and default-branch protections through Vault-backed authentication. Forgejo consumes the same catalog. Ongoing repository synchronization is deferred.
Retire the eleven Bazel rule landing sites through their owning Terraform workflows, removing their DNS records, Pages repositories, and landing configuration. Move all twelve existing standalone rule modules into tools/ and retain their public interfaces and documentation on the main site.
Add tools/rules_terraform with verified provider downloads, packed mirrors in runfiles, and reusable Terraform execution rules. Enforce one version per provider source at an extensible resolution boundary. Migrate every Terraform consumer to thirteen shared provider pins in third_party/terraform. Execution and command maps belong to rules_terraform; consumers explicitly select generic AL wrappers for authentication and Vault injection. Remove tools/terraform and all 43 checked-in Terraform provider locks. Validate installed providers against the declared archives before execution.
Validation covers all fourteen workspace builds, all thirteen standalone test suites, Terraform consumers, offline real-provider regressions, rendered documentation, formatting, and semantic lint. The full root test run has 295 passing tests and one skip; its only failure is the historical secret scan, reduced to four pre-existing synthetic fixture matches. Earlier live imports and the exact landing retirement scope have verified postconditions; the Terraform rules migration uses only offline implementation checks.
OpenSpec-Change: infra/repos/openspec/changes/archive/2026-09-13-adopt-shared-repository-catalog OpenSpec-Change: infra/src/openspec/changes/archive/2026-09-13-retire-bazel-rule-landings OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-add-hermetic-terraform-rules OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-correct-terraform-ownership
LLM-disclaimer: This commit was generated by an LLM.
-
Deploy project DNS through Terraform modules
Move DNS ownership into each project’s Terraform state using shared modules. Load dnsconfig.json files at runtime, reject conflicting domain ownership, and render their records as a table. Add missing project AppRoles and scoped DNS policies, and document grouping related Terraform resources in modules.
Deploy all 45 owners sequentially: adopt 155 existing records and create 13 missing OpenHands records. Preserve every pre-existing provider record and verify no-op follow-up plans and DNS answers. Add DNS-scoped plan/show/apply wrappers with a saved-plan guard for roots that also manage services. Allow bounded aggregate path inventories large enough to deliver this migration while retaining truncation refusal in the delivery tool.
Validate runtime ownership, provider imports and preservation with isolated fixtures, Terraform formatting, wrapper builds, repository quality checks, semantic lint, and project documentation/specification builds.
OpenSpec-Change: infra/dns/openspec/changes/archive/2026-09-13-migrate-project-dns-to-terraform
LLM-disclaimer: This commit was generated by an LLM.
-
Simplify OpenSpec workspace globs
Collapse OpenSpec source globs to specs and changes, drop redundant package visibility blocks already covered by REPO.bazel, and regenerate the affected catalogs.
LLM-disclaimer: This commit was generated by an LLM.
-
Publish project sites and reproducible infrastructure diagrams
Build and deploy all 30 remaining project sites with the standard Docsy header, project descriptions and a linked documentation directory. Omit the repeated page title and generated language heading. Remove the unused cgit and xray_manager projects and retire their site resources.
Add a repeatable GitHub Pages publisher, staged Terraform bootstrap and direct GitHub Pages DNS records. Preserve repeated publication when pages is the remote default branch, and include Rules ISO in the main documentation. Document site onboarding in a registered, validated skill. Keep AL introduction short with useful links and preserve its lifecycle details in a dedicated documentation page.
Render all 15 existing infrastructure Drawio pages with pinned Drawio and Chrome inputs, sandboxed export actions, an update target and freshness checks, and include the maintained diagrams in infra/arch documentation. Paint an opaque white canvas to preserve readability in dark themes.
Validation covers project and apex builds, rendered pages, publisher tests, diagram repeatability and freshness, DNS configuration, Terraform formatting, semantic lint and repository quality.
Goal-Ref: build-and-deploy-every-project-landing-page-a782b800 Attempt-ID: attempt-00941092c164
LLM-disclaimer: This commit was generated by an LLM.
-
Extract DNSControl setup into rules_dnscontrol
Extract the DNSControl setup into
rules_dnscontrol, generate its Bazel dependency bundle from project-owned record files, and update the DNS guidance. Move Hugo rules and the worker to role-based package paths, and give each non-nested project a locally owned Hugo landing target that reuses the shared README-to-landing macro.Clean all landing and Pages DNS records so GitHub Pages serves each project subdomain directly without Cloudflare proxying. Improve the main site with a three-panel home layout, complete project links, documentation explore links, and current deployment guidance.
All affected root-workspace landing, DNS, and site targets pass, along with the nested
rules_hugotests, Buildifier, and repository quality checks.LLM-disclaimer: This commit was generated by an LLM.
-
Add hermetic repository-wide formatting and linting
Integrate upstream formatters for the repository’s meaningful tracked source and configuration file types through Bazel, and add Buildifier, Ruff, and ShellCheck lint aspects for correctness-oriented repository-wide checks.
Pin all new external tools through Bzlmod or the existing pnpm lock, add thin cache/runfiles adapters where required, expose format and check targets, and wire the checks into the pre-commit workflow. Format the existing tree and fix the correctness defects uncovered by the new checks. Preserve generated sources and exact-content fixtures that are not safely rewritable, and clarify that ordinary infrastructure build output is safe to display.
Validation:
- all 21 repository quality and compatibility formatter tests pass
- Buildifier test passes
- lint aspects analyze all 4,629 ordinary root targets without findings
- the complete 18-command root and nested full-repository audit was exercised; remaining failures are documented environment or pre-existing test limits
LLM-disclaimer: This commit was generated by an LLM.
-
Add standalone documentation rules
Move docs_filegroup into a reusable rules_docs nested Bzlmod workspace and migrate every root and nested consumer to it. Add a module-aware Gazelle language that creates docs targets only for existing README packages while preserving manual mappings.
Wire the workspace into module resolution, documentation aggregation, and the ten-command full-repo-check. Add the bazel-nested-module skill so future nested workspaces follow the repository’s rc, lockfile, docs, toolchain, Gazelle, and validation conventions.
Keep reviewed Gazelle dependency canonicalization, while protecting the hand-maintained Go proto, Python resource, Android, embedded-site, and skill runner definitions that generic language plugins would otherwise break.
This commit was generated by an LLM.
-
Gate Harbor images and refresh generated metadata
Make Harbor-backed OCI targets opt-in through –config=harbor while retaining default documentation and non-image tests. Regenerate the Python Gazelle manifest and Bazelrc preset.\n\nThis commit was generated by an LLM.
-
Migrate documentation packaging to docs_filegroup
Preserve custom prefixes, renames, strip prefixes, and standalone workspace behavior.\n\nThis commit was generated by an LLM.
- Add a server to //projects/alwaldend.com
- Add harbor_login, add harbor IaC, fix bazel’s certificates
- Remove //tools/docs, remove .github
- Change template context in rules_template, change lock format in binary_toolchain
- Finalize rules_template refactoring
- Update bazel to 8.6, start moving //tools/template_files to projects
- Add oci image to leetcode_downloader
- Remove al_go_cross_binary, update the setup guide a bit
- Add build_test tests
- Bump protobuf and java deps, update leetcode
- Revert back to REST api, update leetcode submissions
- Fix infinitime alarm update
- Move protobuf contracts into their corresponding modules
- Extract headers from HAR
- Move submission download to graphql
- Rename go modules to git.alwaldend.com/alwaldend/src
- Move all the logig out of the screen to the controller
- Add deploy to dockerhub, add //tools/oras
- Add missing features to the Pomodoro app, update project readmes, add github pages
- Move all remaining code to main
- Move a portion of tool code to main
- Move leetcode downloader go code to main
- Add tools/nogo
- Use separate lock files for each golang tool
- Start fixing go mod tidy errors
- Move some code to main
- Remove sites taxonomy, start adding xray_manager
- Add release_page generation, remove redundant release templates
- Remove contracts tree
- Allow docs to put content outside of docs, refactor git to just use .git directly
- Add cross-compilation, move leetcode downloader contracts out of //contracts
- Refactor release templates into partials, add release cards
- Add more taxonomies, remove docs tree, move alwaldend.com to projects
- Rename proto to contracts, add tools/proto add proto docs
- Remove bazel target docs, add tools/docs, tag projects properly
- Remove changelogs, ignore irrelevant directories in docs
- Remove bzl tree
- Initial commit
-
Add spellcheck skill
This commit was generated by an LLM.
-
Restore light and dark site canvases and set the shared accent
The shared Docsy canvas set the same Bootstrap dark palette and the same black page background on
:root,[data-bs-theme="light"], and[data-bs-theme="dark"], so the light/dark toggle changed nothing. The site also rendered Bootstrap’s stock blue instead of its intended accent.Split the shared palette so light mode uses a pure white canvas with the light-mode palette and dark mode uses a pure black canvas with the dark-mode palette, and keep the pre-stylesheet paint and footer on the active mode. Assign
$primaryto#7c3aedbefore Bootstrap compiles, so links, buttons, badges, focus rings, and the dark-mode link tint all derive from one value rather than from a site-local copy.Both files stay in the reusable shell; the apex site consumes them through the existing declared exports and no longer carries the footer’s own blue.
OpenSpec-Change: projects/hugo_landing/openspec/changes/restore-light-dark-canvas-and-accent
LLM-disclaimer: This commit was generated by an LLM.
1.13.3.1 - head
-
Move project landings into the main site
Publish every registered project’s visitor-facing landing page at /projects/
/ from the main site instead of a dedicated subdomain, and retire the per-project Pages repository, CNAME, and Terraform DNS stage that existed only to serve one page derived from the project README. Each project owns its landing content in projects/
/site/content/ as pure content: no layouts, styles, or build rules. The main site packages those directories into content/projects/ / from the registry in projects/projects.bzl, so membership is declared once. The landing is a short hand-written page for visitors while the README keeps its /docs/projects/ / URL for repository reference documentation, and landing front matter now feeds the statuses, languages, and tags taxonomies. Merge the reusable hugo_landing project into the main site: its shared canvas and accent styles and its landing page rules move into the apex tree, and its landing macro, generated configuration, standalone publisher, and repository-relative rewrite layouts are removed. The theme keeps owning the taxonomy and term layouts, which are richer than the heading-only versions the reusable project carried. Remove the now-unused apex deploy_project.sh and deploy_all.sh landing publishers with it.
Retire the per-project publication and DNS ownership: the project landing targets and the landing deployment command, each landing project’s dnsconfig.json and Terraform root, the build plumbing that served only those stages, and the landing repository and Pages membership in the repository catalog. The apex Terraform root is retained because it also declares VM resources, and no Vault configuration is changed.
Replace the provider-snapshot zone files with generated declaration pages, one per destination view, that project the checked-in declarations and are verified for freshness by the DNS offline check. The DNS linter, both destination pages, the apex site, the skills projection, and the repository quality suite pass, and the whole repository builds.
OpenSpec-Change: projects/alwaldend.com/openspec/changes/consolidate-project-landings-into-apex
LLM-disclaimer: This commit was generated by an LLM.
-
Manage forge resources with hermetic Terraform rules
Centralize organization, repository, and named access configuration in infra/repos. Adopt existing GitHub resources, protect master defaults while retaining Pages publication on pages, and preserve existing repository identities. Manage GitLab one-time imports, the F-Droid metadata fork, and default-branch protections through Vault-backed authentication. Forgejo consumes the same catalog. Ongoing repository synchronization is deferred.
Retire the eleven Bazel rule landing sites through their owning Terraform workflows, removing their DNS records, Pages repositories, and landing configuration. Move all twelve existing standalone rule modules into tools/ and retain their public interfaces and documentation on the main site.
Add tools/rules_terraform with verified provider downloads, packed mirrors in runfiles, and reusable Terraform execution rules. Enforce one version per provider source at an extensible resolution boundary. Migrate every Terraform consumer to thirteen shared provider pins in third_party/terraform. Execution and command maps belong to rules_terraform; consumers explicitly select generic AL wrappers for authentication and Vault injection. Remove tools/terraform and all 43 checked-in Terraform provider locks. Validate installed providers against the declared archives before execution.
Validation covers all fourteen workspace builds, all thirteen standalone test suites, Terraform consumers, offline real-provider regressions, rendered documentation, formatting, and semantic lint. The full root test run has 295 passing tests and one skip; its only failure is the historical secret scan, reduced to four pre-existing synthetic fixture matches. Earlier live imports and the exact landing retirement scope have verified postconditions; the Terraform rules migration uses only offline implementation checks.
OpenSpec-Change: infra/repos/openspec/changes/archive/2026-09-13-adopt-shared-repository-catalog OpenSpec-Change: infra/src/openspec/changes/archive/2026-09-13-retire-bazel-rule-landings OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-add-hermetic-terraform-rules OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-correct-terraform-ownership
LLM-disclaimer: This commit was generated by an LLM.
-
Deploy project DNS through Terraform modules
Move DNS ownership into each project’s Terraform state using shared modules. Load dnsconfig.json files at runtime, reject conflicting domain ownership, and render their records as a table. Add missing project AppRoles and scoped DNS policies, and document grouping related Terraform resources in modules.
Deploy all 45 owners sequentially: adopt 155 existing records and create 13 missing OpenHands records. Preserve every pre-existing provider record and verify no-op follow-up plans and DNS answers. Add DNS-scoped plan/show/apply wrappers with a saved-plan guard for roots that also manage services. Allow bounded aggregate path inventories large enough to deliver this migration while retaining truncation refusal in the delivery tool.
Validate runtime ownership, provider imports and preservation with isolated fixtures, Terraform formatting, wrapper builds, repository quality checks, semantic lint, and project documentation/specification builds.
OpenSpec-Change: infra/dns/openspec/changes/archive/2026-09-13-migrate-project-dns-to-terraform
LLM-disclaimer: This commit was generated by an LLM.
-
Simplify OpenSpec workspace globs
Collapse OpenSpec source globs to specs and changes, drop redundant package visibility blocks already covered by REPO.bazel, and regenerate the affected catalogs.
LLM-disclaimer: This commit was generated by an LLM.
-
Publish project sites and reproducible infrastructure diagrams
Build and deploy all 30 remaining project sites with the standard Docsy header, project descriptions and a linked documentation directory. Omit the repeated page title and generated language heading. Remove the unused cgit and xray_manager projects and retire their site resources.
Add a repeatable GitHub Pages publisher, staged Terraform bootstrap and direct GitHub Pages DNS records. Preserve repeated publication when pages is the remote default branch, and include Rules ISO in the main documentation. Document site onboarding in a registered, validated skill. Keep AL introduction short with useful links and preserve its lifecycle details in a dedicated documentation page.
Render all 15 existing infrastructure Drawio pages with pinned Drawio and Chrome inputs, sandboxed export actions, an update target and freshness checks, and include the maintained diagrams in infra/arch documentation. Paint an opaque white canvas to preserve readability in dark themes.
Validation covers project and apex builds, rendered pages, publisher tests, diagram repeatability and freshness, DNS configuration, Terraform formatting, semantic lint and repository quality.
Goal-Ref: build-and-deploy-every-project-landing-page-a782b800 Attempt-ID: attempt-00941092c164
LLM-disclaimer: This commit was generated by an LLM.
-
Extract DNSControl setup into rules_dnscontrol
Extract the DNSControl setup into
rules_dnscontrol, generate its Bazel dependency bundle from project-owned record files, and update the DNS guidance. Move Hugo rules and the worker to role-based package paths, and give each non-nested project a locally owned Hugo landing target that reuses the shared README-to-landing macro.Clean all landing and Pages DNS records so GitHub Pages serves each project subdomain directly without Cloudflare proxying. Improve the main site with a three-panel home layout, complete project links, documentation explore links, and current deployment guidance.
All affected root-workspace landing, DNS, and site targets pass, along with the nested
rules_hugotests, Buildifier, and repository quality checks.LLM-disclaimer: This commit was generated by an LLM.
-
Add hermetic repository-wide formatting and linting
Integrate upstream formatters for the repository’s meaningful tracked source and configuration file types through Bazel, and add Buildifier, Ruff, and ShellCheck lint aspects for correctness-oriented repository-wide checks.
Pin all new external tools through Bzlmod or the existing pnpm lock, add thin cache/runfiles adapters where required, expose format and check targets, and wire the checks into the pre-commit workflow. Format the existing tree and fix the correctness defects uncovered by the new checks. Preserve generated sources and exact-content fixtures that are not safely rewritable, and clarify that ordinary infrastructure build output is safe to display.
Validation:
- all 21 repository quality and compatibility formatter tests pass
- Buildifier test passes
- lint aspects analyze all 4,629 ordinary root targets without findings
- the complete 18-command root and nested full-repository audit was exercised; remaining failures are documented environment or pre-existing test limits
LLM-disclaimer: This commit was generated by an LLM.
-
Add standalone documentation rules
Move docs_filegroup into a reusable rules_docs nested Bzlmod workspace and migrate every root and nested consumer to it. Add a module-aware Gazelle language that creates docs targets only for existing README packages while preserving manual mappings.
Wire the workspace into module resolution, documentation aggregation, and the ten-command full-repo-check. Add the bazel-nested-module skill so future nested workspaces follow the repository’s rc, lockfile, docs, toolchain, Gazelle, and validation conventions.
Keep reviewed Gazelle dependency canonicalization, while protecting the hand-maintained Go proto, Python resource, Android, embedded-site, and skill runner definitions that generic language plugins would otherwise break.
This commit was generated by an LLM.
-
Gate Harbor images and refresh generated metadata
Make Harbor-backed OCI targets opt-in through –config=harbor while retaining default documentation and non-image tests. Regenerate the Python Gazelle manifest and Bazelrc preset.\n\nThis commit was generated by an LLM.
-
Migrate documentation packaging to docs_filegroup
Preserve custom prefixes, renames, strip prefixes, and standalone workspace behavior.\n\nThis commit was generated by an LLM.
- Add a server to //projects/alwaldend.com
- Add harbor_login, add harbor IaC, fix bazel’s certificates
- Remove //tools/docs, remove .github
- Change template context in rules_template, change lock format in binary_toolchain
- Finalize rules_template refactoring
- Update bazel to 8.6, start moving //tools/template_files to projects
- Add oci image to leetcode_downloader
- Remove al_go_cross_binary, update the setup guide a bit
- Add build_test tests
- Bump protobuf and java deps, update leetcode
- Revert back to REST api, update leetcode submissions
- Fix infinitime alarm update
- Move protobuf contracts into their corresponding modules
- Extract headers from HAR
- Move submission download to graphql
- Rename go modules to git.alwaldend.com/alwaldend/src
- Move all the logig out of the screen to the controller
- Add deploy to dockerhub, add //tools/oras
- Add missing features to the Pomodoro app, update project readmes, add github pages
- Move all remaining code to main
- Move a portion of tool code to main
- Move leetcode downloader go code to main
- Add tools/nogo
- Use separate lock files for each golang tool
- Start fixing go mod tidy errors
- Move some code to main
- Remove sites taxonomy, start adding xray_manager
- Add release_page generation, remove redundant release templates
- Remove contracts tree
- Allow docs to put content outside of docs, refactor git to just use .git directly
- Add cross-compilation, move leetcode downloader contracts out of //contracts
- Refactor release templates into partials, add release cards
- Add more taxonomies, remove docs tree, move alwaldend.com to projects
- Rename proto to contracts, add tools/proto add proto docs
- Remove bazel target docs, add tools/docs, tag projects properly
- Remove changelogs, ignore irrelevant directories in docs
- Remove bzl tree
- Initial commit
-
Add spellcheck skill
This commit was generated by an LLM.
-
Restore light and dark site canvases and set the shared accent
The shared Docsy canvas set the same Bootstrap dark palette and the same black page background on
:root,[data-bs-theme="light"], and[data-bs-theme="dark"], so the light/dark toggle changed nothing. The site also rendered Bootstrap’s stock blue instead of its intended accent.Split the shared palette so light mode uses a pure white canvas with the light-mode palette and dark mode uses a pure black canvas with the dark-mode palette, and keep the pre-stylesheet paint and footer on the active mode. Assign
$primaryto#7c3aedbefore Bootstrap compiles, so links, buttons, badges, focus rings, and the dark-mode link tint all derive from one value rather than from a site-local copy.Both files stay in the reusable shell; the apex site consumes them through the existing declared exports and no longer carries the footer’s own blue.
OpenSpec-Change: projects/hugo_landing/openspec/changes/restore-light-dark-canvas-and-accent
LLM-disclaimer: This commit was generated by an LLM.
1.14 - MCP Cordis
mcp_cordis is a standalone stdio MCP server that mounts runtime JavaScript
packages through Cordis.
It is intentionally an MCP server, not a Codex plugin bundle.
Reusable definitions are ordinary ESM files in
projects/mcp_cordis/plugins, listed by projects/mcp_cordis/cordis.yaml.
Disposable definitions use the same layout under
out/<task>/mcp_cordis/runs/<run>/. Each run writes a bounded manifest with
explicit task, run, worker, information, budget, retention, lock, and cleanup
fields. AGENT_TASK_ID, AGENT_RUN_ID, and AGENT_WORKER_ID may provide
stable identities; the launcher otherwise creates process-scoped identities.
Every
package is addressed by both scope and name, so a scratch package never
silently shadows a reusable package.
Run
The repository’s .codex/config.toml registers mcp_cordis as a
project-scoped stdio server. Codex loads that file for a trusted workspace and
finds the active Git worktree before starting the server. Separate clones and
worktrees therefore use their own source, projects/mcp_cordis packages, and
task/run-namespaced scratch packages. Trusting the repository’s root checkout
also covers its linked worktrees; a glob trust entry is neither needed nor
supported. A new Codex session is needed after the MCP registration itself is
first added; package changes after that do not require another session.
The registration calls cmd/mcp_cordis/launch.sh. With a current installed
bazel_agent, the launcher selects a content-addressed runtime from the
per-user tool cache and executes it directly. The first exact source version
is built and atomically installed under a per-key lock; subsequent worktrees
with the same inputs do not start Bazel or load a configured graph. An older
runner falls back to asking Bazel for a launch script under the task’s ignored
out directory. Either path releases Bazel’s output-base lock before the
long-lived stdio server starts, so builds and tests can run normally while
Codex remains connected.
The cached artifact contains the stable server runtime and pinned JavaScript
dependencies, but not cordis.yaml or reusable plugins. It always reads those
from the explicit active workspace, so editing a package changes live behavior
without repackaging the runtime or selecting a new cache key.
The same project configuration starts an optional asynchronous SessionStart
hook that starts the worktree’s Bazel server and warms repo_delivery. It
produces no session context, ignores failure, and never queries the whole
workspace graph. Cordis itself is already warmed by its MCP launch path, so the
hook does not start a duplicate Cordis build.
To build and run the server directly from the repository root:
bazel_agent bazel run //projects/mcp_cordis:mcp_cordis -- \
--workspace-root "$PWD" \
--task-id example-task \
--run-id example-run
The workspace root is mandatory unless BUILD_WORKSPACE_DIRECTORY is
present. The checked-in launcher resolves the current Git worktree explicitly
and supplies that path to the server.
The fixed cordis_* tools define, start, inspect, invoke, update, stop,
remove, and promote packages without reconnecting the MCP client. Package
handlers are called through cordis_invoke; this remains reliable even when
an MCP client caches its initial tool list.
Cordis configuration and plugin format
cordis.yaml uses the standard Cordis Include entry-list format:
- id: hello
name: ./plugins/hello.mjs
The referenced file is a normal ESM Cordis plugin:
const plugin = {
description: "Provide a greeting.",
apply(ctx) {
ctx.tool(
{
name: "hello_world",
description: "Return a greeting.",
inputSchema: {
type: "object",
properties: { name: { type: "string" } },
additionalProperties: false,
},
},
({ name = "world" }) => ({ greeting: `Hello, ${name}!` }),
);
},
};
plugin.apply.description = plugin.description;
export default plugin;
Cordis normalizes an object plugin to its apply callback. Attaching the
optional package description to that callback exposes it through
cordis_list and cordis_inspect; tool descriptions remain part of each
ctx.tool() definition.
The server mounts the official Cordis Loader, Include, and HMR services.
cordis_define syntax-checks and atomically persists the ordinary module.
Creating or enabling an entry refreshes any cached module through Cordis HMR,
then uses the public Include refresh API and waits for activation. Updating an
already-running entry returns activation: "pending"; poll cordis_invoke or
cordis_list_tools until the new behavior is visible.
The reproducibly pinned HMR package carries a focused pnpm patch that
serializes module reloads and drains source changes arriving during an
in-flight reload, so the latest persisted source is not lost.
Syntax errors are rejected before the file changes. Evaluation and apply()
failures follow native Cordis HMR behavior; the wrapper does not add a second
activation transaction around them. It also does not inject source markers,
inspect Loader caches, correlate watcher events, or maintain its own source
rollback/version store. Reusable history is normal Git history. Manual edits
to watched plugin files are also picked up by Cordis HMR.
Runtime modules use normal Cordis semantics, including static imports,
top-level await, and asynchronous apply(ctx, config). Package code is
trusted: a never-settling module evaluation or activation can therefore stall
Cordis lifecycle work. The stdio launcher reserves its protocol stream and
redirects package stdout to stderr, keeping accidental console.log() calls
off the JSON-RPC wire.
The package context exposes ctx.workspaceRoot, ctx.resolveWorkspace(),
ctx.readText(), and structured ctx.exec() in addition to ctx.tool().
ctx.exec() returns code, signal, stdout, stderr, truncated, and
outputLimitExceeded; maxBytes is a combined stdout/stderr budget. By
default, exceeding that budget or producing invalid UTF-8 rejects with
EXEC_OUTPUT_LIMIT or EXEC_INVALID_UTF8. Packages that explicitly set
allowTruncatedOutput: true instead receive the valid retained prefix with
truncated set; outputLimitExceeded distinguishes the byte cap from UTF-8
loss. A Fiber-owned supervisor admits each launch atomically, and results
settle only after the direct child and every live member of its original Linux
process group have stopped. Limits, timeouts, and plugin disposal use the same
cleanup path. A process that deliberately creates a new session escapes that
group and is outside this trusted-package contract. ctx.exec() therefore
fails closed with EXEC_UNSUPPORTED_PLATFORM away from Linux. Package code
also has normal Node built-ins; this host is a reliability boundary, not a
security sandbox.
cordis_invoke.timeout_ms bounds how long the gateway waits for a result; it
does not cancel an already admitted JavaScript handler. The handler keeps its
Fiber lease until it finishes, so stop, remove, and shutdown wait for it.
Cordis HMR waits for a retired Fiber to finish draining before it activates
and publishes the replacement, so a live invocation can delay a reload. Any
ctx.exec() launched by a timed-out invocation is cancelled and its process
group is confirmed stopped before the timeout response settles.
Included packages
repo_context: bounded repository reads and searches.git_worktree: read-only branch, status, log, and comparison snapshots.network_probe: DNS, TCP/TLS, and HTTP diagnostics.
These were selected from aggregate recurring task categories in recent local sessions. No transcript content, credentials, or private outputs are included.
Maintained change history
The completed runtime extensions change preserves acceptance criteria, decisions, failed attempts and supporting evidence. New work uses the project OpenSpec workspace and a new change; the archived acceptance remains historical.
Dependency notices
The runtime directly uses @deepseek-ai/cordis, its official Loader, Include,
HMR, and Timer plugins, and the Model Context Protocol TypeScript SDK. Their
license texts are retained in the resolved package artifacts by the pinned
pnpm/Bazel dependency graph.
1.15 - Nexus security plugin
This plugin allows you to perform a check every time an artifact is requested from a repository
Links
Features
- A request handler that checks all requests to repositories
- Capability controlling the request handler
- A task that periodically updates the capability using a remote source
- Sonatype Nexus 3 plugin
- Java
Flow
1.15.1 - Model
org.sonatype.nexus.repository.view.Response
etag: c849a44121f823c806f604d6568d9e89 (class java.lang.String)
last_modified: 2021-10-22T15:57:10.000Z (class org.joda.time.DateTime)
hashCodesMap: (class java.util.HashMap)
org.sonatype.nexus.common.hash.HashAlgorithm@7ce01bd8: bcbb583a5a4b4767de8ac020dea3d54011fee961
org.sonatype.nexus.common.hash.HashAlgorithm@5a3efc26: deaf32dcd9ab821e359cd8330786bcd077604b5c5730c0b096eda46f95c24a2d
org.sonatype.nexus.common.hash.HashAlgorithm@5b0c0740: c849a44121f823c806f604d6568d9e89
org.sonatype.nexus.repository.storage.Asset:
metadata: (AttachedEntityMetadata)
schema: assetPath
document:
"#74:0": >-
bucket:#57:1,format:pypi,last_updated:Fri Jul 01 12:46:21 UTC 2022,attributes:[5],component:#65:0,
name:packages/pip/21.3.1/pip-21.3.1-py3-none-any.whl,size:1723581,content_type:application/zip,created_by:anonymous,
created_by_ip:80.78.253.49,blob_ref:default@E1F281C2-0A159DAD-4208CEFD-524F990B-0B4DDE11:739a4ecb-73fc-4422-a7d7-c93c8ad069c6,
last_downloaded:Fri Jul 01 04:44:03 UTC 2022,blob_created:Wed Jun 29 07:01:34 UTC 2022,blob_updated:Wed Jun 29 07:01:34 UTC 2022
name: packages/pip/21.3.1/pip-21.3.1-py3-none-any.whl
org.sonatype.nexus.repository.cache.CacheInfo:
lastVerified: 2022-07-01T12:46:21.457Z
cacheToken: 'null'
org.sonatype.nexus.repository.view.Request
org.apache.shiro.subject.support.DefaultSubjectContext.SESSION_CREATION_ENABLED: false (class java.lang.Boolean)
Key[type=org.sonatype.nexus.security.SecurityFilter, annotation=[none]].FILTERED: true (class java.lang.Boolean)
authcAntiCsrf.FILTERED: true (class java.lang.Boolean)
nx-authc.FILTERED: true (class java.lang.Boolean)
org.apache.shiro.web.servlet.ShiroHttpServletRequest_SESSION_ID_URL_REWRITING_ENABLED: false (class java.lang.Boolean)
javax.servlet.include.servlet_path: /repository/pypi/packages/pip/21.3.1/pip-21.3.1-py3-none-any.whl (class java.lang.String)
nexus.user.principal: admin (class java.lang.String)
nx-anonymous.FILTERED: true (class java.lang.Boolean)
nexus.user.id: admin (class java.lang.String)
nx-apikey-authc.FILTERED: true (class java.lang.Boolean)
org.sonatype.nexus.repository.view.Context
security.authorized: true (class java.lang.Boolean)
nexus.analytics.format_request_rates.marked: true (class java.lang.Boolean)
com.sonatype.nexus.repository.pypi.AssetKind: PACKAGE (class com.sonatype.nexus.repository.pypi.AssetKind)
local.attribute.org.sonatype.nexus.repository.view.handlers.HandlerContributor.extended: true (class java.lang.Boolean)
org.sonatype.nexus.repository.view.matchers.token.TokenMatcher$State: >-
org.sonatype.nexus.repository.view.matchers.token.TokenMatcher$1@19f23c0b ((class org.sonatype.nexus.repository.view.matchers.token.TokenMatcher$1))
org.sonatype.nexus.repository.Repository
proxy: (class java.util.HashMap)
contentMaxAge: 0.0
remoteUrl: https://pypi.org
metadataMaxAge: 0.0
negativeCache: (class java.util.HashMap)
timeToLive: 0.0
enabled: false
storage: (class java.util.HashMap)
strictContentTypeValidation: false
blobStoreName: default
httpclient: (class java.util.HashMap)
blocked: false
connection:
useTrustStore: true
autoBlock: false
org.sonatype.nexus.repository.storage.Asset
checksum: (class org.sonatype.nexus.common.collect.DetachingMap)
sha1: bcbb583a5a4b4767de8ac020dea3d54011fee961
sha256: deaf32dcd9ab821e359cd8330786bcd077604b5c5730c0b096eda46f95c24a2d
md5: c849a44121f823c806f604d6568d9e89
cache: (class org.sonatype.nexus.common.collect.DetachingMap)
last_verified: Fri Jul 01 13:07:08 UTC 2022
provenance: (class org.sonatype.nexus.common.collect.DetachingMap)
hashes_not_verified: false
pypi: (class org.sonatype.nexus.common.collect.DetachingMap)
summary: The PyPA recommended tool for installing Python packages
author: The pip developers
description: ...
content:
etag: c849a44121f823c806f604d6568d9e89
last_modified: Fri Oct 22 15:57:10 UTC 2021
org.sonatype.nexus.repository.view.Content
etag: c849a44121f823c806f604d6568d9e89
last_modified: 2021-10-22T15:57:10.000Z (class org.joda.time.DateTime)
hashCodesMap: (class java.util.HashMap)
org.sonatype.nexus.common.hash.HashAlgorithm@3d97cbd0: deaf32dcd9ab821e359cd8330786bcd077604b5c5730c0b096eda46f95c24a2d, org.sonatype.nexus.common.hash.HashAlgorithm@675317cb=c849a44121f823c806f604d6568d9e89
org.sonatype.nexus.common.hash.HashAlgorithm@67bcbee7: bcbb583a5a4b4767de8ac020dea3d54011fee961
org.sonatype.nexus.repository.storage.Asset: (class org.sonatype.nexus.repository.storage.Asset)
metadata: (AttachedEntityMetadata)
schema: assetPath
document: (#74:0)
bucket: #57:1
format: pypi
last_updated: Fri Jul 01 13:25:15 UTC 2022
attributes: [5]
component: #65:0
name: packages/pip/21.3.1/pip-21.3.1-py3-none-any.whl
size: 1723581
content_type: application/zip
created_by: anonymous
created_by_ip: 80.78.253.49
blob_ref: default@E1F281C2-0A159DAD-4208CEFD-524F990B-0B4DDE11:739a4ecb-73fc-4422-a7d7-c93c8ad069c6
last_downloaded: Fri Jul 01 04:44:03 UTC 2022
blob_created: Wed Jun 29 07:01:34 UTC 2022
blob_updated: Wed Jun 29 07:01:34 UTC 2022
name: packages/pip/21.3.1/pip-21.3.1-py3-none-any.whl
org.sonatype.nexus.repository.cache.CacheInfo: (class org.sonatype.nexus.repository.cache.CacheInfo)
lastVerified: 2022-07-01T13:25:14.841Z
cacheToken: 'null'
1.15.2 - Releases
head
-
Move project landings into the main site
Publish every registered project’s visitor-facing landing page at /projects/
/ from the main site instead of a dedicated subdomain, and retire the per-project Pages repository, CNAME, and Terraform DNS stage that existed only to serve one page derived from the project README. Each project owns its landing content in projects/
/site/content/ as pure content: no layouts, styles, or build rules. The main site packages those directories into content/projects/ / from the registry in projects/projects.bzl, so membership is declared once. The landing is a short hand-written page for visitors while the README keeps its /docs/projects/ / URL for repository reference documentation, and landing front matter now feeds the statuses, languages, and tags taxonomies. Merge the reusable hugo_landing project into the main site: its shared canvas and accent styles and its landing page rules move into the apex tree, and its landing macro, generated configuration, standalone publisher, and repository-relative rewrite layouts are removed. The theme keeps owning the taxonomy and term layouts, which are richer than the heading-only versions the reusable project carried. Remove the now-unused apex deploy_project.sh and deploy_all.sh landing publishers with it.
Retire the per-project publication and DNS ownership: the project landing targets and the landing deployment command, each landing project’s dnsconfig.json and Terraform root, the build plumbing that served only those stages, and the landing repository and Pages membership in the repository catalog. The apex Terraform root is retained because it also declares VM resources, and no Vault configuration is changed.
Replace the provider-snapshot zone files with generated declaration pages, one per destination view, that project the checked-in declarations and are verified for freshness by the DNS offline check. The DNS linter, both destination pages, the apex site, the skills projection, and the repository quality suite pass, and the whole repository builds.
OpenSpec-Change: projects/alwaldend.com/openspec/changes/consolidate-project-landings-into-apex
LLM-disclaimer: This commit was generated by an LLM.
-
Manage forge resources with hermetic Terraform rules
Centralize organization, repository, and named access configuration in infra/repos. Adopt existing GitHub resources, protect master defaults while retaining Pages publication on pages, and preserve existing repository identities. Manage GitLab one-time imports, the F-Droid metadata fork, and default-branch protections through Vault-backed authentication. Forgejo consumes the same catalog. Ongoing repository synchronization is deferred.
Retire the eleven Bazel rule landing sites through their owning Terraform workflows, removing their DNS records, Pages repositories, and landing configuration. Move all twelve existing standalone rule modules into tools/ and retain their public interfaces and documentation on the main site.
Add tools/rules_terraform with verified provider downloads, packed mirrors in runfiles, and reusable Terraform execution rules. Enforce one version per provider source at an extensible resolution boundary. Migrate every Terraform consumer to thirteen shared provider pins in third_party/terraform. Execution and command maps belong to rules_terraform; consumers explicitly select generic AL wrappers for authentication and Vault injection. Remove tools/terraform and all 43 checked-in Terraform provider locks. Validate installed providers against the declared archives before execution.
Validation covers all fourteen workspace builds, all thirteen standalone test suites, Terraform consumers, offline real-provider regressions, rendered documentation, formatting, and semantic lint. The full root test run has 295 passing tests and one skip; its only failure is the historical secret scan, reduced to four pre-existing synthetic fixture matches. Earlier live imports and the exact landing retirement scope have verified postconditions; the Terraform rules migration uses only offline implementation checks.
OpenSpec-Change: infra/repos/openspec/changes/archive/2026-09-13-adopt-shared-repository-catalog OpenSpec-Change: infra/src/openspec/changes/archive/2026-09-13-retire-bazel-rule-landings OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-add-hermetic-terraform-rules OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-correct-terraform-ownership
LLM-disclaimer: This commit was generated by an LLM.
-
Deploy project DNS through Terraform modules
Move DNS ownership into each project’s Terraform state using shared modules. Load dnsconfig.json files at runtime, reject conflicting domain ownership, and render their records as a table. Add missing project AppRoles and scoped DNS policies, and document grouping related Terraform resources in modules.
Deploy all 45 owners sequentially: adopt 155 existing records and create 13 missing OpenHands records. Preserve every pre-existing provider record and verify no-op follow-up plans and DNS answers. Add DNS-scoped plan/show/apply wrappers with a saved-plan guard for roots that also manage services. Allow bounded aggregate path inventories large enough to deliver this migration while retaining truncation refusal in the delivery tool.
Validate runtime ownership, provider imports and preservation with isolated fixtures, Terraform formatting, wrapper builds, repository quality checks, semantic lint, and project documentation/specification builds.
OpenSpec-Change: infra/dns/openspec/changes/archive/2026-09-13-migrate-project-dns-to-terraform
LLM-disclaimer: This commit was generated by an LLM.
-
Simplify OpenSpec workspace globs
Collapse OpenSpec source globs to specs and changes, drop redundant package visibility blocks already covered by REPO.bazel, and regenerate the affected catalogs.
LLM-disclaimer: This commit was generated by an LLM.
-
Publish project sites and reproducible infrastructure diagrams
Build and deploy all 30 remaining project sites with the standard Docsy header, project descriptions and a linked documentation directory. Omit the repeated page title and generated language heading. Remove the unused cgit and xray_manager projects and retire their site resources.
Add a repeatable GitHub Pages publisher, staged Terraform bootstrap and direct GitHub Pages DNS records. Preserve repeated publication when pages is the remote default branch, and include Rules ISO in the main documentation. Document site onboarding in a registered, validated skill. Keep AL introduction short with useful links and preserve its lifecycle details in a dedicated documentation page.
Render all 15 existing infrastructure Drawio pages with pinned Drawio and Chrome inputs, sandboxed export actions, an update target and freshness checks, and include the maintained diagrams in infra/arch documentation. Paint an opaque white canvas to preserve readability in dark themes.
Validation covers project and apex builds, rendered pages, publisher tests, diagram repeatability and freshness, DNS configuration, Terraform formatting, semantic lint and repository quality.
Goal-Ref: build-and-deploy-every-project-landing-page-a782b800 Attempt-ID: attempt-00941092c164
LLM-disclaimer: This commit was generated by an LLM.
-
Repair site navigation and simplify page layout
Show one homepage panel with vertically stacked GitHub and Docs rows using the name: URL format, hiding the protocol and trailing slash in the link text. Center the panel and cap its width at 40rem while allowing it to shrink on mobile. Move it slightly lower on desktop and brighten the footer link. Restore the project assets mount so custom styles load. Reduce the footer to its content height with compact padding. Size the homepage against the visible viewport so mobile browser controls do not hide its footer. Remove the separate Projects page and its header link, while keeping project documentation under Docs. Remove the introductory homepage copy and visible title.
Resolve Markdown links and images from their source locations, package missing documentation and book covers, correct source links, and scope anchors and release controls in combined print pages. Restore the archive-root CNAME explicitly during deployment so replacing the site preserves the custom domain.
Validate generated HTML for missing internal files and fragments, duplicate IDs, image alternatives, and the homepage, Misc source-link, and Goal diagram regressions. Check the production build, repository quality, affected-target semantic lint, desktop and mobile homepage rendering, and deployment output.
Goal-Ref: out/site-fix/goals/fix-local-alwaldend-com-layout-and-links-a2e69a4e Attempt-ID: attempt-165dd5be7d71
LLM-disclaimer: This commit was generated by an LLM.
-
Extract DNSControl setup into rules_dnscontrol
Extract the DNSControl setup into
rules_dnscontrol, generate its Bazel dependency bundle from project-owned record files, and update the DNS guidance. Move Hugo rules and the worker to role-based package paths, and give each non-nested project a locally owned Hugo landing target that reuses the shared README-to-landing macro.Clean all landing and Pages DNS records so GitHub Pages serves each project subdomain directly without Cloudflare proxying. Improve the main site with a three-panel home layout, complete project links, documentation explore links, and current deployment guidance.
All affected root-workspace landing, DNS, and site targets pass, along with the nested
rules_hugotests, Buildifier, and repository quality checks.LLM-disclaimer: This commit was generated by an LLM.
-
Add hermetic repository-wide formatting and linting
Integrate upstream formatters for the repository’s meaningful tracked source and configuration file types through Bazel, and add Buildifier, Ruff, and ShellCheck lint aspects for correctness-oriented repository-wide checks.
Pin all new external tools through Bzlmod or the existing pnpm lock, add thin cache/runfiles adapters where required, expose format and check targets, and wire the checks into the pre-commit workflow. Format the existing tree and fix the correctness defects uncovered by the new checks. Preserve generated sources and exact-content fixtures that are not safely rewritable, and clarify that ordinary infrastructure build output is safe to display.
Validation:
- all 21 repository quality and compatibility formatter tests pass
- Buildifier test passes
- lint aspects analyze all 4,629 ordinary root targets without findings
- the complete 18-command root and nested full-repository audit was exercised; remaining failures are documented environment or pre-existing test limits
LLM-disclaimer: This commit was generated by an LLM.
-
Add standalone documentation rules
Move docs_filegroup into a reusable rules_docs nested Bzlmod workspace and migrate every root and nested consumer to it. Add a module-aware Gazelle language that creates docs targets only for existing README packages while preserving manual mappings.
Wire the workspace into module resolution, documentation aggregation, and the ten-command full-repo-check. Add the bazel-nested-module skill so future nested workspaces follow the repository’s rc, lockfile, docs, toolchain, Gazelle, and validation conventions.
Keep reviewed Gazelle dependency canonicalization, while protecting the hand-maintained Go proto, Python resource, Android, embedded-site, and skill runner definitions that generic language plugins would otherwise break.
This commit was generated by an LLM.
-
Complete docs filegroup migration
Pass ordinary documentation sources directly and isolate generated or renamed outputs in semantic pkg_files dependencies. Remove the obsolete renames and strip_prefix surface from docs_filegroup.\n\nThis commit was generated by an LLM.
-
Migrate documentation packaging to docs_filegroup
Preserve custom prefixes, renames, strip prefixes, and standalone workspace behavior.\n\nThis commit was generated by an LLM.
- Add //third_party/org_kernel_headers, rename all deps files to include
- Remove //tools/docs, remove .github
- Migrate go code of ci_platform
- Fix model README
- Migrate nexus_security_plugin to bazel
- Fix java builds broken after protobuf upgrade
- Add missing features to the Pomodoro app, update project readmes, add github pages
- Move all remaining code to main
- Add more taxonomies, remove docs tree, move alwaldend.com to projects
- Remove bazel target docs, add tools/docs, tag projects properly
- Remove changelogs, ignore irrelevant directories in docs
- Move another group of rules to tools/
- Move a group of rules to tools/
- Remove kt tree
- Initial commit
-
Add spellcheck skill
This commit was generated by an LLM.
-
Restore light and dark site canvases and set the shared accent
The shared Docsy canvas set the same Bootstrap dark palette and the same black page background on
:root,[data-bs-theme="light"], and[data-bs-theme="dark"], so the light/dark toggle changed nothing. The site also rendered Bootstrap’s stock blue instead of its intended accent.Split the shared palette so light mode uses a pure white canvas with the light-mode palette and dark mode uses a pure black canvas with the dark-mode palette, and keep the pre-stylesheet paint and footer on the active mode. Assign
$primaryto#7c3aedbefore Bootstrap compiles, so links, buttons, badges, focus rings, and the dark-mode link tint all derive from one value rather than from a site-local copy.Both files stay in the reusable shell; the apex site consumes them through the existing declared exports and no longer carries the footer’s own blue.
OpenSpec-Change: projects/hugo_landing/openspec/changes/restore-light-dark-canvas-and-accent
LLM-disclaimer: This commit was generated by an LLM.
1.15.2.1 - head
-
Move project landings into the main site
Publish every registered project’s visitor-facing landing page at /projects/
/ from the main site instead of a dedicated subdomain, and retire the per-project Pages repository, CNAME, and Terraform DNS stage that existed only to serve one page derived from the project README. Each project owns its landing content in projects/
/site/content/ as pure content: no layouts, styles, or build rules. The main site packages those directories into content/projects/ / from the registry in projects/projects.bzl, so membership is declared once. The landing is a short hand-written page for visitors while the README keeps its /docs/projects/ / URL for repository reference documentation, and landing front matter now feeds the statuses, languages, and tags taxonomies. Merge the reusable hugo_landing project into the main site: its shared canvas and accent styles and its landing page rules move into the apex tree, and its landing macro, generated configuration, standalone publisher, and repository-relative rewrite layouts are removed. The theme keeps owning the taxonomy and term layouts, which are richer than the heading-only versions the reusable project carried. Remove the now-unused apex deploy_project.sh and deploy_all.sh landing publishers with it.
Retire the per-project publication and DNS ownership: the project landing targets and the landing deployment command, each landing project’s dnsconfig.json and Terraform root, the build plumbing that served only those stages, and the landing repository and Pages membership in the repository catalog. The apex Terraform root is retained because it also declares VM resources, and no Vault configuration is changed.
Replace the provider-snapshot zone files with generated declaration pages, one per destination view, that project the checked-in declarations and are verified for freshness by the DNS offline check. The DNS linter, both destination pages, the apex site, the skills projection, and the repository quality suite pass, and the whole repository builds.
OpenSpec-Change: projects/alwaldend.com/openspec/changes/consolidate-project-landings-into-apex
LLM-disclaimer: This commit was generated by an LLM.
-
Manage forge resources with hermetic Terraform rules
Centralize organization, repository, and named access configuration in infra/repos. Adopt existing GitHub resources, protect master defaults while retaining Pages publication on pages, and preserve existing repository identities. Manage GitLab one-time imports, the F-Droid metadata fork, and default-branch protections through Vault-backed authentication. Forgejo consumes the same catalog. Ongoing repository synchronization is deferred.
Retire the eleven Bazel rule landing sites through their owning Terraform workflows, removing their DNS records, Pages repositories, and landing configuration. Move all twelve existing standalone rule modules into tools/ and retain their public interfaces and documentation on the main site.
Add tools/rules_terraform with verified provider downloads, packed mirrors in runfiles, and reusable Terraform execution rules. Enforce one version per provider source at an extensible resolution boundary. Migrate every Terraform consumer to thirteen shared provider pins in third_party/terraform. Execution and command maps belong to rules_terraform; consumers explicitly select generic AL wrappers for authentication and Vault injection. Remove tools/terraform and all 43 checked-in Terraform provider locks. Validate installed providers against the declared archives before execution.
Validation covers all fourteen workspace builds, all thirteen standalone test suites, Terraform consumers, offline real-provider regressions, rendered documentation, formatting, and semantic lint. The full root test run has 295 passing tests and one skip; its only failure is the historical secret scan, reduced to four pre-existing synthetic fixture matches. Earlier live imports and the exact landing retirement scope have verified postconditions; the Terraform rules migration uses only offline implementation checks.
OpenSpec-Change: infra/repos/openspec/changes/archive/2026-09-13-adopt-shared-repository-catalog OpenSpec-Change: infra/src/openspec/changes/archive/2026-09-13-retire-bazel-rule-landings OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-add-hermetic-terraform-rules OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-correct-terraform-ownership
LLM-disclaimer: This commit was generated by an LLM.
-
Deploy project DNS through Terraform modules
Move DNS ownership into each project’s Terraform state using shared modules. Load dnsconfig.json files at runtime, reject conflicting domain ownership, and render their records as a table. Add missing project AppRoles and scoped DNS policies, and document grouping related Terraform resources in modules.
Deploy all 45 owners sequentially: adopt 155 existing records and create 13 missing OpenHands records. Preserve every pre-existing provider record and verify no-op follow-up plans and DNS answers. Add DNS-scoped plan/show/apply wrappers with a saved-plan guard for roots that also manage services. Allow bounded aggregate path inventories large enough to deliver this migration while retaining truncation refusal in the delivery tool.
Validate runtime ownership, provider imports and preservation with isolated fixtures, Terraform formatting, wrapper builds, repository quality checks, semantic lint, and project documentation/specification builds.
OpenSpec-Change: infra/dns/openspec/changes/archive/2026-09-13-migrate-project-dns-to-terraform
LLM-disclaimer: This commit was generated by an LLM.
-
Simplify OpenSpec workspace globs
Collapse OpenSpec source globs to specs and changes, drop redundant package visibility blocks already covered by REPO.bazel, and regenerate the affected catalogs.
LLM-disclaimer: This commit was generated by an LLM.
-
Publish project sites and reproducible infrastructure diagrams
Build and deploy all 30 remaining project sites with the standard Docsy header, project descriptions and a linked documentation directory. Omit the repeated page title and generated language heading. Remove the unused cgit and xray_manager projects and retire their site resources.
Add a repeatable GitHub Pages publisher, staged Terraform bootstrap and direct GitHub Pages DNS records. Preserve repeated publication when pages is the remote default branch, and include Rules ISO in the main documentation. Document site onboarding in a registered, validated skill. Keep AL introduction short with useful links and preserve its lifecycle details in a dedicated documentation page.
Render all 15 existing infrastructure Drawio pages with pinned Drawio and Chrome inputs, sandboxed export actions, an update target and freshness checks, and include the maintained diagrams in infra/arch documentation. Paint an opaque white canvas to preserve readability in dark themes.
Validation covers project and apex builds, rendered pages, publisher tests, diagram repeatability and freshness, DNS configuration, Terraform formatting, semantic lint and repository quality.
Goal-Ref: build-and-deploy-every-project-landing-page-a782b800 Attempt-ID: attempt-00941092c164
LLM-disclaimer: This commit was generated by an LLM.
-
Repair site navigation and simplify page layout
Show one homepage panel with vertically stacked GitHub and Docs rows using the name: URL format, hiding the protocol and trailing slash in the link text. Center the panel and cap its width at 40rem while allowing it to shrink on mobile. Move it slightly lower on desktop and brighten the footer link. Restore the project assets mount so custom styles load. Reduce the footer to its content height with compact padding. Size the homepage against the visible viewport so mobile browser controls do not hide its footer. Remove the separate Projects page and its header link, while keeping project documentation under Docs. Remove the introductory homepage copy and visible title.
Resolve Markdown links and images from their source locations, package missing documentation and book covers, correct source links, and scope anchors and release controls in combined print pages. Restore the archive-root CNAME explicitly during deployment so replacing the site preserves the custom domain.
Validate generated HTML for missing internal files and fragments, duplicate IDs, image alternatives, and the homepage, Misc source-link, and Goal diagram regressions. Check the production build, repository quality, affected-target semantic lint, desktop and mobile homepage rendering, and deployment output.
Goal-Ref: out/site-fix/goals/fix-local-alwaldend-com-layout-and-links-a2e69a4e Attempt-ID: attempt-165dd5be7d71
LLM-disclaimer: This commit was generated by an LLM.
-
Extract DNSControl setup into rules_dnscontrol
Extract the DNSControl setup into
rules_dnscontrol, generate its Bazel dependency bundle from project-owned record files, and update the DNS guidance. Move Hugo rules and the worker to role-based package paths, and give each non-nested project a locally owned Hugo landing target that reuses the shared README-to-landing macro.Clean all landing and Pages DNS records so GitHub Pages serves each project subdomain directly without Cloudflare proxying. Improve the main site with a three-panel home layout, complete project links, documentation explore links, and current deployment guidance.
All affected root-workspace landing, DNS, and site targets pass, along with the nested
rules_hugotests, Buildifier, and repository quality checks.LLM-disclaimer: This commit was generated by an LLM.
-
Add hermetic repository-wide formatting and linting
Integrate upstream formatters for the repository’s meaningful tracked source and configuration file types through Bazel, and add Buildifier, Ruff, and ShellCheck lint aspects for correctness-oriented repository-wide checks.
Pin all new external tools through Bzlmod or the existing pnpm lock, add thin cache/runfiles adapters where required, expose format and check targets, and wire the checks into the pre-commit workflow. Format the existing tree and fix the correctness defects uncovered by the new checks. Preserve generated sources and exact-content fixtures that are not safely rewritable, and clarify that ordinary infrastructure build output is safe to display.
Validation:
- all 21 repository quality and compatibility formatter tests pass
- Buildifier test passes
- lint aspects analyze all 4,629 ordinary root targets without findings
- the complete 18-command root and nested full-repository audit was exercised; remaining failures are documented environment or pre-existing test limits
LLM-disclaimer: This commit was generated by an LLM.
-
Add standalone documentation rules
Move docs_filegroup into a reusable rules_docs nested Bzlmod workspace and migrate every root and nested consumer to it. Add a module-aware Gazelle language that creates docs targets only for existing README packages while preserving manual mappings.
Wire the workspace into module resolution, documentation aggregation, and the ten-command full-repo-check. Add the bazel-nested-module skill so future nested workspaces follow the repository’s rc, lockfile, docs, toolchain, Gazelle, and validation conventions.
Keep reviewed Gazelle dependency canonicalization, while protecting the hand-maintained Go proto, Python resource, Android, embedded-site, and skill runner definitions that generic language plugins would otherwise break.
This commit was generated by an LLM.
-
Complete docs filegroup migration
Pass ordinary documentation sources directly and isolate generated or renamed outputs in semantic pkg_files dependencies. Remove the obsolete renames and strip_prefix surface from docs_filegroup.\n\nThis commit was generated by an LLM.
-
Migrate documentation packaging to docs_filegroup
Preserve custom prefixes, renames, strip prefixes, and standalone workspace behavior.\n\nThis commit was generated by an LLM.
- Add //third_party/org_kernel_headers, rename all deps files to include
- Remove //tools/docs, remove .github
- Migrate go code of ci_platform
- Fix model README
- Migrate nexus_security_plugin to bazel
- Fix java builds broken after protobuf upgrade
- Add missing features to the Pomodoro app, update project readmes, add github pages
- Move all remaining code to main
- Add more taxonomies, remove docs tree, move alwaldend.com to projects
- Remove bazel target docs, add tools/docs, tag projects properly
- Remove changelogs, ignore irrelevant directories in docs
- Move another group of rules to tools/
- Move a group of rules to tools/
- Remove kt tree
- Initial commit
-
Add spellcheck skill
This commit was generated by an LLM.
-
Restore light and dark site canvases and set the shared accent
The shared Docsy canvas set the same Bootstrap dark palette and the same black page background on
:root,[data-bs-theme="light"], and[data-bs-theme="dark"], so the light/dark toggle changed nothing. The site also rendered Bootstrap’s stock blue instead of its intended accent.Split the shared palette so light mode uses a pure white canvas with the light-mode palette and dark mode uses a pure black canvas with the dark-mode palette, and keep the pre-stylesheet paint and footer on the active mode. Assign
$primaryto#7c3aedbefore Bootstrap compiles, so links, buttons, badges, focus rings, and the dark-mode link tint all derive from one value rather than from a site-local copy.Both files stay in the reusable shell; the apex site consumes them through the existing declared exports and no longer carries the footer’s own blue.
OpenSpec-Change: projects/hugo_landing/openspec/changes/restore-light-dark-canvas-and-accent
LLM-disclaimer: This commit was generated by an LLM.
1.16 - Renders
This project owns reusable Blender assets, their controlling references, and acceptance evidence bound to exact candidate bytes. Maintained work uses the project OpenSpec workspace.
The Reimu Fumo work lives under assets/reimu_fumo/. Its reusable asset target will be added only after a candidate passes the visual, structural, animation, and exact-byte delivery gates in Reimu Fumo change. That change preserves the open outcome, blocked execution and original goal history.
Working candidates and intermediate renders belong under the repository-root
out/reimu_fumo_finish/ directory. They are not accepted or durable merely
because they exist there. A historical packet may move into the source tree
only when exact bytes and provenance are verified and it is labeled with its
actual rejected or accepted state.
1.17 - Sri
sri calculates Subresource Integrity hashes for files using OpenSSL. Its
command-line interface accepts an input file and a digest algorithm, such as
SHA-256.
Links
- Source code: https://github.com/alwaldend/src/tree/master/projects/sri
- Docs: https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity
Features
- Cli app that calculates SRI using OpenSSL
- C, OpenSSL
Usage
Usage: sri [OPTION...]
Generate sri of a file
Example:
bazel run //projects/sri -- --digest sha256 --file ${PWD}/README.md
-d, --digest=String Digest type (sha256, for example)
-f, --file=Path Path to the file to parse
-?, --help Give this help list
--usage Give a short usage message
1.17.1 - Releases
head
-
Move project landings into the main site
Publish every registered project’s visitor-facing landing page at /projects/
/ from the main site instead of a dedicated subdomain, and retire the per-project Pages repository, CNAME, and Terraform DNS stage that existed only to serve one page derived from the project README. Each project owns its landing content in projects/
/site/content/ as pure content: no layouts, styles, or build rules. The main site packages those directories into content/projects/ / from the registry in projects/projects.bzl, so membership is declared once. The landing is a short hand-written page for visitors while the README keeps its /docs/projects/ / URL for repository reference documentation, and landing front matter now feeds the statuses, languages, and tags taxonomies. Merge the reusable hugo_landing project into the main site: its shared canvas and accent styles and its landing page rules move into the apex tree, and its landing macro, generated configuration, standalone publisher, and repository-relative rewrite layouts are removed. The theme keeps owning the taxonomy and term layouts, which are richer than the heading-only versions the reusable project carried. Remove the now-unused apex deploy_project.sh and deploy_all.sh landing publishers with it.
Retire the per-project publication and DNS ownership: the project landing targets and the landing deployment command, each landing project’s dnsconfig.json and Terraform root, the build plumbing that served only those stages, and the landing repository and Pages membership in the repository catalog. The apex Terraform root is retained because it also declares VM resources, and no Vault configuration is changed.
Replace the provider-snapshot zone files with generated declaration pages, one per destination view, that project the checked-in declarations and are verified for freshness by the DNS offline check. The DNS linter, both destination pages, the apex site, the skills projection, and the repository quality suite pass, and the whole repository builds.
OpenSpec-Change: projects/alwaldend.com/openspec/changes/consolidate-project-landings-into-apex
LLM-disclaimer: This commit was generated by an LLM.
-
Manage forge resources with hermetic Terraform rules
Centralize organization, repository, and named access configuration in infra/repos. Adopt existing GitHub resources, protect master defaults while retaining Pages publication on pages, and preserve existing repository identities. Manage GitLab one-time imports, the F-Droid metadata fork, and default-branch protections through Vault-backed authentication. Forgejo consumes the same catalog. Ongoing repository synchronization is deferred.
Retire the eleven Bazel rule landing sites through their owning Terraform workflows, removing their DNS records, Pages repositories, and landing configuration. Move all twelve existing standalone rule modules into tools/ and retain their public interfaces and documentation on the main site.
Add tools/rules_terraform with verified provider downloads, packed mirrors in runfiles, and reusable Terraform execution rules. Enforce one version per provider source at an extensible resolution boundary. Migrate every Terraform consumer to thirteen shared provider pins in third_party/terraform. Execution and command maps belong to rules_terraform; consumers explicitly select generic AL wrappers for authentication and Vault injection. Remove tools/terraform and all 43 checked-in Terraform provider locks. Validate installed providers against the declared archives before execution.
Validation covers all fourteen workspace builds, all thirteen standalone test suites, Terraform consumers, offline real-provider regressions, rendered documentation, formatting, and semantic lint. The full root test run has 295 passing tests and one skip; its only failure is the historical secret scan, reduced to four pre-existing synthetic fixture matches. Earlier live imports and the exact landing retirement scope have verified postconditions; the Terraform rules migration uses only offline implementation checks.
OpenSpec-Change: infra/repos/openspec/changes/archive/2026-09-13-adopt-shared-repository-catalog OpenSpec-Change: infra/src/openspec/changes/archive/2026-09-13-retire-bazel-rule-landings OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-add-hermetic-terraform-rules OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-correct-terraform-ownership
LLM-disclaimer: This commit was generated by an LLM.
-
Deploy project DNS through Terraform modules
Move DNS ownership into each project’s Terraform state using shared modules. Load dnsconfig.json files at runtime, reject conflicting domain ownership, and render their records as a table. Add missing project AppRoles and scoped DNS policies, and document grouping related Terraform resources in modules.
Deploy all 45 owners sequentially: adopt 155 existing records and create 13 missing OpenHands records. Preserve every pre-existing provider record and verify no-op follow-up plans and DNS answers. Add DNS-scoped plan/show/apply wrappers with a saved-plan guard for roots that also manage services. Allow bounded aggregate path inventories large enough to deliver this migration while retaining truncation refusal in the delivery tool.
Validate runtime ownership, provider imports and preservation with isolated fixtures, Terraform formatting, wrapper builds, repository quality checks, semantic lint, and project documentation/specification builds.
OpenSpec-Change: infra/dns/openspec/changes/archive/2026-09-13-migrate-project-dns-to-terraform
LLM-disclaimer: This commit was generated by an LLM.
-
Simplify OpenSpec workspace globs
Collapse OpenSpec source globs to specs and changes, drop redundant package visibility blocks already covered by REPO.bazel, and regenerate the affected catalogs.
LLM-disclaimer: This commit was generated by an LLM.
-
Publish project sites and reproducible infrastructure diagrams
Build and deploy all 30 remaining project sites with the standard Docsy header, project descriptions and a linked documentation directory. Omit the repeated page title and generated language heading. Remove the unused cgit and xray_manager projects and retire their site resources.
Add a repeatable GitHub Pages publisher, staged Terraform bootstrap and direct GitHub Pages DNS records. Preserve repeated publication when pages is the remote default branch, and include Rules ISO in the main documentation. Document site onboarding in a registered, validated skill. Keep AL introduction short with useful links and preserve its lifecycle details in a dedicated documentation page.
Render all 15 existing infrastructure Drawio pages with pinned Drawio and Chrome inputs, sandboxed export actions, an update target and freshness checks, and include the maintained diagrams in infra/arch documentation. Paint an opaque white canvas to preserve readability in dark themes.
Validation covers project and apex builds, rendered pages, publisher tests, diagram repeatability and freshness, DNS configuration, Terraform formatting, semantic lint and repository quality.
Goal-Ref: build-and-deploy-every-project-landing-page-a782b800 Attempt-ID: attempt-00941092c164
LLM-disclaimer: This commit was generated by an LLM.
-
Extract DNSControl setup into rules_dnscontrol
Extract the DNSControl setup into
rules_dnscontrol, generate its Bazel dependency bundle from project-owned record files, and update the DNS guidance. Move Hugo rules and the worker to role-based package paths, and give each non-nested project a locally owned Hugo landing target that reuses the shared README-to-landing macro.Clean all landing and Pages DNS records so GitHub Pages serves each project subdomain directly without Cloudflare proxying. Improve the main site with a three-panel home layout, complete project links, documentation explore links, and current deployment guidance.
All affected root-workspace landing, DNS, and site targets pass, along with the nested
rules_hugotests, Buildifier, and repository quality checks.LLM-disclaimer: This commit was generated by an LLM.
-
Add hermetic repository-wide formatting and linting
Integrate upstream formatters for the repository’s meaningful tracked source and configuration file types through Bazel, and add Buildifier, Ruff, and ShellCheck lint aspects for correctness-oriented repository-wide checks.
Pin all new external tools through Bzlmod or the existing pnpm lock, add thin cache/runfiles adapters where required, expose format and check targets, and wire the checks into the pre-commit workflow. Format the existing tree and fix the correctness defects uncovered by the new checks. Preserve generated sources and exact-content fixtures that are not safely rewritable, and clarify that ordinary infrastructure build output is safe to display.
Validation:
- all 21 repository quality and compatibility formatter tests pass
- Buildifier test passes
- lint aspects analyze all 4,629 ordinary root targets without findings
- the complete 18-command root and nested full-repository audit was exercised; remaining failures are documented environment or pre-existing test limits
LLM-disclaimer: This commit was generated by an LLM.
-
Add standalone documentation rules
Move docs_filegroup into a reusable rules_docs nested Bzlmod workspace and migrate every root and nested consumer to it. Add a module-aware Gazelle language that creates docs targets only for existing README packages while preserving manual mappings.
Wire the workspace into module resolution, documentation aggregation, and the ten-command full-repo-check. Add the bazel-nested-module skill so future nested workspaces follow the repository’s rc, lockfile, docs, toolchain, Gazelle, and validation conventions.
Keep reviewed Gazelle dependency canonicalization, while protecting the hand-maintained Go proto, Python resource, Android, embedded-site, and skill runner definitions that generic language plugins would otherwise break.
This commit was generated by an LLM.
-
Migrate documentation packaging to docs_filegroup
Preserve custom prefixes, renames, strip prefixes, and standalone workspace behavior.\n\nThis commit was generated by an LLM.
- Add a server to //projects/alwaldend.com
- Remove //tools/docs, remove .github
- Add build_test tests
- Move all the logig out of the screen to the controller
- Add deploy to dockerhub, add //tools/oras
- Add missing features to the Pomodoro app, update project readmes, add github pages
- Move all remaining code to main
- Move some code to main
- Add release_page generation, remove redundant release templates
- Allow docs to put content outside of docs, refactor git to just use .git directly
- Add cross-compilation, move leetcode downloader contracts out of //contracts
- Refactor release templates into partials, add release cards
- Add more taxonomies, remove docs tree, move alwaldend.com to projects
- Remove bazel target docs, add tools/docs, tag projects properly
- Remove changelogs, ignore irrelevant directories in docs
- Move another group of rules to tools/
- Move a group of rules to tools/
- Remove c and cpp trees
- Initial commit
-
Add spellcheck skill
This commit was generated by an LLM.
-
Restore light and dark site canvases and set the shared accent
The shared Docsy canvas set the same Bootstrap dark palette and the same black page background on
:root,[data-bs-theme="light"], and[data-bs-theme="dark"], so the light/dark toggle changed nothing. The site also rendered Bootstrap’s stock blue instead of its intended accent.Split the shared palette so light mode uses a pure white canvas with the light-mode palette and dark mode uses a pure black canvas with the dark-mode palette, and keep the pre-stylesheet paint and footer on the active mode. Assign
$primaryto#7c3aedbefore Bootstrap compiles, so links, buttons, badges, focus rings, and the dark-mode link tint all derive from one value rather than from a site-local copy.Both files stay in the reusable shell; the apex site consumes them through the existing declared exports and no longer carries the footer’s own blue.
OpenSpec-Change: projects/hugo_landing/openspec/changes/restore-light-dark-canvas-and-accent
LLM-disclaimer: This commit was generated by an LLM.
1.17.1.1 - head
-
Move project landings into the main site
Publish every registered project’s visitor-facing landing page at /projects/
/ from the main site instead of a dedicated subdomain, and retire the per-project Pages repository, CNAME, and Terraform DNS stage that existed only to serve one page derived from the project README. Each project owns its landing content in projects/
/site/content/ as pure content: no layouts, styles, or build rules. The main site packages those directories into content/projects/ / from the registry in projects/projects.bzl, so membership is declared once. The landing is a short hand-written page for visitors while the README keeps its /docs/projects/ / URL for repository reference documentation, and landing front matter now feeds the statuses, languages, and tags taxonomies. Merge the reusable hugo_landing project into the main site: its shared canvas and accent styles and its landing page rules move into the apex tree, and its landing macro, generated configuration, standalone publisher, and repository-relative rewrite layouts are removed. The theme keeps owning the taxonomy and term layouts, which are richer than the heading-only versions the reusable project carried. Remove the now-unused apex deploy_project.sh and deploy_all.sh landing publishers with it.
Retire the per-project publication and DNS ownership: the project landing targets and the landing deployment command, each landing project’s dnsconfig.json and Terraform root, the build plumbing that served only those stages, and the landing repository and Pages membership in the repository catalog. The apex Terraform root is retained because it also declares VM resources, and no Vault configuration is changed.
Replace the provider-snapshot zone files with generated declaration pages, one per destination view, that project the checked-in declarations and are verified for freshness by the DNS offline check. The DNS linter, both destination pages, the apex site, the skills projection, and the repository quality suite pass, and the whole repository builds.
OpenSpec-Change: projects/alwaldend.com/openspec/changes/consolidate-project-landings-into-apex
LLM-disclaimer: This commit was generated by an LLM.
-
Manage forge resources with hermetic Terraform rules
Centralize organization, repository, and named access configuration in infra/repos. Adopt existing GitHub resources, protect master defaults while retaining Pages publication on pages, and preserve existing repository identities. Manage GitLab one-time imports, the F-Droid metadata fork, and default-branch protections through Vault-backed authentication. Forgejo consumes the same catalog. Ongoing repository synchronization is deferred.
Retire the eleven Bazel rule landing sites through their owning Terraform workflows, removing their DNS records, Pages repositories, and landing configuration. Move all twelve existing standalone rule modules into tools/ and retain their public interfaces and documentation on the main site.
Add tools/rules_terraform with verified provider downloads, packed mirrors in runfiles, and reusable Terraform execution rules. Enforce one version per provider source at an extensible resolution boundary. Migrate every Terraform consumer to thirteen shared provider pins in third_party/terraform. Execution and command maps belong to rules_terraform; consumers explicitly select generic AL wrappers for authentication and Vault injection. Remove tools/terraform and all 43 checked-in Terraform provider locks. Validate installed providers against the declared archives before execution.
Validation covers all fourteen workspace builds, all thirteen standalone test suites, Terraform consumers, offline real-provider regressions, rendered documentation, formatting, and semantic lint. The full root test run has 295 passing tests and one skip; its only failure is the historical secret scan, reduced to four pre-existing synthetic fixture matches. Earlier live imports and the exact landing retirement scope have verified postconditions; the Terraform rules migration uses only offline implementation checks.
OpenSpec-Change: infra/repos/openspec/changes/archive/2026-09-13-adopt-shared-repository-catalog OpenSpec-Change: infra/src/openspec/changes/archive/2026-09-13-retire-bazel-rule-landings OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-add-hermetic-terraform-rules OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-correct-terraform-ownership
LLM-disclaimer: This commit was generated by an LLM.
-
Deploy project DNS through Terraform modules
Move DNS ownership into each project’s Terraform state using shared modules. Load dnsconfig.json files at runtime, reject conflicting domain ownership, and render their records as a table. Add missing project AppRoles and scoped DNS policies, and document grouping related Terraform resources in modules.
Deploy all 45 owners sequentially: adopt 155 existing records and create 13 missing OpenHands records. Preserve every pre-existing provider record and verify no-op follow-up plans and DNS answers. Add DNS-scoped plan/show/apply wrappers with a saved-plan guard for roots that also manage services. Allow bounded aggregate path inventories large enough to deliver this migration while retaining truncation refusal in the delivery tool.
Validate runtime ownership, provider imports and preservation with isolated fixtures, Terraform formatting, wrapper builds, repository quality checks, semantic lint, and project documentation/specification builds.
OpenSpec-Change: infra/dns/openspec/changes/archive/2026-09-13-migrate-project-dns-to-terraform
LLM-disclaimer: This commit was generated by an LLM.
-
Simplify OpenSpec workspace globs
Collapse OpenSpec source globs to specs and changes, drop redundant package visibility blocks already covered by REPO.bazel, and regenerate the affected catalogs.
LLM-disclaimer: This commit was generated by an LLM.
-
Publish project sites and reproducible infrastructure diagrams
Build and deploy all 30 remaining project sites with the standard Docsy header, project descriptions and a linked documentation directory. Omit the repeated page title and generated language heading. Remove the unused cgit and xray_manager projects and retire their site resources.
Add a repeatable GitHub Pages publisher, staged Terraform bootstrap and direct GitHub Pages DNS records. Preserve repeated publication when pages is the remote default branch, and include Rules ISO in the main documentation. Document site onboarding in a registered, validated skill. Keep AL introduction short with useful links and preserve its lifecycle details in a dedicated documentation page.
Render all 15 existing infrastructure Drawio pages with pinned Drawio and Chrome inputs, sandboxed export actions, an update target and freshness checks, and include the maintained diagrams in infra/arch documentation. Paint an opaque white canvas to preserve readability in dark themes.
Validation covers project and apex builds, rendered pages, publisher tests, diagram repeatability and freshness, DNS configuration, Terraform formatting, semantic lint and repository quality.
Goal-Ref: build-and-deploy-every-project-landing-page-a782b800 Attempt-ID: attempt-00941092c164
LLM-disclaimer: This commit was generated by an LLM.
-
Extract DNSControl setup into rules_dnscontrol
Extract the DNSControl setup into
rules_dnscontrol, generate its Bazel dependency bundle from project-owned record files, and update the DNS guidance. Move Hugo rules and the worker to role-based package paths, and give each non-nested project a locally owned Hugo landing target that reuses the shared README-to-landing macro.Clean all landing and Pages DNS records so GitHub Pages serves each project subdomain directly without Cloudflare proxying. Improve the main site with a three-panel home layout, complete project links, documentation explore links, and current deployment guidance.
All affected root-workspace landing, DNS, and site targets pass, along with the nested
rules_hugotests, Buildifier, and repository quality checks.LLM-disclaimer: This commit was generated by an LLM.
-
Add hermetic repository-wide formatting and linting
Integrate upstream formatters for the repository’s meaningful tracked source and configuration file types through Bazel, and add Buildifier, Ruff, and ShellCheck lint aspects for correctness-oriented repository-wide checks.
Pin all new external tools through Bzlmod or the existing pnpm lock, add thin cache/runfiles adapters where required, expose format and check targets, and wire the checks into the pre-commit workflow. Format the existing tree and fix the correctness defects uncovered by the new checks. Preserve generated sources and exact-content fixtures that are not safely rewritable, and clarify that ordinary infrastructure build output is safe to display.
Validation:
- all 21 repository quality and compatibility formatter tests pass
- Buildifier test passes
- lint aspects analyze all 4,629 ordinary root targets without findings
- the complete 18-command root and nested full-repository audit was exercised; remaining failures are documented environment or pre-existing test limits
LLM-disclaimer: This commit was generated by an LLM.
-
Add standalone documentation rules
Move docs_filegroup into a reusable rules_docs nested Bzlmod workspace and migrate every root and nested consumer to it. Add a module-aware Gazelle language that creates docs targets only for existing README packages while preserving manual mappings.
Wire the workspace into module resolution, documentation aggregation, and the ten-command full-repo-check. Add the bazel-nested-module skill so future nested workspaces follow the repository’s rc, lockfile, docs, toolchain, Gazelle, and validation conventions.
Keep reviewed Gazelle dependency canonicalization, while protecting the hand-maintained Go proto, Python resource, Android, embedded-site, and skill runner definitions that generic language plugins would otherwise break.
This commit was generated by an LLM.
-
Migrate documentation packaging to docs_filegroup
Preserve custom prefixes, renames, strip prefixes, and standalone workspace behavior.\n\nThis commit was generated by an LLM.
- Add a server to //projects/alwaldend.com
- Remove //tools/docs, remove .github
- Add build_test tests
- Move all the logig out of the screen to the controller
- Add deploy to dockerhub, add //tools/oras
- Add missing features to the Pomodoro app, update project readmes, add github pages
- Move all remaining code to main
- Move some code to main
- Add release_page generation, remove redundant release templates
- Allow docs to put content outside of docs, refactor git to just use .git directly
- Add cross-compilation, move leetcode downloader contracts out of //contracts
- Refactor release templates into partials, add release cards
- Add more taxonomies, remove docs tree, move alwaldend.com to projects
- Remove bazel target docs, add tools/docs, tag projects properly
- Remove changelogs, ignore irrelevant directories in docs
- Move another group of rules to tools/
- Move a group of rules to tools/
- Remove c and cpp trees
- Initial commit
-
Add spellcheck skill
This commit was generated by an LLM.
-
Restore light and dark site canvases and set the shared accent
The shared Docsy canvas set the same Bootstrap dark palette and the same black page background on
:root,[data-bs-theme="light"], and[data-bs-theme="dark"], so the light/dark toggle changed nothing. The site also rendered Bootstrap’s stock blue instead of its intended accent.Split the shared palette so light mode uses a pure white canvas with the light-mode palette and dark mode uses a pure black canvas with the dark-mode palette, and keep the pre-stylesheet paint and footer on the active mode. Assign
$primaryto#7c3aedbefore Bootstrap compiles, so links, buttons, badges, focus rings, and the dark-mode link tint all derive from one value rather than from a site-local copy.Both files stay in the reusable shell; the apex site consumes them through the existing declared exports and no longer carries the footer’s own blue.
OpenSpec-Change: projects/hugo_landing/openspec/changes/restore-light-dark-canvas-and-accent
LLM-disclaimer: This commit was generated by an LLM.
1.18 - Tf modules
This project contains reusable Terraform modules for Vault configuration, Proxmox virtual machines, backup storage, and related infrastructure. The module collection is still in progress.
Links
- Source code: https://github.com/alwaldend/src/tree/master/projects/tf_modules
- Docs: https://developer.hashicorp.com/terraform/language/modules
Features
- Terraform modules
1.18.1 -
dns-records Specification
Purpose
Provide one canonical DNS transformation for project-local Terraform resources and offline inspection, preserving declared names, values, and view ownership.
Requirements
Requirement: Normalize canonical declarations without providers
The module SHALL accept decoded owner DNS documents and a zone, flatten every supported type member, expand and deduplicate destinations, and expose one normalized map without provider configuration. It SHALL reject unsupported types, destinations, malformed members, and absolute names outside the zone.
Scenario: One logical declaration has several types and destinations
- WHEN an entry contains A and AAAA with destinations all and global
- THEN normalization produces exactly four records, one per type and view
Requirement: Preserve record multiplicity and stable identities
Normalized and provider resource keys SHALL use logical declaration key, type, and view without mutable record values. Separate logical keys SHALL preserve multiple records at the same name and type, including MX priority and TXT values. Explicit TTLs SHALL override the type-specific compatibility defaults.
Scenario: A record changes address
- WHEN an A member changes its address without changing its logical key
- THEN its normalized and provider resource keys remain unchanged
Requirement: Keep provider ownership explicit
The module SHALL accept provider instances from its caller and create individual Cloudflare global and RouterOS dc1 records only when explicitly enabled. It SHALL default to disabled provider ownership while preserving normalized outputs. Cloudflare records SHALL remain unproxied. Disabled ownership SHALL NOT imply that operational provider initialization or credential prerequisites are suppressed.
Scenario: A root prepares a future migration
- WHEN a root calls the module without enabling ownership
- THEN it declares no provider record resources and still exposes every normalized declaration
1.18.2 -
project-dns Specification
Purpose
Record the retirement of this project’s landing DNS infrastructure while preserving its repository documentation and builds.
Requirements
Requirement: Keep landing infrastructure retired
The project SHALL have no dedicated landing DNS declaration, Terraform root, or
operational source export. Its landing page SHALL be published by the main site
under /projects/tf_modules/ instead of a dedicated hostname.
Scenario: Inspect the project after landing retirement
- WHEN the project tree is consumed
- THEN it contains no landing DNS declaration, Terraform DNS stage, or landing build target, and the main site owns its landing page.
1.18.3 -
Reusable Terraform modules
Purpose
Provide reusable infrastructure declarations for Vault, virtual machines,
storage, and related services. This baseline was observed at repository
revision 550d7e79 on 2026-09-08. The collection remains in progress according
to its README. Sources for the
representative module contracts below are the
AppRole module,
transit-key module,
backup-bucket module, and
module packaging.
These are declarative source contracts; no live provisioning is asserted.
Requirements
Requirement: Package reusable module source
The AppRole, transit-key, backup-bucket, and Proxmox VM module packages SHALL
each expose their main.tf through a same-named Bazel filegroup available to
repository subpackages.
Scenario: A repository target consumes a module
- WHEN a target depends on
//projects/tf_modules/vault_approle:vault_approle - THEN its declared source input includes the AppRole module’s
main.tf
Requirement: Associate AppRoles with Vault identities and policies
The AppRole module SHALL declare an identity entity, backend alias, internal group, and named AppRole with configurable token and secret-ID limits. Its role policies SHALL combine the shared and AppRole-secret policies with caller policies and the Yandex-folder policy unless that policy is disabled for the role.
Scenario: Caller disables the Yandex-folder role policy
- WHEN
disable_yc_folder_policyis true - THEN the role’s policy list excludes the module’s Yandex-folder policy while preserving shared, AppRole-secret, and caller policies
Requirement: Separate transit encryption and decryption membership
The transit-key module SHALL declare a named Vault transit key, an encryption policy and group, and a decryption policy and group. Decryptor member groups SHALL also be included in the encryption group.
Scenario: A group is listed as a decryptor
- WHEN a caller adds a group ID to
decryptors_member_group_ids - THEN the module includes that group in both transit permission groups
Requirement: Declare encrypted versioned backup storage
The backup-bucket module SHALL declare a versioned Yandex storage bucket with default KMS encryption, grant read and write permissions to the supplied service accounts, and store bucket identifiers in the caller-selected Vault KV v2 location.
Scenario: Backup storage is configured
- WHEN the caller supplies the bucket name components, folder, service accounts, and Vault destination
- THEN the declarations bind bucket encryption to the module’s KMS key and publish the bucket ID, folder ID, and bucket name to that Vault destination
1.18.4 - Backup bucket
1.18.5 - DNS records
This reusable module translates an owner’s decoded dnsconfig.json through
its provider-free normalizer, then manages individual
global Cloudflare and dc1 RouterOS records with caller-provided providers.
Owners with only global records use the global entrypoint,
which needs only Cloudflare. The combined entrypoint delegates Cloudflare
resources to that same module and consumes its normalization for RouterOS.
Repository infrastructure roots may consume its Bazel source filegroups;
the child normalizer also supports provider-free inspection.
module "dns" {
source = "../../../projects/tf_modules/dns_records"
document = jsondecode(file("${path.module}/../dnsconfig.json"))
cloudflare_zone_id = var.dns_cloudflare_zone_id
enabled = var.dns_enabled
}
zone defaults to alwaldend.com. An explicit cloudflare_zone_id is optional;
when it is null or empty, enabled global records resolve exactly one Cloudflare
zone matching zone. The token must permit zone listing and reading. Disabled
ownership and declarations without global records skip this lookup.
enabled defaults to false so a prepared root owns
no provider records. Keep it true after adoption: setting it false in a state
that already owns records plans deletion and is not a rollback procedure.
Disabling ownership does not suppress provider initialization. Operational
Terraform commands still require the caller’s real provider configuration
and the owning Vault/AppRole prerequisites. In particular, the pinned
RouterOS provider probes its configured API even when no DNS records are
enabled. Use the provider-free normalizer for offline inspection.
The migration runbook
owns cutover, import, and rollback ordering. This module supplies no provider
credentials or state backend.
The input contains exactly one records object. Each stable logical key
contains one or more scalar type members and a nonempty dsp list. Supported
destinations are global, dc1, and all; repeated destinations are deduplicated.
| Type | Required member fields | Default TTL |
|---|---|---|
| A | name, address |
300 |
| AAAA | name, address |
600 |
| CNAME | name, target |
600 |
| NS | name, address |
300 |
| MX | name, target, priority |
300 |
| TXT | name, content |
300 |
Every member accepts an integer ttl from 60 through 86400 seconds. MX
priorities range from 0 through 65535. Multiple scalar values at the same
name and type use distinct logical keys; changing values never changes
resource identity. Unsupported fields and malformed members are rejected.
Names accept @, relative names, or zone-qualified names. Absolute owner
names ending with a dot must be inside the zone. CNAME, MX, and NS targets
accept @, relative names, zone-qualified names, or absolute external names
ending with a dot. Normalization lowercases domain names and omits final dots;
address and TXT bytes are preserved. relative_name is @ at the apex.
normalized_records maps logical_key/type/view to key, name,
relative_name, type, value, priority (null except MX), ttl, view,
and proxied (always false). This output remains available while disabled.
The same keys index module.global.cloudflare_dns_record.records and
module.dc1[0].routeros_ip_dns_record.records in the combined entrypoint; the global-only
entrypoint uses cloudflare_dns_record.records. import_addresses exposes
these addresses relative to the selected module, including while staged.
The pinned providers import Cloudflare
records by zone_id/record_id and RouterOS records by static IDs such as *1A.
Terraform tests use mocked providers and pinned local provider packages. The global-only test root has no RouterOS provider dependency. Normalization tests require no providers. Both run without network access; they establish declaration and resource mapping behavior, not live adoption.
1.18.5.1 - DNS normalization
This child module owns the canonical transformation described by the
DNS module. Its document and zone inputs produce
normalized_records without a provider, backend, or managed resources.
Terraform writers and provider-free inspection consume this output.
1.18.5.2 - DNS test providers
The test target uses the public rules_terraform wrapper with the same Cloudflare, RouterOS, and Proxmox provider labels as infrastructure targets. The shared extension owns provider versions, release URLs, and checksums. Bazel fetches the declared archives before tests execute; Terraform uses the wrapper’s packaged filesystem mirror without a registry fallback.
Each regression runs Terraform in a caller-owned temporary module directory. Tests retain an explicit environment without inherited provider credentials; provider installation and mocked lifecycles require no network access.
The targeted import regression matches the owning Proxmox provider block by
omitting pm_api_url. It checks both empty state and existing Proxmox resource
state with no credentials. Without PM_API_URL, provider validation fails
before target pruning; supplying only a loopback endpoint permits the DNS
operation. The endpoint must receive zero requests.
The test imports a built-in Terraform resource through a root map into
module.dns, checks the exact no-op import, applies that saved plan, and verifies
the next targeted plan has no changes. Existing Proxmox resource attributes
remain unchanged. An untargeted control must fail authentication before
contacting the endpoint. These checks cover provider selection and state
preservation; live DNS adoption retains its separate inventory and plan checks.
1.18.5.3 - Global DNS records
Global-only owners use this entrypoint with the shared module API to avoid requiring RouterOS configuration. The combined module also delegates its Cloudflare resources here, so both entrypoints share one implementation. Normalization returns all declared views, but this entrypoint owns only global records. Mixed-view owners use the parent module to manage dc1 as well.
Enabled global records use the explicit cloudflare_zone_id when supplied.
Otherwise, the pinned cloudflare_zone data source resolves the configured
zone name and rejects missing or ambiguous matches. This requires zone-list
and zone-read access in addition to record permissions. Disabled ownership and
declarations without global records perform no zone lookup.
The optional zone ID must be known during planning so Terraform can select whether discovery is needed. The repository’s AL injection supplies a known value or an empty string before Terraform starts. Zone-name discovery uses the normalizer’s canonical name, including case and final-dot handling.
import_addresses contains global addresses relative to this entrypoint.
record_ids exposes bound Cloudflare IDs for adoption and identity checks.
1.18.6 - Pve vm qemu
1.18.7 - Releases
head
-
Move project landings into the main site
Publish every registered project’s visitor-facing landing page at /projects/
/ from the main site instead of a dedicated subdomain, and retire the per-project Pages repository, CNAME, and Terraform DNS stage that existed only to serve one page derived from the project README. Each project owns its landing content in projects/
/site/content/ as pure content: no layouts, styles, or build rules. The main site packages those directories into content/projects/ / from the registry in projects/projects.bzl, so membership is declared once. The landing is a short hand-written page for visitors while the README keeps its /docs/projects/ / URL for repository reference documentation, and landing front matter now feeds the statuses, languages, and tags taxonomies. Merge the reusable hugo_landing project into the main site: its shared canvas and accent styles and its landing page rules move into the apex tree, and its landing macro, generated configuration, standalone publisher, and repository-relative rewrite layouts are removed. The theme keeps owning the taxonomy and term layouts, which are richer than the heading-only versions the reusable project carried. Remove the now-unused apex deploy_project.sh and deploy_all.sh landing publishers with it.
Retire the per-project publication and DNS ownership: the project landing targets and the landing deployment command, each landing project’s dnsconfig.json and Terraform root, the build plumbing that served only those stages, and the landing repository and Pages membership in the repository catalog. The apex Terraform root is retained because it also declares VM resources, and no Vault configuration is changed.
Replace the provider-snapshot zone files with generated declaration pages, one per destination view, that project the checked-in declarations and are verified for freshness by the DNS offline check. The DNS linter, both destination pages, the apex site, the skills projection, and the repository quality suite pass, and the whole repository builds.
OpenSpec-Change: projects/alwaldend.com/openspec/changes/consolidate-project-landings-into-apex
LLM-disclaimer: This commit was generated by an LLM.
-
Manage forge resources with hermetic Terraform rules
Centralize organization, repository, and named access configuration in infra/repos. Adopt existing GitHub resources, protect master defaults while retaining Pages publication on pages, and preserve existing repository identities. Manage GitLab one-time imports, the F-Droid metadata fork, and default-branch protections through Vault-backed authentication. Forgejo consumes the same catalog. Ongoing repository synchronization is deferred.
Retire the eleven Bazel rule landing sites through their owning Terraform workflows, removing their DNS records, Pages repositories, and landing configuration. Move all twelve existing standalone rule modules into tools/ and retain their public interfaces and documentation on the main site.
Add tools/rules_terraform with verified provider downloads, packed mirrors in runfiles, and reusable Terraform execution rules. Enforce one version per provider source at an extensible resolution boundary. Migrate every Terraform consumer to thirteen shared provider pins in third_party/terraform. Execution and command maps belong to rules_terraform; consumers explicitly select generic AL wrappers for authentication and Vault injection. Remove tools/terraform and all 43 checked-in Terraform provider locks. Validate installed providers against the declared archives before execution.
Validation covers all fourteen workspace builds, all thirteen standalone test suites, Terraform consumers, offline real-provider regressions, rendered documentation, formatting, and semantic lint. The full root test run has 295 passing tests and one skip; its only failure is the historical secret scan, reduced to four pre-existing synthetic fixture matches. Earlier live imports and the exact landing retirement scope have verified postconditions; the Terraform rules migration uses only offline implementation checks.
OpenSpec-Change: infra/repos/openspec/changes/archive/2026-09-13-adopt-shared-repository-catalog OpenSpec-Change: infra/src/openspec/changes/archive/2026-09-13-retire-bazel-rule-landings OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-add-hermetic-terraform-rules OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-correct-terraform-ownership
LLM-disclaimer: This commit was generated by an LLM.
-
Deploy project DNS through Terraform modules
Move DNS ownership into each project’s Terraform state using shared modules. Load dnsconfig.json files at runtime, reject conflicting domain ownership, and render their records as a table. Add missing project AppRoles and scoped DNS policies, and document grouping related Terraform resources in modules.
Deploy all 45 owners sequentially: adopt 155 existing records and create 13 missing OpenHands records. Preserve every pre-existing provider record and verify no-op follow-up plans and DNS answers. Add DNS-scoped plan/show/apply wrappers with a saved-plan guard for roots that also manage services. Allow bounded aggregate path inventories large enough to deliver this migration while retaining truncation refusal in the delivery tool.
Validate runtime ownership, provider imports and preservation with isolated fixtures, Terraform formatting, wrapper builds, repository quality checks, semantic lint, and project documentation/specification builds.
OpenSpec-Change: infra/dns/openspec/changes/archive/2026-09-13-migrate-project-dns-to-terraform
LLM-disclaimer: This commit was generated by an LLM.
-
Simplify OpenSpec workspace globs
Collapse OpenSpec source globs to specs and changes, drop redundant package visibility blocks already covered by REPO.bazel, and regenerate the affected catalogs.
LLM-disclaimer: This commit was generated by an LLM.
-
Publish project sites and reproducible infrastructure diagrams
Build and deploy all 30 remaining project sites with the standard Docsy header, project descriptions and a linked documentation directory. Omit the repeated page title and generated language heading. Remove the unused cgit and xray_manager projects and retire their site resources.
Add a repeatable GitHub Pages publisher, staged Terraform bootstrap and direct GitHub Pages DNS records. Preserve repeated publication when pages is the remote default branch, and include Rules ISO in the main documentation. Document site onboarding in a registered, validated skill. Keep AL introduction short with useful links and preserve its lifecycle details in a dedicated documentation page.
Render all 15 existing infrastructure Drawio pages with pinned Drawio and Chrome inputs, sandboxed export actions, an update target and freshness checks, and include the maintained diagrams in infra/arch documentation. Paint an opaque white canvas to preserve readability in dark themes.
Validation covers project and apex builds, rendered pages, publisher tests, diagram repeatability and freshness, DNS configuration, Terraform formatting, semantic lint and repository quality.
Goal-Ref: build-and-deploy-every-project-landing-page-a782b800 Attempt-ID: attempt-00941092c164
LLM-disclaimer: This commit was generated by an LLM.
-
Wait for AL secret cleanup and plugin shutdown
Roll back partial plugin startup, drain requests before releasing resources, and wait for plugin and command processes to exit. Stop independent plugins concurrently while preserving dependency order inside each plugin.
Revoke invocation-owned credentials, remove temporary secret files, and verify Forgejo and Harbor session cleanup. Preserve the user’s existing Vault login. Enforce Vault OIDC origins and no_auth, redact sensitive errors, and restrict config dumps to owner-only files. Add the AppRole SecretID cleanup permission.
Cover normal exit, cancellation, failed startup, credential revocation, and transport cleanup with synthetic unit and real command/plugin regression tests.
Clarify that required formatting-only repairs need no separate approval, and fix the existing blank-line formatting failure in the GitHub AL wrapper.
Goal-Ref: fix-al-secret-lifecycle-and-plugin-shutdown-3137c0b0 Attempt-ID: attempt-0c1353676e2f
LLM-disclaimer: This commit was generated by an LLM.
-
Extract DNSControl setup into rules_dnscontrol
Extract the DNSControl setup into
rules_dnscontrol, generate its Bazel dependency bundle from project-owned record files, and update the DNS guidance. Move Hugo rules and the worker to role-based package paths, and give each non-nested project a locally owned Hugo landing target that reuses the shared README-to-landing macro.Clean all landing and Pages DNS records so GitHub Pages serves each project subdomain directly without Cloudflare proxying. Improve the main site with a three-panel home layout, complete project links, documentation explore links, and current deployment guidance.
All affected root-workspace landing, DNS, and site targets pass, along with the nested
rules_hugotests, Buildifier, and repository quality checks.LLM-disclaimer: This commit was generated by an LLM.
-
Add standalone documentation rules
Move docs_filegroup into a reusable rules_docs nested Bzlmod workspace and migrate every root and nested consumer to it. Add a module-aware Gazelle language that creates docs targets only for existing README packages while preserving manual mappings.
Wire the workspace into module resolution, documentation aggregation, and the ten-command full-repo-check. Add the bazel-nested-module skill so future nested workspaces follow the repository’s rc, lockfile, docs, toolchain, Gazelle, and validation conventions.
Keep reviewed Gazelle dependency canonicalization, while protecting the hand-maintained Go proto, Python resource, Android, embedded-site, and skill runner definitions that generic language plugins would otherwise break.
This commit was generated by an LLM.
- Set up Split Horizon DNS, refactor IDM a bit
- Add //third_party/org_fedora_cloud, fix alwaldend.com roles
- Set up unikernel deploy
- Add signing policy to vault_pki_server
- Update cluster token ttl, update secrets
- Add sops, add vault_transit_key, add sops to fluxcd
- Add k3s_auth configs
- Add admin group for the flux cluster
- Use a custom traefik deploy instead of the bundled one
- Deploy ClusterIssuer for cert-manager
- Rewrite k3s role, finish flux deploy
- Add optional disk mount to traefik and forgejo, add ceph disks to forgejo VMs
- Enable asyncio=native, iothread, emulatessd, discard, add ceph disk support
- Disable firewalld in firewall role
- Move gateway into pve_vm_qemu
- Move pve to //infra/pve, remove //infra/dc1
- Remove consul IaC
- Add harbor_login, add harbor IaC, fix bazel’s certificates
- Add drawio-desktop, add //infra/arch, update opencode restrictions
- Finish the forgejo role
- Finish the traefik role
- Add fp modules, refactor tf backend to use it, add parallel start of plugins, add lock check to the backend
- Improve consul deploy, improve vault approles
- Migrate proxmox resource to separate resource pools, add a vm module
- Create folders and resource pools from approle config instead of duplication
- Set up automated PVE login using OIDC, remove PVE tokens
- Fix pve firewall, add //infra/dc1/consul1, standardize ssh and pki roles
- Add timezone management to the host role and TrustedUserCAKeys to the ssh role
- Set up OIDC with Vault as provider
- Set up ACME, disable mTLS for Vault
- Automate root token generation, split the main vault policy into separate ones
- Move vault tools to //tools/vault, replace go_binary in al_binary with native_binary
- Fix cert auth entities, reformat all tf files
- Set up client certificate generation, move ica to a separate module
- Add backup_bucket module, add rclone, set up backups for Vault
- Migrate all resources to separate terraform-managed cloud folders
- Add yc_folder terraform module, migrate to it
- Migrate Vault to Raft storage, start setting up backups, add postgresql role
- Migrate some docs target to the new macro
- Write a proper runner for terraform and vault, set up s3 backends for terraform
- Refactor approle management into a terraform module
- Initial commit
-
Add spellcheck skill
This commit was generated by an LLM.
-
Restore light and dark site canvases and set the shared accent
The shared Docsy canvas set the same Bootstrap dark palette and the same black page background on
:root,[data-bs-theme="light"], and[data-bs-theme="dark"], so the light/dark toggle changed nothing. The site also rendered Bootstrap’s stock blue instead of its intended accent.Split the shared palette so light mode uses a pure white canvas with the light-mode palette and dark mode uses a pure black canvas with the dark-mode palette, and keep the pre-stylesheet paint and footer on the active mode. Assign
$primaryto#7c3aedbefore Bootstrap compiles, so links, buttons, badges, focus rings, and the dark-mode link tint all derive from one value rather than from a site-local copy.Both files stay in the reusable shell; the apex site consumes them through the existing declared exports and no longer carries the footer’s own blue.
OpenSpec-Change: projects/hugo_landing/openspec/changes/restore-light-dark-canvas-and-accent
LLM-disclaimer: This commit was generated by an LLM.
1.18.7.1 - head
-
Move project landings into the main site
Publish every registered project’s visitor-facing landing page at /projects/
/ from the main site instead of a dedicated subdomain, and retire the per-project Pages repository, CNAME, and Terraform DNS stage that existed only to serve one page derived from the project README. Each project owns its landing content in projects/
/site/content/ as pure content: no layouts, styles, or build rules. The main site packages those directories into content/projects/ / from the registry in projects/projects.bzl, so membership is declared once. The landing is a short hand-written page for visitors while the README keeps its /docs/projects/ / URL for repository reference documentation, and landing front matter now feeds the statuses, languages, and tags taxonomies. Merge the reusable hugo_landing project into the main site: its shared canvas and accent styles and its landing page rules move into the apex tree, and its landing macro, generated configuration, standalone publisher, and repository-relative rewrite layouts are removed. The theme keeps owning the taxonomy and term layouts, which are richer than the heading-only versions the reusable project carried. Remove the now-unused apex deploy_project.sh and deploy_all.sh landing publishers with it.
Retire the per-project publication and DNS ownership: the project landing targets and the landing deployment command, each landing project’s dnsconfig.json and Terraform root, the build plumbing that served only those stages, and the landing repository and Pages membership in the repository catalog. The apex Terraform root is retained because it also declares VM resources, and no Vault configuration is changed.
Replace the provider-snapshot zone files with generated declaration pages, one per destination view, that project the checked-in declarations and are verified for freshness by the DNS offline check. The DNS linter, both destination pages, the apex site, the skills projection, and the repository quality suite pass, and the whole repository builds.
OpenSpec-Change: projects/alwaldend.com/openspec/changes/consolidate-project-landings-into-apex
LLM-disclaimer: This commit was generated by an LLM.
-
Manage forge resources with hermetic Terraform rules
Centralize organization, repository, and named access configuration in infra/repos. Adopt existing GitHub resources, protect master defaults while retaining Pages publication on pages, and preserve existing repository identities. Manage GitLab one-time imports, the F-Droid metadata fork, and default-branch protections through Vault-backed authentication. Forgejo consumes the same catalog. Ongoing repository synchronization is deferred.
Retire the eleven Bazel rule landing sites through their owning Terraform workflows, removing their DNS records, Pages repositories, and landing configuration. Move all twelve existing standalone rule modules into tools/ and retain their public interfaces and documentation on the main site.
Add tools/rules_terraform with verified provider downloads, packed mirrors in runfiles, and reusable Terraform execution rules. Enforce one version per provider source at an extensible resolution boundary. Migrate every Terraform consumer to thirteen shared provider pins in third_party/terraform. Execution and command maps belong to rules_terraform; consumers explicitly select generic AL wrappers for authentication and Vault injection. Remove tools/terraform and all 43 checked-in Terraform provider locks. Validate installed providers against the declared archives before execution.
Validation covers all fourteen workspace builds, all thirteen standalone test suites, Terraform consumers, offline real-provider regressions, rendered documentation, formatting, and semantic lint. The full root test run has 295 passing tests and one skip; its only failure is the historical secret scan, reduced to four pre-existing synthetic fixture matches. Earlier live imports and the exact landing retirement scope have verified postconditions; the Terraform rules migration uses only offline implementation checks.
OpenSpec-Change: infra/repos/openspec/changes/archive/2026-09-13-adopt-shared-repository-catalog OpenSpec-Change: infra/src/openspec/changes/archive/2026-09-13-retire-bazel-rule-landings OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-add-hermetic-terraform-rules OpenSpec-Change: tools/rules_terraform/openspec/changes/archive/2026-09-14-correct-terraform-ownership
LLM-disclaimer: This commit was generated by an LLM.
-
Deploy project DNS through Terraform modules
Move DNS ownership into each project’s Terraform state using shared modules. Load dnsconfig.json files at runtime, reject conflicting domain ownership, and render their records as a table. Add missing project AppRoles and scoped DNS policies, and document grouping related Terraform resources in modules.
Deploy all 45 owners sequentially: adopt 155 existing records and create 13 missing OpenHands records. Preserve every pre-existing provider record and verify no-op follow-up plans and DNS answers. Add DNS-scoped plan/show/apply wrappers with a saved-plan guard for roots that also manage services. Allow bounded aggregate path inventories large enough to deliver this migration while retaining truncation refusal in the delivery tool.
Validate runtime ownership, provider imports and preservation with isolated fixtures, Terraform formatting, wrapper builds, repository quality checks, semantic lint, and project documentation/specification builds.
OpenSpec-Change: infra/dns/openspec/changes/archive/2026-09-13-migrate-project-dns-to-terraform
LLM-disclaimer: This commit was generated by an LLM.
-
Simplify OpenSpec workspace globs
Collapse OpenSpec source globs to specs and changes, drop redundant package visibility blocks already covered by REPO.bazel, and regenerate the affected catalogs.
LLM-disclaimer: This commit was generated by an LLM.
-
Publish project sites and reproducible infrastructure diagrams
Build and deploy all 30 remaining project sites with the standard Docsy header, project descriptions and a linked documentation directory. Omit the repeated page title and generated language heading. Remove the unused cgit and xray_manager projects and retire their site resources.
Add a repeatable GitHub Pages publisher, staged Terraform bootstrap and direct GitHub Pages DNS records. Preserve repeated publication when pages is the remote default branch, and include Rules ISO in the main documentation. Document site onboarding in a registered, validated skill. Keep AL introduction short with useful links and preserve its lifecycle details in a dedicated documentation page.
Render all 15 existing infrastructure Drawio pages with pinned Drawio and Chrome inputs, sandboxed export actions, an update target and freshness checks, and include the maintained diagrams in infra/arch documentation. Paint an opaque white canvas to preserve readability in dark themes.
Validation covers project and apex builds, rendered pages, publisher tests, diagram repeatability and freshness, DNS configuration, Terraform formatting, semantic lint and repository quality.
Goal-Ref: build-and-deploy-every-project-landing-page-a782b800 Attempt-ID: attempt-00941092c164
LLM-disclaimer: This commit was generated by an LLM.
-
Wait for AL secret cleanup and plugin shutdown
Roll back partial plugin startup, drain requests before releasing resources, and wait for plugin and command processes to exit. Stop independent plugins concurrently while preserving dependency order inside each plugin.
Revoke invocation-owned credentials, remove temporary secret files, and verify Forgejo and Harbor session cleanup. Preserve the user’s existing Vault login. Enforce Vault OIDC origins and no_auth, redact sensitive errors, and restrict config dumps to owner-only files. Add the AppRole SecretID cleanup permission.
Cover normal exit, cancellation, failed startup, credential revocation, and transport cleanup with synthetic unit and real command/plugin regression tests.
Clarify that required formatting-only repairs need no separate approval, and fix the existing blank-line formatting failure in the GitHub AL wrapper.
Goal-Ref: fix-al-secret-lifecycle-and-plugin-shutdown-3137c0b0 Attempt-ID: attempt-0c1353676e2f
LLM-disclaimer: This commit was generated by an LLM.
-
Extract DNSControl setup into rules_dnscontrol
Extract the DNSControl setup into
rules_dnscontrol, generate its Bazel dependency bundle from project-owned record files, and update the DNS guidance. Move Hugo rules and the worker to role-based package paths, and give each non-nested project a locally owned Hugo landing target that reuses the shared README-to-landing macro.Clean all landing and Pages DNS records so GitHub Pages serves each project subdomain directly without Cloudflare proxying. Improve the main site with a three-panel home layout, complete project links, documentation explore links, and current deployment guidance.
All affected root-workspace landing, DNS, and site targets pass, along with the nested
rules_hugotests, Buildifier, and repository quality checks.LLM-disclaimer: This commit was generated by an LLM.
-
Add standalone documentation rules
Move docs_filegroup into a reusable rules_docs nested Bzlmod workspace and migrate every root and nested consumer to it. Add a module-aware Gazelle language that creates docs targets only for existing README packages while preserving manual mappings.
Wire the workspace into module resolution, documentation aggregation, and the ten-command full-repo-check. Add the bazel-nested-module skill so future nested workspaces follow the repository’s rc, lockfile, docs, toolchain, Gazelle, and validation conventions.
Keep reviewed Gazelle dependency canonicalization, while protecting the hand-maintained Go proto, Python resource, Android, embedded-site, and skill runner definitions that generic language plugins would otherwise break.
This commit was generated by an LLM.
- Set up Split Horizon DNS, refactor IDM a bit
- Add //third_party/org_fedora_cloud, fix alwaldend.com roles
- Set up unikernel deploy
- Add signing policy to vault_pki_server
- Update cluster token ttl, update secrets
- Add sops, add vault_transit_key, add sops to fluxcd
- Add k3s_auth configs
- Add admin group for the flux cluster
- Use a custom traefik deploy instead of the bundled one
- Deploy ClusterIssuer for cert-manager
- Rewrite k3s role, finish flux deploy
- Add optional disk mount to traefik and forgejo, add ceph disks to forgejo VMs
- Enable asyncio=native, iothread, emulatessd, discard, add ceph disk support
- Disable firewalld in firewall role
- Move gateway into pve_vm_qemu
- Move pve to //infra/pve, remove //infra/dc1
- Remove consul IaC
- Add harbor_login, add harbor IaC, fix bazel’s certificates
- Add drawio-desktop, add //infra/arch, update opencode restrictions
- Finish the forgejo role
- Finish the traefik role
- Add fp modules, refactor tf backend to use it, add parallel start of plugins, add lock check to the backend
- Improve consul deploy, improve vault approles
- Migrate proxmox resource to separate resource pools, add a vm module
- Create folders and resource pools from approle config instead of duplication
- Set up automated PVE login using OIDC, remove PVE tokens
- Fix pve firewall, add //infra/dc1/consul1, standardize ssh and pki roles
- Add timezone management to the host role and TrustedUserCAKeys to the ssh role
- Set up OIDC with Vault as provider
- Set up ACME, disable mTLS for Vault
- Automate root token generation, split the main vault policy into separate ones
- Move vault tools to //tools/vault, replace go_binary in al_binary with native_binary
- Fix cert auth entities, reformat all tf files
- Set up client certificate generation, move ica to a separate module
- Add backup_bucket module, add rclone, set up backups for Vault
- Migrate all resources to separate terraform-managed cloud folders
- Add yc_folder terraform module, migrate to it
- Migrate Vault to Raft storage, start setting up backups, add postgresql role
- Migrate some docs target to the new macro
- Write a proper runner for terraform and vault, set up s3 backends for terraform
- Refactor approle management into a terraform module
- Initial commit
-
Add spellcheck skill
This commit was generated by an LLM.
-
Restore light and dark site canvases and set the shared accent
The shared Docsy canvas set the same Bootstrap dark palette and the same black page background on
:root,[data-bs-theme="light"], and[data-bs-theme="dark"], so the light/dark toggle changed nothing. The site also rendered Bootstrap’s stock blue instead of its intended accent.Split the shared palette so light mode uses a pure white canvas with the light-mode palette and dark mode uses a pure black canvas with the dark-mode palette, and keep the pre-stylesheet paint and footer on the active mode. Assign
$primaryto#7c3aedbefore Bootstrap compiles, so links, buttons, badges, focus rings, and the dark-mode link tint all derive from one value rather than from a site-local copy.Both files stay in the reusable shell; the apex site consumes them through the existing declared exports and no longer carries the footer’s own blue.
OpenSpec-Change: projects/hugo_landing/openspec/changes/restore-light-dark-canvas-and-accent
LLM-disclaimer: This commit was generated by an LLM.
1.18.8 - Terraform backend
1.18.9 - Vault approle
1.18.10 - Vault approle
1.18.11 - Vault OIDC provider
1.18.12 - Vault pki server
1.18.13 - Vault ssh server role
1.18.15 - Yc folder
1.19 - Useless QT GUI
Useless QT GUI is a desktop application built with C++ and Qt. Its Bazel build uses a pinned Qt distribution without requiring a system Qt installation.
Links
Features
- Desktop GUI
- C++, Qt
Build
The Bazel build downloads a SHA-256-pinned Qt 6.8.3 distribution through
rules_qt; a system Qt installation is not required. The project previously
targeted Qt 6.9.0. Using 6.8.3 is a deliberate downgrade to the LTS version
supported and tested by the pinned rules_qt release.
TODO
- Add some screenshots
2 - Infra
This tree contains infrastructure as code. Tracked source follows the repository’s public-source policy. Infrastructure facts are not confidential merely because they are operational, generated, or live. Reports may include them unless they contain credentials, other secrets, or personal information. Inspect raw state, plans, inventories, and decrypted configuration because those artifacts can contain prohibited content; do not track the artifacts themselves.
Each infrastructure project owns its specifications and maintained changes
in <project>/openspec/. Use the pinned OpenSpec workflow
with that project selected. These specifications describe checked-in definitions;
they do not establish deployed state or authorize infrastructure operations.
Requirements
- Bazel targets MUST use repository-internal visibility.
- Infrastructure definitions MUST NOT be published as production artifacts.
- Infrastructure targets MUST NOT be dependencies of production build targets.
- Public checked-in documentation MAY be included in the repository documentation site, including non-secret, non-personal operational facts.
New project
The commands below are state-changing operator examples. An agent must use
bazel_agent, apply the repository Terraform and secret-handling procedures,
and receive explicit authority for the exact operation and environment before
running an equivalent command.
- Create an approle: example
- Add it to approles: example
- Run apply:
bazel_agent bazel run //infra/vault/tf:tf.apply - Update Yandex Cloud folders:
bazel_agent bazel run //infra/yandex_cloud/org1/tf:tf.apply - Update Proxmox resource pools:
bazel_agent bazel run //infra/pve/tf:tf.apply - Update Xen Orchestra AppRole resource sets:
bazel_agent bazel run //infra/xcp_ng/tf:tf.apply - Set up al config: example
- Configure the component’s Terraform state through the existing
Vault HTTP backend flow.
The
tf_backendplugin creates state and lock KV entries on first use.
2.1 - Architecture
These diagrams render every page of the checked-in Drawio source. They describe the source document, not a live inventory or health check. Pages marked Archive retain the source’s historical classification. Open an image for its full-size SVG.
DC1
Vault
Flux
Forgejo
www
Threexui
DNS
Ingress
T3code
Truenas
Archive/Harvester
Archive/Opencode
Archive/Hermes
Archive/Proxmox
Archive/Harbor
Edit and regenerate
Open the canonical source with the pinned Drawio desktop tool:
bazel_agent bazel run //infra/arch
Regenerate the maintained SVGs after editing arch.drawio:
bazel_agent bazel run //infra/arch:update
bazel_agent bazel test //infra/arch:update_tests
The update target renders all 15 named pages in Bazel sandboxes with Drawio 30.2.6 web assets from the pinned desktop archive and the repository’s pinned headless Chrome. A pinned Liberation font set and isolated Fontconfig configuration keep text measurement independent of host fonts. The renderer loads only local assets, fails on missing pages and export errors, and records the source SHA-256 in each SVG. No display server, live infrastructure access, or runtime download is required. The freshness test compares rendered output with the maintained SVGs; documentation consumes those checked-in images.
2.1.1 -
Infrastructure architecture Specification
Purpose
Describe the maintained infrastructure diagrams owned by infra/arch.
The baseline is checked-in source at revision
550d7e79b1f5fdbc2b6017b75178471d6914082f, observed on 2026-09-08.
These diagrams describe their source document; they do not establish live
inventory, deployment, or health.
Requirements
Requirement: Canonical multi-page architecture source
The project SHALL use arch.drawio as the canonical source for its maintained
SVG diagrams and SHALL expose the source through the //infra/arch editor
target. The named render mapping SHALL preserve all 15 source pages, including
the five pages classified as archives.
Sources: project documentation, target and page definitions, and Drawio source.
Scenario: Render the maintained page set
- WHEN the
//infra/arch:renderedtarget processes the canonical document - THEN it produces the SVG output mapped to each of the 15 named pages, including separate outputs for archived pages.
Requirement: Reproducible diagram refresh
The project SHALL render diagrams through the repository’s pinned Drawio,
headless Chrome, and font inputs. The //infra/arch:update target SHALL update
the maintained SVGs, and //infra/arch:update_tests SHALL compare them with
freshly rendered output. Rendering SHALL use local assets and report missing
pages or export failures.
Sources: rendering guarantees and render and update targets.
Scenario: A maintained diagram becomes stale
- WHEN a source edit changes a rendered SVG without updating its maintained copy
- THEN the freshness test reports a mismatch, and the update target provides the regenerated source file.
Requirement: Documentation preserves historical classification
Documentation SHALL display the maintained SVGs with links to their full-size
images and SHALL retain the source’s Archive classification. The diagrams
SHALL remain documentation artifacts rather than evidence of live service
availability.
Source: diagram documentation.
Scenario: Consult a historical architecture page
- WHEN a reader opens the Proxmox architecture section
- THEN it is labeled
Archive/Proxmoxand links to the maintained SVG.
2.2 - Ceph
Links
- Proxmox docs: https://pve.proxmox.com/wiki/Deploy_Hyper-Converged_Ceph_Cluster
- Single node crushmap: https://imanudin.net/2025/05/12/proxmox-ceph-single-node-installation-for-test-lab-or-home-setup/
See current crush map
Go to Nodes -> Host -> Ceph -> Configuration
Crush map update
Ssh to the PVE host and update the map:
sudo ceph osd getcrushmap -o crushmap.cm
sudo crushtool --decompile crushmap.cm -o crushmap.txt
sudo vim crushmap.txt
sudo crushtool --compile crushmap.txt -o new_crushmap.cm
sudo ceph osd setcrushmap -i new_crushmap.cm
sudo ceph -s
2.2.1 -
Ceph infrastructure specification
Purpose
Describe the single-host Ceph CRUSH map maintained by infra/ceph and its
documented operator workflow. This owner contains a map and documentation;
its BUILD file exposes documentation, not a Ceph deployment target. The
baseline describes checked-in source, not an observed running cluster.
Baseline revision: 550d7e79b1f5fdbc2b6017b75178471d6914082f.
Observed: 2026-09-08. Sources: owner README,
BUILD, and
CRUSH map.
Requirements
Requirement: Single-host CRUSH topology
The maintained CRUSH map SHALL place four HDD devices, osd.0 through
osd.3, in the host1 bucket beneath the default root, using the declared
device weights and straw2 bucket algorithm.
Scenario: Inspect the recorded storage topology
- WHEN a maintainer reads the checked-in CRUSH map
- THEN all four OSDs belong to
host1, and thedefaultroot contains that host - AND this topology establishes a single-host placement baseline without asserting that the running cluster matches it
Requirement: OSD-level replicated and erasure placement
The maintained map SHALL define a replicated rule using
chooseleaf firstn 0 type osd and an erasure rule using
chooseleaf indep 0 type osd beneath the default root. The erasure rule
SHALL set chooseleaf attempts to 5 and choose attempts to 100.
Scenario: Inspect the placement failure domain
- WHEN a maintainer evaluates
replicated_ruleorceph-ec-data - THEN placement selects OSDs within the recorded topology
- AND the map provides no requirement for replica separation across hosts
Requirement: Operator workflow documentation
The owner documentation SHALL describe exporting, decompiling, editing, compiling, and installing a CRUSH map followed by a Ceph status check. Executing that workflow MUST remain subject to the repository’s explicit infrastructure-operation authorization requirement.
Scenario: Use the documented map update procedure
- WHEN an authorized operator follows the map update instructions
- THEN the procedure obtains the current map before creating its compiled
replacement and checks
ceph -safter installation - AND the presence of these instructions alone does not authorize a live map update
2.3 - Cloud-init
assets/cloud_init.yaml is the canonical configuration moved from PVE. PVE
and Yandex Cloud consume it directly. It owns the Ansible sudo user, SSH keys,
local TLS root CA, and common bootstrap policy. The Ansible SSH CA is selected by its certificate-authority principal options;
user and key ordering do not affect the Xen configuration. Missing or duplicate
Ansible users or CA keys fail template rendering.
assets/cloud_init_min.yaml is the existing minimal PVE configuration with
QEMU guest tools. Both original PVE files retain their contents.
The xen_linux target uses the repository’s rules_template Go template rule
to derive xen_linux.json from that same PVE configuration. Its small template
selects the shared Ansible CA key, uses Fedora’s users,wheel groups, and adds
Xen guest tools. It omits PVE’s explicit package-reboot and public metadata-key
flags to preserve the existing Xen bootstrap behavior. All other base fields,
including the TLS CA, come from the PVE configuration. There is no separate
copy of the Xen user or CA configuration and no Terraform template file.
Forgejo merges its hostname into the generated object and uses Terraform’s
yamlencode to serialize it. Its static network structure stays in Terraform,
where interface, address, MAC, gateway, and DNS are runtime values. The rendered
Forgejo user-data and network configuration remain byte-identical to the
previous configuration.
PVE Ansible packages the moved snippets under the existing
files/cloud_init.yaml and files/cloud_init_min.yaml names. Those packaging
aliases preserve local:snippets/cloud_init.yaml references on PVE hosts.
Subsequent persistent VM configuration belongs in Ansible. Targets are
repository-internal runtime inputs, not published artifacts.
2.4 - Dns
DNS records live in each owner’s dnsconfig.json. Each owner manages its records
through the reusable Terraform DNS module
from its designated tf_setup or tf root. This component’s
dnsconfig.json owns shared apex and mail records.
Declaration pages
Cloudflare DNS and Mikrotik DNS list the
records this repository declares for each destination view, with the owning
declaration for every record. They are generated from dnsconfig.json:
bazel_agent bazel run //infra/dns/cmd/dump -- --write
//infra/dns:config_test fails when a checked-in page is out of date, so the
pages cannot drift from the declarations they project.
Inspect and lint declarations
bazel_agent bazel run //infra/dns:lint
The linter discovers dnsconfig.json files in the current workspace at runtime
and prints their DNS declarations as a table. It includes nested project
workspaces and excludes task scratch, tool caches, and generated directories.
There is no central source registry to maintain when a project adds a file.
A canonical domain name must belong to one source file. Multiple values, record types, and destination views within that file are valid. Duplicate JSON object keys and domains declared by different source files are errors. The command reads checked-in declarations without contacting Terraform backends or DNS providers.
bazel_agent bazel test //infra/dns:config_test runs the linter’s fixture tests
and checks every DNS declaration in the current checkout. The repository test
resolves the root MODULE.bazel runfile to the checkout and runs without sandboxing
or cached test results so newly added files and nested workspaces are included
on every run. It only reads local files.
Terraform records
The provider-free normalization module
owns the Terraform input schema, relative-name handling, TTL defaults, and stable
resource keys. Each logical key can contain several record-type members; dsp
selects global, dc1, or all. Explicit member TTLs preserve shared apex and
mail settings. The normalization module remains an internal dependency of each
owner’s Terraform DNS module.
Owner-local roots receive their provider credentials and Vault HTTP state backend through the existing AL configuration. The shared module resolves the Cloudflare zone by name when no optional zone ID is provided. DNS and ingress reuse the RouterOS endpoint declared in the shared AL configuration, while their separate credentials remain in Vault. Neither integration requires adding metadata fields to the existing credential entries. Validate their source with the owning package’s offline checks. A live plan, import, apply, or state operation requires separate authorization for that owner and operation.
Service roots expose dns.plan, dns.show, and dns.apply alongside their
ordinary Terraform commands. They retain the owning root, AppRole and backend,
select the DNS AL calls, and plan module.dns. Required root inputs still load
through the existing read-only Vault injectors. Unrelated service authentication
is not selected. Apply accepts only a reviewed saved plan file and rejects
Terraform CLI argument environment overrides. See the runbook for the optional
import-ID maps and adoption checks.
Migration and recovery
The migration change and cutover runbook describe adoption, imports, recovery, and retirement requirements. Each owner’s adoption change records its verified live transfer; source implementation alone does not establish operational ownership. The completed coordination record links the operational acceptance evidence and its coverage limits.
Current source no longer exposes the central DNSControl deployment commands. Before an owner begins Terraform reconciliation, stop central deployment jobs identified by the active and scheduled writer audit. Record coverage and unavailable observations, and coordinate one owner at a time. Adopt existing records into the owner’s state with an exact-ID, no-change plan. Fresh complete inventories may establish missing declarations for a separately reviewed additions-only plan that preserves all existing records. Rollback requires stopping the affected Terraform writers and following the runbook’s recorded prior revision and state-reconciliation procedure.
Deployment snapshots are not maintained here. The generated declaration pages above project declared state, and the declarations themselves remain the only inventory.
2.4.1 -
Infrastructure DNS
Purpose
Describe owner-local Terraform DNS declarations and runtime source-ownership validation for global and dc1 records. This contract describes checked-in source; it does not establish live adoption or authorize infrastructure writes.
Sources: component documentation, target definitions, runtime linter, and Terraform root.
Requirements
Requirement: Aggregate records from their owning components
DNS declarations SHALL remain in their owners’ dnsconfig.json files. Runtime
inventory SHALL discover all canonical files, including nested modules and
empty declarations, without a checked-in ownership registry. The inventory
SHALL print a deterministic table of files, DNS names, types and views.
Project landing declarations retain their declared direct targets.
Scenario: A new project adds a canonical declaration
- WHEN the runtime linter scans a workspace containing the new file
- THEN it includes the file without requiring a registry update
Requirement: Preserve distinct global and site-local views
The Terraform module SHALL preserve Cloudflare global and MikroTik dc1 views. It SHALL retain every type member, expand and deduplicate destinations, reject unknown inputs and preserve effective values, TTLs, priorities and multiplicity.
Scenario: An entry declares A and AAAA in all views
- WHEN the shared module normalizes the entry
- THEN both types appear exactly once in each destination view
Scenario: An input names an unsupported destination
- WHEN a record names an unsupported destination
- THEN normalization fails with an actionable diagnostic
Requirement: Validate configuration without provider access
The linter and module tests SHALL validate source ownership, names, inputs, normalization and provider mappings without credentials or live provider access. Existing JSON-based VM consumers SHALL remain compatible.
Scenario: Validate a changed declaration
- WHEN offline checks run
- THEN they validate the declaration and fixtures without deploying records
Requirement: Inject credentials into operational wrappers
Owner Terraform roots SHALL use the existing AL/Vault authentication, backend and credential injection workflow. They SHALL obtain only their required view credentials. Operational provider initialization may require live credentials even with resource creation disabled. Central DNSControl write entrypoints SHALL be removed from the candidate.
Scenario: A global-only owner operates its root
- WHEN an authorized operator invokes the root after bootstrap
- THEN it uses that owner’s AppRole and Cloudflare credentials
- AND RouterOS credentials and resources are not required
Requirement: Reconcile DNS through its owner’s Terraform state
Each owner SHALL instantiate the shared module in tf_setup when present,
otherwise in tf. Missing roots and AppRoles SHALL be added. Related
AppRole resources SHALL be grouped in modules under
infra/vault/tf/approles/<name>. Provider instance keys SHALL be stable across
value-only changes; unrelated owners SHALL remain outside the state.
Scenario: An owner has both stages
- WHEN the integration is prepared
- THEN only its setup root declares the DNS module
Requirement: One declaration file owns each DNS name
The runtime linter SHALL reject different files managing the same canonical fully qualified DNS name, across types and views. Multiple records within one file SHALL be allowed. Diagnostics SHALL identify both files.
Scenario: Different files split a name across types or views
- WHEN one file declares an A record and another an AAAA record or a different view for the same name
- THEN lint fails and identifies both source files
Scenario: One file manages multiple records for a name
- WHEN one file declares several values, types or views for a name
- THEN ownership lint accepts the sole source
Requirement: Preserve live records during transfer
Operational cutover SHALL audit active and scheduled central writers, stop identified competing writers, and coordinate one owner at a time. Evidence SHALL state the audit’s coverage and unavailable observations. Each existing record SHALL be imported using its actual provider ID into exactly one owner state, followed by a no-change adoption plan before writes. Fresh complete inventories MAY establish missing declarations for an exact additions-only plan that preserves every existing record. Endpoint-owning batches SHALL verify an independent authenticated recovery path first.
The shared apex and mail records owned by infra/dns SHALL remain disabled
by default in its tf root before the authorized adoption revision and SHALL
retain enabled ownership after import. Reconciliation against the adopted state
and unchanged declarations SHALL propose no record additions, changes,
replacements, or deletions and SHALL preserve unrelated provider records.
Scenario: An owner is adopted
- WHEN its authorized cutover runs
- THEN exact-ID imports preserve existing records
- AND the operator coordinates exclusive active writers and verifies unrelated records remain unchanged
Scenario: Deploy verified missing declarations
- WHEN complete provider inventories establish that declared names are absent and conflict-free
- THEN the reviewed DNS plan creates only those missing declarations
- AND every existing provider identity and attribute remains unchanged
- AND a follow-up DNS plan contains no changes
Scenario: Inspect the prepared shared-record defaults
- WHEN the shared
tfroot uses its checked-in defaults before its authorized adoption revision - THEN shared-record ownership is disabled and the root retains the canonical shared declaration and module inputs
Scenario: Inspect adopted shared-record defaults
- WHEN the adopted shared
tfroot uses its checked-in source defaults - THEN ownership is enabled for the shared apex and mail records in their declared views
Scenario: Reconcile existing shared records
- WHEN the shared
tfroot plans against adopted state and unchanged declarations - THEN it proposes no record additions, changes, replacements, or deletions
- AND unrelated provider records remain unchanged
Requirement: Avoid a separate DNS exporter
The implementation SHALL derive its declaration views from the owning
dnsconfig.json files rather than maintaining a normalized inventory or BIND
exporter. Historical provider snapshots SHALL NOT be presented as current
desired state, and no provider snapshot SHALL be committed as a declaration
source.
Scenario: Inspect declared ownership
- WHEN the runtime linter succeeds
- THEN its table reports the discovered declarations without an export step
Requirement: Publish declaration pages per destination view
The implementation SHALL render one documentation page per destination view from the declared records, with the owning declaration for every record, and SHALL fail its offline check when a checked-in page differs from the declarations it projects.
Scenario: Regenerate a declaration page
- WHEN an owner changes a declaration and the generation command runs
- THEN the affected view’s page lists the declared records with their owner
- AND the check passes against the regenerated page
Scenario: A declaration page is stale
- WHEN a checked-in page no longer matches the declarations
- THEN the offline check fails rather than serving a stale inventory
2.4.2 - Cloudflare DNS
Every record this repository declares for the public zone, which Cloudflare serves.
This page is generated from the declarations; run bazel run //infra/dns/cmd/dump -- --write after changing them. The authoritative source is each owner’s dnsconfig.json.
| Domain | Type | TTL | Value | Declaration |
|---|---|---|---|---|
| @ | A | 300 | 185.199.108.153 | infra/dns/dnsconfig.json |
| @ | A | 300 | 185.199.109.153 | infra/dns/dnsconfig.json |
| @ | A | 300 | 185.199.110.153 | infra/dns/dnsconfig.json |
| @ | A | 300 | 185.199.111.153 | infra/dns/dnsconfig.json |
| @ | AAAA | 300 | 2606:50c0:8000::153 | infra/dns/dnsconfig.json |
| @ | AAAA | 300 | 2606:50c0:8001::153 | infra/dns/dnsconfig.json |
| @ | AAAA | 300 | 2606:50c0:8002::153 | infra/dns/dnsconfig.json |
| @ | AAAA | 300 | 2606:50c0:8003::153 | infra/dns/dnsconfig.json |
| @ | MX | 300 | 10 mail.protonmail.ch. | infra/dns/dnsconfig.json |
| @ | MX | 300 | 20 mailsec.protonmail.ch. | infra/dns/dnsconfig.json |
| @ | TXT | 300 | _globalsign-domain-verification=0QBJgVV_uwcFLTi1Rot3bb1LyJ5uW1WD0ygvIS4OM5 | infra/dns/dnsconfig.json |
| @ | TXT | 300 | protonmail-verification=bdcd133d3f472fa17f66328950d02fbeae1bef75 | infra/dns/dnsconfig.json |
| @ | TXT | 300 | v=spf1 include:_spf.protonmail.ch ~all | infra/dns/dnsconfig.json |
| _dmarc | TXT | 300 | v=DMARC1; p=quarantine; adkim=s | infra/dns/dnsconfig.json |
| _dmarc.simplelogin | TXT | 10800 | v=DMARC1; p=quarantine; pct=100; adkim=s; aspf=s | infra/dns/dnsconfig.json |
| canvas.openhands | CNAME | default | ingress.alwaldend.com. | infra/openhands/dnsconfig.json |
| cloud | CNAME | default | ingress.alwaldend.com. | infra/nas/dnsconfig.json |
| dc1.automation.openhands | A | default | 192.168.10.92 | infra/openhands/dnsconfig.json |
| dc1.canvas.openhands | A | default | 192.168.10.90 | infra/openhands/dnsconfig.json |
| dc1.cloud | A | default | 192.168.1.209 | infra/nas/dnsconfig.json |
| dc1.host-bot.simeonwarren.users | A | default | 192.168.1.210 | users/simeonwarren/host_bot/dnsconfig.json |
| dc1.server.openhands | A | default | 192.168.10.91 | infra/openhands/dnsconfig.json |
| dc1.t3code.host-bot.simeonwarren.users | A | default | 192.168.1.210 | users/simeonwarren/host_bot/dnsconfig.json |
| dkim._domainkey.simplelogin | CNAME | 10800 | dkim._domainkey.simplelogin.co. | infra/dns/dnsconfig.json |
| dkim02._domainkey.simplelogin | CNAME | 10800 | dkim02._domainkey.simplelogin.co. | infra/dns/dnsconfig.json |
| dkim03._domainkey.simplelogin | CNAME | 10800 | dkim03._domainkey.simplelogin.co. | infra/dns/dnsconfig.json |
| forgejo | CNAME | default | ingress.alwaldend.com. | infra/forgejo/dnsconfig.json |
| git | CNAME | default | ingress.alwaldend.com. | infra/forgejo/dnsconfig.json |
| host1.ingress | A | default | 81.26.185.118 | infra/ingress/dnsconfig.json |
| ingress | A | default | 81.26.185.118 | infra/ingress/dnsconfig.json |
| int.forgejo | A | default | 192.168.10.40 | infra/forgejo/dnsconfig.json |
| int.vault | A | default | 192.168.1.218 | infra/vault/dnsconfig.json |
| mail._domainkey.yandex | TXT | 300 | v=DKIM1; k=rsa; t=s; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCcYzFVgkeDOhaIIkWM8gNQjxVsv0/aXfU+ax5urB5y6hA6lSjRnjRo6tm0bXbkOJf41GmiwMNgdXpwRtzgzAlX1i2aJbtEr4b9jzibEGLQ7Cvqs44bOYES9f/K3ueQpnvdTOJmFqlRReFL7ZrUyDFCoQ7f4+7h4i8s01cCcRrt5wIDAQAB | infra/dns/dnsconfig.json |
| njalla1.nodes.threexui | A | default | 45.142.141.133 | infra/threexui/dnsconfig.json |
| njalla1.nodes.threexui | AAAA | default | 2a0a:3840:8078:141:0:2d8e:8d85:1337 | infra/threexui/dnsconfig.json |
| pages | A | default | 185.199.108.153 | projects/alwaldend.com/dnsconfig.json |
| pages | AAAA | default | 2606:50c0:8000::153 | projects/alwaldend.com/dnsconfig.json |
| protonmail._domainkey | CNAME | 300 | protonmail.domainkey.djgwfzcu5fgjtpoijqqomgifmqj6zeiuwdd4mzim4hrxab3zsgwkq.domains.proton.ch. | infra/dns/dnsconfig.json |
| protonmail2._domainkey | CNAME | 300 | protonmail2.domainkey.djgwfzcu5fgjtpoijqqomgifmqj6zeiuwdd4mzim4hrxab3zsgwkq.domains.proton.ch. | infra/dns/dnsconfig.json |
| protonmail3._domainkey | CNAME | 300 | protonmail3.domainkey.djgwfzcu5fgjtpoijqqomgifmqj6zeiuwdd4mzim4hrxab3zsgwkq.domains.proton.ch. | infra/dns/dnsconfig.json |
| simplelogin | MX | 10800 | 10 mx1.simplelogin.co. | infra/dns/dnsconfig.json |
| simplelogin | MX | 10800 | 20 mx2.simplelogin.co. | infra/dns/dnsconfig.json |
| simplelogin | TXT | 10800 | sl-verification=bxfzzfjiggzsxyzxhhmkmjqkaskjgy | infra/dns/dnsconfig.json |
| simplelogin | TXT | 10800 | v=spf1 include:simplelogin.co ~all | infra/dns/dnsconfig.json |
| t3code.host-bot.simeonwarren.users | CNAME | default | ingress.alwaldend.com. | users/simeonwarren/host_bot/dnsconfig.json |
| vault | CNAME | default | ingress.alwaldend.com. | infra/vault/dnsconfig.json |
| www | CNAME | 300 | alwaldend.com. | infra/dns/dnsconfig.json |
| www-staging | CNAME | 300 | alwaldend.github.io. | infra/dns/dnsconfig.json |
| yandex | MX | 21600 | 10 mx.yandex.net. | infra/dns/dnsconfig.json |
| yandex | TXT | 300 | v=spf1 redirect=_spf.yandex.net | infra/dns/dnsconfig.json |
| yandex | TXT | 300 | yandex-verification: b83672f59b3dbe16 | infra/dns/dnsconfig.json |
| yc.threexui | NS | default | ns1.yandexcloud.net. | infra/threexui/dnsconfig.json |
| yc.threexui | NS | default | ns2.yandexcloud.net. | infra/threexui/dnsconfig.json |
| yc1.nodes.threexui | CNAME | default | host1.nodes.yc.threexui.alwaldend.com. | infra/threexui/dnsconfig.json |
2.4.3 - Mikrotik DNS
Every record this repository declares for the internal dc1 view, which RouterOS serves for that network.
This page is generated from the declarations; run bazel run //infra/dns/cmd/dump -- --write after changing them. The authoritative source is each owner’s dnsconfig.json.
| Domain | Type | TTL | Value | Declaration |
|---|---|---|---|---|
| @ | A | 300 | 185.199.108.153 | infra/dns/dnsconfig.json |
| @ | A | 300 | 185.199.109.153 | infra/dns/dnsconfig.json |
| @ | A | 300 | 185.199.110.153 | infra/dns/dnsconfig.json |
| @ | A | 300 | 185.199.111.153 | infra/dns/dnsconfig.json |
| @ | AAAA | 300 | 2606:50c0:8000::153 | infra/dns/dnsconfig.json |
| @ | AAAA | 300 | 2606:50c0:8001::153 | infra/dns/dnsconfig.json |
| @ | AAAA | 300 | 2606:50c0:8002::153 | infra/dns/dnsconfig.json |
| @ | AAAA | 300 | 2606:50c0:8003::153 | infra/dns/dnsconfig.json |
| @ | MX | 300 | 10 mail.protonmail.ch. | infra/dns/dnsconfig.json |
| @ | MX | 300 | 20 mailsec.protonmail.ch. | infra/dns/dnsconfig.json |
| @ | TXT | 300 | _globalsign-domain-verification=0QBJgVV_uwcFLTi1Rot3bb1LyJ5uW1WD0ygvIS4OM5 | infra/dns/dnsconfig.json |
| @ | TXT | 300 | protonmail-verification=bdcd133d3f472fa17f66328950d02fbeae1bef75 | infra/dns/dnsconfig.json |
| @ | TXT | 300 | v=spf1 include:_spf.protonmail.ch ~all | infra/dns/dnsconfig.json |
| _dmarc | TXT | 300 | v=DMARC1; p=quarantine; adkim=s | infra/dns/dnsconfig.json |
| _dmarc.simplelogin | TXT | 10800 | v=DMARC1; p=quarantine; pct=100; adkim=s; aspf=s | infra/dns/dnsconfig.json |
| automation.openhands | A | default | 192.168.10.92 | infra/openhands/dnsconfig.json |
| bm1.dc1 | A | default | 192.168.1.222 | infra/mikrotik/dnsconfig.json |
| bm2.dc1 | A | default | 192.168.1.216 | infra/pve/dnsconfig.json |
| bm2.dc1 | AAAA | default | fd2e:546d:5738:0:365a:60ff:fe08:6daa | infra/pve/dnsconfig.json |
| bm3.dc1 | A | default | 192.168.1.218 | infra/vault/dnsconfig.json |
| bm3.dc1 | AAAA | default | fd2e:546d:5738:0:e2be:3ff:fe2b:9a1a | infra/vault/dnsconfig.json |
| canvas.openhands | A | default | 192.168.10.90 | infra/openhands/dnsconfig.json |
| cloud | CNAME | default | nas.alwaldend.com. | infra/nas/dnsconfig.json |
| cloudinit-test.vm.pve1.dc1 | A | default | 192.168.10.10 | infra/pve/dnsconfig.json |
| dc1.automation.openhands | A | default | 192.168.10.92 | infra/openhands/dnsconfig.json |
| dc1.canvas.openhands | A | default | 192.168.10.90 | infra/openhands/dnsconfig.json |
| dc1.cloud | A | default | 192.168.1.209 | infra/nas/dnsconfig.json |
| dc1.host-bot.simeonwarren.users | A | default | 192.168.1.210 | users/simeonwarren/host_bot/dnsconfig.json |
| dc1.server.openhands | A | default | 192.168.10.91 | infra/openhands/dnsconfig.json |
| dc1.t3code.host-bot.simeonwarren.users | A | default | 192.168.1.210 | users/simeonwarren/host_bot/dnsconfig.json |
| dkim._domainkey.simplelogin | CNAME | 10800 | dkim._domainkey.simplelogin.co. | infra/dns/dnsconfig.json |
| dkim02._domainkey.simplelogin | CNAME | 10800 | dkim02._domainkey.simplelogin.co. | infra/dns/dnsconfig.json |
| dkim03._domainkey.simplelogin | CNAME | 10800 | dkim03._domainkey.simplelogin.co. | infra/dns/dnsconfig.json |
| flux | A | default | 192.168.10.60 | infra/flux/dnsconfig.json |
| forgejo | A | default | 192.168.10.40 | infra/forgejo/dnsconfig.json |
| git | A | default | 192.168.10.40 | infra/forgejo/dnsconfig.json |
| harbor | A | default | 192.168.10.50 | infra/harbor/dnsconfig.json |
| host-bot.simeonwarren.users | A | default | 192.168.1.210 | users/simeonwarren/host_bot/dnsconfig.json |
| host1.automation.openhands | A | default | 192.168.10.92 | infra/openhands/dnsconfig.json |
| host1.canvas.openhands | A | default | 192.168.10.90 | infra/openhands/dnsconfig.json |
| host1.cloud | CNAME | default | host1.nas.alwaldend.com. | infra/nas/dnsconfig.json |
| host1.flux | A | default | 192.168.10.60 | infra/flux/dnsconfig.json |
| host1.forgejo | A | default | 192.168.10.40 | infra/forgejo/dnsconfig.json |
| host1.harbor | A | default | 192.168.10.50 | infra/harbor/dnsconfig.json |
| host1.ingress | A | default | 81.26.185.118 | infra/ingress/dnsconfig.json |
| host1.nas | A | default | 192.168.1.209 | infra/nas/dnsconfig.json |
| host1.pve1.dc1 | CNAME | default | bm2.dc1.alwaldend.com. | infra/pve/dnsconfig.json |
| host1.server.openhands | A | default | 192.168.10.91 | infra/openhands/dnsconfig.json |
| host1.threexui | A | default | 192.168.10.80 | infra/threexui/dnsconfig.json |
| host1.vault.dc1 | A | default | 192.168.1.218 | infra/vault/dnsconfig.json |
| host1.xcp-ng | A | default | 192.168.1.213 | infra/xcp_ng/dnsconfig.json |
| host1.xoa.xcp-ng | A | default | 192.168.1.206 | infra/xcp_ng/dnsconfig.json |
| ingress | A | default | 81.26.185.118 | infra/ingress/dnsconfig.json |
| mail._domainkey.yandex | TXT | 300 | v=DKIM1; k=rsa; t=s; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCcYzFVgkeDOhaIIkWM8gNQjxVsv0/aXfU+ax5urB5y6hA6lSjRnjRo6tm0bXbkOJf41GmiwMNgdXpwRtzgzAlX1i2aJbtEr4b9jzibEGLQ7Cvqs44bOYES9f/K3ueQpnvdTOJmFqlRReFL7ZrUyDFCoQ7f4+7h4i8s01cCcRrt5wIDAQAB | infra/dns/dnsconfig.json |
| nas | A | default | 192.168.1.209 | infra/nas/dnsconfig.json |
| njalla1.nodes.threexui | A | default | 45.142.141.133 | infra/threexui/dnsconfig.json |
| njalla1.nodes.threexui | AAAA | default | 2a0a:3840:8078:141:0:2d8e:8d85:1337 | infra/threexui/dnsconfig.json |
| openid.flux | CNAME | default | flux.alwaldend.com. | infra/flux/dnsconfig.json |
| operator.flux | CNAME | default | flux.alwaldend.com. | infra/flux/dnsconfig.json |
| protonmail._domainkey | CNAME | 300 | protonmail.domainkey.djgwfzcu5fgjtpoijqqomgifmqj6zeiuwdd4mzim4hrxab3zsgwkq.domains.proton.ch. | infra/dns/dnsconfig.json |
| protonmail2._domainkey | CNAME | 300 | protonmail2.domainkey.djgwfzcu5fgjtpoijqqomgifmqj6zeiuwdd4mzim4hrxab3zsgwkq.domains.proton.ch. | infra/dns/dnsconfig.json |
| protonmail3._domainkey | CNAME | 300 | protonmail3.domainkey.djgwfzcu5fgjtpoijqqomgifmqj6zeiuwdd4mzim4hrxab3zsgwkq.domains.proton.ch. | infra/dns/dnsconfig.json |
| pve | A | default | 192.168.1.216 | infra/pve/dnsconfig.json |
| router1.dc1 | A | default | 192.168.1.1 | infra/mikrotik/dnsconfig.json |
| router1.dc1 | AAAA | default | fd2e:546d:5738::1 | infra/mikrotik/dnsconfig.json |
| runner1.forgejo-runner | A | default | 192.168.10.100 | infra/forgejo_runner/dnsconfig.json |
| server.openhands | A | default | 192.168.10.91 | infra/openhands/dnsconfig.json |
| simplelogin | MX | 10800 | 10 mx1.simplelogin.co. | infra/dns/dnsconfig.json |
| simplelogin | MX | 10800 | 20 mx2.simplelogin.co. | infra/dns/dnsconfig.json |
| simplelogin | TXT | 10800 | sl-verification=bxfzzfjiggzsxyzxhhmkmjqkaskjgy | infra/dns/dnsconfig.json |
| simplelogin | TXT | 10800 | v=spf1 include:simplelogin.co ~all | infra/dns/dnsconfig.json |
| switch1.dc1 | A | default | 192.168.1.254 | infra/mikrotik/dnsconfig.json |
| t3code.host-bot.simeonwarren.users | A | default | 192.168.1.210 | users/simeonwarren/host_bot/dnsconfig.json |
| threexui | A | default | 192.168.10.80 | infra/threexui/dnsconfig.json |
| vault | A | default | 192.168.1.218 | infra/vault/dnsconfig.json |
| vault.dc1 | A | default | 192.168.1.218 | infra/vault/dnsconfig.json |
| www | CNAME | 300 | alwaldend.com. | infra/dns/dnsconfig.json |
| www-staging | CNAME | 300 | alwaldend.github.io. | infra/dns/dnsconfig.json |
| xcp-ng | A | default | 192.168.1.213 | infra/xcp_ng/dnsconfig.json |
| xoa.xcp-ng | A | default | 192.168.1.206 | infra/xcp_ng/dnsconfig.json |
| yandex | MX | 21600 | 10 mx.yandex.net. | infra/dns/dnsconfig.json |
| yandex | TXT | 300 | v=spf1 redirect=_spf.yandex.net | infra/dns/dnsconfig.json |
| yandex | TXT | 300 | yandex-verification: b83672f59b3dbe16 | infra/dns/dnsconfig.json |
| yc.threexui | NS | default | ns1.yandexcloud.net. | infra/threexui/dnsconfig.json |
| yc.threexui | NS | default | ns2.yandexcloud.net. | infra/threexui/dnsconfig.json |
| yc1.nodes.threexui | CNAME | default | host1.nodes.yc.threexui.alwaldend.com. | infra/threexui/dnsconfig.json |
2.4.4 - Shared DNS Terraform
This root consumes the canonical common declarations
through the reusable DNS module. It uses the src_infra_dns AppRole and its
existing Vault-backed HTTP state. Both Cloudflare and RouterOS credentials
are injected through the tf=1 stage label.
Shared apex and mail records were adopted on 2026-09-13. dns_enabled now
defaults to true; reconciliation against the adopted state and unchanged
declarations must propose no record changes. The adoption evidence
records 60 imports and preservation of both complete provider inventories.
Operational calls require the AppRole policy and Vault credential fields
described by the cutover procedure.
The module’s import_addresses output gives addresses relative to module.dns;
actual provider IDs come from the authorized adoption inventory.
Build the wrappers or run :tf_tests.fmt_test for offline validation. Import,
plan and apply follow the separately authorized adoption procedure.
2.5 - flux
Links
- Site: https://fluxcd.io/
Set up port forwarding
ssh -L 6443:127.0.0.1:6443 -N flux.alwaldend.com
Run flux CLI
bazel run //infra/flux/cl:flux
Show flux status
bazel run infra/flux/cl:flux -- get all -A
Run bootstrap
bazel run //infra/flux/cl:flux.bootstrap
Run flux operator
bazel run //infra/flux/cl:op
Show oidc info
bazel run //infra/flux/cl:oidc
Renew certificate
bazel run //infra/flux/cl:cmctl -- renew traefik-gateway-websecure-tls -n traefik
Update secrets
- Generate secret id and the token:
SECRET_ID=$(bazel run //infra/flux/cl:vault.secret_id | jq -r .data.secret_id) TOKEN=$(echo "${SECRET_ID}" | bazel run //infra/flux/cl:vault.ops_token | jq -r .auth.client_token) echo "Secret id: ${SECRET_ID}, Token: ${TOKEN}" - Patch secret-id in ./cl/cert-manager/issuer-approle.yaml
- Patch token in projects/kustomization/flux-repo/flux-sops-secret.yaml
- Encrypt:
bazel run //infra/flux/cl:sops.encrypt infra/flux/cl/cert-manager/issuer-approle.yaml bazel run //infra/flux/cl:sops.encrypt projects/kustomization/flux-repo/flux-sops-secret.yaml bazel run //infra/flux/cl:sops.encrypt projects/kustomization/flux-repo/flux-git-src-secret.yaml
2.5.1 -
Flux infrastructure specification
Purpose
Describe the Flux management cluster’s VM definition, K3s configuration,
and Git reconciliation entry points owned by infra/flux. The tf_setup,
ansible, and cl packages implement stages of this owner. This is a
checked-in source baseline; no cluster health or successful deployment was
observed for this specification.
Baseline revision: 550d7e79b1f5fdbc2b6017b75178471d6914082f.
Observed: 2026-09-08. Sources: owner README,
BUILD, and the implementation links below.
Requirements
Requirement: Dedicated K3s management host
Terraform setup SHALL declare a Proxmox VM in the src_infra_flux pool with
two cores, 4096 MiB memory, and separate 20 GiB boot, K3s data, and K3s
storage disks. The deployment playbook SHALL apply the shared host and K3s
roles, and the K3s configuration SHALL enable secrets encryption and disable
the bundled Traefik component.
Sources: VM definition, deployment playbook, and K3s configuration.
Scenario: Inspect the management cluster deployment definition
- WHEN a maintainer evaluates the setup and deployment source
- THEN VM provisioning, host configuration, and K3s configuration are separate stages with the recorded compute and disk allocation
- AND the K3s configuration enables secrets encryption at rest
Requirement: Git reconciliation for Flux and Harbor
The cluster’s root Kustomization SHALL include the Flux and Harbor
reconciliation trees. Flux’s reconciliation resources SHALL read the
flux-git-src GitRepository and use SOPS decryption through
flux-sops-secret, with pruning enabled and forced replacement disabled.
The Harbor tree SHALL include its remote-cluster configuration and Harbor’s
Flux manifests.
Sources: root Kustomization, Flux reconciliation, and Harbor reconciliation tree.
Scenario: Resolve the reconciliation source tree
- WHEN the checked-in root Kustomization is traversed
- THEN both
src-infra-flux-clandsrc-infra-harbor-clare included - AND the Flux reconciliation resources retain their Git source, decryption reference, and explicit prune and force settings
Requirement: Packaged operator and controller configuration
The cluster package SHALL provide repository-configured Flux, Flux operator, kubectl, Helm, certificate-manager, and SOPS command wrappers. Its Flux instance SHALL declare source, Kustomize, Helm, notification, image-reflector, image-automation, and source-watcher controllers, with network policy enabled.
Sources: cluster BUILD and Flux instance.
Scenario: Select a repository operator entry point
- WHEN an operator selects a declared cluster command target
- THEN the target supplies the packaged tool and the Flux owner’s
alconfiguration - AND the controller source records the enabled components without asserting that they are currently available in a live cluster
2.5.2 -
owned-dns Specification
Purpose
Define Flux DNS management through the owner’s tf_setup root,
including canonical declarations, scoped credentials, and offline source checks
before adopting live records.
Requirements
Requirement: Owner-local DNS configuration
The tf_setup root SHALL consume this owner’s canonical dnsconfig.json through
the shared DNS Terraform module, preserving declared record identities and views.
DNS resources SHALL default to disabled before adoption and SHALL remain enabled
by default after authorized adoption. Adoption SHALL bind existing provider records
to the owner’s state without adding, changing, replacing, or deleting DNS records.
Subsequent reconciliation of unchanged declarations SHALL preserve owned and
unrelated records.
Scenario: Inspect the preparatory configuration
- WHEN the checked-in root is evaluated with default inputs before adoption
- THEN it reads this owner’s declaration and disables managed DNS records
- AND the package contains the module and declaration inputs
Scenario: Inspect the adopted configuration
- WHEN the adopted root is evaluated with default inputs
- THEN it reads this owner’s declaration and enables managed DNS records
- AND the package contains the module and declaration inputs
Scenario: Adopt existing records
- WHEN the owner applies a reviewed saved import plan through
//infra/flux/tf_setup:dns.apply - THEN the owner state binds each declared record to its existing provider identity
- AND the reviewed adoption plan proposes no record additions, changes, replacements, or deletions
Scenario: Reconcile unchanged declarations
- WHEN the adopted root plans and applies unchanged declarations through its
//infra/flux/tf_setupwrappers - THEN it makes no DNS resource changes
- AND owned records retain their declared values and views while unrelated records remain unchanged
Requirement: Scoped DNS execution and offline checks
The DNS wrappers SHALL select src_infra_flux through the repository AL flow and
keep secret values in injected variables. The dns.plan, dns.show, and
dns.apply targets SHALL select dns=1 and retain the owner’s setup backend;
plans SHALL target module.dns and apply SHALL require a reviewed saved plan.
Ordinary setup wrappers SHALL retain their service authentication behavior.
Real DNS credentials and Vault policy grants SHALL be prerequisites for operational
Terraform calls. RouterOS DNS credentials SHALL remain isolated from unrelated
RouterOS resources. The package SHALL expose a format test without live credentials.
DNS-targeted validation SHALL NOT establish unrelated VM or service health.
Scenario: Validate the Terraform source
- WHEN the package format test executes
- THEN it checks the packaged Terraform configuration without live credentials
- AND existing non-DNS authentication and backend paths remain unchanged
Scenario: Prepare an operational Terraform invocation
- WHEN an authorized operator selects the owner’s DNS wrapper
- THEN it selects DNS credential injection through the owner AppRole and setup backend
- AND its scoped plan and saved-plan apply cover DNS and its dependencies
- AND disabled DNS resources do not imply offline provider configuration
2.5.3 - Ansible
2.5.4 - cl
Links
- Cert manager charts: https://artifacthub.io/packages/helm/cert-manager/cert-manager
2.5.5 - Tf setup
This root owns the Flux DNS declaration. DNS ownership defaults to enabled after verified adoption; keep it enabled to retain the managed records.
Use //infra/flux/tf_setup:dns.plan, :dns.show, and :dns.apply for
scoped DNS reconciliation.
These targets retain the setup backend and src_infra_flux AppRole, select
dns=1, and target module.dns. Apply requires a reviewed saved plan.
Reconciliation of unchanged declarations must produce no DNS changes.
The ordinary setup targets retain their service authentication behavior. DNS checks do not establish PVE VM or service health; current aggregate source validation remains part of repository delivery.
2.6 - forgejo
Links
- Docs: https://forgejo.org/docs/latest/admin/installation/binary/
- Config reference: https://forgejo.org/docs/latest/admin/config-cheat-sheet/
Repository configuration
Service Terraform consumes the shared repository catalog for organization-owned repositories and named administrator/developer roles. Vault continues to own OIDC login identities and service-specific access. See service Terraform for identity validation, state adoption, and the preserved automation grants.
Deployment
Forgejo is recreated on XCP-ng through Xen Orchestra, using the
src_infra_dc1_forgejo1 resource set provisioned by infra/xcp_ng.
VM provisioning authenticates to XO through Vault OIDC as Forgejo’s own
AppRole. Its exact synchronized user receives the resource-set membership
and an explicit administration ACL on the existing Forgejo VM; it does not
use the shared infrastructure administrator token. These bindings must be
applied by infra/xcp_ng/tf before Forgejo’s setup Terraform runs.
The canonical service URL is https://git.alwaldend.com. The previous
forgejo.alwaldend.com name remains available for existing clients.
The VM retains 192.168.10.40 and host1.forgejo.alwaldend.com. Its boot, Forgejo,
and Traefik disks are 20, 40, and 5 GiB respectively.
See Terraform setup for the template, network, storage, and previous-state prerequisites. These commands create and configure a fresh service; they do not restore the destroyed Proxmox VM’s data.
Fresh host hardening can outlast the ten-minute Vault token. Run host setup and service deployment separately to obtain fresh authentication for each phase. Ansible creates the missing Vault OIDC login source after starting Forgejo; existing active Vault sources are preserved.
Before configuring Forgejo with Terraform, set TF_VAR_vault_oauth_source_id
to the verified ID of the active vault OIDC source, as described in
service Terraform. Its narrowly scoped Vault entity-read policy
must be provisioned first so the required external users can be created.
The guest disables IPv4 redirect acceptance so its traffic uses the configured gateway. LAN clients must also retain symmetric routes: same-interface router redirects can otherwise make connections fail. Router redirect policy and stale client route caches must be resolved before relying on LAN access.
bazel_agent bazel run //infra/forgejo/tf_setup:tf_setup.apply
bazel_agent bazel run //infra/forgejo/ansible:ansible -- --skip-tags traefik,forgejo,forgejo_oidc
bazel_agent bazel run //infra/forgejo/ansible:ansible -- --tags traefik,forgejo,forgejo_oidc
bazel_agent bazel run //infra/forgejo/tf:tf.apply
2.6.1 -
Forgejo infrastructure specification
Purpose
Describe the Forgejo service owned by infra/forgejo, including Xen
Orchestra provisioning, Ansible service configuration, and Terraform account
and repository management. The tf_setup, ansible, and tf packages are
implementation stages of this owner. This baseline records source guarantees
and prerequisites; it does not verify live service health or restore earlier
Forgejo data.
Baseline revision: 550d7e79b1f5fdbc2b6017b75178471d6914082f.
Observed: 2026-09-08. Sources: owner README,
BUILD, and the implementation links below.
Requirements
Requirement: Scoped Xen Orchestra provisioning and disk checks
Setup SHALL provision Forgejo through Xen Orchestra in the
src_infra_dc1_forgejo1 resource set using the owner’s Vault AppRole and
packaged XO OIDC login flow. The VM SHALL declare 20 GiB boot, 40 GiB
Forgejo, and 5 GiB Traefik disks. Ansible SHALL verify the expected sizes
of xvdb and xvdc before applying the service roles that use them.
Sources: setup contract, setup BUILD, VM definition, and deployment playbook.
Scenario: Detect unexpected Xen disk attachments
- WHEN Ansible gathers disks that do not match the expected Forgejo and Traefik device names and sizes
- THEN its pre-task assertion fails before the service roles run
Requirement: Canonical service routing with legacy hostname support
Forgejo SHALL configure https://git.alwaldend.com/ as its canonical root
URL, bind its HTTP service to loopback port 3000, and enable the built-in
SSH service on port 3005. Traefik SHALL route the canonical hostname, the
inventory hostname, and forgejo.alwaldend.com to that HTTP service with
the Vault certificate resolver.
Sources: service variables, Forgejo configuration, and Traefik routing.
Scenario: Inspect support for existing Forgejo clients
- WHEN the Traefik routing template is rendered with the owner’s variables
- THEN the canonical and legacy hostnames resolve to the same configured loopback service
- AND generated Forgejo URLs use the canonical Git hostname
Requirement: Guarded Vault OIDC bootstrap
The deployment playbook SHALL create a missing vault OIDC authentication
source after configuring the Forgejo service. It SHALL preserve one existing
active OAuth2 source and reject multiple matches, an inactive source, or a
source of another type. Creation SHALL obtain client credentials from the
injected environment and suppress secret-bearing task output.
Source: deployment playbook.
Scenario: Preserve an existing active authentication source
- WHEN Forgejo reports exactly one active OAuth2 source named
vault - THEN the bootstrap accepts it and skips source creation
Scenario: Reject an ambiguous authentication source
- WHEN more than one
vaultsource is discovered, or its type or active state is incompatible - THEN the bootstrap assertion fails rather than selecting or replacing an arbitrary source
Requirement: Vault identities and service grants with catalog named roles
Service Terraform SHALL require a verified positive integer Vault OAuth
source ID, discover login users from the owning Vault group through at most
two nested group levels, and use entity UUIDs as external login names.
Managed accounts SHALL be protected from deletion. The shared repository
catalog SHALL own named organization administrator and developer assignments
and organization-owned repository identities. Catalog members and Vault
access-group members SHALL belong to the discovered login population.
Existing Vault service-administrator, package-writer, and automation-writer
grants SHALL be retained; the src automation writer group SHALL resolve to
exactly one user. A catalog developer SHALL NOT also receive administrator
access through the retained Vault groups.
Sources: service Terraform contract, users, access validation, and repository access. The shared catalog contract owns repository naming and named-role assignments; its adoption change records the source migration and pending verification.
Scenario: Reject unsupported group membership
- WHEN a login group extends beyond two nested levels, an access-group member is outside the login population, or the automation writer count is not one
- THEN the corresponding Terraform condition rejects the configuration
- AND Terraform does not silently omit the unsupported membership
Scenario: Resolve a catalog member through Vault
- WHEN a catalog administrator or developer is assigned organization access
- THEN that assignment uses the discovered account’s existing Vault entity UUID and verified OAuth source mapping
- AND the assignment does not create a password-based replacement account
Scenario: Retain service access while restricting a named developer
- WHEN shared named roles are adopted
- THEN existing Vault service administration, package-writing, and automation-writer grants remain configured
- AND the catalog developer receives feature-branch and pull-request access without a default-branch push or merge bypass
- AND an overlapping administrator grant for that developer fails validation
2.6.2 -
owned-dns Specification
Purpose
Define Forgejo DNS management through the owner’s tf_setup root,
including canonical declarations, scoped credentials, and offline source checks
before adopting live records.
Requirements
Requirement: Owner-local DNS configuration
The tf_setup root SHALL consume this owner’s canonical dnsconfig.json through
the shared DNS Terraform module, preserving declared record identities and views.
DNS resources SHALL default to disabled before adoption and SHALL remain enabled
by default after authorized adoption. Adoption SHALL bind existing provider records
to the owner’s state without adding, changing, replacing, or deleting DNS records.
Subsequent reconciliation of unchanged declarations SHALL preserve owned and
unrelated records.
Scenario: Inspect the preparatory configuration
- WHEN the checked-in root is evaluated with default inputs before adoption
- THEN it reads this owner’s declaration and disables managed DNS records
- AND the package contains the module and declaration inputs
Scenario: Inspect the adopted configuration
- WHEN the adopted root is evaluated with default inputs
- THEN it reads this owner’s declaration and enables managed DNS records
- AND the package contains the module and declaration inputs
Scenario: Adopt existing records
- WHEN the owner reviews the matched existing provider imports through
//infra/forgejo/tf_setup:dns.planand:dns.show, then applies that saved plan through:dns.apply - THEN the owner state binds each declared record to its existing provider identity
- AND the reviewed adoption plan proposes no record additions, changes, replacements, or deletions
Scenario: Reconcile unchanged declarations
- WHEN the adopted root plans unchanged declarations through
//infra/forgejo/tf_setup:dns.planand applies its reviewed saved plan through:dns.apply - THEN it makes no DNS resource changes
- AND owned records retain their declared values and views while unrelated records remain unchanged
Requirement: Scoped DNS execution and offline checks
The DNS wrapper SHALL select src_infra_dc1_forgejo1 through the repository AL
flow and keep secret values in injected variables. Dedicated DNS commands SHALL
select dns=1, retain the existing setup backend, and target module.dns without
starting unrelated service authentication. DNS apply SHALL consume only a
reviewed saved plan. Real DNS credentials and Vault policy grants SHALL be
prerequisites for operational Terraform calls. RouterOS DNS credentials SHALL be
isolated from unrelated RouterOS resources. The package SHALL expose a format
test that does not authenticate to Vault or contact DNS providers.
Scenario: Validate the Terraform source
- WHEN the package format test executes
- THEN it checks the packaged Terraform configuration without live credentials
- AND existing non-DNS authentication and backend paths remain unchanged
Scenario: Prepare an operational Terraform invocation
- WHEN the wrapper selects its Terraform stage labels
- THEN it selects DNS credential injection through the owner AppRole with
dns=1, the existing setup backend, and themodule.dnstarget - AND disabled DNS resources do not imply offline provider configuration
2.6.3 - Ansible
2.6.4 - Tf
This package configures Forgejo organizations, repositories, and access from the shared repository catalog. The catalog owns named administrators, developers, repository identities, and destination names. Its Terraform module supplies the consumer’s repository projection. First-party names remain stable across forges; external fork and mirror names retain their original upstream identity.
Before applying, provision the Vault OIDC authentication source with Ansible and set
TF_VAR_vault_oauth_source_id to its verified positive numeric ID. Obtain the
ID from forgejo admin auth list on the instance using the service’s config
and work path; confirm that the vault source is active and uses OpenID
Connect with the expected Vault issuer. Do not assume source IDs survive
instance recreation.
Terraform discovers users from the authoritative Vault
src_infra_dc1_forgejo1_users login group, then looks up their entities,
following the PVE Terraform pattern. Discovery includes direct members and
two levels of nested groups, covering the current administrator membership.
Deeper nesting fails validation rather than silently omitting accounts.
Each account uses its Vault entity UUID as the OIDC login name and its
canonical username/email metadata. No local password or user impersonation is
used. The Forgejo AppRole receives the existing group/entity lookup permissions,
as PVE does. Apply those Vault group memberships before running this package.
The accounts are protected from Terraform deletion. OIDC group claims retain ownership of administrator/restricted status after login. If a user already exists outside this state, verify its source and login-name mapping before importing it; never replace an existing account to resolve a name collision. Resource addresses remain keyed by Vault entity name, preserving existing managed users. The Forgejo service identity may already exist from the first OIDC login: verify and import it before applying its newly discovered resource.
Named organization administrator and developer assignments come from the catalog and must resolve to the discovered Vault login population. The Developer team can read repositories, write feature branches, and open pull requests. Its members receive no default-branch push or merge bypass.
Existing service administration remains sourced from
src_infra_dc1_forgejo1_admins and its direct child groups. Those grants are
retained for entities with a Vault AppRole alias, alongside catalog
administrators. The separate instance-wide OIDC administrator claim remains
owned by Vault. Validation rejects a catalog
developer who also receives administrator access through those Vault groups.
Package writers and the repository automation writer retain the grants from
src_infra_dc1_forgejo1_package_writers and
src_infra_dc1_forgejo1_src_writers. These dedicated groups avoid granting
service permissions to AppRole credential issuers. The existing singleton
collaborator still requires exactly one discovered writer. Access-group
members outside the login population also fail validation.
Repository adoption preserves remote IDs. The existing singleton repository address has an explicit move to its catalog key, while account and service access addresses remain stable. Import an existing untracked destination before applying; never recreate it to resolve a name collision. Review the full plan before execution and obtain separate approval for any deletion or replacement. The retained branch rules continue to own administrator and automation-writer exceptions.
bazel_agent bazel run //infra/forgejo/tf:tf.plan
bazel_agent bazel run //infra/forgejo/tf:tf.apply
2.6.5 - Tf setup
This package creates a Xen Orchestra VM in the src_infra_dc1_forgejo1
resource set. infra/forgejo/al.lua authenticates with Forgejo’s own Vault
AppRole and the packaged XO OIDC login plugin. The plugin supplies a temporary
XO token and revokes it on shutdown; no infrastructure administrator token
is loaded. The setup HTTP backend remains owned by the same Forgejo config.
Before running this package, bootstrap the AppRole’s XO OIDC user and apply
its resource-set membership and existing VM ACL through infra/xcp_ng/tf.
Subjects are matched by immutable Vault entity UUID under the configured
OIDC issuer, not by login name or AppRole group membership. See
XO authentication.
Defaults select the imported Fedora 44 template, local storage and wired
network by name from the Forgejo resource set. Override
TF_VAR_xoa_template_name, TF_VAR_xoa_storage_name, and
TF_VAR_xoa_network_name for another assignment. Native provider lookups run
as Forgejo’s own identity and reject ambiguous matches. No infrastructure
UUID defaults are required; resolved IDs are passed to the XO API.
The template must contain a single boot disk no larger than 20 GiB, Fedora,
and cloud-init. Bootstrap installs Xen guest tools. The pinned Fedora 44
image uses predictable interface naming; xoa_guest_interface defaults to
enX0 for its first Xen interface and can be overridden for another template.
The selected network must carry 192.168.10.0/24; gateway and DNS default to
192.168.10.1 (the wired router) and can be overridden with the Terraform variables.
The PVE-based infra/cloud_init:xen_linux target supplies the shared Ansible
user and CA configuration through the repository template rule. Terraform adds
the hostname and static network configuration from ../dnsconfig.json. After cloud-init completes, verify that /dev/xvda is the
boot disk, /dev/xvdb is the 40 GiB Forgejo disk, and /dev/xvdc is the 5 GiB
Traefik disk before running Ansible, which creates filesystems on the latter
two devices.
The old Proxmox VM was destroyed and its obsolete Terraform state binding was removed without issuing a destroy. This package now uses only XO. There is no cross-provider state move or data restoration in this package.
bazel_agent bazel run //infra/forgejo/tf_setup:tf_setup.plan
bazel_agent bazel run //infra/forgejo/tf_setup:tf_setup.apply
Use this package’s dns.plan, dns.show, and dns.apply targets for the
scoped DNS workflow. They select dns=1, retain the
existing setup backend and src_infra_dc1_forgejo1 AppRole, and target
module.dns without starting unrelated service authentication. Inspect the
saved plan through dns.show and pass only that reviewed file to dns.apply.
dns_enabled defaults to true after verified adoption. Keep it enabled to
retain existing records; disabling it would propose deletion. Follow the
cutover procedure
for prerequisites, reconciliation, and recovery. The owner adoption change
records the historical import and DNS verification evidence; scoped DNS checks
do not establish service or VM health.
2.7 - Forgejo runner
Deploy VMs
bazel run //infra/forgejo_runner/tf_setup # Create VMs
bazel run //infra/forgejo_runner/ansible # Configure VMs
2.7.1 -
Forgejo runner infrastructure specification
Purpose
Describe the Forgejo Actions runner VM and deployment scaffold owned by
infra/forgejo_runner. Its tf_setup and ansible packages are stages of
this owner. The runner role is commented out in the baseline playbook;
the checked-in configuration therefore does not establish a deployed or
registered Actions worker. No live runner state was observed.
Baseline revision: 550d7e79b1f5fdbc2b6017b75178471d6914082f.
Observed: 2026-09-08. Sources:
owner README,
BUILD, and the implementation
links below.
Requirements
Requirement: Dedicated runner VM allocation
Setup SHALL declare runner1 as Proxmox VM 1200 in the
src_infra_forgejo_runner pool, with eight cores, 16 GiB memory, a 20 GiB
boot disk, and a 300 GiB runner disk on ceph-ec storage. Its hostname and
address SHALL derive from the owner’s DNS declaration.
Source: VM definition.
Scenario: Inspect the runner capacity definition
- WHEN a maintainer evaluates the runner VM configuration
- THEN the source declares the dedicated runner pool, compute allocation, and separate boot and runner disks
- AND DNS source supplies the hostname and address
Requirement: Explicit host-only deployment baseline
The baseline deployment playbook SHALL apply the shared host role to the
forgejo_runner inventory group. The specification MUST identify the
commented-out Forgejo runner role as inactive and MUST NOT interpret the
available runner variables as evidence that the worker is installed or
registered.
Sources: deployment playbook and runner variables.
Scenario: Determine the effect of the current playbook
- WHEN the current playbook’s active roles are inspected
- THEN only the shared host role is enabled
- AND runner installation and registration remain outside the behavior established by this source baseline
Requirement: Packaged setup and deployment configuration
The owner SHALL expose Terraform setup and packaged Ansible entry points
through its al configuration and Vault injection dependencies. The runner
configuration SHALL reference https://git.alwaldend.com, /dev/sdb, and
an environment-supplied FORGEJO_RUNNER_TOKEN rather than a checked-in
registration token.
Sources: setup BUILD, Ansible BUILD, and runner variables.
Scenario: Resolve the registration credential source
- WHEN a maintainer inspects the runner configuration scaffold
- THEN its token value is an environment lookup and its instance URL is the canonical Forgejo service
- AND the token reference alone does not enable the inactive runner role
2.7.2 -
owned-dns Specification
Purpose
Define Forgejo Actions runner DNS management through the owner’s tf_setup root,
including canonical declarations, scoped execution, adoption of existing records,
and offline source checks.
Requirements
Requirement: Owner-local DNS configuration
The tf_setup root SHALL consume this owner’s canonical dnsconfig.json through
the shared DNS Terraform module, preserving declared record identities and views.
DNS resources SHALL default to disabled before adoption and SHALL remain enabled
by default after authorized adoption. Adoption SHALL bind existing provider records
to the owner’s state without adding, changing, replacing, or deleting DNS records.
Subsequent reconciliation of unchanged declarations SHALL preserve owned and
unrelated records.
Scenario: Inspect the preparatory configuration
- WHEN the checked-in root is evaluated with default inputs before adoption
- THEN it reads this owner’s declaration and disables managed DNS records
- AND the package contains the module and declaration inputs
Scenario: Inspect the adopted configuration
- WHEN the adopted root is evaluated with default inputs
- THEN it reads this owner’s declaration and enables managed DNS records
- AND the package contains the module and declaration inputs
Scenario: Adopt existing records
- WHEN the owner adopts matched existing provider records through
//infra/forgejo_runner/tf_setup:dns.plan,:dns.show, and:dns.apply - THEN the owner state binds each declared record to its existing provider identity
- AND the reviewed adoption plan proposes no record additions, changes, replacements, or deletions
Scenario: Reconcile unchanged declarations
- WHEN the adopted root plans and applies unchanged declarations through its
scoped
//infra/forgejo_runner/tf_setup:dnswrappers - THEN it makes no DNS resource changes
- AND owned records retain their declared values and views while unrelated records remain unchanged
Requirement: Scoped DNS execution and offline checks
The DNS wrapper SHALL select src_infra_forgejo_runner through the repository
AL flow and keep secret values in injected variables. Dedicated DNS plan, show,
and apply targets SHALL select dns=1 alone and target module.dns while reusing
the owning setup root and backend. DNS apply SHALL consume only a reviewed saved
plan. Ordinary setup targets SHALL retain their existing tf=setup flow.
Real DNS credentials and Vault policy grants SHALL be prerequisites for
operational Terraform calls. RouterOS DNS credentials SHALL be isolated from
unrelated RouterOS resources. The package SHALL expose a format test that does
not authenticate to Vault or contact DNS providers.
Scenario: Validate the Terraform source
- WHEN the package format test executes
- THEN it checks the packaged Terraform configuration without live credentials
- AND existing non-DNS authentication and backend paths remain unchanged
Scenario: Prepare an operational Terraform invocation
- WHEN a dedicated DNS target selects its execution label
- THEN it selects
dns=1and DNS credential injection through the owner AppRole - AND it retains the setup backend while limiting reconciliation to
module.dns - AND disabled DNS resources do not imply offline provider configuration
2.7.3 - Ansible
2.7.4 - Terraform setup
Use this package’s dns.plan, dns.show, and dns.apply targets for the
scoped DNS adoption workflow.
These targets select dns=1 and target module.dns with the existing
src_infra_forgejo_runner AppRole and setup backend. Plan declared imports,
inspect the saved plan with dns.show, and apply only the reviewed file with
dns.apply. Ordinary setup commands retain their tf=setup flow.
dns_enabled defaults to true after verified adoption. Keep it enabled to
retain existing records; disabling it would propose deletion. The
adoption record
contains the import, follow-up plan, inventory, and DNS verification evidence.
The shared cutover procedure
owns prerequisites and recovery. Scoped DNS checks do not establish VM or runner
service health.
2.8 - GitHub
This project manages the GitHub organization and repositories declared by the shared repository catalog, including existing forks, project landing sites, organization membership, and developer access.
Service Terraform adopts existing resources and preserves their identities. It also manages repository default-branch rules and existing Pages configuration. Site content is published through the owning project deployment targets; this infrastructure package does not publish it.
2.8.1 -
Infrastructure GitHub
Purpose
Describe Terraform ownership of the catalog-defined GitHub organization, repositories, member access, default-branch restrictions, and Pages settings. These requirements describe source guarantees; they do not assert that a plan has been applied or that published sites are healthy.
Sources: component documentation, Terraform workflow, shared catalog, packaged inputs, repository resources, organization access, branch rules, and provider configuration.
Requirements
Requirement: Consume the shared organization and repository catalog
The package SHALL consume organization identity, administrator and developer
lists, repository identity, default branches, repository settings, and Pages
configuration through infra/repos/tf. It SHALL NOT generate a second inventory
from the build-project registry. Its provider instance SHALL require exactly
one configured GitHub organization.
Scenario: Consume a catalog repository
- WHEN the package renders its repository resources
- THEN every catalog GitHub repository is managed from its catalog record
Requirement: Publish project landings from the apex site
Dedicated per-project landing repositories SHALL NOT be managed. The main site
publishes every project landing at /projects/<name>/, so the catalog carries
no landing_project key and no per-project Pages repository, custom domain,
github-pages environment, or landing default branch is declared.
Scenario: Publish a project landing
- WHEN a project’s landing page is published
- THEN it is served by the apex site at
/projects/<name>/from the apex Pages repository - AND no per-project repository, Pages configuration, or custom domain is managed
Requirement: Adopt existing resources without recreating them
The package SHALL provide import blocks for existing organization settings,
repositories, default branches, memberships, developer collaborators, and
the two existing src rulesets. Repositories with observed catalog IDs SHALL
retain those IDs. Managed resources SHALL reject Terraform destruction, and
any deletion or replacement SHALL require explicit user approval before apply.
The organization settings resource SHALL own only catalog-defined base repository access. Its mandatory billing argument SHALL be an import-only placeholder whose imported value is ignored; billing, profile, and other organization defaults SHALL remain outside this module’s ownership. Existing Dependabot alert settings SHALL be preserved.
Scenario: An existing repository cannot be imported
- WHEN import cannot resolve an observed catalog repository
- THEN the operation fails rather than creating a replacement repository
Requirement: Restrict developers to contribution branches
Catalog administrators SHALL be organization owners. Catalog developers SHALL
receive explicit write access on every GitHub catalog repository through
non-authoritative collaborator resources. Repository default branches SHALL
have active rulesets restricting creation, updates, deletion, and force
pushes, with bypass restricted to organization administrators. The update
restriction SHALL NOT permit fork syncing as a developer bypass. Ruleset
application SHALL follow the managed default-branch selection. The two
pre-existing src rulesets SHALL be imported unchanged, retaining their
rules and bypass actors alongside the new default-branch ruleset.
Scenario: A developer contributes a change
- WHEN a catalog developer writes to a non-protected contribution branch
- THEN repository write access permits the contribution and opening a pull request
- AND the developer cannot push or merge into the default branch
Scenario: Publish the main site
- WHEN the site publisher writes content to the apex repository’s
pagesbranch - THEN repository write access permits publication
- AND its
masterdefault branch remains protected from developer pushes and merges
Requirement: Keep repository provisioning separate from site and DNS publication
This package SHALL own repository resources and Pages settings. The documented
workflow SHALL use //projects/alwaldend.com:deploy for site content and
//infra/dns for DNS records.
Scenario: Review a site rollout
- WHEN an operator prepares an authorized site rollout
- THEN repository and Pages changes are reviewed in the Terraform workflow
- AND built content publication and DNS changes use their separately owned workflows
Requirement: Provide an explicit certificate reprovision procedure
GitHub issues the custom-domain certificate as part of its Pages build and offers no direct reissue action, so the package SHALL document a supported, separately reviewed way to omit the apex site’s Pages block and then restore it, forcing a new certificate. The procedure SHALL use two filtered applies and SHALL include an HTTPS verification step.
Scenario: Reprovision the apex site certificate
- WHEN an authorized apply removes the apex site’s Pages block
- THEN the reviewed plan removes only that configuration
- AND the documented procedure restores it with a later apply
- AND the operator verifies the certificate served for the custom domain
2.8.2 - GitHub Terraform
This package consumes the shared repository catalog through its provider-free Terraform module. The catalog supplies the GitHub owner, repositories, default branches, repository settings, organization administrators, and developers. This root supports one GitHub organization per provider instance and rejects multiple configured owners.
Existing repositories are imported, including forks. The apex site repository keeps its Pages configuration and custom domain. Published repository names and Pages domains come directly from the catalog; they are not regenerated from the current build-project registry.
Dedicated per-project landing repositories were retired: the main site now
publishes every project landing at /projects/<name>/, so the catalog carries
no landing_project key and this root manages no per-project Pages repository,
custom domain, github-pages environment, or landing default branch.
Adoption and access
The checked-in import blocks adopt the organization, existing repositories,
default branches, memberships, developer collaborators, and both existing
src rulesets. A repository with an observed catalog github.id must retain
that numeric identity. An import failure must be resolved before applying;
never remove an import merely to create an existing object again. Repositories,
memberships, access grants, environments, and rulesets have deletion guards.
Review the complete plan and obtain explicit authorization for any deletion
or replacement. Previously authorized retirement may proceed within its exact
reviewed scope.
Organization settings own only catalog-defined repository base permissions.
Billing, profile fields, and other organization defaults remain controlled by
GitHub and are explicitly ignored. The required empty billing_email argument
is an import-only placeholder: the existing billing address is retained from
state and must never be committed or exposed in plan output. Do not create
this organization-settings resource without its import block. Dependabot alert
settings for newly adopted repositories are similarly preserved.
Catalog administrators are organization owners. Developers receive explicit
write access on every catalog repository, while organization base permissions
remain at the catalog setting. The grants are non-authoritative, preserving
other collaborators. Each repository has an active default-branch ruleset
restricting creation, updates, deletion, and force pushes, with an organization
administrator bypass. Developers can push other branches and open pull
requests, but cannot directly push or merge into the default branch. Forks
also disable the upstream fetch-and-merge exception. Catalog repositories
permit merge commits only; squash and rebase merges are disabled, so an
accepted pull request records a merge commit whose parents include the
reviewed feature commit. Both pre-existing src rulesets retain their
separate release-branch protections and bypass actors; the default-branch
ruleset also applies alongside them. Repository rulesets are available for
these public repositories on
GitHub Free.
Publish the main site
The apex site repository receives its built Hugo site from
//projects/alwaldend.com:deploy in the root workspace. Terraform manages the
catalog-defined custom domain and Pages source. Keep all applies limited to
reviewed, authorized repository and Pages changes. DNS is managed by the
owning Terraform root; DNS documentation describes the
workflow. Validate the public custom domain after rollout.
GitHub issues the custom-domain certificate as part of its Pages build. If a
certificate must be reissued, remove the pages block from the apex catalog
record in a reviewed plan, apply it, then restore it in a second plan; GitHub
schedules a new certificate once the custom domain returns. Verify the pushed
revision, Pages build state, DNS, and the served certificate before closing the
recovery.
2.9 - GitLab
This project owns GitLab groups, memberships, repository imports, and forks through the Terraform module. Organization membership and repository definitions come from the shared repository catalog.
2.9.1 - GitLab Terraform
This module manages the GitLab groups, memberships, repository imports, and forks declared in the shared repository catalog. Its catalog module supplies names, source URLs, and repository settings. Provider versions and checksums are recorded in the shared provider declarations.
Catalog administrators receive the Owner role; catalog users receive the Developer role. Group defaults permit Maintainers and Owners to push and merge into default branches, with force pushes and developer initial pushes disabled. Developers can read repositories, create feature branches, and open merge requests. Existing higher direct or inherited grants must be reviewed separately because GitLab retains a user’s highest access level.
GitHub copies use one-time Git imports, preserving their source default branches. They have no ongoing synchronization. GitLab forks retain their upstream fork relationship and target upstream when opening merge requests. The catalog owns destination names and upstream identities.
AL configuration authenticates with the
src_infra_gitlab AppRole,
injects the gitlab_token field as GITLAB_TOKEN, and supplies the existing
Vault HTTP state backend.
The configuration owns the Vault paths and plugin labels.
The provider uses GitLab.com by default. For another instance, set
GITLAB_BASE_URL to its API endpoint with a trailing slash, such as
https://gitlab.example.com/api/v4/; see the
provider configuration.
The BUILD file exposes the standard tf.* commands and
tf_tests.fmt_test; a plan uses live Vault and GitLab access.
Import and apply
The import blocks adopt existing catalog groups, projects, and their direct memberships.
Membership discovery reads the catalog’s existing group IDs independently of
the managed group resource, allowing a newly added member to be created.
GitLab.com top-level groups must exist before Terraform can manage them.
Group, membership, and project resources have prevent_destroy enabled.
For an existing destination project, record its observed numeric ID as
gitlab.id in its catalog file. The project import block adopts that identity,
and a postcondition rejects an unexpected ID. Do not create a replacement for
an existing project or fork. Review the full plan for deletions and replacements
before every apply; either requires explicit authorization for that scope.
Adopt default-branch protections in two phases:
- A new project starts without
gitlab.id. Apply the reviewed full plan for groups, memberships, and projects. Wait for each repository import or fork to finish, then verify its default branch and effective protection against the catalog and group defaults. - Record the observed project ID in the catalog after verifying its protection.
The existing protection declarations select only projects with recorded IDs
and import
<project-id>:<default-branch>. This keeps new project creation independent of import IDs that are unknown until creation finishes. Review and apply the full plan that imports or updates those protections. Existing protections must never enter the provider’s Create operation: it can unprotect and recreate an existing default-branch rule.
Keep the original protection in place if it cannot be imported or its access
levels need a replacement. The pinned provider supports in-place
allowed_to_push and allowed_to_merge updates on GitLab.com; its scalar
push_access_level and merge_access_level fields can require replacement.
See the provider’s protection behavior.
Confirm that no overlapping project or group rule grants developers access to a default branch. A restrictive rule does not override a more permissive matching rule; see GitLab protected branches.
2.10 - harbor
Links
- Site: https://goharbor.io/
- Releases: https://github.com/goharbor/harbor/releases
CE Login
- Go to User Profile, copy CLI secret
- Run:
podman login harbor.alwaldend.com
Update secrets
- Generate approle secret id:
SECRET_ID=$(bazel run //infra/harbor/cl:vault.secret_id | jq -r .data.secret_id) echo "Secret id: ${SECRET_ID}" - Patch secret-id in ./cl/cert-manager/issuer-approle.yaml
- Encrypt:
bazel run //infra/flux/cl:sops.encrypt infra/harbor/cl/cert-manager/issuer-approle.yaml
2.10.1 -
Harbor infrastructure specification
Purpose
Describe the Harbor registry infrastructure owned by infra/harbor, spanning
Proxmox setup, K3s host configuration, Flux-managed chart declarations, and
Harbor service Terraform. The tf_setup, ansible, cl, and tf packages
are implementation stages of this owner. This is a checked-in source
baseline, without an observation of live registry availability or deployment
success.
Baseline revision: 550d7e79b1f5fdbc2b6017b75178471d6914082f.
Observed: 2026-09-08. Sources: owner README,
BUILD, and the implementation links below.
Requirements
Requirement: Dedicated K3s registry host
Setup SHALL declare a Proxmox VM in the src_infra_harbor pool with two
cores, 4096 MiB memory, and 20 GiB boot, 20 GiB K3s data, and 40 GiB K3s
storage disks. Ansible SHALL apply the shared host and K3s roles with K3s
secrets encryption enabled. Its firewall variables SHALL scope API port
6443 access to the declared Flux host address.
Sources: VM definition, deployment playbook, K3s configuration, and host variables.
Scenario: Inspect management API access
- WHEN the Harbor host configuration is evaluated
- THEN the API-port firewall entry identifies the Flux source address
- AND the K3s configuration enables secrets encryption and disables bundled Traefik
Requirement: Remote Flux chart reconciliation
The Harbor Flux manifests SHALL declare a remote-cluster Kustomization and
HelmRelease using src-infra-harbor-cl-kubeconfig. The HelmRelease SHALL
pin its chart version, enable Helm tests and drift detection, set
https://harbor.alwaldend.com as the external URL, and use the local-path
storage class for its declared persistent components.
Source: Harbor Flux manifests.
Scenario: Inspect the Harbor release declaration
- WHEN a maintainer evaluates the Harbor HelmRelease
- THEN the source selects a specific chart version and the remote Harbor cluster configuration
- AND tests, drift detection, external URL, and persistent storage choices are explicit
Requirement: Vault-backed registry identity configuration
Harbor service Terraform SHALL configure Vault OIDC authentication using
client credentials from the Vault provider, the groups claim, and the
src_infra_harbor_admins administrator group. It SHALL enable automatic
onboarding and use the username claim for users.
Source: authentication configuration.
The baseline sets oidc_verify_cert = false with a CA-issues comment; this
specification does not claim that OIDC server certificate verification is
enabled.
Scenario: Resolve OIDC identity settings
- WHEN the service Terraform authentication resource is inspected
- THEN it references Vault-provided client credentials and the configured user and group claims
- AND its certificate-verification setting remains visible as a baseline limitation
Requirement: Registry projects and guest access
Service Terraform SHALL declare an alwaldend project with vulnerability
scanning and automatic SBOM generation, plus a dockerhub proxy-cache
project linked to the Docker Hub registry. Both projects SHALL grant the
configured src_infra_harbor_users OIDC group the guest role.
Sources: first-party project and Docker Hub proxy.
Scenario: Inspect registry consumer permissions
- WHEN the managed registry projects are evaluated
- THEN
alwaldendenables scanning and SBOM generation, whiledockerhubreferences the Docker Hub proxy registry - AND both group membership resources specify guest access
2.10.2 -
owned-dns Specification
Purpose
Define Harbor DNS management through the owner’s tf_setup root,
including canonical declarations, scoped credentials, and offline source checks
before adopting live records.
Requirements
Requirement: Owner-local DNS configuration
The tf_setup root SHALL consume this owner’s canonical dnsconfig.json through
the shared DNS Terraform module, preserving declared record identities and views.
DNS resources SHALL default to disabled before adoption and SHALL default to
enabled in the reviewed adoption revision and after adoption. Adoption SHALL
import the exact existing provider records and require a scoped no-change import plan before saved-plan
apply. Subsequent reconciliation with unchanged root inputs SHALL preserve
adopted records, unrelated DNS records, and non-DNS resources in the root.
Scenario: Inspect the preparatory configuration
- WHEN the checked-in root is evaluated with default inputs before adoption
- THEN it reads this owner’s declaration and disables managed DNS records
- AND the package contains the module and declaration inputs
Scenario: Inspect the adopted default
- WHEN the reviewed adoption revision or an adopted root is evaluated with default inputs
- THEN it reads this owner’s declaration and enables managed DNS records
- AND enabled ownership remains the default after import
Scenario: Adopt existing records
- WHEN this owner applies a reviewed saved import plan through
//infra/harbor/tf_setup:dns.apply - THEN each existing provider record is imported at its exact owner-local address
- AND a reviewed adoption plan proposes no record additions, changes, replacements, or deletions before apply
Scenario: Reconcile unchanged declarations
- WHEN the adopted root reconciles unchanged canonical declarations and root inputs
- THEN the plan proposes no changes to the adopted DNS records
- AND unrelated DNS records and non-DNS resources in the root remain unchanged
Requirement: Scoped DNS execution and offline checks
The DNS wrappers SHALL select src_infra_harbor through the repository AL flow and
keep secret values in injected variables. The dns.plan, dns.show, and
dns.apply targets SHALL select dns=1 and retain the owner’s setup backend;
plans SHALL target module.dns and apply SHALL require a reviewed saved plan.
Ordinary setup wrappers SHALL retain their service authentication behavior.
Real DNS credentials and Vault policy grants SHALL be prerequisites for operational
Terraform calls. RouterOS DNS credentials SHALL remain isolated from unrelated
RouterOS resources. The package SHALL expose a format test without live credentials.
DNS-targeted validation SHALL NOT establish unrelated VM or service health.
Scenario: Validate the Terraform source
- WHEN the package format test executes
- THEN it checks the packaged Terraform configuration without live credentials
- AND existing non-DNS authentication and backend paths remain unchanged
Scenario: Prepare an operational Terraform invocation
- WHEN an authorized operator selects the owner’s DNS wrapper
- THEN it selects DNS credential injection through the owner AppRole and setup backend
- AND its scoped plan and saved-plan apply cover DNS and its dependencies
- AND disabled DNS resources do not imply offline provider configuration
2.10.3 - Ansible
2.10.4 - cl
2.10.5 - Tf
2.10.6 - Tf setup
This root owns the Harbor DNS declaration. DNS ownership defaults to enabled after verified adoption; keep it enabled to retain the managed records.
Use //infra/harbor/tf_setup:dns.plan, :dns.show, and :dns.apply for
scoped DNS reconciliation.
These targets retain the setup backend and src_infra_harbor AppRole, select
dns=1, and target module.dns. Apply requires a reviewed saved plan.
Reconciliation of unchanged declarations must produce no DNS changes.
The ordinary setup targets retain their service authentication behavior. DNS checks do not establish PVE VM or service health; current aggregate source validation remains part of repository delivery.
2.11 - ingress
Run ansible
bazel run //infra/ingress/ansible
Services in traefik_services must use a backend target that resolves from
the ingress hosts without resolving back to ingress. Define a dedicated
site-local address, conventionally prefixed with dc1., in the owning
service’s DNS configuration and use that address as the target.
Apply terraform
bazel run //infra/ingress/tf
Update signed image url
- Create a signed url: https://yandex.cloud/ru/docs/storage/operations/objects/link-for-download
- Update the secret:
alwaldend.com/vault1/approles/src_infra_ingress/image
Recreate VMs
bazel run infra/ingress/tf -- -replace 'yandex_compute_disk.vpc["*"]'
Regenerate wireguard keys
- Regenerate private and public keys:
wg genkey | tee host1.privatekey.txt | wg pubkey >host1.publickey.txt wg genkey | tee host2.privatekey.txt | wg pubkey >host2.publickey.txt wg genkey | tee router.privatekey.txt | wg pubkey >router.publickey.txt cat - >data.json <<EOF { "wg_public_keys": { "host1": "$(cat host1.publickey.txt)", "host2": "$(cat host2.publickey.txt)", "router": "$(cat router.publickey.txt)" }, "wg_private_keys": { "host1": "$(cat host1.privatekey.txt)", "host2": "$(cat host2.privatekey.txt)", "router": "$(cat router.privatekey.txt)" }, "wg_preshared_keys": { "host1": "$(openssl rand 32 | base64)", "host2": "$(openssl rand 32 | base64)" } } EOF bazel run infra/ingress:vault.kv_put -- -format json alwaldend.com/vault1/approles/src_infra_ingress/wireguard "@${PWD}/data.json" rm data.json *.privatekey.txt *.publickey.txt
2.11.1 -
Infrastructure ingress
Purpose
Describe Yandex Cloud ingress provisioning, the RouterOS WireGuard connection, and the Ansible-managed Traefik configuration. The baseline covers checked-in desired state, not a live routing or availability observation.
Baseline source revision: 550d7e79b1f5fdbc2b6017b75178471d6914082f.
Observation date: 2026-09-08. Sources are linked in full; no excerpts are used.
Sources: component contract, VM resources, WireGuard resources, deployment playbook, Traefik entry points, and Traefik routes.
Requirements
Requirement: Provision ingress hosts from the declared host map
Terraform SHALL create addresses, encrypted boot disks, and instances for the
active local.vpc entries, using the shared cloud-init source. The baseline
active map SHALL contain host1 in ru-central1-d; the commented host2 entry
SHALL NOT be treated as an enabled resource declaration.
Scenario: Evaluate the baseline host configuration
- WHEN the checked-in ingress Terraform configuration is evaluated
- THEN instance resources are declared for
host1 - AND its boot disk references the declared KMS symmetric key
- AND instance metadata includes the shared cloud-init content
Requirement: Connect declared hosts through WireGuard
The RouterOS configuration SHALL declare the ingress-vpc interface and a peer
for each active ingress host. Peer endpoints SHALL use the corresponding cloud
address, and allowed addresses SHALL come from the Ansible inventory’s wg_ip.
Scenario: Configure an ingress peer
- WHEN an ingress host is present in the active Terraform host map
- THEN its WireGuard peer uses the host’s declared public and preshared key variables and inventory address
- AND the interface belongs to the configured LAN, forwarding, and ICMP lists
Requirement: Route to backend addresses that do not return to ingress
Each traefik_services backend target MUST resolve from the ingress hosts
without resolving back to ingress. The service owner SHALL declare the dedicated
site-local address. Generated HTTPS backend transports SHALL use the service
hostname as TLS server name.
Scenario: Add a service behind ingress
- WHEN a service is added to
traefik_services - THEN its host route forwards to
https://followed by its backend target - AND that target is a dedicated site-local address defined by the service owner
- AND backend TLS uses the service’s configured hostname
Requirement: Deploy Traefik with HTTPS and client-certificate authentication
The ingress playbook SHALL apply the host, WireGuard, and Traefik roles. The
Traefik templates SHALL redirect the web entry point to HTTPS and configure
default TLS client authentication as RequireAndVerifyClientCert using the
configured client CA file.
Scenario: Render the ingress TLS configuration
- WHEN the Ansible role renders the checked-in Traefik templates
- THEN port 80 redirects to the secure entry point
- AND the default TLS options require a certificate verified against the configured client CA
2.11.2 -
owned-dns Specification
Purpose
Define retained ingress DNS ownership through the owner’s tf root,
including canonical declarations, scoped execution, and offline source checks.
Requirements
Requirement: Owner-local DNS configuration
The tf root SHALL consume this owner’s canonical dnsconfig.json through
the shared DNS Terraform module, preserving declared record identities and views.
DNS resources SHALL default to disabled until the authorized adoption revision
and SHALL retain enabled ownership after existing records are imported into the
owner’s state. Reconciliation against unchanged declarations and adopted state
SHALL propose no record additions, changes, replacements, or deletions.
Scenario: Inspect the preparatory configuration
- WHEN the checked-in root is evaluated with default inputs before its authorized adoption revision
- THEN it reads this owner’s declaration and disables managed DNS records
- AND the package contains the module and declaration inputs
Scenario: Adopt existing DNS records
- WHEN authorized adoption records the shared writer audit and control coverage and enables the owner’s record management
- THEN the owning root imports existing records by exact provider ID into its state while preserving their declared identities and views
Scenario: Inspect adopted source defaults
- WHEN the adopted root uses its checked-in source defaults
- THEN DNS ownership remains enabled and the package retains the module and canonical declaration inputs
Scenario: Reconcile existing DNS records
- WHEN the owning root plans against its adopted state and unchanged declarations
- THEN it proposes no record additions, changes, replacements, or deletions
Requirement: Scoped DNS execution and offline checks
The DNS wrappers SHALL select src_infra_ingress through the repository AL flow
and keep secret values in injected variables. dns.plan, dns.show, and
dns.apply SHALL retain the owning root and backend, select dns=1, and scope
planning to module.dns. Apply SHALL require the reviewed saved plan. This
workflow SHALL preserve ordinary service authentication and SHALL NOT establish
overall service health. Required DNS credentials and Vault grants SHALL remain
operational prerequisites, and RouterOS DNS credentials SHALL remain isolated
from unrelated RouterOS resources. The package SHALL expose a format test
without Vault authentication or DNS provider access.
Scenario: Validate the Terraform source
- WHEN the package format test executes
- THEN it checks the packaged Terraform configuration without live credentials
- AND existing non-DNS authentication and backend paths remain unchanged
Scenario: Prepare an operational Terraform invocation
- WHEN the operator selects the owning DNS wrappers
- THEN they select DNS credential injection through the owner AppRole with
dns=1 - AND their scoped plan validates DNS and its dependencies
- AND disabled DNS resources do not imply offline provider configuration
2.11.3 - Ansible
2.11.4 - Tf
Use this package’s dns.plan, dns.show, and dns.apply targets for the
scoped DNS adoption workflow.
DNS ownership is enabled by default after the verified 2026-09-13 adoption.
The adoption evidence
records four imports, a no-change follow-up plan, and preserved provider inventories.
The DNS wrappers select dns=1 and module.dns within this root and backend;
their validation covers DNS and its dependencies. Apply requires a reviewed
saved plan, and ordinary ingress service authentication remains separate.
2.12 - Mikrotik
The Terraform package prepares owner-local DNS management. Router exports remain documentation inputs and are not applied by that package.
Deployment
- Open Winbox
- Open new terminal
- Run
/export - Copy output
Links
- Website: https://mikrotik.com
- Docs: https://help.mikrotik.com/docs/spaces/ROS/pages/328155/Configuration+Management
Exports
Router1
/interface bridge
add admin-mac=78:9A:18:38:6C:CA auto-mac=no comment="bridge1 (wired)" name=bridge1
add comment="bridge2 (wireless)" name=bridge2
/interface wifi
set [ find default-name=wifi1 ] channel.frequency=5000-5400 .skip-dfs-channels=10min-cac comment="wifi1 (5GHz)" configuration.country=Russia .mode=ap .ssid=divinity-5GHz datapath.client-isolation=yes disabled=no security.authentication-types=wpa2-psk,wpa3-psk .connect-priority=0 .ft=yes .ft-over-ds=yes
set [ find default-name=wifi2 ] channel.skip-dfs-channels=10min-cac comment="wifi2 (2GHz)" configuration.country=Russia .mode=ap .ssid=divinity-2GHz datapath.client-isolation=yes disabled=no security.authentication-types=wpa2-psk,wpa3-psk .connect-priority=0 .ft=yes .ft-over-ds=yes
/interface ethernet
set [ find default-name=ether1 ] comment=ether1 l2mtu=1500 mac-address=F4:28:53:7F:A4:59
set [ find default-name=ether2 ] comment=ether2
set [ find default-name=ether3 ] comment=ether3
set [ find default-name=ether4 ] comment=ether4
set [ find default-name=ether5 ] comment=ether5
/interface wireguard
add comment="tf[users/simeonwarren/hermes/tf_setup]" disabled=yes listen-port=13232 mtu=1420 name=hermes-vpc
add comment="tf[infra/ingress/tf]" listen-port=13231 mtu=1420 name=ingress-vpc
/interface ethernet switch
set switch1 cpu-flow-control=yes
/interface list
add comment=defconf name=WAN
add comment=defconf name=LAN
add name=accept-forward-WAN
add name=accept-input-DNS
add name=accept-input-DHCP-server
add name=accept-input-ICMP
add name=accept-input-winbox
add name=accept-input-web-ui
add name=accept-input-mikrotik-neighbor-discovery
add name=accept-forward-LAN
add name=accept-output-LAN
add name=accept-input-NTP
add name=accept-input-API
/ip pool
add comment=bridge1 name=bridge1 ranges=192.168.1.10-192.168.1.254
add comment=bridge2 name=bridge2 ranges=192.168.2.10-192.168.2.254
/ip dhcp-server
add address-pool=bridge1 comment=bridge1 interface=bridge1 lease-time=10m name=bridge1
add address-pool=bridge2 interface=bridge2 name=bridge2
/ipv6 pool
add name=dc01 prefix=fd2e:546d:5738::/48 prefix-length=64
/user group
add comment=src_infra_dns name=src_infra_dns policy=read,write,api,rest-api,!local,!telnet,!ssh,!ftp,!reboot,!policy,!test,!winbox,!password,!web,!sniff,!sensitive,!romon
add comment=src_infra_ingress name=src_infra_ingress policy=read,write,api,rest-api,!local,!telnet,!ssh,!ftp,!reboot,!policy,!test,!winbox,!password,!web,!sniff,!sensitive,!romon
add comment=users_simeonwarren name=users_simeonwarren policy=read,write,api,rest-api,!local,!telnet,!ssh,!ftp,!reboot,!policy,!test,!winbox,!password,!web,!sniff,!sensitive,!romon
/interface bridge port
add bridge=bridge1 comment=bridge1-ether2 interface=ether2
add bridge=bridge1 comment=bridge1-ether3 interface=ether3
add bridge=bridge1 comment=bridge1-ether4 interface=ether4
add bridge=bridge1 comment=bridge1-ether5 interface=ether5
add bridge=bridge2 comment=bridge2-wifi1 interface=wifi1
add bridge=bridge2 comment=bridge2-wifi2 interface=wifi2
/ip neighbor discovery-settings
set discover-interface-list=LAN
/interface detect-internet
set detect-interface-list=WAN
/interface list member
add interface=bridge1 list=LAN
add interface=ether1 list=WAN
add interface=bridge2 list=LAN
add interface=bridge2 list=accept-forward-WAN
add interface=bridge1 list=accept-forward-WAN
add interface=bridge1 list=accept-input-DNS
add interface=bridge2 list=accept-input-DNS
add interface=bridge1 list=accept-input-DHCP-server
add interface=bridge2 list=accept-input-DHCP-server
add interface=bridge1 list=accept-input-ICMP
add interface=bridge2 list=accept-input-ICMP
add interface=bridge1 list=accept-input-winbox
add interface=bridge1 list=accept-input-web-ui
add interface=bridge1 list=accept-input-mikrotik-neighbor-discovery
add interface=bridge1 list=accept-forward-LAN
add interface=bridge1 list=accept-output-LAN
add interface=bridge1 list=accept-input-NTP
add interface=bridge1 list=accept-input-API
add comment="tf[infra/ingress/tf]" interface=ingress-vpc list=accept-input-ICMP
add comment="tf[infra/ingress/tf]" interface=ingress-vpc list=LAN
add comment="tf[infra/ingress/tf]" interface=ingress-vpc list=accept-forward-LAN
add comment="tf[users/simeonwarren/hermes/tf_setup]" interface=hermes-vpc list=accept-forward-LAN
add comment="tf[users/simeonwarren/hermes/tf_setup]" interface=hermes-vpc list=accept-input-ICMP
add comment="tf[users/simeonwarren/hermes/tf_setup]" interface=hermes-vpc list=LAN
/interface ovpn-server server
add mac-address=FE:B3:B4:C4:A4:48 name=ovpn-server1
/interface wireguard peers
add allowed-address=10.10.0.2/24 comment=host2 endpoint-address=103.76.53.6 endpoint-port=51820 interface=ingress-vpc name=ingress-vpc-host2 persistent-keepalive=5s public-key="Z2JamOjZYOGaf4tPZzchyHjLw/XlOtUtQObyROEQ9DM="
add allowed-address=10.10.0.1/24 comment=host1 endpoint-address=158.160.196.128 endpoint-port=51820 interface=ingress-vpc name=ingress-vpc-host1 persistent-keepalive=5s public-key="xmyl+frvngmzRB9z5yEURxQj4vTw47tKQV7EZrTAREw="
add allowed-address=10.20.0.1/24 comment=host1 endpoint-address=158.160.220.223 endpoint-port=51820 interface=hermes-vpc name=hermes-vpc-host1 persistent-keepalive=5s public-key="oA4ZpsmrclIOIWh3ECsb4ZFKH1hQMDtuW3xNXat3IyQ="
/ip settings
set send-redirects=no
/ip address
add address=192.168.1.1/24 comment="bridge1 (LAN)" interface=bridge1 network=192.168.1.0
add address=192.168.2.1/24 comment="bridge2 (Wireless)" interface=bridge2 network=192.168.2.0
add address=192.168.10.1/24 comment=host1.pve1.dc1.alwaldend.com interface=bridge1 network=192.168.10.0
add address=10.10.0.0/24 comment="tf[infra/ingress/tf]" interface=ingress-vpc network=10.10.0.0
add address=10.20.0.0/24 comment="tf[users/simeonwarren/hermes/tf_setup]" interface=hermes-vpc network=10.20.0.0
/ip dhcp-client
add comment=defconf interface=ether1 name=ether1 use-peer-dns=no
/ip dhcp-server lease
add address=192.168.1.250 client-id=1:2c:cf:67:67:b5:13 mac-address=2C:CF:67:67:B5:13 server=bridge1
add address=192.168.1.218 client-id=1:e0:be:3:2b:9a:1a mac-address=E0:BE:03:2B:9A:1A server=bridge1
add address=192.168.1.216 client-id=ff:60:8:6d:aa:0:1:0:1:31:93:31:1a:34:5a:60:8:6d:aa mac-address=34:5A:60:08:6D:AA server=bridge1
/ip dhcp-server network
add address=192.168.1.0/24 comment=defconf dns-server=192.168.1.1 gateway=192.168.1.1
add address=192.168.2.0/24 dns-server=192.168.2.1 gateway=192.168.2.1
/ip dns
set allow-remote-requests=yes servers=1.1.1.2,1.0.0.2 use-doh-server=https://odoh.cloudflare-dns.com/dns-query verify-doh-cert=yes
/ip dns static
add address=185.199.108.153 name=alwaldend.com ttl=5m type=A
add address=185.199.109.153 name=alwaldend.com ttl=5m type=A
add address=185.199.110.153 name=alwaldend.com ttl=5m type=A
add address=185.199.111.153 name=alwaldend.com ttl=5m type=A
add address=2606:50c0:8000::153 name=alwaldend.com ttl=5m type=AAAA
add address=2606:50c0:8001::153 name=alwaldend.com ttl=5m type=AAAA
add address=2606:50c0:8002::153 name=alwaldend.com ttl=5m type=AAAA
add address=2606:50c0:8003::153 name=alwaldend.com ttl=5m type=AAAA
add mx-exchange=mail.protonmail.ch mx-preference=10 name=alwaldend.com ttl=5m type=MX
add mx-exchange=mailsec.protonmail.ch mx-preference=20 name=alwaldend.com ttl=5m type=MX
add name=alwaldend.com text="_globalsign-domain-verification=0QBJgVV_uwcFLTi1Rot3bb1LyJ5uW1WD0ygvIS4OM5" ttl=5m type=TXT
add name=alwaldend.com text="protonmail-verification=bdcd133d3f472fa17f66328950d02fbeae1bef75" ttl=5m type=TXT
add name=alwaldend.com text="v=spf1 include:_spf.protonmail.ch ~all" ttl=5m type=TXT
add name=_dmarc.alwaldend.com text="v=DMARC1; p=quarantine; adkim=s" ttl=5m type=TXT
add cname=protonmail.domainkey.djgwfzcu5fgjtpoijqqomgifmqj6zeiuwdd4mzim4hrxab3zsgwkq.domains.proton.ch name=protonmail._domainkey.alwaldend.com ttl=5m type=CNAME
add cname=protonmail2.domainkey.djgwfzcu5fgjtpoijqqomgifmqj6zeiuwdd4mzim4hrxab3zsgwkq.domains.proton.ch name=protonmail2._domainkey.alwaldend.com ttl=5m type=CNAME
add cname=protonmail3.domainkey.djgwfzcu5fgjtpoijqqomgifmqj6zeiuwdd4mzim4hrxab3zsgwkq.domains.proton.ch name=protonmail3._domainkey.alwaldend.com ttl=5m type=CNAME
add address=192.168.1.222 name=bm1.dc1.alwaldend.com ttl=5m type=A
add address=192.168.1.216 name=bm2.dc1.alwaldend.com ttl=5m type=A
add address=fd2e:546d:5738:0:365a:60ff:fe08:6daa name=bm2.dc1.alwaldend.com ttl=10m type=AAAA
add address=192.168.1.218 name=bm3.dc1.alwaldend.com ttl=5m type=A
add address=fd2e:546d:5738:0:e2be:3ff:fe2b:9a1a name=bm3.dc1.alwaldend.com ttl=10m type=AAAA
add cname=bm2.dc1.alwaldend.com name=host1.pve1.dc1.alwaldend.com ttl=10m type=CNAME
add address=192.168.10.10 name=cloudinit-test.vm.pve1.dc1.alwaldend.com ttl=5m type=A
add address=192.168.1.1 name=router1.dc1.alwaldend.com ttl=5m type=A
add address=fd2e:546d:5738::1 name=router1.dc1.alwaldend.com ttl=10m type=AAAA
add address=192.168.1.254 name=switch1.dc1.alwaldend.com ttl=5m type=A
add address=192.168.1.218 name=vault.dc1.alwaldend.com ttl=5m type=A
add mx-exchange=mx1.simplelogin.co mx-preference=10 name=simplelogin.alwaldend.com ttl=3h type=MX
add mx-exchange=mx2.simplelogin.co mx-preference=20 name=simplelogin.alwaldend.com ttl=3h type=MX
add name=simplelogin.alwaldend.com text="sl-verification=bxfzzfjiggzsxyzxhhmkmjqkaskjgy" ttl=3h type=TXT
add name=simplelogin.alwaldend.com text="v=spf1 include:simplelogin.co ~all" ttl=3h type=TXT
add name=_dmarc.simplelogin.alwaldend.com text="v=DMARC1; p=quarantine; pct=100; adkim=s; aspf=s" ttl=3h type=TXT
add cname=dkim._domainkey.simplelogin.co name=dkim._domainkey.simplelogin.alwaldend.com ttl=3h type=CNAME
add cname=dkim02._domainkey.simplelogin.co name=dkim02._domainkey.simplelogin.alwaldend.com ttl=3h type=CNAME
add cname=dkim03._domainkey.simplelogin.co name=dkim03._domainkey.simplelogin.alwaldend.com ttl=3h type=CNAME
add cname=alwaldend.com name=www.alwaldend.com ttl=5m type=CNAME
add mx-exchange=mx.yandex.net mx-preference=10 name=yandex.alwaldend.com ttl=6h type=MX
add name=yandex.alwaldend.com text="v=spf1 redirect=_spf.yandex.net" ttl=5m type=TXT
add name=yandex.alwaldend.com text="yandex-verification: b83672f59b3dbe16" ttl=5m type=TXT
add name=mail._domainkey.yandex.alwaldend.com text="v=DKIM1; k=rsa; t=s; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCcYzFVgkeDOhaIIkWM8gNQjxVsv0/aXfU+ax5urB5y6hA6lSjRnjRo6tm0bXbkOJf41GmiwMNgdXpwRtzgzAlX1i2aJbtEr4b9jzibEGLQ7Cvqs44bOYES9f/K3ueQpnvdTOJmFqlRReFL7ZrUyDFCoQ7f4+7h4i8s01cCcRrt5wIDAQAB" ttl=5m type=TXT
add address=192.168.1.218 name=host1.vault.dc1.alwaldend.com ttl=5m type=A
add address=192.168.10.60 name=flux.alwaldend.com ttl=5m type=A
add address=192.168.10.60 name=host1.flux.alwaldend.com ttl=5m type=A
add cname=flux.alwaldend.com name=openid.flux.alwaldend.com ttl=10m type=CNAME
add cname=flux.alwaldend.com name=operator.flux.alwaldend.com ttl=10m type=CNAME
add address=192.168.10.40 name=forgejo.alwaldend.com ttl=5m type=A
add address=192.168.10.40 name=host1.forgejo.alwaldend.com ttl=5m type=A
add address=192.168.10.50 name=harbor.alwaldend.com ttl=5m type=A
add address=192.168.10.50 name=host1.harbor.alwaldend.com ttl=5m type=A
add address=192.168.1.216 name=pve.alwaldend.com ttl=5m type=A
add address=192.168.10.80 name=threexui.alwaldend.com ttl=5m type=A
add address=192.168.10.80 name=host1.threexui.alwaldend.com ttl=5m type=A
add address=45.142.141.133 name=njalla1.nodes.threexui.alwaldend.com ttl=5m type=A
add address=2a0a:3840:8078:141:0:2d8e:8d85:1337 name=njalla1.nodes.threexui.alwaldend.com ttl=10m type=AAAA
add address=192.168.1.218 name=vault.alwaldend.com ttl=5m type=A
add address=103.76.53.6 name=ingress.alwaldend.com ttl=5m type=A
add address=158.160.196.128 name=ingress.alwaldend.com ttl=5m type=A
add address=158.160.196.128 name=host1.ingress.alwaldend.com ttl=5m type=A
add address=103.76.53.6 name=host2.ingress.alwaldend.com ttl=5m type=A
add name=yc.threexui.alwaldend.com ns=ns1.yandexcloud.net ttl=5m type=NS
add name=yc.threexui.alwaldend.com ns=ns2.yandexcloud.net ttl=5m type=NS
add cname=host1.nodes.yc.threexui.alwaldend.com name=yc1.nodes.threexui.alwaldend.com ttl=10m type=CNAME
add address=192.168.10.100 name=runner1.forgejo-runner.alwaldend.com ttl=5m type=A
add cname=host1.yc.hermes.simeonwarren.users.alwaldend.com name=hermes.simeonwarren.users.alwaldend.com ttl=10m type=CNAME
add cname=host1.yc.hermes.simeonwarren.users.alwaldend.com name=host1.hermes.simeonwarren.users.alwaldend.com ttl=10m type=CNAME
add name=yc.hermes.simeonwarren.users.alwaldend.com ns=ns1.yandexcloud.net ttl=5m type=NS
add name=yc.hermes.simeonwarren.users.alwaldend.com ns=ns2.yandexcloud.net ttl=5m type=NS
/ip firewall filter
add action=accept chain=input comment="defconf: accept established,related,untracked" connection-state=established,related,untracked
add action=drop chain=input comment="defconf: drop invalid" connection-state=invalid log-prefix=drop-invalid
add action=accept chain=input comment="defconf: accept ICMP" in-interface-list=accept-input-ICMP protocol=icmp
add action=accept chain=input comment="defconf: accept to local loopback (for CAPsMAN)" dst-address=127.0.0.1
add action=drop chain=input comment="defconf: drop all not coming from LAN" in-interface-list=!LAN log-prefix=drop-not-coming-from-lan
add action=accept chain=forward comment="defconf: accept in ipsec policy" ipsec-policy=in,ipsec
add action=accept chain=forward comment="defconf: accept out ipsec policy" ipsec-policy=out,ipsec
add action=fasttrack-connection chain=forward comment="defconf: fasttrack" connection-state=established,related
add action=accept chain=forward comment="defconf: accept established,related, untracked" connection-state=established,related,untracked
add action=drop chain=forward comment="defconf: drop invalid" connection-state=invalid log-prefix=drop-invalid
add action=drop chain=forward comment="defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat connection-state=new in-interface-list=WAN log-prefix=drop-from-wan-not-dstnated
add action=accept chain=input in-interface-list=WAN protocol=gre
add action=accept chain=forward comment="accept forward WAN" in-interface-list=accept-forward-WAN out-interface-list=WAN
add action=accept chain=forward comment="accept forward LAN" in-interface-list=accept-forward-LAN out-interface-list=LAN
add action=accept chain=input comment="accept input DNS (udp)" dst-port=53 in-interface-list=accept-input-DNS protocol=udp
add action=accept chain=input comment="accept input DNS (tcp)" dst-port=53 in-interface-list=accept-input-DNS protocol=tcp
add action=accept chain=input comment=accept-input-NTP dst-port=123 in-interface-list=accept-input-NTP protocol=udp
add action=accept chain=input comment="accept input DHCP-server" dst-port=67 in-interface-list=accept-input-DHCP-server log-prefix=accept-DHCP protocol=udp
add action=accept chain=input comment="accept input winbox (tcp)" dst-port=8291 in-interface-list=accept-input-winbox protocol=tcp
add action=accept chain=input comment="accept input winbox (udp)" dst-port=20561 in-interface-list=accept-input-winbox protocol=udp
add action=accept chain=input comment="accept input web ui" dst-port=80,443 in-interface-list=accept-input-web-ui protocol=tcp
add action=accept chain=input comment="accept input mikrotik neighbor discovery" dst-port=5678 in-interface-list=accept-input-mikrotik-neighbor-discovery protocol=udp
add action=drop chain=forward comment="drop forward" log=yes log-prefix=drop-forward
add action=drop chain=input comment="drop input" log=yes log-prefix=drop-input
add action=accept chain=output comment=accept-output-LAN out-interface-list=LAN
/ip firewall nat
add action=masquerade chain=srcnat comment="defconf: masquerade" ipsec-policy=out,none out-interface-list=WAN
/ip ipsec profile
set [ find default=yes ] dpd-interval=2m dpd-maximum-failures=5
/ip service
set www-ssl certificate=alwaldend.com_acme disabled=no
set reverse-proxy certificate=alwaldend.com_acme
set api-ssl certificate=alwaldend.com_acme
/ipv6 address
add address=::1 from-pool=dc01 interface=bridge1
add address=::1:0:0:0:1 from-pool=dc01 interface=bridge2
/ipv6 firewall address-list
add address=::/128 comment="defconf: unspecified address" list=bad_ipv6
add address=::1/128 comment="defconf: lo" list=bad_ipv6
add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6
add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6
add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6
add address=100::/64 comment="defconf: discard only " list=bad_ipv6
add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6
add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6
add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6
/ipv6 firewall filter
add action=accept chain=input comment="defconf: accept established,related,untracked" connection-state=established,related,untracked
add action=drop chain=input comment="defconf: drop invalid" connection-state=invalid
add action=accept chain=input comment="defconf: accept ICMPv6" in-interface-list=accept-input-ICMP protocol=icmpv6
add action=accept chain=input comment="defconf: accept UDP traceroute" dst-port=33434-33534 protocol=udp
add action=accept chain=input comment="defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=udp src-address=fe80::/10
add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 protocol=udp
add action=accept chain=input comment="defconf: accept ipsec AH" protocol=ipsec-ah
add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=ipsec-esp
add action=accept chain=input comment="defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec
add action=drop chain=input comment="defconf: drop everything else not coming from LAN" in-interface-list=!LAN
add action=accept chain=forward comment="defconf: accept established,related,untracked" connection-state=established,related,untracked
add action=drop chain=forward comment="defconf: drop invalid" connection-state=invalid
add action=drop chain=forward comment="defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6
add action=drop chain=forward comment="defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6
add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" hop-limit=equal:1 protocol=icmpv6
add action=accept chain=forward comment="defconf: accept ICMPv6" in-interface-list=accept-input-ICMP protocol=icmpv6
add action=accept chain=forward comment="defconf: accept HIP" protocol=139
add action=accept chain=forward comment="defconf: accept IKE" dst-port=500,4500 protocol=udp
add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=ipsec-ah
add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=ipsec-esp
add action=accept chain=forward comment="defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec
add action=drop chain=forward comment="defconf: drop everything else not coming from LAN" in-interface-list=!LAN
add action=accept chain=forward comment="accept forward WAN" in-interface-list=accept-forward-WAN out-interface-list=WAN
add action=accept chain=forward comment="accept forward LAN" in-interface-list=accept-forward-LAN out-interface-list=LAN
add action=accept chain=input comment="accept input DNS (udp)" dst-port=53 in-interface-list=accept-input-DNS protocol=udp
add action=accept chain=input comment="accept input DNS (tcp)" dst-port=53 in-interface-list=accept-input-DNS protocol=tcp
add action=accept chain=input comment=accept-input-NTP dst-port=123 in-interface-list=accept-input-NTP protocol=udp
add action=accept chain=input comment="accept input winbox (tcp)" dst-port=8291 in-interface-list=accept-input-winbox protocol=tcp
add action=accept chain=input comment="accept input winbox (udp)" dst-port=20561 in-interface-list=accept-input-winbox protocol=udp
add action=accept chain=input comment="accept input web ui" dst-port=80,443 in-interface-list=accept-input-web-ui protocol=tcp
add action=accept chain=input comment="accept input mikrotik neighbor discovery" dst-port=5678 in-interface-list=accept-input-mikrotik-neighbor-discovery protocol=udp
add action=drop chain=forward comment="drop forward" log=yes log-prefix=drop-forward-ipv6
add action=drop chain=input comment="drop input" log=yes log-prefix=drop-input-ipv6
add action=accept chain=output comment=accept-output-LAN out-interface-list=LAN
/ipv6 nd
set [ find default=yes ] advertise-dns=yes interface=bridge1
add advertise-dns=yes interface=bridge2
/system clock
set time-zone-name=Europe/Moscow
/system identity
set name=router1.dc1.alwaldend.com
/system ntp server
set enabled=yes
/system routerboard settings
set auto-upgrade=yes
/tool mac-server
set allowed-interface-list=LAN
/tool mac-server mac-winbox
set allowed-interface-list=LAN
Router2
# 2025-09-07 11:04:01 by RouterOS 7.19.4
# model = L009UiGS-2HaxD
/interface bridge
add name=bridge01
/port
set 0 name=serial0
/interface bridge port
add bridge=bridge01 interface=ether2
add bridge=bridge01 interface=ether3
add bridge=bridge01 interface=ether4
add bridge=bridge01 interface=ether5
add bridge=bridge01 interface=ether6
add bridge=bridge01 interface=ether7
add bridge=bridge01 interface=ether8
add bridge=bridge01 interface=ether1
/ip neighbor discovery-settings
set discover-interface-list=!dynamic
/ipv6 settings
set accept-router-advertisements=yes
/ip dhcp-client
add interface=bridge01
/system clock
set time-zone-name=Europe/Moscow
/system identity
set name=router02.dc01.alwaldend.com
/system routerboard settings
set enter-setup-on=delete-key
2.12.1 -
Infrastructure MikroTik
Purpose
Describe the checked-in RouterOS export snapshots and site DNS declarations for the dc1 routers. This package is a documentation and record-input owner: its BUILD file declares no router deployment executable. Export contents are historical source evidence, not a verification of current device configuration.
Baseline source revision: 550d7e79b1f5fdbc2b6017b75178471d6914082f.
Observation date: 2026-09-08. Sources are linked in full; no excerpts are used.
Sources: export workflow, package targets, router1 snapshot, router2 snapshot, and DNS declarations.
Requirements
Requirement: Preserve export snapshots as the package’s documented interface
The package SHALL retain the router export files as documentation inputs and
describe the RouterOS /export collection workflow. Documentation SHALL
distinguish these snapshots from automatically applied desired state. The
Terraform root SHALL manage DNS records only and SHALL NOT apply router exports.
Scenario: Inspect the router package
- WHEN a reader opens the component documentation
- THEN the reader can inspect both router export snapshots
- AND the Terraform package exposes owner-local DNS management while the snapshots remain documentary inputs
Requirement: Describe the two routers according to their recorded topology
The baseline description SHALL identify router1’s separate wired and wireless bridges with their own DHCP networks, and router2’s single bridge containing its eight Ethernet interfaces with a DHCP client. It SHALL NOT infer additional live devices or enabled topology from comments elsewhere in the repository.
Scenario: Compare the recorded network roles
- WHEN the two checked-in exports are compared
- THEN router1 records
bridge1for wired ports andbridge2for Wi-Fi ports - AND router2 records
bridge01and an IP DHCP client on that bridge
Requirement: Retain the recorded router1 traffic-policy structure
The router1 snapshot SHALL describe named interface lists for input and forwarding permissions, explicit terminal IPv4 input and forwarding drops, and source NAT masquerading for WAN egress. This contract describes the export and SHALL NOT be represented as a live firewall audit.
Scenario: Review router1’s recorded IPv4 policy
- WHEN a reader follows the IPv4 firewall section of the snapshot
- THEN the listed service permissions precede terminal input and forwarding drop rules
- AND the NAT section declares masquerading for traffic leaving the WAN list
Requirement: Supply site-local DNS records to the DNS owner
The package SHALL expose its dnsconfig.json as a Bazel filegroup. Its router,
switch, and bare-metal records SHALL be assigned to the dc1 destination view.
Scenario: Assemble the dc1 DNS configuration
- WHEN the DNS owner consumes
//infra/mikrotik:dnsconfig - THEN router1 IPv4 and IPv6 records and the declared switch and bare-metal IPv4 records are available for the dc1 view
2.12.2 -
owned-dns Specification
Purpose
Define MikroTik router DNS management through the owner’s tf root,
including canonical declarations, scoped credentials, and offline source checks
before adopting live records.
Requirements
Requirement: Owner-local DNS configuration
The tf root SHALL consume this owner’s canonical dnsconfig.json through
the shared DNS Terraform module, preserving declared record identities and views.
DNS resources SHALL default to disabled until the authorized adoption revision
and SHALL retain enabled ownership after existing records are imported into the
owner’s state. Reconciliation against unchanged declarations and adopted state
SHALL propose no record additions, changes, replacements, or deletions.
Scenario: Inspect the preparatory configuration
- WHEN the checked-in root is evaluated with default inputs before its authorized adoption revision
- THEN it reads this owner’s declaration and disables managed DNS records
- AND the package contains the module and declaration inputs
Scenario: Adopt existing DNS records
- WHEN the authorized adoption audits competing writers within its documented coverage, keeps identified competing writers stopped, and enables the owner’s record management
- THEN the owning root imports existing records by exact provider ID into its state while preserving their declared identities and views
Scenario: Inspect adopted source defaults
- WHEN the adopted root uses its checked-in source defaults
- THEN DNS ownership remains enabled and the package retains the module and canonical declaration inputs
Scenario: Reconcile existing DNS records
- WHEN the owning root plans against its adopted state and unchanged declarations
- THEN it proposes no record additions, changes, replacements, or deletions
Requirement: Scoped DNS execution and offline checks
The DNS wrapper SHALL select src_infra_mikrotik through the repository AL flow and keep
secret values in injected variables. DNS injection SHALL select the root’s existing
Terraform stage label. Real DNS credentials and Vault policy grants SHALL be
prerequisites for operational Terraform calls. RouterOS DNS credentials SHALL be isolated
from unrelated RouterOS resources. The package SHALL expose a format test that
does not authenticate to Vault or contact DNS providers.
Scenario: Validate the Terraform source
- WHEN the package format test executes
- THEN it checks the packaged Terraform configuration without live credentials
- AND existing non-DNS authentication and backend paths remain unchanged
Scenario: Prepare an operational Terraform invocation
- WHEN the wrapper selects its Terraform stage labels
- THEN it selects DNS credential injection through the owner AppRole
- AND disabled DNS resources do not imply offline provider configuration
2.12.3 -
DNS Terraform
This root packages the owner’s canonical DNS declaration
through the shared DNS module and keeps state in the owner AppRole’s Vault HTTP
backend. The root contains DNS resources only. dns_enabled defaults to true
after verified adoption. Keep it enabled to retain existing records; disabling
it would propose deletion.
Use the normal //infra/mikrotik/tf:tf.<operation> wrappers for this DNS-only
root. The DNS migration procedure owns credential
provisioning, reconciliation, and recovery. The
adoption record
contains the import and inventory-preservation evidence. The package exposes
//infra/mikrotik/tf:tf_tests.fmt_test for offline formatting checks.
Operational Terraform calls require the DNS AppRole policy grants and credential fields described by the migration procedure. Provider configuration requires real credentials and live access independently of the activation setting.
2.13 - Nas
The Terraform package prepares this owner’s DNS records through its dedicated Vault AppRole. NAS service provisioning remains outside that root.
Links
- Docs: https://www.truenas.com/
2.13.1 -
NAS infrastructure Specification
Purpose
Describe the TrueNAS-related configuration surface currently owned by
infra/nas. The baseline is checked-in source at revision
550d7e79b1f5fdbc2b6017b75178471d6914082f, observed on 2026-09-08.
The directory contains an AL configuration, DNS declarations, Vault wrappers,
and brief documentation. It does not contain a TrueNAS provisioning playbook
or Terraform configuration, and this baseline makes no claim about live NAS
configuration or availability.
Source baseline limitation: the owning BUILD file restricts the AL target’s
visibility to //infra/harvester:__subpackages__, although infra/harvester
does not exist in this revision. This declaration does not establish a working
consumer integration.
Requirements
Requirement: Scoped NAS configuration packaging
The project SHALL declare its AL configuration through //infra/nas:al.
That configuration SHALL depend on the shared //infra:al configuration.
The project’s Vault command map SHALL use its own AL target.
Sources: project description and configuration and command targets.
Scenario: Inspect the NAS configuration and Vault packaging
- WHEN a maintainer inspects the NAS target declarations
- THEN the AL target includes
al.luaand the shared infrastructure AL dependency - AND the Vault command map references that NAS AL target
Requirement: Distinct local and global cloud DNS destinations
The NAS DNS declaration SHALL expose the NAS host and root names as A records,
and SHALL distinguish the DC1 and global cloud aliases. The DC1 cloud alias
SHALL target nas.alwaldend.com., while the global alias SHALL target
ingress.alwaldend.com.. The DNS filegroup SHALL remain visible only within
the infrastructure tree.
Sources: DNS declarations and DNS target visibility.
Scenario: Consume DNS declarations for different views
- WHEN a DNS consumer selects the entries tagged
dc1andglobal - THEN it receives the NAS destination for the DC1
cloudalias and the ingress destination for the globalcloudalias.
2.13.2 -
owned-dns Specification
Purpose
Define NAS DNS management through the owner’s tf root,
including canonical declarations, scoped credentials, and offline source checks
before adopting live records.
Requirements
Requirement: Owner-local DNS configuration
The tf root SHALL consume this owner’s canonical dnsconfig.json through
the shared DNS Terraform module, preserving declared record identities and views.
DNS resources SHALL default to disabled until the authorized adoption revision
and SHALL retain enabled ownership after existing records are imported into the
owner’s state. Reconciliation against unchanged declarations and adopted state
SHALL propose no record additions, changes, replacements, or deletions.
Scenario: Inspect the preparatory configuration
- WHEN the checked-in root is evaluated with default inputs before its authorized adoption revision
- THEN it reads this owner’s declaration and disables managed DNS records
- AND the package contains the module and declaration inputs
Scenario: Adopt existing DNS records
- WHEN the authorized adoption freezes the old central writers and enables the owner’s record management
- THEN the owning root imports existing records by exact provider ID into its state while preserving their declared identities and views
Scenario: Inspect adopted source defaults
- WHEN the adopted root uses its checked-in source defaults
- THEN DNS ownership remains enabled and the package retains the module and canonical declaration inputs
Scenario: Reconcile existing DNS records
- WHEN the owning root plans against its adopted state and unchanged declarations
- THEN it proposes no record additions, changes, replacements, or deletions
Requirement: Scoped DNS execution and offline checks
The DNS wrapper SHALL select src_infra_nas through the repository AL flow and keep
secret values in injected variables. DNS injection SHALL select the root’s existing
Terraform stage label. Real DNS credentials and Vault policy grants SHALL be
prerequisites for operational Terraform calls. RouterOS DNS credentials SHALL be isolated
from unrelated RouterOS resources. The package SHALL expose a format test that
does not authenticate to Vault or contact DNS providers.
Scenario: Validate the Terraform source
- WHEN the package format test executes
- THEN it checks the packaged Terraform configuration without live credentials
- AND existing non-DNS authentication and backend paths remain unchanged
Scenario: Prepare an operational Terraform invocation
- WHEN the wrapper selects its Terraform stage labels
- THEN it selects DNS credential injection through the owner AppRole
- AND disabled DNS resources do not imply offline provider configuration
2.13.3 -
DNS Terraform
This root packages the owner’s canonical DNS declarations
through the shared DNS module and keeps state in the owner AppRole’s Vault HTTP
backend. The root contains DNS resources only. dns_enabled defaults to true
after verified adoption. Keep it enabled to retain existing records; disabling
it would propose deletion.
The DNS migration procedure owns credential provisioning,
reconciliation, and recovery. The adoption record
contains import and verification evidence. Use the //infra/nas/tf:tf wrappers
for operational commands and //infra/nas/tf:tf_tests.fmt_test for offline
source validation.
Operational Terraform calls require the DNS AppRole policy grants and credential fields described by the migration procedure. Provider configuration and authentication require real credentials and live access.
2.14 - OpenHands
OpenHands deploys as separate components because each owns a distinct responsibility and trust boundary:
| Component | Responsibility |
|---|---|
| Agent Canvas | Browser client for conversations, files, settings, backends, automations |
| Agent Server | Runs conversations, agents, tools, and workspace operations |
| Automation Server | Stores schedules and triggers, tracks runs, dispatches conversations |
The agent server runs directly on the host with the service account’s permissions. Its workspace is a working directory; operating-system account permissions define its access to the host. Treat the agent server host as trusted infrastructure.
Layout
tf_setupcreates the Agent Canvas, secured agent server, and automation server VMs in thesrc_infra_openhandsXen Orchestra resource set.ansibledeploys the three VM components. The host-bot project owns and deploys its unsecured agent server.dnsconfig.jsonowns the component hostnames and static addresses.al.luaauthenticates with thesrc_infra_openhandsVault AppRole, signs host keys for Ansible, and injects the component secrets.
There is no tf package: these components keep their state in files and
SQLite on their own hosts, so no API-side resources exist to declare.
Canvas serves the packaged browser assets through its static-server service on loopback. Configure the browser’s backend with the canvas origin as its host and the agent server session key as its credential.
Traefik and TLS
Each component host runs Traefik from the shared role with certificates issued
by src_infra_openhands_pki_server. The canvas origin proxies /api/*,
/api/automation, /sockets, and /server_info to the agent server and
automation server, so the browser talks to one origin and issues no
cross-origin request.
The public canvas.openhands.alwaldend.com record is a CNAME to
ingress.alwaldend.com, and infra/ingress forwards it to
dc1.canvas.openhands.alwaldend.com. That ingress keeps its
RequireAndVerifyClientCert client-auth policy, so reaching canvas from
outside still requires a client certificate.
Secrets
agent_server holds session_api_key and secret_key; automation holds
kv_secret. The session API key is shared by the agent server, the automation
server, and the browser because all three authenticate the same
X-Session-API-Key value.
The unsecured host-bot server has a separate secret_key reference owned by
its host’s AL configuration.
Prepare one private JSON input for each path through the
secret-handling workflow.
Set OPENHANDS_AGENT_SERVER_JSON, OPENHANDS_AUTOMATION_JSON, and
OPENHANDS_HOST_BOT_JSON to those input file paths. Each JSON object contains
the fields listed above for its path. Initialize the paths through standard
input; -cas=0 prevents overwriting existing data:
bazel_agent bazel run //infra/openhands:vault.kv_put -- -cas=0 \
alwaldend.com/vault1/approles/src_infra_openhands/agent_server \
- < "$OPENHANDS_AGENT_SERVER_JSON"
bazel_agent bazel run //infra/openhands:vault.kv_put -- -cas=0 \
alwaldend.com/vault1/approles/src_infra_openhands/automation \
- < "$OPENHANDS_AUTOMATION_JSON"
bazel_agent bazel run //users/simeonwarren:vault.kv_put -- -cas=0 \
alwaldend.com/vault1/approles/user_simeonwarren/openhands \
- < "$OPENHANDS_HOST_BOT_JSON"
Deployment
bazel run //infra/openhands/tf_setup:tf_setup.plan
bazel run //infra/openhands/tf_setup:tf_setup.apply
bazel run //infra/openhands/ansible
The component AppRole must first exist in Vault. Follow the
XO authentication and resource-set workflow to
synchronize its OIDC identity and apply its resource-set assignment before
tf_setup runs. The assignment in
resource_set_inventory supplies the template,
storage, and network by name. Component secrets must be written to Vault
before Ansible runs. State and locking use the repository’s tf_backend
plugin, which stores them as Vault KV entries and creates the entries on first
use, so no separate state bucket is required.
2.14.1 -
owned-dns Specification
Purpose
Define OpenHands DNS management through the owner’s tf_setup root,
including canonical declarations, scoped credentials, and offline source checks
before adopting live records.
Requirements
Requirement: Owner-local DNS configuration
The tf_setup root SHALL consume this owner’s canonical dnsconfig.json through
the shared DNS Terraform module, preserving declared record identities and views.
DNS resources SHALL default to disabled before adoption and SHALL default to
enabled in the reviewed adoption revision. Adoption SHALL bind existing records
to their exact provider identities and SHALL preserve their declared attributes.
Existing-record adoption SHALL contain no DNS record additions, changes,
replacements, or deletions. Verified missing declarations MAY be provisioned
through an exact additions-only DNS plan that preserves every existing record
and excludes non-DNS managed-resource changes. After deployment, default DNS
reconciliation SHALL retain the bindings and preserve unrelated provider records.
Scenario: Inspect the preparatory configuration
- WHEN the checked-in root is evaluated with default inputs before adoption
- THEN it reads this owner’s declaration and disables managed DNS records
- AND the package contains the module and declaration inputs
Scenario: Inspect the adopted default
- WHEN the reviewed adoption revision is evaluated with default inputs after adoption
- THEN it reads this owner’s declaration and enables managed DNS records
- AND the package contains the module and declaration inputs
Scenario: Adopt existing records
- WHEN the owner’s existing records are adopted through its scoped DNS wrappers
- THEN Terraform binds the records to their exact provider identities
- AND their declared values, attributes, and views remain unchanged
- AND the reviewed adoption plan contains no DNS additions, changes, replacements, or deletions
Scenario: Reconcile without changes after adoption
- WHEN the adopted root plans with default inputs and unchanged declarations and provider records
- THEN the plan retains the adopted bindings and contains no DNS additions, changes, replacements, or deletions
- AND unrelated provider records remain unchanged
Scenario: Provision missing declarations
- WHEN fresh complete provider inventories prove the owner’s declared records are absent and conflict-free
- THEN the reviewed DNS plan creates only those declared missing records
- AND existing provider identities and attributes remain unchanged
- AND a subsequent DNS plan contains no changes
Requirement: Scoped DNS execution and offline checks
The dns.plan, dns.show, and dns.apply wrappers SHALL select dns=1 through
the repository AL flow using src_infra_openhands, and operate on module.dns
and its dependencies in the existing tf_setup root and Vault HTTP backend.
Apply SHALL consume the reviewed saved plan. Ordinary VM setup SHALL retain its
tf=setup and xoa_login=1 labels, XO authentication, and existing backend paths.
Secret values SHALL remain in injected variables. Real DNS credentials and
Vault policy grants SHALL be prerequisites for operational DNS calls. RouterOS
DNS credentials SHALL remain isolated from unrelated RouterOS resources.
Successful scoped DNS execution SHALL not establish VM or service health.
The package SHALL expose a format test that does not authenticate to Vault or
contact DNS providers.
Scenario: Validate the Terraform source
- WHEN the package format test executes
- THEN it checks the packaged Terraform configuration without live credentials
- AND existing non-DNS authentication and backend paths remain unchanged
Scenario: Prepare an operational Terraform invocation
- WHEN the scoped DNS wrapper selects
dns=1 - THEN it selects DNS credential injection through the owner AppRole and existing backend without starting XO login
- AND the targeted plan and saved-plan apply cover DNS and its dependencies, without establishing VM or service health
- AND disabled DNS resources do not imply offline provider configuration
2.14.2 - Ansible
Deploys the OpenHands components. The inventory has three hosts in three groups, and the playbook applies one component role per group:
| Group | Host | Component |
|---|---|---|
openhands_canvas |
host1.canvas.openhands.alwaldend.com |
Agent Canvas |
openhands_server_secure |
host1.server.openhands.alwaldend.com |
Agent server (secured) |
openhands_automation |
host1.automation.openhands.alwaldend.com |
Automation server |
The three XCP-ng VMs exist only for the secured agent server and for the
components that must not share a trust boundary with host-bot. The secured
group sets openhands_server_session_api_key and hands the same value to the
automation server so the automation dispatcher can authenticate its
dispatched conversations.
Every component applies host and traefik. Canvas runs the published
package’s static server directly on loopback. The operator configures the
browser backend with the canvas origin and the shared session key.
The canvas host routes /api/automation to the automation host and the agent
server API prefixes to the secured agent server. These routes take precedence
over the frontend route, so the configured browser reaches one origin.
Downstream routers accept the original canvas Host header.
The unsecured agent server runs on host-bot and is deployed by
the host-bot project, which
owns that host entirely. It omits OH_SESSION_API_KEYS_0 and binds to loopback
without a session API key. Access is local to host-bot; its Traefik and firewall
configuration add no route for this server.
The group variables read the session key, secret key, and automation KV secret from the environment the AL Vault injector populates.
2.14.3 - Tf setup
This package creates Xen Orchestra VMs in the src_infra_openhands resource
set for the three OpenHands components that run off host-bot: Agent Canvas,
the agent server, and the automation server. infra/openhands/al.lua
authenticates with OpenHands’ own Vault AppRole and the packaged XO OIDC login
plugin. The plugin supplies a temporary XO token and revokes it on shutdown;
no infrastructure administrator token is loaded. The setup HTTP backend
remains owned by the same OpenHands config.
Before running VM setup, bootstrap the AppRole’s XO OIDC user and apply
its resource-set membership through infra/xcp_ng/tf. Subjects are matched by
immutable Vault entity UUID under the configured OIDC issuer, not by login
name or AppRole group membership. See
XO authentication.
vms holds the component definitions, and each entry names the dnsconfig
record prefix that owns its hostname and address. Adding a component means
adding a record to ../dnsconfig.json and an entry here; the guest hostname,
static address, and derived MAC all come from that one record. The agent
server is sized larger because it stores every backend conversation,
workspace, and bash event.
Defaults select the imported Fedora 44 template, local storage and wired
network by name from the OpenHands resource set. Override
TF_VAR_xoa_template_name, TF_VAR_xoa_storage_name, and
TF_VAR_xoa_network_name for another assignment. Native provider lookups run
as OpenHands’ own identity and reject ambiguous matches. The selected network
must carry 192.168.10.0/24; gateway and DNS default to 192.168.10.1 (the
wired router) and can be overridden.
The PVE-based infra/cloud_init:xen_linux target supplies the shared Ansible
user and CA configuration through the repository template rule. Terraform adds
the hostname and static network configuration from ../dnsconfig.json. After
cloud-init completes, verify that /dev/xvda is the boot disk before running
Ansible.
bazel_agent bazel run //infra/openhands/tf_setup:tf_setup.plan
bazel_agent bazel run //infra/openhands/tf_setup:tf_setup.apply
Use this package’s dns.plan, dns.show, and dns.apply targets for the
scoped DNS adoption workflow.
They select dns=1 and target module.dns in the same root, AppRole, and
backend without starting XO login. Apply requires the reviewed saved plan;
the shared procedure
owns preparation and reconciliation.
dns_enabled defaults to true after
verified initial provisioning.
Keep it enabled to retain the managed records. Unchanged declarations and
provider records produce a no-change DNS plan. Successful DNS checks do not
establish VM, OpenHands service, or TLS readiness; the separate
service deployment change
retains that acceptance work.
2.15 - Pve
Links
Deployment
bazel run //infra/pve/ansible # host setup
bazel run //infra/pve/tf/tf.apply # tf setup
Recreate the test VM
bazel run //infra/pve/tf:tf.apply -- --replace module.vm_cloudinit_test.proxmox_vm_qemu.vm
Cloud-init snippet update
bazel run //infra/pve/ansible -- --tags pve_snippets
Update ACME account
- Create an EAB:
bazel run //infra/dc1/vault -- write -f pki/ica_servers/roles/src_infra_dc1_pve1_pki_server/acme/new-eab - Login as
root@pam - Go to Datacenter -> ACME
- Create a new account with the EAB and a directory:
https://vault.dc1.alwaldend.com:8200/v1/pki/ica_servers/roles/src_infra_dc1_pve1_pki_server/acme/directory
Pve token
- Create a token with Privilege Separation
- Grant it required roles
- Create json:
{ "token_id": "", "token_secret": "" } - Write the data:
bazel run //infra/pve:vault.kv_put alwaldend.com/vault1/approles/src_infra_dc1_pve1/pve_token @"${PWD}/data.json"
2.15.1 -
Proxmox infrastructure Specification
Purpose
Specify the Proxmox cluster configuration, resource pools, and bootstrap test
VM owned by infra/pve. The baseline is checked-in source at revision
550d7e79b1f5fdbc2b6017b75178471d6914082f, observed on 2026-09-08.
It describes declared infrastructure and packaged operator entry points;
deployment and cluster health have not been observed for this baseline.
Requirements
Requirement: AppRole resource pools
The Terraform configuration SHALL resolve the members of Vault’s approles
identity group and declare one Proxmox pool per resolved entity, keyed and
named by that entity’s name. It SHALL also declare a separate templates pool.
Sources: project documentation and resource pool definitions.
Scenario: Declare pools for known AppRoles
- WHEN Terraform resolves the entities in the Vault
approlesgroup - THEN the desired configuration includes a pool with each entity’s name
and the dedicated
templatespool.
Requirement: Packaged host and snippet configuration
The PVE Ansible entry point SHALL package the inventory and deployment playbook
and apply the shared host and PVE roles to the pve1 inventory group. It SHALL
package the canonical shared cloud-init files under files/cloud_init.yaml
and files/cloud_init_min.yaml, preserving the existing snippet update flow.
Sources: deployment target, playbook, and snippet variables.
Scenario: Assemble the PVE deployment package
- WHEN the Ansible binary’s source package is built
- THEN it includes the playbook, inventory, shared role collection, and both shared cloud-init files under their established aliases.
Requirement: Cloud-init test virtual machine
The Terraform configuration SHALL declare its cloud-init test VM through the
shared pve_vm_qemu module, derive its hostname and address from the project’s
DNS configuration, and place it in the src_infra_dc1_pve1 AppRole pool. The
baseline declaration SHALL use VM ID 100, a 5G scsi0 disk, and the test tag.
Sources: VM definition and DNS configuration.
Scenario: Resolve the test VM’s desired configuration
- WHEN Terraform evaluates
module.vm_cloudinit_test - THEN its name and
/24address derive fromcloudinit_testDNS fields, and its pool resolves to the declared PVE AppRole pool.
Requirement: Repository-managed execution inputs
PVE Terraform commands SHALL use the project’s AL configuration and the declared Terraform, PVE-login, and Vault-environment plugins. The package SHALL include the lockfile, Terraform source, shared backend and VM modules, and required Vault helper targets. PVE Ansible commands SHALL likewise use the project AL configuration and packaged injector.
Sources: Terraform wrapper and Ansible wrapper.
Scenario: Construct a PVE Terraform invocation
- WHEN a repository Terraform command target is invoked with authorization for its operation
- THEN the wrapper supplies the declared modules and helper inputs and
selects the
tf,pve_login, andvault_env=default_defaultplugins.
2.15.2 -
owned-dns Specification
Purpose
Define Proxmox cluster DNS management through the owner’s tf root,
including canonical declarations, scoped credentials, and offline source checks
before adopting live records.
Requirements
Requirement: Owner-local DNS configuration
The tf root SHALL consume this owner’s canonical dnsconfig.json through
the shared DNS Terraform module, preserving declared record identities and views.
DNS resources SHALL default to disabled until the authorized adoption revision
and SHALL retain enabled ownership after existing records are imported into the
owner’s state. Reconciliation against unchanged declarations and adopted state
SHALL propose no record additions, changes, replacements, or deletions.
Scenario: Inspect the preparatory configuration
- WHEN the checked-in root is evaluated with default inputs before its authorized adoption revision
- THEN it reads this owner’s declaration and disables managed DNS records
- AND the package contains the module and declaration inputs
Scenario: Adopt existing DNS records
- WHEN the authorized adoption audits competing writers, keeps identified writers stopped within the recorded coverage, and enables owner record management
- THEN the owning root imports existing records by exact provider ID into its state while preserving their declared identities and views
Scenario: Inspect adopted source defaults
- WHEN the adopted root uses its checked-in source defaults
- THEN DNS ownership remains enabled and the package retains the module and canonical declaration inputs
Scenario: Reconcile existing DNS records
- WHEN the owning root plans against its adopted state and unchanged declarations
- THEN it proposes no record additions, changes, replacements, or deletions
Requirement: Scoped DNS execution and offline checks
The DNS wrappers SHALL select src_infra_dc1_pve1 through the repository AL flow
and keep secret values in injected variables. dns.plan, dns.show, and
dns.apply SHALL select dns=1 and operate on module.dns in the existing tf
root and backend. Apply SHALL consume the reviewed saved plan. Required root
inputs SHALL retain their existing Vault readers, while ordinary Proxmox
authentication SHALL remain separate. Scoped DNS operations SHALL verify DNS
and its dependencies without establishing overall PVE service health.
Real DNS credentials and Vault policy grants SHALL be prerequisites for
operational Terraform calls. RouterOS DNS credentials SHALL be isolated from
unrelated RouterOS resources. The package SHALL expose a format test that does
not authenticate to Vault or contact DNS providers.
Scenario: Validate the Terraform source
- WHEN the package format test executes
- THEN it checks the packaged Terraform configuration without live credentials
- AND existing non-DNS authentication and backend paths remain unchanged
Scenario: Prepare an operational Terraform invocation
- WHEN the scoped DNS wrapper selects
dns=1 - THEN it selects DNS credential injection through the owner AppRole and uses the existing root and backend without starting Proxmox login
- AND the targeted plan and saved-plan apply cover DNS and its dependencies, without proving PVE host or API health
- AND disabled DNS resources do not imply offline provider configuration
2.15.3 - Ansible
2.15.4 - Tf
Use this package’s dns.plan, dns.show, and dns.apply targets for the
scoped DNS adoption workflow.
They select dns=1 and target module.dns in this root, retaining the
src_infra_dc1_pve1 AppRole and existing backend. Use the
owner preparation and import procedure
for declarative import maps and reviewed saved-plan apply.
dns_enabled defaults to true after the
completed adoption.
Reconciliation against adopted state and unchanged declarations produces no DNS
changes. DNS targeting covers DNS and its dependencies; it does not establish
PVE host, API, or service health. Ordinary Terraform commands retain their
existing Proxmox authentication.
2.16 - Repositories
This project owns the organization and repository catalog consumed by
GitHub, GitLab, and
Forgejo. Named organization administrators and
developers belong in this catalog. Root configuration owns
the schema version and defaults. Each organization owns
orgs/<organization>/org.json and one
orgs/<organization>/repos/<repository>.json file per repository. Vault
continues to own Forgejo login identities and service-specific access.
First-party means owned by us, regardless of forge. Our repositories retain
their chosen names across GitHub, GitLab, and Forgejo: alwaldend/src stays
alwaldend/src, including when copied or synchronized between those forges.
Forks and mirrors of external repositories must belong to an organization in
the catalog. Their names use the original upstream hostname in reverse order,
followed by its full owner and repository path, in lowercase with punctuation
replaced by underscores. For example, https://gitlab.com/fdroid/fdroiddata
becomes alwaldend/com_gitlab_fdroid_fdroiddata. Copies on another forge keep
that name; they do not add a prefix for our intermediate copy. This naming
rule also applies to external repositories imported once for later syncing.
The Terraform module owns this derivation. A forge key opts a
repository into that consumer. GitLab import_from refers to the corresponding
catalog source; fork_from identifies a GitLab upstream. External origins
belong in the repository’s upstream_url. Forge-specific overrides preserve
settings such as Pages sites and repository descriptions during adoption.
Consumers retain their own providers, state, and Vault authentication. They
adopt existing remote resources by import and preserve managed resource
addresses or declare explicit moves. Named developers can read repositories,
write feature branches, and open pull or merge requests; protected default
branches restrict pushes and merges to administrators and any separately
owned existing service grants. Catalog GitHub repositories permit merge
commits only: the shared defaults disable squash merges and rebase merges, and
a catalog precondition rejects any repository record that enables them. Merging
therefore keeps the reviewed feature commit as a parent of the default-branch
commit instead of replacing it. GitLab and Forgejo merge methods are not owned
here. Dedicated per-project landing repositories are retired: the main site
publishes every project landing at /projects/<name>/, so the catalog carries
no landing repository. The apex site repository keeps the Pages configuration
that serves it.
Catalog targets are repository-internal infrastructure inputs. They are not production build dependencies or published artifacts.
GitLab receives one-time repository imports and the configured upstream fork. The user will arrange ongoing synchronization separately; the decision and adoption evidence live in OpenSpec.
2.16.1 -
repository-catalog Specification
Purpose
Define shared organization, repository identity, naming, and named access configuration for the GitHub, GitLab, and Forgejo infrastructure consumers.
Requirements
Requirement: Authoritative organization and repository inventory
The repository catalog SHALL store shared defaults and schema version at its root, one configuration file per organization, and one configuration file per repository beneath its organization. Those records SHALL own the configured organizations, repositories, named administrators, and named developers. Each forge consumer SHALL use that catalog for its selected repositories and named roles, preserving forge-specific settings without maintaining another copy of the inventory. Authentication and service-specific grants SHALL remain with their existing owners.
Scenario: Consume one organization definition
- WHEN an organization assigns named administrators and developers and selects repositories for multiple forges
- THEN each selected consumer uses the same catalog assignments and repository identities
- AND forge-specific settings and service identities remain with their declared owners
Requirement: Stable names follow ownership and original upstream
First-party repository names SHALL remain the same across forges, including when copied or synchronized. External forks and mirrors SHALL belong to a catalog organization and use a name derived from the original upstream’s reversed hostname followed by its full owner and repository path, in lowercase with punctuation replaced by underscores. Cross-forge copies of external repositories SHALL retain that name rather than naming the intermediate copy as their upstream.
Scenario: Copy an organization-owned repository
- WHEN the first-party
alwaldend/srcrepository is copied from GitHub to GitLab or Forgejo - THEN its destination remains
alwaldend/src
Scenario: Fork an external repository
- WHEN
https://gitlab.com/fdroid/fdroiddatais forked intoalwaldend - THEN its organization-owned name is
alwaldend/com_gitlab_fdroid_fdroiddata - AND subsequent copies on another forge retain that name
Requirement: Named developer access excludes protected default writes
Consumers SHALL grant catalog administrators administrative access and catalog developers repository reads, feature-branch writes, and pull or merge request creation. Catalog developers SHALL NOT receive direct push or merge access to protected default branches through their named roles or overlapping retained grants. Existing service-specific permissions SHALL be preserved and distinguished from named developer assignments.
Scenario: Develop on a feature branch
- WHEN a catalog developer accesses a selected repository
- THEN the developer can read its contents, create a feature branch, and open a pull or merge request
- AND the developer cannot push or merge to its protected default branch
Requirement: Adopt existing resources without recreation
Consumers SHALL adopt existing remote resources through imports and preserve their remote identities. Existing managed resource addresses SHALL remain stable or use explicit state-preserving moves. Existing GitHub repository settings and Pages configuration SHALL remain intact, and default branches SHALL remain unchanged. No deletion or replacement SHALL execute without separate user approval for its concrete scope.
Scenario: Adopt an existing repository
- WHEN a catalog repository already exists remotely or in Terraform state
- THEN its import or state move preserves the existing remote repository ID and contents
- AND the reviewed plan does not recreate it to resolve a name collision
Scenario: Encounter a destructive plan
- WHEN any reviewed plan proposes a deletion or replacement
- THEN execution of that operation stops pending the user’s explicit approval for the identified operation and scope
Requirement: GitLab copies and fork preserve their source identity
GitLab SHALL receive a one-time Git import of every catalog-selected GitHub repository and an organization-owned fork of the selected F-Droid metadata upstream. Imports SHALL preserve the source default branch, and the fork SHALL retain its upstream fork relationship. This change SHALL configure no ongoing synchronization.
Scenario: Complete the initial GitLab population
- WHEN the GitHub default-branch migration completes and the initial GitLab imports and fork finish
- THEN every selected GitHub repository has its intended GitLab copy and source default branch
- AND the metadata repository retains its F-Droid upstream fork identity
- AND later upstream changes are not promised to synchronize
Requirement: Adopt GitLab default-branch protections without removal
GitLab default-branch access SHALL be established through group defaults before new repositories are populated. Existing automatically created protections SHALL be verified and imported before standalone protection management is applied. Adoption SHALL preserve the existing protections; provider limitations SHALL be reported rather than bypassed by unprotecting or recreating them.
Scenario: Adopt an automatically protected default branch
- WHEN an imported GitLab repository has an existing default-branch rule
- THEN Terraform adopts that rule by import before applying permitted in-place access changes
- AND adoption does not invoke unprotect-and-recreate behavior
2.16.2 - Repository catalog module
This provider-free Terraform module reads the catalog files, merges forge defaults, and projects organization-owned repository names and settings for each consumer. It creates no resources and uses no credentials.
Fork and mirror names follow the catalog naming contract. Output keys retain the organization and catalog key, independently of the derived destination name. The consumers retain their existing state addresses where resources were already managed.
The catalog test runs without network access or provider initialization:
bazel_agent bazel test //infra/repos/tf:tf_tests.catalog_test
2.17 - Source repository
This project owns the OpenSpec workspace describing evolution of the alwaldend/src monorepo: its shared structure, build system and development workflows. It also retains the index of the goal-to-OpenSpec migration. Individual projects own their own specifications and change history.
The repository root remains the Bazel workspace and owns shared executable configuration. This directory owns repository development specifications; adding or changing them does not provision infrastructure.
Run the pinned CLI from the repository root. It selects this project by default:
bazel_agent bazel run //tools/openspec -- list --specs
2.17.1 -
Repository evolution
This OpenSpec workspace describes evolution of the alwaldend/src repository
itself: its shared structure, build system and development workflows.
specs/repository/spec.md records that contract;
changes/ records proposed and completed changes to it.
Each component owns a separate OpenSpec workspace beside its source:
projects/<project>/openspec/holds that project’s specs and changes.tools/<project>/openspec/holds that tool project’s specs and changes.infra/<project>/openspec/holds that infrastructure project’s specs and changes.infra/src/openspec/holds the repository’s own specs and changes.
Select the narrowest owner of the requested behavior. A project change belongs in that project’s workspace, including when it has a standalone Bazel module. Changes to shared repository structure belong here. Work spanning owners keeps each affected contract with its owner and links related changes. Component READMEs and build declarations retain their existing authority.
Run OpenSpec
The pinned CLI runs from the Git worktree
root. It selects infra/src by default; use OPENSPEC_PROJECT for a component:
bazel_agent bazel run //tools/openspec -- list --specs
OPENSPEC_PROJECT=projects/agents bazel_agent bazel run //tools/openspec -- list
OPENSPEC_PROJECT=infra/vault bazel_agent bazel run //tools/openspec -- list --specs
Use new change, status, instructions, validate, and archive with the
same owner selection. The packaged OpenSpec skill
documents continuation and acceptance. No global install or assistant
configuration rewrite is needed. The CLI isolates configuration and disables
telemetry.
Repository validation checks every component workspace as well as this one:
bazel_agent bazel test //infra/src/openspec/validation:validate_test //infra/src/openspec/validation:archive_test
Validation checks artifact structure and, for archives, task completion. Requirement acceptance still needs evidence from the owning implementation. Infrastructure specs describe checked-in definitions, not observed deployment.
Maintain work
In the selected workspace, changes/<name>/proposal.md states outcome and
scope, design.md records decisions and continuation, tasks.md records
remaining actions, and specs/<capability>/spec.md contains requirement deltas.
Read an existing matching change before creating another. Keep temporary
notes, raw logs and validation receipts under ignored out/<task>/.
On interruption, preserve the candidate, evidence, execution state and next action. Keep blocked or unfinished work explicit. OpenSpec files and Git do not supply the removed legacy goal store’s transaction locks or evidence verdicts; one coordinator owns a change and reconciles concurrent edits.
After acceptance, validate and archive the change in its owning workspace, then inspect the resulting baseline specs. Specifications and generated instructions neither expand user authority nor introduce an approval gate.
Goal migration
migration.md maps the nine maintained goals to their current
owner-local changes. It records a repository workflow migration; the actual
history and work state live with Agents, MCP Cordis and Renders. Original
history, checksums and acceptance states are preserved. Historical deltas
were archived without applying them to current specs. Reimu Fumo remains
open and blocked.
The legacy goal tool, its skill, and its store have been removed. New maintained work uses the owning OpenSpec workspace; the migration record above preserves the historical record.
2.17.1.1 -
Goal migration to OpenSpec
On 2026-09-08, all nine tracked maintained project goal records at source commit 550d7e79b1f5fdbc2b6017b75178471d6914082f were migrated into native OpenSpec changes. Each change now lives in its owning project’s openspec/ workspace. Eight completed records are imported as archived history. The Reimu Fumo change remains open with blocked execution and no accepted candidate.
The machine-readable inventory maps all 222 tracked source files (834,320 bytes) to byte-identical provenance snapshots. Test fixtures and ignored task scratch are outside the maintained-record inventory.
Record mapping
| Former maintained goal | OpenSpec change | Preserved outcome | Preserved execution |
|---|---|---|---|
projects/agents/goals/agent-system-phase-1 |
agent-system-phase-1 | achieved | paused |
projects/agents/goals/agent-system-phase-2 |
agent-system-phase-2 | achieved | paused |
projects/agents/goals/agent-system-phase-3 |
agent-system-phase-3 | achieved | paused |
projects/agents/goals/agent-system-phase-4 |
agent-system-phase-4 | achieved | paused |
projects/agents/goals/agent-system-phase-five-followup |
agent-system-phase-five-followup | achieved | paused |
projects/agents/goals/agent-system-phase-six-ergonomics |
agent-system-phase-six-ergonomics | achieved | paused |
projects/agents/goals/repo-agent-system |
repo-agent-system | achieved | paused |
projects/renders/goals/reimu-fumo-finish |
reimu-fumo-finish | open | blocked |
projects/mcp_cordis/goals/runtime_extensions |
runtime_extensions | achieved | unavailable in source |
Mapping and acceptance
- Objective and scope map to
proposal.md; accepted plans, decisions, rejected approaches, and constraints map todesign.md. - The latest acceptance criteria map to
tasks.mdand meaningful capability delta requirements. Each YAML criterion keeps its stable ID and revision inmigration.json; original revisions, attempts, review verdicts, and evidence remain in provenance. - Completed task checkboxes reproduce explicit historical acceptance reviews. They do not revalidate today’s source. The Markdown Cordis record declares Complete and no failing criteria; its absent execution field stays unavailable rather than being guessed.
- Reimu acceptance and continuation tasks remain unchecked. A supported authorized unblock can change execution while the outcome remains open until every required criterion passes.
- Completed records were placed directly in their owner’s
openspec/changes/archive/2026-09-08-<id>/. No archive or spec-sync command applied their historical deltas. Current baseline specifications were derived separately from maintained owner source. Do not reapply historical deltas. - Historical Phase 5 acceptance includes an explicit fixture-gap inventory. Its accepted review and still-pending prose are both retained; migration does not claim the missing infrastructure fixtures were implemented.
Provenance and navigation
Each change has migration.json, a checksum inventory at provenance/manifest.json, original record bytes at provenance/source/, and a provenance navigation guide. The old agent goal landing and BUILD file are also retained under the repository-agent-system archive. The historical BUILD snapshot uses .original to preserve bytes without creating a new Bazel package.
Among preserved Markdown links, 47 links depend on the former location; companion navigation tables resolve them where the referenced artifact exists. 46 historical targets are unavailable in the checkout. Original bytes and historical Git identities are not rewritten to disguise unavailable scratch or superseded paths.
The former maintained goal directories are removed, and the legacy goal tool and its store were later removed as well; native OpenSpec work is the continuation surface. Provenance files are excluded from generic formatting so their source digests remain stable. The migration inventory is import evidence, not an alternate work scheduler or mutable status catalog. The removal change is remove-deprecated-goal-component.
2.17.1.2 -
go-mod-version Specification
Purpose
Keep tracked go.mod files on the Go version configured for
tools/go_mod.
Sources: tool README, tool BUILD, and archive.
Requirements
Requirement: Configured go.mod version
The repository SHALL provide a tools/go_mod command that discovers every
tracked go.mod file and sets its go directive to the version configured in
the tool’s BUILD file. The command MUST offer an update mode and a check mode.
Scenario: Update module files
- WHEN a user runs the update target
- THEN every tracked
go.modfile whosegodirective differs from the configured version is rewritten to that version - AND files already on the configured version remain unchanged
Scenario: Check module files
- WHEN the check test runs
- THEN it fails if any tracked
go.modfile has agodirective different from the configured version - AND it passes when every tracked
go.modfile matches
Requirement: Repository quality integration
The go.mod version check MUST run as part of //:repo_quality_test so a
version mismatch fails repository quality.
Scenario: Quality suite covers the check
- WHEN a
go.modfile’sgodirective differs from the configured version - THEN
//:repo_quality_testfails
2.17.1.3 -
Repository Evolution Specification
Purpose
Define how the alwaldend/src monorepo evolves its shared structure, build
system and development workflows. Component behavior is specified in each
owner’s local OpenSpec workspace. This baseline was inspected at source revision
550d7e79b1f5fdbc2b6017b75178471d6914082f on 2026-09-08 and incorporates the
OpenSpec migration delivered with this specification. Changes in infra/src
record repository evolution; they do not collect unrelated component work or claim
runtime health or deployed infrastructure.
Sources: repository map, agent policy, root build, project boundary, infrastructure boundary, tool boundary, and OpenSpec workflow.
Requirements
Requirement: Component ownership and source boundaries
The repository MUST keep component purpose and publication boundaries in the nearest owner README, executable and dependency structure in BUILD and MODULE files, and agent policy in the applicable AGENTS.md chain. Specifications SHALL describe component requirements with links to these owners.
Scenario: Select an implementation owner
- WHEN a change affects a project, tool or infrastructure component
- THEN its owning documents and Bazel workspace determine the affected paths and supported consumers
- AND a repository-wide catalog or specification does not grant broader publication or execution authority
Requirement: Reproducible Bazel development
Repository agent build and test operations MUST use bazel_agent bazel in the
owning workspace with pinned dependencies and the repository’s shared agent
configuration. Generated dependency and catalog files MUST be updated through
their owning generator.
Every nested module that declares MODULE.bazel MUST declare only
dependencies its own sources use, with a resolvable version or an override
that applies when that module is the root. Every nested module directory MUST
appear in the root .bazelignore so root target expansion does not cross the
workspace boundary. Each nested workspace MUST build and test standalone.
Scenario: Change a shared dependency
- WHEN an implementation adds an external build input
- THEN its owner records an immutable version and integrity information
- AND applicable generated locks and package checks validate the declared dependency through the pinned build workflow
Scenario: Build a nested module standalone
- WHEN a nested Bazel workspace is built or tested on its own
- THEN its module graph resolves without depending on root-only overrides
- AND the workspace builds and tests through its shared configuration
Scenario: Expand root targets across a nested boundary
- WHEN the root workspace expands targets beneath a nested module directory
- THEN the nested workspace is excluded by the root ignore list
- AND root expansion neither loads nor silently omits that module
Requirement: Isolated implementation and evidence
Repository modifications MUST use a dedicated feature branch and linked
worktree. Task scratch MUST remain under ignored out/<task>/ in the
applicable workspace. Acceptance SHALL identify the candidate and relevant
checks and representative output before delivery.
Scenario: Finish a repository change
- WHEN an authorized implementation is ready for delivery
- THEN task-owned changes pass applicable formatting, quality and semantic checks and are committed and published through the repository procedure
- AND unrelated edits, scratch and protected data are excluded
Requirement: Declarative infrastructure authority
Persistent infrastructure configuration MUST be defined in checked-in owning infrastructure code. Infrastructure operations MUST require the user’s exact operation and scope authorization; an implementation validation request SHALL NOT authorize live deployment.
Scenario: Validate an infrastructure specification
- WHEN an agent adds or updates an infra component specification
- THEN it inspects source and runs applicable offline checks
- AND it does not infer deployed state or execute live apply or deployment from the existence of the specification
Requirement: OpenSpec coverage and work state
Each direct project in projects/ and infra/ SHALL keep its baseline
specifications and maintained changes in its own openspec/ workspace.
infra/src/openspec SHALL describe evolution of the repository itself,
including shared structure, build system and development workflows. The
repository root SHALL NOT collect component specifications or change records.
Maintained work SHALL preserve outcome, decisions, tasks and requirement
deltas. Existing task authority MUST survive workflow transitions.
Scenario: Change a component contract
- WHEN a change affects a project’s supported behavior
- THEN its specifications and change artifacts remain in that project’s
openspec/directory - AND the pinned CLI and context routing select that owner workspace
Scenario: Evolve the repository itself
- WHEN a change affects the monorepo’s shared structure or development workflow
- THEN
infra/src/openspecrecords its repository requirements and evolution - AND component contracts remain with their respective owners
Scenario: Resume unfinished maintained work
- WHEN an agent resumes a named OpenSpec change
- THEN it reads that owner’s change artifacts, candidate, evidence and next action
- AND unfinished or blocked acceptance remains explicit until evidence supports completion
Scenario: Validate a standalone project
- WHEN a project has its own Bazel module
- THEN repository OpenSpec validation still checks its declared local workspace
- AND a successful repository check does not omit that project’s requirements
Requirement: Legacy goal migration and deprecation
The migration SHALL preserve all tracked maintained goal history and its recorded acceptance and execution states with source-to-change mappings and checksums. The goal skill MUST be disabled for discovery and the goal tool MUST identify itself as deprecated compatibility functionality.
Scenario: Inspect a migrated historical record
- WHEN a reader follows a legacy goal’s migration entry
- THEN its OpenSpec change exposes the original history and status
- AND historical completion does not establish acceptance for a different candidate or automatically apply old specification deltas
Requirement: Rule scripts and generated documentation
Bazel rules MUST NOT embed templated executable content in rule source. A rule
that needs an executable MUST reference an ordinary checked-in script and
supply its inputs as declared arguments or data files. Every public rule set
MUST generate stardoc documentation for its public .bzl entry points, and the
repository’s main documentation output MUST include that generated
documentation.
Scenario: A rule needs to run scripted logic
- WHEN an implementation needs a rule to run a script
- THEN the script is checked in as a normal file with its own target and receives data through arguments or a declared data file
- AND generated shell or program text does not live in the
.bzlsource
Scenario: A rule set exposes public rules
- WHEN a project publishes a public Bazel rule or macro
- THEN it declares stardoc coverage for the declaring file
- AND the generated pages appear in the repository documentation build
Requirement: Bazel rule modules are tool components
First-party standalone Bazel rule modules SHALL live under tools/<module>/.
Their relocation MUST preserve module names, supported public rule and macro
interfaces, standalone workspace resolution, generated rule documentation,
and owner-local specifications. Repository consumers and discovery mechanisms
MUST resolve their new source locations through the owning declarations.
Scenario: Consume a relocated rule module
- WHEN a root or nested workspace loads a relocated rule module through its supported module name and public rule interface
- THEN the module resolves from its new tool-owned location
- AND its supported build behavior remains available without changing the public module identity
Scenario: Discover a relocated owner’s specifications and rules
- WHEN repository documentation, skill discovery, or OpenSpec validation traverses the relocated modules
- THEN it selects the modules’ new owner paths
- AND generated rule documentation and existing component specifications remain included in their declared outputs and checks
Requirement: Rule tools do not publish dedicated project landings
The relocated rule modules SHALL have no dedicated project landing-site configuration. After authorized retirement, their selected landing repository and DNS declarations MUST be absent from the owning infrastructure, and shared-catalog consumers MUST exclude those retired repositories. Retirement MUST preserve unrelated repositories, sites, access grants, and authentication resources.
Scenario: Build or import the remaining repository catalog
- WHEN the catalog is projected for GitHub or GitLab after rule-landing retirement
- THEN the retired landing repositories are absent
- AND remaining repositories retain their catalog identities, names, and configured access behavior
Scenario: Retire a selected landing site
- WHEN the owning declarative workflows execute the user’s explicitly authorized retirement scope
- THEN the selected Pages repository and matching DNS record are removed
- AND the reviewed plans and postconditions show no unrelated deletion or replacement
2.18 - threexui
Links
- Site: https://docs.sanaei.dev/
- Releases: https://github.com/MHSanaei/3x-ui/releases
Fetch and fix subs for a particular subscription id
bazel run //infra/threexui:fix_subs -- --hosts njalla1.nodes.threexui.alwaldend.com,yc1.nodes.threexui.alwaldend.com --sub_id subid
Fix subs from a local file
bazel run //infra/threexui:fix_subs -- --sub_file path_to_file
2.18.1 -
Infrastructure 3x-ui
Purpose
Describe 3x-ui provisioning, host deployment, node routing configuration, and
the subscription URL transformer. This baseline describes checked-in source,
not verified live node access. The advertised host-only subscription command
has a source limitation: sub/main.go also attempts to read sub_file when it
is empty, so successful host-only operation is not a baseline guarantee.
Baseline source revision: 550d7e79b1f5fdbc2b6017b75178471d6914082f.
Observation date: 2026-09-08. Sources are linked in full; no excerpts are used.
Sources: component documentation, root wrappers, provisioning package, configuration package, host playbook, Traefik routes, node definitions, node inbounds, node routing, and subscription transformer.
Requirements
Requirement: Separate provisioning, deployment, and service configuration
The package SHALL keep infrastructure creation in tf_setup, host deployment
in Ansible, and 3x-ui API resources in tf. The deployment playbook SHALL apply
host, Traefik, and 3x-ui roles to the control-plane and data-plane inventory
groups.
Scenario: Select a 3x-ui workflow
- WHEN an authorized operator selects the setup or main Terraform wrapper
- THEN its AL plugin selects the corresponding Terraform stage
- AND the Ansible playbook remains the owner of host and service installation
Requirement: Terminate proxy traffic at the declared local services
The Traefik route template SHALL forward the panel to loopback port 2053 and subscription requests to loopback port 2096. It SHALL define HTTP inbound routes for ports 40000 through 40149 and TCP inbound routes for ports 40150 through 40299, forwarding to corresponding loopback ports.
Scenario: Render a subscription route
- WHEN the checked-in dynamic Traefik template is rendered
- THEN requests matching the configured subscription path prefix route to
http://127.0.0.1:2096 - AND the router selects the configured TLS certificate resolver
Requirement: Declare explicit node and outbound routing relationships
Terraform SHALL configure the njalla1 and yc1 nodes through the shared node
module. The node routing declaration SHALL block the advertising category and
private IP destinations before routing the freedom inbound directly and each
mullvad_min or http_proxy inbound through its named WireGuard outbound.
The enabled mullvad_min_lb inbound has no active dedicated balancing rule;
commented balancing rules SHALL NOT be treated as enabled routing behavior.
Scenario: Inspect a configured Mullvad inbound route
- WHEN a node’s selected relay creates a Mullvad inbound
- THEN the inbound listens on loopback
- AND its routing rule selects the matching
out-mullvad-min-outbound tag - AND the node declaration supplies its own relay selection to the module
Requirement: Normalize subscription URLs from readable inputs
For readable local subscription files, the transformer SHALL ignore blank and
comment lines, parse each remaining URL, set security=tls and sni to the URL
hostname, sort URLs by fragment, and write one URL per output line. It SHALL
return a nonzero exit status when input reading or URL parsing fails.
Scenario: Transform a local subscription file
- WHEN
fix_subsreceives a readable--sub_filecontaining subscription URLs - THEN output URL queries contain
security=tlsand the matching hostname SNI - AND output is ordered by URL fragment with blank and comment lines omitted
2.18.2 -
owned-dns Specification
Purpose
Define retained 3x-ui DNS ownership through the owner’s tf_setup root,
including canonical declarations, scoped execution, and offline source checks.
Requirements
Requirement: Owner-local DNS configuration
The tf_setup root SHALL consume this owner’s canonical dnsconfig.json through
the shared DNS Terraform module, preserving declared record identities and views.
DNS resources SHALL default to disabled before the adoption revision and SHALL
retain enabled ownership after authorized adoption into the owner’s state.
Reconciliation against adopted state and unchanged declarations SHALL propose
no record additions, changes, replacements, or deletions.
Scenario: Inspect the preparatory configuration
- WHEN the preparatory root is evaluated with default inputs before its adoption revision
- THEN it reads this owner’s declaration and disables managed DNS records
- AND the package contains the module and declaration inputs
Scenario: Inspect adopted source defaults
- WHEN the adopted root is evaluated with its checked-in default inputs
- THEN DNS ownership is enabled and the root reads the canonical declaration
- AND the package contains the module and declaration inputs
Scenario: Adopt existing DNS records
- WHEN authorized adoption coordinates the previous writers and enables this owner’s record ownership
- THEN the owner imports existing provider identities into its own state through the owning scoped DNS wrappers and reviewed saved-plan import blocks
- AND existing record values and declared DNS views are preserved
Scenario: Reconcile adopted DNS records
- WHEN the owner plans against its adopted state and unchanged declarations
- THEN it proposes no record additions, changes, replacements, or deletions
- AND unrelated records remain unchanged
Requirement: Scoped DNS execution and offline checks
The DNS wrappers SHALL select src_infra_threexui through the repository AL flow
and keep secret values in injected variables. dns.plan, dns.show, and
dns.apply SHALL retain the owning root and backend, select dns=1, and scope
planning to module.dns. Apply SHALL require the reviewed saved plan. This
workflow SHALL preserve ordinary service authentication and SHALL NOT establish
overall service health. Required DNS credentials and Vault grants SHALL remain
operational prerequisites, and RouterOS DNS credentials SHALL remain isolated
from unrelated RouterOS resources. The package SHALL expose a format test
without Vault authentication or DNS provider access.
Scenario: Validate the Terraform source
- WHEN the package format test executes
- THEN it checks the packaged Terraform configuration without live credentials
- AND existing non-DNS authentication and backend paths remain unchanged
Scenario: Prepare an operational Terraform invocation
- WHEN the operator selects the owning DNS wrappers
- THEN they select DNS credential injection through the owner AppRole with
dns=1 - AND their scoped plan validates DNS and its dependencies
- AND disabled DNS resources do not imply offline provider configuration
2.18.3 - Ansible
2.18.4 - sub
2.18.5 - Tf
2.18.6 - Tf setup
Use this package’s dns.plan, dns.show, and dns.apply targets for the
scoped DNS adoption workflow.
DNS ownership is enabled by default after the verified 2026-09-13 adoption.
The adoption evidence
records 12 imports, a no-change follow-up plan, and preserved provider inventories.
The DNS wrappers select dns=1 and module.dns within this setup root and
backend; their validation covers DNS and its dependencies. Apply requires a
reviewed saved plan, and ordinary service authentication remains separate.
2.19 - Vault
Links
- Intermediate CA: https://developer.hashicorp.com/vault/tutorials/pki/pki-engine-external-ca
- ACME: https://developer.hashicorp.com/vault/docs/secrets/pki/acme
Deployment
bazel run //infra/vault/tf_setup:tf.apply # Create VMs (requires an active Vault host)
bazel run //infra/vault/ansible # Set up hosts (BM and VMs)
bazel run //infra/vault/tf:tf.apply # Configure vault
Backup
bazel run //infra/vault:backup
Unseal
With a working Vault:
bazel run //infra/vault:unseal
Without a working Vault:
bazel run //infra/vault:unseal_standalone
Fix quorum
bazel run //infra/vault/ansible:fix_quorum
Set up only VMs
bazel run //infra/vault/ansible:ansible.vm # Set up only VMs
Set up only bare metal
bazel run //infra/vault/ansible:ansible.bm # Set up only bare metal
Tf
Plan:
bazel run //infra/vault/tf:tf.plan
Apply:
bazel run //infra/vault/tf:tf.apply
Run terraform directly:
bazel run //infra/vault/tf:tf.direct -- -chdir="${PWD}" plan
Replace VMs
bazel run //infra/vault/tf:tf.apply -- -replace 'module.vm_ha["host2"].proxmox_vm_qemu.vm' -replace 'module.vm_ha["host3"].proxmox_vm_qemu.vm
Generate and import a user cilent certificate
username="username"
bazel run //infra/vault:gen_client_cert -- --user "${username}" --output_dir "${PWD}"
bazel run //tools/ykman -- piv certificates import 9A "${PWD}/${username}.pfx"
bazel run //tools/ykman -- piv keys import 9A "${PWD}/${username}.pfx"
Generate a host cilent certificate
bazel run //infra/vault:gen_client_cert -- --host some-host --output_dir "${HOME}/.al/client_cert"
Generate a user device cilent certificate
bazel run //infra/vault:gen_client_cert -- --host some-host --user username --output_dir "${HOME}/.al/client_cert"
Unseal
- Prepare encrypted unseal token
- Run and input the encrypted token:
bazel run //infra/vault:unseal
Root token
- Prepare encrypted unseal token
- Run and input the encrypted token:
bazel run //infra/vault:gen_root_token -- --pgp_key path_to_public_gpg_key_in_base64
Generate an EAB for ACME
bazel run //infra/vault -- write -f pki/ica_servers/roles/ica_servers_dc1_pve1/acme/new-eab
Sign a client ssh key
bazel run //:vault -- write ssh/clients/sign/admins ttl=30000000 public_key=@"${HOME}/.ssh/key"
Revoke all tokens
bazel run //infra/vault -- token revoke -mode=path auth
Vault certificates
Vault certificates (tls_cert_file, tls_key_file) should be updated manually
Read OIDC client info
bazel run //infra/vault -- read identity/oidc/client/src_infra_dc1_forgejo1_provider
Read all entity aliases
bazel run //infra/vault -- list -format json identity/entity-alias/id | jq ".[]" | xargs "-I{}" bazel run //infra/vault -- read "identity/entity-alias/id/{}"
2.19.1 -
Infrastructure Vault
Purpose
Describe the Vault host configuration, authentication and certificate services, and packaged recovery entry points. This baseline concerns checked-in desired state and supported wrapper structure; it does not establish live unsealed state, successful backups, quorum, or certificate freshness.
Baseline source revision: 550d7e79b1f5fdbc2b6017b75178471d6914082f.
Observation date: 2026-09-08. Sources are linked in full; no excerpts are used.
Sources: operator documentation, operational wrappers, Ansible entry points, Vault host template, authentication backends, storage engines, server PKI, client PKI, and public CA outputs.
Requirements
Requirement: Separate host provisioning from Vault configuration
The documented workflow SHALL separate tf_setup VM provisioning, Ansible host
setup, and the tf Vault configuration stage. Ansible SHALL expose combined,
VM-only, and bare-metal-only setup entry points using the shared host and Vault
roles.
Scenario: Prepare an authorized host setup
- WHEN an operator selects
ansible.vmoransible.bm - THEN the wrapper selects the matching checked-in playbook and inventory
- AND Vault’s API configuration remains owned by the separate Terraform stage
Requirement: Configure TLS endpoints and Raft storage
The host template SHALL configure TLS API and cluster endpoints on ports 8200
and 8201 and Raft storage under /opt/vault/raft. It SHALL derive each Raft node
identifier from the inventory hostname and emit retry-join addresses for hosts
in the Vault inventory group.
Scenario: Render a Vault host configuration
- WHEN Ansible renders
vault.hclfor a member of the Vault group - THEN its API and cluster URLs use its inventory hostname
- AND Raft receives that hostname as node ID and the group’s HTTPS join URLs
Requirement: Declare authentication and secret-engine boundaries
Terraform SHALL declare userpass, approle, and cert authentication
backends, a version-two KV engine at secrets, and a transit engine at
transit/default. Client and server certificate authorities SHALL remain
distinct, and server PKI ACME SHALL require external account binding with the
default directory policy set to forbid.
Scenario: Inspect the configured credential services
- WHEN the main Terraform configuration is evaluated
- THEN authentication, KV, transit, client PKI, and server PKI are distinct declared resources
- AND server ACME is enabled with
eab_policy = "always-required" - AND published CA output files contain certificate or public-key material
Requirement: Package recovery and certificate operations explicitly
The package SHALL expose separate wrappers for backup, ordinary unseal,
standalone unseal, client certificate generation, and root-token generation.
Standalone unseal SHALL use the default_no_auth environment without selecting
the ordinary unseal plugin; these wrappers SHALL NOT imply that recovery has
been executed successfully.
Scenario: Select the standalone unseal workflow
- WHEN an authorized operator invokes
//infra/vault:unseal_standalone - THEN the wrapper selects the packaged unseal utility and declared Vault endpoint with its no-auth environment
- AND success remains an operational result to be observed separately
Requirement: Give each DNS owner a component identity
Every owner that manages DNS records through Terraform SHALL use its existing component AppRole or a dedicated owner AppRole when one is missing. A DNS-only identity SHALL retain the shared AppRole module’s own-state and named shared secret access without cloud provisioning, SSH, or PKI permissions. Existing component identities and unrelated authentication flows SHALL remain stable.
Scenario: Introduce a landing site’s DNS stage
- WHEN a project has DNS records but no existing component AppRole
- THEN Vault configuration declares an AppRole named for that owner
- AND the identity can manage its own Terraform state without access to another owner’s state
Scenario: Add host DNS management
- WHEN host_bot uses its dedicated DNS AppRole
- THEN its existing Ansible authentication remains unchanged
Requirement: Restrict provider secret reads to owned DNS views
DNS identities SHALL receive read access to the existing Cloudflare credential only when they own global records and to the existing RouterOS DNS credential only when they own dc1 records. DNS access SHALL NOT grant writes to either provider secret or duplicate credential values.
Scenario: Configure a global-only landing site
- WHEN an owner declares only global records
- THEN its DNS policy grants Cloudflare credential reads
- AND its DNS policy grants no RouterOS credential access
Scenario: Configure records in both views
- WHEN an owner declares global and dc1 records
- THEN its DNS policy grants reads for both existing credential references
- AND neither read policy grants mutation of the provider credential
2.19.2 -
owned-dns Specification
Purpose
Define Vault service DNS management through the owner’s tf_setup root,
including canonical declarations, scoped credentials, and offline source checks
before adopting live records.
Requirements
Requirement: Owner-local DNS configuration
The tf_setup root SHALL consume this owner’s canonical dnsconfig.json through
the shared DNS Terraform module, preserving declared record identities and views.
DNS resources SHALL default to disabled until the authorized adoption revision
and SHALL retain enabled ownership after existing records are imported into the
owner’s state. Reconciliation against unchanged declarations and adopted state
SHALL propose no record additions, changes, replacements, or deletions.
Scenario: Inspect the preparatory configuration
- WHEN the checked-in root is evaluated with default inputs before its authorized adoption revision
- THEN it reads this owner’s declaration and disables managed DNS records
- AND the package contains the module and declaration inputs
Scenario: Adopt existing DNS records
- WHEN the authorized adoption completes the shared writer audit and applicable recovery prerequisites and enables the owner’s record management
- THEN the owning root imports existing records by exact provider ID into its state while preserving their declared identities and views
Scenario: Inspect adopted source defaults
- WHEN the adopted root uses its checked-in source defaults
- THEN DNS ownership remains enabled and the package retains the module and canonical declaration inputs
Scenario: Reconcile existing DNS records
- WHEN the owning root plans against its adopted state and unchanged declarations
- THEN it proposes no record additions, changes, replacements, or deletions
Requirement: Scoped DNS execution and offline checks
The dns.plan, dns.show, and dns.apply entrypoints SHALL select
src_infra_dc1_vault through the repository AL flow using dns=1 and operate
on module.dns in the existing tf_setup root and Vault HTTP backend. The
apply entrypoint SHALL require a saved plan. Ordinary setup and service
wrappers SHALL retain their stage labels, authentication, and backend paths.
Secret values SHALL remain in injected variables. Real DNS credentials and
Vault policy grants SHALL be prerequisites for operational DNS calls.
RouterOS DNS credentials SHALL remain isolated from unrelated RouterOS
resources. The package SHALL expose a format test that does not authenticate
to Vault or contact DNS providers.
Scenario: Validate the Terraform source
- WHEN the package format test executes
- THEN it checks the packaged Terraform configuration without live credentials
- AND existing non-DNS authentication and backend paths remain unchanged
Scenario: Prepare an operational Terraform invocation
- WHEN a scoped DNS entrypoint selects
dns=1 - THEN it selects DNS credential injection through the owner AppRole and
existing setup backend, with plan and show scoped to
module.dnsand apply requiring a saved plan - AND disabled DNS resources do not imply offline provider configuration
- AND ordinary setup and service authentication retains its original labels
2.19.3 - Ansible
2.19.4 - Tf
DNS identities
Missing DNS-owner AppRoles compose the existing reusable
AppRole module with an owner-specific DNS policy in approles/<name>/.
DNS access grants read-only access to the existing
provider credentials for the owner’s views. Existing component identities
receive these policies through their existing module declarations.
DNS-only group membership adds no policies. These identities retain their own state and named shared-secret access without joining the general infrastructure AppRole group or receiving cloud provisioning, SSH, or PKI permissions.
The operator bootstrap membership follows the existing component pattern. An authorized Vault apply must create the roles and policies before their DNS stages can authenticate; source validation does not establish deployed access. Follow the DNS migration for the coordinated cutover and the AppRole bootstrap procedure when distinguishing missing deployment from insufficient operator access.
2.19.4.1 - Output
2.19.5 - Tf setup
This root owns Vault’s canonical DNS declaration and
retains its existing src_infra_dc1_vault AppRole and setup state backend.
Use //infra/vault/tf_setup:dns.plan, dns.show, and dns.apply for the
scoped DNS workflow. They select dns=1 and
module.dns; apply requires a reviewed saved plan. Ordinary setup and service
wrappers retain their existing authentication flow.
dns_enabled defaults to true after verified adoption. Keep it enabled to
retain existing records; disabling it would propose deletion. The
adoption record
contains the import and verification evidence. Targeted DNS checks do not
establish the health of other resources in the root.
Offline formatting is available through
//infra/vault/tf_setup:tf_tests.fmt_test.
2.20 - XCP-ng
Terraform in tf manages a Xen Orchestra resource set for every
entity in Vault’s approles group, following infra/pve/tf. Resource sets
are the XO grouping and delegation mechanism; XCP-ng host pools represent
physical clusters and are not created per AppRole.
resource_set_inventory assigns a pool, template, storage repository and
network by name to each AppRole. Native provider lookups resolve their IDs
and reject ambiguous matches. Forgejo and OpenHands have assignments by default;
other sets remain empty. Subjects are the exact synchronized OIDC users
selected by Vault issuer and immutable AppRole entity UUID. Bootstrap has
synchronized the 18 AppRole users; new AppRoles need their first OIDC login
before Terraform can bind their sets. resource_set_cpu_limit defaults to
32 CPUs per set. Creating a set does not allocate CPUs or storage.
The provider is pinned to vatesfr/xenorchestra 0.41.0. The single
infra/xcp_ng/al.lua configuration supplies administrator authentication for
XCP-ng infrastructure operations: its named xcp_ng Vault AppRole injects
XOA_TOKEN from key xoa_token in
secrets/alwaldend.com/vault1/approles/src_infra_xcp_ng/xoa.
Forgejo instead uses its own Vault identity through the
XO login plugin, which issues an invocation-scoped
XO session and revokes it on shutdown. It retains its own Terraform backend
and does not inherit the infrastructure administrator token. Token values
are not Terraform inputs or outputs.
The default endpoint is wss://xoa.xcp-ng.alwaldend.com. DNS maps the XO
appliance to 192.168.1.206 and the XCP-ng host to 192.168.1.213.
TLS verification is enabled. xoa_insecure is an explicit temporary
bootstrap override for an appliance whose certificate has not been replaced.
The HTTP backend stores state under the AppRole’s tf_backend Vault path.
OIDC and certificates
infra/vault/tf owns the src_infra_xcp_ng_provider OIDC client, the
src_infra_xcp_ng_users and src_infra_xcp_ng_admins groups, and the
src_infra_xcp_ng_pki_server ACME role. Apply those scoped prerequisites
before the XO configuration. The callback is
https://xoa.xcp-ng.alwaldend.com/signin/oidc/callback.
XO must have the auth-oidc plugin installed and trust Vault’s CA. The
Terraform provider has no plugin resource, so terraform_data.oidc invokes
the packaged Go JSON-RPC helper directly, without a shell. It configures
Vault discovery, the client, and the user groups scopes, enables autoload,
and verifies the plugin is loaded. The OIDC client secret remains sensitive
and is stored in the Vault-protected Terraform state. The provisioner signs
the XCP-ng AppRole in through Vault to create the synchronized OIDC groups.
Plugin reconciliation runs when configuration or the helper binary changes,
without native drift refresh. Use -replace=terraform_data.oidc to reapply
after manual plugin drift.
Native xenorchestra_acl resources manage the administrators group’s pool
permissions. An import block adopts matching existing ACLs using their
discovered API IDs. The helper only reads these ACLs; it does not change them.
The users group grants login eligibility, with membership refreshed at login.
Per-AppRole resource-set membership and existing VM ownership use direct user
subjects. The Forgejo user receives administration permission on its own VM;
no shared pool-wide view grant is configured.
The helper remains for gaps in the pinned provider: OIDC plugin configuration and bootstrap, discovery of external identity subjects and synchronized groups, host registration, prepared VHD template import, and diagnostics. Resources, ACLs and named infrastructure lookups use the native provider.
The resource-set management page is
Self Service. In the deployed XO
source revision 961b505cfb74cbf24aaeb8d61c5613f97e78de2c, its
menu entry
requires a global administrator. The
page
also requires XOA_PLAN > 3, corresponding to
Premium or Community.
The runtime edition has not been verified. Pool-level administrator ACLs do
not satisfy the page’s global-administrator requirement.
The certificate playbook uses Certbot with Vault EAB, installs XO’s Vault CA trust, and configures renewal. It requires appliance SSH access and inspected HTTPS certificate paths. Initial issuance and renewal briefly interrupt XO management access, not running guest VMs.
Commands
The XO server must be connected to an XCP-ng host before discovering
templates or creating VMs. xo_inspect prints selected operational metadata
without credentials or plugin configuration:
XOA_URL=wss://xoa.xcp-ng.alwaldend.com bazel_agent bazel run //infra/xcp_ng:xo_inspect
bazel_agent bazel run //infra/xcp_ng/tf:tf.plan
bazel_agent bazel run //infra/xcp_ng/tf:tf.apply
bazel_agent bazel test //infra/xcp_ng/tf:tf_tests.fmt_test //infra/xcp_ng/cmd/xo_config:xo_config_test
Formatting and helper tests run without live authentication. See Forgejo provisioning for VM prerequisites.
To register host1, store its xcpng_username and xcpng_password fields
in secrets/alwaldend.com/vault1/approles/src_infra_xcp_ng/host1, then run:
XOA_URL=wss://xoa.xcp-ng.alwaldend.com XCPNG_HOST=192.168.1.213 bazel_agent bazel run //infra/xcp_ng:xo_register_host
The command uses the XOA token to register the host and supplies its separate
host credentials through AL. It waits for a connected pool and leaves an
already connected host unchanged. Duplicate registrations are rejected.
XCPNG_INSECURE=true explicitly allows the host’s bootstrap certificate;
XOA_INSECURE=true separately controls verification of XO’s certificate.
//infra/xcp_ng:xo_import_template imports the repository-pinned image from
//third_party/org_fedora_cloud through XO’s disk-upload API. Supply
XO_TEMPLATE_SHA256 from the image’s pinned checksum, XO_TEMPLATE_SR,
XO_BASE_TEMPLATE_ID (a diskless Generic Linux BIOS template), and
XO_TEMPLATE_NAME, together with XOA_URL. The host must support QCOW2
imports. The command verifies the image before creating anything, creates an
unbooted template with only a boot disk at device 0, and verifies the final
disk layout. It rejects incomplete or conflicting prior imports for inspection.
This keeps cloud-init fresh for cloned VMs and prevents empty CD drives from
shifting the Forgejo data disks to unexpected device names.
Older XO releases, including 5.192.1, require VHD rather than QCOW2 uploads.
For those releases, convert the pinned image to dynamic VHD in task-private
scratch, verify the decoded contents against the original with qemu-img compare, and record the converter version and converted file’s SHA256.
Use //infra/xcp_ng:xo_import_prepared_template with XO_TEMPLATE_IMAGE
set to the absolute converted path, XO_TEMPLATE_FORMAT=vhd, and
XO_TEMPLATE_SHA256 set to the converted checksum. The other inputs are
the same as for the pinned-image importer.
An interrupted import can resume on an inspected empty, halted task VM by
setting XO_TEMPLATE_RESUME_ID, XO_TEMPLATE_PREVIOUS_FORMAT, and
XO_TEMPLATE_PREVIOUS_SHA256 to its exact prior identity and image marker.
Resume preserves that VM and refuses any attached disk or network interface.
2.20.1 -
XCP-ng infrastructure Specification
Purpose
Specify Xen Orchestra resource delegation, scoped authentication, and
certificate deployment owned by infra/xcp_ng. The baseline is checked-in
source at revision 550d7e79b1f5fdbc2b6017b75178471d6914082f, observed on
2026-09-08. Existing operational observations in project documentation are
historical context; this baseline does not verify current deployment, edition,
identity synchronization, or service health.
Requirements
Requirement: AppRole resource sets with named inventory
Terraform SHALL declare one Xen Orchestra resource set per entity in Vault’s
approles group. Each set SHALL contain its explicitly assigned template,
storage repository, and network resolved by names within the selected pool;
unassigned sets SHALL contain no inventory objects. Each set SHALL have a
positive integer CPU quota, defaulting to 32. These resource sets SHALL
represent delegation groups rather than new physical host pools.
Sources: resource sets, named inventory, and project contract.
Scenario: An AppRole has no assigned inventory
- WHEN an AppRole exists in Vault’s group but has no
resource_set_inventoryentry - THEN its resource set contains no assigned inventory objects and retains the configured CPU quota.
Requirement: Immutable OIDC subjects and explicit existing-VM ownership
Resource-set membership SHALL select the exact synchronized OIDC user by Vault
issuer and immutable AppRole entity UUID. AppRoles without synchronized users
SHALL be reported in approles_pending_oidc_login and have no resource-set
subjects. Existing-VM owner ACLs SHALL require exactly one VM matching the
hostname and owning AppRole tag within its named pool, and SHALL grant admin
to the owner’s synchronized user. Unknown owners, ambiguous VMs, or missing
owner synchronization SHALL fail planning. Native Terraform ACL resources
SHALL separately manage the synchronized administrators group’s pool grants.
Sources: identity contract, owner ACLs and preconditions, resource-set subjects, and administrator ACLs.
Scenario: A new AppRole has not logged in to XO
- WHEN identity discovery cannot find its synchronized OIDC subject
- THEN its resource set has no subjects and its name appears in the pending login output; an existing-VM ownership grant for it fails its precondition.
Scenario: An existing VM name does not identify a unique owned VM
- WHEN hostname and AppRole tag matching in the named pool returns zero or multiple VMs
- THEN Terraform rejects the existing-VM ownership configuration.
Requirement: Invocation-scoped tenant authentication
The XO login plugin SHALL authenticate using the calling component’s Vault
identity and export XOA_TOKEN, XOA_URL, and XOA_INSECURE=false to the
invoked process. XO HTTPS verification SHALL be mandatory for this plugin.
Session cookies and tokens SHALL remain in process memory, and normal plugin
shutdown SHALL revoke only the XO token issued by that invocation. Tenant
authentication SHALL remain separate from the infrastructure administrator
token. Forced termination or a lost callback can leave a session until XO’s
configured expiry and SHALL not be described as guaranteed revocation.
Sources: XO login contract and authentication ownership.
Scenario: A component finishes its authenticated invocation
- WHEN normal plugin shutdown follows a successful XO login
- THEN the plugin revokes its issued session using
token.deleteOwnwithout revoking unrelated sessions.
Requirement: Declarative certificate issuance and renewal
The XO appliance playbook SHALL use Certbot with Vault external account binding, retain the inspected listener certificate paths, install service-specific Vault CA trust, and configure twice-daily renewal checks. The host playbook SHALL use its packaged compatibility helper and the checksum-verified Lego release to install certificates through XAPI’s supported certificate-install command. Temporary EAB registration material SHALL be removed after use. Appliance renewal may interrupt XO management access; host renewal SHALL not stop XAPI or running VMs.
Sources: certificate deployment contract and packaged playbooks and runtime inputs.
Scenario: Renew an XCP-ng host certificate
- WHEN the renewal helper obtains a certificate different from the installed certificate
- THEN it uses
xe host-server-certificate-install, with installation retry tracked independently of issuance, while preserving running VMs.
2.20.2 -
owned-dns Specification
Purpose
Define XCP-ng infrastructure DNS management through the owner’s tf root,
including canonical declarations, scoped execution, and offline source checks
through preparation, adoption, and ongoing reconciliation.
Requirements
Requirement: Owner-local DNS configuration
The tf root SHALL consume this owner’s canonical dnsconfig.json through
the shared DNS Terraform module, preserving declared record identities and views.
DNS resources SHALL default to disabled until the authorized adoption revision
and SHALL retain enabled ownership after existing records are imported into the
owner’s state. Reconciliation against unchanged declarations and adopted state
SHALL propose no record additions, changes, replacements, or deletions.
Scenario: Inspect the preparatory configuration
- WHEN the checked-in root is evaluated with default inputs before its authorized adoption revision
- THEN it reads this owner’s declaration and disables managed DNS records
- AND the package contains the module and declaration inputs
Scenario: Adopt existing DNS records
- WHEN the authorized adoption audits competing writers, controls those identified within its observed scope, and enables the owner’s record management
- THEN the owning root imports existing records by exact provider ID into its state while preserving their declared identities and views
Scenario: Inspect adopted source defaults
- WHEN the adopted root uses its checked-in source defaults
- THEN DNS ownership remains enabled and the package retains the module and canonical declaration inputs
Scenario: Reconcile existing DNS records
- WHEN the owning root plans against its adopted state and unchanged declarations
- THEN it proposes no record additions, changes, replacements, or deletions
Requirement: Scoped DNS execution and offline checks
The DNS-only plan, show, and saved-plan apply commands SHALL select dns=1
through the repository AL flow, using src_infra_xcp_ng through its named
xcp_ng Vault authentication. They SHALL target module.dns in the existing
tf root and backend and keep secret values in injected variables. The ordinary
service wrappers SHALL retain their existing xcp_ng_tf, xoa, and Vault
environment labels and authentication behavior. Real DNS credentials and Vault
policy grants SHALL be prerequisites for operational Terraform calls. RouterOS
DNS credentials SHALL be isolated from unrelated RouterOS resources. The package
SHALL expose a format test that does not authenticate to Vault or contact DNS
providers. Successful DNS-only execution SHALL establish only the scoped DNS
result, not full service health.
Scenario: Validate the Terraform source
- WHEN the package format test executes
- THEN it checks the packaged Terraform configuration without live credentials
- AND existing non-DNS authentication and backend paths remain unchanged
Scenario: Prepare an operational Terraform invocation
- WHEN the DNS wrapper selects
dns=1 - THEN it selects DNS credential injection through the owner AppRole while preserving the existing root and backend without starting XO authentication
- AND disabled DNS resources do not imply offline provider configuration
Scenario: Review and apply only DNS resources
- WHEN the operator reviews and applies a saved plan through the DNS-only plan, show, and apply commands
- THEN the operation is limited to
module.dnsand its dependencies - AND its success does not establish the health of the other services in the root
2.20.3 - Terraform
This configuration manages one Xen Orchestra resource set per Vault AppRole and configures the installed XO OIDC plugin through a packaged JSON-RPC helper. See the project documentation for requirements and checks.
Resource-set subjects reference exact synchronized OIDC users whose OIDC
subject identifiers match Vault AppRole entity UUIDs. AppRole groups can include other
service entities, so using those groups would grant access across deployments.
Bootstrap XO’s OIDC configuration first, then log in through OIDC as each
AppRole and run the full Terraform apply. Identity discovery runs at plan
time and never creates users. AppRoles that have not logged in are listed in
approles_pending_oidc_login; their sets remain without subjects until the
next apply after login. Groups remain responsible for login entitlement and
administrative access, separately from these per-AppRole grants.
resource_set_inventory supplies pool, template, storage and network
names per AppRole. Native data sources resolve a unique pool and unique
objects within that pool. Unassigned resource sets remain empty. These inputs
have no UUID defaults; resolved IDs remain necessary for XO API operations.
existing_vms maps hostnames to an owning AppRole and pool name. Discovery
requires exactly one VM with both the hostname and AppRole tag in that pool.
The owner receives an explicit admin ACL. Resource-set membership permits
provisioning and does not transfer existing VM ownership. Missing or ambiguous
VMs, unknown AppRoles and unsynchronized OIDC users fail planning. ACL resource
keys retain the AppRole and resolved VM ID, preserving their addresses when
the same existing VMs are found through names.
Native xenorchestra_acl.pool_administrator resources manage the synchronized
administrators group’s permissions on connected pools. The read-only helper
identifies existing matching ACLs, and an import block adopts them without
recreating access. Fresh installations must bootstrap terraform_data.oidc
before the full plan so the synchronized groups exist. There is no shared
pool-view grant and the helper performs no ACL writes.
The pinned hashicorp/external provider calls the packaged helper’s read-only
oidc-identities command. XO exposes login names as email and authentication
providers in authProviders; the helper accepts only OIDC-authenticated
identities from the configured Vault issuer and indexes them by
authProviders["oidc:" + issuer].id, the Vault entity UUID.
Duplicate OIDC subjects are an error. Mutable login names and inherited group
membership do not select the ACL subject. Group discovery selects only
synchronized OIDC groups and rejects duplicate names. The provider has no
group datasource and its user datasource does not expose immutable external
subjects. API credentials remain in the injected environment.
Use this package’s dns.plan, dns.show, and dns.apply targets for the
scoped DNS adoption workflow.
These commands select dns=1 and target module.dns in this same root and
backend, using the existing src_infra_xcp_ng AppRole through named xcp_ng
Vault authentication. The ordinary service wrappers retain their XO
authentication and labels. A successful DNS-only operation verifies its scoped
DNS result; full service health requires the service’s own checks.
DNS ownership defaults to enabled after the completed record adoption. Keep that default enabled to retain the imported records.
2.20.4 - Xen Orchestra certificates
This playbook installs Debian’s Certbot package and obtains a certificate for
xoa.xcp-ng.alwaldend.com and host1.xoa.xcp-ng.alwaldend.com from the Vault
src_infra_xcp_ng_pki_server ACME role. The XCP-ng AppRole creates the
external account binding; its registration file is removed after issuance.
The target injects xoa_ssh_password from
secrets/alwaldend.com/vault1/approles/src_infra_xcp_ng/xoa for the appliance’s
xoa SSH account and sudo. Ansible uses its sshpass password mechanism;
the controller must provide sshpass and a verified SSH host key. Passwords
are runtime environment inputs and are not stored in inventory.
Run the read-only inspection target before deploying a different appliance:
bazel_agent bazel run //infra/xcp_ng/ansible:ansible.inspect
bazel_agent bazel run //infra/xcp_ng/ansible:ansible
The checked-in settings match the inspected appliance: xo-server runs as
root and listens on HTTPS with /etc/ssl/cert.pem and /etc/ssl/key.pem.
Native autoCert is disabled. The deployment preserves these listener paths.
Apply the Vault PKI role before certificate issuance.
Certbot uses standalone HTTP-01 validation. Vault must resolve both names to
the appliance and reach TCP port 80. Issuance and renewal briefly stop
xo-server to free that port, interrupting management access but not guest VMs.
The existing TLS files are preserved with .before-vault-acme suffixes before
their paths become symlinks to Certbot’s renewable files. The dedicated
xo-acme-renew.timer checks twice daily. Certbot is configured to renew the
seven-day Vault certificates with two days remaining; stop/start hooks run
when renewal is needed. Certificate keys and ACME account files remain root-only.
The playbook adds a service-specific Vault CA trust override using
NODE_EXTRA_CA_CERTS so XO can also validate Vault’s OIDC endpoint. It verifies
the appliance HTTPS endpoint against that CA after deployment.
The deployment target is //infra/xcp_ng/ansible:ansible. Building
//infra/xcp_ng/ansible:ansible_bin packages the playbook without deploying it.
XO’s native ACME implementation does not pass EAB credentials to its ACME client. Certbot supports external account binding without changing Vault’s mandatory-EAB policy.
XCP-ng host certificates
//infra/xcp_ng/ansible:ansible.host provisions a Vault ACME certificate for
host1.xcp-ng.alwaldend.com and xcp-ng.alwaldend.com. Inspect a different
host with //infra/xcp_ng/ansible:ansible.inspect_host before deployment.
The host must serve /opt/xensource/www/.well-known/acme-challenge through
HTTP or an HTTP-to-HTTPS redirect; the inspection verifies and cleans up a
public probe file. This host supports that path without changing XAPI settings.
XCP-ng’s Python 3.6 cannot run the current Ansible modules. The playbook uses
Ansible’s script transport for a Python 3.6-compatible helper, without adding
packages to dom0. The helper downloads the immutable Lego release declared in
third_party/com_github_go_acme_lego_bin/binary_toolchain.json, verifies its
checksum, and installs it under root-only /etc/xcp-ng-acme.
The initial EAB is temporary. Only the ACME account remains for unattended
renewal; no Vault token is retained on the host. The client requests RSA4096
keys to match the Vault role. xcp-ng-acme-renew.timer runs twice daily and
uses XAPI’s supported xe host-server-certificate-install command when the
issued certificate differs from the installed certificate. Installation is
retried independently of issuance. Renewal does not stop XAPI or running VMs.
The final deployment verifies HTTPS and enables the timer.
Set an absolute task-private TMPDIR for controller registration scratch.
Ansible removes the temporary registration script after execution. The
bootstrap tag updates the helper without ordering a certificate.
OpenID Connect plugin
The XO playbook installs the official xo-server-auth-oidc 0.4.0 plugin with
pinned, checksum-verified upstream files and isolated dependencies. This
version supports Vault group synchronization while remaining compatible with
the installed XO core. Ansible verifies the plugin before restarting XO;
Terraform configures it and reconciles group ACLs through the API.
SSH connection reuse keeps deployment within the appliance’s existing UFW limit of six new SSH connections per 30 seconds. No firewall exception is required.
2.21.1 -
Infrastructure Yandex Cloud
Purpose
Describe organization-level Yandex Cloud folder provisioning derived from Vault
AppRole identities. The direct infra/yandex_cloud owner currently contains one
concrete organization package, org1, covered here. This baseline does not
assert that the cloud organization or its folders were inspected live.
Baseline source revision: 550d7e79b1f5fdbc2b6017b75178471d6914082f.
Observation date: 2026-09-08. Sources are linked in full; no excerpts are used.
Sources: top-level documentation, organization package, organization targets, Terraform packaging, folder derivation, provider configuration, and credential injection.
Requirements
Requirement: Keep organization configuration under its owner
The Yandex Cloud tree SHALL expose its documentation through the infrastructure
documentation boundary and keep org1’s AL configuration and Terraform package
under infra/yandex_cloud/org1.
Scenario: Discover the configured organization
- WHEN a contributor follows the Yandex Cloud package’s child documentation
- THEN
org1identifies the current organization configuration - AND its Terraform wrapper uses
//infra/yandex_cloud/org1:al
Requirement: Derive folders from Vault AppRole membership
Terraform SHALL read the Vault identity group named approles, resolve its
member entities, and instantiate the shared yc_folder module once per entity
name. Folder names SHALL replace underscores with hyphens, and secret references
SHALL use the corresponding yandex.cloud/org1/folders/ path.
Scenario: Map an AppRole identity to a cloud folder
- WHEN the
approlesgroup contains an entity namedexample_service - THEN the folder module receives the name
example-service - AND its secret reference is
yandex.cloud/org1/folders/example-service - AND its cloud identifier comes from the configured
cloud_idvariable
Requirement: Package Terraform with declared modules and injected environment
The Terraform Bazel package SHALL include its provider lock, shared folder and
backend modules, and Vault backend and injector tools. Its operational wrapper
SHALL select the Terraform plugin and the default_default Vault environment;
the package SHALL also expose the configured Terraform test map.
Scenario: Resolve the organization Terraform entry point
- WHEN the organization’s Terraform wrapper is assembled
- THEN its runfiles contain the declared local modules and provider lock
- AND runtime authentication is supplied by the owning AL/Vault flow
2.21.2.1 - Tf
3 - Tools
This tree contains developer tools and reusable Bazel rule modules. All tracked
content follows the repository’s public-source policy. Standalone rules_*
modules retain their own Bzlmod names and public build APIs, with documentation
on the main repository site. They do not own separate landing sites.
Requirements
- Bazel targets MUST use repository-internal visibility except for standalone Bazel rule modules and toolchain types whose owner explicitly exposes a public build API.
- Tool artifacts MUST NOT be published as first-party product artifacts.
- Standalone Bazel rule modules MAY publish their reusable build APIs through their explicit module release workflow.
- Production build targets MAY consume the public build APIs of standalone Bazel rule modules and toolchains. Other tool targets MUST NOT be dependencies of production build targets.
- Tool targets intended for repository-wide use MUST use
visibility = ["//:__subpackages__"]. - Tool targets MAY be used in tests and explicit source-generation/update targets.
An explicit source-generation/update target is a developer workflow, not part
of the production build graph. It may depend on a tool from this tree and use
write_source_file to update a checked-in source artifact. Normal production
and documentation targets must consume that checked-in artifact directly;
they must not depend on the generator, its tool, or an action-generated copy.
3.1 -
Bazel session cleanup
The repository’s .codex/config.toml queues asynchronous Bazel expunge when a
Codex session ends. Review and trust the hook with /hooks in Codex; project
hooks do not run until trusted. A completed assistant turn does not trigger
cleanup.
If /hooks is empty in a linked Git worktree, check the primary checkout’s
.codex/config.toml. In Codex CLI 0.153.4, observed on 2026-09-06, config/read
returned the primary checkout’s configuration even though its project-layer
metadata named the linked worktree. That primary configuration had no hooks,
so hooks/list returned an empty list. The exact worktree TOML listed both
hooks in an isolated normal checkout; separate user-config probes also accepted
both TOML and JSON. Changing formats is therefore not an established fix.
Merge the hook configuration and update the primary checkout, then start a new
CLI session and check /hooks to trust it. Recheck configuration resolution
after upgrading Codex; this is an observed version-specific behavior, not a
guarantee for every release.
The shell hook launches a transient user systemd service, which runs
bazel --noblock_for_lock clean --config=agent --expunge_async in each built,
tracked Bazel workspace in the linked Git worktree. It skips the primary
checkout, submodules, workspaces without a bazel-out symlink, and busy Bazel
instances. Source files, Git worktrees, and shared disk caches are preserved.
Nested workspaces are discovered from tracked MODULE.bazel, WORKSPACE, and
WORKSPACE.bazel files. Custom convenience-symlink prefixes are not supported.
This Linux hook requires Bash, Git, Bazelisk’s bazel on PATH, and a running
user systemd manager. The service inherits PATH, not the session’s full
environment. KillMode=process allows Bazel’s asynchronous deletion child to
finish after the service exits. Failures appear in the user journal; failure
to enqueue is reported by Codex as a hook failure. There is no automatic retry
or orphan-cache sweep. Concurrent sessions sharing a worktree may lose warm
build state when one ends; the Bazel lock protects running builds, not idle
sessions. Resuming a cleaned session rebuilds its outputs normally.
The hook uses shell because it must run from a fresh checkout without first
building a helper. It invokes Bazel directly to supply the startup lock flag,
which bazel_agent does not currently accept. Tests replace Git, systemd, and
Bazel with fixtures and never clean real caches.
Codex’s SessionEnd hook is synchronous even with async: true and permits
at most three seconds. Systemd owns the longer-running cleanup; the hook does
not wait for it. See the Codex hook documentation.
3.2 -
Gradle wrapper
//tools/gradle:gradle-wrapper runs the pinned Gradle distribution from
third_party/net_gradle_gradle with the Java runtime selected by the existing
rules_java toolchain. It does not download anything at run time.
bazel_agent bazel run //tools/gradle:gradle-wrapper -- --version
Gradle caches remain under ignored out/gradle/. Set GRADLE_CACHE_ROOT to
redirect them for a task.
3.3 - Android
3.4 - Android cmdtools
3.5 - Ansible
ansible_lint runs ansible-lint from Bazel-managed Python
dependencies. A Go test runner exposes the CLI binaries under their
hyphenated names, configures writable Ansible paths, and invokes the
linter against workspace-relative sources.
Molecule is not integrated yet. The likely path is to add Molecule to these Python requirements and invoke it through a Bazel-native Go runner, but practical scenarios require choosing and provisioning a Molecule driver before any scenarios can run.
3.7 - Bazel configs
Harbor
Targets that pull from the private Harbor registry are disabled by default so
repository-wide builds work while Harbor is unavailable. Enable them with
--config=harbor when the registry is reachable.
3.8 - Bazel shell worker
3.8.1 - Bzl
3.8.1.1 - al_genrule
al_genrule
load("@com_alwaldend_src//tools/shell_worker/main/bzl:al_genrule.bzl", "al_genrule")
al_genrule(test, executable, **kwargs)
Generate al_genrule target
PARAMETERS
| Name | Description | Default Value |
|---|---|---|
| test | If set, use al_genrule_test | False |
| executable | if set, use al_genrule_executable | False |
| kwargs | kwargs for the rule | none |
3.8.1.2 - al_genrule_rule
al_genrule_executable
load("@com_alwaldend_src//tools/shell_worker/main/bzl:al_genrule_rule.bzl", "al_genrule_executable")
al_genrule_executable(name, srcs, data, outs, cmd, set_flags, shell, tools, worker)
Build executable using shell worker
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| srcs | Sources, will not be added to runfiles | List of labels | optional | [] |
| data | Data, will be added to runfiles | List of labels | optional | [] |
| outs | Outputs | List of labels; nonconfigurable | required | |
| cmd | Script to execute | String | required | |
| set_flags | set flags | List of strings | optional | ["-eux"] |
| shell | shell to use | String | optional | "/bin/sh" |
| tools | Tools, will be added to runfiles | List of labels | optional | [] |
| worker | Worker binary | Label | optional | "@com_alwaldend_src//tools/shell_worker" |
al_genrule_regular
load("@com_alwaldend_src//tools/shell_worker/main/bzl:al_genrule_rule.bzl", "al_genrule_regular")
al_genrule_regular(name, srcs, data, outs, cmd, set_flags, shell, tools, worker)
Build shell worker rule
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| srcs | Sources, will not be added to runfiles | List of labels | optional | [] |
| data | Data, will be added to runfiles | List of labels | optional | [] |
| outs | Outputs | List of labels; nonconfigurable | required | |
| cmd | Script to execute | String | required | |
| set_flags | set flags | List of strings | optional | ["-eux"] |
| shell | shell to use | String | optional | "/bin/sh" |
| tools | Tools, will be added to runfiles | List of labels | optional | [] |
| worker | Worker binary | Label | optional | "@com_alwaldend_src//tools/shell_worker" |
al_genrule_test
load("@com_alwaldend_src//tools/shell_worker/main/bzl:al_genrule_rule.bzl", "al_genrule_test")
al_genrule_test(name, srcs, data, outs, cmd, set_flags, shell, tools, worker)
Test using shell worker
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| srcs | Sources, will not be added to runfiles | List of labels | optional | [] |
| data | Data, will be added to runfiles | List of labels | optional | [] |
| outs | Outputs | List of labels; nonconfigurable | required | |
| cmd | Script to execute | String | required | |
| set_flags | set flags | List of strings | optional | ["-eux"] |
| shell | shell to use | String | optional | "/bin/sh" |
| tools | Tools, will be added to runfiles | List of labels | optional | [] |
| worker | Worker binary | Label | optional | "@com_alwaldend_src//tools/shell_worker" |
3.9 - Bazelrc
Usage
bazel run //tools/bazelrc:preset.update
The agent profile must not propagate ambient TEMP, TMP, or TMPDIR
values into repository rules, actions, host actions, or tests. Those execution
contexts use Bazel-managed temporary storage; host tools own any explicit
task/run scratch they require.
Agent tests use Bazel’s normal result cache. Tests that inspect undeclared
workspace files must opt out with the no-cache tag.
Agent commands use Bazel’s default lockfile update mode. Review and commit
generated lockfile changes with dependency changes. CI retains strict lockfile
checking; use --lockfile_mode=error for an explicit reproducibility check.
In the root workspace, lint actions fail on violations. Their failure setting
is identical across normal and lint configurations to preserve the analysis
cache when switching modes. --config=lint enables the linter aspects and
requests only lint reports and skill validation, not ordinary target outputs.
Links
3.10 - Black
3.14 - Bzl
3.14.1 - Bzl
3.14.1.1 - al_alias_map
al_alias_map
load("@com_alwaldend_src//tools/bzl/main/bzl:al_alias_map.bzl", "al_alias_map")
al_alias_map(aliases, visibility)
Generate aliases from an alias map
PARAMETERS
| Name | Description | Default Value |
|---|---|---|
| aliases | alias map, keys are names, values are alias arguments | none |
| visibility | default visibility | ["//:__subpackages__"] |
3.14.1.2 - al_bzl_generate_repository
al_bzl_generate_repository
load("@com_alwaldend_src//tools/bzl/main/bzl:al_bzl_generate_repository.bzl", "al_bzl_generate_repository")
al_bzl_generate_repository(name, files, repo_mapping)
Generate a repository
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this repository. | Name | required | |
| files | Files to generate, keys are paths, values are file contents | Dictionary: String -> String | optional | {} |
| repo_mapping | In WORKSPACE context only: a dictionary from local repository name to global repository name. This allows controls over workspace dependency resolution for dependencies of this repository.For example, an entry "@foo": "@bar" declares that, for any time this repository depends on @foo (such as a dependency on @foo//some:target, it should actually resolve that dependency within globally-declared @bar (@bar//some:target).This attribute is not supported in MODULE.bazel context (when invoking a repository rule inside a module extension’s implementation function). |
Dictionary: String -> String | optional |
3.14.1.3 - al_bzl_library_map
al_bzl_library_map
load("@com_alwaldend_src//tools/bzl/main/bzl:al_bzl_library_map.bzl", "al_bzl_library_map")
al_bzl_library_map(name, visibility, libs, deps, **kwargs)
Create bzl_library targets from a map
PARAMETERS
| Name | Description | Default Value |
|---|---|---|
| name | combined bzl_library target name | none |
| visibility | - |
None |
| libs | bzl_library names | {} |
| deps | other al_bzl_library_map targets | [] |
| kwargs | bzl_library kwargs | none |
3.14.1.4 - al_bzl_target_doc
al_bzl_target_doc
load("@com_alwaldend_src//tools/bzl/main/bzl:al_bzl_target_doc.bzl", "al_bzl_target_doc")
al_bzl_target_doc(name, visibility, subpackages)
Document bazel targets
PARAMETERS
| Name | Description | Default Value |
|---|---|---|
| name | target name | none |
| visibility | - |
none |
| subpackages | list of subpackages | [] |
3.14.1.5 - al_genquery_write_to_source_file
al_genquery_write_to_source_file
load("@com_alwaldend_src//tools/bzl/main/bzl:al_genquery_write_to_source_file.bzl", "al_genquery_write_to_source_file")
al_genquery_write_to_source_file(name, expression, scope, var_name, out_file)
Write genquery result to a bzl file
Example:
al_genquery_write_to_source_file(
name = "al_bzl_libs",
expression = """
filter(
"^//",
attr(
"srcs",
".{3,}",
kind(
"bzl_library",
deps("//bzl")
)
)
)
""",
out_file = "al_bzl_libs.bzl",
scope = ["//bzl"],
var_name = "AL_BZL_LIBS",
)
PARAMETERS
| Name | Description | Default Value |
|---|---|---|
| name | name prefix | none |
| expression | genquery expression | none |
| scope | genquery scope | none |
| var_name | variable name in the generated .bzl file | none |
| out_file | output bzl file | none |
3.15 - Bzlenv
Rules to create a bazel environment which functions similar to venv
Features
- Adds bazel-built tools to
${PATH} - Exports .env
Usage
Create env and activate:
. "$(bazel run //tools/bzlenv)"
Activate existing env:
. .bzlenv/bin/activate
Deactivate env:
bzlenv_deactivate
3.15.1 - Bzl
3.15.1.1 - al_bzlenv_binary
al_bzlenv_binary
load("@com_alwaldend_src//tools/bzlenv/main/bzl:al_bzlenv_binary.bzl", "al_bzlenv_binary")
al_bzlenv_binary(name, activate, tools)
Dev shell binary
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| activate | Activation script | Label | optional | "@com_alwaldend_src//tools/bzlenv/main/sh:activate" |
| tools | Tools, keys are tool names, values are tool labels | Dictionary: String -> Label | optional | {} |
3.16 - Cc
//:refresh_compile_commands uses the pinned Hedron extractor. Its archive is
declared through use_repo_rule and fetched when the extractor’s package is
loaded, rather than during module resolution. LLVM toolchain registration
remains automatic.
Links
3.19.1 - Gen gossip key
3.20 - Dart Sass
Dart Sass binary toolchain, used by Hugo
for toCSS "dartsass" builds.
3.22 - Drawio
Links
Reproducible SVGs
drawio_svg in defs.bzl renders named pages from a .drawio file with the
pinned Drawio web exporter and the existing pinned Chrome-for-Testing browser.
The extraction action unpacks the web application from the Drawio AppImage;
rendering uses a small Puppeteer bridge for its export messages. Neither action
uses a host display server or accesses the network. JavaScript keeps this
adapter close to Drawio’s browser API and the existing Puppeteer dependency.
Use the rule from an explicit source-update target with write_source_files,
as in //infra/arch:update. Normal documentation consumes the maintained SVGs,
not the rendering tool. The generated freshness tests catch stale output.
Exports use a light theme with an opaque white canvas, keeping labels and connectors readable in both light and dark documentation themes and standalone image viewers. The renderer adds this canvas on every export.
Chrome’s inner sandbox is disabled because it cannot nest within the Bazel Linux sandbox used for these actions. The Bazel sandbox remains enabled; requests outside local files and embedded data are rejected. The renderer is intended for checked-in, reviewed diagram sources and propagates export failures.
The repeat-render test checks byte equality, including stable SVG identifiers.
Rendering uses only the declared Liberation Fonts 2.1.5
through an isolated Fontconfig configuration. Helvetica/Arial map to Liberation
Sans, Times to Liberation Serif, and Courier to Liberation Mono. The fonts are
licensed under the SIL Open Font License 1.1; their archive retains LICENSE.
3.22.1 - Bzl
3.22.1.1 - al_drawio_run_binary
al_drawio_run_binary
load("@com_alwaldend_src//tools/drawio/main/bzl:al_drawio_run_binary.bzl", "al_drawio_run_binary")
al_drawio_run_binary(name, srcs, out, arguments, cmd_timeout)
Run drawio a a build action
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| srcs | Sources | List of labels | optional | [] |
| out | Output | Label; nonconfigurable | required | |
| arguments | Arguments, location statements are expanded | List of strings | required | |
| cmd_timeout | Drawio command timeout | String | optional | "1m" |
3.22.1.2 - al_drawio_toolchain
al_drawio_toolchain
load("@com_alwaldend_src//tools/drawio/main/bzl:al_drawio_toolchain.bzl", "al_drawio_toolchain")
al_drawio_toolchain(name, drawio)
Drawio toolchain
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| drawio | Drawio binary | Label | required |
3.23 - F-Droid
Pinned fdroidserver environment for local F-Droid builds. The wrapper
provisions an isolated Python virtualenv and delegates to fdroid. Use
tools/gradle/gradle-wrapper for the Android app’s Gradle build; this tool
only drives F-Droid metadata and local builds.
Usage
tools/fdroid/fdroid-wrapper <fdroid-subcommand>
Run from an F-Droid data directory containing config.yml and metadata/.
Caches go under the workspace’s ignored out/ tree.
3.24 - File installer
3.26 - Flake8
3.30 - Gazelle
//tools/gazelle:gazelle runs the repository’s Gazelle language plugins.
Repository-wide directives remain in root BUILD.bazel, where Gazelle discovers
them for all packages. Root //:gazelle and //:gazelle_bin remain compatibility
entry points.
//tools/gazelle:gazelle_python_manifest.update refreshes root
gazelle_python.yaml; //tools/gazelle:gazelle_python_manifest.test validates
its integrity against root requirements.txt. Keeping the manifest at the
repository root preserves Python dependency discovery in every package.
3.32 - Git
3.32.1 - Bzl
3.32.1.1 - al_git_binary
al_git_binary
load("@com_alwaldend_src//tools/git/main/bzl:al_git_binary.bzl", "al_git_binary")
al_git_binary(name, arguments)
Run git binary
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| arguments | Git arguments (templated) | List of strings | optional | [] |
3.32.1.2 - al_git_changelog
al_git_changelog
load("@com_alwaldend_src//tools/git/main/bzl:al_git_changelog.bzl", "al_git_changelog")
al_git_changelog(name, visibility, git_binary, subpackages)
Create changelog target
PARAMETERS
| Name | Description | Default Value |
|---|---|---|
| name | target name prefix | none |
| visibility | visibility | none |
| git_binary | - |
"@git//:git" |
| subpackages | subpackages | [] |
3.32.1.3 - al_git_current_state
3.32.1.4 - al_git_extension
al_git_extension
al_git_extension = use_extension("@com_alwaldend_src//tools/git/main/bzl:al_git_extension.bzl", "al_git_extension")
al_git_extension.local_git(name)
Create git repos
TAG CLASSES
local_git
Attributes
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | Name | Name | required |
3.32.1.5 - al_git_info_file
al_git_info_file
load("@com_alwaldend_src//tools/git/main/bzl:al_git_info_file.bzl", "al_git_info_file")
al_git_info_file(name, git_state, git_tool, timeout)
Generate git info file
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| git_state | Files that should invalidate the cache on new commit | List of labels | optional | [] |
| git_tool | Git tool to use | Label | optional | "@com_alwaldend_src//tools/git/main/go" |
| timeout | Timeout in seconds | Integer | optional | 60 |
3.32.1.6 - al_git_repo
al_git_repo
load("@com_alwaldend_src//tools/git/main/bzl:al_git_repo.bzl", "al_git_repo")
al_git_repo(name, repo_mapping)
Git repo
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this repository. | Name | required | |
| repo_mapping | In WORKSPACE context only: a dictionary from local repository name to global repository name. This allows controls over workspace dependency resolution for dependencies of this repository.For example, an entry "@foo": "@bar" declares that, for any time this repository depends on @foo (such as a dependency on @foo//some:target, it should actually resolve that dependency within globally-declared @bar (@bar//some:target).This attribute is not supported in MODULE.bazel context (when invoking a repository rule inside a module extension’s implementation function). |
Dictionary: String -> String | optional |
3.32.1.7 - al_git_resolved_toolchain
al_git_resolved_toolchain
load("@com_alwaldend_src//tools/git/main/bzl:al_git_resolved_toolchain.bzl", "al_git_resolved_toolchain")
al_git_resolved_toolchain(name)
Resolved git toolchain
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required |
3.32.1.8 - al_git_run_binary
al_git_run_binary
load("@com_alwaldend_src//tools/git/main/bzl:al_git_run_binary.bzl", "al_git_run_binary")
al_git_run_binary(name, srcs, outs, arguments, git)
Run a git binary as a build action
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| srcs | Files to be made available | List of labels | optional | [] |
| outs | Outputs | List of labels; nonconfigurable | required | |
| arguments | Arguments (Location is expanded) | List of strings | optional | [] |
| git | Git binary | Label | required |
3.32.1.9 - al_git_toolchain
al_git_toolchain
load("@com_alwaldend_src//tools/git/main/bzl:al_git_toolchain.bzl", "al_git_toolchain")
al_git_toolchain(name, git_dir, git_path, git_root, invalidation)
Local git toolchain
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| git_dir | Git directory path | String | required | |
| git_path | Git binary path | String | required | |
| git_root | Git workspace path | String | required | |
| invalidation | Files that should invalidate git actions | List of labels | optional | [] |
3.32.2 - Proto
3.32.2.1 - contracts
Java
load("@rules_java//java:defs.bzl", "java_library")
java_library(
name = "name",
deps = [
"@com_alwaldend_src//tools/git/main/proto/contracts:contracts_java_library",
],
)
Golang
load("@rules_go//go:def.bzl", "go_library")
go_library(
name = "name",
deps = [
"@com_alwaldend_src//tools/git/main/proto/contracts:contracts",
],
)
Proto
syntax = "proto3";
package git;
option go_package = "git.alwaldend.com/alwaldend/src/tools/git/main/proto/contracts";
message GitSignature {
string name = 1;
string email = 2;
int64 when = 3;
}
message GitCommit {
string hash = 1;
GitSignature author = 2;
GitSignature committer = 3;
string merge_tag = 4;
string pgp_signature = 5;
string message = 6;
repeated string tags = 7;
map<string, bool> changed_files = 8;
}
message GitTagAnnotated {
GitSignature tagger = 1;
string hash = 2;
string message = 3;
string pgp_signature = 4;
}
message GitTag {
string name = 1;
string target = 2;
GitTagAnnotated annotated = 3;
}
message GitRemote {
string name = 1;
repeated string urls = 2;
}
message GitInfo {
map<string, GitCommit> commits = 1;
repeated string commits_order = 2;
map<string, GitTag> tags = 3;
repeated GitRemote remotes = 4;
}
3.33 - Git filter repo
3.36 - Go
3.36.1 - Bzl
3.36.1.1 - al_go_repository
al_go_repository
al_go_repository = use_extension("@com_alwaldend_src//tools/go/main/bzl:al_go_repository.bzl", "al_go_repository")
al_go_repository.go_repository(name, importpath, sum, version)
Extension wrapper around go_repository (useless because you can just call use_repo_rule)
TAG CLASSES
go_repository
Attributes
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | Name | Name | required | |
| importpath | importpath | String | required | |
| sum | checksum | String | optional | "" |
| version | - | String | required |
3.37 - go_mod
go_mod
go_mod keeps every tracked go.mod file on the Go version configured in
tools/go_mod/cmd/go_mod/BUILD.bazel. It discovers files with Git, so ignored
scratch files are excluded.
Update all module files:
bazel run //tools/go_mod/cmd/go_mod:update
Check without writing:
bazel test //tools/go_mod/cmd/go_mod:test
The check target is part of //:repo_quality_test.
3.38 - Gzip
3.38.1 - Bzl
3.38.1.1 - al_gzip_extension
al_gzip_extension
al_gzip_extension = use_extension("@com_alwaldend_src//tools/gzip/main/bzl:al_gzip_extension.bzl", "al_gzip_extension")
al_gzip_extension.download(name, integrity, url)
Extension for gzip repos
TAG CLASSES
download
Attributes
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | Name | Name | required | |
| integrity | Integrity | String | optional | "" |
| url | Url | String | required |
3.38.1.2 - al_gzip_repo
al_gzip_repo
load("@com_alwaldend_src//tools/gzip/main/bzl:al_gzip_repo.bzl", "al_gzip_repo")
al_gzip_repo(name, integrity, repo_mapping, url)
Gzip repo
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this repository. | Name | required | |
| integrity | Integrity | String | optional | "" |
| repo_mapping | In WORKSPACE context only: a dictionary from local repository name to global repository name. This allows controls over workspace dependency resolution for dependencies of this repository.For example, an entry "@foo": "@bar" declares that, for any time this repository depends on @foo (such as a dependency on @foo//some:target, it should actually resolve that dependency within globally-declared @bar (@bar//some:target).This attribute is not supported in MODULE.bazel context (when invoking a repository rule inside a module extension’s implementation function). |
Dictionary: String -> String | optional | |
| url | Url | String | required |
3.39 - Harbor
Links
- Site: https://goharbor.io/
- Releases: https://github.com/goharbor/harbor-cli/releases
3.40.1 - Bzl
3.40.1.1 - al_helm_binary
al_helm_binary
load("@com_alwaldend_src//tools/helm/main/bzl:al_helm_binary.bzl", "al_helm_binary")
al_helm_binary(name, data, arguments, cd)
Helm binary
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| data | Helm chart | List of labels | optional | [] |
| arguments | Helm arguments | List of strings | optional | [] |
| cd | Cd to a directory before running bazel | String | optional | "." |
3.40.1.2 - al_helm_chart
al_helm_chart
load("@com_alwaldend_src//tools/helm/main/bzl:al_helm_chart.bzl", "al_helm_chart")
al_helm_chart(name, deps, package, source)
Helm chart
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| deps | Helm chart deps | List of labels | optional | [] |
| package | Helm chart package | Label | optional | None |
| source | Helm chart source | Label | optional | None |
3.40.1.3 - al_helm_chart_info
AlHelmChartInfo
load("@com_alwaldend_src//tools/helm/main/bzl:al_helm_chart_info.bzl", "AlHelmChartInfo")
AlHelmChartInfo(source, package, deps, files_info)
Information about a helm chart
FIELDS
| Name | Description |
|---|---|
| source | Chart sources (PackageFilegroupInfo, optional) |
| package | Chart package (tgz file) |
| deps | Chart deps (depset of AlHelmChartInfo) |
| files_info | Chart file structure (PackageFilesInfo) |
3.40.1.4 - al_helm_chart_lock
al_helm_chart_lock
load("@com_alwaldend_src//tools/helm/main/bzl:al_helm_chart_lock.bzl", "al_helm_chart_lock")
al_helm_chart_lock(name, lock, lock_out)
Generate targets for a chart lock
PARAMETERS
| Name | Description | Default Value |
|---|---|---|
| name | name | none |
| lock | lock label | none |
| lock_out | parsed lock filename | none |
3.40.1.5 - al_helm_cmds
3.40.1.6 - al_helm_deps
al_helm_deps
al_helm_deps = use_extension("@com_alwaldend_src//tools/helm/main/bzl:al_helm_deps.bzl", "al_helm_deps")
al_helm_deps.from_locks(name, integrity, locks)
Extension to download helm dependencies
TAG CLASSES
from_locks
Attributes
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | Repo name | Name | required | |
| integrity | Intergrity for locks, keys are packages, values are integrity | Dictionary: String -> String | optional | {} |
| locks | Helm lock labels | List of labels | optional | [] |
3.40.1.7 - al_helm_deps_repo
al_helm_deps_repo
load("@com_alwaldend_src//tools/helm/main/bzl:al_helm_deps_repo.bzl", "al_helm_deps_repo")
al_helm_deps_repo(name, integrity, locks, repo_mapping)
Helm deps repo
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this repository. | Name | required | |
| integrity | Intergrity for locks, keys are packages, values are integrity | Dictionary: String -> String | optional | {} |
| locks | Lock labels to parse | List of labels | optional | [] |
| repo_mapping | In WORKSPACE context only: a dictionary from local repository name to global repository name. This allows controls over workspace dependency resolution for dependencies of this repository.For example, an entry "@foo": "@bar" declares that, for any time this repository depends on @foo (such as a dependency on @foo//some:target, it should actually resolve that dependency within globally-declared @bar (@bar//some:target).This attribute is not supported in MODULE.bazel context (when invoking a repository rule inside a module extension’s implementation function). |
Dictionary: String -> String | optional |
3.40.1.8 - al_helm_toolchain
al_helm_toolchain
load("@com_alwaldend_src//tools/helm/main/bzl:al_helm_toolchain.bzl", "al_helm_toolchain")
al_helm_toolchain(name, helm)
Helm toolchain
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| helm | Helm binary | Label | required |
3.41 - Hermes install
Links
Usage
Run the pinned Hermes Agent install script:
bazel run //tools/hermes_install
3.42 - Hooks
The hook installer resolves the repository’s effective hooks directory through
Git. This supports linked worktrees and repositories that configure
core.hooksPath.
The installed pre-commit hook requires bazel_agent. Bootstrap it before
installing the hook:
bazel run --config=agent //projects/bazel_agent:install
Install or update the checked-in hooks:
bazel_agent bazel run //:write_git_hooks
Verify that every hook is current and executable without changing it:
bazel_agent bazel run //:write_git_hooks -- test
3.43 - Http server
3.43.1 - Bzl
3.43.1.1 - al_http_server_binary
al_http_server_binary
load("@com_alwaldend_src//tools/http_server/main/bzl:al_http_server_binary.bzl", "al_http_server_binary")
al_http_server_binary(name, srcs, arguments)
Run a http server
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| srcs | Files to symlink | List of labels | optional | [] |
| arguments | Arguments | List of strings | optional | [] |
3.44 - Hugo
Hugo binary toolchain for the repository. Build rules live in
rules_hugo.
3.45 - Install file
3.45.1 - Bzl
3.45.1.1 - al_install_file
al_install_file
load("@com_alwaldend_src//tools/install_file/main/bzl:al_install_file.bzl", "al_install_file")
al_install_file(name, args, install_file_label, visibility, **py_binary_kwargs)
Create py_binary target to install file
PARAMETERS
3.46 - Isort
3.47 - Js
Repository JavaScript tooling dependencies belong to the pnpm workspace in
tools/. Its package.json and pnpm-lock.yaml own their requested and resolved
versions. //tools:node_modules owns the Bazel package store and links; loading
the repository root package does not load the npm extension’s generated rules.
Run pnpm with //tools/pnpm, passing --dir with the absolute path to tools/
for dependency updates. Keep lifecycle scripts disabled (--ignore-scripts)
when updating the lockfile.
3.48 - Kt
3.50 - Lua
3.50.1 - Bzl
3.50.1.1 - al_lua_library
al_lua_library
load("@com_alwaldend_src//tools/lua/main/bzl:al_lua_library.bzl", "al_lua_library")
al_lua_library(name, srcs, check, stylua_config_label, stylua_label, pkg_kwargs, visibility)
Generate targets for a lua library
PARAMETERS
3.51 - Make install
3.51.1 - Bzl
3.51.1.1 - al_make_install
al_make_install
load("@com_alwaldend_src//tools/make_install/main/bzl:al_make_install.bzl", "al_make_install")
al_make_install(name, srcs)
Create the make install executable and a filegroup
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| srcs | Make install filegroups | List of labels | optional | [] |
3.51.1.2 - al_make_install_binary
al_make_install_binary
load("@com_alwaldend_src//tools/make_install/main/bzl:al_make_install_binary.bzl", "al_make_install_binary")
al_make_install_binary(name, src, arguments)
Create a binary target for a make install
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| src | Make install target | Label | required | |
| arguments | Arugments for the executable | List of strings | optional | [] |
3.51.1.3 - al_make_install_filegroup
al_make_install_filegroup
load("@com_alwaldend_src//tools/make_install/main/bzl:al_make_install_filegroup.bzl", "al_make_install_filegroup")
al_make_install_filegroup(name, deps, srcs, diff_args, install_args, install_dir, pkg_prefix)
Create a make install filegroup
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| deps | Deps | List of labels | optional | [] |
| srcs | Sources to install | List of labels | optional | [] |
| diff_args | Diff args | List of strings | optional | [] |
| install_args | Install args | List of strings | optional | ["--compare", "-D"] |
| install_dir | Install directory | String | optional | "${HOME}" |
| pkg_prefix | Ignore that prefix for srcs | String | required |
3.51.1.4 - al_make_install_filegroup_info
AlMakeInstallFilegroupInfo
load("@com_alwaldend_src//tools/make_install/main/bzl:al_make_install_filegroup_info.bzl", "AlMakeInstallFilegroupInfo")
AlMakeInstallFilegroupInfo(srcs, deps, install_dir, origin, install_args, diff_args, pkg_prefix)
Describe install info for a single filegrop
FIELDS
3.52 - Maven Install Gradle Converter
Converts rules_jvm_external maven_install.json lock files into Gradle
version catalogs and dependency verification metadata so Bazel-built Android
apps can maintain the parallel Gradle build required for F-Droid.
Usage
Use the al_gradle_lock Starlark macro from
main/bzl/gradle_lock.bzl in your app’s gradle/BUILD.bazel:
load("//tools/maven_install_gradle_converter:defs.bzl", "al_gradle_lock")
al_gradle_lock(
name = "update",
lock_file = "//projects/<app>:maven_lock.json",
tool = "//tools/maven_install_gradle_converter/cmd/gradle_lock_gen",
)
Run bazel run :update_toml_write to regenerate the checked-in version
catalog. The corresponding *_write_test target fails when it goes stale.
Gradle owns verification-metadata.xml because it must record the plugin
classpath in addition to the Bazel lock. Regenerate it with:
projects/<app>/../../tools/gradle/gradle-wrapper --project-cache-dir out/gradle-wrapper/project-cache --write-verification-metadata sha256
3.53 - Md
3.53.1 - Bzl
3.53.1.1 - al_md_data
al_md_data
load("@com_alwaldend_src//tools/md/main/bzl:al_md_data.bzl", "al_md_data")
al_md_data(name, srcs, deps, **kwargs)
Markdown data backed by a filegroup
Targets:
- ${name}: filegroup
PARAMETERS
| Name | Description | Default Value |
|---|---|---|
| name | filegroup name | none |
| srcs | markdown files | none |
| deps | deps | [] |
| kwargs | filegroup kwargs | none |
3.54 - Mermaid
This package exposes the Mermaid CLI as a repository-wide Bazel tool. Bazel provisions the pinned Node toolchain, JavaScript dependency graph, Mermaid CLI, and Chrome-for-Testing browser used by Puppeteer. Rendering runs as a Bazel target or action; it does not use a host browser or download one during an npm lifecycle hook.
The JavaScript launcher runs from Bazel’s output tree. Pass absolute paths when rendering source-tree files directly:
repo_root="$PWD"
bazel_agent bazel run //tools/mermaid:mmdc -- \
-i "${repo_root}/path/to/diagram.mmd" \
-o "${repo_root}/path/to/diagram.svg"
Prefer a mermaid_svg action plus write_source_file for maintained diagrams;
those targets use declared Bazel paths and need no absolute-path handling.
3.55 - Minisign
3.56 - Mypy
3.61 - Oci
3.63 - Opencode
Links
- Site: https://opencode.ai/
- Repo: https://github.com/anomalyco/opencode
- Yandex cloud intergration: https://yandex.cloud/en/docs/tutorials/ml-ai/ai-model-ide-integration
3.64 - OpenSpec
This package runs the upstream OpenSpec CLI with
Bazel’s pinned Node toolchain. tools/package.json pins
@fission-ai/openspec to 1.11.0; tools/pnpm-lock.yaml records the package
integrities and transitive dependency versions. Package lifecycle scripts are
disabled. No global npm installation is needed.
Each component owns an OpenSpec workspace at <owner>/openspec/. The
repository’s evolution belongs to infra/src/openspec/,
which is the default for the runnable target. Run commands from the enclosing
repository root; OPENSPEC_PROJECT selects a different owner directory:
bazel_agent bazel run //tools/openspec -- --version
bazel_agent bazel run //tools/openspec -- list --specs --json
bazel_agent bazel run //tools/openspec -- status --change <change-name> --json
bazel_agent bazel run //tools/openspec -- validate --all --strict --no-interactive
OPENSPEC_PROJECT=projects/agents bazel_agent bazel run //tools/openspec -- list --specs --json
OPENSPEC_PROJECT=infra/vault bazel_agent bazel run //tools/openspec -- list --specs --json
OPENSPEC_PROJECT is a repository launcher setting, not an upstream CLI flag.
It is relative to the enclosing repository root, and OpenSpec reads and writes
that owner’s source artifacts directly. Standalone nested projects use the
same root invocation, for example OPENSPEC_PROJECT=tools/rules_skills.
Run upstream validation for all 51 owner workspaces in sandboxed tests against declared source inputs:
bazel_agent bazel test //infra/src/openspec/validation:validate_test //infra/src/openspec/validation:archive_test
validate_test aggregates one strict test per owner for current specs and
active change deltas. archive_test covers the repository, agent-system, and
MCP workspaces and checks that archived changes have completed task
checkboxes; upstream does not reapply historical deltas during that check.
Both are structural checks. Requirement scenarios still need evidence from
their owning implementation and validation workflow.
The source-to-test mapping lives in
infra/src/openspec/validation/BUILD.bazel. Each owner’s
openspec/BUILD.bazel exposes config, baseline specs, and complete native
change artifacts. Standalone projects expose this source through their
existing module repository, without taking an OpenSpec dependency. The shared
openspec_validation macro retains declared source runfiles through a
js_library with no_copy_to_bin: files keep their owning package paths,
including across module boundaries. Tests select that owner inside their
sandbox and receive only declared inputs.
When adding an owner workspace, add its source label to _WORKSPACE_SOURCES.
When it first archives a change, also add it to _ARCHIVE_WORKSPACES. Keep
these aggregate memberships aligned with the checked-in workspaces.
The launcher disables telemetry and update checks. OpenSpec’s XDG config and
data paths are isolated to ignored out/openspec/ in the source workspace for
bazel run, and to Bazel’s test temporary directory for tests. These targets
do not read or change user-global OpenSpec configuration. Commands that create,
edit, or archive changes still modify source artifacts as documented by the
upstream CLI.
Update the version in tools/package.json, then use the owning pnpm workflow
described in tools/js to regenerate its lock with lifecycle
scripts disabled. Re-run the version command and both validation tests after
upgrading.
3.64.1 -
project-rules-openspec Specification
Purpose
Define reusable Bazel validation and execution behavior for owner-local OpenSpec workspaces.
Requirements
OpenSpec validation
The system SHALL validate one owner-local OpenSpec workspace in a sandbox using the pinned OpenSpec CLI.
Scenario: current validation
- WHEN a caller runs the validation target
- THEN OpenSpec validates current specifications and active changes with strict mode
Scenario: archived validation
- WHEN a caller requests archived validation
- THEN OpenSpec validates completed archived changes with strict mode
3.67 - Patch
3.67.1 - Bzl
3.67.1.1 - al_apply_patches
al_apply_patches
load("@com_alwaldend_src//tools/patch/main/bzl:al_apply_patches.bzl", "al_apply_patches")
al_apply_patches(name, src, patches, visibility, **kwargs)
Create a genrule applying patches
PARAMETERS
| Name | Description | Default Value |
|---|---|---|
| name | genrule name | none |
| src | source archive label | none |
| patches | patches label | none |
| visibility | visibility | ["//:__subpackages__"] |
| kwargs | other genrule kwargs | none |
3.68 - Pkg
3.68.1 - Bzl
3.68.1.1 - al_genrule_src
al_genrule_src
load("@com_alwaldend_src//tools/pkg/main/bzl:al_genrule_src.bzl", "al_genrule_src")
al_genrule_src(name, srcs, visibility)
Create a filegroup and a genrule generating a tar archive
PARAMETERS
| Name | Description | Default Value |
|---|---|---|
| name | genrule name | none |
| srcs | source labels | [] |
| visibility | - |
["//:__subpackages"] |
3.68.1.2 - al_pkg_basic_naming
al_pkg_basic_naming
load("@com_alwaldend_src//tools/pkg/main/bzl:al_pkg_basic_naming.bzl", "al_pkg_basic_naming")
al_pkg_basic_naming(name, deps)
Variables for @rules_pkg
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| deps | Deps to merge | List of labels | optional | [] |
3.68.1.3 - al_pkg_extract_dir
al_pkg_extract_dir
load("@com_alwaldend_src//tools/pkg/main/bzl:al_pkg_extract_dir.bzl", "al_pkg_extract_dir")
al_pkg_extract_dir(name, src, out, arguments)
Extract an archive into a TreeArtifact
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| src | Archive to unpack | Label | required | |
| out | Output directory name | String | optional | "" |
| arguments | Additional arguments | List of strings | optional | [] |
3.68.1.4 - al_pkg_tar_combined
al_pkg_tar_combined
load("@com_alwaldend_src//tools/pkg/main/bzl:al_pkg_tar_combined.bzl", "al_pkg_tar_combined")
al_pkg_tar_combined(name, srcs, strip_components, **kwargs)
Create a genrule combining several tars into one
PARAMETERS
3.68.1.5 - al_unpack_archives
al_unpack_archives
load("@com_alwaldend_src//tools/pkg/main/bzl:al_unpack_archives.bzl", "al_unpack_archives")
al_unpack_archives(name, srcs, out)
Unpack several archives using tar into a directory
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| srcs | - | List of labels | required | |
| out | - | String | optional | "" |
3.70 - Pnpm
3.73 - Print deps
3.73.1 - Bzl
3.73.1.1 - al_print_deps
al_print_deps
load("@com_alwaldend_src//tools/print_deps/main/bzl:al_print_deps.bzl", "al_print_deps")
al_print_deps()
ASPECT ATTRIBUTES
| Name | Type |
|---|---|
| deps | String |
ATTRIBUTES
3.74 - Proto
3.74.1 - Bzl
3.74.1.1 - al_proto_docs
al_proto_docs
load("@com_alwaldend_src//tools/proto/main/bzl:al_proto_docs.bzl", "al_proto_docs")
al_proto_docs(name, src, prefix, visibility, renames)
Generate protobuf documentation
PARAMETERS
| Name | Description | Default Value |
|---|---|---|
| name | name | none |
| src | protobuf source file | none |
| prefix | - |
None |
| visibility | visibility | None |
| renames | - |
None |
3.75 - Py
The repository Python dependency lock remains in root requirements.txt, next
to pyproject.toml. Update it with //tools/py:requirements.update and validate
it with //tools/py:requirements.test; the root labels remain compatibility
entry points. These upstream pip-tools workflows require network access to
resolve and validate package versions and run outside the action sandbox.
3.75.1 - Bzl
3.75.1.1 - al_compile_pip_requirements_combined
al_compile_pip_requirements_combined
load("@com_alwaldend_src//tools/py/main/bzl:al_compile_pip_requirements_combined.bzl", "al_compile_pip_requirements_combined")
al_compile_pip_requirements_combined(name, srcs, **kwargs)
Create compile_pip_requirements target for several requirement files
PARAMETERS
| Name | Description | Default Value |
|---|---|---|
| name | compile_pip_requirements name | none |
| srcs | list of labels of requirement files to combine | none |
| kwargs | kwargs for compile_pip_requirements |
none |
3.75.1.2 - al_genrule_with_wheels
al_genrule_with_wheels
load("@com_alwaldend_src//tools/py/main/bzl:al_genrule_with_wheels.bzl", "al_genrule_with_wheels")
al_genrule_with_wheels(name, wheels, srcs, cmd, **kwargs)
Regular genrule with wheels added to ${PYTHONPATH}
PARAMETERS
| Name | Description | Default Value |
|---|---|---|
| name | genrule name | none |
| wheels | list of wheel labels | none |
| srcs | srcs for the genrule | [] |
| cmd | genrule cmd | [] |
| kwargs | other genrule kwargs | none |
3.75.1.3 - al_py_binary_shell
al_py_binary_shell
load("@com_alwaldend_src//tools/py/main/bzl:al_py_binary_shell.bzl", "al_py_binary_shell")
al_py_binary_shell(name, deps, srcs, shell_type, shell_label, **kwargs)
Create a py_binary target that allows you to run commands in proper python environment
PARAMETERS
3.75.1.4 - al_py_checker
al_py_checker
load("@com_alwaldend_src//tools/py/main/bzl:al_py_checker.bzl", "al_py_checker")
al_py_checker(name, tool, args_bin, args_test, test_size, disable_fix, **kwargs)
Create -fix and -test targets for a python checker
PARAMETERS
3.75.1.5 - al_py_checkers
al_py_checkers
load("@com_alwaldend_src//tools/py/main/bzl:al_py_checkers.bzl", "al_py_checkers")
al_py_checkers(name, srcs, isort_label, black_label, mypy_label, flake8_label, pyproject_label)
Generate -fix and -test targets for python checkers
PARAMETERS
3.76 - Qt
Links
Hermetic Qt
The module configuration downloads SHA-256-pinned Qt 6.8.3 distributions via
rules_qt and registers its build tools. Bazel builds do not require Qt under
/opt or another host installation.
3.76.1 - Bzl
3.78 - Readme tree
Example
bazel run tools/readme_tree -- parse -g -C "${PWD}" .
3.79 - Release
3.79.1 - Bzl
3.79.1.1 - al_release
al_release
load("@com_alwaldend_src//tools/release/main/bzl:al_release.bzl", "al_release")
al_release(name, srcs, git_bundle, git_state, manifest, project, release_name, release_tool,
root_prefix)
Rule describing a release
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| srcs | Sources | List of labels | optional | [] |
| git_bundle | Deterministic Git bundle used to generate release metadata | Label | optional | "@com_alwaldend_src_tools_git//:release_git_state" |
| git_state | Additional declared Git state used to generate release metadata | List of labels | optional | [] |
| manifest | Load manifest from a file instead of generating it from srcs | Label | optional | None |
| project | Project package_name | String | required | |
| release_name | Release name | String | required | |
| release_tool | Release tool | Label | optional | "@com_alwaldend_src//tools/release/main/go" |
| root_prefix | Root prefix | String | optional | "content/docs" |
3.79.1.2 - al_release_binary
al_release_binary
load("@com_alwaldend_src//tools/release/main/bzl:al_release_binary.bzl", "al_release_binary")
al_release_binary(name, srcs, arguments, cmd, oras, release_tool)
Release binary
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| srcs | Releases | List of labels | optional | [] |
| arguments | Arguments | List of strings | optional | [] |
| cmd | Cmd | String | optional | "deploy" |
| oras | Oras binary | Label | optional | "@com_alwaldend_src//tools/oras" |
| release_tool | Release tool | Label | optional | "@com_alwaldend_src//tools/release/main/go" |
3.79.1.3 - al_release_deployment
al_release_deployment
load("@com_alwaldend_src//tools/release/main/bzl:al_release_deployment.bzl", "al_release_deployment")
al_release_deployment(name, oci_repository)
Deployment info
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| oci_repository | OCI repository url | String | optional | "" |
3.79.1.4 - al_release_deployment_info
AlReleaseDeploymentInfo
load("@com_alwaldend_src//tools/release/main/bzl:al_release_deployment_info.bzl", "AlReleaseDeploymentInfo")
AlReleaseDeploymentInfo(info, info_file)
Deployment info
FIELDS
| Name | Description |
|---|---|
| info | Deployment info struct |
| info_file | Deployment info file |
3.79.1.5 - al_release_deps
al_release_deps
load("@com_alwaldend_src//tools/release/main/bzl:al_release_deps.bzl", "al_release_deps")
al_release_deps(name, srcs, visibility, **kwargs)
Generate a dependency diagram using genquery
PARAMETERS
| Name | Description | Default Value |
|---|---|---|
| name | name | none |
| srcs | list of labels to generate deps for (should be full labels) | none |
| visibility | visibility | None |
| kwargs | kwargs for al_release_files | none |
3.79.1.6 - al_release_files
al_release_files
load("@com_alwaldend_src//tools/release/main/bzl:al_release_files.bzl", "al_release_files")
al_release_files(name, deps, srcs, deployments, ignore_suffixes, release_tool)
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| deps | Deps | List of labels | optional | [] |
| srcs | Sources | List of labels | optional | [] |
| deployments | Deployment info | List of labels | optional | [] |
| ignore_suffixes | Ignore src files ending with these suffixes | List of strings | optional | [] |
| release_tool | Release tool | Label | optional | "@com_alwaldend_src//tools/release/main/go" |
3.79.1.7 - al_release_files_info
AlReleaseFilesInfo
load("@com_alwaldend_src//tools/release/main/bzl:al_release_files_info.bzl", "AlReleaseFilesInfo")
AlReleaseFilesInfo(files, manifest)
Release files
FIELDS
| Name | Description |
|---|---|
| files | File dict, keys are filenames, values are Files |
| manifest | Release manifest for srcs |
3.79.1.8 - al_release_info
AlReleaseInfo
load("@com_alwaldend_src//tools/release/main/bzl:al_release_info.bzl", "AlReleaseInfo")
AlReleaseInfo(release_name, project, files, manifest)
Release information
FIELDS
| Name | Description |
|---|---|
| release_name | Release name (string) |
| project | Project subdir (string) |
| files | File dict, keys are filenames, values are Files |
| manifest | Release manifest (File) |
3.79.2 - Proto
3.79.2.1 - contracts
Java
load("@rules_java//java:defs.bzl", "java_library")
java_library(
name = "name",
deps = [
"@com_alwaldend_src//tools/release/main/proto/contracts:contracts_java_library",
],
)
Golang
load("@rules_go//go:def.bzl", "go_library")
go_library(
name = "name",
deps = [
"@com_alwaldend_src//tools/release/main/proto/contracts:contracts",
],
)
Proto
syntax = "proto3";
package release;
import "tools/git/main/proto/contracts/contracts.proto";
option go_package = "git.alwaldend.com/alwaldend/src/tools/release/main/proto/contracts";
message ReleaseHash {
string algo = 1;
string content = 2;
}
message ReleaseFile {
repeated ReleaseHash hashes = 1;
string name = 2;
string safe_name = 6;
string url = 3;
int64 size = 4;
string local_path = 5;
}
message ReleaseItem {
ReleaseFile file = 1;
repeated ReleaseDeployment deployments = 2;
}
message Project {
string subdir = 1;
string safe_subdir = 2;
}
message Git {
git.GitCommit revision = 1;
repeated git.GitCommit commits = 2;
}
message ReleasePageSectionItemAttr {
string name = 1;
string content = 2;
}
message ReleasePageSectionItem {
string content = 1;
string content_url = 2;
repeated ReleasePageSectionItemAttr attrs = 3;
}
message ReleasePageSection {
string title = 1;
repeated ReleasePageSectionItem items = 2;
}
message ReleasePage {
repeated ReleasePageSection sections = 1;
}
message ReleaseDeploymentOci {
string repository = 1;
repeated string tags = 2;
}
message ReleaseDeployment {
ReleaseDeploymentOci oci = 1;
}
message Release {
repeated ReleaseItem items = 1;
string name = 2;
Project project = 3;
Git git = 4;
}
3.80 - Replace section
3.81 - Repo map
3.81.1 - Bzl
3.81.1.1 - al_repo_map
al_repo_map
al_repo_map = use_extension("@com_alwaldend_src//tools/repo_map/main/bzl:al_repo_map.bzl", "al_repo_map")
al_repo_map.download(name, build_file_content, build_file_native_binary, download_type, executable,
repos, strip_prefix)
Extension to create several repos from a map
TAG CLASSES
download
Attributes
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | Name | Name | required | |
| build_file_content | Build file content | String | optional | "" |
| build_file_native_binary | Args for a native binary build file | Dictionary: String -> String | optional | {} |
| download_type | Download type | String | optional | "http_archive" |
| executable | Field executable for http_file | Boolean | optional | False |
| repos | Map of repos | Dictionary: String -> List of strings | required | |
| strip_prefix | Strip prefix | String | optional | "" |
3.82 - Repository AL configuration
//tools/al:config packages the repository’s shared AL configuration. The
root //:al label remains a compatibility alias. The Lua source files stay
at the repository root so existing CLI configuration discovery and
require("al_lib") imports retain their paths.
The //:tf.* compatibility aliases select Terraform commands declared here
with the public rules_terraform command maps and the generic AL wrapper. These
bindings use the shared config and explicitly select the repository root as
their Terraform working directory.
3.83 - Repository delivery
repo_delivery implements the deterministic part of repository delivery. It
invokes native Git and a selected forge CLI; it does not infer task ownership,
choose validation commands, resolve conflicts, or judge review feedback.
Provider and delivery workflow
Run delivery commands from this Git worktree’s repository root, which owns the
root MODULE.bazel and tools/repo_delivery. This also applies when changed
files belong to a nested Bazel module: its workspace does not own the delivery
target. Use the same feature worktree, not another checkout. The baseline works
with older installed runners. Detect the provider without printing a
credential-bearing remote URL:
bazel_agent bazel run //tools/repo_delivery -- provider
The optional cached form is al tool repo_delivery -- .... An execution
failure or delivery refusal still requires diagnosis. All examples below use
the baseline.
The sanitized report distinguishes forge support from Git transport support.
adapter_available reports whether the forge has an adapter;
git_transport reports ssh, https, or mixed_or_unsupported; and
delivery_transport_available is true only when both captured endpoints are
canonical SSH endpoints. It never reports either endpoint.
For validation that invokes Bazel, use the cached entry point or generate a
task-local launcher once from the repository root. Ordinary bazel run can
retain the Bazel lock while its target runs; --script_path releases it before
the generated launcher is executed. Refresh the launcher after changing the
delivery tool. This requires no installed runner update:
bazel_agent bazel run --script_path=out/task/repo_delivery \
//tools/repo_delivery
For the supported GitHub adapter, the normal workflow is:
bazel_agent bazel run //tools/repo_delivery -- inspect --base master
bazel_agent bazel run //tools/repo_delivery -- prepare \
--base master \
--message-file out/task/commit.md \
--receipt-file out/task/prepare.json \
--path path/to/task/file \
--rewrite <inspect.local_head_oid> # omit when the range has no commit
# For an explicitly reviewed task-owned multi-commit range, use
# --consolidate <inspect.local_head_oid> instead of --rewrite.
out/task/repo_delivery validate \
--receipt-file out/task/prepare.json --plan-file out/task/checks.json
out/task/repo_delivery continue \
--receipt-file out/task/prepare.json --publish
out/task/repo_delivery continue \
--receipt-file out/task/prepare.json
checks.json is an explicitly selected validation plan. Keep it mode 0600 in
the same ignored out/<task>/ directory as the preparation receipt. For
example, a change confined to the delivery Go package can use:
{
"schema": "repo_delivery/validation_plan/v1",
"checks": [
{
"workspace": ".",
"kind": "test",
"targets": [
"//tools/repo_delivery/cmd/repo_delivery:go_test",
"//:repo_quality_test"
],
"timeout_seconds": 3600
},
{
"workspace": ".",
"kind": "lint",
"targets": ["//tools/repo_delivery/cmd/repo_delivery:all"],
"timeout_seconds": 3600
}
],
"gap_decisions": []
}
Allowed kinds are test, build, and lint (build with --config=lint).
The plan accepts 1–32 sequential checks, 1–128 explicit local labels per check,
and a 1–3600 second deadline per check. Package :all is supported outside the
root package; recursive target patterns, arbitrary run targets, shell
commands, and free-form flags are not. Workspace paths are relative to the Git
worktree root and must name real Bazel workspace roots. Nested checks execute
there; the required //:repo_quality_test check executes in .. The plan must
lint every suggested non-root affected package and resolve each validation gap
with exactly one { "path": "...", "reason": "..." } decision. The caller
still selects sufficient consumer checks and verifies representative output.
validate runs aggregate git diff --check first, then the selected checks.
It requires a fully clean worktree and ordinary index flags before and after
checks. It records exact head/tree, preparation revision, plan bytes, inherited
environment digest, check outcomes, and log digests beside the receipt, using
mode 0600 files. Each output stream is capped at 96 KiB; truncation fails the
check. The same receipt lock protects validation and continuation. Keep all
these files trusted and unedited; they are consistency evidence, not security
tokens. Tool binaries, ignored configuration, external services, and other
inputs outside the recorded Git tree/environment still require the caller’s
input-stability judgment before publication. No passing checks are reused
automatically by a new validation run.
continue reports readiness without publishing. Only continue --publish
uses the captured passing result to call the existing guarded publication and
verification path; it never substitutes the current mutable HEAD as evidence.
Changed candidate, receipt, plan, environment, incomplete results, altered
logs, and dirty inputs refuse publication. A base rebase records
revalidation_required and stops before pushing: rerun validate against the
updated receipt, then explicitly continue. An interrupted or failed publication
remains publication_attempted; further continuation only verifies its remote
postcondition and never blindly repeats a push or metadata mutation. Diagnose
an incomplete result before using the existing manual recovery API. A new
validation run cannot reset an uncertain attempt for the same candidate.
prepare derives affected_bazel_labels from the prepared aggregate changed
paths, selecting each nearest non-root Bazel package. It never infers //:all
from a root-owned file. The reported
bazel_selection_basis is nearest_non_root_package_without_dependency_analysis:
this bounds discovery but does not establish downstream impact. Shared build
inputs may need explicit consumer checks.
bazel_validation_gaps lists paths requiring a separate decision, with reasons
root_package_requires_explicit_targets, ignored_by_root_workspace,
nested_workspace, or no_bazel_package. For each gap, select appropriate
targets or record why no target check applies. Validate nested or ignored
workspaces through their owner, then return to the repository root for delivery.
The suggested commands always include the root-workspace gate
bazel_agent bazel test //:repo_quality_test; that gate does not establish
semantic correctness for BUILD, MODULE, or configuration changes. Run semantic
lint for the selected affected targets in addition to that mandatory gate.
To synchronize a prepared, task-owned, single-commit feature branch with an
advanced base before prepare, use the guarded adapter workflow:
bazel_agent bazel run //tools/repo_delivery -- rebase --base master
The command refuses dirty trees, divergent remote feature tips, multi-commit
or merge-containing ranges, and pull-request metadata changes. It fetches
fresh refs, replays the commit in an isolated worktree, preserves signature
requirements, pushes only with the captured remote feature lease, verifies
base advancement, and reports the literal resulting head. Run required
validations against that head before prepare and publish.
Remote rewrites use rewrite-authorize to write a typed, non-authorizing
authorization receipt (old remote OID, new head OID, owner root, task paths,
provider ownership), then prepare --rewrite-authorization <file> instead of
raw --replace-remote handoff. Review replies accept --goal-ref,
--delivery-ref, and --defect-id durable join references.
prepare refuses a divergent remote feature tip by default. Use
--replace-remote <literal-inspect.remote_head_oid> only after the
git-rebase-remote workflow has preserved that exact old tip and established
that it is task-owned history the user authorized rewriting. Never infer the
OID or use this escape hatch for shared, stacked, human-owned, unrelated, or
ambiguous history. A mismatched, malformed, absent, or unnecessary
authorization is refused. The final fresh snapshot and preparation receipt
bind the same old remote OID for the later exact force-with-lease push.
prepare --consolidate <literal-inspect.local_head_oid> is the explicit
ownership authorization for replacing a multi-commit feature range with one
aggregate commit. It is not inferred from author names. The adapter still
requires a merge-free linear chain, one author and committer identity across
the range, the ownership disclaimer on its oldest commit, pull-request
metadata matching the requested aggregate message, and the exact inspected
head.
It preserves any signature requirement found in the range and keeps the
fetched remote feature tip as the publication lease. --consolidate and
--rewrite are mutually exclusive.
When a clean replay onto an advanced base makes an expected aggregate path disappear from the resulting diff, the adapter accepts that shrink only when the prior candidate and the new base have byte-identical Git tree entries at that path. A new path, a non-identical disappearance, or an entirely empty aggregate remains a refusal. The derived receipt records the reduced exact aggregate path set.
The manual publish --receipt-file <path> --validated-head <literal-head_oid>
API remains available for validations outside the structured plan and diagnosed
recovery. Never populate that flag by resolving current HEAD: carry the
literal candidate that the checks covered. A preparation receipt alone does
not establish validation. The structured continuation path supplies that
literal value from its recorded passing results instead.
For message-only amendments, deliver --message-file <path> --receipt-file <path> --owner-root <root> --task-path <path> combines inspection, any needed
rewrite authorization, and preparation. It stops before publication with a
nonzero exit and a revalidation_required report containing the exact head,
tree, receipt, affected labels, and suggested checks. Establish validation for
that candidate using validate, then use continue --publish, or use the
manual publish API and verify. Do not repeat deliver to continue, because
that prepares another candidate.
Version 1 delivery accepts only SCP-style or ssh:// Git fetch and push
endpoints. The gh CLI is still used for the GitHub forge API, but the tool
does not import mutable global credential-helper configuration installed by
gh auth setup-git. An HTTPS Git remote is therefore rejected before
inspect, preparation, or publication performs network access. Configure an
SSH remote explicitly before using delivery; the tool will not rewrite the
repository’s remote configuration for you.
prepare writes a strict versioned receipt under an ignored
out/<task>/ directory. The receipt binds the prepared head and tree to the
exact worktree and Git directories, fetch and push endpoint digests, sanitized
repository identity, forge adapter, base and head refs, fetched base, expected
remote feature ref, expected pull-request identity or absence, and immutable
aggregate path scope. The file contains no
remote URL, must remain untracked, and is installed with mode 0600 by atomic
rename. It is a consistency record, not an unforgeable authorization token.
The adjacent receipt lock serializes receipt transitions and reads performed
by cooperating repo_delivery processes. Keep the ignored receipt path
trusted and do not edit, replace, copy over, or otherwise write it while
prepare, publish, or receipt-bound verify is running. Stable byte and
revision checks detect changes visible before their checks, but operating
systems do not provide a portable atomic
pathname-content compare-and-swap. A same-user process that ignores the lock
can race the final comparison and rename; the tool does not claim to exclude
that writer. A persistent exclusive revision-claim sidecar would have the same
trust boundary, while a crash before installation could strand the receipt
without a safe automatic cleanup decision, so it is not used.
Use repeated --path flags for fully task-owned paths, or pre-stage only
task-owned hunks and use --use-index. Both modes bind the complete existing
feature diff, not merely the paths newly staged by that invocation.
--message-only --rewrite <exact-oid> preserves the tree but changes the
commit OID. Consolidation also changes the commit OID and parent structure.
Every prepare, consolidation, or message-only amendment therefore requires a
validation decision bound to its returned exact head. Run required checks
after preparation by default. For a tree-preserving amendment, prior passing
evidence may be reused only after recording its exact prior candidate, the
matching tree OID, the new OID, and unchanged inputs relevant to each check.
Those inputs include commands, tools, configuration, and environment. Rerun
checks affected by commit identity, history, or stamping, and any check whose
input stability is unknown. The caller owns and records this applicability
judgment; the receipt neither proves validation nor authorizes reuse.
When an authorized remote replacement is pending, rewrite evidence accepts an
existing pull request only if its metadata matches the exact projectable local
or fetched-remote commit projection. A legacy remote tail that lacks an
aggregate disclaimer cannot block a matching local aggregate, and unrelated
pull-request text remains a refusal.
Publish and receipt-bound verify require a clean index and reject staged,
unstaged, or untracked changes in the prepared task scope. They preserve
unrelated unstaged and untracked files when no rebase is needed. A required
rebase demands a fully clean worktree and index. Run validation from a clean
checkout at the literal head_oid whenever unrelated dirty files could affect
the check; the tool cannot infer a check’s input set.
If the base advances after preparation, publish rebases the exact captured
commit in an isolated ignored worktree. It then exits nonzero before pushing
and emits a revalidation_required JSON report containing the new exact head,
tree, and derived receipt. Validate that returned head directly, then retry
publish with the same receipt file and the new literal OID. Do not run
prepare again unless content or the commit message must change. A receipt
also supports a guarded retry when the remote already equals its prepared head
but pull-request creation or metadata synchronization stopped partway through.
Replacement pull-request identities and any state other than the exact prior
or desired projection are refused. Multi-commit consolidation likewise
requires an existing pull request to equal the requested aggregate message’s
projection, so consolidation cannot silently replace independently edited
pull-request text.
The tool creates commits with Git plumbing and pushes one exact ref with hooks disabled. It rejects shallow, promisor, or grafted history and ignores replacement objects. Each network operation runs in a fresh private, config-free bare Git directory bound to the captured SSH endpoint and the repository’s canonical object database. It does not load mutable main-repo local/worktree URL rewriting, proxy, TLS, SSH-command, or remote configuration. Normal DNS resolution and SSH host-key verification still apply; the tool does not claim to pin an IP address or server key. Ordinary local Git operations still intentionally use repository identity and signing configuration. Fetches use isolated temporary refs without pruning, then install exact private refs locally; pushes use an exact force-with-lease. Repository-required hook checks remain the caller’s responsibility and must complete before recording the validated OID.
The feature-ref lease and base-ref checks are separate because Git forges do not offer a cross-ref compare-and-swap. If the base advances in the narrow push window, the feature ref may be visible briefly before the tool detects the race and attempts an exact guarded rollback. Coordinate consumers that react immediately to branch-update webhooks.
Review workflow
Start with a bounded structured inventory:
bazel_agent bazel run //tools/repo_delivery -- review inspect
Carry values from the latest inspection literally. All mutations require the pull-request node ID, expected head, and pull-request expectation digest. A top-level reply also requires the reported last-comment sentinel and top-level inventory digest:
bazel_agent bazel run //tools/repo_delivery -- review comment \
--pull-request-id <pull_request.id> \
--expected-head <pull_request.head_ref_oid> \
--expected-pull-request-digest <pull_request_expectation_digest> \
--expected-last-top-level-comment \
<expected_last_top_level_comment> \
--expected-top-level-comments-digest \
<expected_top_level_comments_digest> \
--body-file out/task/comment.md
Thread replies and resolutions additionally bind the thread, its last comment, and its complete expectation digest:
bazel_agent bazel run //tools/repo_delivery -- review reply \
--pull-request-id <pull_request.id> \
--expected-head <pull_request.head_ref_oid> \
--expected-pull-request-digest <pull_request_expectation_digest> \
--thread-id <review_threads[index].id> \
--expected-last-comment-id <review_threads[index].comments[-1].id> \
--expected-thread-digest <review_threads[index].expectation_digest> \
--body-file out/task/reply.md \
--reply-receipt-file out/task/reply.json
bazel_agent bazel run //tools/repo_delivery -- review resolve \
--pull-request-id <pull_request.id> \
--expected-head <pull_request.head_ref_oid> \
--expected-pull-request-digest <pull_request_expectation_digest> \
--thread-id <review_threads[index].id> \
--expected-last-comment-id <review_threads[index].comments[-1].id> \
--expected-thread-digest <review_threads[index].expectation_digest> \
--reply-receipt-file out/task/reply.json
bazel_agent bazel run //tools/repo_delivery -- review request \
--pull-request-id <pull_request.id> \
--expected-head <pull_request.head_ref_oid> \
--expected-pull-request-digest <pull_request_expectation_digest> \
--reviewer <login>
Comment and reply bodies must be ignored files under out/<task>/; the tool
adds the exact comment disclaimer. Resolution requires the strict reply
receipt written by review reply, and the receipt must still match the exact
pull request, head, thread, reply, body, and complete bounded review inventory
projection. The parent pull-request UpdatedAt is a nondecreasing floor,
rather than an exact value, because reply side effects can advance it
asynchronously; every review, top-level comment, thread and thread comment, and
review request remains bound.
Reinspect after every mutation and use the newly reported IDs and digests for
the next one.
The one-use reply authority expires no more than five minutes after issuance.
Resolution verifies the authority window and atomically consumes the receipt
before contacting the provider. If a provider read fails before any resolution
mutation is attempted, the tool can restore the original unexpired receipt
without replacing another file or extending its authority window. Only an
explicit restoration report permits retry with that receipt; no additional
public reply is needed for that read failure.
Expiration, semantic or full-inventory mismatch, mutation failure, and an
unknown mutation outcome still consume authority. Never recreate the receipt
yourself. Reinspect the remote state and, if resolution remains appropriate,
leave a fresh reasoned reply to obtain new one-use authority.
GitHub provides neither compare-and-swap resolution nor a documented monotonic review-thread epoch. A human resolve followed by unresolve can therefore be unobservable if it restores identical thread and pull-request state inside the five-minute authority window. The exact-state checks, short expiration, and one-use consumption narrow that risk; they do not prove that such an ABA or a change to provider metadata omitted from the bounded projection did not occur. Do not resolve a thread that may be concurrently moderated.
GitHub does not expose atomic compare-and-swap mutations for pull-request metadata, comments, replies, resolutions, or review requests. The adapter checks exact expectations before each mutation and verifies the complete result afterward, but a concurrent human change can still occur inside that narrow provider-side window. Do not mutate an actively coedited pull request. Post-mutation inspection failures are reported as outcome unknown; reinspect instead of retrying blindly.
Forge adapters
GitHub is supported through the gh CLI. Forge behavior is selected behind a
Go interface and uses argument-vector subprocess calls, so another structured
CLI adapter can be added without changing delivery policy. --forge auto
selects GitHub for github.com; use
--forge github --forge-cli <gh-path> to select an explicit executable.
Unknown or unsupported forges fail before any commit rewrite or push.
Version 1 is limited to same-repository pull requests. It cannot reliably discover or map an upstream pull request whose head lives in a fork. Treat same-repository topology as a caller-enforced precondition: do not use the delivery or review commands for a fork-based or otherwise cross-repository pull request, and stop when remote or pull-request ownership is uncertain. The adapter fails closed when it observes an unsupported or inconsistent topology, but that refusal is not a substitute for this caller check.
The read-only provider command recognizes known Forgejo hosts, but there is
currently no Forgejo delivery adapter. Use the repository’s documented
Forgejo compatibility workflow instead of pretending GitHub operations are
portable.
3.84 - Repository quality
This package uses upstream aspect_rules_lint formatting and linting rules to
discover Git-tracked files and inspect declared source targets with established
tools acquired by Bazel. It does not implement a formatter or linter and does
not download tools at runtime. Thin workspace adapters extend the upstream
language list with the official Go SDK for module and workspace manifests,
StyLua and Selene for Lua, and the existing Prettier XML plugin for Qt .ui
and .qrc files.
Format all safe, hand-maintained files:
bazel_agent bazel run //:format
Run the non-mutating repository check:
bazel_agent bazel test //:repo_quality_test
The suite also parses root BUILD.bazel and rejects load() statements to keep
unrelated tool dependencies out of root package loading. Run this check alone
with bazel_agent bazel test //tools/repo_quality/test/root_build:root_build_test.
Run semantic source linters over declared targets:
bazel_agent bazel build --config=lint //...
The CSS formatter bucket includes CSS, Less and SCSS. The JavaScript bucket
includes JavaScript, JSON, JSON-with-comments, JSON5, TypeScript, TSX and Vue.
Go source uses gofumpt; go.mod and go.work use the official Go SDK.
Lua checks cover every tracked file not excluded by Git attributes, using
StyLua for canonical formatting and Selene for correctness diagnostics.
Explicit templates (.j2, .tmpl, .tpl, and the Hugo layout tree), generic
application configuration, and non-Terraform HCL are deliberately excluded
from general formatting. Ordinary Markdown, YAML, HTML and other files remain
covered even when their contents include template expressions. Generated,
vendored, lock, binary, diagram and exact-content files likewise retain their
owning regeneration, validation or integrity workflow.
The integration test intentionally uses the upstream rule’s no_sandbox mode
so it can inspect files that are tracked by Git but not declared in BUILD
files. This is a local-checkout guarantee, like the root Buildifier test; tool
acquisition remains hermetic and pinned through Bazel.
3.85.1 - Bzl
3.85.1.1 - al_resolved_toolchain
al_resolved_toolchain
load("@com_alwaldend_src//tools/resolved_toolchain/main/bzl:al_resolved_toolchain.bzl", "al_resolved_toolchain")
al_resolved_toolchain(toolchain_label, **kwargs)
Create a resolved toolchain
PARAMETERS
| Name | Description | Default Value |
|---|---|---|
| toolchain_label | - |
none |
| kwargs | rule kwargs | none |
RETURNS
Resolved toolchain rule
3.86.1 - Bzl
3.86.1.1 - al_rfc_extension
al_rfc_extension
al_rfc_extension = use_extension("@com_alwaldend_src//tools/rfc/main/bzl:al_rfc_extension.bzl", "al_rfc_extension")
al_rfc_extension.download(name, integrity, rfcs)
Rfc extension
TAG CLASSES
download
Attributes
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | Name | Name | required | |
| integrity | Rfc integrity | Dictionary: String -> String | optional | {} |
| rfcs | Rfcs | List of strings | optional | [] |
3.86.1.2 - al_rfc_repo
al_rfc_repo
load("@com_alwaldend_src//tools/rfc/main/bzl:al_rfc_repo.bzl", "al_rfc_repo")
al_rfc_repo(name, integrity, repo_mapping, rfcs, url)
Rfc repository
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this repository. | Name | required | |
| integrity | Rfc integrity | Dictionary: String -> String | optional | {} |
| repo_mapping | In WORKSPACE context only: a dictionary from local repository name to global repository name. This allows controls over workspace dependency resolution for dependencies of this repository.For example, an entry "@foo": "@bar" declares that, for any time this repository depends on @foo (such as a dependency on @foo//some:target, it should actually resolve that dependency within globally-declared @bar (@bar//some:target).This attribute is not supported in MODULE.bazel context (when invoking a repository rule inside a module extension’s implementation function). |
Dictionary: String -> String | optional | |
| rfcs | Rfcs | List of strings | optional | [] |
| url | Url format | String | optional | "https://www.rfc-editor.org/rfc/{postfix}" |
3.87 - Root Bazel module
MODULE.bazel is generated directly from include.MODULE.bazel files:
bazel run //tools/bazel_module:update
Dependency declarations and pins stay in their owning include files. The small
root module(...) header lives in the Go generator. Discovery uses the existing
//tools/git host Git wrapper to include tracked and untracked files while
respecting Git ignore rules. Deleted files, symlinks, .bazelignore
directories, and standalone workspaces beneath
MODULE.bazel, WORKSPACE, or WORKSPACE.bazel boundaries are excluded.
Includes are ordered by owning directory, with third_party, tools, then
projects before other trees. This keeps the existing precedence between those
trees, including toolchain registrations. A parent directory precedes its
children. Keep any order-sensitive declarations together in one owning include.
//tools/bazel_module/cmd/update:freshness_test checks the current checkout and
is included in //:repo_quality_test. It intentionally disables sandboxing and
result caching to detect new or removed files outside declared Bazel inputs.
The generator’s unit tests remain sandboxed and cacheable.
Before deleting or moving an existing include, retain a launcher so regeneration does not need to load the old module after its include disappears:
mkdir -p out/bazel_module
bazel run --script_path=out/bazel_module/update //tools/bazel_module:update
# Delete or move the include, then regenerate:
out/bazel_module/update
3.88 - Rules binary toolchain
rules_binary_toolchain creates Bazel toolchains and runnable targets for
packaged executable binaries. Archive entries can include runtime files,
which the generated binary targets expose through Bazel runfiles.
3.88.1 -
project-dns Specification
Purpose
Record the retirement of rules_binary_toolchain landing infrastructure while preserving
its reusable Bazel module.
Requirements
Requirement: Keep landing infrastructure retired
The module SHALL follow the tools boundary and SHALL have no dedicated landing DNS declarations, Terraform root, or operational source exports.
Scenario: Inspect the module after landing retirement
- WHEN the module is consumed from
tools/rules_binary_toolchain - THEN its reusable Bazel rules remain available without landing infrastructure.
3.88.2 -
Rules binary toolchain
Purpose
Provide Bazel toolchains and runnable targets for packaged executable binaries,
including their runtime files. This source baseline was observed on 2026-09-08
at revision 550d7e79b1f5fdbc2b6017b75178471d6914082f.
Sources: project description, lock parsing, module extension, archive repositories, and runnable wrapper.
Requirements
Requirement: Select archives from the declared toolchain lock
The module extension SHALL resolve a requested toolchain by name and version from its JSON lock and create repositories for the matching archives.
Scenario: A requested toolchain has no matching archive
- WHEN the requested toolchain is absent or has no archive matching its locked version
- THEN extension evaluation fails with a diagnostic instead of selecting another version.
Requirement: Verify downloaded archive integrity
Archive repository download and download-and-extract actions SHALL compare the reported integrity against the action’s declared integrity and fail on mismatch.
Scenario: Downloaded content differs from its lock entry
- WHEN a download reports an integrity value different from the lock action
- THEN repository creation fails with the expected and observed integrity values.
Requirement: Preserve runtime files in generated binary targets
Generated native binary and filegroup targets SHALL include the files selected
by each binary’s runtime_files glob patterns, in addition to the executable.
Runnable toolchain wrappers SHALL merge the selected toolchain’s runfiles and
declared data runfiles.
Scenario: A packaged executable needs an adjacent runtime asset
- WHEN an archive declares a runtime asset through
runtime_files - THEN the native binary carries that asset in its data, the filegroup exposes it, and a wrapper carries the toolchain runfiles into execution.
Requirement: Forward wrapper arguments and environment
The runnable wrapper SHALL expand declared location and make-variable arguments,
append invocation arguments, and expose the declared env through
RunEnvironmentInfo.
Scenario: A caller supplies additional command arguments
- WHEN a generated wrapper is invoked with arguments after its configured arguments
- THEN the selected toolchain binary receives both argument sets in that order.
3.88.3 - Bzl
Archive binaries
Each archive binaries entry requires a name and path. It can also set
runtime_files to a list of Bazel glob patterns relative to the unpacked
archive. The generated <name>_native_binary exposes matching files as
runfiles; <name>_filegroup exposes the binary and those same files.
Omit runtime_files when the binary needs no extra runtime files.
3.89 - Rules Dnscontrol
rules_dnscontrol packages a DNSControl JavaScript entrypoint together with
its record configuration files and emits a generated requires.json manifest
of relative paths matching the Bazel runfiles tree. Record symlinks retain a
.json suffix so DNSControl parses them as JSON. Load the manifest with
require() and load each listed path with another require() call;
DNSControl’s JavaScript loader does not implement CommonJS module.exports.
3.90 - Rules docs
rules_docs packages Markdown documentation under a common archive prefix.
Documentation rule
Add the module dependency:
bazel_dep(name = "rules_docs", version = "<VERSION>")
Then declare the package documentation. srcs defaults to
glob(["*.md"]); visibility is optional.
load("@rules_docs//docs:defs.bzl", "docs_filegroup")
docs_filegroup(
name = "docs",
deps = ["child"],
)
Relative dependency names without a colon are normalized to the child
package’s docs target. prefix defaults to the current package beneath
content/docs/.
Files are packaged at their basename by default. When a package’s sources span
subdirectories that hold identically named files, set preserve_paths = True
so each source keeps its package-relative path and the destinations stay
distinct.
Gazelle extension
Generation support is packaged separately so consumers of the documentation rule do not inherit Gazelle and Go dependencies. Add it as a development-only module dependency:
bazel_dep(
name = "rules_docs_gazelle",
version = "<VERSION>",
dev_dependency = True,
)
Add the public language target to the repository’s custom Gazelle binary:
load("@gazelle//:def.bzl", "gazelle_binary")
gazelle_binary(
name = "gazelle_binary",
languages = [
"@rules_docs_gazelle//gazelle",
],
)
The extension only operates in directories where both a BUILD file and a
README.md already exist. Newly generated rules use glob(["*.md"]) and are
visible only to their nearest ancestor Bazel package. Existing srcs, deps,
visibility, and prefix attributes are preserved.
The public @rules_docs_gazelle//gazelle:gazelle_docs binary contains only
this extension and can update a nested workspace without initializing
unrelated language plugins from its parent repository.
3.91 - Rules docs Gazelle
rules_docs_gazelle adds a docs_filegroup to existing Bazel packages that
contain a README.md. The generated rule loads its macro from rules_docs.
Add rules_docs as a normal dependency and this generator as a development
dependency:
bazel_dep(name = "rules_docs", version = "<VERSION>")
bazel_dep(
name = "rules_docs_gazelle",
version = "<VERSION>",
dev_dependency = True,
)
Add the public language target to the repository’s custom Gazelle binary:
load("@gazelle//:def.bzl", "gazelle_binary")
gazelle_binary(
name = "gazelle_binary",
languages = [
"@rules_docs_gazelle//gazelle",
],
)
The extension only operates in directories where both a BUILD file and a
README.md already exist. Newly generated rules use glob(["*.md"]) and are
visible only to their nearest ancestor Bazel package. Existing srcs, deps,
visibility, and prefix attributes are preserved.
The public @rules_docs_gazelle//gazelle:gazelle_docs binary contains only
this extension and can update a nested workspace without initializing
unrelated language plugins from its parent repository.
3.92 - Rules Hugo
rules_hugo builds Hugo sites with a registered Hugo toolchain. It keeps the
site archive in the target configuration and the Hugo binary in the execution
configuration so site sources are not rebuilt for the execution platform.
al_hugo_site wraps a site source archive and its PostCSS tooling.
al_hugo_run_binary builds the site with the registered Hugo toolchain and
al_hugo_binary exposes a runnable Hugo command for a site. The optional
al_hugo_worker rule runs the build through a persistent worker.
Module setup
bazel_dep(name = "rules_hugo", version = "<VERSION>")
The Hugo toolchain is generated by the al_hugo_extension module
extension, not declared in @rules_hugo//pkg/bzl. Declare the extension
in the root module, request the toolchain archives for the Hugo version,
and register the generated toolchain repository:
al_hugo_extension = use_extension(
"@rules_hugo//pkg/bzl:al_hugo_extension.bzl",
"al_hugo_extension",
)
al_hugo_extension.toolchains(
name = "my_hugo_toolchain",
version = "0.165.0",
)
use_repo(
al_hugo_extension,
"my_hugo_toolchain_os_linux_cpu_x86_64",
)
register_toolchains("@my_hugo_toolchain_os_linux_cpu_x86_64")
The generated repository name is "<name>_<os>_<cpu>" for each platform
in the requested version’s archive set. See
projects/alwaldend.com/include.MODULE.bazel for a complete example that
also wires the Hugo lock file and remote themes.
3.92.1 -
project-dns Specification
Purpose
Record the retirement of rules_hugo landing infrastructure while preserving
its reusable Bazel module.
Requirements
Requirement: Keep landing infrastructure retired
The module SHALL follow the tools boundary and SHALL have no dedicated landing DNS declarations, Terraform root, or operational source exports.
Scenario: Inspect the module after landing retirement
- WHEN the module is consumed from
tools/rules_hugo - THEN its reusable Bazel rules remain available without landing infrastructure.
3.92.2 -
Rules Hugo
Purpose
Build and run Hugo sites with registered Bazel toolchains, site source archives,
and declared PostCSS tooling. This source baseline was observed on 2026-09-08
at revision 550d7e79b1f5fdbc2b6017b75178471d6914082f.
Sources: project description, site provider rule, build rule, toolchain extension, and worker rule.
Requirements
Requirement: Separate site inputs from execution tools
al_hugo_site SHALL retain the .tar site archive in the target configuration
and resolve its executable PostCSS dependency in the execution configuration.
Build rules SHALL obtain Hugo from the registered Hugo toolchain.
Scenario: The target and execution platforms differ
- WHEN Bazel analyzes a Hugo site build for distinct target and execution platforms
- THEN the site archive remains a target input and Hugo and PostCSS are selected as execution tools.
Requirement: Build into a declared destination directory
al_hugo_run_binary SHALL unpack the site archive, make its PostCSS executable
available to Hugo, and invoke Hugo with --destination pointing to the declared
output directory.
Scenario: A site build specifies an output directory
- WHEN a caller supplies
out_dirand additional Hugo arguments - THEN the action appends the declared destination to those arguments and exposes the output directory through
DefaultInfo.
Requirement: Generate platform-specific toolchain repositories
The Hugo module extension SHALL create toolchain repositories from the archive set associated with the requested version, carrying each archive’s declared integrity and execution-platform constraints.
Scenario: A supported version has a Linux x86-64 archive
- WHEN a toolchain tag requests that version under a repository name prefix
- THEN the extension creates the corresponding
<name>_os_linux_cpu_x86_64repository with a Hugo toolchain constrained to that platform.
Requirement: Support an explicit persistent-worker build path
al_hugo_worker SHALL serialize site inputs, arguments, tools, environment, and
output location into a flag file and invoke its worker with Bazel’s protobuf
worker protocol requirements.
Scenario: A caller chooses the worker rule
- WHEN a site is built with
al_hugo_worker - THEN Bazel receives a worker-capable
HugoSiteaction whose declared output directory is<target>.dest.
3.93 - Rules Promptfoo
rules_promptfoo runs repository skills through a pinned Promptfoo CLI. It
keeps dependency resolution reproducible in Bazel while deliberately running
model calls only at test runtime.
Setup
Add the module and its skill-provider dependency:
bazel_dep(name = "rules_promptfoo", version = "<VERSION>")
bazel_dep(name = "rules_skills", version = "<VERSION>")
The development checkout uses sibling local_path_override declarations.
Published releases must replace those local overrides with registry versions.
Evaluate a skill
load("@rules_promptfoo//promptfoo:defs.bzl", "promptfoo_test")
promptfoo_test(
name = "answer_question_eval",
config = "promptfooconfig.yaml",
skills = ["//projects/agents/skills/answer-question:skill"],
env_inherit = [
"CODEX_HOME",
"CODEX_PATH_OVERRIDE",
],
reuse_codex_login = True,
)
The runner physically copies each selected SkillInfo.files_by_path bundle
to an isolated Bazel test-temporary
workspace/.agents/skills/<name>/ tree. Point the Codex SDK provider at the
exported workspace and, when using a compatible host Codex executable, at the
exported executable path:
prompts:
- "{{ question }}"
providers:
- id: openai:codex-sdk
config:
codex_path_override: "{{ env.CODEX_PATH_OVERRIDE }}"
working_dir: "{{ env.PROMPTFOO_SKILL_WORKSPACE }}"
cli_env:
CODEX_HOME: "{{ env.PROMPTFOO_SUBJECT_CODEX_HOME }}"
tests:
- vars:
question: Why is the sky blue?
assert:
- type: skill-used
value: answer-question
Live eval targets are tagged manual, requires-network, no-cache,
no-remote, and local. They also pass --no-cache, --no-write, and
--no-share to Promptfoo; local prevents sandboxed or remote execution when
the caller opts into host Codex credentials. The runner exports a separate
empty PROMPTFOO_JUDGE_WORKSPACE so a model judge need not discover the skill
it grades. Explicit results are preserved as the Bazel undeclared output
results.json; Promptfoo configuration, cache, isolated workspaces, and
subprocess temporary files stay in a mode-0700 directory below Bazel’s
absolute TEST_TMPDIR and are removed on exit. Bazel owns and cleans that
private parent directory as a second cleanup boundary. Callers that must
redirect test scratch can use Bazel’s --test_tmpdir option.
The runner deliberately uses Bazel-managed temporary storage instead of a
source-checkout out/ directory. Putting a no-skill control below the source
tree would expose the checkout’s .agents directory through an ancestor and
invalidate the isolation that the control is meant to measure. This is the
repository policy’s operating-system-temporary exception for a tool that
cannot safely use task-local source storage; the runner still removes its
randomized child directory on normal exit and handled signals. The runner
rejects a TEST_TMPDIR below any ancestor containing .agents, so do not
redirect --test_tmpdir into a source checkout or another agent tree.
results.json contains the evaluated prompts and model outputs. CI may collect
undeclared outputs when a manual eval is explicitly run, so treat the artifact
as potentially sensitive even though the target is no-cache and no-remote.
Run a live target explicitly and pass the absolute path to an existing Codex
login and a compatible host Codex executable through the test environment,
never credential contents through env or a checked-in config. Set the
provider’s codex_path_override from CODEX_PATH_OVERRIDE:
bazel_agent bazel test //path/to:answer_question_eval \
--test_env=CODEX_HOME=/absolute/path/to/.codex \
--test_env=CODEX_PATH_OVERRIDE=/absolute/path/to/codex \
--test_output=errors
If that Codex installation reaches OpenAI through host proxy variables, pass
only the needed names as well (for example, --test_env=HTTPS_PROXY and
--test_env=NO_PROXY) and declare the same names in the rule’s env_inherit.
Do not put proxy values in checked-in files.
With reuse_codex_login = True, the runner links only the writable
CODEX_HOME/auth.json into distinct, otherwise empty subject and judge Codex
homes inside its mode-0700 state directory. Provider configs can select them
through PROMPTFOO_SUBJECT_CODEX_HOME and PROMPTFOO_JUDGE_CODEX_HOME. The
runner holds an exclusive advisory lock on the stable login directory for the
complete test, serializing repository eval targets that use the same login.
With a compatible Codex executable, an automatic refresh writes through either
link to the persistent host file, while the host’s config.toml, skills,
plugins, memories, and MCP configuration remain unstaged and cannot contaminate
the subject, no-skill control, or judge. This reuses the caller’s existing
login state; it does not mint or export a token. An API-key-backed target may
instead inherit OPENAI_API_KEY without enabling login reuse.
For this purpose, compatible means that file-backed auth updates open and
truncate $CODEX_HOME/auth.json, preserving the symlink. The bundled Codex
0.144.0 implementation and the tested host Codex 0.150.1 do this. Do not
override the executable with an implementation that atomically replaces the
isolated auth.json path: that would replace the symlink, split subject and
judge state, and fail to persist a rotated refresh token. See the corresponding
OpenAI Codex file-storage implementations for
0.144.0
and
0.150.1.
Login reuse also forces Promptfoo’s CLI, assertion-worker, and prompt-suggestion concurrency to one, overriding higher configuration values so subject and judge Codex processes cannot race the same single-use refresh token within one test.
Do not run another Codex process against the same auth.json concurrently;
unrelated processes do not honor the runner’s advisory lock. ChatGPT-managed
auth can rotate its refresh token, so the refreshed file must remain persistent
and have a single serialized user. The local-login mode is unsuitable for
shared or untrusted CI; use an API key or supported workload identity there.
In this public repository it is strictly a manual, trusted-developer workflow;
never seed or persist ChatGPT-managed auth in repository CI or artifacts.
See OpenAI’s
managed-auth guidance for the
refresh and serialization requirements.
Run credentialed live targets only from a reviewed, trusted revision. The isolated working directory and read-only provider setting reduce accidental writes, but Codex still has whatever host read access its enforced sandbox policy permits and can send prompt context to the configured service.
Files in data are placed in the test runfiles. args are passed literally;
they do not expand Bazel location expressions. Prefer keeping checked-in
Promptfoo prompt and dataset files beside the config and list them in data
so Promptfoo’s own config-relative path resolution remains portable.
The env and env_inherit attributes cannot override Bazel’s test temporary
directories or the runner-owned TMPDIR, TMP, and TEMP values.
Validate without a model call
load(
"@rules_promptfoo//promptfoo:defs.bzl",
"promptfoo_validate_test",
)
promptfoo_validate_test(
name = "promptfoo_config_test",
config = "promptfooconfig.yaml",
)
Validation is an ordinary offline Bazel test and does not receive the live
eval tags. It rejects env_inherit so validation cannot accidentally receive
host credentials.
Dependency boundary
The module pins Promptfoo and the Codex SDK with a dedicated pnpm lock. npm
lifecycle hooks and optional dependencies are disabled. The Codex executable
and Promptfoo’s libSQL binding are promoted to explicit Linux x86-64
dependencies. AJV is also promoted because ajv-formats declares its runtime
peer as optional, which would otherwise be removed by no_optional. The
bundled real CLI target is intentionally compatible only with glibc-based
Linux x86-64. Bazel enforces the OS and CPU constraints, but this repository
does not currently expose a libc constraint. Other Promptfoo providers that
rely on omitted optional packages or install scripts must be reviewed and
promoted explicitly before use.
The pinned Promptfoo distribution is patched so
PROMPTFOO_DISABLE_TELEMETRY=1 also suppresses its best-effort request to
r.promptfoo.app. The upstream 0.122.2 telemetry implementation otherwise
records a “telemetry disabled” event through that separate endpoint. The same
patch makes Promptfoo’s otherwise hard-coded prompt-suggestion concurrency
honor the runner’s serialization setting.
3.94 - Rules Promptfoo Gazelle
rules_promptfoo_gazelle generates required, offline
promptfoo_validate_test targets for Promptfoo configurations below an
evals/ directory. It never creates an evals subpackage and never generates
live promptfoo_test targets.
Add rules_promptfoo as a normal dependency and this generator as a
development dependency:
bazel_dep(name = "rules_promptfoo", version = "<VERSION>")
bazel_dep(
name = "rules_promptfoo_gazelle",
version = "<VERSION>",
dev_dependency = True,
)
For one-pass skill package creation, also add rules_skills as a normal
dependency and rules_skill_gazelle as a development dependency:
bazel_dep(name = "rules_skills", version = "<VERSION>")
bazel_dep(
name = "rules_skill_gazelle",
version = "<VERSION>",
dev_dependency = True,
)
Add both public language targets to the repository’s custom Gazelle binary:
load("@gazelle//:def.bzl", "gazelle_binary")
gazelle_binary(
name = "gazelle_binary",
languages = [
"@rules_promptfoo_gazelle//gazelle",
"@rules_skill_gazelle//gazelle",
],
)
With both extensions installed, a fresh directory containing SKILL.md and a
conventional Promptfoo configuration receives both skill_library and
promptfoo_validate_test targets in one Gazelle run; it does not need an
existing BUILD file.
The extension recognizes these conventional configuration paths:
evals/promptfooconfig.yaml
evals/promptfooconfig.<variant>.yaml
evals/promptfooconfig.yml
evals/promptfooconfig.<variant>.json
The default file produces eval_config_test; a variant produces
eval_<sanitized_variant>_config_test. Variants are lowercased, and runs of
characters other than ASCII letters and digits become underscores. Colliding
sanitized names receive a stable path-derived __<8 lowercase hex digits>
suffix. The double underscore cannot be produced by the sanitizer, so a
variant cannot claim a collision target’s namespace.
When a non-root containing package has a SKILL.md, each ordinary validation
target stages that package’s conventional :skill target. Repository-root
skills are unsupported by rules_skills, so a root-package SKILL.md does not
infer that label. The exact no_skill variant omits skills so it remains a
control. A generic Promptfoo package without SKILL.md receives no inferred
skill label. Every non-configuration regular file under evals/, including
README.md and test cases, is added to data in sorted order. Directories
containing BUILD, BUILD.bazel, or an additional filename configured as
valid in Gazelle are package boundaries and are not traversed.
The extension reconciles config, data, and skills when a discovered
configuration matches a conventionally named validation target. Adding or
editing eval files therefore updates those attributes on the next run.
Removing or renaming a configuration does not delete the old target: a name
shape is not reliable proof that Gazelle created a rule, so stale targets must
be removed explicitly. Gazelle’s # keep semantics remain available at the
rule, attribute, and individual list-item levels for intentional overrides.
Other attributes, including args, env, tags, and visibility, remain
manual and are preserved while the generated target exists. Existing manual
or live promptfoo_test rules are also left intact.
The extension does not follow a symlink used as the package’s evals
directory, because it could escape the repository. Such a symlink, or another
unexpected filesystem scan error including an error while checking a candidate
package boundary, is a non-destructive no-op rather than a signal to remove
targets. Before scanning, it also resolves the repository root and package
directory and refuses a package whose resolved path escapes the workspace,
including a package reached through Gazelle’s symlink-following support. The
extension manages the shared load for both Promptfoo rule symbols and uses
Bzlmod’s apparent repository name.
The public @rules_promptfoo_gazelle//gazelle:gazelle_promptfoo binary
contains only this extension and can update a nested workspace without
initializing unrelated language plugins from its parent repository.
3.95 - Rules skill
rules_skills packages all files belonging to a Codex skill and validates its
instructions and optional OpenAI metadata with a hermetic Bazel aspect.
Getting started
Add the module and register the validation aspect:
bazel_dep(name = "rules_skills", version = "<VERSION>")
build --aspects @rules_skills//skill:defs.bzl%skill_validation_aspect
build --output_groups=+skill_validation
Declare one library in the skill’s named, non-root package:
load("@rules_skills//skill:defs.bzl", "skill_library")
skill_library(
name = "skill",
srcs = glob(
["**"],
exclude = [
"BUILD.bazel",
"BUILD",
"evals/**",
],
),
)
The package’s final path segment is the skill name, so a skill_library
cannot be declared in a repository root package. Move a root-level skill into
a named subpackage before declaring it.
Building the library materializes the skill_validation output group. The
aspect checks SKILL.md, verifies that the frontmatter name matches its
package directory, and validates agents/openai.yaml when it is present.
Consuming a skill
Rules that install or evaluate skills can require the public SkillInfo
provider:
load("@rules_skills//skill:defs.bzl", "SkillInfo")
attrs = {
"skill": attr.label(providers = [SkillInfo]),
}
SkillInfo exposes these fields:
nameis the logical skill name derived from the final segment ofroot. The validation aspect verifies that theSKILL.mdfrontmatter uses the same name.rootis the owning Bazel package path within the skill’s repository, such asprojects/agents/skills/answer-question. It has no repository, execution-path, or runfiles prefix. It is always non-empty because repository root packages are unsupported.files_by_pathmaps slash-separated paths relative torootto BazelFilevalues. It includesSKILL.md, preserves nested paths such asagents/openai.yaml, and has the same shape for source and generated files.filesremains thedepsetof all skill files.skillis the distinguishedSKILL.mdfile, andopenai_yamlis the optional distinguishedagents/openai.yamlfile.
Consumers should use files_by_path when staging a bundle instead of parsing
File.path or File.short_path. Every source must belong to the skill’s Bazel
package, and duplicate logical paths are rejected during analysis.
Packaging skills from an external archive
Use skill_archives when skills are maintained upstream and consumed as a
pinned archive. The external repository’s BUILD file derives one target per
skill directory from a wildcard, so a new upstream skill needs no edit here:
load("@rules_skills//skill:defs.bzl", "skill_archives")
skill_archives(
name = "skills",
roots = [
manifest.rsplit("/", 1)[0]
for manifest in glob(["skills/*/SKILL.md"])
],
)
skill_archives is a macro over the skill_archive rule. Each generated
target’s name is its skill directory’s final segment, root is the skill
directory inside the package, and its packaged logical paths are relative to
root. Analysis fails when a root has no SKILL.md. Declare one
skill_archive directly when a single skill needs a hand-written target.
Writing the source-tree discovery directory
Use skills_write to reconcile .agents/skills from declared skills. Each
symlinks label is installed as a direct relative symlink to its canonical
root; each archives label is copied in as regular files, which is how archive
skills are materialized into the consuming repository:
load("@rules_skills//skill:defs.bzl", "skills_write")
skills_write(
name = "write_skills",
archives = ["@org_fissionai_openspec//:openspec-propose"],
discovery_dir = ".agents/skills",
symlinks = ["//projects/agents/skills/answer-question:skill"],
workspace_marker = "//:AGENTS.md",
)
workspace_marker is a source file in the consuming repository used to
resolve the workspace root from test runfiles. Reconcile and verify:
bazel run //.agents:write_skills
bazel test //.agents:write_skills_test
The generated check requires exactly the declared names: missing, extra, or
stale entries fail, and a written entry must match its declared source
byte-for-byte. The updater holds a sibling <discovery_dir>.lock directory
while it changes entries; a process killed without running its exit trap can
leave that lock behind. After confirming no updater is active, remove the empty
lock directory and rerun the updater.
Both rules require POSIX symlinks and Bash and are limited to Linux and macOS checkouts; native Windows checkouts are not supported.
3.96 - Rules skill Gazelle
rules_skill_gazelle adds a skill_library(name = "skill") to each named
subpackage that contains a SKILL.md. The generated rule loads its macro from
the apparent rules_skills repository, so Bzlmod repository mappings are
respected.
Add rules_skills as a normal dependency and this generator as a development
dependency:
bazel_dep(name = "rules_skills", version = "<VERSION>")
bazel_dep(
name = "rules_skill_gazelle",
version = "<VERSION>",
dev_dependency = True,
)
Add the public language target to the repository’s custom Gazelle binary:
load("@gazelle//:def.bzl", "gazelle_binary")
gazelle_binary(
name = "gazelle_binary",
languages = [
"@rules_skill_gazelle//gazelle",
],
)
The generated source bundle is:
load("@rules_skills//skill:defs.bzl", "skill_library")
skill_library(
name = "skill",
srcs = glob(
["**"],
exclude = [
"BUILD.bazel",
"BUILD",
"evals/**",
],
),
)
The generator always excludes BUILD.bazel and BUILD, plus every custom
BUILD filename configured in Gazelle. Duplicate configured names are removed.
SKILL.md is sufficient for Gazelle to create a new BUILD file below the
repository root. A root-level SKILL.md is ignored because rules_skills
requires a named package from which it can derive the skill name. Existing
attributes on a manually maintained skill_library(name = "skill") are
preserved, and a missing SKILL.md does not delete a manual rule.
The public @rules_skill_gazelle//gazelle:gazelle_skills binary contains only
this extension and can update a nested workspace without initializing
unrelated language plugins from its parent repository.
3.97 - Rules template
rules_template provides Bazel rules and a Go command for rendering template
files. A registered toolchain supplies the templating executable to build
actions.
Getting started
MODULE.bazel:
bazel_dep(name = "rules_template", version = "<VERSION>")
register_toolchains("@rules_template//main/bzl:all")
BUILD.bazel:
3.97.1 -
project-dns Specification
Purpose
Record the retirement of rules_template landing infrastructure while preserving
its reusable Bazel module.
Requirements
Requirement: Keep landing infrastructure retired
The module SHALL follow the tools boundary and SHALL have no dedicated landing DNS declarations, Terraform root, or operational source exports.
Scenario: Inspect the module after landing retirement
- WHEN the module is consumed from
tools/rules_template - THEN its reusable Bazel rules remain available without landing infrastructure.
3.97.2 -
Rules template
Purpose
Render Go text templates from declared data files through a command and a Bazel
toolchain rule. This source baseline was observed on 2026-09-08 at revision
550d7e79b1f5fdbc2b6017b75178471d6914082f. The command operates on one template
and output per invocation; the rule’s list attributes do not establish a
multi-template rendering guarantee.
Sources: project description, command flags, templater, template functions, and Bazel action.
Requirements
Requirement: Load supported data formats into template context
The template command SHALL load data files in argument order into DataFiles,
decode .toml, .json, .ndjson, and .yaml data, and expose .txt files as
lines without structured decoding. --extension SHALL override extension
selection for the supplied data files.
Scenario: A caller renders a template using newline-delimited JSON
- WHEN a declared
.ndjsoninput contains valid JSON on each data line - THEN its template context contains a parsed sequence in
Dataand the input lines inLines.
Requirement: Report unsupported formats and rendering failures
The command SHALL return errors for unsupported data extensions, failed reads, invalid structured data, invalid template syntax, template execution failures, and failed output writes.
Scenario: A data file uses an unsupported extension
- WHEN a data path has an unrecognized extension and no supported override
- THEN rendering fails with an unsupported-extension diagnostic identifying the data path.
Requirement: Expose the registered template function set
Template execution SHALL use the project’s function map, including JSON serialization, HTML escaping, path basename and dirname helpers, and first and last element helpers.
Scenario: A template serializes structured data
- WHEN a valid template invokes
to_jsonon JSON-serializable context data - THEN the function returns the JSON representation for inclusion in the output.
Requirement: Render declared Bazel inputs with the selected toolchain
template_run_binary SHALL invoke the registered templater with its template
subcommand, declare source and data files as inputs, declare output files, and
forward additional rule arguments.
Scenario: A target declares one template and one output
- WHEN Bazel executes the target with its registered template toolchain
- THEN the action passes the template, ordered data flags, and output path to the templater and exposes the declared output to downstream targets.
3.97.3 - Bzl
3.98 - Rules Terraform
This standalone module owns reusable Terraform rules. Terraform and provider archives are declared Bazel inputs. Provider downloads belong to the Bzlmod extension; Terraform uses a filesystem mirror containing only the providers selected by its target.
The extension resolves one version per provider source. Consumers select a provider by Bazel label. Explicit version override policy can be added at this resolution boundary later; conflicting versions currently fail resolution.
Repository authentication and backend injection are supplied by the caller. The module does not depend on the enclosing monorepo’s AL or Vault packages.
Declare providers
Use terraform_providers from @rules_terraform//:extensions.bzl. Each
archive tag requires a unique repository name, canonical lowercase
source (hostname/namespace/type), exact version, Terraform platform
(os_arch), immutable HTTPS urls, and SHA256 SRI integrity. Verify the
integrity against the publisher’s release checksums before declaring it.
Import each generated repository with use_repo. Its public :provider
target exposes TerraformProviderInfo. Different platforms can share one
provider version; duplicate archives or conflicting versions fail before
repositories are registered. Provider downloads use Bazel’s verified downloader
and repository cache, without executing host tools or querying a registry.
This repository’s concrete declarations live in the Terraform dependency package. The module is currently developed with a local Bzlmod override; no registry release is implied.
Run Terraform
load("@rules_terraform//terraform:defs.bzl", "terraform_binary", "terraform_test")
terraform_binary(
name = "tf_plan",
srcs = glob(["*.tf"]),
data = ["//modules/example:source"],
providers = ["@my_provider_linux_amd64//:provider"],
arguments = ["plan"],
)
terraform_test(
name = "tf_fmt_test",
srcs = glob(["*.tf"]),
arguments = ["--direct", "fmt", "-check", "-recursive"],
)
arguments are fixed runner/Terraform arguments; command-line arguments are
appended. srcs and data declare configuration, local child modules, and files
read by the configuration. chdir defaults to the target’s package. The
rules package ZIPs at
HOST/NAMESPACE/TYPE/terraform-provider-TYPE_VERSION_OS_ARCH.zip beneath a
target-specific runfiles mirror, following Terraform’s
filesystem mirror contract.
Command maps and wrappers
The same terraform/defs.bzl exports terraform_binary_map,
terraform_target_binary_map, and terraform_test_map. They preserve explicit
operation names such as tf.plan, tf.apply, and tf_tests.fmt_test.
Targeted maps produce plan/show/apply commands; their apply command requires
one saved plan. No unnamed apply alias is generated.
Maps run the Terraform rules directly by default. Callers can supply a
wrapper macro and its wrapper_kwargs to compose authentication or other
command setup without adding that framework to rules_terraform. The wrapper
receives the final target name, the inner executable in args, its runfiles
in data, and common target attributes. wrapper_kwargs cannot replace those
arguments or duplicate common attributes. Wrapped tests require a test wrapper.
Repository consumers load AL’s generic al_binary_run or
al_binary_run_test and pass their configs and run_args in
wrapper_kwargs. Their plugin binaries remain in data. Provider-free tests
can use the Terraform test maps directly. Repository root command bindings
live with the shared AL configuration.
The default Terraform executable is the pinned toolchain in
terraform/binary_toolchain.json, acquired through rules_binary_toolchain.
The initial supported executable platform is Linux amd64. The optional
terraform executable attribute permits a caller-supplied Bazel tool.
@rules_terraform//terraform:cli exposes the pinned CLI for formatting and
other consumers that do not initialize providers.
Initialization and generated locks remain in runtime workspaces. No source
.terraform.lock.hcl is required. The launcher contract
describes working directories, direct commands, saved plans, and manifest-only
execution. Provider and backend operations can still use the network when
the operator invokes them; provider acquisition itself has no runtime registry
fallback. Configuration modules must be declared local inputs.
3.98.1 -
terraform-execution Specification
Purpose
Provide reusable Bazel rules that acquire pinned Terraform providers and run Terraform with declared configuration, executable, and provider inputs.
Requirements
Requirement: Verified provider acquisition
The provider module extension SHALL download immutable HTTPS archives with mandatory SHA256 integrity through Bazel repository fetching. It SHALL select one version for each canonical provider source across the extension graph.
Scenario: Conflicting provider versions
- WHEN declarations select different versions of the same provider source
- THEN extension resolution fails before provider repositories are created.
Scenario: Verified archive
- WHEN a provider archive is fetched
- THEN Bazel verifies the declared integrity and exposes its canonical source, version, platform, and packed filesystem-mirror path.
Requirement: Declared provider execution
Terraform rules SHALL place selected provider archives in runfiles using the packed filesystem-mirror layout. The runner SHALL configure only that mirror for provider installation and SHALL preserve the declared Terraform executable.
Scenario: Offline initialization
- WHEN all required providers are declared by a target
- THEN initialization and provider schema validation succeed without registry access or a host provider cache.
Scenario: Missing provider
- WHEN configuration requires a provider absent from the target’s mirror
- THEN initialization fails without falling back to a registry download.
Requirement: Reusable execution and repository integration
The reusable module SHALL own Terraform execution and named command maps while remaining independent of parent repository labels. Maps SHALL support optional caller-supplied command wrappers. Repository consumers SHALL select generic AL wrappers explicitly to preserve configuration, plugin lifecycle, backend injection, named operations, and the saved-plan apply guard. Shared provider pins SHALL be owned by third_party/terraform.
Scenario: Saved-plan apply
- WHEN a targeted apply wrapper receives a missing plan or extra arguments
- THEN the runner rejects it before Terraform initialization.
Scenario: Repository migration
- WHEN repository Terraform commands and tests are analyzed
- THEN they load maps from rules_terraform, select shared provider labels, and require neither tools/terraform nor a checked-in .terraform.lock.hcl file.
Scenario: Optional wrapper
- WHEN a command map supplies a wrapper
- THEN the wrapper receives the declared Terraform invocation and runfiles without requiring a framework dependency in the reusable module.
Scenario: Direct tests
- WHEN a test map needs no external command setup
- THEN it runs the Terraform test rule without an AL dependency.
3.98.2 - Terraform launcher
This implementation launcher reads the generated target sidecar and resolves Terraform, configuration inputs, and provider archives through Bazel runfiles. Consumer targets use the public Terraform rules instead of invoking this binary directly.
The launcher selects the target’s working directory inside the runfiles tree. Source files can remain symlinks, so formatting retains its existing source behavior. Initialization writes lockfiles and Terraform metadata in that runfiles directory. Saved plans and local state retain their normal paths relative to the working directory; the launcher never removes them.
Each invocation uses a private CLI configuration containing only the declared filesystem provider mirror. It overrides user CLI configuration, removes inherited provider-cache settings, disables checkpoint checks, and rejects injected CLI arguments, provider reattachment, and provider-download commands. Missing provider versions and platforms fail without a registry installation fallback. Temporary CLI configuration and any materialized provider mirror are removed on exit.
Before commands that can load providers, the launcher reads Terraform’s lock
selections through version -json and checks every selected installed package
against its declared archive. Source addresses, versions, file paths, and file
contents must match; undeclared selections and extra, missing, modified, or linked
package files fail before the requested command starts. The check honors
TF_DATA_DIR, including paths relative to Terraform’s working directory. It also
runs after explicit initialization. This adds local archive decompression and
hashing work; it does not initialize the backend or contact a registry. The
working directory must not be modified concurrently during execution.
Initialization runs before the requested command unless --direct precedes it.
Its standard output goes to standard error, preserving structured command output.
AL_TF_BACKEND_CONFIG* environment values remain literal initialization
arguments; other provider and backend environment, including TF_HTTP_*, is
preserved. Terraform process exit codes are returned unchanged.
Configuration supports declared local modules. Provider installation is isolated; the launcher does not inspect module source expressions or sandbox Terraform’s service connections.
--require-saved-plan accepts only apply <saved-plan-file>. The file must exist
and be regular; relative paths resolve against the selected working directory.
Argument and environment validation happens before initialization.
Manifest-only tests materialize declared configuration inputs beneath
TEST_TMPDIR, retaining their workspace until Bazel removes that test directory.
Outside tests, a directory runfiles tree is required to preserve persistent
working-directory semantics. An explicit --chdir before the Terraform command
selects a caller-owned directory when that behavior is intended.
Invocation scratch uses TEST_TMPDIR, then an explicitly configured TMPDIR,
then BUILD_WORKSPACE_DIRECTORY/out/rules_terraform/runtime. It never falls back
to the system temporary directory.
3.99 - rules_iso
Module extension that downloads ISO images with http_file and adds a
runnable iso_flash target next to each image.
3.100 - Run tool
3.100.1 - Bzl
3.100.1.1 - al_run_tool
al_run_tool
load("@com_alwaldend_src//tools/run_tool/main/bzl:al_run_tool.bzl", "al_run_tool")
al_run_tool(name, tool, executable, test, **kwargs)
Generate either native_test, native_binary, or run_binary target
PARAMETERS
3.101 - Selene
Selene provides correctness-oriented linting for the repository’s
hand-maintained Lua files. The repository standard-library description permits
the intentional al configuration DSL and Neovim’s vim global while keeping
Selene’s ordinary Lua diagnostics enabled.
Links
- Repo: https://github.com/Kampfkarren/selene
- Documentation: https://kampfkarren.github.io/selene/
3.102 - Sh
3.102.1 - Bzl
3.102.1.1 - al_sh_library
al_sh_library
load("@com_alwaldend_src//tools/sh/main/bzl:al_sh_library.bzl", "al_sh_library")
al_sh_library(name, shfmt_src, editorconfig_src, shellcheck_src, run_args_src, visibility,
test_data, **sh_kwargs)
Create targets for a shell library
Targets:
- ${name}.shfmt_fix: executable to run shfmt
- ${name}.shfmt_test: test whether the script is formatted
- ${name}.shellcheck_test: shellcheck test
PARAMETERS
3.102.1.2 - al_write_script
al_write_script
load("@com_alwaldend_src//tools/sh/main/bzl:al_write_script.bzl", "al_write_script")
al_write_script(name, out, content, make_vars, set_flags, shebang)
Write a script and make it executable
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| out | Output file | Label; nonconfigurable | required | |
| content | Script content | String | required | |
| make_vars | Additional make vars | Dictionary: String -> String | optional | {} |
| set_flags | Flags to pass to set | List of strings | optional | ["-eu"] |
| shebang | Sheband to use | String | optional | "#!/usr/bin/env sh" |
3.108 - Toml
3.108.1 - Bzl
3.108.1.1 - al_toml_data
al_toml_data
load("@com_alwaldend_src//tools/toml/main/bzl:al_toml_data.bzl", "al_toml_data")
al_toml_data(name, deps, srcs, tomlv)
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| deps | Toml data targets | List of labels | optional | [] |
| srcs | Toml files | List of labels | optional | [] |
| tomlv | Tomlv target to use for validation | Label | optional | "@com_alwaldend_src//tools/tomlv" |
3.108.1.2 - al_toml_info
AlTomlInfo
load("@com_alwaldend_src//tools/toml/main/bzl:al_toml_info.bzl", "AlTomlInfo")
AlTomlInfo(srcs, deps)
Provide toml data info
FIELDS
| Name | Description |
|---|---|
| srcs | Toml files |
| deps | Toml data targets |
3.108.1.3 - al_toml_validate
al_toml_validate
load("@com_alwaldend_src//tools/toml/main/bzl:al_toml_validate.bzl", "al_toml_validate")
al_toml_validate()
Aspect adding linters for toml files
ASPECT ATTRIBUTES
| Name | Type |
|---|---|
| deps | String |
ATTRIBUTES
3.109 - Tomlv
3.111 - Transitive sources
3.111.1 - Bzl
3.111.1.1 - al_transitive_sources
AlTransitiveSources
load("@com_alwaldend_src//tools/transitive_sources/main/bzl:al_transitive_sources.bzl", "AlTransitiveSources")
AlTransitiveSources(transitive_sources)
Provide transitive sources
- https://github.com/bazelbuild/examples/blob/main/rules/depsets/foo.bzl
- https://stackoverflow.com/a/57699683
FIELDS
| Name | Description |
|---|---|
| transitive_sources | - |
al_transitive_sources
load("@com_alwaldend_src//tools/transitive_sources/main/bzl:al_transitive_sources.bzl", "al_transitive_sources")
al_transitive_sources(srcs, deps)
Obtain the source files for a target and its transitive dependencies.
PARAMETERS
| Name | Description | Default Value |
|---|---|---|
| srcs | a list of source files | none |
| deps | a list of targets that are direct dependencies | none |
RETURNS
a collection of the transitive sources
3.112 - Trufflehog
The normal //tools/trufflehog:repo_test scans the history reachable from the
checked-out HEAD and skips unrelated local refs. Run the manual
//tools/trufflehog:repo_all_refs_test target explicitly when an audit must
include every local Git ref, such as T3 checkpoint refs from other worktrees.
Links
3.113 - Twine
3.114 - Txt
3.114.1 - Bzl
3.114.1.1 - al_combine_files
al_combine_files
load("@com_alwaldend_src//tools/txt/main/bzl:al_combine_files.bzl", "al_combine_files")
al_combine_files(name, srcs, **kwargs)
Create a genrule combining several files into one
PARAMETERS
| Name | Description | Default Value |
|---|---|---|
| name | genrule target | none |
| srcs | list of labels to combine | none |
| kwargs | other genrule kwargs | none |
3.114.1.2 - al_txt_data
al_txt_data
load("@com_alwaldend_src//tools/txt/main/bzl:al_txt_data.bzl", "al_txt_data")
al_txt_data(name, srcs, **kwargs)
Text data
PARAMETERS
| Name | Description | Default Value |
|---|---|---|
| name | target name | none |
| srcs | sources | none |
| kwargs | filegroup kwargs | none |
3.115 - Vault
Links
The root //:vault and //:vault.* labels delegate to wrappers in
//tools/vault/cmd/workspace, using //tools/al:config. //tools/vault:vault
is the standalone CLI; the wrappers add the existing AL environment injection.
3.115.1 - Backup
3.115.2 - Forgejo login
The plugin registers token removal before issuance, using a unique token name. Startup failure and normal shutdown attempt removal through the authenticated Forgejo browser session, including when creation did not return a usable token. Cleanup parses the complete applications settings page and verifies token absence after deletion. It then logs out the invocation’s browser session and verifies that the retained original cookie no longer accesses authenticated settings. Cleanup failures are reported.
The parser follows the Forgejo 15.0.3 applications template: all tokens appear on
one page, each in a flex-item row with a title and a matching delete button.
It requires the applications page marker and new-token link before accepting an
empty list. Login pages, invalid token IDs, duplicates, and responses larger than
4 MiB fail closed. A changed upstream template may require a parser update.
Network requests have a ten-second timeout and honor cancellation. Forced process
termination or an unavailable Forgejo server can prevent cleanup; Forgejo tokens
do not acquire an expiry merely because this plugin created them.
3.115.2.1 - api
Java
load("@rules_java//java:defs.bzl", "java_library")
java_library(
name = "name",
deps = [
"@com_alwaldend_src//tools/vault/forgejo_login:api_java_library",
],
)
Golang
load("@rules_go//go:def.bzl", "go_library")
go_library(
name = "name",
deps = [
"@com_alwaldend_src//tools/vault/forgejo_login:forgejo_login",
],
)
Proto
syntax = "proto3";
package com.alwaldend.src.tools.vault.forgejo_login.forgejo_login_proto;
option go_package = "git.alwaldend.com/alwaldend/src/tools/vault/forgejo_login/forgejo_login_proto";
message Config {
string forgejo_url = 1;
string forgejo_oauth_name = 2;
string vault_conn = 3;
string vault_auth = 4;
}
3.115.3 - Gen client cert
3.115.4 - Gen root token
3.115.5 - Harbor login
The plugin destroys its Harbor session on normal shutdown and checks that the
original session ID is rejected by the current-user API. Cleanup uses Harbor’s
/c/oidc/logout endpoint (available in newer Harbor releases) and does not follow
the optional identity-provider logout redirect. Unsupported endpoints, network
failures, or sessions that remain valid are reported as cleanup errors. Session
expiry remains server-controlled; forced termination cannot guarantee logout.
The session destruction behavior is defined by Harbor’s OIDC controller. Vault tokens created by the invocation are revoked after session cleanup.
3.115.5.1 - api
Java
load("@rules_java//java:defs.bzl", "java_library")
java_library(
name = "name",
deps = [
"@com_alwaldend_src//tools/vault/harbor_login:api_java_library",
],
)
Golang
load("@rules_go//go:def.bzl", "go_library")
go_library(
name = "name",
deps = [
"@com_alwaldend_src//tools/vault/harbor_login:harbor_login",
],
)
Proto
syntax = "proto3";
package com.alwaldend.src.tools.vault.harbor_login.harbor_login_proto;
option go_package = "git.alwaldend.com/alwaldend/src/tools/vault/harbor_login/harbor_login_proto";
message Config {
string harbor_url = 1;
string vault_conn = 2;
string vault_auth = 3;
}
3.115.6 - Injector
Shutdown first drains plugin requests, then stops and waits for resource
processes, revokes invocation-owned Vault credentials, and deletes temporary
files and SSH key directories. Failed cleanup is reported. Registration after
shutdown is rejected; a fetcher removes any unregistered temporary material.
Temporary files use mode 0600 and directories use 0700. Deletion is filesystem
unlinking, not secure erasure, and cannot run after SIGKILL or host failure.
no_auth explicitly sets the injected VAULT_TOKEN to an empty value so an
inherited token is overridden. This does not remove the user’s token-helper
file; commands that independently consult that helper may still authenticate.
Template errors and OIDC status errors omit input and response contents.
OIDC requests honor cancellation and do not follow redirects.
3.115.6.1 - api
Java
load("@rules_java//java:defs.bzl", "java_library")
java_library(
name = "name",
deps = [
"@com_alwaldend_src//tools/vault/injector:api_java_library",
],
)
Golang
load("@rules_go//go:def.bzl", "go_library")
go_library(
name = "name",
deps = [
"@com_alwaldend_src//tools/vault/injector:injector",
],
)
Proto
syntax = "proto3";
package com.alwaldend.src.tools.vault.injector.injector_proto;
option go_package = "git.alwaldend.com/alwaldend/src/tools/vault/injector/injector_proto";
message File {
string value = 1;
string from_file = 2;
map<string, string> extra = 3;
}
message Env {
string value = 1;
}
message Kv {
// Secret path
string path = 1;
// Secret mount
string mount = 2;
}
message Op {
string method = 1;
string path = 4;
map<string, string> data = 5;
}
message VaultSsh {
string backend = 1;
int64 ttl = 2;
}
message Process {
string name = 1;
repeated string args = 2;
}
message Oidc {
string name = 1;
string scope = 2;
string client_id = 3;
string redirect_uri = 4;
}
message VaultEnv {
// Vault connection
string conn = 1;
// Vault auth
string auth = 2;
}
message Resource {
// Resource name
string name = 1;
// Vault connection for the resource
string vault_conn = 2;
// Vault auth for the resource
string vault_auth = 3;
// Dependencies
repeated string deps = 8;
oneof res {
// Vault operation
Op op = 4;
// Vault KV secret
Kv kv = 5;
// Environment variable
Env env = 6;
// File
File file = 7;
// Vault environment variables
VaultEnv vault_env = 9;
// Ssh key signed by Vautl
VaultSsh vault_ssh = 10;
// Run a cmd
Process process = 11;
// Create an OIDC token
Oidc oidc = 12;
}
}
message Config {
// Resources
repeated Resource res = 1;
}
3.115.8 - PVE login
The plugin requests an API token with a one-hour expiry and deletes that token on shutdown using the retained login ticket and CSRF token. The token name is registered for cleanup before creation, so cleanup is attempted even when a creation response is lost or malformed. Failures to delete are reported; expiry is the fallback when shutdown cannot complete. Pre-existing credentials are not revoked. Vault tokens created by the invocation are revoked after token cleanup.
Token deletion uses the Proxmox user token API.
3.115.8.1 - api
Java
load("@rules_java//java:defs.bzl", "java_library")
java_library(
name = "name",
deps = [
"@com_alwaldend_src//tools/vault/pve_login:api_java_library",
],
)
Golang
load("@rules_go//go:def.bzl", "go_library")
go_library(
name = "name",
deps = [
"@com_alwaldend_src//tools/vault/pve_login:pve_login",
],
)
Proto
syntax = "proto3";
package com.alwaldend.src.tools.vault.pve_login.pve_login_proto;
option go_package = "git.alwaldend.com/alwaldend/src/tools/vault/pve_login/pve_login_proto";
message Config {
string pve_base_url = 1;
string pve_redirect_url = 2;
string pve_realm = 3;
string vault_conn = 4;
string vault_auth = 5;
}
3.115.9 - Tf backend
The plugin tracks each running backend for shutdown, including backends created before a later call fails. Shutdown drains HTTP requests before revoking the backend’s invocation-owned Vault credentials. If the shutdown deadline expires, connections are forcibly closed and the timeout is reported. Normal HTTP server closure is not an error. Vault requests use their incoming request context.
3.115.9.1 - api
Java
load("@rules_java//java:defs.bzl", "java_library")
java_library(
name = "name",
deps = [
"@com_alwaldend_src//tools/vault/tf_backend:api_java_library",
],
)
Golang
load("@rules_go//go:def.bzl", "go_library")
go_library(
name = "name",
deps = [
"@com_alwaldend_src//tools/vault/tf_backend:tf_backend",
],
)
Proto
syntax = "proto3";
package com.alwaldend.src.tools.vault.tf_backend.tf_backend_proto;
option go_package = "git.alwaldend.com/alwaldend/src/tools/vault/tf_backend/tf_backend_proto";
message Config {
string vault_conn = 1;
string vault_auth = 2;
string vault_secret = 3;
string vault_secret_mount = 4;
}
3.115.10 - Unseal
3.116 - Versioning
versioning owns versions for this repository and its first-party projects.
It deliberately does not manage versions of third-party dependencies.
The repository uses SemVer-compatible calendar versions:
- ordinary development:
0.0.0-dev; - nightly trunk tag:
vYYYY.W.0-nightly.YYYYMMDD; - weekly release branch:
releases/YYYY.W; - release tag:
vYYYY.W.PATCH.
YYYY and W are the ISO week-year and week. The week is not zero-padded,
because SemVer forbids leading zeroes in numeric identifiers. Patch zero is
the release branch point. Every first-parent commit after that point advances
the calculated patch number by one.
Calculated versions and Bazel status omit the Git tag’s leading v.
A commit may carry one nightly tag and one release tag when a nightly is
promoted. Branch context selects the channel automatically. On detached HEAD,
pass --channel release or --channel nightly for that exact co-tagged
commit. For an untagged detached commit from a release branch, pass
--release YYYY.W so the tool can calculate its patch from the correct
branch-point tag.
Build and inspect the tool with:
bazel_agent bazel run //tools/versioning/cmd/versioning -- show
For a stamped build, use the bootstrap entry point. It generates a
source-current Bazel launcher under out/versioning/, then the Go tool runs
Bazel with itself as workspace status:
tools/versioning/cmd/versioning/versioning.sh bazel -- \
build --config=release //path/to:artifact
Read $versioning for the guarded nightly, release, and Bazel stamping
workflows.
Guarded release-ref publication
versioning also owns a typed, reviewed release-ref plan and a
provider-neutral guarded publisher for the generated nightly and release
tags. It never merges versioning, delivery, or goal authority; the tool
retains its own release-refs authority.
Generate a deterministic plan from the resolved version state:
bazel_agent bazel run //tools/versioning/cmd/versioning -- release-plan \
--plan out/delivery/release-plan.json
The plan records the exact version, channel, commit, tree state, target refs (tag-only for nightly, branch-plus-tag for release), the expected remote preconditions, and whether atomic multi-ref publication is required. It is reviewed before consumption and is not an authorization.
Publish the reviewed plan only after explicit release scope:
bazel_agent bazel run //tools/versioning/cmd/versioning -- release-publish \
--plan out/delivery/release-plan.json \
--receipt out/delivery/release-ref-receipt.json
The guarded publisher fetches expected remote state, acquires a distinct
release-refs lease, publishes the refs (atomically when required and
supported), and verifies the remote before emitting a ReleaseRefReceipt.
An existing immutable release tag never moves; a remote that cannot guarantee
atomic multi-ref publication is an explicit refusal, never a generic success.
3.117.1 - Bzl
3.117.1.1 - al_vial_configs
al_vial_configs
load("@com_alwaldend_src//tools/vial/main/bzl:al_vial_configs.bzl", "al_vial_configs")
al_vial_configs(name, srcs, visibility, **kwargs)
Generate vial config targets
PARAMETERS
| Name | Description | Default Value |
|---|---|---|
| name | generated docs archive name | none |
| srcs | vial config | none |
| visibility | visibility | None |
| kwargs | kwargs for template_files | none |
4 - Misc
4.1 - Android
Diagnostics
Android has some built-in tests for the display and other components in
Settings -> System -> Device diagnostics
4.2 - Bazel
Advantages
- Hermetic builds
- Dependency graph
- Local build and test cache
- Remote cache
- Remote execution
- Unified API for builds, tasks, and tests
Disadvantages
- Additional layer of abstraction and complexity
- Weird edge cases and occasional bugs
- Lack of support, documentation, and information on the internet
- The majority of advantages are irrelevant for the majority of codebases
.bazelrc has variables
%workspace%: Workspace directory
https://bazel.build/run/bazelrc
Local registry module is cached
If you changed a local registry module, but bazel still uses the old version,
restart bazel: bazel shutdown
https://github.com/bazelbuild/bazel/issues/20477#issuecomment-1851057077
Output root ownership
Bazel checks ownership of the output root at startup, so it will fail with
mkdir('/path/to/dir'): (error: 13): Permission denied if the current user does
not own the directory.
Example:
$ bazel --client_debug
...
[FATAL 15:19:33.457 src/main/cpp/blaze_util_posix.cc:499] mkdir('/path/to/dir'): (error: 13): Permission denied
Traceback:
- https://github.com/bazelbuild/bazel/blob/d798ebde6c6394203a87b5f1a6b62ecfc3880991/src/main/cpp/blaze_util_posix.cc#L497
- https://github.com/bazelbuild/bazel/blob/d798ebde6c6394203a87b5f1a6b62ecfc3880991/src/main/cpp/util/file_posix.cc#L518
- https://github.com/bazelbuild/bazel/blob/d798ebde6c6394203a87b5f1a6b62ecfc3880991/src/main/cpp/util/file_posix.cc#L90
- https://github.com/bazelbuild/bazel/blob/d798ebde6c6394203a87b5f1a6b62ecfc3880991/src/main/cpp/util/file_posix.cc#L48
- https://github.com/bazelbuild/bazel/blob/d798ebde6c6394203a87b5f1a6b62ecfc3880991/src/main/cpp/util/file_posix.cc#L67
js_binary does not work for some reason
One of possible errors:
FATAL: aspect_rules_js[js_binary]: RUNFILES environment variable is not set
Solutions
Run the binary (that fixes it for some reason)
bazel run //tools/postcss
Run pnpm install (sometimes node_modules directory is not up-to-date)
bazel run //tools/pnpm -- --dir "${PWD}/tools" install --ignore-scripts
4.3 - Books
|
Title |
Sky Pride |
|||
| Quality | Good | ||||
| Authors | Warby Picus | ||||
| Reading | Dropped, B6C25 | ||||
| Links | royalroad , royalroad (author) | ||||
| Title |
Girls’ Last Tour(少女終末旅行) |
||||
| Quality | Good | ||||
| Authors | Tsukumizu (つくみず) | ||||
| Reading | Finished, V6C43.6 | ||||
| Links | wikipedia , wikipedia (author) | ||||
|
Title |
Surviving as a Talent in the Primordial Saint Sect(苟在初圣魔门当人材) (Lying Low as the First Saint Demonic Sect’s ‘Top Talent’) |
|||
| Quality | Decent | ||||
| Authors | Crane by the Moonlit Pond (鹤守月满池) | ||||
| Reading | Finished, C1537 (C1441) | ||||
| Links | novelupdates , novelupdates (author) | ||||
|
Title |
How Can You Cultivate Immortality Without Money?(没钱修什么仙?) (No Money to Cultivate Immortality?) |
|||
| Quality | Decent | ||||
| Authors | 熊狼狗 | ||||
| Reading | Dropped, C827 (C815) | ||||
| Links | novelupdates , novelupdates (author) | ||||
|
Title |
Corpse Retriever(捞尸人) |
|||
| Quality | Decent? | ||||
| Authors | 纯洁滴小龙 | ||||
| Reading | Dropped, C26 | ||||
| Links | novelupdates , novelupdates (author) | ||||
|
Title |
The Mirror Legacy(玄鉴仙族) |
|||
| Quality | Decent? | ||||
| Authors | 季越人 | ||||
| Reading | Dropped, C10 | ||||
| Links | novelupdates , novelupdates (author) | ||||
|
Title |
Book Of The Dead |
|||
| Quality | Decent | ||||
| Authors | RinoZ | ||||
| Reading | Dropped, B6C8 | ||||
| Links | royalroad , royalroad (author) | ||||
|
Title |
Hell Difficulty Tutorial |
|||
| Quality | Decent | ||||
| Authors | Cerim | ||||
| Reading | Dropped, C841 | ||||
| Links | royalroad | ||||
|
Title |
Reforged from Ruin |
|||
| Quality | Decent | ||||
| Authors | Silv3rtongue | ||||
| Reading | Dropped, C390 | ||||
| Links | royalroad , royalroad (author) | ||||
|
Title |
Re:Cursed |
|||
| Quality | Decent | ||||
| Authors | Joroboros | ||||
| Reading | Dropped, C176 | ||||
| Links | royalroad , royalroad (author) | ||||
|
Title |
The Legend of William Oh |
|||
| Quality | Decent | ||||
| Authors | Macronomicon | ||||
| Reading | Dropped, C264 | ||||
| Links | royalroad , royalroad (author) | ||||
|
Title |
Path of the Deathless |
|||
| Quality | Decent | ||||
| Authors | |||||
| Reading | Dropped, C333 | ||||
| Links | royalroad | ||||
|
Title |
Throne of Time |
|||
| Quality | Ok, bland | ||||
| Authors | Cognosticon | ||||
| Reading | Dropped, C23 | ||||
| Links | royalroad , royalroad (author) | ||||
|
Title |
[Grave Robber] |
|||
| Quality | Ok, mediorce | ||||
| Authors | DisheveledVagabond | ||||
| Reading | Dropped, C6 | ||||
| Links | royalroad , royalroad (author) | ||||
|
Title |
To Walk The Red Path |
|||
| Quality | Ok, bland | ||||
| Authors | Jman8763 C. Ashen | ||||
| Reading | Dropped, F6P2C10 | ||||
| Links | royalroad , royalroad (author) | ||||
|
Title |
Shadow Clone Sorcery |
|||
| Quality | Ok, bland | ||||
| Authors | JPwrites | ||||
| Reading | Dropped, C110 | ||||
| Links | royalroad , royalroad (author) | ||||
|
Title |
DIE TRYING |
|||
| Quality | Ok, bland | ||||
| Authors | Mark Arrows | ||||
| Reading | Dropped, C47 | ||||
| Links | royalroad , royalroad (author) | ||||
|
Title |
No More Heroes |
|||
| Quality | Ok, boring | ||||
| Authors | LokiTheQuick | ||||
| Reading | Dropped, C22 | ||||
| Links | royalroad , royalroad (author) | ||||
|
Title |
Explorer of Edregon |
|||
| Quality | Ok, bland | ||||
| Authors | Wizardly Dude | ||||
| Reading | Dropped, C20 | ||||
| Links | royalroad , royalroad (author) | ||||
|
|
Title |
Mysterious Revival |
|||
| Quality | Ok | ||||
| Authors | Offering flowers before the Buddha | ||||
| Reading | Dropped, C54 | ||||
| Links | webnovel | ||||
|
|
Title |
Staring directly at the ancient gods for a whole year(直视古神一整年) |
|||
| Quality | Slop | ||||
| Authors | 三藏的左轮 | ||||
| Reading | Dropped, C100 | ||||
| Links | wtrlab , wtrlab (author) | ||||
|
Title |
Shan He Ji(山河稷) (Mountains, Rivers, and the Grain God) |
|||
| Quality | Ok | ||||
| Authors | 姬叉 | ||||
| Reading | Dropped, C27 | ||||
| Links | novelupdates , novelupdates (author) | ||||
|
Title |
I Am a Demon Cultivator, Not a Conscientious Capitalist(我是魔修,不是良心资本家) |
|||
| Quality | Slop | ||||
| Authors | 窗边的鸽子 | ||||
| Reading | Dropped, C19 | ||||
| Links | novelupdates , novelupdates (author) | ||||
|
Title |
I Cultivate Legally, Why Call Me a Demon?(我合法修仙,凭什么叫我魔头?) |
|||
| Quality | Slop | ||||
| Authors | 一辈子小说家 | ||||
| Reading | Dropped, C89 | ||||
| Links | novelupdates , novelupdates (author) | ||||
|
Title |
Shadow Slave |
|||
| Quality | Decent | ||||
| Authors | Guiltythree | ||||
| Reading | Dropped, chapter 2777 | ||||
| Links | webnovel | ||||
|
Title |
Pale Lights |
|||
| Quality | Good | ||||
| Authors | ErraticErrata | ||||
| Reading | Dropped, V3C37 | ||||
| Links | royalroad , royalroad (author) | ||||
|
Title |
The Tower of Infinite Evil |
|||
| Quality | Decent | ||||
| Authors | Lit Homunculus | ||||
| Reading | Dropped, C127 | ||||
| Links | royalroad , royalroad (author) | ||||
|
Title |
Changeling |
|||
| Quality | Decent | ||||
| Authors | Mecanimus | ||||
| Reading | Dropped, C103 | ||||
| Links | royalroad | ||||
|
Title |
Mask of Humanity |
|||
| Quality | Decent | ||||
| Authors | SlaughterBot | ||||
| Reading | Dropped, C366 | ||||
| Links | royalroad , royalroad (author) | ||||
|
Title |
Afterlife 2.0 |
|||
| Quality | Decent | ||||
| Authors | QuickDuckling | ||||
| Reading | Finished available (hiatus), C86 | ||||
| Links | royalroad , royalroad (author) | ||||
|
Title |
The Hundred Reigns |
|||
| Quality | Ok | ||||
| Authors | Maxime J. Durand | ||||
| Reading | Dropped, C183 | ||||
| Links | royalroad , royalroad (author) | ||||
|
Title |
Grotesqueries of the Old Domain(旧域怪诞) (The Grotesque Old Domain) |
|||
| Quality | Good? | ||||
| Authors | Foxtail Quill (狐尾的笔) | ||||
| Reading | Dropped, C268 | ||||
| Links | novelupdates , novelupdates (author) | ||||
|
Title |
Magical Girl Mechanical Heart |
|||
| Quality | Ok | ||||
| Authors | Thundamoo | ||||
| Reading | Dropped, C52 | ||||
| Links | royalroad | ||||
|
Title |
This Magical Girl is Mine |
|||
| Quality | Ok | ||||
| Authors | VoraVora | ||||
| Reading | Dropped, V5C1.2 | ||||
| Links | royalroad , royalroad (author) | ||||
|
Title |
Magical Girl Gunslinger |
|||
| Quality | Ok | ||||
| Authors | Mikasane | ||||
| Reading | Finished available (hiatus), C37 | ||||
| Links | royalroad , royalroad (author) | ||||
|
Title |
For the Glory of Rome |
|||
| Quality | Ok | ||||
| Authors | zaifyr | ||||
| Reading | Dropped, V3C12 | ||||
| Links | royalroad , royalroad (author) | ||||
|
Title |
Throne Hunters |
|||
| Quality | Ok | ||||
| Authors | Phill Tucker | ||||
| Reading | Dropped, V1C44 | ||||
| Links | royalroad , royalroad (author) | ||||
|
Title |
Young Master’s PoV: Woke Up As A Villain In A Game One Day |
|||
| Quality | Ok | ||||
| Authors | The_One_Who_Was | ||||
| Reading | Dropped, C293 | ||||
| Links | webnovel , webnovel (author) | ||||
|
Title |
Unsong |
|||
| Quality | Good, disgusting ending | ||||
| Authors | Scott Alexander | ||||
| Reading | Finished | ||||
| Links | site , goodreads (author) | ||||
|
Title |
A Gamer’s Guide To Beating The Tutorial |
|||
| Quality | Ok | ||||
| Authors | |||||
| Reading | Dropped, C352 | ||||
| Links | royalroad | ||||
|
Title |
Are You Even Human |
|||
| Quality | Decent | ||||
| Authors | Thundamoo | ||||
| Reading | Dropped, C54 | ||||
| Links | royalroad | ||||
|
Title |
The Crazy Knight’s Age of the Universe(疯骑士的宇宙时代) |
|||
| Quality | Ok, lost the vibe of the first book | ||||
| Authors | Angry Squirrel (愤怒的松鼠) | ||||
| Reading | Dropped, C167 | ||||
| Links | wtr-lab | ||||
|
Title |
Diary of a Dead Wizard(死亡巫师日记) |
|||
| Quality | Good | ||||
| Authors | Jin Nai (今奈) | ||||
| Reading | Finished, C1037 | ||||
| Links | novelupdates , novelupdates (author) | ||||
|
Title |
Shrouded Seascape(诡秘地海) |
|||
| Quality | Good | ||||
| Authors | Foxtail Quill (狐尾的笔) | ||||
| Reading | Finished, C1149 | ||||
| Links | novelupdates , novelupdates (author) | ||||
|
Title |
Salvage System |
|||
| Quality | Slop | ||||
| Authors | Nicholas Sansbury Smith | ||||
| Reading | Dropped, V1C11 | ||||
| Links | aethonbooks , aethonbooks (author) | ||||
|
Title |
Mage Tank |
|||
| Quality | Slop | ||||
| Authors | Cornman | ||||
| Reading | Dropped, V1C50 | ||||
| Links | royalroad , royalroad (author) | ||||
|
Title |
Nightmare Realm Summoner |
|||
| Quality | Ok | ||||
| Authors | Actus | ||||
| Reading | Dropped, C278 | ||||
| Links | royalroad | ||||
|
Title |
All the Dust that Falls |
|||
| Quality | Ok | ||||
| Authors | zaifyr | ||||
| Reading | Finished, V4 | ||||
| Links | royalroad , royalroad (author) | ||||
|
Title |
Dear Spellbook |
|||
| Quality | Ok | ||||
| Authors | TK523 | ||||
| Reading | Dropped, V3C13 | ||||
| Links | royalroad , royalroad (author) | ||||
|
Title |
I Became The Necromancer Of The Academy |
|||
| Quality | Slop | ||||
| Authors | _172 | ||||
| Reading | Dropped, C37 | ||||
| Links | novelupdates , novelupdates (author) | ||||
|
Title |
The Shards of Etherious |
|||
| Quality | Bad | ||||
| Authors | Colin J.D. Crooks | ||||
| Reading | Dropped, V1C9 | ||||
| Links | goodreads , goodreads (author) | ||||
|
Title |
Etherious |
|||
| Quality | Ok | ||||
| Authors | EmEs | ||||
| Reading | Dropped, finished V4 | ||||
| Links | royalroad , royalroad (author) | ||||
|
Title |
Only at the Mahayana Stage Does the Reversal System Appear |
|||
| Quality | Ok, bad translation | ||||
| Authors | The Whitest Crow (最白的乌鸦) | ||||
| Reading | Dropped, C164 | ||||
| Links | novelupdates , novelupdates (author) | ||||
|
Title |
New Life As A Max Level Archmage |
|||
| Quality | Ok | ||||
| Authors | ArcaneCadence | ||||
| Reading | Dropped, C44 | ||||
| Links | royalroad , royalroad (author) | ||||
|
Title |
I Just Want to Slack Off in Cultivation(我只想安静的做个苟道中人) |
|||
| Quality | Slop | ||||
| Authors | Exploding Small Latte (爆炸小拿铁) | ||||
| Reading | Dropped, C54 | ||||
| Links | novelupdates , novelupdates (author) | ||||
|
|
Title |
Kill the Sun |
|||
| Quality | Decent | ||||
| Authors | Warmaisach | ||||
| Reading | Finished, C992 | ||||
| Links | webnovel , webnovel (author) | ||||
|
Title |
The System is Abstract, Luckily, So Am I |
|||
| Quality | Slop | ||||
| Authors | Pū jiē tiānxiàn (扑街天线) | ||||
| Reading | Dropped, C311 | ||||
| Links | novelupdates , novelupdates (author) | ||||
|
Title |
Theos |
|||
| Quality | Decent | ||||
| Authors | Arthur Wordsmith | ||||
| Reading | Hiatus, B3C4 | ||||
| Links | royalroad , royalroad (author) | ||||
|
Title |
Saving the school would have been easier as a cafeteria worker |
|||
| Quality | Decent | ||||
| Authors | CluelessRR | ||||
| Reading | Finished available (hiatus), chapter 90 | ||||
| Links | royalroad , royalroad (author) | ||||
|
Title |
1% Lifesteal |
|||
| Quality | Ok, boring protagonist | ||||
| Authors | Robert Blaise | ||||
| Reading | Dropped, C128 (volume 2) | ||||
| Links | royalroad | ||||
|
Title |
Versatile Mage(全职法师) |
|||
| Quality | Slop | ||||
| Authors | Chaos (乱) | ||||
| Reading | Dropped, chapter 8 | ||||
| Links | novelupdates | ||||
|
Title |
Why Are the Talismans I Drawn Banned Again?!(我画的符箓必被禁用) |
|||
| Quality | Slop, rushed ending | ||||
| Authors | Quiet Support (安静捧场) | ||||
| Reading | Finshed, chapter 258 | ||||
| Links | novelupdates , novelupdates (author) | ||||
|
Title |
Dungeon Inspector |
|||
| Quality | Ok, mediocre | ||||
| Authors | Flossindune | ||||
| Reading | Dropped, finished volume 1 | ||||
| Links | royalroad , royalorad (author) | ||||
|
Title |
The Perfect Run |
|||
| Quality | Decent | ||||
| Authors | Maxime J. Durand | ||||
| Reading | Finished | ||||
| Links | royalroad , royalroad (author) | ||||
|
Title |
Blood & Fur |
|||
| Quality | Good | ||||
| Authors | Maxime J. Durand | ||||
| Reading | Finished | ||||
| Links | royalroad , royalroad (author) | ||||
|
Title |
Dao of the Bizarre Immortal(道诡异仙) |
|||
| Quality | Decent | ||||
| Authors | Foxtail Quill (狐尾的笔) | ||||
| Reading | Finished | ||||
| Links | novelupdates , novelupdates (author) | ||||
|
Title |
Cultivation Chat Group(修真聊天群) |
|||
| Quality | Decent | ||||
| Authors | Legend of the Paladin (圣骑士的传说) | ||||
| Reading | Finished | ||||
| Links | novelupdates | ||||
|
Title |
The Strongest System(最强的系统) |
|||
| Quality | Ok | ||||
| Summary | Shallow | ||||
| Authors | Xin Feng (新丰) | ||||
| Reading | Dropped, chapter 113 | ||||
| Links | novelupdates | ||||
|
Title |
Solo Leveling(我独自升级) |
|||
| Quality | Ok | ||||
| Summary | Shallow litrpg slop | ||||
| Authors | Chugong (추공) | ||||
| Reading | Dropped, chapter 52 | ||||
| Links | novelupdates | ||||
|
Title |
I Shall Be Everlasting In the World of Immortals(我在修仙界万古长青) |
|||
| Quality | Ok | ||||
| Summary | Shallow | ||||
| Authors | Fast Food Restaurant (快餐店) | ||||
| Reading | Dropped, chapter 241 | ||||
| Links | novelupdates | ||||
|
Title |
The Stubborn Skill-Grinder In A Time Loop |
|||
| Quality | Ok | ||||
| Summary | Shallow litrpg slop | ||||
| Authors | X-RHODEN-X | ||||
| Reading | Dropped, chapter 44 | ||||
| Links | royalroad | ||||
|
Title |
Unbound |
|||
| Quality | Ok | ||||
| Summary | Shallow | ||||
| Authors | Necariin | ||||
| Reading | Dropped, finisehd volume 3 | ||||
| Links | royalroad , royalroad (author) | ||||
|
Title |
The Spiritual Attainment of Minghe(明和的精神境界) |
|||
| Quality | Ok | ||||
| Summary | Shallow, bad translation | ||||
| Authors | God Loves The World (神仙爱凡尘) | ||||
| Reading | Dropped, chapter 8 | ||||
| Links | novelupdates | ||||
|
Title |
My House of Horrors(我有一座冒险屋) |
|||
| Quality | Ok | ||||
| Summary | Repetitive | ||||
| Authors | Can Fix Air-Conditioners (我会修空调) | ||||
| Reading | Dropped at some point | ||||
| Links | novelupdates | ||||
|
Title |
Chrysalis |
|||
| Quality | Ok | ||||
| Authors | RinoZ | ||||
| Reading | Dropped, C1654 | ||||
| Links | royalroad , royalroad (author) | ||||
|
Title |
Rune Seeker |
|||
| Quality | Ok | ||||
| Summary | Shallow | ||||
| Authors | J.M. Clarke (U Juggernaut) | ||||
| Reading | Dropped, volume 2, chapter 12 | ||||
| Links | royalroad | ||||
|
Title |
The Empty Box and Zeroth Maria(Utsuro no Hako to Zero no Maria) (空ろの箱と零のマリア) |
|||
| Quality | Decent? | ||||
| Summary | Don't remember | ||||
| Authors | Mikage Eiji | ||||
| Reading | Finished | ||||
| Links | novelupdates | ||||
|
Title |
Forty Millenniums of Cultivation(Forty Thousand Years Of Cultivation) (修真四万年) |
|||
| Quality | Ok | ||||
| Summary | Good worldbuilding, but too many empty exclamations and not enough substance | ||||
| Authors | The Enlightened Master Crouching Cow (卧牛真人) | ||||
| Reading | Dropped, chapter 2935 | ||||
| Links | novelupdates | ||||
|
Title |
Trash of the Count’s Family |
|||
| Quality | Bad | ||||
| Summary | Korean slop, the same stuff happens over and over again, endless saving of useless garbage, humble bragging | ||||
| Authors | Yu Ryeo Han (유려한) | ||||
| Reading | Dropped, chapter 215 | ||||
| Links | novelupdates | ||||
|
Title |
Perfect World |
|||
| Quality | Don't remember, children are boring | ||||
| Authors | Chen Dong (辰东) | ||||
| Reading | Dropped, chapter 75 | ||||
| Links | novelupdates | ||||
|
Title |
Warlock of the Magus World |
|||
| Quality | Bad, edgy slop, too much 'AI chip, do the thing' | ||||
| Authors | The Plagiarist | ||||
| Reading | Dropped, chapter 58 | ||||
| Links | novelupdates | ||||
|
Title |
Shen Yin Wang Zuo(Sealed Divine Throne) (神印王座) |
|||
| Quality | Bad, too bland | ||||
| Authors | Tang Jia San Shao (唐家三少) | ||||
| Reading | Dropped, chapter 101 | ||||
| Links | novelupdates | ||||
|
Title |
Corpo Age |
|||
| Quality | Ok, feels basic | ||||
| Authors | RandomBlueCat | ||||
| Reading | Dropped, volume 1, chapter 2 | ||||
| Links | royalroad | ||||
|
Title |
SSS-Class Suicide Hunter |
|||
| Quality | Ok, too much emotional bullshit | ||||
| Authors | Sinnoa | ||||
| Reading | Dropped at some point | ||||
| Links | novelupdates | ||||
|
Title |
The Divine Dungeon |
|||
| Quality | Ok, a bit basic | ||||
| Authors | Dakota Krout | ||||
| Reading | Finished | ||||
| Links | goodreads | ||||
|
Title |
Full Murderhobo |
|||
| Quality | Ok, a bit basic | ||||
| Authors | Dakota Krout | ||||
| Reading | Finished, volume 3 | ||||
| Links | goodreads | ||||
|
Title |
Worm |
|||
| Quality | Decent | ||||
| Authors | Wildbow | ||||
| Reading | Finished | ||||
| Links | website | ||||
|
Title |
12 Miles Below |
|||
| Quality | Decent | ||||
| Authors | Mark Arrows | ||||
| Reading | Dropped at some point | ||||
| Links | royalroad | ||||
|
Title |
The Charm of Soul Pets |
|||
| Quality | Don't remember | ||||
| Authors | Chaos (乱) | ||||
| Reading | Dropped, chapter 42 | ||||
| Links | novelupdates | ||||
|
Title |
Throne of Magical Arcana |
|||
| Quality | Decent, a bit mediocre | ||||
| Authors | Cuttlefish That Loves Diving (爱潜水的乌贼) | ||||
| Reading | Dropped near the end when the main plot ended | ||||
| Links | novelupdates | ||||
|
Title |
The Jester of Apocalypse |
|||
| Quality | Ok, basic and a bit edgy | ||||
| Authors | Robert Blaise | ||||
| Reading | Finished available chapters | ||||
| Links | royalroad | ||||
|
Title |
Accel World |
|||
| Quality | Bad, japanese slop | ||||
| Authors | Kawahara Reki | ||||
| Reading | Dropped at some point | ||||
| Links | novelupdates | ||||
|
Title |
Reborn as a Demonic Tree |
|||
| Quality | Ok, mediocre | ||||
| Authors | XKARNATION | ||||
| Reading | Dropped, volume 8, chapter 421 | ||||
| Links | royalroad | ||||
|
Title |
System Breaker |
|||
| Quality | Decent, MC is a bit immature | ||||
| Authors | |||||
| Reading | Dropped, volume 2, chapter 55 | ||||
| Links | royalroad | ||||
|
Title |
DIE. RESPAWN. REPEAT. |
|||
| Quality | Decent, a bit bland | ||||
| Authors | SilverLinings | ||||
| Reading | Dropped, volume 4, chapter 8 (chapter 222) | ||||
| Links | royalroad | ||||
|
Title |
Mark of the Fool |
|||
| Quality | Decent, not enough progression | ||||
| Authors | J.M. Clarke (U Juggernaut) | ||||
| Reading | Finished | ||||
| Links | royalroad | ||||
|
Title |
If It’s for My Daughter, I’d Even Defeat a Demon Lord |
|||
| Quality | Bad, Japanese slice-of-life litrpg fantasy slop | ||||
| Authors | Chirolu | ||||
| Reading | Dropped, V4C2 | ||||
| Links | novelupdates | ||||
|
Title |
Ultimate Level 1 |
|||
| Quality | Bad, litrpg slop | ||||
| Authors | Dads Bedtime Stories | ||||
| Reading | Dropped, V1C17 | ||||
| Links | royalroad | ||||
|
Title |
Vigor Mortis |
|||
| Quality | Ok | ||||
| Authors | Thundamoo | ||||
| Reading | Dropped, V4C27 | ||||
| Links | royalroad | ||||
|
Title |
Rise of the Living Forge |
|||
| Quality | Ok | ||||
| Authors | Actus | ||||
| Reading | Dropped, C509 | ||||
| Links | royalroad | ||||
|
Title |
The Beginning After the End |
|||
| Quality | Bad, isekai slop | ||||
| Authors | TurtleMe | ||||
| Reading | Dropped, volume 1, chapter 13 | ||||
| Links | wikipedia | ||||
|
Title |
Ghost of the Truthseeker |
|||
| Quality | Ok | ||||
| Authors | Strungbound | ||||
| Reading | Dropped, chapter 220 | ||||
| Links | royalroad | ||||
|
Title |
I Am Become Death |
|||
| Quality | Decent | ||||
| Summary | Nothing exceptional | ||||
| Authors | J.M. Clarke (U Juggernaut) | ||||
| Reading | Dropped, chapter 55 | ||||
| Links | royalroard | ||||
|
Title |
Return of the Runebound Professor |
|||
| Quality | Ok | ||||
| Authors | Actus | ||||
| Reading | Reading, B7C749 | ||||
| Links | royalroad | ||||
| Title |
World of Cultivation(修真世界) |
||||
| Quality | Good | ||||
| Authors | Fang Xiang (方想) | ||||
| Reading | Finished | ||||
| Links | novelupdates | ||||
|
Title |
I Shall Seal the Heavens |
|||
| Quality | Good | ||||
| Authors | Er Gen (耳根) | ||||
| Reading | Finished | ||||
| Links | novelupdates , novelupdates (author) | ||||
|
Title |
Beware Of Chicken |
|||
| Quality | Decent | ||||
| Authors | Casualfarmer | ||||
| Reading | Dropped, V4(V6)C68 | ||||
| Links | royalroad | ||||
|
Title |
Dungeon Crawler Carl |
|||
| Quality | Good | ||||
| Authors | DoctorHepa | ||||
| Reading | Finished available, B7 | ||||
| Links | royalroad | ||||
|
Title |
A Practical Guide to Sorcery |
|||
| Quality | Decent, slow upload | ||||
| Authors | Azalea Ellis | ||||
| Reading | Dropped, C262 | ||||
| Links | azaleaellis | ||||
|
Title |
Downtown Druid |
|||
| Quality | Decent | ||||
| Authors | seersucker | ||||
| Reading | Finished volume 1 | ||||
| Links | royalroad | ||||
|
Title |
The Years of Apocalypse |
|||
| Quality | Decent | ||||
| Authors | UraniumPhoenix | ||||
| Reading | Dropped, C226 | ||||
| Links | royalroad | ||||
|
Title |
Renegade Immortal |
|||
| Quality | Good | ||||
| Authors | Er Gen (耳根) | ||||
| Reading | Finished | ||||
| Links | novelupdates , novelupdates (author) | ||||
|
Title |
Matabar |
|||
| Quality | Good | ||||
| Authors | Kirill Klevanski | ||||
| Reading | Dropped, chapter 120 | ||||
| Links | royalroad | ||||
|
Title |
Defiance of the Fall |
|||
| Quality | Decent | ||||
| Authors | TheFirstDefier | ||||
| Reading | Dropped, C1370 | ||||
| Links | royalroad | ||||
|
Title |
Godclads |
|||
| Quality | Good, a bit too dramatic | ||||
| Authors | OstensibleMammal | ||||
| Reading | Dropped, C37-11 | ||||
| Links | royalroad , royalroad (author) | ||||
|
Title |
Archfiend(最强妖孽) |
|||
| Quality | Decent | ||||
| Authors | Nocturnal Stranger (厄夜怪客) | ||||
| Reading | Finished translated chapters, chapter 528 | ||||
| Links | novelupdates | ||||
|
Title |
Outside of time(光阴之外) |
|||
| Quality | Ok | ||||
| Authors | Er Gen (耳根) | ||||
| Reading | Dropped, C1470 | ||||
| Links | novelupdates , novelupdates (author) | ||||
|
Title |
The Sage Who Transcended Samsara(一世之尊) |
|||
| Quality | Good | ||||
| Authors | Cuttlefish That Loves Diving (爱潜水的乌贼) | ||||
| Reading | Finished, dropped at the end | ||||
| Links | novelupdates | ||||
|
Title |
The Experimental Log of the Crazy Lich(疯巫妖的实验日志) |
|||
| Quality | Good | ||||
| Authors | Angry Squirrel (愤怒的松鼠) | ||||
| Reading | Finished volume 1 | ||||
| Links | novelupdates | ||||
|
Title |
Nightfall(Ever Night) (将夜) |
|||
| Quality | Good | ||||
| Authors | Mao Ni (猫腻) | ||||
| Reading | Finished | ||||
| Links | novelupdates | ||||
|
Title |
The Path Toward Heaven(大道朝天) |
|||
| Quality | Good | ||||
| Authors | Mao Ni (猫腻) | ||||
| Reading | Finished available chapters | ||||
| Links | novelupdates | ||||
|
Title |
Ze Tian Ji(Way of Choices) (择天记) |
|||
| Quality | Good | ||||
| Authors | Mao Ni (猫腻) | ||||
| Reading | Finished | ||||
| Links | novelupdates | ||||
|
Title |
Lord of the Mysteries |
|||
| Quality | Good | ||||
| Authors | Cuttlefish That Loves Diving (爱潜水的乌贼) | ||||
| Reading | Finished volume 2 | ||||
| Links | novelupdates | ||||
|
Title |
Unintended Immortality(The Unintentional Path to Immortality) (我本无意成仙) |
|||
| Quality | Good | ||||
| Authors | Golden Jasmine (金色茉莉花) | ||||
| Reading | Finished, C713 | ||||
| Links | novelupdates , novelfile | ||||
|
Title |
My Longevity Simulation |
|||
| Quality | Good | ||||
| Authors | Angry Squid (愤怒的乌贼) | ||||
| Reading | Dropped, C838 | ||||
| Links | novelupdates , novelbin | ||||
|
Title |
Virtuous Sons |
|||
| Quality | Peak | ||||
| Authors | Ya Boy | ||||
| Reading | Finished available (hiatus), C2.22 | ||||
| Links | royalroad , royalroad (author) | ||||
|
Title |
Reverend Insanity(Gu Daoist Master) (蛊真人) |
|||
| Quality | Peak | ||||
| Authors | Gu Zhen Ren (蛊真人) | ||||
| Reading | Finished available, C2334 | ||||
| Links | novelupdates | ||||
4.4 - Glossary
Advanced Persistent Threat (APT)
An advanced persistent threat (APT) refers to an attack that continues, secretively, using innovative hacking methods to access a system and stay inside for a long period of time. Typical attackers are cyber criminals, like the Iranian group APT34, the Russian organization APT28, and others. Although they can come from all over the world, some of the most notable attackers come from Iran, other areas of the Middle East, and North Korea.
Docs: https://www.fortinet.com/resources/cyberglossary/advanced-persistent-threat
Subresource Integrity (SRI)
Subresource Integrity (SRI) is a security feature that enables browsers to verify that resources they fetch (for example, from a CDN) are delivered without unexpected manipulation. It works by allowing you to provide a cryptographic hash that a fetched resource must match.
Docs: https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity
Conflict-free Replicated Data Type (CRDT)
A Conflict-free Replicated Data Type (CRDT) is a data structure that simplifies distributed data storage systems and multi-user applications.
In many systems, copies of some data need to be stored on multiple computers (known as replicas). Examples of such systems include:
Mobile apps that store data on the local device, and that need to sync that data to other devices belonging to the same user (such as calendars, notes, contacts, or reminders); Distributed databases, which maintain multiple replicas of the data (in the same datacenter or in different locations) so that the system continues working correctly if some of the replicas are offline; Collaboration software, such as Google Docs, Trello, Figma, or many others, in which several users can concurrently make changes to the same file or data; Large-scale data storage and processing systems, which replicate data in order to achieve global scalability.
Docs: https://crdt.tech/
4.5 - Gnome boxes
Gnome boxes is a hypervisor.
Cpu
The default cpu doesn’t have a lot of capabilities, so you might need to patch the config:
<!-- https://www.qemu.org/docs/master/system/i386/cpu.html -->
<cpu mode="host-model" />
Network
Default libvirt network interferes with gnome-boxes, you might need to disable it:
sudo systemctl disable --now libvirtd
Disk size
Just increasing the disk size is not enough, you need to increase the logical volume size:
sudo growpart /dev/vda 3
sudo lvextend -l +100%FREE /dev/fedora/root
sudo xfs_growfs /dev/fedora/root
Links:
4.6 - Hugo
Hugo is a static site builder
Environment variables
Hugo has an allowlist of environment variables, and js_binary rules
do not work because they need a BAZEL_BINDIR variable
Fix:
[security.exec]
osEnv = [
'(?i)^((HTTPS?|NO)_PROXY|PATH(EXT)?|APPDATA|TE?MP|TERM|GO\w+|(XDG_CONFIG_)?HOME|USERPROFILE|SSH_AUTH_SOCK|DISPLAY|LANG|SYSTEMDRIVE|BAZEL.+)$',
]
Configuration reference: https://gohugo.io/configuration/security/
4.7 - Leetcode submissions
4.7.1 - 2026-04-11 20:57:04 +0300 MSK
Links
Code
class Solution:
def minimumDistance(self, nums: List[int]) -> int:
n = len(nums)
nxt = [-1] * n
occur = {}
ans = n + 1
for i in range(n - 1, -1, -1):
if nums[i] in occur:
nxt[i] = occur[nums[i]]
occur[nums[i]] = i
for i in range(n):
second_pos = nxt[i]
if second_pos != -1:
third_pos = nxt[second_pos]
if third_pos != -1:
ans = min(ans, third_pos - i)
return -1 if ans == n + 1 else ans * 2
4.7.2 - 2026-04-10 21:12:54 +0300 MSK
Links
Code
class Solution:
def minimumDistance(self, nums: List[int]) -> int:
n = len(nums)
ans = n + 1
for i in range(n - 2):
for j in range(i + 1, n - 1):
if nums[i] != nums[j]:
continue
for k in range(j + 1, n):
if nums[j] == nums[k]:
ans = min(ans, k - i)
break
return -1 if ans == n + 1 else ans * 2
4.7.3 - 2026-04-09 22:31:40 +0300 MSK
Links
Code
class Solution:
def xorAfterQueries(self, nums: List[int], queries: List[List[int]]) -> int:
mod = 10**9 + 7
n = len(nums)
T = int(n**0.5)
groups = [[] for _ in range(T)]
for l, r, k, v in queries:
if k < T:
groups[k].append((l, r, v))
else:
for i in range(l, r + 1, k):
nums[i] = nums[i] * v % mod
dif = [1] * (n + T)
for k in range(1, T):
if not groups[k]:
continue
dif[:] = [1] * len(dif)
for l, r, v in groups[k]:
dif[l] = dif[l] * v % mod
R = ((r - l) // k + 1) * k + l
dif[R] = dif[R] * pow(v, mod - 2, mod) % mod
for i in range(k, n):
dif[i] = dif[i] * dif[i - k] % mod
for i in range(n):
nums[i] = nums[i] * dif[i] % mod
res = 0
for x in nums:
res ^= x
return res
4.7.4 - 2026-04-08 20:09:31 +0300 MSK
Links
Code
class Solution:
MOD = 10**9 + 7
def xorAfterQueries(self, nums: List[int], queries: List[List[int]]) -> int:
for l, r, k, v in queries:
for i in range(l, r + 1, k):
nums[i] = (nums[i] * v) % self.MOD
res = 0
for x in nums:
res ^= x
return res
4.7.5 - 2026-04-07 20:43:50 +0300 MSK
Links
Code
class Robot:
TO_DIR = {
0: "East",
1: "North",
2: "West",
3: "South",
}
def __init__(self, width: int, height: int):
self.moved = False
self.idx = 0
self.pos = list()
self.dirs = list()
pos_, dirs_ = self.pos, self.dirs
for i in range(width):
pos_.append((i, 0))
dirs_.append(0)
for i in range(1, height):
pos_.append((width - 1, i))
dirs_.append(1)
for i in range(width - 2, -1, -1):
pos_.append((i, height - 1))
dirs_.append(2)
for i in range(height - 2, 0, -1):
pos_.append((0, i))
dirs_.append(3)
dirs_[0] = 3
def step(self, num: int) -> None:
self.moved = True
self.idx = (self.idx + num) % len(self.pos)
def getPos(self) -> List[int]:
return list(self.pos[self.idx])
def getDir(self) -> str:
if not self.moved:
return "East"
return Robot.TO_DIR[self.dirs[self.idx]]
4.7.6 - 2026-04-06 20:15:21 +0300 MSK
Links
Code
class Solution:
def __init__(self):
self.HASH_MULTIPLIER = (
60013 # Slightly larger than 2 * max coordinate value
)
def robotSim(self, commands: List[int], obstacles: List[List[int]]) -> int:
# Store obstacles in an set for efficient lookup
obstacle_set = {self._hash_coordinates(x, y) for x, y in obstacles}
# Define direction vectors: North, East, South, West
directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]
x, y = 0, 0
max_distance_squared = 0
current_direction = 0 # 0: North, 1: East, 2: South, 3: West
for command in commands:
if command == -1: # Turn right
current_direction = (current_direction + 1) % 4
continue
if command == -2: # Turn left
current_direction = (current_direction + 3) % 4
continue
# Move forward
dx, dy = directions[current_direction]
for _ in range(command):
next_x, next_y = x + dx, y + dy
if self._hash_coordinates(next_x, next_y) in obstacle_set:
break
x, y = next_x, next_y
max_distance_squared = max(max_distance_squared, x * x + y * y)
return max_distance_squared
# Hash function to convert (x, y) coordinates to a unique integer value
def _hash_coordinates(self, x: int, y: int) -> int:
return x + self.HASH_MULTIPLIER * y
4.7.7 - 2026-04-06 20:14:55 +0300 MSK
Links
Code
class Solution(object):
def judgeCircle(self, moves):
x = y = 0
for move in moves:
if move == 'U': y -= 1
elif move == 'D': y += 1
elif move == 'L': x -= 1
elif move == 'R': x += 1
return x == y == 0
4.7.8 - 2026-04-04 20:41:56 +0300 MSK
Links
Code
class Solution:
def decodeCiphertext(self, encodedText: str, rows: int) -> str:
if rows == 1:
return encodedText
n = len(encodedText)
cols = n // rows
res = []
for c in range(cols):
r, j = 0, c
while r < rows and j < cols:
res.append(encodedText[r * cols + j])
r += 1
j += 1
return "".join(res).rstrip()
4.7.9 - 2026-04-03 22:48:45 +0300 MSK
Links
Code
class Solution:
def maxWalls(
self, robots: List[int], distance: List[int], walls: List[int]
) -> int:
n = len(robots)
robot_dist = list(zip(robots, distance))
robot_dist.sort(key=lambda x: x[0])
walls.sort()
m = len(walls)
right_ptr = left_ptr = cur_ptr = robot_ptr = 0
prev_left = prev_right = prev_num = 0
sub_left = sub_right = 0
for i in range(n):
robot_pos, robot_dist_val = robot_dist[i]
while right_ptr < m and walls[right_ptr] <= robot_pos:
right_ptr += 1
pos1 = right_ptr
while cur_ptr < m and walls[cur_ptr] < robot_pos:
cur_ptr += 1
pos2 = cur_ptr
if i >= 1:
left_bound = max(
robot_pos - robot_dist_val, robot_dist[i - 1][0] + 1
)
else:
left_bound = robot_pos - robot_dist_val
while left_ptr < m and walls[left_ptr] < left_bound:
left_ptr += 1
left_pos = left_ptr
current_left = pos1 - left_pos
if i < n - 1:
right_bound = min(
robot_pos + robot_dist_val, robot_dist[i + 1][0] - 1
)
else:
right_bound = robot_pos + robot_dist_val
while right_ptr < m and walls[right_ptr] <= right_bound:
right_ptr += 1
right_pos = right_ptr
current_right = right_pos - pos2
current_num = 0
if i > 0:
while robot_ptr < m and walls[robot_ptr] < robot_dist[i - 1][0]:
robot_ptr += 1
pos3 = robot_ptr
current_num = pos1 - pos3
if i == 0:
sub_left = current_left
sub_right = current_right
else:
new_sub_left = max(
sub_left + current_left,
sub_right
- prev_right
+ min(current_left + prev_right, current_num),
)
new_sub_right = max(
sub_left + current_right, sub_right + current_right
)
sub_left = new_sub_left
sub_right = new_sub_right
prev_left = current_left
prev_right = current_right
prev_num = current_num
return max(sub_left, sub_right)
4.7.10 - 2026-04-02 19:46:57 +0300 MSK
Links
Code
class Solution:
def maximumAmount(self, coins: List[List[int]]) -> int:
n = len(coins[0])
dp = [[-inf] * 3 for _ in range(n + 1)]
dp[1] = [0] * 3
for row in coins:
for j, x in enumerate(row):
dp[j + 1][2] = max(
dp[j][2] + x, dp[j + 1][2] + x, dp[j][1], dp[j + 1][1]
)
dp[j + 1][1] = max(
dp[j][1] + x, dp[j + 1][1] + x, dp[j][0], dp[j + 1][0]
)
dp[j + 1][0] = max(dp[j][0], dp[j + 1][0]) + x
return dp[n][2]
4.7.11 - 2026-04-01 20:54:07 +0300 MSK
Links
Code
class Solution:
def survivedRobotsHealths(
self, positions: List[int], healths: List[int], directions: str
) -> List[int]:
n = len(positions)
indices = list(range(n))
result = []
stack = deque()
# Sort indices based on their positions
indices.sort(key=lambda x: positions[x])
for current_index in indices:
# Add right-moving robots to the stack
if directions[current_index] == "R":
stack.append(current_index)
else:
while stack and healths[current_index] > 0:
# Pop the top robot from the stack for collision check
top_index = stack.pop()
if healths[top_index] > healths[current_index]:
# Top robot survives, current robot is destroyed
healths[top_index] -= 1
healths[current_index] = 0
stack.append(top_index)
elif healths[top_index] < healths[current_index]:
# Current robot survives, top robot is destroyed
healths[current_index] -= 1
healths[top_index] = 0
else:
# Both robots are destroyed
healths[current_index] = 0
healths[top_index] = 0
# Collect surviving robots
for index in range(n):
if healths[index] > 0:
result.append(healths[index])
return result
4.7.12 - 2026-03-31 23:43:31 +0300 MSK
Links
Code
class Solution:
def generateString(self, str1: str, str2: str) -> str:
n, m = len(str1), len(str2)
s = ["a"] * (n + m - 1)
fixed = [False] * (n + m - 1)
# process the case of 'T'
for i, ch in enumerate(str1):
if ch == "T":
for j, c in enumerate(str2, i):
if fixed[j] and s[j] != c:
return ""
s[j], fixed[j] = c, True
# process the case of 'F'
for i, ch in enumerate(str1):
if ch == "F":
# check if there are already different characters
if any(str2[j - i] != s[j] for j in range(i, i + m)):
continue
# find the first modifiable position
for j in range(i + m - 1, i - 1, -1):
if not fixed[j]:
s[j] = "b"
break
else:
return ""
return "".join(s)
4.7.13 - 2026-03-30 19:50:10 +0300 MSK
Links
Code
class Solution:
def checkStrings(self, s1: str, s2: str) -> bool:
return Counter(s1[::2]) == Counter(s2[::2]) and Counter(
s1[1::2]
) == Counter(s2[1::2])
4.7.14 - 2026-03-29 23:45:59 +0300 MSK
Links
Code
class Solution:
def canBeEqual(self, s1: str, s2: str) -> bool:
a = sorted([s1[0], s1[2]])
b = sorted([s1[1], s1[3]])
c = sorted([s2[0], s2[2]])
d = sorted([s2[1], s2[3]])
return a == c and b == d
4.7.15 - 2026-03-28 19:49:17 +0300 MSK
Links
Code
class Solution:
def findTheString(self, lcp: List[List[int]]) -> str:
n = len(lcp)
word = [""] * n
current = ord("a")
# construct the string starting from 'a' to 'z' sequentially
for i in range(n):
if not word[i]:
if current > ord("z"):
return ""
word[i] = chr(current)
for j in range(i + 1, n):
if lcp[i][j]:
word[j] = word[i]
current += 1
# verify if the constructed string meets the LCP matrix requirements
for i in range(n - 1, -1, -1):
for j in range(n - 1, -1, -1):
if word[i] != word[j]:
if lcp[i][j]:
return ""
else:
if i == n - 1 or j == n - 1:
if lcp[i][j] != 1:
return ""
else:
if lcp[i][j] != lcp[i + 1][j + 1] + 1:
return ""
return "".join(word)
4.7.16 - 2026-03-27 09:35:17 +0300 MSK
Links
Code
class Solution:
def areSimilar(self, mat: List[List[int]], k: int) -> bool:
m, n = len(mat), len(mat[0])
for i in range(m):
is_even = i % 2 == 0
for j in range(n):
if is_even:
new_j = (j - k) % n
else:
new_j = (j + k) % n
if mat[i][j] != mat[i][new_j]:
return False
return True
4.7.17 - 2026-03-26 21:00:59 +0300 MSK
Links
Code
class Solution:
def canPartitionGrid(self, grid: List[List[int]]) -> bool:
total = 0
m = len(grid)
n = len(grid[0])
for i in range(m):
for j in range(n):
total += grid[i][j]
for _ in range(4):
exist = set()
exist.add(0)
sum_val = 0
m = len(grid)
n = len(grid[0])
if m < 2:
grid = self.rotation(grid)
continue
if n == 1:
for i in range(m - 1):
sum_val += grid[i][0]
tag = sum_val * 2 - total
if tag == 0 or tag == grid[0][0] or tag == grid[i][0]:
return True
grid = self.rotation(grid)
continue
for i in range(m - 1):
for j in range(n):
exist.add(grid[i][j])
sum_val += grid[i][j]
tag = sum_val * 2 - total
if i == 0:
if tag == 0 or tag == grid[0][0] or tag == grid[0][n - 1]:
return True
continue
if tag in exist:
return True
grid = self.rotation(grid)
return False
def rotation(self, grid: List[List[int]]) -> List[List[int]]:
m = len(grid)
n = len(grid[0])
tmp = [[0] * m for _ in range(n)]
for i in range(m):
for j in range(n):
tmp[j][m - 1 - i] = grid[i][j]
return tmp
4.7.18 - 2026-03-25 23:26:40 +0300 MSK
Links
Code
class Solution:
def constructProductMatrix(self, grid: List[List[int]]) -> List[List[int]]:
MOD = 12345
n, m = len(grid), len(grid[0])
p = [[0] * m for _ in range(n)]
suffix = 1
for i in range(n - 1, -1, -1):
for j in range(m - 1, -1, -1):
p[i][j] = suffix
suffix = (suffix * grid[i][j]) % MOD
prefix = 1
for i in range(n):
for j in range(m):
p[i][j] = (p[i][j] * prefix) % MOD
prefix = (prefix * grid[i][j]) % MOD
return p
4.7.19 - 2026-03-25 23:26:14 +0300 MSK
Links
Code
class Solution:
def canPartitionGrid(self, grid: List[List[int]]) -> bool:
m, n = len(grid), len(grid[0])
total = sum(sum(row) for row in grid)
if total % 2:
return False
target = total // 2
s = 0
for i in range(m - 1):
s += sum(grid[i])
if s == target:
return True
s = 0
for j in range(n - 1):
for i in range(m):
s += grid[i][j]
if s == target:
return True
return False
4.7.20 - 2026-03-23 21:09:09 +0300 MSK
Links
Code
class Solution:
def maxProductPath(self, grid: List[List[int]]) -> int:
mod = 10**9 + 7
m, n = len(grid), len(grid[0])
maxgt = [[0] * n for _ in range(m)]
minlt = [[0] * n for _ in range(m)]
maxgt[0][0] = minlt[0][0] = grid[0][0]
for i in range(1, n):
maxgt[0][i] = minlt[0][i] = maxgt[0][i - 1] * grid[0][i]
for i in range(1, m):
maxgt[i][0] = minlt[i][0] = maxgt[i - 1][0] * grid[i][0]
for i in range(1, m):
for j in range(1, n):
if grid[i][j] >= 0:
maxgt[i][j] = (
max(maxgt[i][j - 1], maxgt[i - 1][j]) * grid[i][j]
)
minlt[i][j] = (
min(minlt[i][j - 1], minlt[i - 1][j]) * grid[i][j]
)
else:
maxgt[i][j] = (
min(minlt[i][j - 1], minlt[i - 1][j]) * grid[i][j]
)
minlt[i][j] = (
max(maxgt[i][j - 1], maxgt[i - 1][j]) * grid[i][j]
)
if maxgt[m - 1][n - 1] < 0:
return -1
return maxgt[m - 1][n - 1] % mod
4.7.21 - 2026-03-22 15:36:46 +0300 MSK
Links
Code
class Solution:
def findRotation(
self, mat: List[List[int]], target: List[List[int]]
) -> bool:
n = len(mat)
# at most 4 rotations
for k in range(4):
# rotation operation
for i in range(n // 2):
for j in range((n + 1) // 2):
(
mat[i][j],
mat[n - 1 - j][i],
mat[n - 1 - i][n - 1 - j],
mat[j][n - 1 - i],
) = (
mat[n - 1 - j][i],
mat[n - 1 - i][n - 1 - j],
mat[j][n - 1 - i],
mat[i][j],
)
if mat == target:
return True
return False
4.7.22 - 2026-03-21 19:43:30 +0300 MSK
Links
Code
class Solution:
def reverseSubmatrix(
self, grid: List[List[int]], x: int, y: int, k: int
) -> List[List[int]]:
i0, i1 = x, x + k - 1
while i0 < i1:
for j in range(y, y + k):
grid[i0][j], grid[i1][j] = grid[i1][j], grid[i0][j]
i0, i1 = i0 + 1, i1 - 1
return grid
4.7.23 - 2026-03-20 19:36:10 +0300 MSK
Links
Code
class Solution:
def minAbsDiff(self, grid: List[List[int]], k: int) -> List[List[int]]:
m, n = len(grid), len(grid[0])
res = [[0] * (n - k + 1) for _ in range(m - k + 1)]
for i in range(m - k + 1):
for j in range(n - k + 1):
kgrid = []
for x in range(i, i + k):
for y in range(j, j + k):
kgrid.append(grid[x][y])
kmin = float("inf")
kgrid.sort()
for t in range(1, len(kgrid)):
if kgrid[t] == kgrid[t - 1]:
continue
kmin = min(kmin, kgrid[t] - kgrid[t - 1])
if kmin != float("inf"):
res[i][j] = kmin
return res
4.7.24 - 2026-03-19 23:36:34 +0300 MSK
Links
Code
class Solution:
def numberOfSubmatrices(self, grid: List[List[str]]) -> int:
n, m = len(grid), len(grid[0])
ans = 0
sum = [[[0, 0] for _ in range(m + 1)] for _ in range(n + 1)]
for i in range(n):
for j in range(m):
if grid[i][j] == "X":
sum[i + 1][j + 1][0] = (
sum[i + 1][j][0] + sum[i][j + 1][0] - sum[i][j][0] + 1
)
sum[i + 1][j + 1][1] = 1
elif grid[i][j] == "Y":
sum[i + 1][j + 1][0] = (
sum[i + 1][j][0] + sum[i][j + 1][0] - sum[i][j][0] - 1
)
sum[i + 1][j + 1][1] = sum[i + 1][j][1] | sum[i][j + 1][1]
else:
sum[i + 1][j + 1][0] = (
sum[i + 1][j][0] + sum[i][j + 1][0] - sum[i][j][0]
)
sum[i + 1][j + 1][1] = sum[i + 1][j][1] | sum[i][j + 1][1]
if sum[i + 1][j + 1][0] == 0 and sum[i + 1][j + 1][1] == 1:
ans += 1
return ans
4.7.25 - 2026-03-18 20:01:58 +0300 MSK
Links
Code
class Solution:
def countSubmatrices(self, grid: List[List[int]], k: int) -> int:
n, m = len(grid), len(grid[0])
cols = [0] * m
res = 0
for i in range(n):
row_sum = 0
for j in range(m):
cols[j] += grid[i][j]
row_sum += cols[j]
if row_sum <= k:
res += 1
return res
4.7.26 - 2026-03-17 21:22:16 +0300 MSK
Links
Code
class Solution:
def largestSubmatrix(self, matrix: List[List[int]]) -> int:
m = len(matrix)
n = len(matrix[0])
prev_heights = []
ans = 0
for row in range(m):
heights = []
seen = [False] * n
for height, col in prev_heights:
if matrix[row][col] == 1:
heights.append((height + 1, col))
seen[col] = True
for col in range(n):
if seen[col] == False and matrix[row][col] == 1:
heights.append((1, col))
for i in range(len(heights)):
ans = max(ans, heights[i][0] * (i + 1))
prev_heights = heights
return ans
4.7.27 - 2026-03-16 21:13:19 +0300 MSK
Links
Code
class Answer:
def __init__(self):
self.ans = [0, 0, 0]
def put(self, x: int):
_ans = self.ans
if x > _ans[0]:
_ans[0], _ans[1], _ans[2] = x, _ans[0], _ans[1]
elif x != _ans[0] and x > _ans[1]:
_ans[1], _ans[2] = x, _ans[1]
elif x != _ans[0] and x != _ans[1] and x > _ans[2]:
_ans[2] = x
def get(self) -> List[int]:
_ans = self.ans
return [num for num in _ans if num != 0]
class Solution:
def getBiggestThree(self, grid: List[List[int]]) -> List[int]:
m, n = len(grid), len(grid[0])
sum1 = [[0] * (n + 2) for _ in range(m + 1)]
sum2 = [[0] * (n + 2) for _ in range(m + 1)]
for i in range(1, m + 1):
for j in range(1, n + 1):
sum1[i][j] = sum1[i - 1][j - 1] + grid[i - 1][j - 1]
sum2[i][j] = sum2[i - 1][j + 1] + grid[i - 1][j - 1]
ans = Answer()
for i in range(m):
for j in range(n):
# a single cell is also a rhombus
ans.put(grid[i][j])
for k in range(i + 2, m, 2):
ux, uy = i, j
dx, dy = k, j
lx, ly = (i + k) // 2, j - (k - i) // 2
rx, ry = (i + k) // 2, j + (k - i) // 2
if ly < 0 or ry >= n:
break
ans.put(
(sum2[lx + 1][ly + 1] - sum2[ux][uy + 2])
+ (sum1[rx + 1][ry + 1] - sum1[ux][uy])
+ (sum1[dx + 1][dy + 1] - sum1[lx][ly])
+ (sum2[dx + 1][dy + 1] - sum2[rx][ry + 2])
- (
grid[ux][uy]
+ grid[dx][dy]
+ grid[lx][ly]
+ grid[rx][ry]
)
)
return ans.get()
4.7.28 - 2026-03-15 16:53:42 +0300 MSK
Links
Code
class Fancy:
def __init__(self):
self.mod = 10**9 + 7
self.v = list()
self.a = 1
self.b = 0
# fast exponentiation
def quickmul(self, x: int, y: int) -> int:
return pow(x, y, self.mod)
# multiplicative inverse
def inv(self, x: int) -> int:
return self.quickmul(x, self.mod - 2)
def append(self, val: int) -> None:
self.v.append((val - self.b) * self.inv(self.a) % self.mod)
def addAll(self, inc: int) -> None:
self.b = (self.b + inc) % self.mod
def multAll(self, m: int) -> None:
self.a = self.a * m % self.mod
self.b = self.b * m % self.mod
def getIndex(self, idx: int) -> int:
if idx >= len(self.v):
return -1
return (self.a * self.v[idx] + self.b) % self.mod
4.7.29 - 2026-03-14 21:37:31 +0300 MSK
Links
Code
class Solution:
def getHappyString(self, n: int, k: int) -> str:
# Calculate the total number of happy strings of length n
total = 3 * (1 << (n - 1))
# If k is greater than the total number of happy strings, return an empty string
if k > total:
return ""
result = ["a"] * n # Initialize result with 'a' characters
# Define mappings for the next smallest and greatest valid characters
next_smallest = {"a": "b", "b": "a", "c": "a"}
next_greatest = {"a": "c", "b": "c", "c": "b"}
# Calculate the starting indices for strings beginning with 'a', 'b', and 'c'
start_a = 1
start_b = start_a + (1 << (n - 1))
start_c = start_b + (1 << (n - 1))
# Determine the first character based on the value of k
if k < start_b:
result[0] = "a"
k -= start_a
elif k < start_c:
result[0] = "b"
k -= start_b
else:
result[0] = "c"
k -= start_c
# Iterate through the remaining positions in the result string
for char_index in range(1, n):
# Calculate the midpoint of the group for the current character position
midpoint = 1 << (n - char_index - 1)
# Determine the next character based on the value of k
if k < midpoint:
result[char_index] = next_smallest[result[char_index - 1]]
else:
result[char_index] = next_greatest[result[char_index - 1]]
k -= midpoint
return "".join(result)
4.7.30 - 2026-03-13 20:46:12 +0300 MSK
Links
Code
class Solution:
def minNumberOfSeconds(
self, mountainHeight: int, workerTimes: List[int]
) -> int:
maxWorkerTimes = max(workerTimes)
l, r, ans = (
1,
maxWorkerTimes * mountainHeight * (mountainHeight + 1) // 2,
0,
)
eps = 1e-7
while l <= r:
mid = (l + r) // 2
cnt = 0
for t in workerTimes:
work = mid // t
# find the largest k such that 1+2+...+k <= work
k = int((-1 + ((1 + work * 8) ** 0.5)) / 2 + eps)
cnt += k
if cnt >= mountainHeight:
ans = mid
r = mid - 1
else:
l = mid + 1
return ans
4.7.31 - 2026-03-12 19:11:46 +0300 MSK
Links
Code
class DSU:
def __init__(self, parent):
self.parent = parent
def find(self, x):
if self.parent[x] == x:
return x
self.parent[x] = self.find(self.parent[x])
return self.parent[x]
def join(self, x, y):
px = self.find(x)
py = self.find(y)
self.parent[px] = py
MAX_STABILITY = 200000
class Solution:
def maxStability(self, n: int, edges: List[List[int]], k: int) -> int:
ans = -1
if len(edges) < n - 1:
return -1
mustEdges = [e for e in edges if e[3] == 1]
optionalEdges = [e for e in edges if e[3] != 1]
if len(mustEdges) > n - 1:
return -1
optionalEdges.sort(key=lambda x: x[2], reverse=True)
selectedInit = 0
mustMinStability = MAX_STABILITY
dsuInit = DSU(list(range(n)))
for u, v, s, must in mustEdges:
if dsuInit.find(u) == dsuInit.find(v) or selectedInit == n - 1:
return -1
dsuInit.join(u, v)
selectedInit += 1
mustMinStability = min(mustMinStability, s)
l = 0
r = mustMinStability
while l < r:
mid = l + ((r - l + 1) >> 1)
dsu = DSU(dsuInit.parent[:])
selected = selectedInit
doubledCount = 0
for u, v, s, must in optionalEdges:
if dsu.find(u) == dsu.find(v):
continue
if s >= mid:
dsu.join(u, v)
selected += 1
elif doubledCount < k and s * 2 >= mid:
doubledCount += 1
dsu.join(u, v)
selected += 1
else:
break
if selected == n - 1:
break
if selected != n - 1:
r = mid - 1
else:
ans = l = mid
return ans
4.7.32 - 2026-03-11 21:48:29 +0300 MSK
Links
Code
class Solution:
def bitwiseComplement(self, n: int) -> int:
if n == 0: return 1
mask = n
for i in (1, 2, 4, 8, 16):
mask |= mask >> i
return ~n & mask
4.7.33 - 2026-03-10 21:15:05 +0300 MSK
Links
Code
class Solution:
def numberOfStableArrays(self, zero: int, one: int, limit: int) -> int:
mod = 10**9 + 7
dp = [[[0, 0] for _ in range(one + 1)] for _ in range(zero + 1)]
for i in range(zero + 1):
for j in range(one + 1):
for lastBit in range(2):
if i == 0:
if lastBit == 0 or j > limit:
dp[i][j][lastBit] = 0
else:
dp[i][j][lastBit] = 1
elif j == 0:
if lastBit == 1 or i > limit:
dp[i][j][lastBit] = 0
else:
dp[i][j][lastBit] = 1
elif lastBit == 0:
dp[i][j][lastBit] = dp[i - 1][j][0] + dp[i - 1][j][1]
if i > limit:
dp[i][j][lastBit] -= dp[i - limit - 1][j][1]
else:
dp[i][j][lastBit] = dp[i][j - 1][0] + dp[i][j - 1][1]
if j > limit:
dp[i][j][lastBit] -= dp[i][j - limit - 1][0]
dp[i][j][lastBit] %= mod
return (dp[-1][-1][0] + dp[-1][-1][1]) % mod
4.7.34 - 2026-03-09 19:32:26 +0300 MSK
Links
Code
class Solution:
def numberOfStableArrays(self, zero: int, one: int, limit: int) -> int:
dp = [[[0, 0] for _ in range(one + 1)] for _ in range(zero + 1)]
mod = int(1e9 + 7)
for i in range(min(zero, limit) + 1):
dp[i][0][0] = 1
for j in range(min(one, limit) + 1):
dp[0][j][1] = 1
for i in range(1, zero + 1):
for j in range(1, one + 1):
if i > limit:
dp[i][j][0] = (
dp[i - 1][j][0]
+ dp[i - 1][j][1]
- dp[i - limit - 1][j][1]
)
else:
dp[i][j][0] = dp[i - 1][j][0] + dp[i - 1][j][1]
dp[i][j][0] = (dp[i][j][0] % mod + mod) % mod
if j > limit:
dp[i][j][1] = (
dp[i][j - 1][1]
+ dp[i][j - 1][0]
- dp[i][j - limit - 1][0]
)
else:
dp[i][j][1] = dp[i][j - 1][1] + dp[i][j - 1][0]
dp[i][j][1] = (dp[i][j][1] % mod + mod) % mod
return (dp[zero][one][0] + dp[zero][one][1]) % mod
4.7.35 - 2026-03-08 19:12:47 +0300 MSK
Links
Code
class Solution:
def findDifferentBinaryString(self, nums: List[str]) -> str:
ans = []
for i in range(len(nums)):
curr = nums[i][i]
ans.append("1" if curr == "0" else "0")
return "".join(ans)
4.7.36 - 2026-03-07 13:13:17 +0300 MSK
Links
Code
class Solution:
def minFlips(self, s: str) -> int:
# Characteristic function
I = lambda ch, x: int(ord(ch) - ord("0") == x)
n = len(s)
pre = [[0, 0] for _ in range(n)]
# Note the boundary case when i=0
for i in range(n):
pre[i][0] = (0 if i == 0 else pre[i - 1][1]) + I(s[i], 1)
pre[i][1] = (0 if i == 0 else pre[i - 1][0]) + I(s[i], 0)
ans = min(pre[n - 1][0], pre[n - 1][1])
if n % 2 == 1:
# If n is an odd number, it is also necessary to calculate suf
suf = [[0, 0] for _ in range(n)]
# Note the boundary case when i = n - 1
for i in range(n - 1, -1, -1):
suf[i][0] = (0 if i == n - 1 else suf[i + 1][1]) + I(s[i], 1)
suf[i][1] = (0 if i == n - 1 else suf[i + 1][0]) + I(s[i], 0)
for i in range(n - 1):
ans = min(ans, pre[i][0] + suf[i + 1][0])
ans = min(ans, pre[i][1] + suf[i + 1][1])
return ans
4.7.37 - 2026-03-06 19:47:33 +0300 MSK
Links
Code
class Solution:
def checkOnesSegment(self, s: str) -> bool:
found_1, cur_1 = False, False
for char in s:
if char == "1":
if found_1 and not cur_1:
return False
elif not found_1:
found_1 = True
cur_1 = True
elif cur_1:
cur_1 = False
return True
4.7.38 - 2026-03-05 21:05:59 +0300 MSK
Links
Code
class Solution:
def minOperations(self, s: str) -> int:
if len(s) < 2:
return 0
prev1 = int(s[0])
prev2 = prev1 ^ 1
count1, count2 = 0, 1
for char in s[1:]:
cur = int(char)
if cur == prev1:
count1 += 1
prev1 = cur ^ 1
else:
prev1 = cur
if cur == prev2:
count2 += 1
prev2 = cur ^ 1
else:
prev2 = cur
return min(count1, count2)
4.7.39 - 2026-03-04 20:10:10 +0300 MSK
Links
Code
class Solution:
def numSpecial(self, mat: List[List[int]]) -> int:
m = len(mat)
n = len(mat[0])
row_count = [0] * m
col_count = [0] * n
ones = []
for row in range(m):
for col in range(n):
if mat[row][col] == 1:
row_count[row] += 1
col_count[col] += 1
ones.append((row, col))
res = 0
while ones:
row, col = ones.pop()
if row_count[row] == 1 and col_count[col] == 1:
res += 1
return res
4.7.40 - 2026-03-03 20:16:05 +0300 MSK
Links
Code
class Solution:
def findKthBit(self, n: int, k: int) -> str:
# Find the position of the rightmost set bit in k
# This helps determine which "section" of the string we're in
position_in_section = k & -k
# Determine if k is in the inverted part of the string
# This checks if the bit to the left of the rightmost set bit is 1
is_in_inverted_part = ((k // position_in_section) >> 1 & 1) == 1
# Determine if the original bit (before any inversion) would be 1
# This is true if k is even (i.e., its least significant bit is 0)
original_bit_is_one = (k & 1) == 0
if is_in_inverted_part:
# If we're in the inverted part, we need to flip the bit
return "0" if original_bit_is_one else "1"
else:
# If we're not in the inverted part, return the original bit
return "1" if original_bit_is_one else "0"
4.7.41 - 2026-03-03 09:50:42 +0300 MSK
Links
Code
class Solution:
def minSwaps(self, grid: List[List[int]]) -> int:
n = len(grid)
pos = [-1] * n
for i in range(n):
for j in range(n - 1, -1, -1):
if grid[i][j] == 1:
pos[i] = j
break
ans = 0
for i in range(n):
k = -1
for j in range(i, n):
if pos[j] <= i:
ans += j - i
k = j
break
if k != -1:
for j in range(k, i, -1):
pos[j], pos[j - 1] = pos[j - 1], pos[j]
else:
return -1
return ans
4.7.42 - 2026-03-03 09:49:36 +0300 MSK
Links
Code
class Solution:
def minSwaps(self, grid: List[List[int]]) -> int:
n = len(grid)
pos = [-1] * n
for i in range(n):
for j in range(n - 1, -1, -1):
if grid[i][j] == 1:
pos[i] = j
break
ans = 0
for i in range(n):
k = -1
for j in range(i, n):
if pos[j] <= i:
ans += j - i
k = j
break
if k != -1:
for j in range(k, i, -1):
pos[j], pos[j - 1] = pos[j - 1], pos[j]
else:
return -1
return ans
4.7.43 - 2026-03-03 09:49:19 +0300 MSK
Links
Code
class Solution:
def minSwaps(self, grid: List[List[int]]) -> int:
n = len(grid)
pos = [-1] * n
for i in range(n):
for j in range(n - 1, -1, -1):
if grid[i][j] == 1:
pos[i] = j
break
ans = 0
for i in range(n):
k = -1
for j in range(i, n):
if pos[j] <= i:
ans += j - i
k = j
break
if k != -1:
for j in range(k, i, -1):
pos[j], pos[j - 1] = pos[j - 1], pos[j]
else:
return -1
return ans
4.7.44 - 2026-03-01 18:20:27 +0300 MSK
Links
Code
class Solution:
def minPartitions(self, n: str) -> int:
return int(max(n))
4.7.45 - 2026-03-01 18:20:02 +0300 MSK
Links
Code
class Solution:
def minPartitions(self, n: str) -> int:
res = 0
for num in n:
res = max(res, int(num))
return res
4.7.46 - 2026-02-28 10:54:54 +0300 MSK
Links
Code
class Solution:
def concatenatedBinary(self, n: int) -> int:
cur = 0
mod = (10 ** 9) + 7
for i in range(1, n + 1):
cur_i = i
while cur_i > 0:
cur = (cur << 1)
cur_i //= 2
cur = (cur + i) % mod
return cur
4.7.47 - 2026-02-27 21:53:34 +0300 MSK
Links
Code
class Solution:
def minOperations(self, s: str, k: int) -> int:
n, m = len(s), s.count("0")
dist = [math.inf] * (n + 1)
nodeSets = [
SortedList(range(0, n + 1, 2)),
SortedList(range(1, n + 1, 2)),
]
q = deque([m])
dist[m] = 0
nodeSets[m % 2].remove(m)
while q:
m = q.popleft()
c1, c2 = max(k - n + m, 0), min(m, k)
lnode, rnode = m + k - 2 * c2, m + k - 2 * c1
nodeSet = nodeSets[lnode % 2]
idx = nodeSet.bisect_left(lnode)
while idx < len(nodeSet) and nodeSet[idx] <= rnode:
m2 = nodeSet[idx]
dist[m2] = dist[m] + 1
q.append(m2)
nodeSet.pop(idx)
return -1 if dist[0] == math.inf else dist[0]
4.7.48 - 2026-02-26 20:44:53 +0300 MSK
Links
Code
class Solution:
def numSteps(self, s: str) -> int:
N = len(s)
operations = 0
carry = 0
for i in range(N - 1, 0, -1):
digit = int(s[i]) + carry
if digit % 2 == 1:
operations += 2
carry = 1
else:
operations += 1
return operations + carry
4.7.49 - 2026-02-25 21:05:52 +0300 MSK
Links
Code
class Solution:
def sortByBits(self, arr: List[int]) -> List[int]:
def find_weight(num):
weight = 0
while num:
weight += 1
num &= (num - 1)
return weight
arr.sort(key = lambda num: (find_weight(num), num))
return arr
4.7.50 - 2026-02-24 19:51:26 +0300 MSK
Links
Code
class Solution:
def sumRootToLeaf(self, root: TreeNode) -> int:
def dfs(node: TreeNode, n = 0)-> None:
if not node: return
n = 2 * n + node.val
if not node.left and not node.right:
self.ans+= n
return
dfs(node.left , n)
dfs(node.right, n)
return
self.ans = 0
dfs(root)
return self.ans
4.7.51 - 2026-02-23 18:14:19 +0300 MSK
Links
Code
class Solution:
def hasAllCodes(self, s: str, k: int) -> bool:
req = 1 << k
seen = [False] * req
mask = req - 1
h = 0
for i, ch in enumerate(s):
h = ((h << 1) & mask) | (ord(ch) & 1)
if i >= k - 1 and not seen[h]:
seen[h] = True
req -= 1
if req == 0:
return True
return False
4.7.52 - 2026-02-22 17:40:07 +0300 MSK
Links
Code
class Solution(object):
def binaryGap(self, N):
last = None
ans = 0
for i in range(32):
if (N >> i) & 1:
if last is not None:
ans = max(ans, i - last)
last = i
return ans
4.7.53 - 2026-02-21 18:56:25 +0300 MSK
Links
Code
class Solution(object):
def countPrimeSetBits(self, L, R):
primes = {2, 3, 5, 7, 11, 13, 17, 19}
return sum(bin(x).count('1') in primes
for x in range(L, R+1))
4.7.54 - 2026-02-21 18:55:40 +0300 MSK
Links
Code
class Solution:
def makeLargestSpecial(self, s: str) -> str:
count = 0
i = 0
res = []
for j in range(len(s)):
# Track balance: +1 for '1', -1 for '0'
count += 1 if s[j] == '1' else -1
# Found a balanced chunk when count returns to 0
if count == 0:
# Recursively maximize inner part, wrap with 1...0
res.append('1' + self.makeLargestSpecial(s[i + 1:j]) + '0')
i = j + 1 # Move to next potential chunk
# Sort chunks in descending order for largest arrangement
res.sort(reverse=True)
return ''.join(res)
4.7.55 - 2026-02-19 20:42:48 +0300 MSK
Links
Code
class Solution:
def countBinarySubstrings(self, s):
ans, prev, cur = 0, 0, 1
for i in range(1, len(s)):
if s[i-1] != s[i]:
ans += min(prev, cur)
prev, cur = cur, 1
else:
cur += 1
return ans + min(prev, cur)
4.7.56 - 2026-02-18 20:35:40 +0300 MSK
Links
Code
class Solution(object):
def hasAlternatingBits(self, n):
n, cur = divmod(n, 2)
while n:
if cur == n % 2: return False
n, cur = divmod(n, 2)
return True
4.7.57 - 2026-02-17 20:18:33 +0300 MSK
Links
Code
class Solution:
def readBinaryWatch(self, turnedOn: int) -> List[str]:
ans = list()
for h in range(12):
for m in range(60):
if bin(h).count("1") + bin(m).count("1") == turnedOn:
ans.append(f"{h}:{m:02d}")
return ans
4.7.58 - 2026-02-16 19:40:12 +0300 MSK
Links
Code
class Solution:
def reverseBits(self, n: int) -> int:
res = 0
count = 32
while n > 0 or count > 0:
res = (res << 1) | (n & 1)
n >>= 1
count -= 1
return res
4.7.59 - 2026-02-15 20:58:12 +0300 MSK
Links
Code
class Solution:
def addBinary(self, a, b) -> str:
x, y = int(a, 2), int(b, 2)
while y:
x, y = x ^ y, (x & y) << 1
return bin(x)[2:]
4.7.60 - 2026-02-14 12:54:19 +0300 MSK
Links
Code
class Solution:
def champagneTower(self, poured, query_row, query_glass):
A = [[0] * k for k in range(1, 102)]
A[0][0] = poured
for r in range(query_row + 1):
for c in range(r+1):
q = (A[r][c] - 1.0) / 2.0
if q > 0:
A[r+1][c] += q
A[r+1][c+1] += q
return min(1, A[query_row][query_glass])
4.7.61 - 2026-02-13 09:19:20 +0300 MSK
Links
Code
class Solution:
def longestBalanced(self, s: str) -> int:
n=len(s)
# Deal with 1-letter balance
ans, Len=1, 1
for c0, c1 in pairwise(s):
if c0==c1: Len+=1
else:
ans=max(ans, Len)
Len=1
ans=max(ans, Len)
ab, bc, ca, abc={},{},{},{}
abc[(0, 0)]=ab[(0, 0)]=bc[(0, 0)]=ca[(0, 0)]=-1
cnt=[0, 0, 0]
for i, c in enumerate(s):
cnt[ord(c)-97]+=1
A, B, C=cnt
# 3-letter balance: A=B=C
key=(B-A, C-A)
if key in abc: ans=max(ans, i-abc[key])
else: abc[key]=i
# 2-letter balance:
key=(A-B, C)
if key in ab: ans=max(ans, i-ab[key])
else: ab[key]=i
key=(B-C, A)
if key in bc: ans=max(ans, i-bc[key])
else: bc[key]=i
key=(C-A, B)
if key in ca: ans=max(ans, i-ca[key])
else: ca[key]=i
return ans
4.7.62 - 2026-02-12 19:02:27 +0300 MSK
Links
Code
class Solution:
def longestBalanced(self, s: str) -> int:
n = len(s)
res = 0
for i in range(n):
cnt = defaultdict(int)
for j in range(i, n):
cnt[s[j]] += 1
if len(set(cnt.values())) == 1:
res = max(res, j - i + 1)
return res
4.7.63 - 2026-02-11 20:12:38 +0300 MSK
Links
Code
class LazyTag:
def __init__(self):
self.to_add = 0
def add(self, other):
self.to_add += other.to_add
return self
def has_tag(self):
return self.to_add != 0
def clear(self):
self.to_add = 0
class SegmentTreeNode:
def __init__(self):
self.min_value = 0
self.max_value = 0
self.lazy_tag = LazyTag()
class SegmentTree:
def __init__(self, data):
self.n = len(data)
self.tree = [SegmentTreeNode() for _ in range(self.n * 4 + 1)]
self._build(data, 1, self.n, 1)
def add(self, l, r, val):
tag = LazyTag()
tag.to_add = val
self._update(l, r, tag, 1, self.n, 1)
def find_last(self, start, val):
if start > self.n:
return -1
return self._find(start, self.n, val, 1, self.n, 1)
def _apply_tag(self, i, tag):
self.tree[i].min_value += tag.to_add
self.tree[i].max_value += tag.to_add
self.tree[i].lazy_tag.add(tag)
def _pushdown(self, i):
if self.tree[i].lazy_tag.has_tag():
tag = LazyTag()
tag.to_add = self.tree[i].lazy_tag.to_add
self._apply_tag(i << 1, tag)
self._apply_tag((i << 1) | 1, tag)
self.tree[i].lazy_tag.clear()
def _pushup(self, i):
self.tree[i].min_value = min(
self.tree[i << 1].min_value, self.tree[(i << 1) | 1].min_value
)
self.tree[i].max_value = max(
self.tree[i << 1].max_value, self.tree[(i << 1) | 1].max_value
)
def _build(self, data, l, r, i):
if l == r:
self.tree[i].min_value = data[l - 1]
self.tree[i].max_value = data[l - 1]
return
mid = l + ((r - l) >> 1)
self._build(data, l, mid, i << 1)
self._build(data, mid + 1, r, (i << 1) | 1)
self._pushup(i)
def _update(self, target_l, target_r, tag, l, r, i):
if target_l <= l and r <= target_r:
self._apply_tag(i, tag)
return
self._pushdown(i)
mid = l + ((r - l) >> 1)
if target_l <= mid:
self._update(target_l, target_r, tag, l, mid, i << 1)
if target_r > mid:
self._update(target_l, target_r, tag, mid + 1, r, (i << 1) | 1)
self._pushup(i)
def _find(self, target_l, target_r, val, l, r, i):
if self.tree[i].min_value > val or self.tree[i].max_value < val:
return -1
if l == r:
return l
self._pushdown(i)
mid = l + ((r - l) >> 1)
if target_r >= mid + 1:
res = self._find(target_l, target_r, val, mid + 1, r, (i << 1) | 1)
if res != -1:
return res
if l <= target_r and mid >= target_l:
return self._find(target_l, target_r, val, l, mid, i << 1)
return -1
class Solution:
def longestBalanced(self, nums: List[int]) -> int:
occurrences = defaultdict(deque)
def sgn(x):
return 1 if x % 2 == 0 else -1
length = 0
prefix_sum = [0] * len(nums)
prefix_sum[0] = sgn(nums[0])
occurrences[nums[0]].append(1)
for i in range(1, len(nums)):
prefix_sum[i] = prefix_sum[i - 1]
occ = occurrences[nums[i]]
if not occ:
prefix_sum[i] += sgn(nums[i])
occ.append(i + 1)
seg = SegmentTree(prefix_sum)
for i in range(len(nums)):
length = max(length, seg.find_last(i + length, 0) - i)
next_pos = len(nums) + 1
occurrences[nums[i]].popleft()
if occurrences[nums[i]]:
next_pos = occurrences[nums[i]][0]
seg.add(i + 1, next_pos - 1, -sgn(nums[i]))
return length
4.7.64 - 2026-02-10 13:02:01 +0300 MSK
Links
Code
import collections
class Solution:
def longestBalanced(self, nums: List[int]) -> int:
count_even, count_odd = 0, 0
res = 0
freqs = collections.defaultdict(int)
for i in range(len(nums)):
num_i = nums[i]
for j in range(i, len(nums)):
num = nums[j]
freqs[num] += 1
if freqs[num] == 1:
if num % 2 == 0:
count_even += 1
else:
count_odd += 1
if count_even == count_odd:
res = max(res, j - i + 1)
freqs.clear()
count_even, count_odd = 0, 0
return res
4.7.65 - 2026-02-09 20:09:17 +0300 MSK
Links
Code
class Solution:
def balanceBST(self, root: TreeNode) -> TreeNode:
if not root:
return None
# Step 1: Create the backbone (vine)
# Temporary dummy node
vine_head = TreeNode(0)
vine_head.right = root
current = vine_head
while current.right:
if current.right.left:
self.right_rotate(current, current.right)
else:
current = current.right
# Step 2: Count the nodes
node_count = 0
current = vine_head.right
while current:
node_count += 1
current = current.right
# Step 3: Create a balanced BST
m = 2 ** math.floor(math.log2(node_count + 1)) - 1
self.make_rotations(vine_head, node_count - m)
while m > 1:
m //= 2
self.make_rotations(vine_head, m)
balanced_root = vine_head.right
# Delete the temporary dummy node
vine_head = None
return balanced_root
# Function to perform a right rotation
def right_rotate(self, parent: TreeNode, node: TreeNode):
tmp = node.left
node.left = tmp.right
tmp.right = node
parent.right = tmp
# Function to perform a left rotation
def left_rotate(self, parent: TreeNode, node: TreeNode):
tmp = node.right
node.right = tmp.left
tmp.left = node
parent.right = tmp
# Function to perform a series of left rotations to balance the vine
def make_rotations(self, vine_head: TreeNode, count: int):
current = vine_head
for _ in range(count):
tmp = current.right
self.left_rotate(current, tmp)
current = current.right
4.7.66 - 2026-02-08 13:23:59 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def isBalanced(self, root: Optional[TreeNode]) -> bool:
return self.dfs(root) != -1
def dfs(self, node: Optional[TreeNode]) -> int:
if node is None:
return 0
depth1, depth2 = self.dfs(node.left), self.dfs(node.right)
if depth1 == -1 or depth2 == -1 or abs(depth2 - depth1) > 1:
return -1
return 1 + max(depth1, depth2)
4.7.67 - 2026-02-07 18:17:37 +0300 MSK
Links
Code
class Solution:
def minimumDeletions(self, s: str) -> int:
left_a, right_a = 0, s.count("a")
left_b, right_b = 0, len(s) - right_a
res = min(right_a, right_b)
for char in s:
if char == "a":
left_a += 1
right_a -= 1
else:
left_b += 1
right_b -= 1
res = min(res, left_b + right_a)
return res
4.7.68 - 2026-02-06 20:36:14 +0300 MSK
Links
Code
class Solution:
def minRemoval(self, nums: List[int], k: int) -> int:
n = len(nums)
nums.sort()
ans = n
right = 0
for left in range(n):
while right < n and nums[right] <= nums[left] * k:
right += 1
ans = min(ans, n - (right - left))
return ans
4.7.69 - 2026-02-05 15:26:43 +0300 MSK
Links
Code
class Solution:
def constructTransformedArray(self, nums: List[int]) -> List[int]:
res = [0] * len(nums)
for i, num in enumerate(nums):
res[i] = nums[(i + num) % len(nums)]
return res
4.7.70 - 2026-02-04 18:39:04 +0300 MSK
Links
Code
class Solution:
def maxSumTrionic(self, nums: List[int]) -> int:
n = len(nums)
ans = float("-inf")
i = 0
while i < n:
j = i + 1
res = 0
# first segment: increasing segment
while j < n and nums[j - 1] < nums[j]:
j += 1
p = j - 1
if p == i: # 没有有效的increasing segment
i += 1
continue
# second segment: decreasing segment
res += nums[p] + nums[p - 1]
while j < n and nums[j - 1] > nums[j]:
res += nums[j]
j += 1
q = j - 1
if q == p or q == n - 1 or (j < n and nums[j] <= nums[q]):
i = q
continue
# third segment: increasing segment
res += nums[q + 1]
# find the maximum sum of the third segment
max_sum = 0
curr_sum = 0
k = q + 2
while k < n and nums[k] > nums[k - 1]:
curr_sum += nums[k]
max_sum = max(max_sum, curr_sum)
k += 1
res += max_sum
# find the maximum sum of the first segment
max_sum = 0
curr_sum = 0
for k in range(p - 2, i - 1, -1):
curr_sum += nums[k]
max_sum = max(max_sum, curr_sum)
res += max_sum
# update answer
ans = max(ans, res)
i = q
return ans
4.7.71 - 2026-02-03 21:24:01 +0300 MSK
Links
Code
class Solution:
def isTrionic(self, nums: List[int]) -> bool:
if nums[0] >= nums[1] or nums[-2] >= nums[-1] :
return False
seg = 1
for i in range(2, len(nums)):
cur, prev = nums[i], nums[i - 1]
if cur == prev:
return False
if cur > prev:
if seg == 2:
seg = 3
else:
if seg == 1:
seg = 2
elif seg == 3:
return False
return seg == 3
4.7.72 - 2026-02-03 14:14:39 +0300 MSK
Links
Code
class Solution:
def countMonobit(self, n: int) -> int:
res = 0
cur = 0
while cur <= n:
res += 1
cur = (cur << 1) | 1
return res
4.7.73 - 2026-02-03 14:11:12 +0300 MSK
Links
Code
class Solution:
def reverseByType(self, s: str) -> str:
res = list(s)
length = len(s)
alpha, spec = length - 1, length - 1
for i, char in enumerate(s):
if char.isalpha():
while not s[alpha].isalpha():
alpha -= 1
target = alpha
alpha -= 1
else:
while s[spec].isalpha():
spec -= 1
target = spec
spec -= 1
res[i], res[target] = s[target], char
return "".join(res)
4.7.74 - 2026-02-03 14:06:32 +0300 MSK
Links
Code
class Solution:
def reverseByType(self, s: str) -> str:
alpha, spec, res = [], [], []
for char in s:
if char.isalpha():
alpha.append(char)
else:
spec.append(char)
for char in s:
if char.isalpha():
res.append(alpha.pop())
else:
res.append(spec.pop())
return "".join(res)
4.7.75 - 2026-02-03 13:54:07 +0300 MSK
Links
Code
class Solution:
def vowelConsonantScore(self, s: str) -> int:
length = len(s)
vow = {"a", "e", "i", "o", "u"}
vows = 0
cons = 0
for char in s:
if char in vow:
vows += 1
elif char.isalpha():
cons += 1
if cons == 0:
return 0
return vows // cons
4.7.76 - 2026-02-03 12:24:12 +0300 MSK
Links
Code
class Solution:
def residuePrefixes(self, s: str) -> int:
freqs = [0] * 26
dist = 0
res = 0
for i in range(len(s)):
target = (i + 1) % 3
chr = ord(s[i]) - 97
freqs[chr] += 1
if freqs[chr] == 1:
dist += 1
if dist == target:
res += 1
return res
4.7.77 - 2026-02-02 18:52:16 +0300 MSK
Links
Code
class Container:
def __init__(self, k: int):
self.k = k
self.st1 = SortedList()
self.st2 = SortedList()
self.sm = 0
def adjust(self):
while len(self.st1) < self.k and len(self.st2) > 0:
x = self.st2[0]
self.st1.add(x)
self.st2.remove(x)
self.sm += x
while len(self.st1) > self.k:
x = self.st1[-1]
self.st2.add(x)
self.st1.remove(x)
self.sm -= x
# insert element x
def add(self, x: int):
if len(self.st2) > 0 and x >= self.st2[0]:
self.st2.add(x)
else:
self.st1.add(x)
self.sm += x
self.adjust()
# delete element x
def erase(self, x: int):
if x in self.st1:
self.st1.remove(x)
self.sm -= x
elif x in self.st2:
self.st2.remove(x)
self.adjust()
# sum of the first k smallest elements
def sum(self) -> int:
return self.sm
class Solution:
def minimumCost(self, nums: List[int], k: int, dist: int) -> int:
n = len(nums)
cnt = Container(k - 2)
for i in range(1, k - 1):
cnt.add(nums[i])
ans = cnt.sum() + nums[k - 1]
for i in range(k, n):
j = i - dist - 1
if j > 0:
cnt.erase(nums[j])
cnt.add(nums[i - 1])
ans = min(ans, cnt.sum() + nums[i])
return ans + nums[0]
4.7.78 - 2026-02-01 19:46:21 +0300 MSK
Links
Code
class Solution:
def minimumCost(self, nums: List[int]) -> int:
num1, num2 = float("inf"), float("inf")
heap = []
for i in range(1, len(nums)):
heapq.heappush(heap, nums[i])
return nums[0] + heapq.heappop(heap) + heapq.heappop(heap)
4.7.79 - 2026-02-01 19:45:22 +0300 MSK
Links
Code
class Solution:
def minimumCost(self, nums: List[int]) -> int:
num1, num2 = float("inf"), float("inf")
for i in range(1, len(nums)):
num = nums[i]
if num <= num1:
num1, num2 = num, min(num1, num2)
elif num <= num2:
num1, num2 = min(num1, num2), num
return nums[0] + num1 + num2
4.7.80 - 2026-01-31 21:17:17 +0300 MSK
Links
Code
class Solution:
def nextGreatestLetter(self, letters: List[str], target: str) -> str:
for ch in letters:
if ch > target:
return ch
return letters[0]
4.7.81 - 2026-01-30 20:30:09 +0300 MSK
Links
Code
INF = 10**18
INF_INT = 10**9
class Solution:
def minimumCost(
self,
source: str,
target: str,
original: List[str],
changed: List[str],
cost: List[int],
) -> int:
n = len(source)
m = len(original)
child = [[-1] * 26]
tid = [-1]
def new_node() -> int:
child.append([-1] * 26)
tid.append(-1)
return len(child) - 1
idx = -1
def add(word: str) -> int:
nonlocal idx
node = 0
for ch in word:
c = ord(ch) - 97
nxt = child[node][c]
if nxt == -1:
nxt = new_node()
child[node][c] = nxt
node = nxt
if tid[node] == -1:
idx += 1
tid[node] = idx
return tid[node]
edges = []
for i in range(m):
x = add(original[i])
y = add(changed[i])
edges.append((x, y, cost[i]))
P = idx + 1
if P == 0:
return 0 if source == target else -1
dist = [[INF_INT] * P for _ in range(P)]
for i in range(P):
dist[i][i] = 0
for x, y, w in edges:
if w < dist[x][y]:
dist[x][y] = w
for k in range(P):
dk = dist[k]
for i in range(P):
di = dist[i]
dik = di[k]
if dik == INF_INT:
continue
base = dik
for j in range(P):
nd = base + dk[j]
if nd < di[j]:
di[j] = nd
dp = [INF] * (n + 1)
dp[0] = 0
s_arr = [ord(c) - 97 for c in source]
t_arr = [ord(c) - 97 for c in target]
for j in range(n):
if dp[j] >= INF:
continue
base = dp[j]
if source[j] == target[j] and base < dp[j + 1]:
dp[j + 1] = base
u = 0
v = 0
for i in range(j, n):
u = child[u][s_arr[i]]
v = child[v][t_arr[i]]
if u == -1 or v == -1:
break
uid = tid[u]
vid = tid[v]
if uid != -1 and vid != -1:
w = dist[uid][vid]
if w != INF_INT:
ni = i + 1
cand = base + w
if cand < dp[ni]:
dp[ni] = cand
ans = dp[n]
return -1 if ans >= INF else ans
4.7.82 - 2026-01-29 22:21:59 +0300 MSK
Links
Code
class Solution:
def minimumCost(
self,
source: str,
target: str,
original: List[str],
changed: List[str],
cost: List[int],
) -> int:
# Initialize result to store the total minimum cost
total_cost = 0
# Initialize a 2D list to store the minimum transformation cost
# between any two characters
min_cost = [[float("inf")] * 26 for _ in range(26)]
# Fill the initial transformation costs from the given original,
# changed, and cost arrays
for orig, chg, cst in zip(original, changed, cost):
start_char = ord(orig) - ord("a")
end_char = ord(chg) - ord("a")
min_cost[start_char][end_char] = min(
min_cost[start_char][end_char], cst
)
# Use Floyd-Warshall algorithm to find the shortest path between any
# two characters
for k in range(26):
for i in range(26):
for j in range(26):
min_cost[i][j] = min(
min_cost[i][j], min_cost[i][k] + min_cost[k][j]
)
# Calculate the total minimum cost to transform the source string to
# the target string
for src, tgt in zip(source, target):
if src == tgt:
continue
source_char = ord(src) - ord("a")
target_char = ord(tgt) - ord("a")
# If the transformation is not possible, return -1
if min_cost[source_char][target_char] == float("inf"):
return -1
total_cost += min_cost[source_char][target_char]
return total_cost
4.7.83 - 2026-01-28 20:51:42 +0300 MSK
Links
Code
class Solution:
def minCost(self, grid: list[list[int]], k: int) -> int:
m, n = len(grid), len(grid[0])
points = [(i, j) for i in range(m) for j in range(n)]
points.sort(key=lambda p: grid[p[0]][p[1]])
costs = [[float("inf")] * n for _ in range(m)]
for t in range(k + 1):
minCost = float("inf")
j = 0
for i in range(len(points)):
minCost = min(minCost, costs[points[i][0]][points[i][1]])
if (
i + 1 < len(points)
and grid[points[i][0]][points[i][1]]
== grid[points[i + 1][0]][points[i + 1][1]]
):
i += 1
continue
for r in range(j, i + 1):
costs[points[r][0]][points[r][1]] = minCost
j = i + 1
for i in range(m - 1, -1, -1):
for j in range(n - 1, -1, -1):
if i == m - 1 and j == n - 1:
costs[i][j] = 0
continue
if i != m - 1:
costs[i][j] = min(
costs[i][j], costs[i + 1][j] + grid[i + 1][j]
)
if j != n - 1:
costs[i][j] = min(
costs[i][j], costs[i][j + 1] + grid[i][j + 1]
)
return costs[0][0]
4.7.84 - 2026-01-27 22:11:38 +0300 MSK
Links
Code
class Solution:
def dijkstra(self, n: int) -> int:
INF = 10**9
vis = [False] * n
dist = [INF] * n
pq: List[Tuple[int, int]] = [(0, 0)]
dist[0] = 0
while pq:
du, u = heapq.heappop(pq)
if vis[u]:
continue
vis[u] = True
for v, w in self.G[u]:
nd = du + w
if nd < dist[v]:
dist[v] = nd
heapq.heappush(pq, (nd, v))
return -1 if dist[n - 1] == INF else dist[n - 1]
def minCost(self, n: int, edges: List[List[int]]) -> int:
self.G = [[] for _ in range(n)]
for u, v, w in edges:
self.G[u].append((v, w))
self.G[v].append((u, 2 * w))
return self.dijkstra(n)
4.7.85 - 2026-01-26 20:02:52 +0300 MSK
Links
Code
class Solution:
def minimumAbsDifference(self, arr: List[int]) -> List[List[int]]:
arr.sort()
res = []
min_diff = float("inf")
for i in range(len(arr) - 1):
cur, nxt = arr[i], arr[i + 1]
diff = nxt - cur
if diff < min_diff:
min_diff = diff
res.clear()
if diff == min_diff:
res.append((cur, nxt))
return res
4.7.86 - 2026-01-25 21:10:14 +0300 MSK
Links
Code
class Solution:
def minimumDifference(self, nums: List[int], k: int) -> int:
nums.sort()
return min(nums[i + k - 1] - nums[i] for i in range(len(nums) - k + 1))
4.7.87 - 2026-01-24 19:43:56 +0300 MSK
Links
Code
class Solution:
def minPairSum(self, nums: List[int]) -> int:
nums.sort()
res = float("-inf")
for i in range((len(nums) // 2) + 1):
res = max(res, nums[i] + nums[-i - 1])
return res
4.7.88 - 2026-01-23 20:09:20 +0300 MSK
Links
Code
class Node:
def __init__(self, value, left):
self.value = value
self.left = left
self.prev = None
self.next = None
class Solution:
def minimumPairRemoval(self, nums: List[int]) -> int:
class PQItem:
def __init__(self, first, second, cost):
self.first = first
self.second = second
self.cost = cost
def __lt__(self, other):
if self.cost == other.cost:
return self.first.left < other.first.left
return self.cost < other.cost
pq = []
head = Node(nums[0], 0)
current = head
merged = [False] * len(nums)
decrease_count = 0
count = 0
for i in range(1, len(nums)):
new_node = Node(nums[i], i)
current.next = new_node
new_node.prev = current
heapq.heappush(
pq, PQItem(current, new_node, current.value + new_node.value)
)
if nums[i - 1] > nums[i]:
decrease_count += 1
current = new_node
while decrease_count > 0:
item = heapq.heappop(pq)
first, second, cost = item.first, item.second, item.cost
if (
merged[first.left]
or merged[second.left]
or first.value + second.value != cost
):
continue
count += 1
if first.value > second.value:
decrease_count -= 1
prev_node = first.prev
next_node = second.next
first.next = next_node
if next_node:
next_node.prev = first
if prev_node:
if prev_node.value > first.value and prev_node.value <= cost:
decrease_count -= 1
elif prev_node.value <= first.value and prev_node.value > cost:
decrease_count += 1
heapq.heappush(
pq, PQItem(prev_node, first, prev_node.value + cost)
)
if next_node:
if second.value > next_node.value and cost <= next_node.value:
decrease_count -= 1
elif second.value <= next_node.value and cost > next_node.value:
decrease_count += 1
heapq.heappush(
pq, PQItem(first, next_node, cost + next_node.value)
)
first.value = cost
merged[second.left] = True
return count
4.7.89 - 2026-01-22 19:21:03 +0300 MSK
Links
Code
class Solution:
def removeElement(self, nums: List[int], val: int) -> int:
length = len(nums)
if length < 2:
return length - nums.count(val)
left, right = 0, length - 1
res = 0
while left <= right:
if nums[left] != val:
res += 1
left += 1
continue
if left == right:
break
while right > left:
if nums[right] == val:
right -= 1
else:
nums[left] = nums[right]
right -= 1
left += 1
res += 1
break
return res
4.7.90 - 2026-01-22 18:45:34 +0300 MSK
Links
Code
class Solution:
def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
"""
Do not return anything, modify nums1 in-place instead.
"""
target, idx1, idx2 = m + n - 1, m - 1, n - 1
neg_inf = float("-inf")
while target >= 0:
if idx1 >= 0:
num1 = nums1[idx1]
else:
num1 = neg_inf
if idx2 >= 0:
num2 = nums2[idx2]
else:
num2 = neg_inf
if num1 >= num2:
nums1[target] = num1
idx1 -= 1
target -= 1
else:
nums1[target] = num2
idx2 -= 1
target -= 1
4.7.91 - 2026-01-22 18:41:51 +0300 MSK
Links
Code
class Solution:
def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
"""
Do not return anything, modify nums1 in-place instead.
"""
if not nums2:
return nums1
for i in reversed(range(m)):
nums1[i + n] = nums1[i]
target, idx1, idx2 = 0, 0, 0
inf = float("inf")
while target < m + n:
if idx1 < m:
num1 = nums1[idx1 + n]
else:
num1 = inf
if idx2 < n:
num2 = nums2[idx2]
else:
num2 = inf
if num1 < num2:
nums1[target] = num1
target += 1
idx1 += 1
else:
nums1[target] = num2
target += 1
idx2 += 1
4.7.92 - 2026-01-22 18:07:41 +0300 MSK
Links
Code
class Solution:
def minimumPairRemoval(self, nums: List[int]) -> int:
count = 0
while len(nums) > 1:
isAscending = True
minSum = float("inf")
targetIndex = -1
for i in range(len(nums) - 1):
pair_sum = nums[i] + nums[i + 1]
if nums[i] > nums[i + 1]:
isAscending = False
if pair_sum < minSum:
minSum = pair_sum
targetIndex = i
if isAscending:
break
count += 1
nums[targetIndex] = minSum
nums.pop(targetIndex + 1)
return count
4.7.93 - 2026-01-22 10:20:58 +0300 MSK
Links
Code
class Solution:
def minBitwiseArray(self, nums: List[int]) -> List[int]:
for i in range(len(nums)):
res = -1
d = 1
while (nums[i] & d) != 0:
res = nums[i] - d
d <<= 1
nums[i] = res
return nums
4.7.94 - 2026-01-20 11:39:04 +0300 MSK
Links
Code
class Solution:
def minBitwiseArray(self, nums: List[int]) -> List[int]:
for i in range(len(nums)):
res = -1
d = 1
while (nums[i] & d) != 0:
res = nums[i] - d
d <<= 1
nums[i] = res
return nums
4.7.95 - 2026-01-19 12:02:06 +0300 MSK
Links
Code
class Solution:
def maxSideLength(self, mat: List[List[int]], threshold: int) -> int:
m, n = len(mat), len(mat[0])
P = [[0] * (n + 1) for _ in range(m + 1)]
for i in range(1, m + 1):
for j in range(1, n + 1):
P[i][j] = (
P[i - 1][j]
+ P[i][j - 1]
- P[i - 1][j - 1]
+ mat[i - 1][j - 1]
)
def getRect(x1, y1, x2, y2):
return P[x2][y2] - P[x1 - 1][y2] - P[x2][y1 - 1] + P[x1 - 1][y1 - 1]
r, ans = min(m, n), 0
for i in range(1, m + 1):
for j in range(1, n + 1):
for c in range(ans + 1, r + 1):
if (
i + c - 1 <= m
and j + c - 1 <= n
and getRect(i, j, i + c - 1, j + c - 1) <= threshold
):
ans += 1
else:
break
return ans
4.7.96 - 2026-01-18 17:30:31 +0300 MSK
Links
Code
class Solution:
def largestMagicSquare(self, grid: List[List[int]]) -> int:
m, n = len(grid), len(grid[0])
rowsum = [[0] * n for _ in range(m)]
for i in range(m):
rowsum[i][0] = grid[i][0]
for j in range(1, n):
rowsum[i][j] = rowsum[i][j - 1] + grid[i][j]
colsum = [[0] * n for _ in range(m)]
for j in range(n):
colsum[0][j] = grid[0][j]
for i in range(1, m):
colsum[i][j] = colsum[i - 1][j] + grid[i][j]
for edge in range(min(m, n), 1, -1):
for i in range(m - edge + 1):
for j in range(n - edge + 1):
stdsum = rowsum[i][j + edge - 1] - (
0 if j == 0 else rowsum[i][j - 1]
)
check = True
for ii in range(i + 1, i + edge):
if (
rowsum[ii][j + edge - 1]
- (0 if j == 0 else rowsum[ii][j - 1])
!= stdsum
):
check = False
break
if not check:
continue
for jj in range(j, j + edge):
if (
colsum[i + edge - 1][jj]
- (0 if i == 0 else colsum[i - 1][jj])
!= stdsum
):
check = False
break
if not check:
continue
d1 = d2 = 0
for k in range(edge):
d1 += grid[i + k][j + k]
d2 += grid[i + k][j + edge - 1 - k]
if d1 == stdsum and d2 == stdsum:
return edge
return 1
4.7.97 - 2026-01-18 16:48:45 +0300 MSK
Links
Code
class Solution:
def largestSquareArea(
self, bottomLeft: List[List[int]], topRight: List[List[int]]
) -> int:
max_size = 0
for (bottom_left_i, top_right_i), (
bottom_left_j,
top_right_j,
) in combinations(zip(bottomLeft, topRight), 2):
w = min(top_right_i[0], top_right_j[0]) - max(
bottom_left_i[0], bottom_left_j[0]
)
h = min(top_right_i[1], top_right_j[1]) - max(
bottom_left_i[1], bottom_left_j[1]
)
max_size = max(max_size, min(w, h))
return max_size * max_size
4.7.98 - 2026-01-16 19:37:40 +0300 MSK
Links
Code
class Solution:
def get_edges(self, fences: List[int], border: int) -> set:
points = sorted([1] + fences + [border])
return {
points[j] - points[i]
for i in range(len(points))
for j in range(i + 1, len(points))
}
def maximizeSquareArea(
self, m: int, n: int, hFences: List[int], vFences: List[int]
) -> int:
MOD = 10**9 + 7
h_edges = self.get_edges(hFences, m)
v_edges = self.get_edges(vFences, n)
max_edge = max(h_edges & v_edges, default=0)
return (max_edge * max_edge) % MOD if max_edge else -1
4.7.99 - 2026-01-15 17:40:29 +0300 MSK
Links
Code
class Solution:
def maximizeSquareHoleArea(
self, n: int, m: int, hBars: List[int], vBars: List[int]
) -> int:
hBars.sort()
vBars.sort()
hmax, vmax = 1, 1
hcur, vcur = 1, 1
for i in range(1, len(hBars)):
if hBars[i] == hBars[i - 1] + 1:
hcur += 1
else:
hcur = 1
hmax = max(hmax, hcur)
for i in range(1, len(vBars)):
if vBars[i] == vBars[i - 1] + 1:
vcur += 1
else:
vcur = 1
vmax = max(vmax, vcur)
side = min(hmax, vmax) + 1
return side * side
4.7.100 - 2026-01-14 22:52:51 +0300 MSK
Links
Code
from typing import List
import bisect
class SegmentTree:
def __init__(self, xs: List[int]):
self.xs = xs
self.n = len(xs) - 1
self.count = [0] * (4 * self.n)
self.covered = [0] * (4 * self.n)
def update(self, qleft, qright, qval, left, right, pos):
if self.xs[right + 1] <= qleft or self.xs[left] >= qright:
return
if qleft <= self.xs[left] and self.xs[right + 1] <= qright:
self.count[pos] += qval
else:
mid = (left + right) // 2
self.update(qleft, qright, qval, left, mid, pos * 2 + 1)
self.update(qleft, qright, qval, mid + 1, right, pos * 2 + 2)
if self.count[pos] > 0:
self.covered[pos] = self.xs[right + 1] - self.xs[left]
else:
if left == right:
self.covered[pos] = 0
else:
self.covered[pos] = (
self.covered[pos * 2 + 1] + self.covered[pos * 2 + 2]
)
def query(self):
return self.covered[0]
class Solution:
def separateSquares(self, squares: List[List[int]]) -> float:
events = []
xs_set = set()
for x, y, l in squares:
events.append((y, 1, x, x + l))
events.append((y + l, -1, x, x + l))
xs_set.update([x, x + l])
xs = sorted(xs_set)
seg_tree = SegmentTree(xs)
events.sort()
psum = []
widths = []
total_area = 0.0
prev_y = events[0][0]
# scan: calculate total area and record intermediate states
for y, delta, xl, xr in events:
length = seg_tree.query()
total_area += length * (y - prev_y)
seg_tree.update(xl, xr, delta, 0, seg_tree.n - 1, 0)
# record prefix sums and widths
psum.append(total_area)
widths.append(seg_tree.query())
prev_y = y
# calculate the target area (half rounded up)
target = (total_area + 1) // 2
# find the first position greater than or equal to target using binary search
i = bisect.bisect_left(psum, target) - 1
# get the corresponding area, width, and height
area = psum[i]
width = widths[i]
height = events[i][0]
return height + (total_area - area * 2) / (width * 2.0)
4.7.101 - 2026-01-13 19:03:15 +0300 MSK
Links
Code
class Solution:
def separateSquares(self, squares: List[List[int]]) -> float:
total_area = 0
events = []
for sq in squares:
y, l = sq[1], sq[2]
total_area += l * l
events.append((y, l, 1))
events.append((y + l, l, -1))
# sort by y-coordinate
events.sort(key=lambda x: x[0])
covered_width = (
0.0 # sum of all bottom edges under the current scanning line
)
curr_area = 0.0 # current cumulative area
prev_height = 0.0 # height of the previous scanning line
for y, l, delta in events:
diff = y - prev_height
# additional area between two scanning lines
area = covered_width * diff
# if this part of the area exceeds more than half of the total area
if 2 * (curr_area + area) >= total_area:
return prev_height + (total_area - 2 * curr_area) / (
2 * covered_width
)
# update width: add width at the start event, subtract width at the end event
covered_width += delta * l
curr_area += area
prev_height = y
return 0.0
4.7.102 - 2026-01-12 10:11:59 +0300 MSK
Links
Code
class Solution:
def minTimeToVisitAllPoints(self, points: List[List[int]]) -> int:
pos_x, pos_y = points[0]
res = 0
for x, y in points[1:]:
diff_x, diff_y = abs(pos_x - x), abs(pos_y - y)
diff_min, diff_max = min(diff_x, diff_y), max(diff_x, diff_y)
res += diff_min + (diff_max - diff_min)
pos_x, pos_y = x, y
return res
4.7.103 - 2026-01-11 13:52:04 +0300 MSK
Links
Code
class Solution:
def maximalRectangle(self, matrix: List[List[str]]) -> int:
m, n = len(matrix), len(matrix[0])
dp = [[0] * (n + 1) for _ in range(m + 1)]
max_area = 0
for i in range(m):
for j in range(n):
if matrix[i][j] == "0":
continue
dp_i, dp_j = i + 1, j + 1
width = dp[dp_i][dp_j - 1] + 1
dp[dp_i][dp_j] = width
max_area = max(max_area, width)
for cur_dp_i in reversed(range(1, dp_i)):
height = dp_i - cur_dp_i + 1
width = min(width, dp[cur_dp_i][dp_j])
if width == 0:
break
max_area = max(max_area, height * width)
return max_area
4.7.104 - 2026-01-11 08:25:47 +0300 MSK
Links
Code
class Solution:
def shortestPalindrome(self, s: str) -> str:
length = len(s)
reversed_string = s[::-1] # Reverse the string
for i in range(length):
if s[: length - i] == reversed_string[i:]:
return reversed_string[:i] + s
return ""
4.7.105 - 2026-01-10 14:26:29 +0300 MSK
Links
Code
class Solution:
def shortestPalindrome(self, s: str) -> str:
reversed_string = s[::-1]
combined_string = "#".join((s, reversed_string))
prefix_table = self._kmp_table(combined_string)
palindrome_length = prefix_table[-1]
suffix = reversed_string[: len(s) - palindrome_length]
return suffix + s
def _kmp_table(self, s: str) -> list[int]:
prefix_table = [0] * len(s)
length = 0
for i in range(1, len(s)):
while length > 0 and s[i] != s[length]:
length = prefix_table[length - 1]
if s[i] == s[length]:
length += 1
prefix_table[i] = length
return prefix_table
4.7.106 - 2026-01-10 14:23:41 +0300 MSK
Links
Code
class Solution:
def shortestPalindrome(self, s: str) -> str:
length = len(s)
if length == 0:
return s
left = 0
for right in range(length - 1, -1, -1):
if s[right] == s[left]:
left += 1
if left == length:
return s
non_palindrome_suffix = s[left:]
reverse_suffix = non_palindrome_suffix[::-1]
return (
reverse_suffix
+ self.shortestPalindrome(s[:left])
+ non_palindrome_suffix
)
4.7.107 - 2026-01-10 14:04:15 +0300 MSK
Links
Code
class Solution:
def shortestPalindrome(self, s: str) -> str:
length = len(s)
if length < 2:
return s
left = 0
for right in reversed(range(length)):
if s[left] == s[right]:
left += 1
if left == length:
return s
non_palindrome_suffix = s[left:]
reverse_suffix = non_palindrome_suffix[::-1]
return (
reverse_suffix
+ self.shortestPalindrome(s[:left])
+ non_palindrome_suffix
)
4.7.108 - 2026-01-10 12:50:38 +0300 MSK
Links
Code
class Solution:
def minimumDeleteSum(self, s1: str, s2: str) -> int:
length1, length2 = len(s1), len(s2)
dp = [[-1] * (length2 + 1) for _ in range(length1 + 1)]
inf = float("inf")
def dfs(i: int, j: int) -> int:
if dp[i][j] != -1:
return dp[i][j]
elif i == length1:
res = sum(ord(char) for char in s2[j:])
elif j == length2:
res = sum(ord(char) for char in s1[i:])
else:
char1, char2 = ord(s1[i]), ord(s2[j])
res = min(char1 + dfs(i + 1, j), char2 + dfs(i, j + 1))
if char1 == char2:
res = min(res, dfs(i + 1, j + 1))
dp[i][j] = res
return res
return dfs(0, 0)
4.7.109 - 2026-01-10 12:34:56 +0300 MSK
Links
Code
class Solution:
def largestEven(self, s: str) -> str:
last = len(s) - 1
while last >= 0 and s[last] == "1":
last -= 1
return s[:last + 1]
4.7.110 - 2026-01-10 12:32:09 +0300 MSK
Links
Code
class Solution:
def reversePrefix(self, s: str, k: int) -> str:
return s[k - 1::-1] + s[k:]
4.7.111 - 2026-01-10 12:31:07 +0300 MSK
Links
Code
class Solution:
def reversePrefix(self, s: str, k: int) -> str:
return s[:k][::-1] + s[k:]
4.7.112 - 2026-01-10 12:28:57 +0300 MSK
Links
Code
SELECT
user_id,
COUNT(prompt) AS "prompt_count",
ROUND(AVG(tokens),2) AS "avg_tokens"
FROM
prompts
GROUP BY
user_id
HAVING
COUNT(prompt) > 2
AND MAX(tokens) > AVG(tokens)
ORDER BY
avg_tokens DESC,
user_id;
4.7.113 - 2026-01-09 15:34:38 +0300 MSK
Links
Code
def solve(i: int, j: int, dungeon: list[list[int]], dp: list[list[int]]) -> int:
m, n = len(dungeon), len(dungeon[0])
if i == m - 1 and j == n - 1:
return max(1, 1 - dungeon[i][j])
if i >= m or j >= n:
return float("inf")
if dp[i][j] != -1:
return dp[i][j]
right = solve(i, j + 1, dungeon, dp)
down = solve(i + 1, j, dungeon, dp)
min_health = min(right, down) - dungeon[i][j]
dp[i][j] = max(1, min_health)
return dp[i][j]
class Solution:
def calculateMinimumHP(self, dungeon):
m, n = len(dungeon), len(dungeon[0])
dp = [[-1] * n for _ in range(m)]
return solve(0, 0, dungeon, dp)
4.7.114 - 2026-01-09 13:31:31 +0300 MSK
Links
Code
import functools
class Solution:
def findMin(self, nums: List[int]) -> int:
length = len(nums)
if length < 3:
return min(nums)
inf = float("inf")
@functools.cache
def check(i: int) -> int:
if i == 0:
prev, nxt = length - 1, 1
elif i == length - 1:
prev, nxt = length - 2, 0
else:
prev, nxt = i - 1, i + 1
num_prev, num_cur, num_nxt = nums[prev], nums[i], nums[nxt]
if num_cur < num_prev:
return num_cur
if num_nxt < num_cur:
return num_nxt
return -1
@functools.cache
def dp(left: int, right: int) -> int:
if left < 0 or right == length or left > right:
return inf
mid = left + (right - left) // 2
num_left, num_mid, num_right = nums[left], nums[mid], nums[right]
for idx in (left, mid, right):
check_res = check(idx)
if check_res != -1:
return check_res
if num_left == num_mid == num_right:
return min(num_left, dp(left + 1, mid - 1), dp(mid + 1, right - 1))
if num_mid < num_left:
return dp(left + 1, mid - 1)
return dp(mid + 1, right - 1)
return dp(0, length - 1)
4.7.115 - 2026-01-09 11:15:58 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def subtreeWithAllDeepest(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
if root is None:
return None
neg_inf = float("-inf")
def dfs(node: TreeNode, depth: int) -> tuple[TreeNode, int]:
if node.left is None and node.right is None:
return node, depth
if node.left is None:
return dfs(node.right, depth + 1)
if node.right is None:
return dfs(node.left, depth + 1)
left_node, left_depth = dfs(node.left, depth + 1)
right_node, right_depth = dfs(node.right, depth + 1)
if left_depth == right_depth:
return node, left_depth
if left_depth > right_depth:
return left_node, left_depth
return right_node, right_depth
return dfs(root, 0)[0]
4.7.116 - 2026-01-08 22:11:32 +0300 MSK
Links
Code
class Solution:
def minCut(self, s: str) -> int:
n = len(s)
cuts = [i for i in range(n)]
for center in range(n):
for left, right in ((center, center), (center, center + 1)):
while left >= 0 and right < n and s[left] == s[right]:
if left == 0:
cuts[right] = 0
else:
cuts[right] = min(cuts[right], cuts[left - 1] + 1)
left -= 1
right += 1
return cuts[-1]
4.7.117 - 2026-01-08 19:05:53 +0300 MSK
Links
Code
class Solution:
def findLadders(self, beginWord: str, endWord: str, wordList: List[str]) -> int:
words, mp, ans = set(wordList), defaultdict(list), []
def bfs(words: set[str]) -> None:
letters = [chr(97 + x) for x in range(26)]
ws, q, next_lev = len(beginWord), deque([beginWord]), set()
while q:
size = len(q)
for _ in range(size):
w = q.popleft()
for i in range(ws):
pre, suf = w[:i], w[i+1:]
for l in letters:
nw = pre + l + suf
if nw in words:
mp[nw].append(w)
next_lev.add(nw)
q.extend(next_lev)
words -= next_lev
next_lev.clear()
bfs(words)
def dfs(w: str, arr):
if w == beginWord:
ans.append(list(arr))
return
for nw in mp[w]:
arr.appendleft(nw)
dfs(nw,arr)
arr.popleft()
if endWord in mp:
dfs(endWord, deque([endWord]))
return ans
4.7.118 - 2026-01-08 17:17:32 +0300 MSK
Links
Code
class Solution:
def numDistinct(self, s: str, t: str) -> int:
cache = {}
length1, length2 = len(s), len(t)
def dp(i: int, j: int) -> int:
if j == length2:
return 1
if i == length1:
return 0
key = (i, j)
if key in cache:
return cache[key]
res = 0
if s[i] == t[j]:
res += dp(i + 1, j+ 1)
res += dp(i + 1, j)
cache[key] = res
return res
return dp(0, 0)
4.7.119 - 2026-01-08 15:42:20 +0300 MSK
Links
Code
class Solution:
def maxDotProduct(self, nums1: List[int], nums2: List[int]) -> int:
cache = {}
def dp(i: int, j: int):
if i == len(nums1) or j == len(nums2):
return float("-inf")
if (i, j) in cache:
return cache[(i, j)]
take = nums1[i] * nums2[j]
res = max(take + dp(i+1, j+1), take, dp(i+1,j), dp(i,j+1))
cache[(i, j)] = res
return cache[(i, j)]
return dp(0,0)
4.7.120 - 2026-01-07 21:40:08 +0300 MSK
Links
Code
class Solution:
def isScramble(self, s1: str, s2: str) -> bool:
cache = {}
def check(s1: str, s2: str) -> bool:
key = (s1, s2)
if key in cache:
return cache[key]
if s1 == s2:
cache[key] = True
return True
res = False
for middle in range(1, len(s1)):
if (
check(s1[:middle], s2[:middle])
and check(s1[middle:], s2[middle:])
) or (
check(s1[:middle], s2[-middle:])
and check(s1[middle:], s2[:len(s1) - middle])
):
res = True
break
cache[key] = res
return res
return check(s1, s2)
4.7.121 - 2026-01-07 19:46:02 +0300 MSK
Links
Code
class Solution:
def largestRectangleArea(self, heights: List[int]) -> int:
stack = []
area = 0
length = len(heights)
for i in range(length):
while stack and heights[i] < heights[stack[-1]]:
bar = stack.pop()
if stack:
pse = stack[-1]
else:
pse = -1
nse = i
area = max(area, heights[bar] * (nse - pse - 1))
stack.append(i)
while stack:
bar = stack.pop()
if stack:
pse = stack[-1]
else:
pse = -1
nse = length
area = max(area, heights[bar] * (nse - pse - 1))
return area
4.7.122 - 2026-01-07 18:35:43 +0300 MSK
Links
Code
class Solution:
def orderlyQueue(self, s: str, k: int) -> str:
if k > 1:
return "".join(sorted(s))
min_string = s
for i in range(1, len(s)):
min_string = min(min_string, s[i:] + s[:i])
return min_string
4.7.123 - 2026-01-07 15:39:17 +0300 MSK
Links
Code
import itertools
class Solution:
def getPermutation(self, n: int, k: int) -> str:
for nums in itertools.permutations(range(1, n + 1), n):
if k == 1:
return "".join(map(str, nums))
k -= 1
raise Exception
4.7.124 - 2026-01-07 15:23:44 +0300 MSK
Links
Code
class Solution:
def solveNQueens(self, n: int) -> List[List[str]]:
res = []
state = [["."] * n for _ in range(n)]
def backtrack(row: int, col: int, left: int) -> None:
if left == 0:
res.append(tuple("".join(cur_row) for cur_row in state))
return
if row >= n or col >= n:
return
place = True
for i in range(row):
if state[i][col] == "Q":
place = False
break
if place:
cur_i, cur_j = row, col
while cur_i >= 0 and cur_j >= 0:
if state[cur_i][cur_j] == "Q":
place = False
break
cur_i -= 1
cur_j -= 1
if place:
cur_i, cur_j = row, col
while cur_i >= 0 and cur_j < n:
if state[cur_i][cur_j] == "Q":
place = False
break
cur_i -= 1
cur_j += 1
if place:
state[row][col] = "Q"
backtrack(row + 1, 0, left - 1)
state[row][col] = "."
if col + 1 == n:
nxt_row, nxt_col = row + 1, 0
else:
nxt_row, nxt_col = row, col + 1
backtrack(nxt_row, nxt_col, left)
backtrack(0, 0, n)
return res
4.7.125 - 2026-01-07 14:29:52 +0300 MSK
Links
Code
class Solution:
def longestValidParentheses(self, s: str) -> int:
stack = []
lengths = [0] * len(s)
max_length = 0
for i, char in enumerate(s):
stack.append((i, char))
while len(stack) > 1 and stack[-2][1] == "(" and stack[-1][1] == ")":
start, end = stack[-2][0], stack[-1][0]
length = end - start + 1
if start > 1:
length += lengths[start - 1]
lengths[end] = length
max_length = max(max_length, length)
stack.pop()
stack.pop()
return max_length
4.7.126 - 2026-01-07 13:23:43 +0300 MSK
Links
Code
class Solution:
def isMatch(self, s: str, p: str) -> bool:
length1, length2 = len(s), len(p)
def match(i: int, j: int) -> bool:
if i < length1:
char = s[i]
else:
char = None
if j < length2:
pat = p[j]
else:
pat = None
if char is None and pat is None:
res = True
elif pat is None:
res = False
elif char is None:
res = (length2 - j) % 2 == 0
if res:
for cur_j in range(j, length2, 2):
if p[cur_j] == "*" or p[cur_j + 1] != "*":
res = False
break
else:
if j + 1 < length2:
pat_nxt = p[j + 1]
else:
pat_nxt = None
valid = pat == "." or char == pat
if pat_nxt and pat_nxt == "*":
res = (valid and match(i + 1, j)) or match(i, j + 2)
else:
res = valid and match(i + 1, j + 1)
return res
return match(0, 0)
4.7.127 - 2026-01-07 13:23:17 +0300 MSK
Links
Code
class Solution:
def isMatch(self, s: str, p: str) -> bool:
length1, length2 = len(s), len(p)
cache = {}
def match(i: int, j: int) -> bool:
if (i, j) in cache:
return cache[(i, j)]
if i < length1:
char = s[i]
else:
char = None
if j < length2:
pat = p[j]
else:
pat = None
if char is None and pat is None:
res = True
elif pat is None:
res = False
elif char is None:
res = (length2 - j) % 2 == 0
if res:
for cur_j in range(j, length2, 2):
if p[cur_j] == "*" or p[cur_j + 1] != "*":
res = False
break
else:
if j + 1 < length2:
pat_nxt = p[j + 1]
else:
pat_nxt = None
valid = pat == "." or char == pat
if pat_nxt and pat_nxt == "*":
res = (valid and match(i + 1, j)) or match(i, j + 2)
else:
res = valid and match(i + 1, j + 1)
cache[(i, j)] = res
return res
return match(0, 0)
4.7.128 - 2026-01-07 12:50:50 +0300 MSK
Links
Code
class Solution:
def isMatch(self, s: str, p: str) -> bool:
length1, length2 = len(s), len(p)
cache = {}
def search(i: int, j: int) -> bool:
if (i, j) in cache:
return cache[(i, j)]
if i < length1:
char = s[i]
else:
char = None
if j < length2:
pat = p[j]
else:
pat = None
if char is None and pat is None:
res = True
elif char is None:
res = pat == "*" and search(i, j + 1)
elif pat is None:
res = False
elif pat == "?":
res = search(i + 1, j + 1)
elif pat == "*":
nxt = j + 1
while nxt < length2 and p[nxt] == "*":
nxt += 1
res = search(i, nxt) or search(i + 1, nxt) or search(i + 1, j)
else:
res = pat == char and search(i + 1, j + 1)
cache[(i, j)] = res
return res
return search(0, 0)
4.7.129 - 2026-01-07 11:11:18 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def maxProduct(self, root: Optional[TreeNode]) -> int:
if root is None:
return 0
sums = {}
def dfs_sum(node: Optional[TreeNode]) -> int:
if node is None:
return 0
node_id = id(node)
if node_id in sums:
return sums[node_id]
res = node.val + dfs_sum(node.left) + dfs_sum(node.right)
sums[node_id] = res
return res
dfs_sum(root)
root_sum = sums[id(root)]
def dfs(node: Optional[TreeNode]) -> int:
if node is None:
return 0
tree1 = sums[id(node)]
tree2 = root_sum - tree1
res = max(tree1 * tree2, dfs(node.left), dfs(node.right))
return res
return max(dfs(root.left), dfs(root.right)) % (10 ** 9 + 7)
4.7.130 - 2026-01-06 23:04:34 +0300 MSK
Links
Code
import re
PATTERN = r"^[-+]?(\d+|[.]\d+|\d+[.]\d*)([eE][-+]?\d+)?$"
class Solution:
def isNumber(self, s: str) -> bool:
return re.match(PATTERN, s) is not None
4.7.131 - 2026-01-06 22:19:43 +0300 MSK
Links
Code
class Encrypter:
def __init__(self, keys: List[str], values: List[str], dictionary: List[str]):
self.key_to_i = {}
self.keys = keys
self.values = values
self.value_to_i = collections.defaultdict(list)
for i, key in enumerate(keys):
self.key_to_i[key] = i
for i, value in enumerate(values):
self.value_to_i[value].append(i)
self.trie = {}
for word in dictionary:
trie = self.trie
for char in word:
if char not in trie:
trie[char] = {}
trie = trie[char]
trie[""] = True
def encrypt(self, word1: str) -> str:
res = []
for char in word1:
if char not in self.key_to_i:
return ""
res.append(self.values[self.key_to_i[char]])
return "".join(res)
def decrypt(self, word2: str) -> int:
def backtrack(i: int, trie: dict[str, dict]) -> int:
if i >= len(word2):
if trie.get(""):
return 1
return 0
res = 0
for idx in self.value_to_i[word2[i:i+ 2]]:
key = self.keys[idx]
if key in trie:
res += backtrack(i + 2, trie[key])
return res
return backtrack(0, self.trie)
# Your Encrypter object will be instantiated and called as such:
# obj = Encrypter(keys, values, dictionary)
# param_1 = obj.encrypt(word1)
# param_2 = obj.decrypt(word2)
4.7.132 - 2026-01-06 21:39:35 +0300 MSK
Links
Code
class MaxString:
__slots__ = ("s")
def __init__(self, s):
self.s = s
def __lt__(self, other):
return self.s > other.s
class SORTracker:
def __init__(self):
self.right = []
self.left = []
def add(self, name: str, score: int) -> None:
_, name, score = heapq.heappushpop(
self.left,
((score, MaxString(name)), name, score)
)
heapq.heappush(self.right, ((-score, name), name, score))
def get(self) -> str:
_, name, score = heapq.heappop(self.right)
heapq.heappush(self.left, ((score, MaxString(name)), name, score))
return name
4.7.133 - 2026-01-06 21:10:32 +0300 MSK
Links
Code
from sortedcontainers import SortedList
class SORTracker:
def __init__(self):
self.cnt = 0
self.data = SortedList()
def add(self, location: str, score: int) -> None:
self.data.add((-score, location))
def get(self) -> str:
_, location = self.data[self.cnt]
self.cnt+= 1
return location
4.7.134 - 2026-01-06 19:37:48 +0300 MSK
Links
Code
class WordFilter:
def __init__(self, words: List[str]):
self.prefix = {}
self.postfix = {}
for i, word in enumerate(words):
prefix = self.prefix
for char in word:
if char not in prefix:
prefix[char] = {}
prefix = prefix[char]
prefix[""] = i
postfix = self.postfix
for char in reversed(word):
if char not in postfix:
postfix[char] = {}
postfix = postfix[char]
if "" not in postfix:
postfix[""] = set()
postfix[""] = i
def f(self, pref: str, suff: str) -> int:
prefixes, postfixes = set(), set()
postfix, prefix = self.postfix, self.prefix
for char in pref:
if char not in prefix:
return -1
prefix = prefix[char]
for char in reversed(suff):
if char not in postfix:
return -1
postfix = postfix[char]
postfix_queue = [postfix]
prefix_queue = [prefix]
while postfix_queue:
for key, value in postfix_queue.pop().items():
if key == "":
postfixes.add(value)
else:
postfix_queue.append(value)
while prefix_queue:
for key, value in prefix_queue.pop().items():
if key == "":
prefixes.add(value)
else:
prefix_queue.append(value)
res = prefixes & postfixes
if not res:
return -1
return max(res)
# Your WordFilter object will be instantiated and called as such:
# obj = WordFilter(words)
# param_1 = obj.f(pref,suff)
4.7.135 - 2026-01-06 12:16:09 +0300 MSK
Links
Code
class FreqStack:
def __init__(self):
self.levels = [None]
self.last_level = 0
self.freqs = collections.defaultdict(int)
def push(self, val: int) -> None:
freq = self.freqs[val] + 1
if freq >= len(self.levels):
self.levels.append([])
self.levels[freq].append(val)
self.freqs[val] = freq
def pop(self) -> int:
for i in reversed(range(len(self.levels))):
level = self.levels[i]
if level:
val = level.pop()
self.freqs[val] -= 1
return val
raise Exception
# Your FreqStack object will be instantiated and called as such:
# obj = FreqStack()
# obj.push(val)
# param_2 = obj.pop()
4.7.136 - 2026-01-06 10:05:37 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def maxLevelSum(self, root: Optional[TreeNode]) -> int:
cur, nxt = [root], []
level = 1
min_level, max_sum = 1, root.val
while cur or nxt:
cur_sum = 0
while cur:
node = cur.pop()
cur_sum += node.val
if node.left:
nxt.append(node.left)
if node.right:
nxt.append(node.right)
if cur_sum > max_sum:
min_level, max_sum = level, cur_sum
cur, nxt = nxt, cur
level += 1
return min_level
4.7.137 - 2026-01-05 18:58:31 +0300 MSK
Links
Code
class TreeAncestor:
def __init__(self, n: int, parent: List[int]):
m = 1 + int(log2(n)) #at most 16 for this problem
self.dp = [[-1] * m for _ in range(n)] #ith node's 2^j parent
for j in range(m):
for i in range(n):
if j == 0:
self.dp[i][0] = parent[i]
elif self.dp[i][j-1] != -1:
self.dp[i][j] = self.dp[self.dp[i][j-1]][j-1]
def getKthAncestor(self, node: int, k: int) -> int:
while k > 0 and node != -1:
i = int(log2(k))
node = self.dp[node][i]
k -= (1 << i)
return node
4.7.138 - 2026-01-05 14:24:49 +0300 MSK
Links
Code
class Node:
def __init__(
self,
char: str,
prev: Optional["Node"],
nxt: Optional["Node"]
) -> None:
self.char = char
self.prev = prev
self.nxt = nxt
class TextEditor:
def __init__(self):
self.length = 0
self.root = Node("", None, None)
self.cursor = self.root
def addText(self, text: str) -> None:
node = self.cursor
self.length += len(text)
for char in text:
cur = Node(char, node, node.nxt)
nxt = node.nxt
node.nxt = cur
if nxt:
nxt.prev = cur
node = cur
self.cursor = cur
def deleteText(self, k: int) -> int:
res = 0
while self.cursor is not self.root and k > 0:
res += 1
k -= 1
if self.cursor.nxt:
self.cursor.nxt.prev = self.cursor.prev
self.cursor.prev.nxt = self.cursor.nxt
self.cursor = self.cursor.prev
return res
def last_ten(self) -> str:
res = []
node = self.cursor
while node is not self.root and len(res) < 10:
res.append(node.char)
node = node.prev
res.reverse()
return "".join(res)
def cursorLeft(self, k: int) -> str:
while self.cursor is not self.root and k > 0:
k -= 1
self.cursor = self.cursor.prev
res = self.last_ten()
return res
def cursorRight(self, k: int) -> str:
while self.cursor.nxt and k > 0:
k -= 1
self.cursor = self.cursor.nxt
res = self.last_ten()
return res
# Your TextEditor object will be instantiated and called as such:
# obj = TextEditor()
# obj.addText(text)
# param_2 = obj.deleteText(k)
# param_3 = obj.cursorLeft(k)
# param_4 = obj.cursorRight(k)
4.7.139 - 2026-01-05 12:30:08 +0300 MSK
Links
Code
class Solution:
def maxMatrixSum(self, matrix: List[List[int]]) -> int:
heap = []
min_pos = float("inf")
res = 0
for row in matrix:
for col in row:
if col < 0:
heapq.heappush(heap, col)
else:
res += col
min_pos = min(min_pos, col)
while len(heap) >= 2:
res += -(heapq.heappop(heap) + heapq.heappop(heap))
if not heap:
return res
last = heap.pop()
if min_pos == float("inf"):
return res + last
return max(res + last, (res - min_pos) - (min_pos + last))
4.7.140 - 2026-01-04 21:18:13 +0300 MSK
Links
Code
class Solution:
def sumFourDivisors(self, nums: list[int]) -> int:
res = 0
for n in nums:
val = self.sumOne(n)
if val != -1:
res += val
return res
def sumOne(self, n: int) -> int:
p = round(n ** (1/3))
if p ** 3 == n and self.isPrime(p):
return 1 + p + p*p + p*p*p
for i in range(2, int(n ** 0.5) + 1):
if n % i == 0:
a, b = i, n // i
if a != b and self.isPrime(a) and self.isPrime(b):
return 1 + a + b + n
return -1
return -1
def isPrime(self, x: int) -> bool:
if x < 2:
return False
for i in range(2, int(x ** 0.5) + 1):
if x % i == 0:
return False
return True
4.7.141 - 2026-01-03 13:57:12 +0300 MSK
Links
Code
class Solution:
def numOfWays(self, n: int) -> int:
MOD = 10**9 + 7
A = B = 6
for _ in range(2, n + 1):
A, B = (2*A + 2*B) % MOD, (2*A + 3*B) % MOD
return (A + B) % MOD
4.7.142 - 2026-01-02 16:54:09 +0300 MSK
Links
Code
class StreamChecker:
def __init__(self, words: List[str]):
self.trie = {}
self.min_length = float("inf")
for word in words:
node = self.trie
self.min_length = min(self.min_length, len(word))
for char in reversed(word):
if char not in node:
node[char] = {}
node = node[char]
node["is_word"] = True
self.letters = []
def query(self, letter: str) -> bool:
self.letters.append(letter)
if len(self.letters) < self.min_length:
return False
node = self.trie
for letter in reversed(self.letters):
if letter not in node:
return False
if node[letter].get("is_word"):
return True
node = node[letter]
return False
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)
4.7.143 - 2026-01-02 16:49:02 +0300 MSK
Links
Code
class StreamChecker:
def __init__(self, words: List[str]):
self.trie = {}
self.lengths = set()
for word in words:
node = self.trie
self.lengths.add(len(word))
for char in word:
if char not in node:
node[char] = {}
node = node[char]
node["is_word"] = True
self.letters = []
def query(self, letter: str) -> bool:
self.letters.append(letter)
for length in self.lengths:
if length > len(self.letters):
continue
node = self.trie
was_break = False
for letter in self.letters[-length:]:
if letter not in node:
was_break = True
break
node = node[letter]
if was_break:
continue
if node.get("is_word", False):
return True
return False
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)
4.7.144 - 2026-01-02 10:21:34 +0300 MSK
Links
Code
class Solution:
def repeatedNTimes(self, nums: List[int]) -> int:
enc = set()
for num in nums:
if num in enc:
return num
enc.add(num)
raise Exception
4.7.145 - 2026-01-01 13:06:44 +0300 MSK
Links
Code
class RLEIterator:
def __init__(self, encoding: List[int]):
self.i, self.enc, self.length = 0, encoding, len(encoding)
def next(self, n: int) -> int:
while self.i < self.length and n > 0:
count = self.enc[self.i]
if count == 0:
self.i += 2
elif count >= n:
self.enc[self.i] -= n
return self.enc[self.i + 1]
else:
n -= count
self.i += 2
return -1
# Your RLEIterator object will be instantiated and called as such:
# obj = RLEIterator(encoding)
# param_1 = obj.next(n)
4.7.146 - 2026-01-01 13:05:15 +0300 MSK
Links
Code
class RLEIterator:
def __init__(self, encoding: List[int]):
self.enc = encoding
self.enc.reverse()
def next(self, n: int) -> int:
while self.enc and n > 0:
count = self.enc[-1]
if count == 0:
self.enc.pop()
self.enc.pop()
elif count >= n:
self.enc[-1] -= n
return self.enc[-2]
else:
n -= count
self.enc.pop()
self.enc.pop()
return -1
# Your RLEIterator object will be instantiated and called as such:
# obj = RLEIterator(encoding)
# param_1 = obj.next(n)
4.7.147 - 2026-01-01 12:27:10 +0300 MSK
Links
Code
class Solution:
def plusOne(self, digits: List[int]) -> List[int]:
for i in reversed(range(len(digits))):
dig = digits[i] + 1
if dig == 10:
digits[i] = 0
if i == 0:
digits.insert(0, 1)
else:
digits[i] = dig
break
return digits
4.7.148 - 2025-12-31 18:07:08 +0300 MSK
Links
Code
class Solution:
def latestDayToCross(self, row: int, col: int, cells: list[list[int]]) -> int:
dsu = DSU(row * col + 2)
grid = [[0] * col for _ in range(row)]
dirs = [(0, 1), (0, -1), (1, 0), (-1, 0), (1, 1), (1, -1), (-1, 1), (-1, -1)]
for i in range(row * col):
r = cells[i][0] - 1
c = cells[i][1] - 1
grid[r][c] = 1
id1 = r * col + c + 1
for dr, dc in dirs:
nr, nc = r + dr, c + dc
if 0 <= nr < row and 0 <= nc < col and grid[nr][nc] == 1:
id2 = nr * col + nc + 1
dsu.union(id1, id2)
if c == 0:
dsu.union(0, id1)
if c == col - 1:
dsu.union(row * col + 1, id1)
if dsu.find(0) == dsu.find(row * col + 1):
return i
return -1
class DSU:
def __init__(self, n):
self.root = list(range(n))
self.size = [1] * n
def find(self, x):
if self.root[x] != x:
self.root[x] = self.find(self.root[x])
return self.root[x]
def union(self, x, y):
rx = self.find(x)
ry = self.find(y)
if rx == ry:
return
if self.size[rx] > self.size[ry]:
rx, ry = ry, rx
self.root[rx] = ry
self.size[ry] += self.size[rx]
4.7.149 - 2025-12-30 21:07:43 +0300 MSK
Links
Code
class Solution:
def numMagicSquaresInside(self, grid: List[List[int]]) -> int:
ans = 0
m = len(grid)
n = len(grid[0])
for row in range(m - 2):
for col in range(n - 2):
if self._isMagicSquare(grid, row, col):
ans += 1
return ans
def _isMagicSquare(self, grid, row, col):
# The sequences are each repeated twice to account for
# the different possible starting points of the sequence
# in the magic square
sequence = "2943816729438167"
sequenceReversed = "7618349276183492"
border = []
# Flattened indices for bordering elements of 3x3 grid
borderIndices = [0, 1, 2, 5, 8, 7, 6, 3]
for i in borderIndices:
num = grid[row + i // 3][col + (i % 3)]
border.append(str(num))
borderConverted = "".join(border)
# Make sure the sequence starts at one of the corners
return (
grid[row][col] % 2 == 0
and (
sequence.find(borderConverted) != -1
or sequenceReversed.find(borderConverted) != -1
)
and grid[row + 1][col + 1] == 5
)
4.7.150 - 2025-12-29 19:39:26 +0300 MSK
Links
Code
from functools import cache
class Solution:
def pyramidTransition(self, bottom: str, allowed: List[str]) -> bool:
# build up potential values for next rows based on allowed values
tops = defaultdict(list)
for key in allowed:
tops[key[:2]].append(key[2])
def gen_next_rows(full_items, all_valid=set(), i=0, cur=''):
# handle when a base pair does not have a top option in allowed
if any([item == [] for item in full_items]):
return []
# generated a full new line, add to set of valid options
if i == len(full_items):
all_valid.add(cur)
return
# full line is not complete, for each top option of current base pair,
# use it and look at the options for the next base pair.
for item in full_items[i]:
gen_next_rows(full_items, all_valid, i + 1, cur + item)
# all row options generated, return the options
return all_valid
seen = set()
def find_next_row(last):
n = len(last)
# made it to the top with a valid top option for the row of length 2
if n == 1:
return True
# Generate all potential options for the next row and try them.
# For example 2: the list comprehension used in gen_next_rows would be
# [['B', 'C'], ['B', 'C'], ['B', 'C']] for the next row choices after bottom
options = gen_next_rows([tops[last[i:i + 2]] for i in range(n - 1)], set())
# cache is useful here because the same sequence may appear more than once
# as the pyramid builds up.
for option in options:
if option in seen:
continue
if find_next_row(option):
return True
seen.add(option)
return False
return find_next_row(bottom)
4.7.151 - 2025-12-28 16:38:30 +0300 MSK
Links
Code
class Solution:
def countNegatives(self, grid: List[List[int]]) -> int:
count = 0
for row in reversed(grid):
for col in reversed(row):
if col < 0:
count += 1
else:
break
return count
4.7.152 - 2025-12-27 17:07:34 +0300 MSK
Links
Code
class Solution:
def mostBooked(self, n: int, meetings: List[List[int]]) -> int:
unused_rooms, used_rooms = list(range(n)), []
heapify(unused_rooms)
meeting_count = [0] * n
for start, end in sorted(meetings):
while used_rooms and used_rooms[0][0] <= start:
_, room = heappop(used_rooms)
heappush(unused_rooms, room)
if unused_rooms:
room = heappop(unused_rooms)
heappush(used_rooms, [end, room])
else:
room_availability_time, room = heappop(used_rooms)
heappush(
used_rooms,
[room_availability_time + end - start, room]
)
meeting_count[room] += 1
return meeting_count.index(max(meeting_count))
4.7.153 - 2025-12-27 16:57:55 +0300 MSK
Links
Code
class Node:
def __init__(self, name: str, parent: Optional["Node"] = None) -> None:
self.name: str = name
self.parent: Optional["Node"] = parent
self.children: list[Node] = []
self.dead: bool = False
def __iter__(self) -> Generator["Node", None, None]:
if not self.dead:
yield self
for child in self.children:
yield from child
class ThroneInheritance:
def __init__(self, kingName: str):
self._root: Node = Node(kingName)
self._nodes: dict[str, Node] = {
kingName: self._root
}
def birth(self, parentName: str, childName: str) -> None:
parent = self._nodes[parentName]
child = Node(childName, parent)
parent.children.append(child)
self._nodes[childName] = child
def death(self, name: str) -> None:
node = self._nodes.pop(name)
node.dead = True
def getInheritanceOrder(self) -> List[str]:
return list(node.name for node in self._root)
# Your ThroneInheritance object will be instantiated and called as such:
# obj = ThroneInheritance(kingName)
# obj.birth(parentName,childName)
# obj.death(name)
# param_3 = obj.getInheritanceOrder()
4.7.154 - 2025-12-27 16:45:10 +0300 MSK
Links
Code
class LUPrefix:
def __init__(self, n: int):
self._start = {}
self._end = {}
def upload(self, video: int) -> None:
if video - 1 not in self._end and video + 1 not in self._start:
self._start[video] = video
self._end[video] = video
elif video - 1 in self._end and video + 1 in self._start:
end = self._start.pop(video + 1)
start = self._end.pop(video - 1)
self._start[start] = end
self._end[end] = start
elif video -1 in self._end:
start = self._end.pop(video - 1)
self._start[start] = video
self._end[video] = start
elif video + 1 in self._start:
end = self._start.pop(video + 1)
self._start[video] = end
self._end[end] = video
def longest(self) -> int:
return self._start.get(1, 0)
# Your LUPrefix object will be instantiated and called as such:
# obj = LUPrefix(n)
# obj.upload(video)
# param_2 = obj.longest()
4.7.155 - 2025-12-26 21:12:54 +0300 MSK
Links
Code
class CombinationIterator:
def __init__(self, characters: str, combinationLength: int):
self._length: int = combinationLength
self._chars: str = characters
self._cur: list[str] = []
self._gen = self._generator(0)
self._nxt: Optional[str] = next(self._gen, None)
def _generator(self, i: int) -> Generator[str, None, None]:
if len(self._cur) == self._length:
yield "".join(self._cur)
return
if i >= len(self._chars):
return
char = self._chars[i]
self._cur.append(char)
yield from self._generator(i + 1)
self._cur.pop()
yield from self._generator(i + 1)
def next(self) -> str:
nxt = self._nxt
self._nxt = next(self._gen, None)
return nxt
def hasNext(self) -> bool:
return self._nxt is not None
# Your CombinationIterator object will be instantiated and called as such:
# obj = CombinationIterator(characters, combinationLength)
# param_1 = obj.next()
# param_2 = obj.hasNext()
4.7.156 - 2025-12-26 14:01:28 +0300 MSK
Links
Code
class Solution:
def bestClosingTime(self, customers: str) -> int:
j, min_pen = len(customers), customers.count("N")
cur_pen = min_pen
for i in reversed(range(len(customers))):
if customers[i] == "Y":
cur_pen += 1
else:
cur_pen -= 1
if cur_pen <= min_pen:
j, min_pen = i, cur_pen
return j
4.7.157 - 2025-12-25 20:08:37 +0300 MSK
Links
Code
class Solution:
def maximumHappinessSum(self, happiness: List[int], k: int) -> int:
happiness.sort()
res = 0
for i in range(k):
res += max(0, happiness.pop() - i)
return res
4.7.158 - 2025-12-25 20:05:52 +0300 MSK
Links
Code
class Solution:
def maximumHappinessSum(self, happiness: List[int], k: int) -> int:
happiness.sort(reverse=True)
happiness = happiness[:k]
res = 0
for i in range(len(happiness)):
res += max(0, happiness[i] - i)
return res
4.7.159 - 2025-12-24 15:28:01 +0300 MSK
Links
Code
class Solution:
def minimumBoxes(self, apple: List[int], capacity: List[int]) -> int:
count = sum(apple)
capacity.sort()
res = 0
while count > 0:
res += 1
count -= capacity.pop()
return res
4.7.160 - 2025-12-24 14:24:51 +0300 MSK
Links
Code
class Solution:
def rob(self, nums: List[int]) -> int:
n = len(nums)
if n == 1:
return nums[0]
def dp(i, j, memo: dict):
if i == j:
return 0
if i == j-1:
return nums[j-1]
if (i, j) not in memo:
rob = nums[i] + dp(i+2, j, memo)
skip = dp(i+1, j, memo)
memo[(i, j)] = max(rob, skip)
return memo[(i, j)]
return max(dp(0, n-1, {}), dp(1, n, {}))
4.7.161 - 2025-12-24 13:58:01 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:
res, cur = [], []
def dfs(node: Optional[TreeNode], cur_sum: int) -> None:
if node is None:
return
cur_sum += node.val
cur.append(node.val)
if node.right or node.left:
dfs(node.left, cur_sum)
dfs(node.right, cur_sum)
elif cur_sum == targetSum:
res.append(cur.copy())
cur.pop()
dfs(root, 0)
return res
4.7.162 - 2025-12-24 13:51:10 +0300 MSK
Links
Code
class Solution:
def recoverTree(self, root: Optional[TreeNode]) -> None:
self.first = self.second = self.prev = None
def inorder(node):
if not node:
return
inorder(node.left)
if self.prev and self.prev.val > node.val:
if not self.first:
self.first = self.prev
self.second = node
self.prev = node
inorder(node.right)
inorder(root)
# Swap the values
self.first.val, self.second.val = self.second.val, self.first.val
4.7.163 - 2025-12-24 13:44:07 +0300 MSK
Links
Code
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
heap = []
freqs = defaultdict(int)
for num in nums:
freqs[num] += 1
freq = freqs[num]
heapq.heappush(heap, (-freq, num))
res = set()
while k > 0:
_, num = heapq.heappop(heap)
if num not in res:
k -= 1
res.add(num)
return list(res)
4.7.164 - 2025-12-24 12:18:23 +0300 MSK
Links
Code
class Solution:
def hIndex(self, citations: List[int]) -> int:
left, right = 0, len(citations) - 1
h = 0
while left <= right:
mid = left + (right - left) // 2
count = len(citations) - mid
val = citations[mid]
h = max(h, min(count, val))
if count >= val:
left = mid + 1
else:
right = mid - 1
return h
4.7.165 - 2025-12-23 19:29:34 +0300 MSK
Links
Code
class Solution:
def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
r = 0
c = len(matrix[0])-1
while r < len(matrix) and c >= 0:
if matrix[r][c] == target:
return True
elif matrix[r][c] > target:
c -= 1
else:
r += 1
return False
4.7.166 - 2025-12-23 18:39:29 +0300 MSK
Links
Code
class Solution:
def maxTwoEvents(self, events):
times = []
for e in events:
# 1 denotes start time.
times.append([e[0], 1, e[2]])
# 0 denotes end time.
times.append([e[1] + 1, 0, e[2]])
ans, max_value = 0, 0
times.sort()
for time_value in times:
# If current time is a start time, find maximum sum of maximum end
# time till now.
if time_value[1]:
ans = max(ans, time_value[2] + max_value)
else:
max_value = max(max_value, time_value[2])
return ans
4.7.167 - 2025-12-22 19:27:46 +0300 MSK
Links
Code
class Solution(object):
def minDeletionSize(self, A):
W = len(A[0])
dp = [1] * W
for i in range(W-2, -1, -1):
for j in range(i+1, W):
if all(row[i] <= row[j] for row in A):
dp[i] = max(dp[i], 1 + dp[j])
return W - max(dp)
4.7.168 - 2025-12-22 16:40:19 +0300 MSK
Links
Code
class Solution:
def minCost(self, s: str, cost: List[int]) -> int:
costs = [0] * 26
for i in range(len(s)):
char, cur_cost = s[i], cost[i]
char_val = ord(char) - ord("a")
for j in range(26):
if j != char_val:
costs[j] += cur_cost
res = float("inf")
for cost in costs:
res = min(res, cost)
return res
4.7.169 - 2025-12-22 16:34:47 +0300 MSK
Links
Code
class Solution:
def mirrorDistance(self, n: int) -> int:
dig = []
orig = n
while n > 0:
dig.append(n % 10)
n //= 10
res = 0
cur = 0
while dig:
res += dig.pop() * (10 ** cur)
cur += 1
return abs(orig - res)
4.7.170 - 2025-12-21 20:30:45 +0300 MSK
Links
Code
class Solution(object):
def minDeletionSize(self, A):
cuts = [False] * (len(A) - 1)
ans = 0
for col in zip(*A):
if all(cuts[i] or col[i] <= col[i+1] for i in range(len(col) - 1)):
for i in range(len(col) - 1):
if col[i] < col[i+1]:
cuts[i] = True
else:
ans += 1
return ans
4.7.171 - 2025-12-20 19:15:02 +0300 MSK
Links
Code
class Solution:
def minDeletionSize(self, strs: List[str]) -> int:
res = 0
for col in range(len(strs[0])):
prev = 0
for row in range(len(strs)):
char = ord(strs[row][col])
if char >= prev:
prev = char
else:
res += 1
break
return res
4.7.172 - 2025-12-20 19:14:25 +0300 MSK
Links
Code
package main
import (
"sort"
)
func find(groups []int, index int) int {
for index != groups[index] {
index = groups[index]
}
return index
}
func findAllPeople(n int, meetings [][]int, firstPerson int) []int {
groups := make([]int, 100000)
var result []int
var temp []int
for i := 0; i < n; i++ {
groups[i] = i
}
groups[firstPerson] = 0
sort.Slice(meetings, func(i, j int) bool {
return meetings[i][2] < meetings[j][2]
})
i := 0
for i < len(meetings) {
currentTime := meetings[i][2]
temp = temp[:0]
for i < len(meetings) && meetings[i][2] == currentTime {
g1 := find(groups, meetings[i][0])
g2 := find(groups, meetings[i][1])
groups[max(g1, g2)] = min(g1, g2)
temp = append(temp, meetings[i][0], meetings[i][1])
i++
}
for _, j := range temp {
if find(groups, j) != 0 {
groups[j] = j
}
}
}
for j := 0; j < n; j++ {
if find(groups, j) == 0 {
result = append(result, j)
}
}
return result
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
4.7.173 - 2025-12-18 21:06:02 +0300 MSK
Links
Code
class Solution:
def maxProfit(self, prices: List[int], strategy: List[int], k: int) -> int:
native_profit = 0
native_segment = 0
changed_segment = 0
max_changed_segment = 0
for i in range(len(prices)):
price = prices[i]
native_profit += price * strategy[i]
native_segment += price * strategy[i]
if i + 1 <= k // 2:
pass
elif i + 1 < k :
changed_segment += price
elif i + 1 == k:
changed_segment += price
max_changed_segment = max(max_changed_segment, changed_segment - native_segment)
else:
changed_segment += price - prices[i - (k // 2)]
native_segment -= prices[i - k] * strategy[i - k]
max_changed_segment = max(max_changed_segment, changed_segment - native_segment)
return max(native_profit, native_profit + max_changed_segment)
4.7.174 - 2025-12-17 08:08:52 +0300 MSK
Links
Code
class Solution:
def maximumProfit(self, prices: List[int], k: int) -> int:
n = len(prices)
dp = [[0] * 3 for _ in range(k + 1)]
# initialize the state on day 0
for j in range(1, k + 1):
dp[j][1] = -prices[0]
dp[j][2] = prices[0]
for i in range(1, n):
for j in range(k, 0, -1):
dp[j][0] = max(
dp[j][0], max(dp[j][1] + prices[i], dp[j][2] - prices[i])
)
dp[j][1] = max(dp[j][1], dp[j - 1][0] - prices[i])
dp[j][2] = max(dp[j][2], dp[j - 1][0] + prices[i])
return dp[k][0]
4.7.175 - 2025-12-16 20:00:23 +0300 MSK
Links
Code
class Solution:
def absDifference(self, nums: List[int], k: int) -> int:
nums.sort()
return abs(sum(nums[:k]) - sum(nums[-k:]))
4.7.176 - 2025-12-16 19:58:35 +0300 MSK
Links
Code
class Solution:
def sortByReflection(self, nums: List[int]) -> List[int]:
reverse = lambda num: int(bin(num)[-1:1:-1], 2) # <--1)
nums.sort(key = lambda x: (reverse(x), x)) # <--2)
return nums
4.7.177 - 2025-12-16 19:57:10 +0300 MSK
Links
Code
class Solution:
def sumAndMultiply(self, n: int) -> int:
cur = 0
dig_sum, num = 0, 0
while n > 0:
dig = n % 10
n //= 10
if dig != 0:
dig_sum += dig
num += dig * (10 ** cur)
cur += 1
return num * dig_sum
4.7.178 - 2025-12-16 19:53:04 +0300 MSK
Links
Code
class Solution:
def minimumFlips(self, n: int) -> int:
bits = []
while n > 0:
bits.append(n % 2)
n //= 2
print(bits)
res = 0
for i in range(len(bits) // 2):
if bits[i] != bits[-i-1]:
res += 2
return res
4.7.179 - 2025-12-16 19:48:24 +0300 MSK
Links
Code
class Solution:
def maximizeExpressionOfThree(self, nums: List[int]) -> int:
nums.sort()
return nums.pop() + nums.pop() - nums[0]
4.7.180 - 2025-12-16 19:46:51 +0300 MSK
Links
Code
import collections
class Solution:
def minimumDistance(self, nums: list[int]) -> int:
idx1 = {}
idx2 = {}
res = float("inf")
for i, num in enumerate(nums):
if num in idx2:
dist = abs(idx1[num] - idx2[num]) + abs(idx2[num] - i) + abs(i - idx1[num])
res = min(res, dist)
idx1[num] = idx2[num]
idx2[num] = i
elif num in idx1:
idx2[num] = i
else:
idx1[num] = i
if res == float("inf"):
return -1
return res
4.7.181 - 2025-12-16 19:33:50 +0300 MSK
Links
Code
class Solution:
def minMoves(self, nums: List[int]) -> int:
target = max(nums)
res = 0
for num in nums:
res += target - num
return res
4.7.182 - 2025-12-16 19:32:04 +0300 MSK
Links
Code
class Solution:
def findMissingElements(self, nums: List[int]) -> List[int]:
nums.sort()
res = []
for i in range(1, len(nums)):
cur, prev = nums[i], nums[i - 1]
res.extend(range(prev + 1, cur))
return res
4.7.183 - 2025-12-16 19:29:16 +0300 MSK
Links
Code
class Solution:
def removeZeros(self, n: int) -> int:
cur = 0
res = 0
while n > 0:
dig = n % 10
if dig != 0:
res += dig * (10 ** cur)
cur += 1
n //= 10
return res
4.7.184 - 2025-12-16 19:26:34 +0300 MSK
Links
Code
class Solution:
def missingMultiple(self, nums: List[int], k: int) -> int:
enc = set(nums)
cur = k
while True:
if cur in enc:
cur += k
else:
return cur
4.7.185 - 2025-12-16 19:23:42 +0300 MSK
Links
Code
class Solution:
def sumDivisibleByK(self, nums: List[int], k: int) -> int:
freq = [0] * 101
for num in nums:
freq[num] += 1
res = 0
for num, freq in enumerate(freq):
if freq != 0 and freq % k == 0:
res += num * freq
return res
4.7.186 - 2025-12-16 19:02:03 +0300 MSK
Links
Code
class Solution:
def maxProfit(
self,
n: int,
present: List[int],
future: List[int],
hierarchy: List[List[int]],
budget: int,
) -> int:
g = [[] for _ in range(n)]
for e in hierarchy:
g[e[0] - 1].append(e[1] - 1)
def dfs(u: int):
cost = present[u]
dCost = present[u] // 2
# dp[u][state][budget]
# state = 0: Do not purchase parent node, state = 1: Must purchase parent node
dp0 = [0] * (budget + 1)
dp1 = [0] * (budget + 1)
# subProfit[state][budget]
# state = 0: discount not available, state = 1: discount available
subProfit0 = [0] * (budget + 1)
subProfit1 = [0] * (budget + 1)
uSize = cost
for v in g[u]:
child_dp0, child_dp1, vSize = dfs(v)
uSize += vSize
for i in range(budget, -1, -1):
for sub in range(min(vSize, i) + 1):
if i - sub >= 0:
subProfit0[i] = max(
subProfit0[i],
subProfit0[i - sub] + child_dp0[sub],
)
subProfit1[i] = max(
subProfit1[i],
subProfit1[i - sub] + child_dp1[sub],
)
for i in range(budget + 1):
dp0[i] = subProfit0[i]
dp1[i] = subProfit0[i]
if i >= dCost:
dp1[i] = max(
subProfit0[i], subProfit1[i - dCost] + future[u] - dCost
)
if i >= cost:
dp0[i] = max(
subProfit0[i], subProfit1[i - cost] + future[u] - cost
)
return dp0, dp1, uSize
return dfs(0)[0][budget]
4.7.187 - 2025-12-15 21:33:29 +0300 MSK
Links
Code
class Solution:
def getDescentPeriods(self, prices: List[int]) -> int:
n = len(prices)
res = 1 # total number of smooth descending periods, initial value is dp[0]
prev = 1 # total number of smooth descending periods ending with the previous element, initial value is dp[0]
# traverse the array starting from 1, and update prev and the total res according to the recurrence relation
for i in range(1, n):
if prices[i] == prices[i - 1] - 1:
prev += 1
else:
prev = 1
res += prev
return res
4.7.188 - 2025-12-14 20:42:06 +0300 MSK
Links
Code
class Solution {
public:
// Store 1000000007 in a variable for convenience
const int MOD = 1e9 + 7;
// Count the number of ways to divide from "index" to the last index
// with "seats" number of "S" in the current section
int count(int index, int seats, string& corridor, int cache[][3]) {
// If we have reached the end of the corridor, then
// the current section is valid only if "seats" is 2
if (index == corridor.length()) {
return seats == 2 ? 1 : 0;
}
// If we have already computed the result of this sub-problem,
// then return the cached result
if (cache[index][seats] != -1) {
return cache[index][seats];
}
// Result of the sub-problem
int result = 0;
// If the current section has exactly 2 "S"
if (seats == 2) {
// If the current element is "S", then we have to close the
// section and start a new section from this index. Next index
// will have one "S" in the current section
if (corridor[index] == 'S') {
result = count(index + 1, 1, corridor, cache);
} else {
// If the current element is "P", then we have two options
// 1. Close the section and start a new section from this index
// 2. Keep growing the section
result = (count(index + 1, 0, corridor, cache) + count(index + 1, 2, corridor, cache)) % MOD;
}
} else {
// Keep growing the section. Increment "seats" if present
// element is "S"
if (corridor[index] == 'S') {
result = count(index + 1, seats + 1, corridor, cache);
} else {
result = count(index + 1, seats, corridor, cache);
}
}
// Memoize the result, and return it
cache[index][seats] = result;
return cache[index][seats];
}
int numberOfWays(string corridor) {
// Cache the result of each sub-problem
int cache[corridor.length()][3];
memset(cache, -1, sizeof(cache));
// Call the count function
return count(0, 0, corridor, cache);
}
};
4.7.189 - 2025-12-13 20:21:05 +0300 MSK
Links
Code
class Solution:
def validateCoupons(self, code: List[str], businessLine: List[str], isActive: List[bool]) -> List[str]:
res, n = [], len(code)
b_order = {"electronics": 0, "grocery": 1, "pharmacy": 2, "restaurant": 3}
for i in range(n):
if (
isActive[i]
and code[i]
and re.match("^[a-zA-Z0-9_]+$", code[i])
and businessLine[i] in (
"electronics", "grocery", "pharmacy", "restaurant"
)
):
res.append(i)
def sort(i: int) -> tuple[str, str]:
return (b_order[businessLine[i]], code[i])
res.sort(key=sort)
for i in range(len(res)):
res[i] = code[res[i]]
return res
4.7.190 - 2025-12-13 20:20:09 +0300 MSK
Links
Code
class Solution:
def countMentions(
self, numberOfUsers: int, events: List[List[str]]
) -> List[int]:
events.sort(key=lambda e: (int(e[1]), e[0] == "MESSAGE"))
count = [0] * numberOfUsers
next_online_time = [0] * numberOfUsers
for event in events:
cur_time = int(event[1])
if event[0] == "MESSAGE":
if event[2] == "ALL":
for i in range(numberOfUsers):
count[i] += 1
elif event[2] == "HERE":
for i, t in enumerate(next_online_time):
if t <= cur_time:
count[i] += 1
else:
for idx in event[2].split():
count[int(idx[2:])] += 1
else:
next_online_time[int(event[2])] = cur_time + 60
return count
4.7.191 - 2025-12-11 14:20:50 +0300 MSK
Links
Code
class Solution:
def countCoveredBuildings(self, n: int, buildings: List[List[int]]) -> int:
max_row = [0] * (n + 1)
min_row = [n + 1] * (n + 1)
max_col = [0] * (n + 1)
min_col = [n + 1] * (n + 1)
for p in buildings:
x, y = p[0], p[1]
max_row[y] = max(max_row[y], x)
min_row[y] = min(min_row[y], x)
max_col[x] = max(max_col[x], y)
min_col[x] = min(min_col[x], y)
res = 0
for p in buildings:
x, y = p[0], p[1]
if (
x > min_row[y]
and x < max_row[y]
and y > min_col[x]
and y < max_col[x]
):
res += 1
return res
4.7.192 - 2025-12-10 20:14:13 +0300 MSK
Links
Code
class Solution:
def countPermutations(self, complexity: List[int]) -> int:
n = len(complexity)
for i in range(1, n):
if complexity[i] <= complexity[0]:
return 0
ans, mod = 1, 10**9 + 7
for i in range(2, n):
ans = ans * i % mod
return ans
4.7.193 - 2025-12-09 20:31:56 +0300 MSK
Links
Code
class Solution:
def specialTriplets(self, nums: List[int]) -> int:
MOD = 10**9 + 7
pos = defaultdict(list)
for i, v in enumerate(nums):
pos[v].append(i)
def upper_bound(arr, i):
l, r = 0, len(arr) - 1
while l < r:
mid = l + ((r - l + 1) >> 1)
if i >= arr[mid]:
l = mid
else:
r = mid - 1
return l + 1, len(arr) - 1 - l
ans = 0
for i in range(1, len(nums) - 1):
target = nums[i] * 2
if target in pos and len(pos[target]) > 1 and pos[target][0] < i:
l, r = upper_bound(pos[target], i)
if nums[i] == 0:
l -= 1
ans = (ans + l * r) % MOD
return ans
4.7.194 - 2025-12-08 20:20:12 +0300 MSK
Links
Code
class Solution:
def countTriples(self, n: int) -> int:
res = 0
for a in range(1, n):
for b in range(a + 1, n):
c = math.sqrt(a * a + b * b)
if c % 1 == 0 and c <= n:
res += 2
return res
4.7.195 - 2025-12-07 19:27:13 +0300 MSK
Links
Code
func countOdds(low int, high int) int {
low_even, high_even, half := (low&1) == 0, (high&1) == 0, (high-low)/2
if low_even && high_even {
return half
}
return half + 1
}
4.7.196 - 2025-12-06 19:08:58 +0300 MSK
Links
Code
class Solution:
def countPartitions(self, nums: List[int]) -> int:
sm, n = [0] * len(nums), len(nums)
sm[0] = nums[0]
for i in range(n):
sm[i] = sm[i - 1] + nums[i]
res = 0
for i in range(n - 1):
left = sm[i]
right = sm[-1] - left
res += abs(right - left) % 2 == 0
return res
4.7.197 - 2025-12-06 19:07:24 +0300 MSK
Links
Code
class Solution:
def countPartitions(self, nums: List[int], k: int) -> int:
n = len(nums)
mod = 10**9 + 7
dp = [0] * (n + 1)
prefix = [0] * (n + 1)
min_q = deque()
max_q = deque()
dp[0] = 1
prefix[0] = 1
j = 0
for i in range(n):
# maintain the maximum value queue
while max_q and nums[max_q[-1]] <= nums[i]:
max_q.pop()
max_q.append(i)
# maintain the minimum value queue
while min_q and nums[min_q[-1]] >= nums[i]:
min_q.pop()
min_q.append(i)
# adjust window
while max_q and min_q and nums[max_q[0]] - nums[min_q[0]] > k:
if max_q[0] == j:
max_q.popleft()
if min_q[0] == j:
min_q.popleft()
j += 1
if j > 0:
dp[i + 1] = (prefix[i] - prefix[j - 1] + mod) % mod
else:
dp[i + 1] = prefix[i] % mod
prefix[i + 1] = (prefix[i] + dp[i + 1]) % mod
return dp[n]
4.7.198 - 2025-12-04 19:31:16 +0300 MSK
Links
Code
class Solution:
def countCollisions(self, directions: str) -> int:
dirs = directions.lstrip("L").rstrip("R")
return len(dirs) - dirs.count("S")
4.7.199 - 2025-12-03 21:01:12 +0300 MSK
Links
Code
class Solution:
def countTrapezoids(self, points: List[List[int]]) -> int:
n = len(points)
inf = 10**9 + 7
slope_to_intercept = defaultdict(list)
mid_to_slope = defaultdict(list)
ans = 0
for i in range(n):
x1, y1 = points[i]
for j in range(i + 1, n):
x2, y2 = points[j]
dx = x1 - x2
dy = y1 - y2
if x2 == x1:
k = inf
b = x1
else:
k = (y2 - y1) / (x2 - x1)
b = (y1 * dx - x1 * dy) / dx
mid = (x1 + x2) * 10000 + (y1 + y2)
slope_to_intercept[k].append(b)
mid_to_slope[mid].append(k)
for sti in slope_to_intercept.values():
if len(sti) == 1:
continue
cnt = defaultdict(int)
for b_val in sti:
cnt[b_val] += 1
total_sum = 0
for count in cnt.values():
ans += total_sum * count
total_sum += count
for mts in mid_to_slope.values():
if len(mts) == 1:
continue
cnt = defaultdict(int)
for k_val in mts:
cnt[k_val] += 1
total_sum = 0
for count in cnt.values():
ans -= total_sum * count
total_sum += count
return ans
4.7.200 - 2025-12-02 19:36:01 +0300 MSK
Links
Code
class Solution:
def countTrapezoids(self, points: List[List[int]]) -> int:
point_num = defaultdict(int)
mod = 10**9 + 7
ans, total_sum = 0, 0
for point in points:
point_num[point[1]] += 1
for p_num in point_num.values():
edge = p_num * (p_num - 1) // 2
ans = (ans + edge * total_sum) % mod
total_sum = (total_sum + edge) % mod
return ans
4.7.201 - 2025-12-01 19:36:43 +0300 MSK
Links
Code
class Solution:
# n = 2, batteries = [3,3,3], Output: 4
# n = 2, batteries = [1,1,1,1], Output: 2
def maxRunTime(self, n: int, batteries: List[int]) -> int:
length = len(batteries)
if length < n:
return 0
if length == n:
return min(batteries)
batteries.sort()
extra = sum(batteries[:-n])
live = batteries[-n:]
# We increase the total running time using 'extra' by increasing
# the running time of the computer with the smallest battery.
for i in range(n - 1):
# If the target running time is between live[i] and live[i + 1].
if extra // (i + 1) < live[i + 1] - live[i]:
return live[i] + extra // (i + 1)
# Reduce 'extra' by the total power used.
extra -= (i + 1) * (live[i + 1] - live[i])
# If there is power left, we can increase the running time
# of all computers.
return live[-1] + extra // n
4.7.202 - 2025-11-30 20:53:29 +0300 MSK
Links
Code
class Solution:
def minSubarray(self, nums: List[int], p: int) -> int:
n = len(nums)
total_sum = 0
# Step 1: Calculate total sum and target remainder
for num in nums:
total_sum = (total_sum + num) % p
target = total_sum % p
if target == 0:
return 0 # The array is already divisible by p
# Step 2: Use a dict to track prefix sum mod p
mod_map = {
0: -1
} # To handle the case where the whole prefix is the answer
current_sum = 0
min_len = n
# Step 3: Iterate over the array
for i in range(n):
current_sum = (current_sum + nums[i]) % p
# Calculate what we need to remove
needed = (current_sum - target + p) % p
# If we have seen the needed remainder, we can consider this subarray
if needed in mod_map:
min_len = min(min_len, i - mod_map[needed])
# Store the current remainder and index
mod_map[current_sum] = i
# Step 4: Return result
return -1 if min_len == n else min_len
4.7.203 - 2025-11-29 21:07:28 +0300 MSK
Links
Code
class Solution:
def minOperations(self, nums: List[int], k: int) -> int:
return sum(nums) % k
4.7.204 - 2025-11-28 20:52:48 +0300 MSK
Links
Code
class Solution:
def maxKDivisibleComponents(
self, n: int, edges: List[List[int]], values: List[int], k: int
) -> int:
if n < 2:
return 1
component_count = 0
graph = defaultdict(list)
in_degree = [0 for _ in range(n)]
# Build the graph and calculate in-degrees
for node1, node2 in edges:
graph[node1].append(node2)
graph[node2].append(node1)
in_degree[node1] += 1
in_degree[node2] += 1
# Initialize the queue with nodes having in-degree of 1 (leaf nodes)
queue = deque(node for node in range(n) if in_degree[node] == 1)
while queue:
current_node = queue.popleft()
in_degree[current_node] -= 1
add_value = 0
# Check if the current node's value is divisible by k
if values[current_node] % k == 0:
component_count += 1
else:
add_value = values[current_node]
# Propagate the value to the neighbor nodes
for neighbor_node in graph[current_node]:
if in_degree[neighbor_node] == 0:
continue
in_degree[neighbor_node] -= 1
values[neighbor_node] += add_value
# If the neighbor node's in-degree becomes 1, add it to the queue
if in_degree[neighbor_node] == 1:
queue.append(neighbor_node)
return component_count
4.7.205 - 2025-11-27 17:52:11 +0300 MSK
Links
Code
class Solution:
def maxSubarraySum(self, nums: List[int], k: int) -> int:
n = len(nums)
prefixSum = 0
maxSum = -sys.maxsize
kSum = [sys.maxsize // 2] * k
kSum[k - 1] = 0
for i in range(n):
prefixSum += nums[i]
maxSum = max(maxSum, prefixSum - kSum[i % k])
kSum[i % k] = min(kSum[i % k], prefixSum)
return maxSum
4.7.206 - 2025-11-26 18:06:00 +0300 MSK
Links
Code
class Solution:
def numberOfPaths(self, grid: List[List[int]], k: int) -> int:
MOD = 10**9 + 7
m, n = len(grid), len(grid[0])
dp = [[[0] * k for _ in range(n + 1)] for _ in range(m + 1)]
for i in range(1, m + 1):
for j in range(1, n + 1):
if i == 1 and j == 1:
dp[i][j][grid[0][0] % k] = 1
continue
value = grid[i - 1][j - 1] % k
for r in range(k):
prev_mod = (r - value + k) % k
dp[i][j][r] = (
dp[i - 1][j][prev_mod] + dp[i][j - 1][prev_mod]
) % MOD
return dp[m][n][0]
4.7.207 - 2025-11-25 19:49:04 +0300 MSK
Links
Code
class Solution:
def smallestRepunitDivByK(self, K: int) -> int:
remainder = 0
for length_N in range(1,K+1):
remainder = (remainder*10+1) % K
if remainder == 0:
return length_N
return -1
4.7.208 - 2025-11-24 18:58:12 +0300 MSK
Links
Code
class Solution:
def prefixesDivBy5(self, nums: List[int]) -> List[bool]:
cur = 0
for i in range(len(nums)):
cur <<= 1
cur |= nums[i]
nums[i] = cur % 5 == 0
return nums
4.7.209 - 2025-11-23 18:20:29 +0300 MSK
Links
Code
class Solution:
def maxSumDivThree(self, nums: List[int]) -> int:
f = [0, -float("inf"), -float("inf")]
for num in nums:
g = f[:]
for i in range(3):
g[(i + num % 3) % 3] = max(g[(i + num % 3) % 3], f[i] + num)
f = g
return f[0]
4.7.210 - 2025-11-22 17:51:32 +0300 MSK
Links
Code
class Solution:
def minimumOperations(self, nums: List[int]) -> int:
res = 0
for i in range(len(nums)):
res += nums[i] % 3 != 0
return res
4.7.211 - 2025-11-21 17:40:54 +0300 MSK
Links
Code
class Solution {
public:
int countPalindromicSubsequence(string s) {
unordered_set<char> letters;
for (char c : s) {
letters.insert(c);
}
int ans = 0;
for (char letter : letters) {
int i = -1;
int j = 0;
for (int k = 0; k < s.size(); k++) {
if (s[k] == letter) {
if (i == -1) {
i = k;
}
j = k;
}
}
unordered_set<char> between;
for (int k = i + 1; k < j; k++) {
between.insert(s[k]);
}
ans += between.size();
}
return ans;
}
};
4.7.212 - 2025-11-20 18:30:09 +0300 MSK
Links
Code
class Solution(object):
def intersectionSizeTwo(self, intervals):
intervals.sort(key =lambda val: (val[0], -val[1]))
todo = [2] * len(intervals)
ans = 0
while intervals:
(s, e), t = intervals.pop(), todo.pop()
for p in range(s, s+t):
for i, (s0, e0) in enumerate(intervals):
if todo[i] and p <= e0:
todo[i] -= 1
ans += 1
return ans
4.7.213 - 2025-11-19 18:01:12 +0300 MSK
Links
Code
class Solution:
def findFinalValue(self, nums: List[int], original: int) -> int:
nums.sort()
length = len(nums)
left, right = 0, length - 1
while left <= right:
i = left + (right - left) // 2
val = nums[i]
if val > original:
right = i - 1
elif val == original:
original *= 2
left = i + 1
right = length - 1
else:
left = i + 1
return original
4.7.214 - 2025-11-18 19:16:52 +0300 MSK
Links
Code
class Solution(object):
def isOneBitCharacter(self, bits):
i = 0
while i < len(bits) - 1:
i += bits[i] + 1
return i == len(bits) - 1
4.7.215 - 2025-11-17 18:59:11 +0300 MSK
Links
Code
class Solution:
def kLengthApart(self, nums: List[int], k: int) -> bool:
prev = -k - 1
for i, num in enumerate(nums):
if num == 0:
continue
if i - prev - 1 >= k:
prev = i
else:
return False
return True
4.7.216 - 2025-11-16 18:07:29 +0300 MSK
Links
Code
class Solution:
def numSub(self, s: str) -> int:
total, consecutive = 0, 0
length = len(s)
for i in range(length):
if s[i] == "0":
total += consecutive * (consecutive + 1) // 2
consecutive = 0
else:
consecutive += 1
total += consecutive * (consecutive + 1) // 2
total %= 10**9 + 7
return total
4.7.217 - 2025-11-15 18:41:02 +0300 MSK
Links
Code
class Solution:
def numberOfSubstrings(self, s: str) -> int:
n = len(s)
pre = [-1] * (n + 1)
for i in range(n):
if i == 0 or s[i - 1] == "0":
pre[i + 1] = i
else:
pre[i + 1] = pre[i]
res = 0
for i in range(1, n + 1):
cnt0 = 1 if s[i - 1] == "0" else 0
j = i
while j > 0 and cnt0 * cnt0 <= n:
cnt1 = (i - pre[j]) - cnt0
if cnt0 * cnt0 <= cnt1:
res += min(j - pre[j], cnt1 - cnt0 * cnt0 + 1)
j = pre[j]
cnt0 += 1
return res
4.7.218 - 2025-11-14 15:39:54 +0300 MSK
Links
Code
class Solution:
def maxOperations(self, s: str) -> int:
count_one = 0
ans = 0
i = 0
while i < len(s):
if s[i] == "0":
while i + 1 < len(s) and s[i + 1] == "0":
i += 1
ans += count_one
else:
count_one += 1
i += 1
return ans
4.7.219 - 2025-11-14 15:39:21 +0300 MSK
Links
Code
class Solution:
def minOperations(self, nums: List[int]) -> int:
n = len(nums)
num1 = 0
g = 0
for x in nums:
if x == 1:
num1 += 1
g = gcd(g, x)
if num1 > 0:
return n - num1
if g > 1:
return -1
min_len = n
for i in range(n):
g = 0
for j in range(i, n):
g = gcd(g, nums[j])
if g == 1:
min_len = min(min_len, j - i + 1)
break
return min_len + n - 2
4.7.220 - 2025-11-14 15:38:45 +0300 MSK
Links
Code
class Solution:
def rangeAddQueries(
self, n: int, queries: List[List[int]]
) -> List[List[int]]:
diff = [[0] * (n + 1) for _ in range(n + 1)]
for row1, col1, row2, col2 in queries:
diff[row1][col1] += 1
diff[row2 + 1][col1] -= 1
diff[row1][col2 + 1] -= 1
diff[row2 + 1][col2 + 1] += 1
mat = [[0] * n for _ in range(n)]
for i in range(n):
for j in range(n):
x1 = 0 if i == 0 else mat[i - 1][j]
x2 = 0 if j == 0 else mat[i][j - 1]
x3 = 0 if i == 0 or j == 0 else mat[i - 1][j - 1]
mat[i][j] = diff[i][j] + x1 + x2 - x3
return mat
4.7.221 - 2025-11-11 19:43:26 +0300 MSK
Links
Code
class Solution:
def findMaxForm(self, strs: List[str], m: int, n: int) -> int:
dp = {(0, 0): 0}
for s in strs:
ones = 0
zeroes = 0
for ch in s:
if ch == "0":
zeroes += 1
else:
ones += 1
newdp = {}
for k, v in dp.items():
prevzeroes, prevones = k
newzeroes, newones = prevzeroes + zeroes, prevones + ones
if newzeroes <= m and newones <= n:
if (newzeroes, newones) not in dp:
newdp[(newzeroes, newones)] = v + 1
elif dp[(newzeroes, newones)] < v + 1:
newdp[(newzeroes, newones)] = v + 1
dp.update(newdp)
return max(dp.values())
4.7.222 - 2025-11-10 19:49:56 +0300 MSK
Links
Code
class Solution:
def minOperations(self, nums: List[int]) -> int:
s = []
res = 0
for a in nums:
while s and s[-1] > a:
s.pop()
if a == 0:
continue
if not s or s[-1] < a:
res += 1
s.append(a)
return res
4.7.223 - 2025-11-09 17:05:22 +0300 MSK
Links
Code
class Solution:
def countOperations(self, num1: int, num2: int) -> int:
count = 0
while num1 > 0 and num2 > 0:
if num1 >= num2:
count += num1 // num2
num1 %= num2
else:
count += num2 // num1
num2 %= num1
return count
4.7.224 - 2025-11-08 22:09:46 +0300 MSK
Links
Code
class Solution:
def minimumOneBitOperations(self, n: int) -> int:
if n == 0:
return 0
k = 0
curr = 1
while (curr * 2) <= n:
curr *= 2
k += 1
return 2 ** (k + 1) - 1 - self.minimumOneBitOperations(n ^ curr)
4.7.225 - 2025-11-07 20:28:33 +0300 MSK
Links
Code
class Solution:
def maxPower(self, stations: List[int], r: int, k: int) -> int:
n = len(stations)
cnt = [0] * (n + 1)
for i in range(n):
left = max(0, i - r)
right = min(n, i + r + 1)
cnt[left] += stations[i]
cnt[right] -= stations[i]
def check(val: int) -> bool:
diff = cnt.copy()
total = 0
remaining = k
for i in range(n):
total += diff[i]
if total < val:
add = val - total
if remaining < add:
return False
remaining -= add
end = min(n, i + 2 * r + 1)
diff[end] -= add
total += add
return True
lo, hi = min(stations), sum(stations) + k
res = 0
while lo <= hi:
mid = (lo + hi) // 2
if check(mid):
res = mid
lo = mid + 1
else:
hi = mid - 1
return res
4.7.226 - 2025-11-06 20:39:45 +0300 MSK
Links
Code
class DSU:
def __init__(self, size):
self.parent = list(range(size))
def find(self, x):
if self.parent[x] != x:
self.parent[x] = self.find(self.parent[x])
return self.parent[x]
def join(self, u, v):
self.parent[self.find(v)] = self.find(u)
class Solution:
def processQueries(
self, c: int, connections: List[List[int]], queries: List[List[int]]
) -> List[int]:
dsu = DSU(c + 1)
for p in connections:
dsu.join(p[0], p[1])
online = [True] * (c + 1)
offline_counts = [0] * (c + 1)
minimum_online_stations = {}
for q in queries:
op, x = q[0], q[1]
if op == 2:
online[x] = False
offline_counts[x] += 1
for i in range(1, c + 1):
root = dsu.find(i)
if root not in minimum_online_stations:
minimum_online_stations[root] = -1
station = minimum_online_stations[root]
if online[i]:
if station == -1 or station > i:
minimum_online_stations[root] = i
ans = []
for i in range(len(queries) - 1, -1, -1):
op, x = queries[i][0], queries[i][1]
root = dsu.find(x)
station = minimum_online_stations[root]
if op == 1:
if online[x]:
ans.append(x)
else:
ans.append(station)
if op == 2:
if offline_counts[x] > 1:
offline_counts[x] -= 1
else:
online[x] = True
if station == -1 or station > x:
minimum_online_stations[root] = x
return ans[::-1]
4.7.227 - 2025-11-05 20:31:23 +0300 MSK
Links
Code
class Helper:
def __init__(self, x):
self.x = x
self.result = 0
self.large = SortedList()
self.small = SortedList()
self.occ = defaultdict(int)
def insert(self, num):
if self.occ[num] > 0:
self.internal_remove((self.occ[num], num))
self.occ[num] += 1
self.internal_insert((self.occ[num], num))
def remove(self, num):
self.internal_remove((self.occ[num], num))
self.occ[num] -= 1
if self.occ[num] > 0:
self.internal_insert((self.occ[num], num))
def get(self):
return self.result
def internal_insert(self, p):
if len(self.large) < self.x or p > self.large[0]:
self.result += p[0] * p[1]
self.large.add(p)
if len(self.large) > self.x:
to_remove = self.large[0]
self.result -= to_remove[0] * to_remove[1]
self.large.remove(to_remove)
self.small.add(to_remove)
else:
self.small.add(p)
def internal_remove(self, p):
if p >= self.large[0]:
self.result -= p[0] * p[1]
self.large.remove(p)
if self.small:
to_add = self.small[-1]
self.result += to_add[0] * to_add[1]
self.small.remove(to_add)
self.large.add(to_add)
else:
self.small.remove(p)
class Solution:
def findXSum(self, nums, k, x):
helper = Helper(x)
ans = []
for i in range(len(nums)):
helper.insert(nums[i])
if i >= k:
helper.remove(nums[i - k])
if i >= k - 1:
ans.append(helper.get())
return ans
4.7.228 - 2025-11-04 17:04:32 +0300 MSK
Links
Code
class Solution:
def findXSum(self, nums: List[int], k: int, x: int) -> List[int]:
def do_sum (idx: int)-> int:
ctr = Counter(nums[idx:idx + k])
most_freq = nlargest(x, ctr, key = lambda y: (ctr[y], y))
return sum(map(lambda y: y * ctr[y], most_freq))
return tuple(map(do_sum,range(len(nums)+1 - k)))
4.7.229 - 2025-11-03 17:26:21 +0300 MSK
Links
Code
class Solution:
def minCost(self, colors: str, neededTime: list[int]) -> int:
total_time, curr_max_time = 0, 0
for i in range(len(colors)):
if i > 0 and colors[i] != colors[i - 1]:
curr_max_time = 0
total_time += min(curr_max_time, neededTime[i])
curr_max_time = max(curr_max_time, neededTime[i])
return total_time
4.7.230 - 2025-11-02 19:37:10 +0300 MSK
Links
Code
class Solution:
def modifiedList(
self, nums: List[int], head: Optional[ListNode]
) -> Optional[ListNode]:
# Create a set for efficient lookup of values in nums
values_to_remove = set(nums)
# Handle the case where the head node needs to be removed
while head and head.val in values_to_remove:
head = head.next
# If the list is empty after removing head nodes, return None
if not head:
return None
# Iterate through the list, removing nodes with values in the set
current = head
while current.next:
if current.next.val in values_to_remove:
# Skip the next node by updating the pointer
current.next = current.next.next
else:
# Move to the next node
current = current.next
return head
4.7.231 - 2025-11-02 19:36:12 +0300 MSK
Links
Code
class Solution:
def modifiedList(
self, nums: List[int], head: Optional[ListNode]
) -> Optional[ListNode]:
# Create a set for efficient lookup of values in nums
values_to_remove = set(nums)
# Handle the case where the head node needs to be removed
while head and head.val in values_to_remove:
head = head.next
# If the list is empty after removing head nodes, return None
if not head:
return None
# Iterate through the list, removing nodes with values in the set
current = head
while current.next:
if current.next.val in values_to_remove:
# Skip the next node by updating the pointer
current.next = current.next.next
else:
# Move to the next node
current = current.next
return head
4.7.232 - 2025-11-02 19:35:07 +0300 MSK
Links
Code
class Solution:
UNGUARDED = 0
GUARDED = 1
GUARD = 2
WALL = 3
# Depth-First Search to mark guarded cells
def _recurse(
self, row: int, col: int, grid: List[List[int]], direction: str
) -> None:
if (
row < 0
or row >= len(grid)
or col < 0
or col >= len(grid[0])
or grid[row][col] == self.GUARD
or grid[row][col] == self.WALL
):
return
grid[row][col] = self.GUARDED # Mark cell as guarded
if direction == "U":
self._recurse(row - 1, col, grid, "U") # Up
if direction == "D":
self._recurse(row + 1, col, grid, "D") # Down
if direction == "L":
self._recurse(row, col - 1, grid, "L") # Left
if direction == "R":
self._recurse(row, col + 1, grid, "R") # Right
def countUnguarded(
self, m: int, n: int, guards: List[List[int]], walls: List[List[int]]
) -> int:
grid = [[self.UNGUARDED] * n for _ in range(m)]
# Mark guards' positions
for guard in guards:
grid[guard[0]][guard[1]] = self.GUARD
# Mark walls' positions
for wall in walls:
grid[wall[0]][wall[1]] = self.WALL
# Mark cells as guarded by traversing from each guard
for guard in guards:
self._recurse(guard[0] - 1, guard[1], grid, "U") # Up
self._recurse(guard[0] + 1, guard[1], grid, "D") # Down
self._recurse(guard[0], guard[1] - 1, grid, "L") # Left
self._recurse(guard[0], guard[1] + 1, grid, "R") # Right
# Count unguarded cells
count = sum(row.count(self.UNGUARDED) for row in grid)
return count
4.7.233 - 2025-10-31 21:10:44 +0300 MSK
Links
Code
class Solution:
def getSneakyNumbers(self, nums: List[int]) -> List[int]:
n = len(nums) - 2
xor_all = 0
for num in nums:
xor_all ^= num
for num in range(n):
xor_all ^= num
rightmost_bit = xor_all & -xor_all
dup1, dup2 = 0, 0
for num in nums:
if num & rightmost_bit:
dup1 ^= num
else:
dup2 ^= num
for num in range(n):
if num & rightmost_bit:
dup1 ^= num
else:
dup2 ^= num
return [dup1, dup2]
4.7.234 - 2025-10-30 20:34:31 +0300 MSK
Links
Code
class Solution:
def minNumberOperations(self, target: List[int]) -> int:
n = len(target)
ans = target[0]
for i in range(1, n):
ans += max(target[i] - target[i - 1], 0)
return ans
4.7.235 - 2025-10-29 19:40:08 +0300 MSK
Links
Code
class Solution:
def smallestNumber(self, n: int) -> int:
res = 0
while n > 0:
res = (res << 1) | 1
n //= 2
return res
4.7.236 - 2025-10-28 17:46:01 +0300 MSK
Links
Code
class Solution:
def scoreBalance(self, s: str) -> bool:
right, left = 0, 0
for char in s:
right += ord(char) - ord('a') + 1
for char in s:
val = ord(char) - ord('a') + 1
left += val
right -= val
if left == right:
return True
if left > right:
return False
return False
4.7.237 - 2025-10-28 17:19:30 +0300 MSK
Links
Code
class Solution:
def countValidSelections(self, nums: List[int]) -> int:
n, res = len(nums), 0
left, right = [0 for _ in range(n)], [0 for _ in range(n)]
for i in range(1, n):
left[i] = left[i - 1] + nums[i - 1]
right[-i - 1] = right[-i] + nums[-i]
for i, num in enumerate(nums):
if num != 0: continue
if left[i] == right[i]: res += 2
if abs(left[i] - right[i]) == 1: res += 1
return res
4.7.238 - 2025-10-27 20:43:34 +0300 MSK
Links
Code
class Solution:
def numberOfBeams(self, bank):
ans, temp = 0, 0
for s in bank:
n = s.count('1')
if n == 0:
continue
ans += temp * n
temp = n
return ans
4.7.239 - 2025-10-27 12:49:36 +0300 MSK
Links
Code
class Bank:
def __init__(self, balance: List[int]):
self.balance = balance
def transfer(self, account1: int, account2: int, money: int) -> bool:
if (
account1 > len(self.balance)
or account2 > len(self.balance)
or self.balance[account1 - 1] < money
):
return False
self.balance[account1 - 1] -= money
self.balance[account2 - 1] += money
return True
def deposit(self, account: int, money: int) -> bool:
if account > len(self.balance):
return False
self.balance[account - 1] += money
return True
def withdraw(self, account: int, money: int) -> bool:
if account > len(self.balance) or self.balance[account - 1] < money:
return False
self.balance[account - 1] -= money
return True
4.7.240 - 2025-10-27 12:48:19 +0300 MSK
Links
Code
class Bank:
def __init__(self, balance: List[int]):
self.balance = balance
def transfer(self, account1: int, account2: int, money: int) -> bool:
if (
account1 > len(self.balance)
or account2 > len(self.balance)
or self.balance[account1 - 1] < money
):
return False
self.balance[account1 - 1] -= money
self.balance[account2 - 1] += money
return True
def deposit(self, account: int, money: int) -> bool:
if account > len(self.balance):
return False
self.balance[account - 1] += money
return True
def withdraw(self, account: int, money: int) -> bool:
if account > len(self.balance) or self.balance[account - 1] < money:
return False
self.balance[account - 1] -= money
return True
4.7.241 - 2025-10-25 13:13:55 +0300 MSK
Links
Code
class Solution {
public:
int totalMoney(int n) {
int ans {0};
int monday {1};
while (n > 0) {
for (int day {0}; day < min(n, 7); ++day) {
ans += monday + day;
}
n -= 7;
++monday;
}
return ans;
}
};
4.7.242 - 2025-10-24 19:02:20 +0300 MSK
Links
Code
class Solution:
def nextBeautifulNumber(self, n: int) -> int:
for i in range(n + 1, 1224445):
count = Counter(str(i))
if all(count[d] == int(d) for d in count):
return i
4.7.243 - 2025-10-23 19:12:54 +0300 MSK
Links
Code
class Solution:
def hasSameDigits(self, s: str) -> bool:
stack = list(map(int, s))
stack.reverse()
while len(stack) > 2:
prev = stack.pop()
for i in reversed(range(len(stack))):
stack[i], prev = (prev + stack[i]) % 10, stack[i]
return stack[0] == stack[1]
4.7.244 - 2025-10-22 16:36:23 +0300 MSK
Links
Code
class Solution:
def maxFrequency(self, nums: List[int], k: int, numOperations: int) -> int:
nums.sort()
ans = 0
num_count = defaultdict(int)
modes = set()
def add_mode(value):
modes.add(value)
if value - k >= nums[0]:
modes.add(value - k)
if value + k <= nums[-1]:
modes.add(value + k)
last_num_index = 0
for i in range(len(nums)):
if nums[i] != nums[last_num_index]:
num_count[nums[last_num_index]] = i - last_num_index
ans = max(ans, i - last_num_index)
add_mode(nums[last_num_index])
last_num_index = i
num_count[nums[last_num_index]] = len(nums) - last_num_index
ans = max(ans, len(nums) - last_num_index)
add_mode(nums[last_num_index])
for mode in sorted(modes):
l = bisect.bisect_left(nums, mode - k)
r = bisect.bisect_right(nums, mode + k) - 1
if mode in num_count:
temp_ans = min(r - l + 1, num_count[mode] + numOperations)
else:
temp_ans = min(r - l + 1, numOperations)
ans = max(ans, temp_ans)
return ans
4.7.245 - 2025-10-21 20:51:47 +0300 MSK
Links
Code
class Solution:
def maxFrequency(self, nums: List[int], k: int, numOperations: int) -> int:
nums.sort()
ans = 0
num_count = {}
last_num_index = 0
for i in range(len(nums)):
if nums[i] != nums[last_num_index]:
num_count[nums[last_num_index]] = i - last_num_index
ans = max(ans, i - last_num_index)
last_num_index = i
num_count[nums[last_num_index]] = len(nums) - last_num_index
ans = max(ans, len(nums) - last_num_index)
for i in range(nums[0], nums[-1] + 1):
l = bisect.bisect_left(nums, i - k)
r = bisect.bisect_right(nums, i + k) - 1
if i in num_count:
temp_ans = min(r - l + 1, num_count[i] + numOperations)
else:
temp_ans = min(r - l + 1, numOperations)
ans = max(ans, temp_ans)
return ans
4.7.246 - 2025-10-20 21:06:38 +0300 MSK
Links
Code
class Solution:
def finalValueAfterOperations(self, operations: List[str]) -> int:
res = 0
for op in operations:
if op.startswith("++") or op.endswith("++"):
res += 1
else:
res -= 1
return res
4.7.247 - 2025-10-19 18:18:20 +0300 MSK
Links
Code
class Solution:
def findLexSmallestString(self, s: str, a: int, b: int) -> str:
n = len(s)
vis = [False] * n
res = s
# double the length of s for convenience in extracting the rotated string t
s = s + s
i = 0
while not vis[i]:
vis[i] = True
for j in range(10):
k_limit = 0 if b % 2 == 0 else 9
for k in range(k_limit + 1):
# before each accumulation, re-truncate t
t = list(s[i : i + n])
for p in range(1, n, 2):
t[p] = str((int(t[p]) + j * a) % 10)
for p in range(0, n, 2):
t[p] = str((int(t[p]) + k * a) % 10)
t_str = "".join(t)
if t_str < res:
res = t_str
i = (i + b) % n
return res
4.7.248 - 2025-10-18 20:20:30 +0300 MSK
Links
Code
class Solution:
def maxDistinctElements(self, nums: List[int], k: int) -> int:
nums.sort()
cnt = 0
prev = -math.inf
for num in nums:
curr = min(max(num - k, prev + 1), num + k)
if curr > prev:
cnt += 1
prev = curr
return cnt
4.7.249 - 2025-10-17 20:03:35 +0300 MSK
Links
Code
class Solution:
def maxPartitionsAfterOperations(self, s: str, k: int) -> int:
n = len(s)
left = [[0] * 3 for _ in range(n)]
right = [[0] * 3 for _ in range(n)]
num, mask, count = 0, 0, 0
for i in range(n - 1):
binary = 1 << (ord(s[i]) - ord("a"))
if not (mask & binary):
count += 1
if count <= k:
mask |= binary
else:
num += 1
mask = binary
count = 1
left[i + 1][0] = num
left[i + 1][1] = mask
left[i + 1][2] = count
num, mask, count = 0, 0, 0
for i in range(n - 1, 0, -1):
binary = 1 << (ord(s[i]) - ord("a"))
if not (mask & binary):
count += 1
if count <= k:
mask |= binary
else:
num += 1
mask = binary
count = 1
right[i - 1][0] = num
right[i - 1][1] = mask
right[i - 1][2] = count
max_val = 0
for i in range(n):
seg = left[i][0] + right[i][0] + 2
tot_mask = left[i][1] | right[i][1]
tot_count = bin(tot_mask).count("1")
if left[i][2] == k and right[i][2] == k and tot_count < 26:
seg += 1
elif min(tot_count + 1, 26) <= k:
seg -= 1
max_val = max(max_val, seg)
return max_val
4.7.250 - 2025-10-16 21:12:42 +0300 MSK
Links
Code
class Solution:
def findSmallestInteger(self, nums: List[int], value: int) -> int:
mp = Counter(x % value for x in nums)
mex = 0
while mp[mex % value] > 0:
mp[mex % value] -= 1
mex += 1
return mex
4.7.251 - 2025-10-15 21:05:53 +0300 MSK
Links
Code
class Solution:
def maxIncreasingSubarrays(self, nums: List[int]) -> int:
n = len(nums)
cnt, precnt, ans = 1, 0, 0
for i in range(1, n):
if nums[i] > nums[i - 1]:
cnt += 1
else:
precnt, cnt = cnt, 1
ans = max(ans, min(precnt, cnt))
ans = max(ans, cnt // 2)
return ans
4.7.252 - 2025-10-14 21:36:00 +0300 MSK
Links
Code
class Solution:
def hasIncreasingSubarrays(self, nums: List[int], k: int) -> bool:
n = len(nums)
cnt = 1
prv_cnt = 0
for i in range(1, n):
cur, prv = nums[i], nums[i - 1]
if cur > prv:
cnt += 1
else:
prv_cnt, cnt = cnt, 1
if cnt >= 2 * k or prv_cnt >= k and cnt >= k:
return True
return False
4.7.253 - 2025-10-13 21:06:28 +0300 MSK
Links
Code
class Solution:
def removeAnagrams(self, words: List[str]) -> List[str]:
freqs1, freqs2 = bytearray(26), bytearray(26)
res = []
for i, word in enumerate(words):
for i in range(26):
freqs2[i] = 0
for char in word:
freqs2[ord(char) - 97] += 1
if i != 0 and freqs1 == freqs2:
continue
freqs1, freqs2 = freqs2, freqs1
res.append(word)
return res
4.7.254 - 2025-10-12 18:25:03 +0300 MSK
Links
Code
class Solution:
def quickmul(self, x: int, y: int, mod: int) -> int:
res, cur = 1, x % mod
while y:
if y & 1:
res = res * cur % mod
y >>= 1
cur = cur * cur % mod
return res
def magicalSum(self, m: int, k: int, nums: List[int]) -> int:
n = len(nums)
mod = 10**9 + 7
fac = [1] * (m + 1)
for i in range(1, m + 1):
fac[i] = fac[i - 1] * i % mod
ifac = [1] * (m + 1)
for i in range(2, m + 1):
ifac[i] = self.quickmul(i, mod - 2, mod)
for i in range(2, m + 1):
ifac[i] = ifac[i - 1] * ifac[i] % mod
numsPower = [[1] * (m + 1) for _ in range(n)]
for i in range(n):
for j in range(1, m + 1):
numsPower[i][j] = numsPower[i][j - 1] * nums[i] % mod
f = [
[[[0] * (k + 1) for _ in range(m * 2 + 1)] for _ in range(m + 1)]
for _ in range(n)
]
for j in range(m + 1):
f[0][j][j][0] = numsPower[0][j] * ifac[j] % mod
for i in range(n - 1):
for j in range(m + 1):
for p in range(m * 2 + 1):
for q in range(k + 1):
if f[i][j][p][q] == 0:
continue
q2 = (p % 2) + q
if q2 > k:
break
for r in range(m - j + 1):
p2 = (p // 2) + r
if p2 > m * 2:
continue
f[i + 1][j + r][p2][q2] = (
f[i + 1][j + r][p2][q2]
+ f[i][j][p][q]
* numsPower[i + 1][r]
% mod
* ifac[r]
% mod
) % mod
res = 0
for p in range(m * 2 + 1):
for q in range(k + 1):
if bin(p).count("1") + q == k:
res = (res + f[n - 1][m][p][q] * fac[m] % mod) % mod
return res
4.7.255 - 2025-10-11 21:08:12 +0300 MSK
Links
Code
class Solution:
def maximumTotalDamage(self, power):
count = Counter(power)
vec = [(-(10**9), 0)]
for k in sorted(count.keys()):
vec.append((k, count[k]))
n = len(vec)
f = [0] * n
mx = 0
j = 1
for i in range(1, n):
while j < i and vec[j][0] < vec[i][0] - 2:
mx = max(mx, f[j])
j += 1
f[i] = mx + vec[i][0] * vec[i][1]
return max(f)
4.7.256 - 2025-10-10 19:31:54 +0300 MSK
Links
Code
class Solution:
def maximumEnergy(self, energy: List[int], k: int) -> int:
n = len(energy)
ans = -inf
for i in range(n - k, n):
total = 0
j = i
while j >= 0:
total += energy[j]
ans = max(ans, total)
j -= k
return ans
4.7.257 - 2025-10-09 21:03:44 +0300 MSK
Links
Code
class Solution:
def minTime(self, skill: List[int], mana: List[int]) -> int:
n, m = len(skill), len(mana)
times = [0] * n
for j in range(m):
cur_time = 0
for i in range(n):
cur_time = max(cur_time, times[i]) + skill[i] * mana[j]
times[n - 1] = cur_time
for i in range(n - 2, -1, -1):
times[i] = times[i + 1] - skill[i + 1] * mana[j]
return times[n - 1]
4.7.258 - 2025-10-08 20:28:20 +0300 MSK
Links
Code
class Solution:
def successfulPairs(self, spells: List[int], potions: List[int], success: int) -> List[int]:
freq=Counter(potions)
pMax=max(freq)
F=[0]*(1+pMax)
for p, f in freq.items():
F[p]=f
freq=list(accumulate(F))
n, m=len(spells), len(potions)
res=[0]*n
for i, x in enumerate(spells):
k=(success+x-1)//x
if k<=pMax:
res[i]=m-freq[k-1]
return res
4.7.259 - 2025-10-07 19:48:34 +0300 MSK
Links
Code
from sortedcontainers import SortedList
class Solution:
def avoidFlood(self, rains: List[int]) -> List[int]:
ans = [1] * len(rains)
st = SortedList()
mp = {}
for i, rain in enumerate(rains):
if rain == 0:
st.add(i)
else:
ans[i] = -1
if rain in mp:
it = st.bisect(mp[rain])
if it == len(st):
return []
ans[st[it]] = rain
st.discard(st[it])
mp[rain] = i
return ans
4.7.260 - 2025-10-06 20:51:45 +0300 MSK
Links
Code
class Solution:
def swimInWater(self, grid: List[List[int]]) -> int:
m, n = len(grid), len(grid[0])
pq = [(grid[0][0], 0, 0)]
directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]
seen = set()
while pq:
max_d, r, c = heapq.heappop(pq)
if (r, c) in seen: continue
seen.add((r, c))
if r == m-1 and c == n-1:
return max_d
for dr, dc in directions:
nr, nc = r + dr, c + dc
if 0 <= nr < m and 0 <= nc < n and (nr, nc) not in seen:
new_d = max(max_d, grid[nr][nc])
heapq.heappush(pq, (new_d, nr, nc))
return -1
4.7.261 - 2025-10-05 19:06:52 +0300 MSK
Links
Code
class Solution:
def pacificAtlantic(self, heights: List[List[int]]) -> List[List[int]]:
def dfs(cell, visited):
if cell in visited:
return
visited.add(cell)
r, c = cell
for nr, nc in [(r-1, c), (r+1, c), (r, c-1), (r, c+1)]:
if 0 <= nr < rows and 0 <= nc < cols and heights[nr][nc] >= heights[r][c]:
dfs((nr, nc), visited)
rows, cols = len(heights), len(heights[0])
pacific, atlantic = set(), set()
for r in range(rows):
dfs((r, 0), pacific)
dfs((r, cols - 1), atlantic)
for c in range(cols):
dfs((0, c), pacific)
dfs((rows - 1, c), atlantic)
return list(pacific & atlantic)
4.7.262 - 2025-10-05 18:56:55 +0300 MSK
Links
Code
class Solution:
def alternatingSum(self, nums: List[int]) -> int:
res = 0
for i, num in enumerate(nums):
if i % 2 == 0:
res += num
else:
res -= num
return res
4.7.263 - 2025-10-04 21:18:06 +0300 MSK
Links
Code
class Solution:
def maxArea(self, height: list[int]) -> int:
i = 0
j = len(height) - 1
res = 0
while i < j:
res = max(res, (j - i) * min(height[i], height[j]))
if height[i] < height[j]:
i += 1
else:
j -= 1
return res
4.7.264 - 2025-10-03 16:57:28 +0300 MSK
Links
Code
class Solution:
# Class to store the height and coordinates of a cell in the grid
class Cell:
def __init__(self, height, row, col):
self.height = height
self.row = row
self.col = col
# Comparison method for the priority queue (min-heap)
def __lt__(self, other):
return self.height < other.height
# Helper function to check if a cell is valid (within grid bounds)
def _is_valid_cell(self, row, col, num_of_rows, num_of_cols):
return 0 <= row < num_of_rows and 0 <= col < num_of_cols
def trapRainWater(self, height_map):
# Direction arrays
d_row = [0, 0, -1, 1]
d_col = [-1, 1, 0, 0]
num_of_rows = len(height_map)
num_of_cols = len(height_map[0])
visited = [[False] * num_of_cols for _ in range(num_of_rows)]
# Priority queue (min-heap) to process boundary cells in increasing height order
boundary = []
# Add the first and last column cells to the boundary and mark them as visited
for i in range(num_of_rows):
heapq.heappush(boundary, self.Cell(height_map[i][0], i, 0))
heapq.heappush(
boundary,
self.Cell(height_map[i][num_of_cols - 1], i, num_of_cols - 1),
)
visited[i][0] = visited[i][num_of_cols - 1] = True
# Add the first and last row cells to the boundary and mark them as visited
for i in range(num_of_cols):
heapq.heappush(boundary, self.Cell(height_map[0][i], 0, i))
heapq.heappush(
boundary,
self.Cell(height_map[num_of_rows - 1][i], num_of_rows - 1, i),
)
visited[0][i] = visited[num_of_rows - 1][i] = True
# Initialize the total water volume to 0
total_water_volume = 0
# Process cells in the boundary (min-heap will always pop the smallest height)
while boundary:
# Pop the cell with the smallest height from the boundary
current_cell = heapq.heappop(boundary)
current_row = current_cell.row
current_col = current_cell.col
min_boundary_height = current_cell.height
# Explore all 4 neighboring cells
for direction in range(4):
# Calculate the row and column of the neighbor
neighbor_row = current_row + d_row[direction]
neighbor_col = current_col + d_col[direction]
# Check if the neighbor is within the grid bounds and not yet visited
if (
self._is_valid_cell(
neighbor_row, neighbor_col, num_of_rows, num_of_cols
)
and not visited[neighbor_row][neighbor_col]
):
# Get the height of the neighbor cell
neighbor_height = height_map[neighbor_row][neighbor_col]
# If the neighbor's height is less than the current boundary height, water can be trapped
if neighbor_height < min_boundary_height:
# Add the trapped water volume
total_water_volume += (
min_boundary_height - neighbor_height
)
# Push the neighbor into the boundary with updated height (to prevent water leakage)
heapq.heappush(
boundary,
self.Cell(
max(neighbor_height, min_boundary_height),
neighbor_row,
neighbor_col,
),
)
visited[neighbor_row][neighbor_col] = True
# Return the total amount of trapped water
return total_water_volume
4.7.265 - 2025-10-02 17:45:08 +0300 MSK
Links
Code
class Solution:
def maxBottlesDrunk(self, numBottles: int, numExchange: int) -> int:
res, empty = numBottles, numBottles
while empty >= numExchange:
empty = (empty - numExchange) + 1
numExchange += 1
res += 1
return res
4.7.266 - 2025-10-01 09:21:36 +0300 MSK
Links
Code
class Solution:
def decimalRepresentation(self, n: int) -> List[int]:
res = []
count = 0
while n > 0:
val = (n % 10) * (10 ** count)
if val != 0:
res.append(val)
count += 1
n //= 10
res.reverse()
return res
4.7.267 - 2025-10-01 09:19:12 +0300 MSK
Links
Code
class Solution:
def majorityFrequencyGroup(self, s: str) -> str:
freqs = [0] * 26
groups = [([], 0) for _ in range(101)]
for char in s:
freqs[ord(char) - 97] += 1
for i, freq in enumerate(freqs):
if freq == 0:
continue
chars, _ = groups[freq]
chars.append(chr(i + 97))
groups[freq] = (chars, freq)
groups.sort(key=lambda val: (len(val[0]), val[1]))
return "".join(groups[-1][0])
4.7.268 - 2025-10-01 08:50:51 +0300 MSK
Links
Code
class Solution:
def evenNumberBitwiseORs(self, nums: List[int]) -> int:
res = 0
for num in nums:
if num % 2 == 0:
res |= num
return res
4.7.269 - 2025-10-01 08:48:37 +0300 MSK
Links
Code
class Solution:
def maxKDistinct(self, nums: List[int], k: int) -> List[int]:
nums.sort(reverse=True)
res = []
for i in range(len(nums)):
if i == 0 or nums[i] != nums[i - 1]:
res.append(nums[i])
if len(res) == k:
break
return res
4.7.270 - 2025-10-01 08:46:25 +0300 MSK
Links
Code
class Solution:
def earliestTime(self, tasks: List[List[int]]) -> int:
res = math.inf
for start, dur in tasks:
res = min(res, start + dur)
return res
4.7.271 - 2025-10-01 08:43:05 +0300 MSK
Links
Code
class Solution:
def numWaterBottles(self, numBottles: int, numExchange: int) -> int:
res, empty = 0, 0
while numBottles > 0:
res += numBottles
empty += numBottles
numBottles, empty = empty // numExchange, empty % numExchange
return res
4.7.272 - 2025-09-30 19:51:05 +0300 MSK
Links
Code
class Solution:
def triangularSum(self, nums: List[int]) -> int:
while len(nums) > 1:
new_nums = list()
for i in range(len(nums) - 1):
new_nums.append((nums[i] + nums[i + 1]) % 10)
nums = new_nums
return nums[0]
4.7.273 - 2025-09-29 18:59:55 +0300 MSK
Links
Code
class Solution:
def minScoreTriangulation(self, values: List[int]) -> int:
@lru_cache(None)
def dp(i, j):
if i + 2 > j:
return 0
if i + 2 == j:
return values[i] * values[i + 1] * values[j]
return min(
(values[i] * values[k] * values[j] + dp(i, k) + dp(k, j))
for k in range(i + 1, j)
)
return dp(0, len(values) - 1)
4.7.274 - 2025-09-28 17:19:33 +0300 MSK
Links
Code
class Solution:
def largestPerimeter(self, nums: List[int]) -> int:
nums.sort(reverse=True)
for i in range(len(nums) - 2):
if nums[i + 1] + nums[i + 2] > nums[i]:
return nums[i] + nums[i + 1] + nums[i + 2]
return 0
4.7.275 - 2025-09-27 17:16:05 +0300 MSK
Links
Code
class Solution:
def smallestAbsent(self, nums: List[int]) -> int:
enc = set(nums)
avg = max(sum(nums) // len(nums), 0) + 1
while True:
if avg in enc:
avg += 1
else:
return avg
4.7.276 - 2025-09-27 10:04:38 +0300 MSK
Links
Code
class Solution(object):
def largestTriangleArea(self, points):
def area(p, q, r):
return .5 * abs(p[0]*q[1]+q[0]*r[1]+r[0]*p[1]
-p[1]*q[0]-q[1]*r[0]-r[1]*p[0])
return max(area(*triangle)
for triangle in itertools.combinations(points, 3))
4.7.277 - 2025-09-26 19:59:24 +0300 MSK
Links
Code
class Solution:
def triangleNumber(self, nums: List[int]) -> int:
nums.sort()
n = len(nums)
count = 0
for i in range(n - 1, -1, -1):
left, right = 0, i - 1
while left < right:
if nums[left] + nums[right] > nums[i]:
count += right - left
right -= 1
else:
left += 1
return count
4.7.278 - 2025-09-25 17:15:32 +0300 MSK
Links
Code
class Solution:
def minimumTotal(self, triangle: List[List[int]]) -> int:
cur, prev = [], triangle[0]
for row in range(1, len(triangle)):
for col in range(row + 1):
if col == 0:
val = prev[col]
elif col == row:
val = prev[col - 1]
else:
val = min(prev[col - 1], prev[col])
cur.append(val + triangle[row][col])
prev.clear()
cur, prev = prev, cur
return min(prev)
4.7.279 - 2025-09-24 18:51:01 +0300 MSK
Links
Code
class Solution:
def fractionToDecimal(self, numerator: int, denominator: int) -> str:
if numerator == 0:
return "0"
fraction = []
if (numerator < 0) ^ (denominator < 0):
fraction.append("-")
dividend = abs(numerator)
divisor = abs(denominator)
fraction.append(str(dividend // divisor))
remainder = dividend % divisor
if remainder == 0:
return "".join(fraction)
fraction.append(".")
map_dict = {}
while remainder != 0:
if remainder in map_dict:
fraction.insert(map_dict[remainder], "(")
fraction.append(")")
break
map_dict[remainder] = len(fraction)
remainder *= 10
fraction.append(str(remainder // divisor))
remainder %= divisor
return "".join(fraction)
4.7.280 - 2025-09-23 16:55:31 +0300 MSK
Links
Code
class Solution:
def compareVersion(self, version1: str, version2: str) -> int:
digs1, digs2 = list(map(int, version1.split("."))), list(map(int, version2.split(".")))
while digs1 and digs1[-1] == 0:
digs1.pop()
while digs2 and digs2[-1] == 0:
digs2.pop()
length1, length2 = len(digs1), len(digs2)
for i in range(max(length1, length2)):
if i == length1:
return -1
if i == length2:
return 1
dig1, dig2 = digs1[i], digs2[i]
if dig1 > dig2:
return 1
elif dig2 > dig1:
return -1
return 0
4.7.281 - 2025-09-22 19:34:44 +0300 MSK
Links
Code
class Solution:
def maxFrequencyElements(self, nums: List[int]) -> int:
max_freq, max_freq_count = 0, 0
freqs = [0] * 101
for num in nums:
freqs[num] += 1
for num, freq in enumerate(freqs):
if freq > max_freq:
max_freq, max_freq_count = freq, freq
elif freq == max_freq:
max_freq_count += freq
return max_freq_count
4.7.282 - 2025-09-21 19:30:58 +0300 MSK
Links
Code
class MovieRentingSystem:
def __init__(self, n: int, entries: List[List[int]]):
self.available = {} # (shop, movie) -> price
self.movie_shops = {} # movie -> list of (price, shop)
self.rented = set() # (shop, movie) that are currently rented
for shop, movie, price in entries:
self.available[(shop, movie)] = price
if movie not in self.movie_shops:
self.movie_shops[movie] = []
self.movie_shops[movie].append((price, shop))
# Sort shops by price for each movie initially
for movie in self.movie_shops:
self.movie_shops[movie].sort()
def search(self, movie: int) -> List[int]:
result = []
for price, shop in self.movie_shops.get(movie, []):
if (shop, movie) not in self.rented:
result.append(shop)
if len(result) == 5:
break
return result
def rent(self, shop: int, movie: int) -> None:
self.rented.add((shop, movie))
def drop(self, shop: int, movie: int) -> None:
self.rented.discard((shop, movie))
def report(self) -> List[List[int]]:
rented_list = []
for shop, movie in self.rented:
price = self.available[(shop, movie)]
rented_list.append((price, shop, movie))
rented_list.sort()
return [[shop, movie] for price, shop, movie in rented_list[:5]]
4.7.283 - 2025-09-20 19:25:16 +0300 MSK
Links
Code
class Router:
def __init__(self, memoryLimit: int):
self.size = memoryLimit
self.packets = {} # key -> [source, destination, timestamp]
self.counts = defaultdict(list) # destination -> sorted list of timestamps
self.queue = deque() # FIFO order of packets
def addPacket(self, source: int, destination: int, timestamp: int) -> bool:
key = self._encode(source, destination, timestamp)
# Duplicate check
if key in self.packets:
return False
# If memory full, forward oldest packet
if len(self.packets) >= self.size:
self.forwardPacket()
# Add packet
self.packets[key] = [source, destination, timestamp]
self.queue.append(key)
self.counts[destination].append(timestamp)
return True
def forwardPacket(self):
if not self.packets:
return []
key = self.queue.popleft()
packet = self.packets.pop(key)
dest = packet[1]
self.counts[dest].pop(0) # remove the earliest timestamp
return packet
def getCount(self, destination: int, startTime: int, endTime: int) -> int:
timestamps = self.counts.get(destination, [])
if not timestamps:
return 0
# Binary search for range
left = bisect.bisect_left(timestamps, startTime)
right = bisect.bisect_right(timestamps, endTime)
return right - left
def _encode(self, source: int, destination: int, timestamp: int) -> int:
# Encode uniquely into 1 number
return (source << 40) | (destination << 20) | timestamp
4.7.284 - 2025-09-19 18:44:46 +0300 MSK
Links
Code
class Spreadsheet:
def __init__(self, rows: int):
self._grid = [[0] * 26 for _ in range(rows)]
def _coord(self, cell: str) -> tuple[int, int]:
return int(cell[1:]) - 1, ord(cell[0]) - ord("A")
def setCell(self, cell: str, value: int) -> None:
row, col = self._coord(cell)
self._grid[row][col] = value
def resetCell(self, cell: str) -> None:
row, col = self._coord(cell)
self._grid[row][col] = 0
def getValue(self, formula: str) -> int:
res = 0
for cell in formula[1:].split("+"):
if cell[0].isdigit():
res += int(cell)
else:
row, col = self._coord(cell)
res += self._grid[row][col]
return res
# Your Spreadsheet object will be instantiated and called as such:
# obj = Spreadsheet(rows)
# obj.setCell(cell,value)
# obj.resetCell(cell)
# param_3 = obj.getValue(formula)
4.7.285 - 2025-09-18 19:58:25 +0300 MSK
Links
Code
class TaskManager:
def __init__(self, tasks: List[List[int]]):
self.tasks = SortedSet()
self.task_to_users = {}
self.task_to_priority = {}
for user_id, task_id, priority in tasks:
self.add(user_id, task_id, priority)
def add(self, userId: int, taskId: int, priority: int) -> None:
self.tasks.add((priority, taskId, userId))
self.task_to_users[taskId] = userId
self.task_to_priority[taskId] = priority
def edit(self, taskId: int, newPriority: int) -> None:
user = self.task_to_users[taskId]
self.rmv(taskId)
self.add(user, taskId, newPriority)
def rmv(self, taskId: int) -> None:
user = self.task_to_users[taskId]
priority = self.task_to_priority[taskId]
self.tasks.remove((priority, taskId, user))
del self.task_to_users[taskId]
del self.task_to_priority[taskId]
def execTop(self) -> int:
if not self.tasks:
return -1
_, task_id, user_id = self.tasks[-1]
self.rmv(task_id)
return user_id
4.7.286 - 2025-09-17 20:39:54 +0300 MSK
Links
Code
from sortedcontainers import SortedSet
class FoodRatings:
def __init__(self, foods: List[str], cuisines: List[str], ratings: List[int]):
# Map food with its rating.
self.food_rating_map = {}
# Map food with the cuisine it belongs to.
self.food_cuisine_map = {}
# Store all food of cuisine in a set (to sort them on ratings/name)
# Set element -> Tuple: (-1 * food_rating, food_name)
self.cuisine_food_map = defaultdict(SortedSet)
for i in range(len(foods)):
# Store 'rating' and 'cuisine' of the current 'food' in 'food_rating_map' and 'food_cuisine_map' maps.
self.food_rating_map[foods[i]] = ratings[i]
self.food_cuisine_map[foods[i]] = cuisines[i]
# Insert the '(-1 * rating, name)' element in the current cuisine's set.
self.cuisine_food_map[cuisines[i]].add((-ratings[i], foods[i]))
def changeRating(self, food: str, newRating: int) -> None:
# Fetch cuisine name for food.
cuisine_name = self.food_cuisine_map[food]
# Find and delete the element from the respective cuisine's set.
old_element = (-self.food_rating_map[food], food)
self.cuisine_food_map[cuisine_name].remove(old_element)
# Update food's rating in 'food_rating' map.
self.food_rating_map[food] = newRating
# Insert the '(-1 * new rating, name)' element in the respective cuisine's set.
self.cuisine_food_map[cuisine_name].add((-newRating, food))
def highestRated(self, cuisine: str) -> str:
highest_rated = self.cuisine_food_map[cuisine][0]
# Return name of the highest-rated 'food' of 'cuisine'.
return highest_rated[1]
4.7.287 - 2025-09-16 18:41:40 +0300 MSK
Links
Code
from math import gcd
class Solution(object):
def replaceNonCoprimes(self, nums):
stack = []
for num in nums:
while stack:
g = gcd(stack[-1], num)
if g == 1:
break
num = (stack.pop() * num) // g
stack.append(num)
return stack
4.7.288 - 2025-09-15 18:04:52 +0300 MSK
Links
Code
class Solution:
def canBeTypedWords(self, text: str, brokenLetters: str) -> int:
ignore = False
res = 0
for char in itertools.chain(text, " "):
if char == " ":
if ignore:
ignore = False
else:
res += 1
elif char in brokenLetters:
ignore = True
return res
4.7.289 - 2025-09-14 19:11:43 +0300 MSK
Links
Code
class Solution(object):
def spellchecker(self, wordlist, queries):
def devowel(word):
return "".join('*' if c in 'aeiou' else c
for c in word)
words_perfect = set(wordlist)
words_cap = {}
words_vow = {}
for word in wordlist:
wordlow = word.lower()
words_cap.setdefault(wordlow, word)
words_vow.setdefault(devowel(wordlow), word)
def solve(query):
if query in words_perfect:
return query
queryL = query.lower()
if queryL in words_cap:
return words_cap[queryL]
queryLV = devowel(queryL)
if queryLV in words_vow:
return words_vow[queryLV]
return ""
return tuple(map(solve, queries))
4.7.290 - 2025-09-13 18:48:49 +0300 MSK
Links
Code
class Solution:
def maxFreqSum(self, s: str) -> int:
freqs = [0] * 26
for char in s:
freqs[ord(char) - 97] += 1
max_vow, max_con = 0, 0
for i in range(26):
if chr(i + 97) in ("a", "e", "i", "o", "u"):
max_vow = max(max_vow, freqs[i])
else:
max_con = max(max_con, freqs[i])
return max_vow + max_con
4.7.291 - 2025-09-12 21:22:49 +0300 MSK
Links
Code
class Solution:
def doesAliceWin(self, s: str) -> bool:
return any(c in "aeiou" for c in s)
4.7.292 - 2025-09-11 20:29:02 +0300 MSK
Links
Code
class Solution:
def sortVowels(self, s: str) -> str:
vowels = []
s_list = list(s)
# collect all vowels
for i in s_list:
if i in "AEIOUaeiou":
vowels.append(i)
if vowels == []:
return s
# sort the vowels
vowels.sort()
count = 0
# replace original vowels with sorted ones
for j in range(len(s)):
if s_list[j] in "AEIOUaeiou":
s_list[j] = vowels[count]
count += 1
return "".join(s_list)
4.7.293 - 2025-09-10 18:11:04 +0300 MSK
Links
Code
class Solution:
def minimumTeachings(
self, n: int, languages: List[List[int]], friendships: List[List[int]]
) -> int:
cncon = set()
for friendship in friendships:
mp = {}
conm = False
for lan in languages[friendship[0] - 1]:
mp[lan] = 1
for lan in languages[friendship[1] - 1]:
if lan in mp:
conm = True
break
if not conm:
cncon.add(friendship[0] - 1)
cncon.add(friendship[1] - 1)
max_cnt = 0
cnt = [0] * (n + 1)
for friendship in cncon:
for lan in languages[friendship]:
cnt[lan] += 1
max_cnt = max(max_cnt, cnt[lan])
return len(cncon) - max_cnt
4.7.294 - 2025-09-09 18:44:51 +0300 MSK
Links
Code
class Solution:
def peopleAwareOfSecret(self, n: int, delay: int, forget: int) -> int:
know, share = deque([(1, 1)]), deque([])
know_cnt, share_cnt = 1, 0
for i in range(2, n + 1):
if know and know[0][0] == i - delay:
know_cnt -= know[0][1]
share_cnt += know[0][1]
share.append(know[0])
know.popleft()
if share and share[0][0] == i - forget:
share_cnt -= share[0][1]
share.popleft()
if share:
know_cnt += share_cnt
know.append((i, share_cnt))
return (know_cnt + share_cnt) % (10**9 + 7)
4.7.295 - 2025-09-08 18:09:53 +0300 MSK
Links
Code
class Solution:
def getNoZeroIntegers(self, n: int) -> List[int]:
for A in range(1, n):
B = n - A
if "0" not in str(A) + str(B):
return [A, B]
return []
4.7.296 - 2025-09-07 11:16:52 +0300 MSK
Links
Code
class Solution:
def minOperations(self, nums: List[int]) -> int:
num1 = nums[0]
for num in nums[1:]:
if num != num1:
return 1
return 0
4.7.297 - 2025-09-07 11:00:41 +0300 MSK
Links
Code
class Solution:
def sumZero(self, n: int) -> List[int]:
res = []
for i in range(1, n, 2):
res.extend((i, -i))
if len(res) < n:
res.append(0)
return res
4.7.298 - 2025-09-06 17:38:19 +0300 MSK
Links
Code
class Solution:
def get(self, num: int) -> int:
i = 1
base = 1
cnt = 0
while base <= num:
cnt += ((i + 1) // 2) * (min(base * 2 - 1, num) - base + 1)
i += 1
base *= 2
return cnt
def minOperations(self, queries: List[List[int]]) -> int:
res = 0
for q in queries:
res += (self.get(q[1]) - self.get(q[0] - 1) + 1) // 2
return res
4.7.299 - 2025-09-05 19:23:51 +0300 MSK
Links
Code
class Solution:
def makeTheIntegerZero(self, num1: int, num2: int) -> int:
k = 1
while True:
x = num1 - num2 * k
if x < k:
return -1
if k >= x.bit_count():
return k
k += 1
4.7.300 - 2025-09-04 22:15:30 +0300 MSK
Links
Code
class Solution:
def findClosest(self, x: int, y: int, z: int) -> int:
dxz = abs(x - z)
dyz = abs(y - z)
if dxz < dyz:
return 1
elif dxz > dyz:
return 2
else:
return 0
4.7.301 - 2025-09-03 18:20:51 +0300 MSK
Links
Code
class Solution:
def numberOfPairs(self, points: List[List[int]]) -> int:
ans = 0
points.sort(key=lambda x: (x[0], -x[1]))
for i in range(len(points) - 1):
pointA = points[i]
xMin = pointA[0] - 1
xMax = math.inf
yMin = -math.inf
yMax = pointA[1] + 1
for j in range(i + 1, len(points)):
pointB = points[j]
if (
pointB[0] > xMin
and pointB[0] < xMax
and pointB[1] > yMin
and pointB[1] < yMax
):
ans += 1
xMin = pointB[0]
yMin = pointB[1]
return ans
4.7.302 - 2025-09-02 20:18:23 +0300 MSK
Links
Code
class Solution:
def numberOfPairs(self, points: List[List[int]]) -> int:
ans = 0
n = len(points)
for i in range(n):
pointA = points[i]
for j in range(n):
pointB = points[j]
if i == j or not (
pointA[0] <= pointB[0] and pointA[1] >= pointB[1]
):
continue
if n == 2:
ans += 1
continue
illegal = False
for k in range(n):
if k == i or k == j:
continue
pointTmp = points[k]
isXContained = (
pointTmp[0] >= pointA[0] and pointTmp[0] <= pointB[0]
)
isYContained = (
pointTmp[1] <= pointA[1] and pointTmp[1] >= pointB[1]
)
if isXContained and isYContained:
illegal = True
break
if not illegal:
ans += 1
return ans
4.7.303 - 2025-09-01 17:35:05 +0300 MSK
Links
Code
class Solution:
def maxAverageRatio(self, classes: List[List[int]], extraStudents: int) -> float:
n = len(classes)
res = 0
for i in range(n):
pass_, total = classes[i]
profit = ((pass_ + 1) / (total + 1)) - (pass_ / total)
classes[i] = (-profit, pass_, total)
heapq.heapify(classes)
while classes and extraStudents > 0:
_, pass_, total = heapq.heappop(classes)
if pass_ == total:
res += 1
else:
pass_ += 1
total += 1
profit = ((pass_ + 1) / (total + 1)) - (pass_ / total)
heapq.heappush(classes, (-profit, pass_, total))
extraStudents -= 1
for _, pass_, total in classes:
res += pass_ / total
return res / n
4.7.304 - 2025-08-31 15:07:32 +0300 MSK
Links
Code
class Solution:
def solveSudoku(self, board: list[list[str]]) -> None:
n, N = 3, 9
rows = [[0] * (N + 1) for _ in range(N)]
cols = [[0] * (N + 1) for _ in range(N)]
boxes = [[0] * (N + 1) for _ in range(N)]
sudokuSolved = False
def couldPlace(d, row, col):
idx = (row // n) * n + col // n
return (rows[row][d] + cols[col][d] + boxes[idx][d]) == 0
def placeNumber(d, row, col):
idx = (row // n) * n + col // n
rows[row][d] += 1
cols[col][d] += 1
boxes[idx][d] += 1
board[row][col] = str(d)
def removeNumber(d, row, col):
idx = (row // n) * n + col // n
rows[row][d] -= 1
cols[col][d] -= 1
boxes[idx][d] -= 1
board[row][col] = '.'
def placeNextNumbers(row, col):
nonlocal sudokuSolved
if row == N - 1 and col == N - 1:
sudokuSolved = True
elif col == N - 1:
backtrack(row + 1, 0)
else:
backtrack(row, col + 1)
def backtrack(row, col):
nonlocal sudokuSolved
if board[row][col] == '.':
for d in range(1, 10):
if couldPlace(d, row, col):
placeNumber(d, row, col)
placeNextNumbers(row, col)
if not sudokuSolved:
removeNumber(d, row, col)
else:
placeNextNumbers(row, col)
for i in range(N):
for j in range(N):
if board[i][j] != '.':
placeNumber(int(board[i][j]), i, j)
backtrack(0, 0)
4.7.305 - 2025-08-31 14:18:46 +0300 MSK
Links
Code
class Solution:
def recoverOrder(self, order: List[int], friends: List[int]) -> List[int]:
for i in range(len(order)):
if order[i] in friends:
order[i] = (i, order[i])
else:
order[i] = (101, 101)
order.sort()
while order[-1] == (101, 101):
order.pop()
for i in range(len(order)):
order[i] = order[i][1]
return order
4.7.306 - 2025-08-31 14:13:40 +0300 MSK
Links
Code
class Solution:
def getLeastFrequentDigit(self, n: int) -> int:
freqs = [0] * 10
while n > 0:
freqs[n % 10] += 1
n //= 10
min_freq, min_num = math.inf, -math.inf
for i in range(10):
if freqs[i] != 0 and (
freqs[i] < min_freq or (freqs[i] == min_freq and i < min_num)
):
min_freq, min_num = freqs[i], i
return min_num
4.7.307 - 2025-08-30 20:16:00 +0300 MSK
Links
Code
class Solution:
def isValidSudoku(self, board: List[List[str]]) -> bool:
rows = [[False] * 9 for _ in range(9)]
cols = [[False] * 9 for _ in range(9)]
boxes = [[False] * 9 for _ in range(9)]
for i in range(9):
for j in range(9):
if board[i][j] != '.':
num = ord(board[i][j]) - ord('1')
boxIndex = (i // 3) * 3 + (j // 3)
if rows[i][num] or cols[j][num] or boxes[boxIndex][num]:
return False
rows[i][num] = cols[j][num] = boxes[boxIndex][num] = True
return True
4.7.308 - 2025-08-29 19:59:52 +0300 MSK
Links
Code
class Solution:
def flowerGame(self, n: int, m: int) -> int:
return (m * n) // 2
4.7.309 - 2025-08-28 16:59:23 +0300 MSK
Links
Code
class Solution:
def sortMatrix(self, grid: List[List[int]]) -> List[List[int]]:
n = len(grid)
for i in range(n):
tmp = [grid[i + j][j] for j in range(n - i)]
tmp.sort(reverse=True)
for j in range(n - i):
grid[i + j][j] = tmp[j]
for j in range(1, n):
tmp = [grid[i][j + i] for i in range(n - j)]
tmp.sort()
for i in range(n - j):
grid[i][j + i] = tmp[i]
return grid
4.7.310 - 2025-08-27 16:22:50 +0300 MSK
Links
Code
class Solution:
def lenOfVDiagonal(self, grid: List[List[int]]) -> int:
DIRS = [(1, 1), (1, -1), (-1, -1), (-1, 1)]
m, n = len(grid), len(grid[0])
@cache
def dfs(cx, cy, direction, turn, target):
nx, ny = cx + DIRS[direction][0], cy + DIRS[direction][1]
# If it goes beyond the boundary or the next node's value is not the target value, then return
if nx < 0 or ny < 0 or nx >= m or ny >= n or grid[nx][ny] != target:
return 0
turn_int = 1 if turn else 0
# Continue walking in the original direction.
max_step = dfs(nx, ny, direction, turn, 2 - target)
if turn:
# Clockwise rotate 90 degrees turn
max_step = max(
max_step,
dfs(nx, ny, (direction + 1) % 4, False, 2 - target),
)
return max_step + 1
res = 0
for i in range(m):
for j in range(n):
if grid[i][j] == 1:
for direction in range(4):
res = max(res, dfs(i, j, direction, True, 2) + 1)
return res
4.7.311 - 2025-08-26 09:10:25 +0300 MSK
Links
Code
class Solution:
def myAtoi(self, s: str) -> int:
digits = []
sign = None
found_dig = False
for char in s:
if char.isdigit():
digits.append(int(char))
found_dig = True
elif not found_dig and sign is None and char == " ":
continue
elif not found_dig and sign is None and char in ("+", "-"):
sign = 1
if char == "-":
sign = -1
else:
break
if sign is None:
sign = 1
res = 0
cnt = 0
while digits:
res += digits.pop() * (10 ** cnt)
cnt += 1
if res > 2 ** 31 - 1 and sign == 1:
return 2 ** 31 - 1
elif res > 2 ** 31 and sign == -1:
return -(2 ** 31)
return res * sign
4.7.312 - 2025-08-26 08:16:39 +0300 MSK
Links
Code
class Solution:
def reverse(self, x: int) -> int:
digits = []
neg = 1
if x < 0:
neg = -1
x = -x
while x > 0:
digits.append(x % 10)
x //= 10
cnt, res = 0, 0
while digits:
res += digits.pop() * (10 ** cnt)
cnt += 1
if res > 2 ** 31:
return 0
return res * neg
4.7.313 - 2025-08-26 08:11:15 +0300 MSK
Links
Code
class Solution:
def areaOfMaxDiagonal(self, dimensions: List[List[int]]) -> int:
max_diag, max_area = 0, 0
for ln, wdth in dimensions:
diag, area = ln ** 2 + wdth ** 2, ln * wdth
if diag > max_diag or (diag == max_diag and area > max_area):
max_diag, max_area = diag, area
return max_area
4.7.314 - 2025-08-25 17:00:38 +0300 MSK
Links
Code
class MyCalendar:
def __init__(self):
self.events = SortedList()
def book(self, startTime: int, endTime: int) -> bool:
insert_index = self.events.bisect_left((startTime, endTime))
if (
insert_index - 1 >= 0
and startTime < self.events[insert_index - 1][1]
) or (
insert_index < len(self.events)
and self.events[insert_index][0] < endTime
):
return False
self.events.add((startTime, endTime))
return True
# Your MyCalendar object will be instantiated and called as such:
# obj = MyCalendar()
# param_1 = obj.book(startTime,endTime)
4.7.315 - 2025-08-25 11:40:44 +0300 MSK
Links
Code
class Solution:
def findDiagonalOrder(self, mat: List[List[int]]) -> List[int]:
res, rows, cols, cur = [], len(mat), len(mat[0]), []
for i in range(rows + cols):
if i < rows:
row, col = i, 0
else:
row, col = rows - 1, (i - rows) + 1
while row >= 0 and col < cols:
cur.append(mat[row][col])
row, col = row - 1, col + 1
if i % 2 != 0:
cur.reverse()
res.extend(cur)
cur.clear()
return res
4.7.316 - 2025-08-24 20:51:14 +0300 MSK
Links
Code
class MyCircularQueue:
def __init__(self, k: int):
self._k = k
self._q = [-1] * k
self._i = 0
self._len = 0
def enQueue(self, value: int) -> bool:
if self.isFull():
return False
self._q[self._i] = value
self._i = (self._i + 1) % self._k
self._len += 1
return True
def deQueue(self) -> bool:
if self._len > 0:
self._len -= 1
return True
return False
def Front(self) -> int:
if self.isEmpty():
return -1
return self._q[(self._i - self._len + self._k) % self._k]
def Rear(self) -> int:
if self.isEmpty():
return -1
return self._q[(self._i - 1 + self._k) % self._k]
def isEmpty(self) -> bool:
return self._len == 0
def isFull(self) -> bool:
return self._len == self._k
# Your MyCircularQueue object will be instantiated and called as such:
# obj = MyCircularQueue(k)
# param_1 = obj.enQueue(value)
# param_2 = obj.deQueue()
# param_3 = obj.Front()
# param_4 = obj.Rear()
# param_5 = obj.isEmpty()
# param_6 = obj.isFull()
4.7.317 - 2025-08-24 19:54:22 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Codec:
def serialize(self, root: Optional[TreeNode]) -> str:
"""Encodes a tree to a single string.
"""
if root is None:
return ""
left, right = self.serialize(root.left), self.serialize(root.right)
return f"{root.val}|{len(left)}|{left}{right}"
def deserialize(self, data: str) -> Optional[TreeNode]:
"""Decodes your encoded data to tree.
"""
if not data:
return None
val, left_len, rest = data.split("|", 2)
root = TreeNode(int(val))
root.left = self.deserialize(rest[:int(left_len)])
root.right = self.deserialize(rest[int(left_len):])
return root
# Your Codec object will be instantiated and called as such:
# Your Codec object will be instantiated and called as such:
# ser = Codec()
# deser = Codec()
# tree = ser.serialize(root)
# ans = deser.deserialize(tree)
# return ans
4.7.318 - 2025-08-24 19:38:13 +0300 MSK
Links
Code
class Solution:
def __init__(self, nums: List[int]):
self._orig = nums
self._cur = nums.copy()
def reset(self) -> List[int]:
return self._orig
def shuffle(self) -> List[int]:
return random.sample(self._orig, k=len(self._orig))
# Your Solution object will be instantiated and called as such:
# obj = Solution(nums)
# param_1 = obj.reset()
# param_2 = obj.shuffle()
4.7.319 - 2025-08-24 19:30:45 +0300 MSK
Links
Code
class Solution:
def maxHeightOfTriangle(self, red: int, blue: int) -> int:
return max(self.helper(red, blue), self.helper(blue, red))
def helper(self, red: int, blue: int) -> int:
h = 0
i = 1
while True:
if i % 2 == 1:
if red >= i:
red -= i
else:
break
else:
if blue >= i:
blue -= i
else:
break
h += 1
i += 1
return h
4.7.320 - 2025-08-24 19:28:22 +0300 MSK
Links
Code
class Solution:
def incremovableSubarrayCount(self, nums: List[int]) -> int:
result = 0
n = len(nums)
if n == 0:
return 0
prefix_idx, suffix_idx = 0, n - 1
while prefix_idx + 1 < n and nums[prefix_idx + 1] > nums[prefix_idx]:
prefix_idx += 1
if prefix_idx == n - 1:
return (n * (n + 1)) // 2
while suffix_idx > 0 and nums[suffix_idx] > nums[suffix_idx - 1]:
suffix_idx -= 1
result += prefix_idx + 1
result += n - suffix_idx + 1
i = 0
j = suffix_idx
while i <= prefix_idx:
while j < n and nums[i] >= nums[j]:
j += 1
result += n - j
i += 1
return result
4.7.321 - 2025-08-24 19:26:17 +0300 MSK
Links
Code
class Solution:
def gcdOfOddEvenSums(self, n: int) -> int:
odd_num = 1 + (n - 1) * 2
even_num = 2 + (n - 1) * 2
odd_sum = (n * (1 + odd_num)) // 2
even_sum = (n * (2 + even_num)) // 2
return math.gcd(odd_sum, even_sum)
4.7.322 - 2025-08-24 19:18:26 +0300 MSK
Links
Code
class Solution:
def reverseSubmatrix(self, grid: List[List[int]], x: int, y: int, k: int) -> List[List[int]]:
rows, cols = len(grid), len(grid[0])
for col in range(y, y + k):
for row_dlt in range(k // 2):
row1 = x + row_dlt
row2 = (x + k - 1) - row_dlt
grid[row1][col], grid[row2][col] = grid[row2][col], grid[row1][col]
return grid
4.7.323 - 2025-08-24 19:07:06 +0300 MSK
Links
Code
SELECT r.book_id,
b.title,
b.author,
b.genre,
b.pages,
Max(r.session_rating) - Min(r.session_rating) rating_spread,
Round(( Sum(CASE WHEN r.session_rating < 3 THEN 1 ELSE 0 END + CASE WHEN
r.session_rating >
3 THEN 1 ELSE 0 END) ) / COUNT(r.session_id) ::
Decimal(10, 2), 2) polarization_score
FROM reading_sessions r
INNER JOIN books b USING(book_id)
GROUP BY r.book_id,
b.title,
b.author,
b.genre,
b.pages
HAVING COUNT(r.session_id) > 4
AND Max(r.session_rating) > 3
AND Min(r.session_rating) < 3
AND Round(( Sum(CASE WHEN r.session_rating < 3 THEN 1 ELSE 0 END + CASE
WHEN
r.session_rating >
3 THEN 1 ELSE 0 END) ) / COUNT(r.session_id)
::
Decimal(
10, 2), 2) >= 0.6
ORDER BY polarization_score desc,
b.title desc
4.7.324 - 2025-08-24 19:02:12 +0300 MSK
Links
Code
class Solution:
def isTrionic(self, nums: List[int]) -> bool:
seg, n = 0, len(nums)
for i in range(1, n):
cur, prv = nums[i], nums[i - 1]
if cur == prv:
return False
if seg == 0:
if cur < prv:
if i == 1:
return False
seg = 1
elif seg == 1:
if cur > prv:
seg = 2
elif seg == 2:
if cur < prv:
return False
return seg == 2
4.7.325 - 2025-08-24 18:57:13 +0300 MSK
Links
Code
from typing import List
class Solution:
def earliestFinishTime(self,landStartTime: List[int],landDuration: List[int],waterStartTime: List[int],waterDuration: List[int]) -> int:
res = float('inf')
n, m = len(landStartTime), len(waterStartTime)
for i in range(n):
a, d = landStartTime[i], landDuration[i]
for j in range(m):
b, e = waterStartTime[j], waterDuration[j]
land_end = a + d
start_water = max(land_end, b)
finish1 = start_water + e
water_end = b + e
start_land = max(water_end, a)
finish2 = start_land + d
res = min(res, finish1, finish2)
return res
4.7.326 - 2025-08-24 18:52:47 +0300 MSK
Links
Code
class Solution:
def checkDivisibility(self, n: int) -> bool:
sm, pr, num = 0, 1, n
while num > 0:
dig = num % 10
num //= 10
sm += dig
pr *= dig
return n % (sm + pr) == 0
4.7.327 - 2025-08-24 18:50:32 +0300 MSK
Links
Code
class Solution:
def validateCoupons(self, code: List[str], businessLine: List[str], isActive: List[bool]) -> List[str]:
res, n = [], len(code)
b_order = {"electronics": 0, "grocery": 1, "pharmacy": 2, "restaurant": 3}
for i in range(n):
if (
isActive[i]
and code[i]
and re.match("^[a-zA-Z0-9_]+$", code[i])
and businessLine[i] in (
"electronics", "grocery", "pharmacy", "restaurant"
)
):
res.append(i)
def sort(i: int) -> tuple[str, str]:
return (b_order[businessLine[i]], code[i])
res.sort(key=sort)
for i in range(len(res)):
res[i] = code[res[i]]
return res
4.7.328 - 2025-08-24 18:39:15 +0300 MSK
Links
Code
class Solution:
def concatHex36(self, n: int) -> str:
res = []
for num, base in ((n ** 3, 36), (n ** 2, 16)):
while num > 0:
dig = num % base
if dig < 10:
res.append(str(dig))
else:
res.append(chr((dig - 10) + 65))
num //= base
res.reverse()
return "".join(res)
4.7.329 - 2025-08-24 18:38:15 +0300 MSK
Links
Code
class Solution:
def concatHex36(self, n: int) -> str:
res, cur = [], []
for num, base in ((n ** 2, 16), (n ** 3, 36)):
while num > 0:
dig = num % base
if dig < 10:
cur.append(str(dig))
else:
cur.append(chr((dig - 10) + 65))
num //= base
cur.reverse()
res.extend(cur)
cur.clear()
return "".join(res)
4.7.330 - 2025-08-24 18:22:04 +0300 MSK
Links
Code
class Solution:
def checkPrimeFrequency(self, nums: List[int]) -> bool:
def is_prime(v: int) -> bool:
for i in range(2, int(math.sqrt(v)) + 1):
if v % i == 0:
return False
return True
freqs = [0] * 101
for num in nums:
freqs[num] += 1
for freq in freqs:
if freq > 1 and is_prime(freq):
return True
return False
4.7.331 - 2025-08-24 18:15:48 +0300 MSK
Links
Code
class Solution:
def generateTag(self, caption: str) -> str:
res, n, cur = [], len(caption), []
for i in range(n):
ch = caption[i]
if ch.isalpha():
cur.append(ch.lower())
if (ch == " " or i + 1 == n) and cur:
if res:
cur[0] = cur[0].upper()
res.append("".join(cur))
cur.clear()
return "".join(itertools.chain("#", res))[:100]
4.7.332 - 2025-08-24 18:07:04 +0300 MSK
Links
Code
SELECT
book_id,
MAX(title) AS title,
MAX(author) AS author,
MAX(genre) AS genre,
MAX(publication_year) AS publication_year,
MAX(total_copies) AS current_borrowers
FROM
(
SELECT
book_id,
title,
author,
genre,publication_year,
total_copies,
total_copies AS total_remain
FROM
library_books
UNION
ALL
SELECT
book_id,
'',
'',
'',
1000,
0,
-1
FROM
borrowing_records
WHERE
return_date IS NULL
) sub
GROUP BY
book_id
HAVING
SUM(total_remain) = 0
ORDER BY
current_borrowers DESC,
title;
4.7.333 - 2025-08-24 18:01:04 +0300 MSK
Links
Code
class Solution:
def minCuttingCost(self, n: int, m: int, k: int) -> int:
ans = 0
if m <= k and n <= k:
return 0
if m > k and n <= k:
ans += (m - k) * k
if n > k and m <= k:
ans += (n - k) * k
return ans
4.7.334 - 2025-08-24 17:55:59 +0300 MSK
Links
Code
class Solution:
def smallestIndex(self, nums: List[int]) -> int:
for i in range(len(nums)):
num = nums[i]
sm = 0
while num > 0:
sm += num % 10
num //= 10
if sm == i:
return i
return -1
4.7.335 - 2025-08-24 17:54:29 +0300 MSK
Links
Code
class Solution:
def minDeletion(self, s: str, k: int) -> int:
freqs, n = [0] * 26, len(s)
for i in range(n):
freqs[ord(s[i]) - 97] += 1
freqs.sort()
res = 0
for i in range(26 - k):
res += freqs[i]
return res
4.7.336 - 2025-08-24 17:52:40 +0300 MSK
Links
Code
class Solution:
def minDeletion(self, s: str, k: int) -> int:
freqs, n = [0] * 26, len(s)
for i in range(n):
freqs[ord(s[i]) - 97] += 1
freqs.sort(reverse=True)
res = 0
while len(freqs) > k:
res += freqs.pop()
return res
4.7.337 - 2025-08-24 17:46:18 +0300 MSK
Links
Code
class Solution:
def maxFreqSum(self, s: str) -> int:
freqs, n = [0] * 26, len(s)
for i in range(n):
freqs[ord(s[i]) - 97] += 1
max_vow, max_con = 0, 0
vow = tuple(ord(ch) - 97 for ch in ("a", "e", "i", "o", "u"))
for i in range(26):
if i in vow:
max_vow = max(max_vow, freqs[i])
else:
max_con = max(max_con, freqs[i])
return max_vow + max_con
4.7.338 - 2025-08-24 17:42:32 +0300 MSK
Links
Code
class Solution:
def maxProduct(self, n: int) -> int:
num1, num2 = -math.inf, -math.inf
while n > 0:
dig = n % 10
if dig > num2:
num1, num2 = num2, dig
elif dig > num1:
num1 = dig
n //= 10
return num1 * num2
4.7.339 - 2025-08-24 17:41:29 +0300 MSK
Links
Code
class Solution:
def maxProduct(self, n: int) -> int:
dig = []
while n > 0:
heapq.heappush(dig, -(n % 10))
n //= 10
return abs(heapq.heappop(dig) * heapq.heappop(dig))
4.7.340 - 2025-08-24 17:40:23 +0300 MSK
Links
Code
class Solution:
def findClosest(self, x: int, y: int, z: int) -> int:
diff1, diff2 = abs(z - x), abs(z - y)
if diff1 == diff2:
return 0
if diff1 < diff2:
return 1
return 2
4.7.341 - 2025-08-24 17:38:35 +0300 MSK
Links
Code
class Solution:
def minOperations(self, nums: List[int], k: int) -> int:
return sum(nums) % k
4.7.342 - 2025-08-24 17:36:34 +0300 MSK
Links
Code
class Solution:
def minimumPairRemoval(self, nums: List[int], ans = 0) -> int:
def notSorted(nums: List[int]) -> bool:
for a, b in pairwise(nums):
if a > b:
return True
return False
while notSorted(nums):
minSum, mnIdx = inf, -1
for i, pair in enumerate(pairwise(nums)):
if sum(pair) < minSum:
minSum, mnIdx, delIdx = sum(pair), i, i + 1
nums[mnIdx] = minSum
del nums[delIdx]
ans += 1
return ans
4.7.343 - 2025-08-24 17:22:24 +0300 MSK
Links
Code
class Solution:
def minCosts(self, cost: List[int]) -> List[int]:
return list(accumulate(cost, min))
4.7.344 - 2025-08-24 17:12:42 +0300 MSK
Links
Code
class Solution:
def reverseDegree(self, s: str) -> int:
res, n = 0, len(s)
for i in range(n):
res += (i + 1) * (26 - (ord(s[i]) - 97))
return res
4.7.345 - 2025-08-24 17:10:49 +0300 MSK
Links
Code
class Solution:
def maxContainers(self, n: int, w: int, maxWeight: int) -> int:
return min(maxWeight // w, n * n)
4.7.346 - 2025-08-24 17:08:09 +0300 MSK
Links
Code
class Solution:
def totalNumbers(self, digits: List[int]) -> int:
enc = set()
p = [a * 100 + b * 10 + c for a, b, c in itertools.permutations(digits, 3)]
for num in p:
if num not in enc and len(str(num)) == 3:
if num % 2 == 0:
enc.add(num)
return len(enc)
4.7.347 - 2025-08-24 17:02:11 +0300 MSK
Links
Code
class Solution:
def largestInteger(self, nums: List[int], k: int) -> int:
n = len(nums)
subarray_count = defaultdict(int)
for i in range(n - k + 1):
for num in set(nums[i:i+k]):
subarray_count[num] += 1
res = -1
for num, count in subarray_count.items():
if count == 1:
res = max(res, num)
return res
4.7.348 - 2025-08-24 16:02:46 +0300 MSK
Links
Code
class Solution:
def transformArray(self, nums: List[int]) -> List[int]:
for i in range(len(nums)):
val = nums[i]
if val % 2 == 0:
nums[i] = 0
else:
nums[i] = 1
nums.sort()
return nums
4.7.349 - 2025-08-24 16:00:53 +0300 MSK
Links
Code
SELECT
*
FROM
Products
WHERE
description ~ '\mSN[0-9]{4}-[0-9]{4}\M'
ORDER BY
product_id ASC;
4.7.350 - 2025-08-24 15:55:14 +0300 MSK
Links
Code
class Solution:
def hasSameDigits(self, s: str) -> bool:
stack = list(map(int, s))
stack.reverse()
while len(stack) > 2:
prev = stack.pop()
for i in reversed(range(len(stack))):
stack[i], prev = (prev + stack[i]) % 10, stack[i]
return stack[0] == stack[1]
4.7.351 - 2025-08-24 15:40:47 +0300 MSK
Links
Code
class Solution:
def hasSpecialSubstring(self, s: str, k: int) -> bool:
cnt, n = 0, len(s)
for i in range(n):
if i > 0 and s[i] == s[i - 1]:
cnt += 1
else:
cnt = 1
if cnt != k:
continue
if (
i - cnt >= 0 and s[i - cnt] == s[i]
) or (
i + 1 < n and s[i + 1] == s[i]
):
cnt = 1
else:
return True
return False
4.7.352 - 2025-08-24 15:35:22 +0300 MSK
Links
Code
class Solution:
def sumOfGoodNumbers(self, nums: List[int], k: int) -> int:
res, n = 0, len(nums)
for i in range(n):
left, right, cur = -1, -1, nums[i]
if i - k >= 0:
left = nums[i - k]
if i + k < n:
right = nums[i + k]
if left < cur > right:
res += cur
return res
4.7.353 - 2025-08-24 15:32:58 +0300 MSK
Links
Code
class Solution:
def maxDifference(self, s: str) -> int:
freqs, n = [0] * 26, len(s)
for i in range(n):
freqs[ord(s[i]) - 97] += 1
max_odd, min_even = -math.inf, math.inf
for i in range(26):
freq = freqs[i]
if freq == 0:
continue
if freq % 2 == 0:
min_even = min(min_even, freq)
else:
max_odd = max(max_odd, freq)
return max_odd - min_even
4.7.354 - 2025-08-24 15:21:21 +0300 MSK
Links
Code
class Solution:
def findValidPair(self, s: str) -> str:
freqs, n = [0] * 10, len(s)
for i in range(n):
freqs[int(s[i])] += 1
for i in range(1, n):
cur, prv = int(s[i]), int(s[i - 1])
if cur != prv and freqs[cur] == cur and freqs[prv] == prv:
return f"{prv}{cur}"
return ""
4.7.355 - 2025-08-24 15:17:24 +0300 MSK
Links
Code
SELECT
user_id,
email
FROM
users
WHERE
email ~ '^\w+@[A-Za-z]+\.com$'
ORDER BY
user_id ASC;
4.7.356 - 2025-08-24 15:14:50 +0300 MSK
Links
Code
class Solution:
def countPartitions(self, nums: List[int]) -> int:
sm, n = [0] * len(nums), len(nums)
sm[0] = nums[0]
for i in range(n):
sm[i] = sm[i - 1] + nums[i]
res = 0
for i in range(n - 1):
left = sm[i]
right = sm[-1] - left
res += abs(right - left) % 2 == 0
return res
4.7.357 - 2025-08-24 15:11:09 +0300 MSK
Links
Code
class Solution:
def subarraySum(self, nums: List[int]) -> int:
sm, n = [0] * len(nums), len(nums)
sm[0] = nums[0]
for i in range(1, n):
sm[i] = sm[i - 1] + nums[i]
res = 0
for i in range(n):
left = max(0, i - nums[i])
left_sum = 0
if left > 0:
left_sum = sm[left - 1]
res += sm[i] - left_sum
return res
4.7.358 - 2025-08-24 15:07:53 +0300 MSK
Links
Code
class Solution:
def maxAdjacentDistance(self, nums: List[int]) -> int:
res = abs(nums[0] - nums[-1])
for i in range(1, len(nums)):
res = max(res, abs(nums[i] - nums[i - 1]))
return res
4.7.359 - 2025-08-24 15:06:30 +0300 MSK
Links
Code
class Solution:
def zigzagTraversal(self, grid: List[List[int]]) -> List[int]:
m, n = len(grid), len(grid[0])
res = []
skip = False
for row in range(m):
if row % 2 == 0:
start, end, step = 0, n, 1
else:
start, end, step = n - 1, -1, -1
for col in range(start, end, step):
if not skip:
res.append(grid[row][col])
skip = not skip
return res
4.7.360 - 2025-08-24 15:00:31 +0300 MSK
Links
Code
class Solution:
def maxLength(self, A: List[int]) -> int:
N = len(A)
ans = 2
last = {}
i = 0
for j, x in enumerate(A):
for p in prime_divisors(x):
i = max(i, last.get(p, -1) + 1)
last[p] = j
ans = max(ans, j - i + 1)
return ans
def prime_divisors(x):
d = 2
while d * d <= x:
if x % d == 0:
x //= d
while x % d == 0:
x //= d
yield d
d += 1 + d & 1
if x > 1:
yield x
4.7.361 - 2025-08-24 14:57:30 +0300 MSK
Links
Code
class Solution:
def hasMatch(self, string: str, pattern: str) -> bool:
left_part, right_part = pattern.split("*")
left_idx = string.find(left_part)
right_idx = string.find(right_part, left_idx + len(left_part))
return left_idx != -1 and right_idx != -1
4.7.362 - 2025-08-24 14:47:52 +0300 MSK
Links
Code
class Solution:
def minimumOperations(self, grid: List[List[int]]) -> int:
m, n = len(grid), len(grid[0])
res = 0
for col in range(n):
prv = grid[0][col]
for row in range(1, m):
val = grid[row][col]
if val > prv:
prv = val
else:
diff = (prv + 1) - val
res += diff
prv += 1
return res
4.7.363 - 2025-08-24 14:42:38 +0300 MSK
Links
Code
class Solution:
def minimumOperations(self, nums: List[int]) -> int:
freqs, n = [0] * 101, len(nums)
for i in range(n):
freqs[nums[i]] += 1
res = 0
for i in range(0, n, 3):
if max(freqs) == 1:
return res
res += 1
for j in range(i, min(i + 3, n)):
freqs[nums[j]] -= 1
return res
4.7.364 - 2025-08-24 14:38:49 +0300 MSK
Links
Code
class Solution:
def countSubarrays(self, nums: List[int]) -> int:
res, n = 0, len(nums)
for i in range(n - 2):
if nums[i] + nums[i + 2] == nums[i + 1] / 2:
res += 1
return res
4.7.365 - 2025-08-24 14:36:54 +0300 MSK
Links
Code
class Solution:
def buttonWithLongestTime(self, events: List[List[int]]) -> int:
(mx_idx, mx_time), n = events[0], len(events)
for i in range(n):
(cur_idx, cur_time), (prv_idx, prv_time) = events[i], events[i - 1]
diff = cur_time - prv_time
if diff > mx_time or (diff == mx_time and cur_idx < mx_idx):
mx_idx, mx_time = cur_idx, diff
return mx_idx
4.7.366 - 2025-08-24 14:33:39 +0300 MSK
Links
Code
class Solution:
def constructTransformedArray(self, nums: List[int]) -> List[int]:
n = len(nums)
res = [0] * n
for i in range(n):
num = nums[i]
if num == 0:
val = 0
elif num > 0:
val = nums[(i + num) % n]
else:
val = nums[(i - -num + n) % n]
res[i] = val
return res
4.7.367 - 2025-08-24 14:28:25 +0300 MSK
Links
Code
class Solution:
def smallestNumber(self, n: int) -> int:
res = 0
while n > 0:
res = (res << 1) | 1
n //= 2
return res
4.7.368 - 2025-08-24 14:25:47 +0300 MSK
Links
Code
class Solution:
def minimumSumSubarray(self, nums: List[int], l: int, r: int) -> int:
sm, n = [0] * len(nums), len(nums)
cur = 0
for i in range(n):
cur += nums[i]
sm[i] = cur
res = math.inf
for i in range(n):
left = 0
if i > 0:
left = sm[i - 1]
for j in range(i + l - 1, min(i + r, n)):
cur = sm[j] - left
if cur > 0:
res = min(res, cur)
if res == math.inf:
return -1
return res
4.7.369 - 2025-08-24 14:09:37 +0300 MSK
Links
Code
class Solution:
def canAliceWin(self, n: int) -> bool:
cnt = 10
while True:
if n >= cnt:
n -= cnt
cnt -= 1
else:
return False
if n >= cnt:
n -= cnt
cnt -= 1
else:
return True
4.7.370 - 2025-08-24 14:03:51 +0300 MSK
Links
Code
class Solution:
def countValidSelections(self, nums: List[int]) -> int:
n, res = len(nums), 0
left, right = [0 for _ in range(n)], [0 for _ in range(n)]
for i in range(1, n):
left[i] = left[i - 1] + nums[i - 1]
right[-i - 1] = right[-i] + nums[-i]
for i, num in enumerate(nums):
if num != 0: continue
if left[i] == right[i]: res += 2
if abs(left[i] - right[i]) == 1: res += 1
return res
4.7.371 - 2025-08-24 13:57:16 +0300 MSK
Links
Code
class Solution:
def hasIncreasingSubarrays(self, nums: List[int], k: int) -> bool:
n = len(nums)
cnt = 1
prv_cnt = 0
for i in range(1, n):
cur, prv = nums[i], nums[i - 1]
if cur > prv:
cnt += 1
else:
prv_cnt, cnt = cnt, 1
if cnt >= 2 * k or prv_cnt >= k and cnt >= k:
return True
return False
4.7.372 - 2025-08-24 13:46:58 +0300 MSK
Links
Code
class Solution:
def smallestNumber(self, n: int, t: int) -> int:
while True:
cur = n
prd = 1
while cur > 0:
prd *= cur % 10
if prd == 0:
break
cur //= 10
if prd % t == 0:
return n
n += 1
4.7.373 - 2025-08-24 13:33:19 +0300 MSK
Links
Code
class Solution:
def isBalanced(self, num: str) -> bool:
sm, n = 0, len(num)
for i in range(n):
if i % 2 == 0:
sm += int(num[i])
else:
sm -= int(num[i])
return sm == 0
4.7.374 - 2025-08-24 13:31:22 +0300 MSK
Links
Code
class Solution:
def possibleStringCount(self, word: str) -> int:
res, n = 1, len(word)
for i in range(1, n):
cur, prev = word[i], word[i - 1]
if cur == prev:
res += 1
return res
4.7.375 - 2025-08-24 13:27:05 +0300 MSK
Links
Code
class Solution:
def findXSum(self, nums: List[int], k: int, x: int) -> List[int]:
def do_sum (idx: int)-> int:
ctr = Counter(nums[idx:idx + k])
most_freq = nlargest(x, ctr, key = lambda y: (ctr[y], y))
return sum(map(lambda y: y * ctr[y], most_freq))
return tuple(map(do_sum,range(len(nums)+1 - k)))
4.7.376 - 2025-08-24 13:21:47 +0300 MSK
Links
Code
class Solution:
def minBitwiseArray(self, nums: List[int]) -> List[int]:
ans = []
for i in nums:
for j in range(i):
if j | (j + 1) == i:
ans.append(j)
break
else:
ans.append(-1)
return ans
4.7.377 - 2025-08-24 13:10:51 +0300 MSK
Links
Code
class Solution:
def kthCharacter(self, k: int) -> str:
res = 0
while k != 1:
ln = k.bit_length() - 1
if (1 << ln) == k:
ln -= 1
k -= 1 << ln
res += 1
return chr(res + 97)
4.7.378 - 2025-08-24 13:05:10 +0300 MSK
Links
Code
class Solution:
def minElement(self, nums: List[int]) -> int:
res = math.inf
for num in nums:
cur = 0
while num > 0:
cur += num % 10
num //= 10
res = min(res, cur)
return res
4.7.379 - 2025-08-24 12:59:57 +0300 MSK
Links
Code
class Solution:
def getSneakyNumbers(self, nums: List[int]) -> List[int]:
n = len(nums) - 2
xor_all = 0
for num in nums:
xor_all ^= num
for num in range(n):
xor_all ^= num
rightmost_bit = xor_all & -xor_all
dup1, dup2 = 0, 0
for num in nums:
if num & rightmost_bit:
dup1 ^= num
else:
dup2 ^= num
for num in range(n):
if num & rightmost_bit:
dup1 ^= num
else:
dup2 ^= num
return [dup1, dup2]
4.7.380 - 2025-08-24 12:47:23 +0300 MSK
Links
Code
class Solution:
def stableMountains(self, height: List[int], threshold: int) -> List[int]:
res, n = [], len(height)
for i in range(1, n):
cur, prv = height[i], height[i - 1]
if prv > threshold:
res.append(i)
return res
4.7.381 - 2025-08-24 12:44:46 +0300 MSK
Links
Code
class Solution:
def convertDateToBinary(self, date: str) -> str:
res, cur = [], []
for num in map(int, (date[:4], date[5:7], date[-2:])):
while num > 0:
cur.append(num & 1)
num >>= 1
cur.reverse()
res.append("".join(map(str, cur)))
cur.clear()
return "-".join(res)
4.7.382 - 2025-08-24 12:44:03 +0300 MSK
Links
Code
class Solution:
def convertDateToBinary(self, date: str) -> str:
res, cur = [], []
for num in map(int, (date[:4], date[5:7], date[-2:])):
while num > 0:
cur.append(num % 2)
num //= 2
cur.reverse()
res.append("".join(map(str, cur)))
cur.clear()
return "-".join(res)
4.7.383 - 2025-08-24 12:38:10 +0300 MSK
Links
Code
class Solution:
def checkTwoChessboards(self, coordinate1: str, coordinate2: str) -> bool:
row1, col1 = ord(coordinate1[0]) - 97, int(coordinate1[1]) - 1
row2, col2 = ord(coordinate2[0]) - 97, int(coordinate2[1]) - 1
if row1 % 2 == 0:
is_black1 = col1 % 2 == 0
else:
is_black1 = col1 % 2 != 0
if row2 % 2 == 0:
is_black2 = col2 % 2 == 0
else:
is_black2 = col2 % 2 != 0
return is_black1 == is_black2
4.7.384 - 2025-08-24 12:34:32 +0300 MSK
Links
Code
class Solution:
def generateKey(self, num1: int, num2: int, num3: int) -> int:
res = 0
cnt = 0
while num1 > 0 and num2 > 0 and num3 > 0:
res += min(num1 % 10, num2 % 10, num3 % 10) * (10 ** cnt)
cnt += 1
num1 //= 10
num2 //= 10
num3 //= 10
return res
4.7.385 - 2025-08-24 12:31:27 +0300 MSK
Links
Code
class Solution:
def getFinalState(self, nums: List[int], k: int, multiplier: int):
hp = [(val, i) for i, val in enumerate(nums)]
heapq.heapify(hp)
for _ in range(k):
_, i = heapq.heappop(hp)
nums[i] *= multiplier
heapq.heappush(hp, (nums[i], i))
return nums
4.7.386 - 2025-08-24 12:29:48 +0300 MSK
Links
Code
class Solution:
def getFinalState(self, nums: List[int], k: int, multiplier: int) -> List[int]:
pos, n = defaultdict(list), len(nums)
hp = nums.copy()
heapq.heapify(hp)
for i in reversed(range(n)):
heapq.heappush(pos[nums[i]], i)
while k > 0:
k -= 1
val = heapq.heappop(hp)
new_val = val * multiplier
heapq.heappush(hp, new_val)
idx = heapq.heappop(pos[val])
nums[idx] = new_val
heapq.heappush(pos[new_val], idx)
return nums
4.7.387 - 2025-08-24 12:20:45 +0300 MSK
Links
Code
class Solution:
def countKConstraintSubstrings(self, s: str, k: int) -> int:
res, n, ones, l = 0, len(s), 0, 0
for r in range(n):
ones += int(s[r])
while (ones > k) and ((r - l + 1) - ones) > k:
ones -= int(s[l])
l += 1
res += r - l + 1
return res
4.7.388 - 2025-08-24 11:46:23 +0300 MSK
Links
Code
class Solution:
def finalPositionOfSnake(self, n: int, commands: List[str]) -> int:
col, row = 0, 0
for cmd in commands:
if cmd == "RIGHT":
col += 1
elif cmd == "UP":
row -= 1
elif cmd == "DOWN":
row += 1
else:
col -= 1
return row * n + col
4.7.389 - 2025-08-24 11:43:54 +0300 MSK
Links
Code
class Solution:
def winningPlayerCount(self, n: int, pick: List[List[int]]) -> int:
res, n, freqs = 0, len(pick), [[0] * 11 for _ in range(11)]
for i in range(n):
pl, cl = pick[i]
freqs[pl][cl] += 1
for i in range(len(freqs)):
if max(freqs[i]) > i:
res += 1
return res
4.7.390 - 2025-08-24 10:55:08 +0300 MSK
Links
Code
class Solution:
def longestSubarray(self, nums: List[int]) -> int:
res, n, cnt1, cnt2 = 0, len(nums), 0, 0
for i in range(len(nums)):
cur = nums[i]
if cur == 1:
cnt2 += 1
res = max(res, cnt1 + cnt2)
elif cur == 0:
cnt1, cnt2 = cnt2, 0
if res == n:
return res - 1
return res
4.7.391 - 2025-08-23 20:17:19 +0300 MSK
Links
Code
class Solution:
def canAliceWin(self, nums: List[int]) -> bool:
sm_single, sm_double, sm_all = 0, 0, 0
for num in nums:
if num < 10:
sm_single += num
elif num < 100:
sm_double += num
sm_all += num
return sm_single > (sm_all - sm_single) or sm_double > (sm_all - sm_double)
4.7.392 - 2025-08-23 19:28:34 +0300 MSK
Links
Code
class Solution:
def minChanges(self, n: int, k: int) -> int:
res = 0
if n < k:
return -1
while k > 0 or n > 0:
n1, k1 = n & 1, k & 1
if n1 != k1 and n1 == 0 and k1 == 1:
return -1
if n1 != k1:
res += 1
n >>= 1
k >>= 1
return res
4.7.393 - 2025-08-23 18:30:08 +0300 MSK
Links
Code
class Solution:
def minimumSum2(
self, grid: List[List[int]], u: int, d: int, l: int, r: int
) -> int:
min_i = len(grid)
max_i = 0
min_j = len(grid[0])
max_j = 0
for i in range(u, d + 1):
for j in range(l, r + 1):
if grid[i][j] == 1:
min_i = min(min_i, i)
min_j = min(min_j, j)
max_i = max(max_i, i)
max_j = max(max_j, j)
return (
(max_i - min_i + 1) * (max_j - min_j + 1)
if min_i <= max_i
else sys.maxsize // 3
)
def rotate(self, vec: List[List[int]]) -> List[List[int]]:
n = len(vec)
m = len(vec[0]) if n > 0 else 0
ret = [[0] * n for _ in range(m)]
for i in range(n):
for j in range(m):
ret[m - j - 1][i] = vec[i][j]
return ret
def solve(self, grid: List[List[int]]) -> int:
n = len(grid)
m = len(grid[0]) if n > 0 else 0
res = n * m
for i in range(n - 1):
for j in range(m - 1):
res = min(
res,
self.minimumSum2(grid, 0, i, 0, m - 1)
+ self.minimumSum2(grid, i + 1, n - 1, 0, j)
+ self.minimumSum2(grid, i + 1, n - 1, j + 1, m - 1),
)
res = min(
res,
self.minimumSum2(grid, 0, i, 0, j)
+ self.minimumSum2(grid, 0, i, j + 1, m - 1)
+ self.minimumSum2(grid, i + 1, n - 1, 0, m - 1),
)
for i in range(n - 2):
for j in range(i + 1, n - 1):
res = min(
res,
self.minimumSum2(grid, 0, i, 0, m - 1)
+ self.minimumSum2(grid, i + 1, j, 0, m - 1)
+ self.minimumSum2(grid, j + 1, n - 1, 0, m - 1),
)
return res
def minimumSum(self, grid: List[List[int]]) -> int:
rgrid = self.rotate(grid)
return min(self.solve(grid), self.solve(rgrid))
4.7.394 - 2025-08-22 21:36:17 +0300 MSK
Links
Code
class Solution:
def winningPlayer(self, x: int, y: int) -> str:
y //= 4
x = min(x, y)
if x % 2 == 1:
return "Alice"
else:
return "Bob"
4.7.395 - 2025-08-22 21:29:25 +0300 MSK
Links
Code
class Solution:
def getSmallestString(self, s: str) -> str:
res = list(s)
for i in range(len(s) - 1):
cur, nxt = int(s[i]), int(s[i + 1])
if cur % 2 == nxt % 2 and cur > nxt:
res[i], res[i + 1] = s[i + 1], s[i]
break
return "".join(res)
4.7.396 - 2025-08-22 21:16:52 +0300 MSK
Links
Code
class Solution:
def getEncryptedString(self, s: str, k: int) -> str:
res = []
for i in range(len(s)):
res.append(s[(i + k) % len(s)])
return "".join(res)
4.7.397 - 2025-08-22 21:13:56 +0300 MSK
Links
Code
class Solution:
def numberOfAlternatingGroups(self, colors: List[int]) -> int:
res = 0
if colors[0] != colors[-1] and colors[0] != colors[1]:
res += 1
if colors[-1] != colors[-2] and colors[-1] != colors[0]:
res += 1
for i in range(1, len(colors) - 1):
if colors[i] != colors[i - 1] and colors[i] != colors[i + 1]:
res += 1
return res
4.7.398 - 2025-08-22 21:08:45 +0300 MSK
Links
Code
class Solution:
def minimumAverage(self, nums: List[int]) -> float:
av = []
nums.sort()
for i in range(len(nums) // 2):
heapq.heappush(av, nums[i] + nums[len(nums) - i - 1])
return heapq.heappop(av) / 2
4.7.399 - 2025-08-22 21:06:36 +0300 MSK
Links
Code
class Solution:
def minimumOperations(self, nums: List[int]) -> int:
res = 0
for i in range(len(nums)):
res += nums[i] % 3 != 0
return res
4.7.400 - 2025-08-22 21:05:07 +0300 MSK
Links
Code
class Solution:
def minimumOperations(self, nums: List[int]) -> int:
res = 0
for i in range(len(nums)):
res += min(nums[i] % 3, ((nums[i] // 3) + 1) * 3 - nums[i])
return res
4.7.401 - 2025-08-22 21:02:15 +0300 MSK
Links
Code
class Solution:
def countCompleteDayPairs(self, hours: List[int]) -> int:
freqs = [0] * 24
for i in range(len(hours)):
freqs[hours[i] % 24] += 1
res = 0
for i in range(len(hours)):
hr = hours[i] % 24
freqs[hr] -= 1
if hr == 0:
res += freqs[hr]
else:
res += freqs[24 - hr]
return res
4.7.402 - 2025-08-22 20:53:33 +0300 MSK
Links
Code
class Solution:
def numberOfChild(self, n: int, k: int) -> int:
circleback = (n - 1) * 2
k %= circleback
if k < n:
return k
return circleback - k
4.7.403 - 2025-08-22 20:44:21 +0300 MSK
Links
Code
class Solution:
def clearDigits(self, s: str) -> str:
res = []
for i in range(len(s)):
ch = s[i]
if not ch.isdigit():
res.append(ch)
elif res:
res.pop()
return "".join(res)
4.7.404 - 2025-08-22 20:41:37 +0300 MSK
Links
Code
class Solution:
def minimumChairs(self, s: str) -> int:
left = 0
res = 0
for i in range(len(s)):
if s[i] == "E":
if left > 0:
left -= 1
else:
res += 1
else:
left += 1
return res
4.7.405 - 2025-08-22 20:34:34 +0300 MSK
Links
Code
class Solution:
def numberOfPairs(self, nums1: List[int], nums2: List[int], k: int) -> int:
freqs = [0] * 51
for i in range(len(nums2)):
freqs[nums2[i]] += 1
res = 0
for i in range(len(nums1)):
for num2 in range(1, len(freqs)):
if nums1[i] % (num2 * k) == 0:
res += freqs[num2]
return res
4.7.406 - 2025-08-22 20:29:48 +0300 MSK
Links
Code
class Solution:
def duplicateNumbersXOR(self, nums: List[int]) -> int:
freqs = [0] * 51
res = 0
for i in range(len(nums)):
freqs[nums[i]] += 1
if freqs[nums[i]] == 2:
res ^= nums[i]
return res
4.7.407 - 2025-08-22 20:27:37 +0300 MSK
Links
Code
class Solution:
def isArraySpecial(self, nums: List[int]) -> bool:
for i in range(1, len(nums)):
cur, prev = nums[i] % 2 == 0, nums[i - 1] % 2 == 0
if cur == prev:
return False
return True
4.7.408 - 2025-08-22 20:25:28 +0300 MSK
Links
Code
class Solution:
def findPermutationDifference(self, s: str, t: str) -> int:
pos = [0] * 26
for i in range(len(s)):
pos[ord(s[i]) - 97] += i
res = 0
for i in range(len(t)):
res += abs(i - pos[ord(t[i]) - 97])
return res
4.7.409 - 2025-08-22 20:22:48 +0300 MSK
Links
Code
class Solution:
def satisfiesConditions(self, grid: List[List[int]]) -> bool:
rows, cols = len(grid), len(grid[0])
for row in range(rows):
for col in range(cols):
val = grid[row][col]
if row + 1 < rows and val != grid[row + 1][col]:
return False
if col + 1 < cols and val == grid[row][col + 1]:
return False
return True
4.7.410 - 2025-08-22 20:20:58 +0300 MSK
Links
Code
class Solution:
def isValid(self, word: str) -> bool:
vws = ('a', 'e', 'i', 'o', 'u')
if len(word) < 3:
return False
has_vw, has_cons = False, False
for i in range(len(word)):
ch = word[i]
if ch.isalpha():
if ch.lower() in vws:
has_vw = True
else:
has_cons = True
elif not ch.isdigit():
return False
return has_vw and has_cons
4.7.411 - 2025-08-22 20:15:56 +0300 MSK
Links
Code
class Solution:
def addedInteger(self, nums1: List[int], nums2: List[int]) -> int:
nums1.sort()
nums2.sort()
return nums2[0] - nums1[0]
4.7.412 - 2025-08-22 20:12:59 +0300 MSK
Links
Code
class Solution:
def canMakeSquare(self, grid: List[List[str]]) -> bool:
rows, cols = len(grid), len(grid[0])
moves = ((0, 0), (0, -1), (-1, -1), (-1, 0))
for row in range(1, rows):
for col in range(1, cols):
cnt = 0
for row_dlt, col_dlt in moves:
if grid[row + row_dlt][col + col_dlt] == "W":
cnt += 1
else:
cnt -= 1
if cnt in (2, -2, 4, -4):
return True
return False
4.7.413 - 2025-08-22 20:03:50 +0300 MSK
Links
Code
class Solution:
def numberOfSpecialChars(self, word: str) -> int:
freqs = [0] * 26
res = 0
for i in range(len(word)):
char = word[i]
idx = ord(char)
if char.isupper():
idx -= 65
freqs[idx] |= 0x01
else:
idx -= 97
freqs[idx] |= 0x10
for i in range(len(freqs)):
freq = freqs[i]
if freq ^ 0x11 == 0:
res += 1
return res
4.7.414 - 2025-08-22 19:58:17 +0300 MSK
Links
Code
class Solution:
def findLatestTime(self, time_str):
len_time_str = len(time_str)
ret_val = ''
i = 0
while (i < len_time_str):
c = time_str[i]
if (c == '?'):
if (i == 0):
if (time_str[i+1] == '?'):
ret_val += '1'
elif (time_str[i+1] in ('0', '1')):
ret_val += '1'
else:
ret_val += '0'
elif (i == 1):
if (time_str[i-1] == '?'):
ret_val += '1'
elif (time_str[i-1] in ('0')):
ret_val += '9'
elif (time_str[i-1] in ('1')):
ret_val += '1'
else:
ret_val += '0'
elif (i == 3):
ret_val += '5'
elif (i == 4):
ret_val += '9'
else:
ret_val += c
i += 1
return ret_val
4.7.415 - 2025-08-22 19:49:07 +0300 MSK
Links
Code
class Solution:
def longestMonotonicSubarray(self, nums: List[int]) -> int:
inc_len, dec_len, cur_len, cur_state = 1, 1, 1, 0
for i in range(1, len(nums)):
cur, prev = nums[i], nums[i - 1]
if cur > prev:
if cur_state == 1:
cur_len += 1
else:
cur_state = 1
cur_len = 2
inc_len = max(inc_len, cur_len)
elif cur == prev:
cur_len = 1
cur_state = 0
else:
if cur_state == -1:
cur_len += 1
else:
cur_state = -1
cur_len = 2
dec_len = max(dec_len, cur_len)
return max(inc_len, dec_len)
4.7.416 - 2025-08-22 19:43:35 +0300 MSK
Links
Code
class Solution:
def sumOfTheDigitsOfHarshadNumber(self, x: int) -> int:
cur = x
sm = 0
while cur > 0:
sm += cur % 10
cur //= 10
if x % sm == 0:
return sm
return -1
4.7.417 - 2025-08-22 19:42:24 +0300 MSK
Links
Code
class Solution:
def minimumSubarrayLength(self, nums: List[int], k: int) -> int:
n = len(nums)
min_len = math.inf
for i in range(n):
curr = 0
for j in range(i, n):
curr |= nums[j]
if curr >= k:
min_len = min(min_len , j - i + 1)
break
if min_len == math.inf:
return -1
return min_len
4.7.418 - 2025-08-22 19:24:16 +0300 MSK
Links
Code
class Solution:
def maximumLengthSubstring(self, s: str) -> int:
ans = ii = 0
freq = Counter()
for i, ch in enumerate(s):
freq[ch] += 1
while freq[ch] == 3:
freq[s[ii]] -= 1
ii += 1
ans = max(ans, i - ii + 1)
return ans
4.7.419 - 2025-08-22 19:19:46 +0300 MSK
Links
Code
class Solution:
def isSubstringPresent(self, s: str) -> bool:
for i in range(1, len(s)):
cur, prev = s[i], s[i - 1]
for j in range(i, len(s)):
cur2, prev2 = s[j], s[j - 1]
if cur == prev2 and prev == cur2:
return True
return False
4.7.420 - 2025-08-22 19:14:44 +0300 MSK
Links
Code
class Solution:
def sumOfEncryptedInt(self, nums: List[int]) -> int:
res = 0
for i in range(len(nums)):
cur = nums[i]
max_dig = 0
enc = 0
cnt = 0
while cur > 0:
max_dig = max(max_dig, cur % 10)
cur //= 10
enc += 10 ** cnt
cnt += 1
enc *= max_dig
res += enc
return res
4.7.421 - 2025-08-22 19:10:19 +0300 MSK
Links
Code
class Solution:
def minimumBoxes(self, apple: List[int], capacity: List[int]) -> int:
apples = sum(apple)
capacity.sort(reverse=True)
for i in range(len(capacity)):
apples = max(apples - capacity[i], 0)
if apples == 0:
return i + 1
raise Exception
4.7.422 - 2025-08-22 19:03:00 +0300 MSK
Links
Code
class Solution:
def resultArray(self, nums):
len_nums = len(nums)
arr1 = [nums[0]]
arr2 = [nums[1]]
for i in range(2, len(nums)):
if arr1[-1] > arr2[-1]:
arr1.append(nums[i])
else:
arr2.append(nums[i])
arr1.extend(arr2)
return arr1
4.7.423 - 2025-08-22 18:58:03 +0300 MSK
Links
Code
class Solution:
def minOperations(self, nums: List[int], k: int) -> int:
nums.sort()
for i in range(len(nums)):
if nums[i] >= k:
return i
return len(nums)
4.7.424 - 2025-08-22 18:56:27 +0300 MSK
Links
Code
class Solution:
def isPossibleToSplit(self, nums: List[int]) -> bool:
freqs = [0] * 101
for num in nums:
freqs[num] += 1
if freqs[num] == 3:
return False
return True
4.7.425 - 2025-08-22 18:53:34 +0300 MSK
Links
Code
class Solution:
def countPrefixSuffixPairs(self, words: List[str]) -> int:
res = 0
for i in range(len(words)):
w1 = words[i]
for j in range(i + 1, len(words)):
w2 = words[j]
if w2.startswith(w1) and w2.endswith(w1):
res += 1
return res
4.7.426 - 2025-08-22 18:48:54 +0300 MSK
Links
Code
class Solution:
def maxOperations(self, nums: List[int]) -> int:
target = sum(nums[:2])
res = 1
for i in range(2, len(nums) - 1, 2):
if sum(nums[i:i + 2]) == target:
res += 1
else:
break
return res
4.7.427 - 2025-08-22 18:46:45 +0300 MSK
Links
Code
class Solution:
def modifiedMatrix(self, matrix: List[List[int]]) -> List[List[int]]:
rows, cols = len(matrix), len(matrix[0])
for col in range(cols):
max_val = -1
for row in range(rows):
max_val = max(max_val, matrix[row][col])
for row in range(rows):
if matrix[row][col] == -1:
matrix[row][col] = max_val
return matrix
4.7.428 - 2025-08-22 18:44:22 +0300 MSK
Links
Code
class Solution:
def returnToBoundaryCount(self, nums: List[int]) -> int:
res = 0
pos = nums[0]
for num in nums[1:]:
pos += num
if pos == 0:
res += 1
return res
4.7.429 - 2025-08-22 18:43:10 +0300 MSK
Links
Code
class Solution:
def triangleType(self, nums: List[int]) -> str:
s1, s2, s3 = nums
if s1 == s2 == s3:
return "equilateral"
if s1 + s2 <= s3 or s1 + s3 <= s2 or s2 + s3 <= s1:
return "none"
if s1 == s2 or s2 == s3 or s1 == s3:
return "isosceles"
if s1 != s2 and s2 != s3 and s1 != s3:
return "scalene"
return "none"
4.7.430 - 2025-08-22 18:39:40 +0300 MSK
Links
Code
class Solution:
def countKeyChanges(self, s: str) -> int:
res = 0
for i in range(1, len(s)):
cur, prev = ord(s[i]), ord(s[i - 1])
if cur < 97:
cur += 32
if prev < 97:
prev += 32
if cur != prev:
res += 1
return res
4.7.431 - 2025-08-22 18:38:14 +0300 MSK
Links
Code
class Solution:
def countKeyChanges(self, s: str) -> int:
res = 0
for i in range(1, len(s)):
cur, prev = s[i].lower(), s[i - 1].lower()
if cur != prev:
res += 1
return res
4.7.432 - 2025-08-22 18:36:52 +0300 MSK
Links
Code
class Solution:
def minimumPushes(self, word: str) -> int:
freqs = [0] * 26
for char in word:
freqs[ord(char) - 97] += 1
freqs.sort()
res = 0
for i in range(26):
freq = freqs[26 - i - 1]
if freq == 0:
break
res += freq * (i // 8 + 1)
return res
4.7.433 - 2025-08-22 18:30:44 +0300 MSK
Links
Code
class Solution:
def minimumPushes(self, word: str) -> int:
freqs = [0] * 26
for char in word:
freqs[ord(char) - 97] += 1
freqs.sort()
cost = 1
res = 0
while freqs and freqs[-1] != 0:
for _ in range(8):
if not freqs:
break
freq = freqs.pop()
if freq == 0:
break
res += freq * cost
cost += 1
return res
4.7.434 - 2025-08-22 18:25:20 +0300 MSK
Links
Code
class Solution:
def minimumCost(self, nums: List[int]) -> int:
nums.reverse()
first = nums.pop()
nums.sort()
return first + sum(nums[:2])
4.7.435 - 2025-08-22 18:22:55 +0300 MSK
Links
Code
class Solution:
def areaOfMaxDiagonal(self, dimensions: List[List[int]]) -> int:
max_diag, max_area = 0, 0
for length, width in dimensions:
diag = length ** 2 + width ** 2
area = length * width
if diag > max_diag or (diag == max_diag and area > max_area):
max_diag, max_area = diag, area
return max_area
4.7.436 - 2025-08-22 18:19:44 +0300 MSK
Links
Code
class Solution:
def missingInteger(self, nums: List[int]) -> int:
s = set(nums)
x = nums[0] - 1
seqSum = 0
for i in nums:
if i - x == 1:
seqSum += i
x = i
else:
break
index = seqSum
while True:
if index not in s:
return index
index += 1
4.7.437 - 2025-08-22 17:02:28 +0300 MSK
Links
Code
class Solution:
def hasTrailingZeros(self, nums: List[int]) -> bool:
cnt = 0
for num in nums:
if num & 1 == 0:
cnt += 1
if cnt == 2:
return True
return False
4.7.438 - 2025-08-22 16:56:33 +0300 MSK
Links
Code
class Solution:
def numberGame(self, nums: List[int]) -> List[int]:
res = []
nums.sort(reverse=True)
while nums:
al, bob = nums.pop(), nums.pop()
res.extend((bob, al))
return res
4.7.439 - 2025-08-22 14:49:18 +0300 MSK
Links
Code
class Solution:
def findMissingAndRepeatedValues(self, grid: List[List[int]]) -> List[int]:
n = len(grid)
freqs = [0] * (n ** 2 + 1)
res1 = None
for row in grid:
for num in row:
freqs[num] += 1
if freqs[num] == 2:
res1 = num
return res1, freqs[1:].index(0) + 1
4.7.440 - 2025-08-22 14:41:39 +0300 MSK
Links
Code
class Solution:
def countTestedDevices(self, batteryPercentages: List[int]) -> int:
res = 0
for i, perc in enumerate(batteryPercentages):
if perc - res > 0:
res += 1
return res
4.7.441 - 2025-08-22 14:33:33 +0300 MSK
Links
Code
class Solution:
def findIntersectionValues(self, nums1: List[int], nums2: List[int]) -> List[int]:
freqs1, freqs2 = [0] * 101, [0] * 101
for num in nums1:
freqs1[num] += 1
for num in nums2:
freqs2[num] += 1
res1, res2 = 0, 0
for num, freq in enumerate(freqs1):
if freqs2[num] > 0:
res1 += freq
for num, freq in enumerate(freqs2):
if freqs1[num] > 0:
res2 += freq
return res1, res2
4.7.442 - 2025-08-22 14:30:04 +0300 MSK
Links
Code
class Solution:
def findPeaks(self, mountain: List[int]) -> List[int]:
res = []
for i in range(1, len(mountain) - 1):
if mountain[i - 1] < mountain[i] > mountain[i + 1]:
res.append(i)
return res
4.7.443 - 2025-08-22 14:28:05 +0300 MSK
Links
Code
class Solution:
def areSimilar(self, mat: List[List[int]], k: int) -> bool:
cols = len(mat[0])
for row in range(len(mat)):
is_even = row % 2 == 0
for col in range(cols):
if is_even:
new_col = (col - k + cols) % cols
else:
new_col = (col + k) % cols
if mat[row][col] != mat[row][new_col]:
return False
return True
4.7.444 - 2025-08-22 14:23:13 +0300 MSK
Links
Code
class Solution:
def findWordsContaining(self, words: List[str], x: str) -> List[int]:
for i in range(len(words)):
if x in words[i]:
words[i] = i
else:
words[i] = -1
words.sort(reverse=True)
while words and words[-1] == -1:
words.pop()
return words
4.7.445 - 2025-08-22 14:20:44 +0300 MSK
Links
Code
class Solution:
def findWordsContaining(self, words: List[str], x: str) -> List[int]:
res = []
for i, word in enumerate(words):
if x in word:
res.append(i)
return res
4.7.446 - 2025-08-22 14:19:56 +0300 MSK
Links
Code
class Solution:
def findMinimumOperations(self, s1: str, s2: str, s3: str) -> int:
n1, n2, n3 = len(s1), len(s2), len(s3)
for i in range(max(n1, n2, n3)):
fail = True
if i < n1 and i < n2 and i < n3:
c1, c2, c3 = s1[i], s2[i], s3[i]
if c1 == c2 and c2 == c3:
fail = False
if not fail:
continue
if i == 0:
return -1
return max(n1 - i, 0) + max(n2 - i, 0) + max(n3 - i, 0)
return 0
4.7.447 - 2025-08-22 14:06:34 +0300 MSK
Links
Code
class Solution:
def maximumStrongPairXor(self, nums: List[int]) -> int:
nums.sort()
n, l, r, res = len(nums), 0, 0, 0
while r < n:
num1, num2 = nums[l], nums[r]
if num2 - num1 > num1:
l += 1
continue
for i in range(l, r):
res = max(res, nums[i] ^ num2)
r += 1
return res
4.7.448 - 2025-08-22 13:59:13 +0300 MSK
Links
Code
class Solution:
def maximumStrongPairXor(self, nums: List[int]) -> int:
max_xor = 0
for i in range(len(nums)):
for j in range(i + 1, len(nums)):
num1, num2 = nums[i], nums[j]
if abs(num2 - num1) <= min(num1, num2):
max_xor = max(max_xor, num1 ^ num2)
return max_xor
4.7.449 - 2025-08-22 13:58:21 +0300 MSK
Links
Code
class Solution:
def maximumStrongPairXor(self, nums: List[int]) -> int:
max_xor = 0
for num1, num2 in itertools.permutations(nums, 2):
if abs(num2 - num1) <= min(num1, num2):
max_xor = max(max_xor, num1 ^ num2)
return max_xor
4.7.450 - 2025-08-22 13:53:08 +0300 MSK
Links
Code
class Solution:
def distributeCandies(self, n: int, limit: int) -> int:
min_first = max(0, n - 2 * limit)
max_first = min(n, limit)
ways = 0
for i in range(min_first, max_first + 1):
N = n - i
min_ch2 = max(0, N - limit)
max_ch2 = min(N, limit)
ways += max_ch2 - min_ch2 + 1
return ways
4.7.451 - 2025-08-22 13:44:20 +0300 MSK
Links
Code
class Solution:
def findChampion(self, grid: List[List[int]]) -> int:
loses = [False] * len(grid)
for row in range(len(grid)):
for col in range(len(grid)):
if row == col:
continue
val = grid[row][col]
if val == 1:
loses[col] = True
else:
loses[row] = True
return loses.index(False)
4.7.452 - 2025-08-22 13:37:11 +0300 MSK
Links
Code
class Solution:
def findKOr(self, nums: List[int], k: int) -> int:
freqs = [0] * 31
for num in nums:
i = 0
while num > 0:
if num & 1 == 1:
freqs[i] += 1
i += 1
num >>= 1
res = 0
for i, freq in enumerate(freqs):
if freq >= k:
res |= 1 << i
return res
4.7.453 - 2025-08-22 09:54:03 +0300 MSK
Links
Code
class Solution:
def minimumArea(self, grid: List[List[int]]) -> int:
min_row, max_row = math.inf, -math.inf
min_col, max_col = math.inf, -math.inf
for row in range(len(grid)):
for col in range(len(grid[0])):
if grid[row][col] == 0:
continue
min_row, max_row = min(min_row, row), max(max_row, row)
min_col, max_col = min(min_col, col), max(max_col, col)
return (max_row - min_row + 1) * (max_col - min_col + 1)
4.7.454 - 2025-08-21 19:04:22 +0300 MSK
Links
Code
class Solution:
def sumCounts(self, nums: List[int]) -> int:
n = len(nums)
result = 0
for i in range(n):
s = set()
for j in range(i, n):
s.add(nums[j])
result += len(s) ** 2
return result
4.7.455 - 2025-08-21 19:01:40 +0300 MSK
Links
Code
import pandas as pd
def findHeavyAnimals(animals: pd.DataFrame) -> pd.DataFrame:
return animals[animals['weight'] > 100].sort_values(by='weight', ascending=False)[['name']]
4.7.456 - 2025-08-21 18:59:14 +0300 MSK
Links
Code
import pandas as pd
def meltTable(report: pd.DataFrame) -> pd.DataFrame:
report = report.melt(
id_vars=["product"],
value_vars=["quarter_1", "quarter_2", "quarter_3", "quarter_4"],
var_name="quarter",
value_name="sales",
)
return report
4.7.457 - 2025-08-21 18:58:06 +0300 MSK
Links
Code
import pandas as pd
def pivotTable(weather: pd.DataFrame) -> pd.DataFrame:
ans = weather.pivot(index='month', columns='city', values='temperature')
return ans
4.7.458 - 2025-08-21 18:57:41 +0300 MSK
Links
Code
class Solution:
def minimumSum(self, nums: List[int]) -> int:
n = len(nums)
min_left, min_right = [0] * n, [0] * n
cur_min = math.inf
for i in range(n):
cur_min = min(cur_min, nums[i])
min_left[i] = cur_min
cur_min = math.inf
for i in reversed(range(n)):
cur_min = min(cur_min, nums[i])
min_right[i] = cur_min
min_sum = math.inf
for i in range(1, n - 1):
left, mid, right = min_left[i - 1], nums[i], min_right[i + 1]
if left < mid > right:
min_sum = min(min_sum, left + mid + right)
if min_sum == math.inf:
return -1
return min_sum
4.7.459 - 2025-08-21 18:50:35 +0300 MSK
Links
Code
import pandas as pd
def concatenateTables(df1: pd.DataFrame, df2: pd.DataFrame) -> pd.DataFrame:
return pd.concat([df1, df2], axis=0)
4.7.460 - 2025-08-21 18:50:21 +0300 MSK
Links
Code
class Solution:
def findIndices(self, A: List[int], d: int, valueDifference: int) -> List[int]:
mini = maxi = 0
for i in range(d, len(A)):
if A[i - d] < A[mini]:
mini = i - d
if A[i - d] > A[maxi]:
maxi = i - d
if A[i] - A[mini] >= valueDifference:
return [mini, i]
if A[maxi] - A[i] >= valueDifference:
return [maxi, i]
return [-1, -1]
4.7.461 - 2025-08-21 18:45:02 +0300 MSK
Links
Code
import pandas as pd
def fillMissingValues(products: pd.DataFrame) -> pd.DataFrame:
products['quantity'].fillna(0, inplace=True)
return products
4.7.462 - 2025-08-21 18:35:19 +0300 MSK
Links
Code
import pandas as pd
def changeDatatype(students: pd.DataFrame) -> pd.DataFrame:
students = students.astype({'grade': int})
return students
4.7.463 - 2025-08-21 18:35:00 +0300 MSK
Links
Code
class Solution:
def getLongestSubsequence(self, words: List[str], groups: List[int]) -> List[str]:
res = [words[0]]
prev = groups[0]
for i in range(1, len(groups)):
cur = groups[i]
if cur == prev:
continue
prev = cur
res.append(words[i])
return res
4.7.464 - 2025-08-21 18:34:31 +0300 MSK
Links
Code
import pandas as pd
def renameColumns(students: pd.DataFrame) -> pd.DataFrame:
students = students.rename(
columns={
"id": "student_id",
"first": "first_name",
"last": "last_name",
"age": "age_in_years",
}
)
return students
4.7.465 - 2025-08-21 18:30:25 +0300 MSK
Links
Code
import pandas as pd
def modifySalaryColumn(employees: pd.DataFrame) -> pd.DataFrame:
employees['salary'] = employees['salary'] * 2
return employees
4.7.466 - 2025-08-21 18:30:11 +0300 MSK
Links
Code
class Solution:
def lastVisitedIntegers(self, nums: List[int]) -> List[int]:
enc = []
res = []
m1_cnt = 0
for num in nums:
if num != -1:
m1_cnt = 0
enc.append(num)
continue
m1_cnt += 1
if m1_cnt <= len(enc):
res.append(enc[len(enc) - (m1_cnt - 1) - 1])
else:
res.append(-1)
return res
4.7.467 - 2025-08-21 18:24:42 +0300 MSK
Links
Code
import pandas as pd
def dropMissingData(students: pd.DataFrame) -> pd.DataFrame:
students.dropna(subset=['name'], inplace=True)
return students
4.7.468 - 2025-08-21 18:24:23 +0300 MSK
Links
Code
class Solution:
def differenceOfSums(self, n: int, m: int) -> int:
al = n * (1 + n) // 2
div = (n // m) * (m + (n - (n % m))) // 2
non_div = al - div
return (al - div) - div
4.7.469 - 2025-08-21 18:18:09 +0300 MSK
Links
Code
import pandas as pd
def dropDuplicateEmails(customers: pd.DataFrame) -> pd.DataFrame:
customers.drop_duplicates(subset='email', keep='first', inplace=True)
return customers
4.7.470 - 2025-08-21 18:17:44 +0300 MSK
Links
Code
import pandas as pd
def createBonusColumn(employees: pd.DataFrame) -> pd.DataFrame:
employees['bonus'] = employees['salary'] * 2
return employees
4.7.471 - 2025-08-21 18:17:05 +0300 MSK
Links
Code
import pandas as pd
def selectData(students: pd.DataFrame) -> pd.DataFrame:
return students.loc[students["student_id"] == 101, ["name", "age"]]
4.7.472 - 2025-08-21 18:16:46 +0300 MSK
Links
Code
import pandas as pd
def selectFirstRows(employees: pd.DataFrame) -> pd.DataFrame:
return employees.head(3)
4.7.473 - 2025-08-21 18:16:25 +0300 MSK
Links
Code
import pandas as pd
def getDataframeSize(players: pd.DataFrame) -> List:
return [players.shape[0], players.shape[1]]
4.7.474 - 2025-08-21 18:16:06 +0300 MSK
Links
Code
import pandas as pd
def createDataframe(student_data: List[List[int]]) -> pd.DataFrame:
column_names = ["student_id", "age"]
result_dataframe = pd.DataFrame(student_data, columns=column_names)
return result_dataframe
4.7.475 - 2025-08-21 18:15:24 +0300 MSK
Links
Code
from typing import List
class Solution:
def maximumTripletValue(self, nums: List[int]) -> int:
n = len(nums)
if n < 3:
return 0
left_max = [0] * n
left_max[0] = nums[0]
for i in range(1, n):
left_max[i] = max(left_max[i - 1], nums[i])
right_max = [0] * n
right_max[-1] = nums[-1]
for i in reversed(range(1, n - 1)):
right_max[i] = max(right_max[i + 1], nums[i])
ans = 0
for i in range(1, n - 1):
left = left_max[i - 1]
right = right_max[i + 1]
ans = max(ans, (left - nums[i]) * right)
return ans
4.7.476 - 2025-08-21 17:56:20 +0300 MSK
Links
Code
class Solution:
def minOperations(self, nums: List[int], k: int) -> int:
enc = [False] * (k + 1)
res = 0
rem = k
for num in reversed(nums):
res += 1
if 1 <= num <= k and not enc[num]:
enc[num] = True
rem -= 1
if rem == 0:
return res
raise Exception
4.7.477 - 2025-08-21 17:51:03 +0300 MSK
Links
Code
class Solution:
def minimumRightShifts(self, nums: List[int]) -> int:
drop = -1
for i, num in enumerate(nums[1:], 1):
if num > nums[i - 1]:
continue
if drop != -1:
return -1
drop = i
if drop == -1:
return 0
if nums[0] <= nums[-1]:
return -1
return len(nums) - drop
4.7.478 - 2025-08-21 17:41:49 +0300 MSK
Links
Code
class Solution:
def numberOfPoints(self, nums: List[List[int]]) -> int:
line = [0] * 102
points_on_line = 0
for start, end in nums:
line[start] += 1
line[end + 1] -= 1
for i in range(1, 102):
line[i] += line[i - 1]
if line[i] != 0:
points_on_line += 1
return points_on_line
4.7.479 - 2025-08-21 17:35:46 +0300 MSK
Links
Code
class Solution:
def canBeEqual(self, s1: str, s2: str) -> bool:
freqs_even = [0] * 26
freqs_odd = [0] * 26
for i, (char1, char2) in enumerate(zip(s1, s2)):
if i % 2 == 0:
trg = freqs_even
else:
trg = freqs_odd
trg[ord(char1) - 97] += 1
trg[ord(char2) - 97] -= 1
for freq1, freq2 in zip(freqs_even, freqs_odd):
if freq1 != 0 or freq2 != 0:
return False
return True
4.7.480 - 2025-08-21 17:31:03 +0300 MSK
Links
Code
class Solution:
def furthestDistanceFromOrigin(self, moves: str) -> int:
cnt_left, cnt_right, cnt_any = 0, 0, 0
for char in moves:
if char == "L":
cnt_left += 1
elif char == "R":
cnt_right += 1
else:
cnt_any += 1
if cnt_right > cnt_left:
return cnt_right - cnt_left + cnt_any
return cnt_left - cnt_right + cnt_any
4.7.481 - 2025-08-21 17:26:29 +0300 MSK
Links
Code
class Solution:
def isAcronym(self, words: List[str], s: str) -> bool:
if len(words) != len(s):
return False
for i in range(len(words)):
if words[i][0] != s[i]:
return False
return True
4.7.482 - 2025-08-21 17:15:57 +0300 MSK
Links
Code
class Solution:
def maxSum(self, nums: List[int]) -> int:
freqs = [[] for _ in range(10)]
for num in nums:
dig = 0
orig = num
while num > 0:
dig = max(dig, num % 10)
num //= 10
heapq.heappush(freqs[dig], -orig)
res = -1
for nms in freqs:
if len(nms) < 2:
continue
res = max(res, -(heapq.heappop(nms) + heapq.heappop(nms)))
return res
4.7.483 - 2025-08-21 17:07:52 +0300 MSK
Links
Code
class Solution:
def splitWordsBySeparator(self, words: List[str], separator: str) -> List[str]:
res = []
cur = []
for word in words:
for char in itertools.chain(word, separator):
if char != separator:
cur.append(char)
elif cur:
res.append("".join(cur))
cur.clear()
return res
4.7.484 - 2025-08-21 17:05:33 +0300 MSK
Links
Code
class Solution:
def isGood(self, nums: list[int]) -> bool:
mx = max(nums)
if len(nums) != mx + 1:
return False
freqs = defaultdict(int)
for num in nums:
freqs[num] += 1
if freqs[mx] != 2:
return False
for i in range(1, mx):
if freqs[i] != 1:
return False
return True
4.7.485 - 2025-08-21 17:00:40 +0300 MSK
Links
Code
class Solution:
def sumOfSquares(self, nums: List[int]) -> int:
n = len(nums)
res = 0
for i in range(1, int(math.sqrt(n)) + 1):
if n % i != 0:
continue
idx1, idx2 = i - 1, (n // i) - 1
res += nums[idx1] ** 2
if idx2 != idx1:
res += nums[idx2] ** 2
return res
4.7.486 - 2025-08-21 16:51:13 +0300 MSK
Links
Code
class Solution:
def sumOfSquares(self, nums: List[int]) -> int:
n = len(nums)
res = 0
for i in range(n):
if n % (i + 1) == 0:
res += nums[i] ** 2
return res
4.7.487 - 2025-08-21 16:50:01 +0300 MSK
Links
Code
class Solution:
def theMaximumAchievableX(self, num: int, t: int) -> int:
return num + (t * 2)
4.7.488 - 2025-08-21 16:46:44 +0300 MSK
Links
Code
class Solution:
def alternatingSubarray(self, nums: list[int]) -> int:
n = len(nums)
maxi = 0
for i in range(n - 1):
if nums[i + 1] != nums[i] + 1:
continue
curr, prev = 2, 1
for j in range(i + 2, n):
diff = nums[j] - nums[j - 1]
if diff == -prev:
curr += 1
prev = -prev
else:
break
maxi = max(maxi, curr)
return maxi if maxi > 0 else -1
4.7.489 - 2025-08-21 16:44:37 +0300 MSK
Links
Code
class Solution:
def longestAlternatingSubarray(self, nums: list[int], threshold: int) -> int:
n = len(nums)
if n == 1:
if nums[0] % 2 == 0 and nums[0] <= threshold:
return 1
return 0
length = 0
for l in range(n):
if nums[l] % 2 != 0:
continue
for r in range(l, n):
if nums[r] > threshold:
break
ok = True
for i in range(l, r):
if nums[i] % 2 == nums[i + 1] % 2:
ok = False
break
if ok:
length = max(length, r - l + 1)
return length
4.7.490 - 2025-08-21 16:42:44 +0300 MSK
Links
Code
class Solution:
def countBeautifulPairs(self, nums: List[int]) -> int:
def check(num1: int, num2: int) -> bool:
first, last = 0, num2 % 10
while num1 > 0:
first = num1 % 10
num1 //= 10
return math.gcd(first, last) == 1
res = 0
for i in range(len(nums)):
for j in range(i + 1, len(nums)):
if check(nums[i], nums[j]):
res += 1
return res
4.7.491 - 2025-08-21 16:38:20 +0300 MSK
Links
Code
class Solution:
def maximumNumberOfStringPairs(self, words: List[str]) -> int:
enc = set()
res = 0
for word in words:
if word in enc:
res += 1
else:
enc.add(word[::-1])
return res
4.7.492 - 2025-08-21 16:26:55 +0300 MSK
Links
Code
class Solution:
def distanceTraveled(self, mainTank: int, additionalTank: int) -> int:
res = 0
while mainTank > 4:
count = mainTank // 5
res += count * 5
mainTank %= 5
add_count = min(count, additionalTank)
additionalTank -= add_count
mainTank += add_count
res += mainTank
return res * 10
4.7.493 - 2025-08-21 16:19:42 +0300 MSK
Links
Code
class Solution:
def findNonMinOrMax(self, nums: List[int]) -> int:
nums.sort()
min_val, max_val = nums[0], nums[-1]
if nums[0] == nums[-1]:
return -1
if len(nums) < 3:
return -1
left, right = 0, len(nums) - 1
while left <= right:
mid = left + (right - left) // 2
val = nums[mid]
if val == min_val:
left = mid + 1
elif val == max_val:
right = mid - 1
return val
return -1
4.7.494 - 2025-08-21 16:16:56 +0300 MSK
Links
Code
class Solution:
def isFascinating(self, n: int) -> bool:
freqs = [False] * 9
for num in (n, n * 2, n * 3):
while num > 0:
dig = num % 10
if dig == 0:
return False
if freqs[dig - 1]:
return False
freqs[dig - 1] = True
num //= 10
return sum(freqs) == 9
4.7.495 - 2025-08-21 16:07:01 +0300 MSK
Links
Code
/**
* @param {Object|Array} obj
* @return {boolean}
*/
var isEmpty = function(obj) {
if (Array.isArray(obj)) {
return obj.length === 0;
} else {
return Object.keys(obj).length === 0;
}
};
4.7.496 - 2025-08-21 16:06:09 +0300 MSK
Links
Code
class Calculator {
/**
* @param {number} value
*/
constructor(value) {
this.result = value
}
/**
* @param {number} value
* @return {Calculator}
*/
add(value){
this.result += value
return this
}
/**
* @param {number} value
* @return {Calculator}
*/
subtract(value){
this.result -= value
return this
}
/**
* @param {number} value
* @return {Calculator}
*/
multiply(value) {
this.result *= value
return this
}
/**
* @param {number} value
* @return {Calculator}
*/
divide(value) {
if(value === 0){
throw new Error("Division by zero is not allowed")
}
this.result /= value
return this
}
/**
* @param {number} value
* @return {Calculator}
*/
power(value) {
this.result **= value
return this
}
/**
* @return {number}
*/
getResult() {
return this.result
}
}
4.7.497 - 2025-08-21 16:01:02 +0300 MSK
Links
Code
/**
* @param {Function} fn
* @param {Array} args
* @param {number} t
* @return {Function}
*/
var cancellable = function(fn, args, t) {
fn(...args);
const timer = setInterval(() => fn(...args), t);
const cancelFn = () => clearInterval(timer);
return cancelFn;
};
/**
* const result = [];
*
* const fn = (x) => x * 2;
* const args = [4], t = 35, cancelTimeMs = 190;
*
* const start = performance.now();
*
* const log = (...argsArr) => {
* const diff = Math.floor(performance.now() - start);
* result.push({"time": diff, "returned": fn(...argsArr)});
* }
*
* const cancel = cancellable(log, args, t);
*
* setTimeout(cancel, cancelTimeMs);
*
* setTimeout(() => {
* console.log(result); // [
* // {"time":0,"returned":8},
* // {"time":35,"returned":8},
* // {"time":70,"returned":8},
* // {"time":105,"returned":8},
* // {"time":140,"returned":8},
* // {"time":175,"returned":8}
* // ]
* }, cancelTimeMs + t + 15)
*/
4.7.498 - 2025-08-21 15:58:36 +0300 MSK
Links
Code
/**
* @param {Array} arr
* @param {Function} fn
* @return {Array}
*/
var sortBy = function(arr, fn) {
return arr.toSorted((a, b) => fn(a) - fn(b));
};
4.7.499 - 2025-08-21 15:55:14 +0300 MSK
Links
Code
/**
* @param {Promise} promise1
* @param {Promise} promise2
* @return {Promise}
*/
var addTwoPromises = async function(promise1, promise2) {
const [value1, value2] = await Promise.all([promise1, promise2]);
return value1 + value2;
};
// // Example usage:
// var promise1 = new Promise(resolve => setTimeout(() => resolve(2), 20));
// var promise2 = new Promise(resolve => setTimeout(() => resolve(5), 60));
// addTwoPromises(promise1, promise2)
// .then(console.log); // Output: 7
4.7.500 - 2025-08-21 15:49:02 +0300 MSK
Links
Code
class Solution:
def semiOrderedPermutation(self, nums: List[int]) -> int:
i1, i2 = 0, 0
n = len(nums)
for i, num in enumerate(nums):
if num == 1:
i1 = i
elif num == n:
i2 = i
if i1 and i2:
break
res = i1 + (n - i2 - 1)
if i2 < i1:
res -= 1
return res
4.7.501 - 2025-08-21 15:45:35 +0300 MSK
Links
Code
class Solution:
def minimizedStringLength(self, s: str) -> int:
freqs = [False] * 26
for char in s:
freqs[ord(char) - 97] = True
return sum(freqs)
4.7.502 - 2025-08-21 15:42:45 +0300 MSK
Links
Code
/**
* @param {Function} fn
* @param {Array} args
* @param {number} t
* @return {Function}
*/
const cancellable = function(fn, args, t) {
const timer = setTimeout(() => {
fn(...args)
}, t);
const cancelFn = function() {
clearTimeout(timer);
};
return cancelFn;
};
/**
* const result = []
*
* const fn = (x) => x * 5
* const args = [2], t = 20, cancelT = 50
*
* const log = (...argsArr) => {
* result.push(fn(...argsArr))
* }
*
* const cancel = cancellable(fn, args, t);
*
* setTimeout(() => {
* cancel()
* console.log(result) // [{"time":20,"returned":10}]
* }, cancelT)
*/
4.7.503 - 2025-08-21 15:40:49 +0300 MSK
Links
Code
class Solution:
def removeTrailingZeros(self, num: str) -> str:
val = int(num)
while val > 0 and val % 10 == 0:
val //= 10
return str(val)
4.7.504 - 2025-08-21 15:37:36 +0300 MSK
Links
Code
class Check {
constructor(val) {
this.val = val;
}
toBe(val) {
if (val === this.val) {
return true;
}
throw new Error("Not Equal");
}
notToBe(val) {
if (val !== this.val) {
return true;
}
throw new Error("Equal");
}
}
/**
* @param {string} val
* @return {Object}
*/
var expect = function(val) {
return new Check(val);
};
/**
* expect(5).toBe(5); // true
* expect(5).notToBe(5); // throws "Equal"
*/
4.7.505 - 2025-08-21 15:33:15 +0300 MSK
Links
Code
/**
* @param {...(null|boolean|number|string|Array|Object)} args
* @return {number}
*/
var argumentsLength = function(...args) {
return args.length;
};
/**
* argumentsLength(1, 2, 3); // 3
*/
4.7.506 - 2025-08-21 15:32:49 +0300 MSK
Links
Code
class Solution:
def makeSmallestPalindrome(self, s: str) -> str:
letters = list(s)
for i in range(len(s) // 2):
letters[i] = letters[~i] = min(letters[i], letters[~i])
return ''.join(letters)
4.7.507 - 2025-08-21 15:03:03 +0300 MSK
Links
Code
class Solution:
def minLength(self, s: str) -> int:
stack = []
for char in s:
if not stack or char not in "ABCD":
stack.append(char)
continue
if (
(stack[-1] == "A" and char == "B")
or (stack[-1] == "C" and char == "D")
):
stack.pop()
else:
stack.append(char)
return len(stack)
4.7.508 - 2025-08-21 14:57:54 +0300 MSK
Links
Code
class Solution:
def minLength(self, s: str) -> int:
while "AB" in s or "CD" in s:
s = s.replace("AB", "").replace("CD", "")
return len(s)
4.7.509 - 2025-08-21 14:56:18 +0300 MSK
Links
Code
/**
* @param {number[]} nums
* @return {void}
*/
var ArrayWrapper = function(nums) {
this.sum = nums.reduce((a, b) => a + b, 0);
this.string = `[${nums.toString()}]`;
};
/**
* @return {number}
*/
ArrayWrapper.prototype.valueOf = function() {
return this.sum;
}
/**
* @return {string}
*/
ArrayWrapper.prototype.toString = function() {
return this.string;
}
/**
* const obj1 = new ArrayWrapper([1,2]);
* const obj2 = new ArrayWrapper([3,4]);
* obj1 + obj2; // 10
* String(obj1); // "[1,2]"
* String(obj2); // "[3,4]"
*/
4.7.510 - 2025-08-21 14:52:44 +0300 MSK
Links
Code
class Solution:
def circularGameLosers(self, n: int, k: int) -> List[int]:
count = 1
i = 0
enc = set((0, ))
while True:
i = (i + k * count) % n
if i in enc:
break
enc.add(i)
count += 1
res = []
for i in range(n):
if i not in enc:
res.append(i + 1)
return res
4.7.511 - 2025-08-21 14:47:10 +0300 MSK
Links
Code
class Solution:
def countSeniors(self, details: List[str]) -> int:
count = 0
for detail in details:
if int(detail[-4:-2]) > 60:
count += 1
return count
4.7.512 - 2025-08-21 14:44:56 +0300 MSK
Links
Code
/**
* @param {Array} arr
* @param {number} size
* @return {Array}
*/
var chunk = function(arr, size) {
const chunkedArray = [];
let index = 0;
while (index < arr.length) {
chunkedArray.push(arr.slice(index, index + size));
index += size;
}
return chunkedArray;
};
4.7.513 - 2025-08-21 14:42:42 +0300 MSK
Links
Code
class Solution:
def distinctDifferenceArray(self, nums: List[int]) -> List[int]:
left, right = set(), defaultdict(int)
for num in nums:
right[num] += 1
res = []
for num in nums:
left.add(num)
right[num] -= 1
if right[num] == 0:
del right[num]
res.append(len(left) - len(right))
return res
4.7.514 - 2025-08-21 14:32:28 +0300 MSK
Links
Code
/**
* @return {Function}
*/
var createHelloWorld = function() {
return function(...args) {
return "Hello World";
}
};
/**
* const f = createHelloWorld();
* f(); // "Hello World"
*/
4.7.515 - 2025-08-21 14:31:55 +0300 MSK
Links
Code
/**
* @param {Function} fn
* @return {Function}
*/
var once = function(fn) {
let called = false;
return function(...args){
if (called) {
return undefined;
}
called = true;
return fn(...args);
}
};
/**
* let fn = (a,b,c) => (a + b + c)
* let onceFn = once(fn)
*
* onceFn(1,2,3); // 6
* onceFn(2,3,6); // returns undefined without calling fn
*/
4.7.516 - 2025-08-21 14:30:46 +0300 MSK
Links
Code
class Counter {
constructor(init) {
this.init = init;
this.val = init;
}
increment() {
let val = this.val + 1;
this.val = val;
return val;
}
decrement() {
let val = this.val - 1;
this.val = val;
return val;
}
reset() {
let val = this.init;
this.val = val;
return val;
}
}
/**
* @param {integer} init
* @return { increment: Function, decrement: Function, reset: Function }
*/
var createCounter = function(init) {
return new Counter(init)
};
/**
* const counter = createCounter(5)
* counter.increment(); // 6
* counter.reset(); // 5
* counter.decrement(); // 4
*/
4.7.517 - 2025-08-21 14:28:11 +0300 MSK
Links
Code
class Solution:
def isWinner(self, player1: List[int], player2: List[int]) -> int:
last_10_1, last_10_2 = -10, -10
score = 0
for i, (hit1, hit2) in enumerate(zip(player1, player2)):
mult1, mult2 = 1, 1
if i - last_10_1 < 3:
mult1 = 2
if i - last_10_2 < 3:
mult2 = 2
score += hit1 * mult1 - hit2 * mult2
if hit1 == 10:
last_10_1 = i
if hit2 == 10:
last_10_2 = i
if score > 0:
return 1
elif score < 0:
return 2
return 0
4.7.518 - 2025-08-21 14:14:45 +0300 MSK
Links
Code
class Solution:
def maximizeSum(self, nums: List[int], k: int) -> int:
first = max(nums)
last = first + (k - 1) * 1
return (k * (first + last)) // 2
4.7.519 - 2025-08-21 14:03:34 +0300 MSK
Links
Code
class Solution:
def sumOfMultiples(self, n: int) -> int:
enc = set()
for num in range(3, n + 1, 3):
enc.add(num)
for num in range(5, n + 1, 5):
enc.add(num)
for num in range(7, n + 1, 7):
enc.add(num)
return sum(enc)
4.7.520 - 2025-08-21 13:59:45 +0300 MSK
Links
Code
class Solution:
def findDelayedArrivalTime(self, arrivalTime: int, delayedTime: int) -> int:
return (arrivalTime + delayedTime) % 24
4.7.521 - 2025-08-21 13:58:37 +0300 MSK
Links
Code
/**
* @return {Generator<number>}
*/
var fibGenerator = function*() {
let num1 = 0;
let num2 = 1;
yield num1;
yield num2;
while (true) {
const num3 = num1 + num2;
num1 = num2;
num2 = num3;
yield num3;
}
};
/**
* const gen = fibGenerator();
* gen.next().value; // 0
* gen.next().value; // 1
*/
4.7.522 - 2025-08-21 13:56:09 +0300 MSK
Links
Code
class Solution:
def maxDivScore(self, nums: List[int], divisors: List[int]) -> int:
freqs = defaultdict(int)
for num in nums:
freqs[num] += 1
divisors.sort()
max_div, max_count = divisors[0], 0
for div in divisors:
count = 0
for num, freq in freqs.items():
if num % div == 0:
count += freq
if count > max_count:
max_div, max_count = div, count
return max_div
4.7.523 - 2025-08-21 13:42:53 +0300 MSK
Links
Code
class Solution:
def rowAndMaximumOnes(self, mat: List[List[int]]) -> List[int]:
max_row, max_count = 0, sum(mat[0])
for i, row in enumerate(mat[1:], 1):
count = sum(row)
if count > max_count:
max_row, max_count = i, count
return max_row, max_count
4.7.524 - 2025-08-21 13:40:48 +0300 MSK
Links
Code
class Solution:
def findColumnWidth(self, grid: List[List[int]]) -> List[int]:
res = []
for col in range(len(grid[0])):
max_len = 0
for row in range(len(grid)):
val = grid[row][col]
if val == 0:
count = 1
elif val < 0:
count = 1
val = -val
else:
count = 0
while val > 0:
count += 1
val //= 10
max_len = max(max_len, count)
res.append(max_len)
return res
4.7.525 - 2025-08-21 13:31:24 +0300 MSK
Links
Code
class TreeNode:
def __init__(self, val, start, end, left_child = None, right_child = None):
self.val = val
self.start = start
self.end = end
self.left_child = left_child
self.right_child = right_child
class SegmentTree:
def __init__(self, nums):
self.nums = nums
self.root = self.build(0, len(nums) - 1)
def build(self, start, end):
if start == end:
return TreeNode(self.nums[start], start, end)
left_child = self.build(start, (start + end) //2)
right_child = self.build((start+end) // 2 + 1, end)
return TreeNode(left_child.val + right_child.val, start, end, left_child, right_child)
def update(self, root, index, value):
if root.start == root.end and index == root.start: # target
root.val = value
return value
if root.start > index or root.end < index:
return root.val
root.val = self.update(root.left_child, index, value) + self.update(root.right_child, index, value)
return root.val
def query(self, root, left, right):
if root.start > right or root.end < left: return 0
if root.start >= left and root.end <= right: return root.val
return self.query(root.left_child, left, right) + self.query(root.right_child, left, right)
class NumArray:
def __init__(self, nums: List[int]):
self.tree = SegmentTree(nums)
self.root = self.tree.root
def update(self, index: int, val: int) -> None:
self.tree.update(self.root, index, val)
def sumRange(self, left: int, right: int) -> int:
return self.tree.query(self.root, left, right)
4.7.526 - 2025-08-21 13:26:07 +0300 MSK
Links
Code
class TopVotedCandidate:
def __init__(self, persons: List[int], times: List[int]):
self._lead = times
freqs = [0] * 5001
prev = persons[0]
freqs[prev] = 1
times[0] = (times[0], prev)
for i in range(1, len(times)):
person = persons[i]
freq = freqs[person] + 1
freqs[person] = freq
if freq >= freqs[prev]:
prev = person
times[i] = (times[i], prev)
def q(self, t: int) -> int:
left, right = 0, len(self._lead) - 1
res = None
while left <= right:
mid = left + (right - left) // 2
lead_time, lead_person = self._lead[mid]
if lead_time > t:
right = mid - 1
elif lead_time == t:
return lead_person
else:
res = lead_person
left = mid + 1
return res
# Your TopVotedCandidate object will be instantiated and called as such:
# obj = TopVotedCandidate(persons, times)
# param_1 = obj.q(t)
4.7.527 - 2025-08-21 12:41:54 +0300 MSK
Links
Code
class Robot:
def __init__(self, width: int, height: int):
self.cur = (0, 0)
self.cur_dir = 0
self.width = width
self.height = height
self.dir_mapping = {
0: "East",
1: "North",
2: "West",
3: "South"
}
self.mod = 2 * (self.width + self.height - 2)
def step(self, num: int) -> None:
if num >= self.mod:
num %= self.mod
if self.cur == (0, 0) and self.cur_dir == 0:
self.cur_dir = 3
row, col = self.cur
while num > 0:
if self.cur_dir == 0:
steps = min(num, self.width - row -1)
num -= steps
row += steps
elif self.cur_dir == 1:
steps = min(num, self.height -1 - col)
num -= steps
col += steps
elif self.cur_dir == 2:
steps = min(num, row)
num -= steps
row -= steps
else:
steps = min(num, col)
num -= steps
col -= steps
if num > 0:
self.cur_dir = (self.cur_dir + 1) % 4
self.cur = row, col
def getPos(self) -> List[int]:
return self.cur
def getDir(self) -> str:
return self.dir_mapping[self.cur_dir]
# Your Robot object will be instantiated and called as such:
# obj = Robot(width, height)
# obj.step(num)
# param_2 = obj.getPos()
# param_3 = obj.getDir()
4.7.528 - 2025-08-21 12:07:22 +0300 MSK
Links
Code
class Solution:
def numberOfBeautifulIntegers(self, low: int, high: int, k: int) -> int:
low, hgh = str(low), str(high)
n = len(hgh)
low = low.rjust(n,'0')
@lru_cache(None)
def dfs(idx,
belowHgh,
aboveLow,
init0,
parity,
rem):
if idx == n:
return rem == 0 == parity
lowD, hghD = int(low[idx]), int(hgh[idx])
res = 0
for digit in range(0 if aboveLow else lowD,
(9 if belowHgh else hghD) + 1):
res += dfs(idx + 1,
belowHgh or digit < hghD,
aboveLow or digit > lowD,
init0 and not digit,
parity + digit % 2 - (
not init0 and not digit or
digit and not digit % 2),
(rem * 10 + digit) % k)
return res
return dfs(0, False, False, True, 0, 0)
4.7.529 - 2025-08-21 11:45:30 +0300 MSK
Links
Code
class Solution:
def minimumSeconds(self, nums: List[int]) -> int:
nums += nums
indices = defaultdict(list)
for i, num in enumerate(nums):
indices[num].append(i)
min_diff = math.inf
for idxs in indices.values():
max_diff = -math.inf
for i1, i2 in itertools.pairwise(idxs):
max_diff = max(max_diff, i2 - i1)
min_diff = min(min_diff, max_diff // 2)
return min_diff
4.7.530 - 2025-08-21 11:32:12 +0300 MSK
Links
Code
class Solution:
def longestSubsequence(self, arr: List[int], difference: int) -> int:
dp = {}
for num in arr:
prv = num - difference
if prv in dp:
dp[num] = dp[prv] + 1
else:
dp[num] = 1
return max(dp.values())
4.7.531 - 2025-08-21 11:29:38 +0300 MSK
Links
Code
class Solution:
def longestSubsequence(self, arr: List[int], difference: int) -> int:
n = len(arr)
freqs = defaultdict(list)
for i, num in enumerate(arr):
freqs[num].append(i)
dp = [1] * n
for i in reversed(range(n - 1)):
cur, nxt = arr[i], arr[i] + difference
if nxt not in freqs:
continue
cnt = 0
for j in freqs[nxt]:
if j > i:
cnt = max(cnt, dp[j])
dp[i] = cnt + 1
return max(dp)
4.7.532 - 2025-08-21 11:16:33 +0300 MSK
Links
Code
class Solution:
def minimumString(self, a: str, b: str, c: str) -> str:
res, l = '', float('inf')
def merge(s1: str, s2: str) -> str:
if s2 in s1:
return s1
for i in range(len(s1)):
if s2.startswith(s1[i:]):
return s1[:i] + s2
return s1 + s2
for s1, s2, s3 in itertools.permutations((a, b ,c)):
merged = merge(merge(s1, s2), s3)
if len(merged) < l:
res, l = merged, len(merged)
elif len(merged) == l:
res = min(res, merged)
return res
4.7.533 - 2025-08-21 11:08:30 +0300 MSK
Links
Code
class NeighborSum:
def __init__(self, grid: List[List[int]]):
self._adj = [0] * 101
self._diag = [0] * 101
rows, cols = len(grid), len(grid[0])
adj_moves = ((0, 1), (0, -1), (-1, 0), (1, 0))
diag_moves = ((-1, -1), (-1, 1), (1, -1), (1, 1))
for row in range(rows):
for col in range(cols):
val = grid[row][col]
for row_dlt, col_dlt in adj_moves:
adj_row, adj_col = row + row_dlt, col + col_dlt
if 0 <= adj_row < rows and 0 <= adj_col < cols:
self._adj[grid[adj_row][adj_col]] += val
for row_dlt, col_dlt in diag_moves:
diag_row, diag_col = row + row_dlt, col + col_dlt
if 0 <= diag_row < rows and 0 <= diag_col < cols:
self._diag[grid[diag_row][diag_col]] += val
def adjacentSum(self, value: int) -> int:
return self._adj[value]
def diagonalSum(self, value: int) -> int:
return self._diag[value]
# Your NeighborSum object will be instantiated and called as such:
# obj = NeighborSum(grid)
# param_1 = obj.adjacentSum(value)
# param_2 = obj.diagonalSum(value)
4.7.534 - 2025-08-21 08:52:21 +0300 MSK
Links
Code
class Solution:
def numSubmat(self, mat: List[List[int]]) -> int:
heights = [0] * len(mat[0])
res = 0
for row in mat:
for i, x in enumerate(row):
heights[i] = 0 if x == 0 else heights[i] + 1
stack = [[-1, 0, -1]]
for i, h in enumerate(heights):
while stack[-1][2] >= h:
stack.pop()
j, prev, _ = stack[-1]
cur = prev + (i - j) * h
stack.append([i, cur, h])
res += cur
return res
4.7.535 - 2025-08-20 20:41:08 +0300 MSK
Links
Code
/**
* @param {number[]} arr
* @param {Function} fn
* @return {number[]}
*/
var map = function(arr, fn) {
const transformedArr = [];
let index = 0;
for (const element of arr) {
transformedArr[index] = fn(element, index);
index++;
}
return transformedArr;
};
4.7.536 - 2025-08-20 20:38:27 +0300 MSK
Links
Code
/**
* @param {number[]} arr
* @param {Function} fn
* @return {number[]}
*/
var filter = function(arr, fn) {
let res = [];
for (const [i, val] of arr.entries()) {
if (fn(val, i)) {
res.push(val);
}
}
return res;
};
4.7.537 - 2025-08-20 20:36:18 +0300 MSK
Links
Code
/**
* @param {Function[]} functions
* @return {Function}
*/
var compose = function(functions) {
if (functions.length === 0) {
return function(x) { return x; };
}
return functions.reduceRight(function(prevFn, nextFn) {
return function(x) {
return nextFn(prevFn(x));
};
});
};
4.7.538 - 2025-08-20 20:31:33 +0300 MSK
Links
Code
/**
* @param {number[]} nums
* @param {Function} fn
* @param {number} init
* @return {number}
*/
var reduce = function(nums, fn, init) {
let res = init;
for (const num of nums) {
res = fn(res, num);
}
return res;
};
4.7.539 - 2025-08-20 20:28:21 +0300 MSK
Links
Code
/**
* @param {number} millis
* @return {Promise}
*/
async function sleep(millis) {
return new Promise((resolve) => setTimeout(resolve, millis));
}
/**
* let t = Date.now()
* sleep(100).then(() => console.log(Date.now() - t)) // 100
*/
4.7.540 - 2025-08-20 20:26:57 +0300 MSK
Links
Code
/**
* @param {number} n
* @return {Function} counter
*/
var createCounter = function(n) {
val = n - 1;
return function() {
val += 1;
return val;
};
};
/**
* const counter = createCounter(10)
* counter() // 10
* counter() // 11
* counter() // 12
*/
4.7.541 - 2025-08-20 20:25:45 +0300 MSK
Links
Code
/**
* @return {null|boolean|number|string|Array|Object}
*/
Array.prototype.last = function() {
if (this.length > 0) {
return this[this.length - 1];
}
return -1;
};
/**
* const arr = [1, 2, 3];
* arr.last(); // 3
*/
4.7.542 - 2025-08-20 20:20:02 +0300 MSK
Links
Code
class Solution:
def diagonalPrime(self, nums: List[List[int]]) -> int:
def is_prime(num: int) -> int:
if num <= 1:
return 0
for i in range(2, int(math.sqrt(num)) + 1):
if num % i == 0:
return 0
return num
res = 0
n = len(nums)
for i in range(n):
res = max(res, is_prime(nums[i][i]), is_prime(nums[i][n - i - 1]))
return res
4.7.543 - 2025-08-20 20:15:03 +0300 MSK
Links
Code
class Solution:
def findTheLongestBalancedSubstring(self, s: str) -> int:
res = 0
cnt_0, cnt_1 = 0, 0
for char in s:
if char == "0":
if cnt_1 != 0:
cnt_0 = 0
cnt_0 += 1
cnt_1 = 0
else:
cnt_1 += 1
res = max(res, min(cnt_0, cnt_1) * 2)
return res
4.7.544 - 2025-08-20 20:10:18 +0300 MSK
Links
Code
class Solution:
def minNumber(self, nums1: List[int], nums2: List[int]) -> int:
freqs1 = [False] * 10
freqs2 = [False] * 10
for num in nums1:
freqs1[num] = True
for num in nums2:
freqs2[num] = True
min1, min2 = None, None
for i in range(10):
if freqs1[i] and freqs2[i]:
return i
if min1 is None and freqs1[i]:
min1 = i
if min2 is None and freqs2[i]:
min2 = i
return min(min1, min2) * 10 + max(min1, min2)
4.7.545 - 2025-08-20 19:48:54 +0300 MSK
Links
Code
class Solution:
def kItemsWithMaximumSum(self, numOnes: int, numZeros: int, numNegOnes: int, k: int) -> int:
res = 0
for val, cnt in ((1, numOnes), (0, numZeros), (-1, numNegOnes)):
if k == 0:
break
cnt = min(k, cnt)
k -= cnt
res += val * cnt
return res
4.7.546 - 2025-08-20 19:41:49 +0300 MSK
Links
Code
class Solution:
def distMoney(self, money: int, children: int) -> int:
if money < children:
return -1
n = 8 * children - money
if n <= 0:
return children - (n < 0)
ans, rem = divmod(money - children, 7)
return ans - ((ans, rem) == (children - 1, 3))
4.7.547 - 2025-08-20 19:24:46 +0300 MSK
Links
Code
class Solution:
def vowelStrings(self, words: List[str], left: int, right: int) -> int:
res = 0
vowels = ("a", "e", "i", "o", "u")
for i in range(left, right + 1):
word = words[i]
if word[0] in vowels and word[-1] in vowels:
res += 1
return res
4.7.548 - 2025-08-20 19:22:34 +0300 MSK
Links
Code
class Solution:
def passThePillow(self, n, time):
full_rounds = time // (n - 1)
extra_time = time % (n - 1)
if full_rounds % 2 == 0:
return extra_time + 1
else:
return n - extra_time
4.7.549 - 2025-08-20 19:11:13 +0300 MSK
Links
Code
class Solution:
def splitNum(self, num: int) -> int:
count = 0
digits = []
while num > 0:
digits.append(num % 10)
num //= 10
digits.sort()
res = 0
while digits:
for _ in range(2):
if digits:
res += digits.pop() * (10 ** count)
count += 1
return res
4.7.550 - 2025-08-20 19:07:59 +0300 MSK
Links
Code
class Solution:
def leftRightDifference(self, nums: List[int]) -> List[int]:
left, right = 0, sum(nums)
for i in range(len(nums)):
val = nums[i]
right -= val
nums[i] = abs(left - right)
left += val
return nums
4.7.551 - 2025-08-20 19:05:44 +0300 MSK
Links
Code
class Solution:
def mergeArrays(self, nums1: List[List[int]], nums2: List[List[int]]) -> List[List[int]]:
freqs = [0] * 1001
for idx, val in itertools.chain(nums1, nums2):
freqs[idx] += val
res = []
for i, freq in enumerate(freqs):
if freq > 0:
res.append((i, freq))
return res
4.7.552 - 2025-08-20 19:01:55 +0300 MSK
Links
Code
class Solution:
def minMaxDifference(self, num: int) -> int:
s = str(num)
t = s
pos = 0
while pos < len(s) and s[pos] == "9":
pos += 1
if pos < len(s):
s = s.replace(s[pos], "9")
t = t.replace(t[0], "0")
return int(s) - int(t)
4.7.553 - 2025-08-20 18:54:48 +0300 MSK
Links
Code
class Solution:
def findTheArrayConcVal(self, nums: List[int]) -> int:
def concat(num1: int, num2: int) -> int:
res = 0
count = 0
for num in (num2, num1):
while num > 0:
res += (num % 10) * (10 ** count)
count += 1
num //= 10
return res
left, right = 0, len(nums) - 1
res = 0
while left <= right:
num1, num2 = nums[left], nums[right]
if left == right:
res += num1
else:
res += concat(num1, num2)
left += 1
right -= 1
return res
4.7.554 - 2025-08-20 18:49:12 +0300 MSK
Links
Code
class Solution:
def pickGifts(self, gifts: List[int], k: int) -> int:
for i in range(len(gifts)):
gifts[i] = -gifts[i]
heapq.heapify(gifts)
for _ in range(k):
val = int(math.sqrt(-heapq.heappop(gifts)))
heapq.heappush(gifts, -val)
return -sum(gifts)
4.7.555 - 2025-08-20 18:45:47 +0300 MSK
Links
Code
class Solution:
def separateDigits(self, nums: List[int]) -> List[int]:
res = []
cur = []
for num in nums:
while num > 0:
cur.append(num % 10)
num //= 10
cur.reverse()
res.extend(cur)
cur.clear()
return res
4.7.556 - 2025-08-20 18:44:00 +0300 MSK
Links
Code
class Solution:
def distinctIntegers(self, n: int) -> int:
if n == 1:
return 1
return n - 1
4.7.557 - 2025-08-20 18:28:35 +0300 MSK
Links
Code
class Solution:
def alternateDigitSum(self, n: int) -> int:
sign = 1
count = 0
res = 0
while n > 0:
res += (n % 10) * sign
sign *= -1
count += 1
n //= 10
if count % 2 == 0:
return -res
return res
4.7.558 - 2025-08-20 18:24:20 +0300 MSK
Links
Code
class Solution:
def differenceOfSum(self, nums: List[int]) -> int:
el_sum, dig_sum = 0, 0
for num in nums:
el_sum += num
while num > 0:
dig_sum += num % 10
num //= 10
return abs(el_sum - dig_sum)
4.7.559 - 2025-08-20 18:23:07 +0300 MSK
Links
Code
class Solution:
def maximumCount(self, nums: List[int]) -> int:
left, right = 0, len(nums) - 1
start_neg, start_pos = -1, len(nums)
while left <= right:
mid = left + (right - left) // 2
if nums[mid] >= 0:
right = mid - 1
else:
start_neg = mid
left = mid + 1
left, right = start_neg + 1, len(nums) - 1
while left <= right:
mid = left + (right - left) // 2
if nums[mid] > 0:
start_pos = mid
right = mid - 1
else:
left = mid + 1
return max(start_neg + 1, len(nums) - start_pos)
4.7.560 - 2025-08-20 18:22:39 +0300 MSK
Links
Code
class Solution:
def maximumCount(self, nums: List[int]) -> int:
left, right = 0, len(nums) - 1
start_neg, start_pos = -1, len(nums)
while left <= right:
mid = left + (right - left) // 2
if nums[mid] >= 0:
right = mid - 1
else:
start_neg = mid
left = mid + 1
left, right = start_neg + 1, len(nums) - 1
while left <= right:
mid = left + (right - left) // 2
if nums[mid] > 0:
start_pos = mid
right = mid - 1
else:
left = mid + 1
print(start_neg, start_pos)
return max(start_neg + 1, len(nums) - start_pos)
4.7.561 - 2025-08-20 17:57:07 +0300 MSK
Links
Code
class Solution:
def categorizeBox(self, length: int, width: int, height: int, mass: int) -> str:
is_bulky = (
max(length, width, height) >= 10 ** 4
or length * width * height >= 10 ** 9
)
is_heavy = mass >= 100
if is_bulky and is_heavy:
return "Both"
if is_bulky and not is_heavy:
return "Bulky"
if is_heavy and not is_bulky:
return "Heavy"
return "Neither"
4.7.562 - 2025-08-20 17:48:38 +0300 MSK
Links
Code
class Solution:
def countDigits(self, num: int) -> int:
cur = num
res = 0
while cur > 0:
dig = cur % 10
if num % dig == 0:
res += 1
cur //= 10
return res
4.7.563 - 2025-08-20 17:47:52 +0300 MSK
Links
Code
class Solution:
def closestTarget(self, words: List[str], target: str, startIndex: int) -> int:
n = len(words)
for i in range(n):
left, right = (startIndex - i + n) % n, (startIndex + i) % n
if words[left] == target or words[right] == target:
return i
return -1
4.7.564 - 2025-08-20 17:43:24 +0300 MSK
Links
Code
class Solution:
def captureForts(self, forts: List[int]) -> int:
start = None
max_capt = 0
for i, fort in enumerate(forts):
if fort == 0:
continue
if start is None:
start = i
continue
start_val = forts[start]
if (start_val == 1 and fort == -1) or (start_val == -1 and fort == 1):
max_capt = max(max_capt, i - start - 1)
start = i
return max_capt
4.7.565 - 2025-08-20 17:23:29 +0300 MSK
Links
Code
class Solution:
def similarPairs(self, words: List[str]) -> int:
freqs = defaultdict(int)
res = 0
for word in words:
freq = 0
for char in word:
freq |= 1 << (ord(char) - 97)
res += freqs[freq]
freqs[freq] += 1
return res
4.7.566 - 2025-08-20 17:18:47 +0300 MSK
Links
Code
class Solution:
def similarPairs(self, words: List[str]) -> int:
freqs = [False] * 26
freqs2 = defaultdict(int)
for word in words:
for char in word:
freqs[ord(char) - 97] = True
freqs2[tuple(freqs)] += 1
for i in range(26):
freqs[i] = False
res = 0
for freq in freqs2.values():
for i in range(freq):
res += (freq - i - 1)
return res
4.7.567 - 2025-08-20 15:09:02 +0300 MSK
Links
Code
class Solution:
def deleteGreatestValue(self, grid: List[List[int]]) -> int:
for row in grid:
row.sort()
res = 0
for _ in range(len(grid[0])):
cur_sum = 0
for row in grid:
cur_sum = max(cur_sum, row.pop())
res += cur_sum
return res
4.7.568 - 2025-08-20 13:48:16 +0300 MSK
Links
Code
class Solution:
def maximumValue(self, strs: List[str]) -> int:
max_val = 0
for s in strs:
if s.isdigit():
val = int(s)
else:
val = len(s)
if val > max_val:
max_val = val
return max_val
4.7.569 - 2025-08-20 13:45:38 +0300 MSK
Links
Code
class Solution:
def isCircularSentence(self, sentence: str) -> bool:
if sentence[0] != sentence[-1]:
return False
for i, char in enumerate(sentence):
if char == " " and sentence[i - 1] != sentence[i + 1]:
return False
return True
4.7.570 - 2025-08-20 13:41:05 +0300 MSK
Links
Code
class Solution:
def numberOfCuts(self, n: int) -> int:
if n == 1:
return 0
if n % 2 == 0:
return n // 2
return n
4.7.571 - 2025-08-20 13:36:58 +0300 MSK
Links
Code
class Solution:
def unequalTriplets(self, nums: List[int]) -> int:
freqs = [0] * 1001
for num in nums:
freqs[num] += 1
res = 0
left = 0
right = len(nums)
for freq in freqs:
if freq == 0:
continue
right -= freq
res += left * freq * right
left += freq
return res
4.7.572 - 2025-08-20 13:29:30 +0300 MSK
Links
Code
class Solution:
def unequalTriplets(self, nums: List[int]) -> int:
freqs = [0] * 1001
for num in nums:
freqs[num] += 1
res = 0
left = 0
right = len(nums)
for freq in freqs:
if freq == 0:
continue
right -= freq
res += left * freq * right
left += freq
return res
4.7.573 - 2025-08-20 13:16:55 +0300 MSK
Links
Code
class Solution:
def convertTemperature(self, celsius: float) -> List[float]:
return (celsius + 273.15, (celsius * 1.80 + 32.00))
4.7.574 - 2025-08-20 13:13:48 +0300 MSK
Links
Code
class Solution:
def distinctAverages(self, nums: List[int]) -> int:
nums.sort()
freqs = [False] * 201
n = len(nums)
res = 0
for i in range(n // 2 + 1):
freq = nums[i] + nums[n - i - 1]
if not freqs[freq]:
res += 1
freqs[freq] = True
return res
4.7.575 - 2025-08-20 13:06:17 +0300 MSK
Links
Code
class Solution:
def applyOperations(self, nums: List[int]) -> List[int]:
n = len(nums)
for i in range(1, n):
cur, prev = nums[i], nums[i - 1]
if prev != 0 and cur == prev:
nums[i], nums[i - 1] = 0, prev * 2
left, right = 0, 1
while left < n and right < n:
num1, num2 = nums[left], nums[right]
if num1 != 0:
left += 1
elif num2 == 0:
right += 1
elif left >= right:
right += 1
else:
nums[left], nums[right] = num2, 0
left += 1
right += 1
return nums
4.7.576 - 2025-08-20 12:43:09 +0300 MSK
Links
Code
class Solution:
def averageValue(self, nums: List[int]) -> int:
res = 0
cnt = 0
for num in nums:
if num % 2 == 0 and num % 3 == 0:
cnt += 1
res += num
if cnt == 0:
return 0
return res // cnt
4.7.577 - 2025-08-20 12:38:03 +0300 MSK
Links
Code
class Solution:
def oddString(self, words: List[str]) -> str:
freq1, freq2, cur = None, None, []
freq1_word, freq2_word = None, None
freq1_cnt, freq2_cnt = 0, 0
for word in words:
for i in range(1, len(word)):
cur.append(ord(word[i]) - ord(word[i - 1]))
if freq1 is None:
freq1, freq1_word, freq1_cnt = cur, word, 1
cur = []
elif cur == freq1:
freq1_cnt += 1
elif freq2 is None:
freq2, freq2_word, freq2_cnt = cur, word, 1
cur = []
elif cur == freq2:
freq2_cnt += 1
cur.clear()
if min(freq1_cnt, freq2_cnt) == 1 and max(freq1_cnt, freq2_cnt) > 1:
if freq1_cnt == 1:
return freq1_word
return freq2_word
raise Exception
4.7.578 - 2025-08-20 12:08:13 +0300 MSK
Links
Code
class Solution:
def countSquares(self, matrix: List[List[int]]) -> int:
rows, cols = len(matrix), len(matrix[0])
dp = [[0] * (cols + 1) for _ in range(rows + 1)]
res = 0
for row in range(rows):
for col in range(cols):
val = matrix[row][col]
if val == 0:
continue
dp_row, dp_col = row + 1, col + 1
dp_val = min(
dp[dp_row - 1][dp_col],
dp[dp_row][dp_col - 1],
dp[dp_row - 1][dp_col - 1]
) + 1
dp[dp_row][dp_col] = dp_val
res += dp_val
return res
4.7.579 - 2025-08-19 20:23:46 +0300 MSK
Links
Code
class Solution:
def haveConflict(self, event1: List[str], event2: List[str]) -> bool:
def parse(clock: str) -> int:
hh, mm = clock[:2], clock[2:]
return hh * 60 + mm
start1, end1 = map(parse, event1)
start2, end2 = map(parse, event2)
if start1 == start2:
return True
if start1 > start2:
return start1 <= end2
return end1 >= start2
4.7.580 - 2025-08-19 20:13:25 +0300 MSK
Links
Code
class Solution:
def countTime(self, time: str) -> int:
hh, mm = time.split(':')
count_possible_hours = 1
if (hh == '??'):
count_possible_hours = 24
elif (hh[0] == '?' and int(hh[1]) >= 4):
count_possible_hours = 2
elif (hh[0] == '?' and int(hh[1]) <= 4):
count_possible_hours = 3
elif (int(hh[0]) <= 1 and hh[1] == '?'):
count_possible_hours = 10
elif (int(hh[0]) == 2 and hh[1] == '?'):
count_possible_hours = 4
count_possible_minutes = 1
if (mm == '??'):
count_possible_minutes = 60
elif (mm[0] == '?'):
count_possible_minutes = 6
elif (mm[1] == '?'):
count_possible_minutes = 10
return count_possible_hours * count_possible_minutes
4.7.581 - 2025-08-19 20:11:33 +0300 MSK
Links
Code
class Solution:
def hardestWorker(self, n: int, logs: List[List[int]]) -> int:
max_id, max_dur = logs[0]
for i, (emp_id, leave) in enumerate(logs[1:], 1):
dur = leave - logs[i - 1][1]
if dur > max_dur:
max_id, max_dur = emp_id, dur
elif dur == max_dur and emp_id < max_id:
max_id = emp_id
return max_id
4.7.582 - 2025-08-19 20:00:15 +0300 MSK
Links
Code
class Solution:
def commonFactors(self, a: int, b: int) -> int:
res = 0
for i in range(1, min(a, b) + 1):
if a % i == 0 and b % i == 0:
res += 1
return res
4.7.583 - 2025-08-19 19:47:47 +0300 MSK
Links
Code
class Solution:
def equalFrequency(self, word: str) -> bool:
freqs1, freqs2 = defaultdict(int), defaultdict(int)
for char in word:
freqs1[char] += 1
for freq in freqs1.values():
freqs2[freq] += 1
if len(freqs2) == 1:
return next(iter(freqs2.keys())) == 1 or next(iter(freqs2.values())) == 1
if len(freqs2) == 2:
f1, f2 = min(freqs2.keys()), max(freqs2.keys())
return (
f1 + 1 == f2 and freqs2[f2] == 1
) or (
f1 == 1 and freqs2[f1] == 1
)
return False
4.7.584 - 2025-08-19 16:10:29 +0300 MSK
Links
Code
class Solution:
def sortPeople(self, names: List[str], heights: List[int]) -> List[str]:
for i in range(len(names)):
names[i] = (heights[i], names[i])
names.sort(reverse=True)
for i in range(len(names)):
names[i] = names[i][1]
return names
4.7.585 - 2025-08-19 15:27:24 +0300 MSK
Links
Code
class Solution:
def smallestEvenMultiple(self, n: int) -> int:
if n % 2 == 0:
return n
return n * 2
4.7.586 - 2025-08-19 15:24:40 +0300 MSK
Links
Code
class Solution:
def countDaysTogether(self, arriveAlice: str, leaveAlice: str, arriveBob: str, leaveBob: str) -> int:
months = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
def count(date: str) -> int:
month = int(date[:2])
days = int(date[3:])
return sum(months[:month - 1]) + days
return max(0, count(min(leaveAlice, leaveBob)) - count(max(arriveAlice, arriveBob)) + 1)
4.7.587 - 2025-08-19 15:04:21 +0300 MSK
Links
Code
class Solution:
def mostFrequentEven(self, nums: List[int]) -> int:
nums.sort()
max_freq, max_freq_num = 0, -1
cur_freq = 0
prev = -1
for num in nums:
if num % 2 != 0:
continue
if num == prev:
cur_freq += 1
else:
cur_freq, prev = 1, num
if cur_freq > max_freq:
max_freq, max_freq_num = cur_freq, num
return max_freq_num
4.7.588 - 2025-08-19 14:58:59 +0300 MSK
Links
Code
class Solution:
def checkDistances(self, s: str, distance: List[int]) -> bool:
for i, char in enumerate(s):
idx = ord(char) - 97
dist = distance[idx]
if dist == -1:
continue
nxt = i + dist + 1
if nxt >= len(s) or s[nxt] != char:
return False
distance[idx] = -1
return True
4.7.589 - 2025-08-19 14:42:34 +0300 MSK
Links
Code
class Solution:
def findSubarrays(self, nums: List[int]) -> bool:
enc = set()
for i in range(1, len(nums)):
val = nums[i] + nums[i - 1]
if val in enc:
return True
enc.add(val)
return False
4.7.590 - 2025-08-19 14:37:35 +0300 MSK
Links
Code
class Solution:
def answerQueries(self, nums: List[int], queries: List[int]) -> List[int]:
nums.sort()
for i in range(1, len(nums)):
nums[i] += nums[i - 1]
for i in range(len(queries)):
target = queries[i]
count = 0
for num in nums:
if num <= target:
count += 1
else:
break
queries[i] = count
return queries
4.7.591 - 2025-08-19 14:29:00 +0300 MSK
Links
Code
class Solution:
def minNumberOfHours(self, initialEnergy: int, initialExperience: int, energy: List[int], experience: List[int]) -> int:
res = max(0, sum(energy) - initialEnergy + 1)
for exp in experience:
if initialExperience <= exp:
diff = exp - initialExperience + 1
res += diff
initialExperience += diff
initialExperience += exp
return res
4.7.592 - 2025-08-19 14:04:31 +0300 MSK
Links
Code
class Solution:
def minimumRecolors(self, blocks: str, k: int) -> int:
left = 0
num_whites = 0
num_recolors = math.inf
for right in range(len(blocks)):
if blocks[right] == "W":
num_whites += 1
if right - left + 1 == k:
num_recolors = min(num_recolors, num_whites)
if blocks[left] == "W":
num_whites -= 1
left += 1
return num_recolors
4.7.593 - 2025-08-19 13:54:21 +0300 MSK
Links
Code
class Solution:
def arithmeticTriplets(self, nums: List[int], diff: int) -> int:
freqs = [[] for _ in range(201)]
for i, num in enumerate(nums):
freqs[num].append(i)
length = len(nums)
res = 0
for i in range(length):
num1 = nums[i]
for j in range(i + 1, length):
num2 = nums[j]
if num2 - num1 != diff:
continue
num3 = num2 + diff
if num3 > 200:
continue
for k in freqs[num3]:
if k > j:
res += 1
break
return res
4.7.594 - 2025-08-19 13:40:19 +0300 MSK
Links
Code
class Solution:
def mergeSimilarItems(self, items1: List[List[int]], items2: List[List[int]]) -> List[List[int]]:
freqs = [0] * 1001
for val, weight in itertools.chain(items1, items2):
freqs[val] += weight
res = [(num, weight) for num, weight in enumerate(freqs) if weight != 0]
return res
4.7.595 - 2025-08-19 13:37:47 +0300 MSK
Links
Code
class Solution:
def mergeSimilarItems(self, items1: List[List[int]], items2: List[List[int]]) -> List[List[int]]:
freqs = [(i, 0) for i in range(1001)]
for val, weight in itertools.chain(items1, items2):
_, cur_weight = freqs[val]
freqs[val] = (val, weight + cur_weight)
freqs.sort(reverse=True, key=lambda val: val[1])
while freqs and freqs[-1][1] == 0:
freqs.pop()
freqs.sort()
return freqs
4.7.596 - 2025-08-19 13:11:40 +0300 MSK
Links
Code
class Solution:
def minimumOperations(self, nums: List[int]) -> int:
nums.sort(reverse=True)
res = 0
while nums:
num = nums.pop()
if num == 0:
continue
for i in range(len(nums)):
nums[i] = max(0, nums[i] - num)
res += 1
return res
4.7.597 - 2025-08-19 11:34:12 +0300 MSK
Links
Code
SELECT
teacher_id,
COUNT(DISTINCT subject_id) AS "cnt"
FROM
Teacher
GROUP BY
teacher_id
4.7.598 - 2025-08-19 09:58:54 +0300 MSK
Links
Code
class Solution:
def repeatedCharacter(self, s: str) -> str:
freqs = [0] * 26
for char in s:
idx = ord(char) - 97
freq = freqs[idx] + 1
if freq == 2:
return char
freqs[idx] = freq
raise Exception
4.7.599 - 2025-08-19 08:52:54 +0300 MSK
Links
Code
class Solution:
def bestHand(self, ranks: List[int], suits: List[str]) -> str:
ranks.sort()
suits.sort()
same_suit = 1
cur_same_suit = 1
same_rank = 1
cur_same_rank = 1
for i in range(1, len(ranks)):
if ranks[i] == ranks[i - 1]:
cur_same_rank += 1
same_rank = max(same_rank, cur_same_rank)
else:
cur_same_rank = 1
if suits[i] == suits[i - 1]:
cur_same_suit += 1
same_suit = max(same_suit, cur_same_suit)
else:
cur_same_suit = 1
print(same_suit, same_rank)
if same_suit == 5:
return "Flush"
if same_rank >= 3:
return "Three of a Kind"
if same_rank >= 2:
return "Pair"
return "High Card"
4.7.600 - 2025-08-19 08:18:09 +0300 MSK
Links
Code
class Solution:
def zeroFilledSubarray(self, nums: List[int]) -> int:
res = 0
cur = 0
for num in nums:
if num == 0:
cur += 1
res += cur
elif cur != 0:
cur = 0
return res
4.7.601 - 2025-08-18 21:10:17 +0300 MSK
Links
Code
class Solution:
def numberOfPairs(self, nums: List[int]) -> List[int]:
cnt_pair, cnt_rest = 0, 0
nums.sort()
length = len(nums)
i = 0
while i < length:
cur = nums[i]
nxt = nums[i + 1] if i + 1 < length else -1
if nxt == cur:
cnt_pair += 1
i += 2
else:
cnt_rest += 1
i += 1
return cnt_pair, cnt_rest
4.7.602 - 2025-08-18 21:06:45 +0300 MSK
Links
Code
class Solution:
def fillCups(self, amount: List[int]) -> int:
res = 0
for i in range(len(amount)):
amount[i] = -amount[i]
heapq.heapify(amount)
while len(amount) > 2:
num1, num2 = heapq.heappop(amount), heapq.heappop(amount)
if num1 < 0 or num2 < 0:
res += 1
if num1 < 0:
num1 += 1
heapq.heappush(amount, num1)
if num2 < 0:
num2 += 1
heapq.heappush(amount, num2)
if len(amount) == 1:
return res - amount[0]
num1, num2 = amount
res += min(-num1, -num2) + abs(num1 - num2)
return res
4.7.603 - 2025-08-18 20:23:18 +0300 MSK
Links
Code
class Solution:
def decodeMessage(self, key: str, message: str) -> str:
subst = [-1] * 26
res = []
count = 0
for char in key:
if char == " ":
continue
idx = ord(char) - 97
if subst[idx] == -1:
subst[idx] = count
count += 1
for char in message:
if char == " ":
val = char
else:
val = chr(subst[ord(char) - 97] + 97)
res.append(val)
return "".join(res)
4.7.604 - 2025-08-18 20:18:16 +0300 MSK
Links
Code
class Solution:
def checkXMatrix(self, grid: List[List[int]]) -> bool:
length = len(grid)
for row in range(length):
for col in range(length):
is_diag = row == col or length - row - 1 == col
val = grid[row][col]
if (is_diag and val == 0) or (not is_diag and val != 0):
return False
return True
4.7.605 - 2025-08-18 20:07:07 +0300 MSK
Links
Code
class Solution:
def countAsterisks(self, s: str) -> int:
start = False
res = 0
for char in s:
if char == "|":
start = not start
elif char == "*" and not start:
res += 1
return res
4.7.606 - 2025-08-18 20:04:04 +0300 MSK
Links
Code
class Solution:
def greatestLetter(self, s: str) -> str:
freqs = [(False, False)] * 26
for char in reversed(s):
if char.islower():
idx = ord(char) - 97
is_lower = True
else:
idx = ord(char) - 65
is_lower = False
enc_lower, enc_upper = freqs[idx]
new_val = (enc_lower or is_lower, enc_upper or not is_lower)
if new_val != (enc_lower, enc_upper):
freqs[idx] = new_val
for i in reversed(range(len(freqs))):
if all(freqs[i]):
return chr(i + 65)
return ""
4.7.607 - 2025-08-18 19:52:53 +0300 MSK
Links
Code
class Solution:
def calculateTax(self, brackets: List[List[int]], income: int) -> float:
tax = prev = 0
for upper, perc in brackets:
if income >= upper:
tax += (upper - prev) * perc / 100
prev = upper
else:
tax += (income - prev) * perc / 100
return tax
return tax
4.7.608 - 2025-08-18 19:41:27 +0300 MSK
Links
Code
class Solution:
def strongPasswordCheckerII(self, password: str) -> bool:
if len(password) < 8:
return False
has_lower, has_upper, has_digit, has_spec = False, False, False, False
prev = None
spec = "!@#$%^&*()-+"
for char in password:
if char.islower():
has_lower = True
elif char.isupper():
has_upper = True
elif char.isdigit():
has_digit = True
elif char in spec:
has_spec = True
if prev is not None and char == prev:
return False
prev = char
return has_lower and has_upper and has_digit and has_spec
4.7.609 - 2025-08-18 19:36:10 +0300 MSK
Links
Code
class Solution:
def minMaxGame(self, nums: List[int]) -> int:
while len(nums) > 1:
length = len(nums) // 2
for i in range(length):
if i % 2 == 0:
nums[i] = min(nums[i * 2], nums[i * 2 + 1])
else:
nums[i] = max(nums[i * 2], nums[i * 2 + 1])
while len(nums) > length:
nums.pop()
return nums[0]
4.7.610 - 2025-08-18 19:26:10 +0300 MSK
Links
Code
class Solution:
def rearrangeCharacters(self, s: str, target: str) -> int:
freqs1, freqs2 = [0] * 26, [0] * 26
for char in s:
freqs1[ord(char) - 97] += 1
for char in target:
freqs2[ord(char) - 97] += 1
count = math.inf
for i in range(26):
freq1, freq2 = freqs1[i], freqs2[i]
if freq2 == 0:
continue
cur_count = freq1 // freq2
if cur_count == 0:
return 0
if cur_count < count:
count = cur_count
return count
4.7.611 - 2025-08-18 19:21:41 +0300 MSK
Links
Code
class Solution:
def digitCount(self, num: str) -> bool:
freqs = [0] * 10
for char in num:
freqs[int(char)] += 1
for i, char in enumerate(num):
if freqs[i] != int(char):
return False
return True
4.7.612 - 2025-08-18 19:16:20 +0300 MSK
Links
Code
class Solution:
def percentageLetter(self, s: str, letter: str) -> int:
count = 0
for char in s:
if char == letter:
count += 1
return (count * 100) // len(s)
4.7.613 - 2025-08-18 19:11:33 +0300 MSK
Links
Code
class Solution:
def removeAnagrams(self, words: List[str]) -> List[str]:
freqs1, freqs2 = bytearray(26), bytearray(26)
res = []
for i, word in enumerate(words):
for i in range(26):
freqs2[i] = 0
for char in word:
freqs2[ord(char) - 97] += 1
if i != 0 and freqs1 == freqs2:
continue
freqs1, freqs2 = freqs2, freqs1
res.append(word)
return res
4.7.614 - 2025-08-18 19:02:01 +0300 MSK
Links
Code
class Solution:
def removeAnagrams(self, words: List[str]) -> List[str]:
prev = ()
res = []
for word in words:
word_sorted = sorted(word)
if prev != word_sorted:
res.append(word)
prev = word_sorted
return res
4.7.615 - 2025-08-18 18:43:22 +0300 MSK
Links
Code
class Solution:
def divisorSubstrings(self, num: int, k: int) -> int:
digits = []
cur_num = num
while cur_num > 0:
digits.append(cur_num % 10)
cur_num //= 10
digits.reverse()
length = len(digits)
if length < k:
return 0
cur_sum = 0
res = 0
for i in range(k):
cur_sum += digits[i] * (10 ** (k - i - 1))
if num % cur_sum == 0:
res += 1
i = k
while i < length:
cur_sum -= digits[i - k] * (10 ** (k - 1))
cur_sum = cur_sum * 10 + digits[i]
if cur_sum != 0 and num % cur_sum == 0:
res += 1
i += 1
return res
4.7.616 - 2025-08-18 15:12:00 +0300 MSK
Links
Code
class Solution:
def removeDigit(self, number: str, digit: str) -> str:
last_index = 0
digit_int = int(digit)
for i in range(1, len(number)):
cur, prev = int(number[i]), int(number[i - 1])
if prev == digit_int:
if cur > prev:
return "".join((number[:i-1], number[i:]))
else:
last_index = i - 1
if number[-1] == digit:
last_index = len(number) - 1
return "".join((number[:last_index], number[last_index + 1:]))
4.7.617 - 2025-08-18 15:03:06 +0300 MSK
Links
Code
class Solution:
def countPrefixes(self, words: List[str], s: str) -> int:
res = 0
for word in words:
if s.startswith(word):
res += 1
return res
4.7.618 - 2025-08-18 14:55:52 +0300 MSK
Links
Code
class Solution:
def intersection(self, nums: List[List[int]]) -> List[int]:
length = len(nums)
freqs = [[False] * length for _ in range(1002)]
for i, arr in enumerate(nums):
for num in arr:
if not freqs[num][i]:
freqs[num][i] = True
nums.clear()
for num, freq in enumerate(freqs):
if all(freq):
nums.append(num)
return nums
4.7.619 - 2025-08-18 14:48:14 +0300 MSK
Links
Code
class Solution:
def intersection(self, nums: List[List[int]]) -> List[int]:
enc = set(nums[0])
for arr in nums[1:]:
enc.intersection_update(arr)
return sorted(enc)
4.7.620 - 2025-08-18 14:43:36 +0300 MSK
Links
Code
class Solution:
def digitSum(self, s: str, k: int) -> str:
res, cur, group = list(map(int, s)), [], []
i = 0
def add_digits(num: int) -> None:
if num == 0:
cur.append(0)
return
while num > 0:
group.append(num % 10)
num //= 10
group.reverse()
cur.extend(group)
group.clear()
while len(res) > k:
while i < len(res):
add_digits(sum(res[i:i + k]))
i += k
res, cur = cur, res
cur.clear()
i = 0
return "".join(map(str, res))
4.7.621 - 2025-08-18 13:44:46 +0300 MSK
Links
Code
class Solution:
def findClosestNumber(self, nums: List[int]) -> int:
max_diff, max_num = math.inf, 0
for num in nums:
diff = abs(num)
if diff < max_diff or (diff == max_diff and num > max_num):
max_diff, max_num = diff, num
return max_num
4.7.622 - 2025-08-18 13:40:40 +0300 MSK
Links
Code
class Solution:
def largestInteger(self, num: int) -> int:
odd, even, digits = [], [], []
while num > 0:
dig = num % 10
if dig % 2 == 0:
heapq.heappush(even, dig)
digits.append(True)
else:
heapq.heappush(odd, dig)
digits.append(False)
num //= 10
res = 0
for i in range(len(digits)):
if digits[i]:
target = even
else:
target = odd
res += heapq.heappop(target) * (10 ** i)
return res
4.7.623 - 2025-08-18 13:34:09 +0300 MSK
Links
Code
class Solution:
def largestInteger(self, num: int) -> int:
odd, even, res = [], [], []
while num > 0:
dig = num % 10
if dig % 2 == 0:
even.append(dig)
res.append(True)
else:
odd.append(dig)
res.append(False)
num //= 10
odd.sort(reverse=True)
even.sort(reverse=True)
res.reverse()
length = len(res)
num = 0
for i in reversed(range(length)):
if res[i]:
num += even.pop() * (10 ** (length - i - 1))
else:
num += odd.pop() * (10 ** (length - i - 1))
return num
4.7.624 - 2025-08-18 10:06:49 +0300 MSK
Links
Code
from typing import List
import math
class Solution:
def judgePoint24(self, cards: List[int]) -> bool:
EPS = 1e-6
def backtrack(nums: List[float]) -> bool:
if len(nums) == 1:
return abs(nums[0] - 24.0) < EPS
n = len(nums)
for i in range(n):
for j in range(i + 1, n):
rest = [nums[k] for k in range(n) if k != i and k != j]
a, b = nums[i], nums[j]
candidates = []
candidates.append(a + b)
candidates.append(a * b)
candidates.append(a - b)
candidates.append(b - a)
if abs(b) > EPS:
candidates.append(a / b)
if abs(a) > EPS:
candidates.append(b / a)
for x in candidates:
if backtrack(rest + [x]):
return True
return False
return backtrack([float(x) for x in cards])
4.7.625 - 2025-08-17 20:02:56 +0300 MSK
Links
Code
class Solution:
def convertTime(self, current: str, correct: str) -> int:
current_time = 60 * int(current[0:2]) + int(current[3:5])
target_time = 60 * int(correct[0:2]) + int(correct[3:5])
diff = target_time - current_time
count = 0
for i in (60, 15, 5, 1):
count += diff // i
diff %= i
return count
4.7.626 - 2025-08-17 19:56:52 +0300 MSK
Links
Code
class Solution:
def divideArray(self, nums: List[int]) -> bool:
nums.sort()
prev = nums[0]
count = 1
for num in nums[1:]:
if num == prev:
count += 1
elif count % 2 != 0:
return False
else:
count = 1
prev = num
return count % 2 == 0
4.7.627 - 2025-08-17 19:54:48 +0300 MSK
Links
Code
class Solution:
def divideArray(self, nums: List[int]) -> bool:
freqs = defaultdict(int)
for num in nums:
freqs[num] += 1
for freq in freqs.values():
if freq % 2 != 0:
return False
return True
4.7.628 - 2025-08-17 19:44:55 +0300 MSK
Links
Code
class Solution:
def findKDistantIndices(
self, nums: List[int], key: int, k: int
) -> List[int]:
res = []
right = 0
length = len(nums)
for j in range(length):
if nums[j] != key:
continue
left = max(right, j - k)
right = min(length - 1, j + k) + 1
res.extend(range(left, right))
return res
4.7.629 - 2025-08-17 19:21:20 +0300 MSK
Links
Code
class Solution:
def cellsInRange(self, s: str) -> List[str]:
cell1, cell2 = s.split(":")
row1, col1 = cell1[0], int(cell1[1:])
row2, col2 = cell2[0], int(cell2[1:])
res = []
while row1 <= row2:
for col in range(col1, col2 + 1):
res.append(f"{row1}{col}")
row1 = chr(ord(row1) + 1)
return res
4.7.630 - 2025-08-17 19:15:00 +0300 MSK
Links
Code
class Solution:
def mostFrequent(self, nums: List[int], key: int) -> int:
freqs = [0] * 1001
prev = nums[0]
max_freq, max_freq_num = 0, 0
res = 0
for num in nums[1:]:
if prev == key:
freq = freqs[num] + 1
freqs[num] = freq
if freq > max_freq:
max_freq, max_freq_num = freq, num
prev = num
return max_freq_num
4.7.631 - 2025-08-17 19:10:32 +0300 MSK
Links
Code
class Solution:
def prefixCount(self, words: List[str], pref: str) -> int:
res = 0
for word in words:
if word.startswith(pref):
res += 1
return res
4.7.632 - 2025-08-17 19:08:02 +0300 MSK
Links
Code
class Solution:
def countEven(self, num: int) -> int:
dig_sum = 0
val = num
while val > 0:
dig_sum += val % 10
val //= 10
if dig_sum % 2 == 0:
return num // 2
return (num - 1) // 2
4.7.633 - 2025-08-17 18:51:40 +0300 MSK
Links
Code
class Solution:
def countPairs(self, nums: List[int], k: int) -> int:
freqs = tuple([] for i in range(101))
res = 0
for j, num in enumerate(nums):
for i in freqs[num]:
if (i * j) % k == 0:
res += 1
freqs[num].append(j)
return res
4.7.634 - 2025-08-17 18:46:10 +0300 MSK
Links
Code
class Solution:
def countPairs(self, nums: List[int], k: int) -> int:
length = len(nums)
res = 0
for i in range(length):
num1 = nums[i]
for j in range(i + 1, length):
if (i * j) % k == 0 and num1 == nums[j]:
res += 1
return res
4.7.635 - 2025-08-17 18:44:14 +0300 MSK
Links
Code
class Solution:
def countPairs(self, nums: List[int], k: int) -> int:
length = len(nums)
res = 0
for i in range(length):
num1 = nums[i]
for j in range(i + 1, length):
if num1 == nums[j] and (i * j) % k == 0:
res += 1
return res
4.7.636 - 2025-08-17 18:40:15 +0300 MSK
Links
Code
class Solution:
def countOperations(self, num1: int, num2: int) -> int:
count = 0
while num1 > 0 and num2 > 0:
if num1 >= num2:
count += num1 // num2
num1 %= num2
else:
count += num2 // num1
num2 %= num1
return count
4.7.637 - 2025-08-17 18:38:02 +0300 MSK
Links
Code
class Solution:
def countOperations(self, num1: int, num2: int) -> int:
count = 0
while num1 > 0 and num2 > 0:
if num1 >= num2:
num1 -= num2
else:
num2 -= num1
count += 1
return count
4.7.638 - 2025-08-17 18:25:12 +0300 MSK
Links
Code
class Solution:
def sortEvenOdd(self, nums: List[int]) -> List[int]:
odd, even = [], []
for i, num in enumerate(nums):
if i % 2 == 0:
heapq.heappush(even, num)
else:
heapq.heappush(odd, -num)
for i in range(len(nums)):
if i % 2 == 0:
nums[i] = heapq.heappop(even)
else:
nums[i] = -heapq.heappop(odd)
return nums
4.7.639 - 2025-08-17 18:16:02 +0300 MSK
Links
Code
class Solution:
def minimumSum(self, num: int) -> int:
digits = []
while num > 0:
digits.append(num % 10)
num //= 10
digits.sort()
return digits[0] * 10 + digits[1] * 10 + digits[2] + digits[3]
4.7.640 - 2025-08-17 18:06:00 +0300 MSK
Links
Code
class Solution:
def findFinalValue(self, nums: List[int], original: int) -> int:
nums.sort()
length = len(nums)
left, right = 0, length - 1
while left <= right:
i = left + (right - left) // 2
val = nums[i]
if val > original:
right = i - 1
elif val == original:
original *= 2
left = i + 1
right = length - 1
else:
left = i + 1
return original
4.7.641 - 2025-08-17 17:56:42 +0300 MSK
Links
Code
class Solution:
def findFinalValue(self, nums: List[int], original: int) -> int:
nums = set(nums)
while original in nums:
original *= 2
return original
4.7.642 - 2025-08-17 17:28:49 +0300 MSK
Links
Code
class Solution:
def countElements(self, nums: List[int]) -> int:
if len(nums) < 3:
return 0
nums.sort()
res = 0
prev, cur, cur_count = None, nums[0], 1
for num in nums:
if num == cur:
cur_count += 1
elif prev is None:
prev = cur
cur = num
cur_count = 1
else:
res += cur_count
prev = cur
cur = num
cur_count = 1
return res
4.7.643 - 2025-08-17 17:16:59 +0300 MSK
Links
Code
class Solution:
def minimumCost(self, cost: List[int]) -> int:
cost.sort()
res = 0
while cost:
if len(cost) > 2:
res += cost.pop() + cost.pop()
cost.pop()
else:
res += cost.pop()
return res
4.7.644 - 2025-08-17 17:04:01 +0300 MSK
Links
Code
class Solution:
def divideString(self, s: str, k: int, fill: str) -> List[str]:
res = []
cur = []
for char in s:
cur.append(char)
if len(cur) == k:
res.append("".join(cur))
cur.clear()
if cur and len(cur) < k:
cur.append(fill * (k - len(cur)))
res.append("".join(cur))
cur.clear()
return res
4.7.645 - 2025-08-17 16:00:07 +0300 MSK
Links
Code
class Solution:
def checkValid(self, matrix: List[List[int]]) -> bool:
length = len(matrix)
rows = bytearray(length + 1)
cols = bytearray(length + 1)
for row in range(length):
for col in range(length):
row_col, col_row = matrix[row][col], matrix[col][row]
rows[row_col] += 1
cols[col_row] += 1
if rows[row_col] > 1 or cols[col_row] > 1:
return False
for i in range(length + 1):
rows[i] = 0
cols[i] = 0
return True
4.7.646 - 2025-08-17 13:53:56 +0300 MSK
Links
Code
class Solution:
def capitalizeTitle(self, title: str) -> str:
res = []
cur = []
for char in itertools.chain(title, " "):
if char != " ":
cur.append(char)
continue
for i in range(len(cur)):
cur[i] = cur[i].lower()
if len(cur) > 2:
cur[0] = cur[0].upper()
res.append("".join(cur))
cur.clear()
return " ".join(res)
4.7.647 - 2025-08-17 13:41:15 +0300 MSK
Links
Code
class Solution:
def checkString(self, s: str) -> bool:
found_a = False
found_b = False
for char in s:
if char == "a":
if found_b:
return False
if not found_a:
found_a = True
else:
if not found_b:
found_b = True
return True
4.7.648 - 2025-08-17 13:38:02 +0300 MSK
Links
Code
class Solution:
def isSameAfterReversals(self, num: int) -> bool:
if num == 0:
return True
return num % 10 != 0
4.7.649 - 2025-08-17 13:36:24 +0300 MSK
Links
Code
class Solution:
def mostWordsFound(self, sentences: List[str]) -> int:
res = 0
for sentence in sentences:
count = sentence.count(" ") + 1
if count > res:
res = count
return res
4.7.650 - 2025-08-17 13:34:11 +0300 MSK
Links
Code
class Solution:
def countPoints(self, rings: str) -> int:
rods = [(False, False, False)] * 10
res = 0
for i in range(0, len(rings), 2):
rod = int(rings[i + 1])
color = rings[i]
has_red, has_green, has_blue = rods[rod]
if color == "R":
has_red = True
elif color == "G":
has_green = True
else:
has_blue = True
rods[rod] = (has_red, has_green, has_blue)
for vals in rods:
if all(vals):
res += 1
return res
4.7.651 - 2025-08-17 13:25:54 +0300 MSK
Links
Code
class Solution:
def maxSubsequence(self, nums: List[int], k: int) -> List[int]:
length = len(nums)
for i in range(length):
nums[i] = (i, nums[i])
nums.sort(key=lambda num: -num[1])
while len(nums) > k:
nums.pop()
nums.sort()
for i in range(k):
nums[i] = nums[i][1]
return nums
4.7.652 - 2025-08-17 13:10:43 +0300 MSK
Links
Code
class Solution:
def findEvenNumbers(self, digits: List[int]) -> List[int]:
res = []
freq = Counter(digits)
for i in range(100, 1000, 2):
freq1 = Counter([int(d) for d in str(i)])
if all(freq[d] >= freq1[d] for d in freq1.keys()):
res.append(i)
return res
4.7.653 - 2025-08-17 12:55:05 +0300 MSK
Links
Code
class Solution:
def targetIndices(self, nums: List[int], target: int) -> List[int]:
count_eq = 0
count_less = 0
for num in nums:
if num == target:
count_eq += 1
elif num < target:
count_less += 1
return tuple(range(count_less, count_less + count_eq))
4.7.654 - 2025-08-17 12:47:03 +0300 MSK
Links
Code
class Solution:
def targetIndices(self, nums: List[int], target: int) -> List[int]:
nums.sort()
if nums[0] > target or nums[-1] < target:
return []
res = []
for i, num in enumerate(nums):
if num == target:
res.append(i)
return res
4.7.655 - 2025-08-17 12:39:05 +0300 MSK
Links
Code
class Solution:
def countWords(self, words1: List[str], words2: List[str]) -> int:
freqs = defaultdict(lambda: (0, 0))
for word in words1:
freq1, _ = freqs[word]
if freq1 in (0, 1):
freqs[word] = (freq1 + 1, 0)
for word in words2:
freq1, freq2 = freqs[word]
if freq2 in (0, 1):
freqs[word] = (freq1, freq2 + 1)
res = 0
for freq1, freq2 in freqs.values():
if freq1 == freq2 == 1:
res += 1
return res
4.7.656 - 2025-08-17 11:54:12 +0300 MSK
Links
Code
class Solution:
def maxDistance(self, colors: List[int]) -> int:
prev, res = math.inf, 0
start = colors[0]
for i, color in enumerate(colors):
if color != start:
res = i
prev = min(prev, i)
else:
res = max(res, i - prev)
return res
4.7.657 - 2025-08-17 09:23:21 +0300 MSK
Links
Code
class Solution:
def new21Game(self, n: int, k: int, maxPts: int) -> float:
dp = [0] * (n + 1)
dp[0] = 1
s = 1 if k > 0 else 0
for i in range(1, n + 1):
dp[i] = s / maxPts
if i < k:
s += dp[i]
if i - maxPts >= 0 and i - maxPts < k:
s -= dp[i - maxPts]
return sum(dp[k:])
4.7.658 - 2025-08-16 18:43:20 +0300 MSK
Links
Code
class Solution:
def checkAlmostEquivalent(self, word1: str, word2: str) -> bool:
freqs = [0] * 26
for char in word1:
freqs[ord(char) - 97] += 1
for char in word2:
freqs[ord(char) - 97] -= 1
for freq in freqs:
if freq > 3 or freq < -3:
return False
return True
4.7.659 - 2025-08-16 16:51:28 +0300 MSK
Links
Code
from collections import defaultdict
class Solution:
def countVowelSubstrings(self, word):
vowels_map = {'a': True, 'e': True, 'i': True, 'o': True, 'u': True}
len_word = len(word)
left_index = 0
right_index = 0
ret_val = 0
char_to_freq_map = defaultdict(int)
i = 0
while i < len_word:
c = word[i]
if c in vowels_map.keys():
char_to_freq_map[c] += 1
while set(char_to_freq_map.keys()) == set(vowels_map.keys()):
c = word[right_index]
char_to_freq_map[c] -= 1
if (char_to_freq_map[c] <= 0):
char_to_freq_map.pop(c)
right_index += 1
ret_val += (right_index - left_index)
else:
char_to_freq_map.clear()
left_index = i + 1
right_index = i + 1
i += 1
return ret_val
4.7.660 - 2025-08-16 16:11:23 +0300 MSK
Links
Code
class Solution:
def smallestEqual(self, nums: List[int]) -> int:
for i, num in enumerate(nums):
if i % 10 == num:
return i
return -1
4.7.661 - 2025-08-16 14:42:51 +0300 MSK
Links
Code
class Solution:
def kthDistinct(self, arr: List[str], k: int) -> str:
freqs = defaultdict(int)
for string in arr:
if freqs[string] in (0, 1):
freqs[string] += 1
for string in arr:
if freqs[string] == 1:
if k == 1:
return string
k -= 1
return ""
4.7.662 - 2025-08-16 14:31:57 +0300 MSK
Links
Code
class Solution:
def countValidWords(self, sentence: str) -> int:
def is_valid_word(token):
len_token = len(token)
i = 0
while (i < len_token):
c = token[i]
if (ord(c) not in range(ord('a'), ord('z') + 1)
and c != '-'
and c not in ('!', '.', ',')):
return False
elif (c == '-'
and i > 1
and not token[:i].isalpha()):
return False
elif (c == '-'
and i < len_token - 1
and (not token[i+1:].isalpha() and not (token[i+1:-1].isalpha() and token[-1] in ('!', '.', ',')))):
return False
elif (c == '-'
and (i == 0 or i == len_token-1)):
return False
elif (c in ('!', '.', ',')
and i < len_token - 1):
return False
i += 1
return True
tokens = [t for t in sentence.split(' ') if t != '']
count_valid_words = 0
for token in tokens:
print(token, is_valid_word(token))
if (is_valid_word(token)):
count_valid_words += 1
return count_valid_words
4.7.663 - 2025-08-16 14:30:59 +0300 MSK
Links
Code
class Solution:
def areNumbersAscending(self, s: str) -> bool:
cur = []
prev = 0
for char in itertools.chain(s, " "):
if char.isdigit():
cur.append(char)
elif cur:
val = 0
count = 0
while cur:
val += int(cur.pop()) * (10 ** count)
count += 1
if val <= prev:
return False
prev = val
return True
4.7.664 - 2025-08-16 14:27:06 +0300 MSK
Links
Code
class Solution:
def twoOutOfThree(self, nums1: List[int], nums2: List[int], nums3: List[int]) -> List[int]:
freqs = [(False, False, False)] * 102
for num in nums1:
freqs[num] = (True, False, False)
for num in nums2:
stat1, stat2, _ = freqs[num]
if not stat2:
freqs[num] = (stat1, True, False)
for num in nums3:
stat1, stat2, stat3 = freqs[num]
if not stat3:
freqs[num] = (stat1, stat2, True)
nums1.clear()
for num in range(1, len(freqs)):
if sum(freqs[num]) >= 2:
nums1.append(num)
return nums1
4.7.665 - 2025-08-16 14:19:48 +0300 MSK
Links
Code
class Solution:
def minimumMoves(self, s: str) -> int:
i = 0
length = len(s)
res = 0
while i < length:
if s[i] == "X":
res += 1
i += 3
else:
i += 1
return res
4.7.666 - 2025-08-16 14:16:53 +0300 MSK
Links
Code
class Solution:
def construct2DArray(self, original: List[int], m: int, n: int) -> List[List[int]]:
i = 0
if len(original) != m * n:
return []
res = [[None] * n for _ in range(m)]
for row in range(m):
for col in range(n):
res[row][col] = original[i]
i += 1
return res
4.7.667 - 2025-08-16 14:14:34 +0300 MSK
Links
Code
class Solution:
def maximumDifference(self, nums: List[int]) -> int:
res, left = -1, nums[0]
for num in nums[1:]:
if num > left:
diff = num - left
if diff > res:
res = diff
else:
left = num
return res
4.7.668 - 2025-08-16 14:05:37 +0300 MSK
Links
Code
class Solution:
def finalValueAfterOperations(self, operations: List[str]) -> int:
res = 0
for op in operations:
if op.startswith("++") or op.endswith("++"):
res += 1
else:
res -= 1
return res
4.7.669 - 2025-08-16 14:04:12 +0300 MSK
Links
Code
class Solution:
def countKDifference(self, nums: List[int], k: int) -> int:
freqs = [0] * 102
count = 0
for num in nums:
freqs[num] += 1
for num in nums:
freqs[num] = max(freqs[num] - 1, 0)
target = num + k
for target in (num - k, num + k):
if target >= 0 and target < 102 and freqs[target] > 0:
count += freqs[target]
return count
4.7.670 - 2025-08-16 13:53:07 +0300 MSK
Links
Code
class Solution:
def countQuadruplets(self, nums: List[int]) -> int:
count = 0
numbers = defaultdict(list)
length = len(nums)
for i in range(length - 1):
for j in range(i + 1, length):
numbers[nums[i] + nums[j]].append(j)
for i in range(2, length - 1):
for j in range(i + 1, length):
target = nums[j] - nums[i]
for idx in numbers[target]:
if i > idx:
count += 1
return count
4.7.671 - 2025-08-16 13:39:08 +0300 MSK
Links
Code
class Solution:
def findMiddleIndex(self, nums: List[int]) -> int:
left, right = 0, sum(nums)
for i, num in enumerate(nums):
right -= num
if left == right:
return i
left += num
return -1
4.7.672 - 2025-08-16 13:35:39 +0300 MSK
Links
Code
class Solution:
def minimumDifference(self, nums: list[int], k: int) -> int:
if (k < 2 or k > len(nums)):
return 0
nums.sort()
lowest = float('inf')
for i in range(len(nums) - k + 1):
diff = nums[i + k - 1] - nums[i]
if diff < lowest:
lowest = diff
return lowest
4.7.673 - 2025-08-16 13:22:50 +0300 MSK
Links
Code
class Solution:
def findGCD(self, nums: List[int]) -> int:
nums.sort()
small, big = nums[0], nums[-1]
for i in range(1, small + 1):
if small % i != 0:
continue
val = small // i
if big % val == 0:
return val
raise Exception
4.7.674 - 2025-08-16 13:15:31 +0300 MSK
Links
Code
SELECT
employee_id
FROM
Employees
WHERE
manager_id NOT IN (
SELECT
employee_id
FROM
Employees
)
AND salary < 30000
ORDER BY
employee_id
4.7.675 - 2025-08-16 13:13:30 +0300 MSK
Links
Code
class Solution:
def minTimeToType(self, word: str) -> int:
pos = 97
res = 0
for char in word:
cur_pos = ord(char)
diff = abs(cur_pos - pos)
res += min(diff, 26 - diff) + 1
pos = cur_pos
return res
4.7.676 - 2025-08-16 12:59:52 +0300 MSK
Links
Code
class Solution:
def numOfStrings(self, patterns: List[str], word: str) -> int:
count = 0
for pattern in patterns:
if pattern in word:
count += 1
return count
4.7.677 - 2025-08-16 12:54:52 +0300 MSK
Links
Code
SELECT
COALESCE(
t1.employee_id,
t2.employee_id
) AS employee_id
FROM
Employees t1
FULL JOIN
Salaries t2
ON
t1.employee_id = t2.employee_id
WHERE
t1.name IS NULL
OR t2.salary IS NULL
ORDER BY
employee_id;
4.7.678 - 2025-08-16 12:42:27 +0300 MSK
Links
Code
class Solution:
def isPrefixString(self, s: str, words: List[str]) -> bool:
i = 0
length = len(s)
for word in words:
if i >= length:
return True
word_length = len(word)
if word_length > length - i:
return False
if word != s[i:i+word_length]:
return False
i += word_length
return i >= length
4.7.679 - 2025-08-16 12:24:35 +0300 MSK
Links
Code
class Solution:
def isThree(self, n: int) -> bool:
count = 1
for num in range(2, n // 2 + 1):
if n % num == 0:
count += 2
if count > 3:
break
return count == 3
4.7.680 - 2025-08-16 12:19:08 +0300 MSK
Links
Code
class Solution:
def getLucky(self, s: str, k: int) -> int:
def trans(val: int, count: int) -> int:
if count == 0:
return val
res = 0
while val > 0:
res += val % 10
val //= 10
return trans(res, count - 1)
val = 0
for char in s:
val += trans(ord(char) - 97 + 1, 1)
return trans(val, k - 1)
4.7.681 - 2025-08-16 12:12:54 +0300 MSK
Links
Code
class Solution:
def areOccurrencesEqual(self, s: str) -> bool:
freqs = defaultdict(int)
for char in s:
freqs[char] += 1
target = freqs[s[0]]
for freq in freqs.values():
if freq != target:
return False
return True
4.7.682 - 2025-08-16 12:11:17 +0300 MSK
Links
Code
class Solution:
def canBeTypedWords(self, text: str, brokenLetters: str) -> int:
ignore = False
res = 0
for char in itertools.chain(text, " "):
if char == " ":
if ignore:
ignore = False
else:
res += 1
elif char in brokenLetters:
ignore = True
return res
4.7.683 - 2025-08-16 12:07:23 +0300 MSK
Links
Code
class Solution:
def getConcatenation(self, nums: List[int]) -> List[int]:
for i in range(len(nums)):
nums.append(nums[i])
return nums
4.7.684 - 2025-08-16 12:06:11 +0300 MSK
Links
Code
class Solution:
def countTriples(self, n: int) -> int:
res = 0
for a in range(1, n):
for b in range(a + 1, n):
c = math.sqrt(a * a + b * b)
if c % 1 == 0 and c <= n:
res += 2
return res
4.7.685 - 2025-08-16 11:58:38 +0300 MSK
Links
Code
class Solution:
def buildArray(self, nums: List[int]) -> List[int]:
length = len(nums)
for i in range(length):
val = nums[i] % 1000
res = 1000 * (nums[val] % 1000)
nums[i] = res + val
for i in range(length):
nums[i] //= 1000
return nums
4.7.686 - 2025-08-16 11:50:13 +0300 MSK
Links
Code
class Solution:
def buildArray(self, nums: List[int]) -> List[int]:
res = [None] * len(nums)
for i, num in enumerate(nums):
res[i] = nums[num]
return res
4.7.687 - 2025-08-16 11:32:58 +0300 MSK
Links
Code
class Solution:
def canBeIncreasing(self, nums: List[int]) -> bool:
removed = False
length = len(nums)
for i in range(length - 1):
cur, nxt = nums[i], nums[i + 1]
if nxt > cur:
continue
if removed:
return False
removed = True
if (
i > 0 and nums[i - 1] >= nxt
) and (
i + 2 < length and cur >= nums[i + 2]
):
return False
return True
4.7.688 - 2025-08-16 11:14:35 +0300 MSK
Links
Code
class Solution:
def isCovered(self, ranges: List[List[int]], left: int, right: int) -> bool:
cov = [False] * (right - left + 1)
for start, end in ranges:
for num in range(max(left, start), min(end, right) + 1):
i = num - left
if not cov[i]:
cov[i] = True
return False not in cov
4.7.689 - 2025-08-16 11:13:51 +0300 MSK
Links
Code
class Solution:
def isCovered(self, ranges: List[List[int]], left: int, right: int) -> bool:
cov = [False] * (right - left + 1)
for start, end in ranges:
for num in range(max(left, start), min(end, right) + 1):
cov[num - left] = True
return False not in cov
4.7.690 - 2025-08-16 11:09:17 +0300 MSK
Links
Code
SELECT
user_id,
MAX(time_stamp) AS last_stamp
FROM
Logins
WHERE
time_stamp >= '2020-01-01'
AND time_stamp < '2021-01-01'
GROUP BY
user_id
4.7.691 - 2025-08-16 10:49:39 +0300 MSK
Links
Code
class Solution:
def findRotation(self, mat: List[List[int]], target: List[List[int]]) -> bool:
length = len(mat)
count_0, count_90, count_180, count_270 = 0, 0, 0, 0
for i in range(length):
for j in range(length):
val = mat[i][j]
if val == target[i][j]:
count_0 += 1
if val == target[j][length - i - 1]:
count_90 += 1
if val == target[length - i - 1][length - j - 1]:
count_180 += 1
if val == target[length - j - 1][i]:
count_270 += 1
return length * length in {count_0, count_90, count_180, count_270}
4.7.692 - 2025-08-16 10:22:08 +0300 MSK
Links
Code
class Solution:
def isSumEqual(self, firstWord: str, secondWord: str, targetWord: str) -> bool:
def count(word: str) -> int:
length = len(word)
res = 0
for i in reversed(range(length)):
res += (ord(word[i]) - 97) * (10 ** (length - i - 1))
return res
return count(firstWord) + count(secondWord) == count(targetWord)
4.7.693 - 2025-08-16 10:19:18 +0300 MSK
Links
Code
class Solution:
def isSumEqual(self, firstWord: str, secondWord: str, targetWord: str) -> bool:
digits = []
def count(word: str) -> int:
for char in word:
digits.append(ord(char) - 97)
res = 0
count = 0
while digits:
res += digits.pop() * (10 ** count)
count += 1
return res
return count(firstWord) + count(secondWord) == count(targetWord)
4.7.694 - 2025-08-16 10:09:43 +0300 MSK
Links
Code
class Solution:
def maximum69Number (self, num: int) -> int:
digits = []
while num > 0:
digits.append(num % 10)
num //= 10
digits.reverse()
for i in range(len(digits)):
if digits[i] == 6:
digits[i] = 9
break
res = 0
count = 0
while digits:
res += digits.pop() * (10 ** count)
count += 1
return res
4.7.695 - 2025-08-15 17:31:44 +0300 MSK
Links
Code
class Solution:
def countGoodSubstrings(self, s: str) -> int:
res = 0
for i in range(len(s) - 2):
char1, char2, char3 = s[i:i+3]
if char1 != char2 and char1 != char3 and char2 != char3:
res += 1
return res
4.7.696 - 2025-08-15 16:57:42 +0300 MSK
Links
Code
SELECT
employee_id,
(
CASE
WHEN
employee_id % 2 != 0
AND NOT STARTS_WITH(name, 'M')
THEN
salary
ELSE
0
END
) AS "bonus"
FROM
Employees
ORDER BY
employee_id
4.7.697 - 2025-08-15 16:43:07 +0300 MSK
Links
Code
class Solution:
def checkZeroOnes(self, s: str) -> bool:
max_length = [0, 0]
cur = 0
prev = -1
for char in s:
val = int(char)
if val == prev:
cur += 1
else:
cur = 1
if cur > max_length[val]:
max_length[val] = cur
prev = val
return max_length[1] > max_length[0]
4.7.698 - 2025-08-15 16:35:39 +0300 MSK
Links
Code
class Solution:
def sortSentence(self, s: str) -> str:
res = [None] * 9
cur = []
for char in s:
if char.isalpha():
cur.append(char)
elif char.isdigit():
res[int(char) - 1] = "".join(cur)
cur.clear()
return " ".join(word for word in res if word is not None)
4.7.699 - 2025-08-15 16:30:08 +0300 MSK
Links
Code
class Solution:
def maximumPopulation(self, logs: List[List[int]]) -> int:
population = [0] * 102
max_population = 0
for birth, death in logs:
for year in range(birth, death):
i = year - 1950
new_population = population[i] + 1
population[i] = new_population
if new_population > max_population:
max_population = new_population
for i, count in enumerate(population):
if count == max_population:
return 1950 + i
raise Exception
4.7.700 - 2025-08-15 16:25:44 +0300 MSK
Links
Code
class Solution:
def getMinDistance(self, nums: List[int], target: int, start: int) -> int:
length = len(nums)
dist = 0
while dist < length:
left, right = start - dist, start + dist
if left >= 0 and nums[left] == target:
return dist
if right < length and nums[right] == target:
return dist
dist += 1
raise Exception
4.7.701 - 2025-08-15 16:20:07 +0300 MSK
Links
Code
class Solution:
def replaceDigits(self, s: str) -> str:
res = []
for i in range(0, len(s) - 1, 2):
char, digit = s[i], int(s[i + 1])
res.append(char)
res.append(chr(ord(char) + digit))
if len(s) % 2 != 0:
res.append(s[-1])
return "".join(res)
4.7.702 - 2025-08-15 16:13:25 +0300 MSK
Links
Code
class Solution:
def sumBase(self, n: int, k: int) -> int:
digits = []
while n > 0:
digits.append(n % k)
n //= k
return sum(digits)
4.7.703 - 2025-08-15 16:11:57 +0300 MSK
Links
Code
class Solution:
def checkIfPangram(self, sentence: str) -> bool:
freqs = [0] * 26
for char in sentence:
freqs[ord(char) - 97] += 1
return 0 not in freqs
4.7.704 - 2025-08-15 16:11:03 +0300 MSK
Links
Code
class Solution:
def minOperations(self, nums: List[int]) -> int:
res = 0
prev = nums[0]
for num in nums[1:]:
if num > prev:
prev = num
else:
new = prev + 1
res += new - num
prev = new
return res
4.7.705 - 2025-08-15 16:06:24 +0300 MSK
Links
Code
class Solution:
def truncateSentence(self, s: str, k: int) -> str:
res = s.split(" ")
while len(res) > k:
res.pop()
return " ".join(res)
4.7.706 - 2025-08-15 16:05:32 +0300 MSK
Links
Code
class Solution:
def truncateSentence(self, s: str, k: int) -> str:
res = []
cur = []
for char in itertools.chain(s, " "):
if char.isalpha():
cur.append(char)
else:
res.append("".join(cur))
cur.clear()
if len(res) == k:
return " ".join(res)
raise Exception
4.7.707 - 2025-08-15 16:03:03 +0300 MSK
Links
Code
class Solution:
def squareIsWhite(self, coordinates: str) -> bool:
col = ord(coordinates[0]) - 97
row = int(coordinates[1])
if row % 2 == 0:
return col % 2 == 0
return col % 2 != 0
4.7.708 - 2025-08-15 15:54:30 +0300 MSK
Links
Code
class Solution:
def numDifferentIntegers(self, word: str) -> int:
enc = set()
cur = []
for char in itertools.chain(word, "a"):
if char.isalpha():
if cur:
count = 0
num = 0
while cur:
num += cur.pop() * (10 ** count)
count += 1
enc.add(num)
else:
cur.append(int(char))
return len(enc)
4.7.709 - 2025-08-15 15:47:22 +0300 MSK
Links
Code
class Solution:
def maxAscendingSum(self, nums: List[int]) -> int:
max_sum, cur_sum, prev = nums[0], nums[0], nums[0]
for num in nums[1:]:
if num > prev:
cur_sum += num
else:
cur_sum = num
if cur_sum > max_sum:
max_sum = cur_sum
prev = num
return max_sum
4.7.710 - 2025-08-15 15:44:11 +0300 MSK
Links
Code
class Solution:
def secondHighest(self, s: str) -> int:
num1, num2 = -1, -1
for char in s:
if not char.isdigit():
continue
num = int(char)
if num > num2:
num1, num2 = num2, num
elif num != num2 and num > num1:
num1 = num
return num1
4.7.711 - 2025-08-15 15:38:40 +0300 MSK
Links
Code
(
SELECT
product_id,
'store1' AS store,
store1 AS price
FROM
Products
WHERE
store1 IS NOT NULL
) UNION (
SELECT
product_id,
'store2' AS store,
store2 AS price
FROM
Products
WHERE
store2 IS NOT NULL
) UNION (
SELECT
product_id,
'store3' AS store,
store3 AS price
FROM
Products
WHERE
store3 IS NOT NULL
)
ORDER BY
product_id,
store;
4.7.712 - 2025-08-15 15:32:17 +0300 MSK
Links
Code
class Solution:
def findCenter(self, edges: List[List[int]]) -> int:
num1, num2 = edges[0]
num3, num4 = edges[1]
if num1 == num3 or num1 == num4:
return num1
return num2
4.7.713 - 2025-08-15 15:28:53 +0300 MSK
Links
Code
class Solution:
def areAlmostEqual(self, s1: str, s2: str) -> bool:
if s1 == s2:
return True
length = len(s1)
if length != len(s2):
return False
i1, i2 = -1, -1
for i, (char1, char2) in enumerate(zip(s1, s2)):
if char1 == char2:
continue
if i1 == -1:
i1 = i
elif i2 == -1:
i2 = i
else:
return False
if i2 == -1:
return False
return s1[i1] == s2[i2] and s1[i2] == s2[i1]
4.7.714 - 2025-08-15 15:12:21 +0300 MSK
Links
Code
SELECT
employee_id,
department_id
FROM
(
SELECT
employee_id,
department_id,
primary_flag,
COUNT(employee_id) OVER(
PARTITION BY
employee_id
) AS employee_count
FROM
Employee
) EmployeePartition
WHERE
employee_count = 1
OR primary_flag = 'Y';
4.7.715 - 2025-08-15 15:04:18 +0300 MSK
Links
Code
class Solution:
def checkOnesSegment(self, s: str) -> bool:
enc = False
for char in s:
if char == "1":
if enc:
return False
elif not enc:
enc = True
return True
4.7.716 - 2025-08-15 15:03:12 +0300 MSK
Links
Code
class Solution:
def checkOnesSegment(self, s: str) -> bool:
enc = False
for char in s[1:]:
if char == "1" and enc:
return False
elif char == "1":
continue
enc = True
return True
4.7.717 - 2025-08-15 14:37:22 +0300 MSK
Links
Code
class Solution:
def countMatches(self, items: List[List[str]], ruleKey: str, ruleValue: str) -> int:
count = 0
for type, color, name in items:
if (
(ruleKey == "type" and ruleValue == type)
or (ruleKey == "color" and ruleValue == color)
or (ruleKey == "name" and ruleValue == name)
):
count += 1
return count
4.7.718 - 2025-08-15 14:34:58 +0300 MSK
Links
Code
SELECT
Products.product_id
FROM
Products
WHERE
Products.low_fats = 'Y'
AND Products.recyclable = 'Y';
4.7.719 - 2025-08-15 14:33:22 +0300 MSK
Links
Code
class Solution:
def check(self, nums: List[int]) -> bool:
prev = nums[0]
count = 0
for num in nums[1:]:
if num >= prev:
pass
elif count == 0:
count = 1
else:
return False
prev = num
if count == 0:
return True
return nums[0] >= nums[-1]
4.7.720 - 2025-08-15 14:31:10 +0300 MSK
Links
Code
class Solution:
def check(self, nums: List[int]) -> bool:
prev = nums[0]
new_start = 0
for num in nums[1:]:
if num >= prev:
pass
elif new_start == 0:
new_start = num
else:
return False
prev = num
if new_start == 0:
return True
return nums[0] >= nums[-1]
4.7.721 - 2025-08-15 14:21:42 +0300 MSK
Links
Code
class Solution:
def sumOfUnique(self, nums: List[int]) -> int:
enc = [0] * 101
res = 0
for num in nums:
count = enc[num]
if count == 1:
res -= num
enc[num] = 2
elif count == 0:
res += num
enc[num] = 1
return res
4.7.722 - 2025-08-15 14:17:27 +0300 MSK
Links
Code
class Solution:
def countBalls(self, lowLimit: int, highLimit: int) -> int:
freqs = [0] * 100
max_freq = 0
for num in range(lowLimit, highLimit + 1):
box = 0
while num > 0:
box += num % 10
num //= 10
freqs[box] += 1
max_freq = max(max_freq, freqs[box])
return max_freq
4.7.723 - 2025-08-15 14:14:49 +0300 MSK
Links
Code
class Solution:
def countBalls(self, lowLimit: int, highLimit: int) -> int:
freqs = defaultdict(int)
max_freq = 0
for num in range(lowLimit, highLimit + 1):
box = 0
while num > 0:
box += num % 10
num //= 10
freqs[box] += 1
max_freq = max(max_freq, freqs[box])
return max_freq
4.7.724 - 2025-08-15 13:38:16 +0300 MSK
Links
Code
SELECT
Employees.event_day AS "day",
Employees.emp_id,
SUM(Employees.out_time - Employees.in_time) AS "total_time"
FROM
Employees
GROUP BY
Employees.event_day,
Employees.emp_id
4.7.725 - 2025-08-15 13:31:41 +0300 MSK
Links
Code
class Solution:
def maximumTime(self, time: str) -> str:
hours, minutes = time.split(":")
hour1, hour2 = hours
minute1, minute2 = minutes
if hour1 == "?" and hour2 == "?":
hour1, hour2 = "2", "3"
elif hour1 == "?" and hour2 < "4":
hour1 = "2"
elif hour1 == "?":
hour1 = "1"
elif hour1 == "2" and hour2 == "?":
hour2 = "3"
elif hour2 == "?":
hour2 = "9"
if minute1 == "?":
minute1 = "5"
if minute2 == "?":
minute2 = "9"
return ":".join(("".join((hour1, hour2)), "".join((minute1, minute2))))
4.7.726 - 2025-08-15 13:23:40 +0300 MSK
Links
Code
SELECT
managers.employee_id,
managers.name,
COUNT(reports.employee_id) AS reports_count,
ROUND(AVG(reports.age)) AS average_age
FROM
Employees managers
INNER JOIN
Employees reports
ON
managers.employee_id = reports.reports_to
GROUP BY
managers.employee_id,
managers.name
ORDER BY
managers.employee_id;
4.7.727 - 2025-08-15 13:09:22 +0300 MSK
Links
Code
SELECT
Followers.user_id,
COUNT(Followers.user_id) AS followers_count
FROM
Followers
GROUP BY
Followers.user_id
ORDER BY
Followers.user_id ASC;
4.7.728 - 2025-08-15 13:07:52 +0300 MSK
Links
Code
SELECT
followers1.user_id,
COUNT(DISTINCT followers1.follower_id) AS "followers_count"
FROM
Followers followers1
LEFT JOIN
Followers followers2
ON
followers1.user_id = followers2.user_id
GROUP BY
followers1.user_id;
4.7.729 - 2025-08-15 12:54:27 +0300 MSK
Links
Code
class Solution:
def countGoodRectangles(self, rectangles: List[List[int]]) -> int:
max_len, res = 0, 0
for length, width in rectangles:
side = min(length, width)
if side < max_len:
continue
elif side == max_len:
res += 1
else:
max_len = side
res = 1
return res
4.7.730 - 2025-08-15 12:49:02 +0300 MSK
Links
Code
class Solution:
def decode(self, encoded: List[int], first: int) -> List[int]:
prev_encoded = encoded[0]
encoded[0] = first
for i in range(1, len(encoded)):
encoded[i], prev_encoded = prev_encoded ^ encoded[i - 1], encoded[i]
encoded.append(prev_encoded ^ encoded[-1])
return encoded
4.7.731 - 2025-08-15 12:36:30 +0300 MSK
Links
Code
class Solution:
def decode(self, encoded: List[int], first: int) -> List[int]:
prev = first
for i in range(len(encoded)):
prev = encoded[i] ^ prev
encoded[i] = prev
encoded.insert(0, first)
return encoded
4.7.732 - 2025-08-15 12:28:46 +0300 MSK
Links
Code
class Solution:
def maximumUnits(self, boxTypes: List[List[int]], truckSize: int) -> int:
boxTypes.sort(key=lambda item: item[1])
res = 0
while boxTypes and truckSize > 0:
boxes, units = boxTypes.pop()
count = min(boxes, truckSize)
truckSize -= count
res += count * units
return res
4.7.733 - 2025-08-15 12:22:34 +0300 MSK
Links
Code
class Solution:
def reformatNumber(self, number: str) -> str:
digits = []
for char in number:
if char == " " or char == "-":
continue
digits.append(char)
res = []
digits.reverse()
while len(digits) > 4:
res.append("".join((digits.pop(), digits.pop(), digits.pop())))
length = len(digits)
if length == 4:
res.append("".join((digits.pop(), digits.pop())))
res.append("".join((digits.pop(), digits.pop())))
elif length == 3:
res.append("".join((digits.pop(), digits.pop(), digits.pop())))
elif length == 2:
res.append("".join((digits.pop(), digits.pop())))
return "-".join(res)
4.7.734 - 2025-08-15 11:52:01 +0300 MSK
Links
Code
class Solution:
def isPowerOfFour(self, n: int) -> bool:
if n <= 0:
return False
if n & (n - 1) != 0:
return False
while n % 4 == 0:
n //= 4
return n == 1
4.7.735 - 2025-08-15 11:51:01 +0300 MSK
Links
Code
class Solution:
def isPowerOfFour(self, n: int) -> bool:
if n <= 0:
return False
while n % 4 == 0:
n //= 4
return n == 1
4.7.736 - 2025-08-14 20:09:09 +0300 MSK
Links
Code
class Solution:
def largestGoodInteger(self, num: str) -> str:
max_digit = "\0"
for index in range(len(num) - 2):
if num[index] == num[index + 1] == num[index + 2]:
max_digit = max(max_digit, num[index])
if max_digit == "\0":
return ""
return max_digit * 3
4.7.737 - 2025-08-13 17:56:30 +0300 MSK
Links
Code
class Solution:
def isPowerOfThree(self, n: int) -> bool:
if n <= 0:
return False
while n % 3 == 0:
n //= 3
return n == 1
4.7.738 - 2025-08-13 17:55:25 +0300 MSK
Links
Code
class Solution:
def isPowerOfThree(self, n: int) -> bool:
if n <= 0:
return False
if n == 1:
return True
while n > 1:
if n % 3 != 0:
return False
n //= 3
return True
4.7.739 - 2025-08-12 17:49:12 +0300 MSK
Links
Code
class Solution:
def numberOfWays(self, n: int, x: int) -> int:
MOD = 10**9 + 7
dp = [0] * (n + 1)
dp[0] = 1
for i in range(1, n + 1):
val = i**x
if val > n:
break
for j in range(n, val - 1, -1):
dp[j] = (dp[j] + dp[j - val]) % MOD
return dp[n]
4.7.740 - 2025-08-11 18:03:04 +0300 MSK
Links
Code
class Solution:
def productQueries(self, n: int, queries: List[List[int]]) -> List[int]:
mod = 10**9 + 7
bins, rep = [], 1
while n > 0:
if n % 2 == 1:
bins.append(rep)
n //= 2
rep *= 2
m = len(bins)
results = [[0] * m for _ in range(m)]
for i in range(m):
cur = 1
for j in range(i, m):
cur = cur * bins[j] % mod
results[i][j] = cur
ans = []
for left, right in queries:
ans.append(results[left][right])
return ans
4.7.741 - 2025-08-10 13:14:07 +0300 MSK
Links
Code
SELECT
DailySales.date_id,
DailySales.make_name,
COUNT(DISTINCT DailySales.lead_id) AS unique_leads,
COUNT(DISTINCT DailySales.partner_id) AS unique_partners
FROM
DailySales
GROUP BY
DailySales.date_id,
DailySales.make_name;
4.7.742 - 2025-08-10 13:10:37 +0300 MSK
Links
Code
SELECT
Tweets.tweet_id
FROM
Tweets
WHERE
LENGTH(Tweets.content) > 15
4.7.743 - 2025-08-10 13:08:24 +0300 MSK
Links
Code
class Solution:
def interpret(self, command: str) -> str:
stack = []
res = []
for char in command:
if char == ")":
if stack:
res.extend(stack)
stack.clear()
else:
res.append("o")
elif char == "G":
res.append("G")
elif char != "(":
stack.append(char)
return "".join(res)
4.7.744 - 2025-08-10 13:03:22 +0300 MSK
Links
Code
class Solution:
def maxRepeating(self, sequence: str, word: str) -> int:
temp, res = word, 0
while temp in sequence:
res += 1
temp += word
return res
4.7.745 - 2025-08-10 12:56:18 +0300 MSK
Links
Code
SELECT
Users.user_id,
UPPER(LEFT(Users.name, 1))
|| LOWER(SUBSTRING(Users.name FROM 2)) AS name
FROM
Users
ORDER BY
Users.user_id;
4.7.746 - 2025-08-10 12:52:07 +0300 MSK
Links
Code
SELECT
act1.machine_id,
ROUND(AVG(act2.timestamp - act1.timestamp)::decimal, 3) AS processing_time
FROM
Activity act1,
Activity act2
WHERE
act1.machine_id = act2.machine_id
AND act1.process_id = act2.process_id
AND act1.activity_type = 'start'
AND act2.activity_type = 'end'
GROUP BY
act1.machine_id;
4.7.747 - 2025-08-10 12:45:06 +0300 MSK
Links
Code
class Solution:
def decrypt(self, code: List[int], k: int) -> List[int]:
length = len(code)
result = [0 for _ in range(length)]
if k == 0:
return result
start, end, window_sum = 1, k + 1, 0
if k < 0:
start = length - (-k)
end = length
for i in range(start, end):
window_sum += code[i]
for i in range(length):
result[i] = window_sum
window_sum -= code[start % length]
window_sum += code[end % length]
start += 1
end += 1
return result
4.7.748 - 2025-08-10 12:15:52 +0300 MSK
Links
Code
class Solution:
def getMaximumGenerated(self, n: int) -> int:
if n == 0 or n == 1:
return n
nums = [0] * (n + 1)
nums[1] = 1
res = 1
for i in range(2, n + 1):
if i % 2 == 0:
val = nums[i // 2]
else:
val = nums[i // 2] + nums[(i // 2) + 1]
nums[i] = val
res = max(res, val)
return res
4.7.749 - 2025-08-10 11:45:24 +0300 MSK
Links
Code
class Solution:
def canFormArray(self, arr: List[int], pieces: List[List[int]]) -> bool:
num_to_piece = {}
for i, nums in enumerate(pieces):
for num in nums:
num_to_piece[num] = i
i = 0
length = len(arr)
while i < length:
num1 = arr[i]
if num1 not in num_to_piece:
return False
piece = pieces[num_to_piece[num1]]
for j, num2 in enumerate(piece):
if i + j >= length:
return False
num1 = arr[i + j]
if num1 != num2:
return False
i += len(piece)
return True
4.7.750 - 2025-08-10 11:25:09 +0300 MSK
Links
Code
class Solution:
def frequencySort(self, nums: List[int]) -> List[int]:
freqs = collections.defaultdict(int)
for num in nums:
freqs[num] += 1
nums.sort(key=lambda val: (freqs[val], -val))
return nums
4.7.751 - 2025-08-10 11:14:30 +0300 MSK
Links
Code
WITH total_users AS (
SELECT
COUNT(DISTINCT user_id) AS total_count
FROM
Users
)
SELECT
Register.contest_id,
ROUND(
COUNT(DISTINCT Register.user_id) * 100.0 / total_users.total_count,
2
) AS percentage
FROM
Register
CROSS JOIN
total_users
GROUP BY
Register.contest_id,
total_users.total_count
ORDER BY
percentage DESC,
Register.contest_id;
4.7.752 - 2025-08-10 11:02:20 +0300 MSK
Links
Code
class Solution:
def slowestKey(self, releaseTimes: List[int], keysPressed: str) -> str:
max_key, max_dur = keysPressed[0], releaseTimes[0]
for i, num in enumerate(releaseTimes[1:], 1):
dur = num - releaseTimes[i - 1]
cur_key = keysPressed[i]
if dur > max_dur or (dur == max_dur and cur_key > max_key):
max_dur = dur
max_key = cur_key
return max_key
4.7.753 - 2025-08-10 10:27:29 +0300 MSK
Links
Code
class Solution:
def reorderedPowerOf2(self, n: int) -> bool:
if n > 0 and n & (n - 1) == 0:
return True
def count_digits(num: int, out: list[int]) -> None:
while num > 0:
out.append(num % 10)
num //= 10
out.sort()
target = []
count_digits(n, target)
cur = []
for i in range(31):
cur.clear()
count_digits(1 << i, cur)
if cur == target:
return True
return False
4.7.754 - 2025-08-09 16:43:21 +0300 MSK
Links
Code
class Solution:
def trimMean(self, arr: List[int]) -> float:
arr.sort()
length = len(arr)
interval = length // 20
res = sum(arr[interval:length - interval])
res = (res / (length - interval * 2))
return res
4.7.755 - 2025-08-09 16:34:28 +0300 MSK
Links
Code
class Solution:
def minOperations(self, logs: List[str]) -> int:
depth = 0
for op in logs:
if op == "../":
depth = max(depth - 1, 0)
elif op == "./":
pass
else:
depth += 1
return depth
4.7.756 - 2025-08-09 16:31:49 +0300 MSK
Links
Code
class Solution:
def reorderSpaces(self, text: str) -> str:
res = []
cur_word = []
space_count = 0
for char in text:
if char == " ":
space_count += 1
if cur_word:
res.append("".join(cur_word))
cur_word.clear()
else:
cur_word.append(char)
if cur_word:
res.append("".join(cur_word))
words = len(res) - 1
if words == 0:
join_str = ""
rem_str = " " * space_count
else:
join_str = " " * (space_count // words)
rem_str = " " * (space_count % words)
return "".join((join_str.join(res), rem_str))
4.7.757 - 2025-08-09 16:17:16 +0300 MSK
Links
Code
class Solution:
def sumOddLengthSubarrays(self, arr: List[int]) -> int:
length = len(arr)
answer = 0
for i, num in enumerate(arr):
left, right = i, length - i - 1
odd_left, odd_right = (left // 2) + 1, (right // 2) + 1
even_left, even_right = (left + 1) // 2, (right + 1) // 2
sub_count = (odd_left * odd_right) + (even_left * even_right)
answer += num * sub_count
return answer
4.7.758 - 2025-08-09 15:53:09 +0300 MSK
Links
Code
class Solution:
def sumOddLengthSubarrays(self, arr: List[int]) -> int:
res = 0
for i in range(len(arr)):
cur_sum = 0
for j in range(i, len(arr)):
cur_sum += arr[j]
if (j - i + 1) % 2 != 0:
res += cur_sum
return res
4.7.759 - 2025-08-09 11:14:40 +0300 MSK
Links
Code
class Solution:
def isPowerOfTwo(self, n: int) -> bool:
return n > 0 and (n & (n - 1)) == 0
4.7.760 - 2025-08-08 18:19:33 +0300 MSK
Links
Code
class Solution:
def soupServings(self, n: int) -> float:
m = ceil(n / 25)
dp = collections.defaultdict(dict)
def calculate_dp(i: int, j: int) -> float:
if i <= 0 and j <= 0:
return 0.5
if i <= 0:
return 1.0
if j <= 0:
return 0.0
if i in dp and j in dp[i]:
return dp[i][j]
dp[i][j] = (
calculate_dp(i - 4, j)
+ calculate_dp(i - 3, j - 1)
+ calculate_dp(i - 2, j - 2)
+ calculate_dp(i - 1, j - 3)
) / 4.0
return dp[i][j]
for k in range(1, m + 1):
if calculate_dp(k, k) > 1 - 1e-5:
return 1.0
return calculate_dp(m, m)
4.7.761 - 2025-08-07 17:57:34 +0300 MSK
Links
Code
SELECT
Users.name AS "NAME",
SUM(Transactions.amount) AS "BALANCE"
FROM
Users
LEFT JOIN
Transactions
ON
Users.account = Transactions.account
GROUP BY
Users.account, Users.name
HAVING
SUM(Transactions.amount) > 10000
4.7.762 - 2025-08-07 17:15:08 +0300 MSK
Links
Code
class Solution:
def maxCollectedFruits(self, fruits):
n = len(fruits)
ans = sum(fruits[i][i] for i in range(n))
def dp():
prev = [float("-inf")] * n
curr = [float("-inf")] * n
prev[n - 1] = fruits[0][n - 1]
for i in range(1, n - 1):
for j in range(max(n - 1 - i, i + 1), n):
best = prev[j]
if j - 1 >= 0:
best = max(best, prev[j - 1])
if j + 1 < n:
best = max(best, prev[j + 1])
curr[j] = best + fruits[i][j]
prev, curr = curr, prev
return prev[n - 1]
ans += dp()
for i in range(n):
for j in range(i):
fruits[i][j], fruits[j][i] = fruits[j][i], fruits[i][j]
ans += dp()
return ans
4.7.763 - 2025-08-06 19:26:47 +0300 MSK
Links
Code
SELECT
Visits.customer_id,
COUNT(Visits.visit_id) AS "count_no_trans"
FROM
Visits
LEFT JOIN
Transactions
ON
Visits.visit_id = Transactions.visit_id
WHERE
Transactions.visit_id IS NULL
GROUP BY
Visits.customer_id
4.7.764 - 2025-08-06 16:17:09 +0300 MSK
Links
Code
class Solution:
def numOfUnplacedFruits(self, fruits: List[int], baskets: List[int]) -> int:
length = len(baskets)
section_length = int(math.sqrt(length))
sections = (length + section_length - 1) // section_length
count = 0
sections_max = [0] * sections
for i in range(length):
section = i // section_length
sections_max[section] = max(sections_max[section], baskets[i])
for fruit in fruits:
unset = 1
for section in range(sections):
if sections_max[section] < fruit:
continue
choose = 0
sections_max[section] = 0
for i in range(section_length):
pos = section * section_length + i
if pos < length and baskets[pos] >= fruit and not choose:
baskets[pos] = 0
choose = 1
if pos < length:
sections_max[section] = max(sections_max[section], baskets[pos])
unset = 0
break
count += unset
return count
4.7.765 - 2025-08-05 20:11:10 +0300 MSK
Links
Code
class Solution:
def numOfUnplacedFruits(self, fruits: List[int], baskets: List[int]) -> int:
count = 0
length = len(baskets)
for fruit in fruits:
unset = 1
for i in range(length):
if fruit <= baskets[i]:
baskets[i] = 0
unset = 0
break
count += unset
return count
4.7.766 - 2025-08-04 19:06:02 +0300 MSK
Links
Code
class Solution:
def totalFruit(self, fruits: list[int]) -> int:
start = 0
max_len = 0
fruit_count = defaultdict(int)
for end in range(len(fruits)):
fruit_count[fruits[end]] += 1
while len(fruit_count) > 2:
fruit_count[fruits[start]] -= 1
if fruit_count[fruits[start]] == 0:
del fruit_count[fruits[start]]
start += 1
max_len = max(max_len, end - start + 1)
return max_len
4.7.767 - 2025-08-03 16:36:16 +0300 MSK
Links
Code
class Solution:
def modifyString(self, s: str) -> str:
res = list(s)
length = len(s)
for i in range(length):
char = res[i]
if char != "?":
continue
for char_ascii in string.ascii_lowercase:
if (
(i > 0 and res[i - 1] == char_ascii)
or (i < length - 1 and res[i + 1] == char_ascii)
):
continue
res[i] = char_ascii
break
return "".join(res)
4.7.768 - 2025-08-03 16:21:01 +0300 MSK
Links
Code
class Solution:
def diagonalSum(self, mat: List[List[int]]) -> int:
length = len(mat)
res = 0
for i in range(length):
row1, col1 = i, i
row2, col2 = i, length - i - 1
res += mat[row1][col1]
if row2 != row1 or col2 != col1:
res += mat[row2][col2]
return res
4.7.769 - 2025-08-03 16:03:54 +0300 MSK
Links
Code
class Solution:
def containsPattern(self, arr: List[int], m: int, k: int) -> bool:
length = len(arr)
if length < m * k:
return False
for i in range(length - m + 1):
cur_pat = arr[i:i+m]
count = 1
for j in range(i + m, length, m):
if arr[j:j+m] == cur_pat:
count += 1
else:
break
if count >= k:
return True
return False
4.7.770 - 2025-08-03 15:13:16 +0300 MSK
Links
Code
class Solution:
def mostVisited(self, n: int, rounds: List[int]) -> List[int]:
start_sector, end_sector = rounds[0], rounds[-1]
if start_sector <= end_sector:
return tuple(range(start_sector, end_sector + 1))
return tuple(
itertools.chain(
range(1, end_sector + 1),
range(start_sector, n + 1)
)
)
4.7.771 - 2025-08-03 15:01:18 +0300 MSK
Links
Code
class Solution:
def thousandSeparator(self, n: int) -> str:
if n < 1000:
return str(n)
res = []
count = 0
while n > 0:
res.append(str(n % 10))
count += 1
n //= 10
if count % 3 == 0 and n > 0:
res.append(".")
res.reverse()
return "".join(res)
4.7.772 - 2025-08-03 14:57:57 +0300 MSK
Links
Code
class Solution:
def threeConsecutiveOdds(self, arr: List[int]) -> bool:
count = 0
for num in arr:
if num % 2 == 0:
count = 0
else:
count += 1
if count == 3:
return True
return False
4.7.773 - 2025-08-03 14:56:16 +0300 MSK
Links
Code
class Solution:
def findKthPositive(self, arr: List[int], k: int) -> int:
prev = 0
for num in arr:
diff = num - prev - 1
if k > diff:
k -= diff
else:
return prev + k
prev = num
return prev + k
4.7.774 - 2025-08-03 14:39:49 +0300 MSK
Links
Code
class Solution:
def restoreString(self, s: str, indices: List[int]) -> str:
res = [None] * len(s)
for i, char in zip(indices, s):
res[i] = char
return "".join(res)
4.7.775 - 2025-08-03 14:36:46 +0300 MSK
Links
Code
SELECT
Patients.patient_id,
Patients.patient_name,
Patients.conditions
FROM
Patients
WHERE
Patients.conditions ~ '(^|\s)DIAB1'
4.7.776 - 2025-08-03 14:33:50 +0300 MSK
Links
Code
class Solution:
def numWaterBottles(self, numBottles: int, numExchange: int) -> int:
res = 0
empty = 0
while numBottles > 0:
res += numBottles
empty += numBottles
numBottles = empty // numExchange
empty %= numExchange
return res
4.7.777 - 2025-08-03 14:29:35 +0300 MSK
Links
Code
SELECT
*
FROM
Users
WHERE
Users.mail ~ '^[a-zA-Z][a-zA-Z0-9\.\-_]*@leetcode\.com$';
4.7.778 - 2025-08-03 14:27:36 +0300 MSK
Links
Code
class Solution:
def reformatDate(self, date: str) -> str:
day_str, mnth_str, year_str = date.split()
if len(day_str) == 3:
day = int(day_str[0:1])
else:
day = int(day_str[0:2])
mnth = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"].index(mnth_str) + 1
year = int(year_str)
return f"{year}-{mnth:02}-{day:02}"
4.7.779 - 2025-08-03 14:18:22 +0300 MSK
Links
Code
class Solution:
def canMakeArithmeticProgression(self, arr: List[int]) -> bool:
arr.sort()
diff = abs(arr[0] - arr[1])
for i in range(1, len(arr) - 1):
if abs(arr[i] - arr[i+1]) != diff:
return False
return True
4.7.780 - 2025-08-03 14:14:27 +0300 MSK
Links
Code
SELECT
Activities.sell_date,
COUNT(
DISTINCT (Activities.product, Activities.sell_date)
) AS num_sold,
STRING_AGG(
DISTINCT Activities.product, ',' ORDER BY product
) AS products
FROM
Activities
GROUP BY
Activities.sell_date
ORDER BY
Activities.sell_date;
4.7.781 - 2025-08-03 13:56:55 +0300 MSK
Links
Code
class Solution:
def finalPrices(self, prices: List[int]) -> List[int]:
stack = deque()
for i in range(len(prices)):
price = prices[i]
while True:
if not stack:
break
last_i, last_price = stack[-1]
if last_price >= price:
prices[last_i] -= price
stack.pop()
else:
break
stack.append((i, price))
return prices
4.7.782 - 2025-08-03 13:42:44 +0300 MSK
Links
Code
class Solution:
def shuffle(self, nums: List[int], n: int) -> List[int]:
res = []
for j in range(n, 2 * n):
res.extend((nums[j - n], nums[j]))
return res
4.7.783 - 2025-08-03 13:35:23 +0300 MSK
Links
Code
class Solution:
def canBeEqual(self, target: List[int], arr: List[int]) -> bool:
freqs = defaultdict(int)
length = len(target)
if length != len(arr):
return False
for i in range(length):
freqs[target[i]] += 1
freqs[arr[i]] -= 1
for count in freqs.values():
if count != 0:
return False
return True
4.7.784 - 2025-08-03 13:30:55 +0300 MSK
Links
Code
class Solution:
def isPrefixOfWord(self, sentence: str, searchWord: str) -> int:
for i, word in enumerate(sentence.split()):
if word.startswith(searchWord):
return i + 1
return -1
4.7.785 - 2025-08-03 13:25:11 +0300 MSK
Links
Code
class Solution:
def maxPower(self, s: str) -> int:
prev = s[0]
count = 1
max_count= 1
for char in s[1:]:
if char == prev:
count += 1
max_count = max(max_count, count)
else:
count = 1
prev = char
return max_count
4.7.786 - 2025-08-03 13:22:53 +0300 MSK
Links
Code
class Solution:
def kLengthApart(self, nums: List[int], k: int) -> bool:
prev = -k - 1
for i, num in enumerate(nums):
if num == 0:
continue
if i - prev - 1 >= k:
prev = i
else:
return False
return True
4.7.787 - 2025-08-03 13:19:10 +0300 MSK
Links
Code
class Solution:
def reformat(self, s: str) -> str:
res, digits, al = [""], [], []
for char in s:
if char.isalpha():
al.append(char)
else:
digits.append(char)
while digits and al:
res.extend((digits.pop(), al.pop()))
if digits:
res.append(digits.pop())
elif al:
res[0] = al.pop()
if digits or al:
return ""
return "".join(res)
4.7.788 - 2025-08-03 11:38:37 +0300 MSK
Links
Code
class Solution:
def minStartValue(self, nums: List[int]) -> int:
min_sum = float('inf')
cur_sum = 0
for num in nums:
cur_sum += num
min_sum = min(min_sum, cur_sum)
return max(1 - min_sum, 1)
4.7.789 - 2025-08-03 10:42:15 +0300 MSK
Links
Code
class Solution:
class TrieNode:
def __init__(self):
# Tracks how many times this substring appears in the Trie.
self.frequency = 0
# Maps characters to their respective child nodes.
self.child_nodes = {}
def stringMatching(self, words: List[str]) -> List[str]:
matching_words = []
root = self.TrieNode() # Initialize the root of the Trie.
# Insert all suffixes of each word into the Trie.
for word in words:
for start_index in range(len(word)):
# Insert each suffix starting from index start_index.
self._insert_word(root, word[start_index:])
# Check each word to see if it exists as a substring in the Trie.
for word in words:
if self._is_substring(root, word):
matching_words.append(word)
return matching_words
def _insert_word(self, root: "TrieNode", word: str) -> None:
current_node = root
for char in word:
if char not in current_node.child_nodes:
# Create a new node if the character does not exist.
current_node.child_nodes[char] = self.TrieNode()
current_node = current_node.child_nodes[char]
current_node.frequency += 1 # Increment the frequency of the node.
def _is_substring(self, root: "TrieNode", word: str) -> bool:
current_node = root
for char in word:
# Traverse the Trie following the characters of the word.
current_node = current_node.child_nodes[char]
# A word is a substring if its frequency in the Trie is greater than 1.
return current_node.frequency > 1
4.7.790 - 2025-08-03 10:26:28 +0300 MSK
Links
Code
class Solution:
def maxTotalFruits(
self, fruits: List[List[int]], startPos: int, k: int
) -> int:
n = len(fruits)
sum_ = [0] * (n + 1)
indices = [0] * n
for i in range(n):
sum_[i + 1] = sum_[i] + fruits[i][1]
indices[i] = fruits[i][0]
ans = 0
for x in range(k // 2 + 1):
# move left x steps, then right (k - 2x) steps
y = k - 2 * x
left = startPos - x
right = startPos + y
start = bisect_left(indices, left)
end = bisect_right(indices, right)
ans = max(ans, sum_[end] - sum_[start])
# move right x steps, then left (k - 2x) steps
y = k - 2 * x
left = startPos - y
right = startPos + x
start = bisect_left(indices, left)
end = bisect_right(indices, right)
ans = max(ans, sum_[end] - sum_[start])
return ans
4.7.791 - 2025-08-02 20:09:46 +0300 MSK
Links
Code
SELECT
Users.name,
COALESCE(SUM(Rides.distance), 0) AS "travelled_distance"
FROM
Users
LEFT JOIN
Rides
ON
Users.id = Rides.user_id
GROUP BY
Users.id, Users.name
ORDER BY
travelled_distance DESC,
Users.name ASC
4.7.792 - 2025-08-02 20:03:30 +0300 MSK
Links
Code
class Solution:
def minSubsequence(self, nums: List[int]) -> List[int]:
max_sum = sum(nums)
nums.sort(reverse=True)
cur_sum = 0
res = []
for num in nums:
cur_sum += num
res.append(num)
if cur_sum > max_sum - cur_sum:
break
return res
4.7.793 - 2025-08-02 19:58:48 +0300 MSK
Links
Code
class Solution:
def countLargestGroup(self, n: int) -> int:
freqs = defaultdict(int)
def count(num: int) -> int:
res = 0
while num > 0:
res += num % 10
num //= 10
return res
max_freq = 0
for i in range(1, n + 1):
group = count(i)
freq = freqs[group] + 1
freqs[group] = freq
if freq > max_freq:
max_freq = freq
res = 0
for freq in freqs.values():
if freq == max_freq:
res += 1
return res
4.7.794 - 2025-08-02 19:54:21 +0300 MSK
Links
Code
class Solution:
def findLucky(self, arr: List[int]) -> int:
freqs = defaultdict(int)
for num in arr:
freqs[num] += 1
max_num = -1
for num, freq in freqs.items():
if num == freq:
max_num = max(max_num, num)
return max_num
4.7.795 - 2025-08-02 19:50:44 +0300 MSK
Links
Code
class Solution:
def createTargetArray(self, nums: List[int], index: List[int]) -> List[int]:
res = []
for i, num in zip(index, nums):
res.insert(i, num)
return res
4.7.796 - 2025-08-02 19:45:12 +0300 MSK
Links
Code
class Solution:
def luckyNumbers(self, matrix: List[List[int]]) -> List[int]:
rows = len(matrix)
cols = len(matrix[0])
min_row = float("-inf")
max_col = float("inf")
for row in range(rows):
min_row = max(min_row, min(matrix[row]))
for col in range(cols):
cur_max_col = float("-inf")
for row in range(rows):
cur_max_col = max(cur_max_col, matrix[row][col])
max_col = min(max_col, cur_max_col)
if min_row == max_col:
return [min_row]
return []
4.7.797 - 2025-08-02 19:36:06 +0300 MSK
Links
Code
class Solution:
def luckyNumbers(self, matrix: List[List[int]]) -> List[int]:
rows = len(matrix)
cols = len(matrix[0])
min_row = [None] * rows
max_col = [None] * cols
for row in range(rows):
min_row[row] = min(matrix[row])
for col in range(cols):
num_max = float("-inf")
for row in range(rows):
num = matrix[row][col]
if num > num_max:
num_max = num
max_col[col] = num_max
res = []
for row in range(rows):
for col in range(cols):
num = matrix[row][col]
if num == min_row[row] and num == max_col[col]:
res.append(num)
return res
4.7.798 - 2025-08-02 19:28:39 +0300 MSK
Links
Code
SELECT
EmployeeUNI.unique_id, Employees.name
FROM
Employees
LEFT JOIN
EmployeeUNI
ON
Employees.id = EmployeeUNI.id
4.7.799 - 2025-08-02 19:24:42 +0300 MSK
Links
Code
class Solution:
def generateTheString(self, n: int) -> str:
if n % 2 == 0:
return ("a" * (n - 1)) + "b"
return "a" * n
4.7.800 - 2025-08-02 19:22:20 +0300 MSK
Links
Code
class Solution:
def sortString(self, s: str) -> str:
freqs = defaultdict(int)
for char in s:
freqs[char] += 1
keys = list(freqs.keys())
keys.sort(key = ord)
length = len(keys)
res = []
while freqs:
for i in itertools.chain(range(length), reversed(range(length))):
key = keys[i]
if key not in freqs:
continue
res.append(key)
freqs[key] -= 1
if freqs[key] == 0:
freqs.pop(key)
return "".join(res)
4.7.801 - 2025-08-02 19:12:42 +0300 MSK
Links
Code
class Solution:
def smallerNumbersThanCurrent(self, nums: List[int]) -> List[int]:
num_to_count = {}
for i, num in enumerate(sorted(nums)):
if num not in num_to_count:
num_to_count[num] = i
for i in range(len(nums)):
nums[i] = num_to_count[nums[i]]
return nums
4.7.802 - 2025-08-02 19:08:24 +0300 MSK
Links
Code
class Solution:
def daysBetweenDates(self, date1: str, date2: str) -> int:
year1, month1, day1 = map(int, date1.split('-'))
year2, month2, day2 = map(int, date2.split('-'))
date1 = datetime.date(year1, month1, day1)
date2 = datetime.date(year2, month2, day2)
return abs((date2 - date1).days)
4.7.803 - 2025-08-02 18:59:52 +0300 MSK
Links
Code
class Solution:
def checkIfExist(self, arr: List[int]) -> bool:
enc = set()
for num in arr:
if num == 0 and 0 in enc:
return True
if num % 2 == 0 and num // 2 in enc:
return True
if num * 2 in enc:
return True
enc.add(num)
return False
4.7.804 - 2025-08-02 18:49:48 +0300 MSK
Links
Code
class Solution:
def removePalindromeSub(self, s: str) -> int:
if s == s[::-1]:
return 1
return 2
4.7.805 - 2025-08-02 18:45:57 +0300 MSK
Links
Code
class Solution:
def arrayRankTransform(self, arr: List[int]) -> List[int]:
num_to_rank = defaultdict(int)
nums = sorted(set(arr))
for rank, num in enumerate(nums, 1):
num_to_rank[num] = rank
for i in range(len(arr)):
arr[i] = num_to_rank[arr[i]]
return arr
4.7.806 - 2025-08-02 18:40:13 +0300 MSK
Links
Code
class Solution:
def arrayRankTransform(self, arr: List[int]) -> List[int]:
ind = defaultdict(list)
for i, num in enumerate(arr):
ind[num].append(i)
for rank, num in enumerate(sorted(ind.keys()), 1):
for i in ind[num]:
arr[i] = rank
return arr
4.7.807 - 2025-08-02 18:33:48 +0300 MSK
Links
Code
SELECT
Products.product_name, SUM(Orders.unit) as "unit"
FROM
Products
JOIN
Orders
ON
Orders.product_id = Products.product_id
WHERE
Orders.order_date BETWEEN '2020-02-01' AND '2020-02-29'
GROUP BY
Products.product_name
HAVING
SUM(Orders.unit) >= 100;
4.7.808 - 2025-08-02 18:22:51 +0300 MSK
Links
Code
class Solution:
def maximum69Number(self, num: int) -> int:
digits = []
while num > 0:
digits.append(num % 10)
num //= 10
digits.reverse()
res = 0
enc = False
length = len(digits)
for i, digit in enumerate(digits):
if digit == 6 and not enc:
digit = 9
enc = True
res += (10 ** (length - i - 1)) * digit
return res
4.7.809 - 2025-08-02 18:14:37 +0300 MSK
Links
Code
class Solution:
def getNoZeroIntegers(self, n: int) -> List[int]:
if n <= 10:
return [1, n - 1]
def check(num: int) -> bool:
while num > 0:
if num % 10 == 0:
return False
num //= 10
return True
for i in range(1, (n + 1) // 2):
num1, num2 = i, n - i
if check(num1) and check(num2):
return [num1, num2]
raise Exception
4.7.810 - 2025-08-02 18:07:54 +0300 MSK
Links
Code
class Solution:
def decompressRLElist(self, nums: List[int]) -> List[int]:
res = []
i = 0
length = len(nums)
while i < length:
freq, val = nums[i], nums[i + 1]
i += 2
res.extend((val, ) * freq)
return res
4.7.811 - 2025-08-02 18:04:04 +0300 MSK
Links
Code
class Solution:
def freqAlphabets(self, s: str) -> str:
res = []
length = len(s)
i = 0
while i < length:
if i + 2 < length and s[i + 2] == "#":
res.append(chr(int(s[i:i+2]) + 97 - 1))
i += 3
else:
res.append(chr(int(s[i]) + 97 - 1))
i += 1
return "".join(res)
4.7.812 - 2025-08-02 17:59:03 +0300 MSK
Links
Code
class Solution:
def sumZero(self, n: int) -> List[int]:
if n == 1:
return [0]
res = []
if n % 2 != 0:
res.append(0)
n -= 1
for i in range(1, (n // 2) + 1):
res.extend((i, -i))
return res
4.7.813 - 2025-08-02 17:54:14 +0300 MSK
Links
Code
class Solution:
def replaceElements(self, arr: List[int]) -> List[int]:
greatest = -1
for i in reversed(range(len(arr))):
current = arr[i]
arr[i] = greatest
if current > greatest:
greatest = current
return arr
4.7.814 - 2025-08-02 17:28:54 +0300 MSK
Links
Code
class Solution:
def findNumbers(self, nums: List[int]) -> int:
def count(num: int) -> int:
res = 0
while num:
res += 1
num //= 10
return res
res = 0
for num in nums:
if count(num) % 2 == 0:
res += 1
return res
4.7.815 - 2025-08-02 17:26:28 +0300 MSK
Links
Code
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def getDecimalValue(self, head: Optional[ListNode]) -> int:
res = 0
while head:
res <<= 1
res |= head.val
head = head.next
return res
4.7.816 - 2025-08-02 17:24:46 +0300 MSK
Links
Code
SELECT
Students.student_id,
Students.student_name,
Subjects.subject_name,
COUNT(Examinations.subject_name) as "attended_exams"
FROM
Students
CROSS JOIN
Subjects
LEFT JOIN
Examinations
ON
Students.student_id = Examinations.student_id
AND Subjects.subject_name = Examinations.subject_name
GROUP BY
Students.student_id,
Students.student_name,
Subjects.subject_name
ORDER BY
Students.student_id,
Subjects.subject_name
4.7.817 - 2025-08-02 17:06:00 +0300 MSK
Links
Code
class Solution:
def tictactoe(self, moves: List[List[int]]) -> str:
cols = [[0] * 3 for _ in range(2)]
rows = [[0] * 3 for _ in range(2)]
diags = [[0] * 2 for _ in range(2)]
players = ["A", "B"]
for i, (row, col) in enumerate(moves):
if i % 2 == 0:
player = 0
else:
player = 1
rows[player][row] += 1
cols[player][col] += 1
if row == col:
diags[player][0] += 1
if row == 2 - col:
diags[player][1] += 1
for player in range(2):
for win in (cols, rows, diags):
if 3 in win[player]:
return players[player]
if len(moves) == 9:
return "Draw"
return "Pending"
4.7.818 - 2025-08-02 16:50:59 +0300 MSK
Links
Code
class Solution:
def shiftGrid(self, grid: List[List[int]], k: int) -> List[List[int]]:
if not grid or not grid[0]:
return grid
row_length = len(grid)
col_length = len(grid[0])
num_count = row_length * col_length
k %= num_count
res = [[0] * col_length for _ in range(row_length)]
for row in range(row_length):
for col in range(col_length):
flat_mat_index = (row * col_length) + col
new_flat_mat_index = (flat_mat_index + k) % num_count
new_row = new_flat_mat_index // col_length
new_col = new_flat_mat_index % col_length
res[new_row][new_col] = grid[row][col]
return res
4.7.819 - 2025-08-02 16:38:17 +0300 MSK
Links
Code
class Solution:
def oddCells(self, m: int, n: int, indices: List[List[int]]) -> int:
mat = [[0] * n for _ in range(m)]
for row, col in indices:
for cur_col in range(n):
mat[row][cur_col] += 1
for cur_row in range(m):
mat[cur_row][col] += 1
count = 0
for row in range(m):
for col in range(n):
if mat[row][col] % 2 != 0:
count += 1
return count
4.7.820 - 2025-08-02 16:29:04 +0300 MSK
Links
Code
class Solution:
def minCost(self, basket1: List[int], basket2: List[int]) -> int:
freq = Counter()
m = float("inf")
for b1 in basket1:
freq[b1] += 1
m = min(m, b1)
for b2 in basket2:
freq[b2] -= 1
m = min(m, b2)
merge = []
for k, c in freq.items():
if c % 2 != 0:
return -1
merge.extend([k] * (abs(c) // 2))
if not merge:
return 0
merge.sort()
return sum(min(2 * m, x) for x in merge[: len(merge) // 2])
4.7.821 - 2025-08-02 16:25:49 +0300 MSK
Links
Code
SELECT
Prices.product_id,
CASE
WHEN
SUM(UnitsSold.units) is null
THEN
0
ELSE
ROUND(SUM(UnitsSold.units * Prices.price) / SUM(UnitsSold.units)::numeric, 2)
END AS average_price
FROM
Prices
LEFT JOIN
UnitsSold
ON
UnitsSold.product_id = Prices.product_id
AND UnitsSold.purchase_date
BETWEEN Prices.start_date AND Prices.end_date
GROUP BY
Prices.product_id;
4.7.822 - 2025-08-02 16:11:25 +0300 MSK
Links
Code
class Solution:
def checkStraightLine(self, coordinates: List[List[int]]) -> bool:
x1, y1 = coordinates[0]
x2, y2 = coordinates[1]
for x3, y3 in coordinates[2:]:
if (x3 - x1) * (y2 - y1) != (x2 - x1) * (y3 - y1):
return False
return True
4.7.823 - 2025-08-02 16:04:47 +0300 MSK
Links
Code
class Solution:
def balancedStringSplit(self, s: str) -> int:
count_l, count_r = 0, 0
count = 0
for char in s:
if char == "R":
count_r += 1
else:
count_l += 1
if count_l == count_r:
count += 1
return count
4.7.824 - 2025-08-02 15:56:06 +0300 MSK
Links
Code
class Solution:
def minCostToMoveChips(self, position: List[int]) -> int:
length = len(position)
odd, even = 0, 0
for pos in position:
if pos % 2 == 0:
even += 1
else:
odd += 1
return min(odd, even)
4.7.825 - 2025-08-02 15:46:47 +0300 MSK
Links
Code
SELECT
query_name,
ROUND(SUM(rating * 1.0 / position) / COUNT(*), 2) AS quality,
ROUND(
COUNT(CASE WHEN rating < 3 THEN 1 END) * 1.0 / COUNT(*),
4
) * 100 AS poor_query_percentage
FROM
Queries
GROUP BY
query_name;
4.7.826 - 2025-08-02 15:43:09 +0300 MSK
Links
Code
class Solution:
def minimumAbsDifference(self, arr: List[int]) -> List[List[int]]:
arr.sort()
min_diff = float("inf")
res = []
for i, num in enumerate(arr[:-1]):
nxt = arr[i + 1]
diff = abs(nxt - num)
if diff < min_diff:
res.clear()
res.append((num, nxt))
min_diff = diff
elif diff == min_diff:
res.append((num, nxt))
return res
4.7.827 - 2025-08-02 15:41:03 +0300 MSK
Links
Code
class Solution:
def minimumAbsDifference(self, arr: List[int]) -> List[List[int]]:
arr.sort()
min_diff = float("inf")
diffs = defaultdict(list)
for i, num in enumerate(arr[:-1]):
nxt = arr[i + 1]
diff = abs(nxt - num)
diffs[diff].append((num, nxt))
min_diff = min(min_diff, diff)
return diffs[min_diff]
4.7.828 - 2025-08-02 15:39:53 +0300 MSK
Links
Code
class Solution:
def minimumAbsDifference(self, arr: List[int]) -> List[List[int]]:
arr.sort()
min_diff = float("inf")
res = []
for i, num in enumerate(arr[:-1]):
nxt = arr[i + 1]
diff = abs(nxt - num)
min_diff = min(min_diff, diff)
for i, num in enumerate(arr[:-1]):
nxt = arr[i + 1]
diff = abs(nxt - num)
if diff == min_diff:
res.append((num, nxt))
return res
4.7.829 - 2025-08-02 15:34:16 +0300 MSK
Links
Code
class Solution:
def maxNumberOfBalloons(self, text: str) -> int:
freqs = defaultdict(int)
for char in text:
freqs[char] += 1
res = min(
freqs["b"],
freqs["a"],
freqs["l"] // 2,
freqs["o"] // 2,
freqs["n"]
)
return res
4.7.830 - 2025-08-02 15:27:49 +0300 MSK
Links
Code
class Solution:
def dayOfTheWeek(self, day: int, month: int, year: int) -> str:
return [
"Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday",
"Sunday"
][datetime.date(year, month, day).weekday()]
4.7.831 - 2025-08-02 15:19:46 +0300 MSK
Links
Code
class Solution:
def distanceBetweenBusStops(self, distance: List[int], start: int, destination: int) -> int:
length = len(distance)
forward_dist, back_dist = 0, 0
forward, back = start, start
while True:
if forward == destination:
return forward_dist
if back == destination or length + back == destination:
return back_dist
forward_dist += distance[forward]
forward = (forward + 1) % length
back_dist += distance[back - 1]
back -= 1
raise Exception
4.7.832 - 2025-08-02 15:01:25 +0300 MSK
Links
Code
SELECT id,
SUM(
CASE
WHEN
month = 'Jan'
THEN
revenue
ELSE
NULL
END
) AS Jan_Revenue,
SUM(
CASE
WHEN
month = 'Feb'
THEN
revenue
ELSE
NULL
END
) AS Feb_Revenue,
SUM(
CASE
WHEN
month = 'Mar'
THEN
revenue
ELSE
NULL
END
) AS Mar_Revenue,
SUM(
CASE
WHEN
month = 'Apr'
THEN
revenue
ELSE
NULL
END
) AS Apr_Revenue,
SUM(
CASE
WHEN
month = 'May'
THEN
revenue
ELSE
NULL
END
) AS May_Revenue,
SUM(
CASE
WHEN
month = 'Jun'
THEN
revenue
ELSE
NULL
END
) AS Jun_Revenue,
SUM(
CASE
WHEN
month = 'Jul'
THEN
revenue
ELSE
NULL
END
) AS Jul_Revenue,
SUM(
CASE
WHEN
month = 'Aug'
THEN
revenue
ELSE
NULL
END
) AS Aug_Revenue,
SUM(
CASE
WHEN
month = 'Sep'
THEN
revenue
ELSE
NULL
END
) AS Sep_Revenue,
SUM(
CASE
WHEN
month = 'Oct'
THEN
revenue
ELSE
NULL
END
) AS Oct_Revenue,
SUM(
CASE
WHEN
month = 'Nov'
THEN
revenue
ELSE
NULL
END
) AS Nov_Revenue,
SUM(
CASE
WHEN
month = 'Dec'
THEN
revenue
ELSE
NULL
END
) AS Dec_Revenue
FROM
Department
GROUP BY
id;
4.7.833 - 2025-08-02 14:54:02 +0300 MSK
Links
Code
class Solution:
def numPrimeArrangements(self, n: int) -> int:
prime = [True] * (n + 1)
prime[0] = prime[1] = False
for i in range(2, int(n ** 0.5) + 1):
if not prime[i]:
continue
for j in range(i * i, n + 1, i):
prime[j] = False
prime_count = sum(prime)
mod = 10**9 + 7
fact_primes = math.factorial(prime_count)
fact_norm = math.factorial(n - prime_count)
return (fact_primes * fact_norm) % mod
4.7.834 - 2025-08-02 14:25:28 +0300 MSK
Links
Code
class Solution:
def dayOfYear(self, date: str) -> int:
year, month, day = map(int, date.split('-'))
days_in_month = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
if (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0):
days_in_month[1] = 29
day_number = sum(days_in_month[:month - 1]) + day
return day_number
4.7.835 - 2025-08-02 14:21:50 +0300 MSK
Links
Code
SELECT DISTINCT
views1.author_id as "id"
FROM
Views views1
CROSS JOIN
Views views2
WHERE
views1.author_id = views2.viewer_id
AND views1.author_id = views2.author_id
ORDER BY
views1.author_id ASC
4.7.836 - 2025-08-02 14:15:20 +0300 MSK
Links
Code
SELECT
activity_date AS day,
COUNT(DISTINCT(user_id)) AS active_users
FROM
Activity
WHERE
activity_date
BETWEEN '2019-07-27'::DATE - INTERVAL '29 DAYS'
AND '2019-07-27'::DATE
GROUP BY
activity_date
4.7.837 - 2025-08-02 14:10:21 +0300 MSK
Links
Code
class Solution:
def numEquivDominoPairs(self, dominoes: List[List[int]]) -> int:
freqs = [0] * 100
res = 0
for num1, num2 in dominoes:
if num1 > num2:
val = num1 * 10 + num2
else:
val = num2 * 10 + num1
res += freqs[val]
freqs[val] += 1
return res
4.7.838 - 2025-08-02 14:00:42 +0300 MSK
Links
Code
class Foo:
def __init__(self):
self._lock1 = threading.Lock()
self._lock2 = threading.Lock()
self._lock1.acquire()
self._lock2.acquire()
def first(self, printFirst: 'Callable[[], None]') -> None:
printFirst()
self._lock1.release()
def second(self, printSecond: 'Callable[[], None]') -> None:
with self._lock1:
printSecond()
self._lock2.release()
def third(self, printThird: 'Callable[[], None]') -> None:
with self._lock2:
printThird()
4.7.839 - 2025-08-02 13:55:22 +0300 MSK
Links
Code
class Solution:
def defangIPaddr(self, address: str) -> str:
return address.replace(".", "[.]")
4.7.840 - 2025-08-02 13:54:26 +0300 MSK
Links
Code
class Solution:
def distributeCandies(self, candies: int, num_people: int) -> List[int]:
res = [0] * num_people
i = 0
while candies > 0:
loss = min(i + 1, candies)
res[i % num_people] += loss
i += 1
candies -= loss
return res
4.7.841 - 2025-08-02 13:48:16 +0300 MSK
Links
Code
class Solution:
def distributeCandies(self, candies: int, num_people: int) -> List[int]:
res = [0] * num_people
mult = 0
while candies > 0:
for i in range(num_people):
target = min((mult * num_people) + (i + 1), candies)
if candies > 0:
res[i] += target
candies -= target
else:
break
mult += 1
return res
4.7.842 - 2025-08-02 13:02:23 +0300 MSK
Links
Code
class Solution:
def duplicateZeros(self, arr: List[int]) -> None:
"""
Do not return anything, modify arr in-place instead.
"""
possible_dups = 0
length_ = len(arr) - 1
for left in range(length_ + 1):
if left > length_ - possible_dups:
break
if arr[left] == 0:
if left == length_ - possible_dups:
arr[length_] = 0
length_ -= 1
break
possible_dups += 1
last = length_ - possible_dups
for i in range(last, -1, -1):
if arr[i] == 0:
arr[i + possible_dups] = 0
possible_dups -= 1
arr[i + possible_dups] = 0
else:
arr[i + possible_dups] = arr[i]
4.7.843 - 2025-08-02 12:36:15 +0300 MSK
Links
Code
class Solution:
def duplicateZeros(self, arr: List[int]) -> None:
"""
Do not return anything, modify arr in-place instead.
"""
queue = deque()
for i in range(len(arr)):
num = arr[i]
if queue:
arr[i] = queue.popleft()
queue.append(num)
if num == 0:
queue.append(0)
4.7.844 - 2025-08-02 12:22:49 +0300 MSK
Links
Code
SELECT
Product.product_id, Product.product_name
FROM
Sales
JOIN
Product
ON
Product.product_id = Sales.product_id
GROUP BY
Product.product_id, Product.product_name
HAVING
MIN(Sales.sale_date) >= '2019-01-01'
AND MAX(Sales.sale_date) <= '2019-03-31'
4.7.845 - 2025-08-02 11:12:11 +0300 MSK
Links
Code
class Solution:
def findOcurrences(self, text: str, first: str, second: str) -> List[str]:
words = text.split()
length = len(words)
if length < 3:
return []
res = []
i = 0
while i + 2 < length:
if words[i] == first and words[i+1] == second:
res.append(words[i+2])
i += 1
return res
4.7.846 - 2025-08-02 10:56:41 +0300 MSK
Links
Code
SELECT
project_id,
ROUND(AVG(experience_years), 2) AS average_years
FROM
Project
JOIN
Employee
ON
Project.employee_id = Employee.employee_id
GROUP BY
project_id
4.7.847 - 2025-08-02 10:53:44 +0300 MSK
Links
Code
SELECT
project_id,
ROUND(AVG(experience_years), 2) AS average_years
FROM
Project
JOIN
Employee
ON
Project.employee_id = Employee.employee_id
GROUP BY
project_id
4.7.848 - 2025-08-02 10:46:44 +0300 MSK
Links
Code
SELECT
product_name, year, price
FROM
Sales
LEFT JOIN
Product
ON
Sales.product_id = Product.product_id
4.7.849 - 2025-08-02 10:41:17 +0300 MSK
Links
Code
SELECT
actor_id, director_id
FROM
ActorDirector
GROUP BY
actor_id, director_id
HAVING
COUNT(actor_id) >= 3;
4.7.850 - 2025-08-02 10:38:33 +0300 MSK
Links
Code
class Solution:
def removeDuplicates(self, s: str) -> str:
stack = []
for char in s:
if stack and char == stack[-1]:
stack.pop()
else:
stack.append(char)
return "".join(stack)
4.7.851 - 2025-08-02 10:31:09 +0300 MSK
Links
Code
class Solution:
def lastStoneWeight(self, stones: List[int]) -> int:
for i, num in enumerate(stones):
stones[i] = -num
heapq.heapify(stones)
while stones:
last = -heapq.heappop(stones)
if not stones:
return last
prev = -heapq.heappop(stones)
if last > prev:
heapq.heappush(stones, -(last - prev))
return 0
4.7.852 - 2025-08-02 10:28:21 +0300 MSK
Links
Code
class Solution:
def lastStoneWeight(self, stones: List[int]) -> int:
stones.sort()
while stones:
last = stones.pop()
if not stones:
return last
prev = stones[-1]
if last == prev:
stones.pop()
else:
stones[-1] = last - prev
stones.sort()
return 0
4.7.853 - 2025-08-02 09:19:39 +0300 MSK
Links
Code
class Solution:
def isBoomerang(self, points: List[List[int]]) -> bool:
x1, y1 = points[0]
x2, y2 = points[1]
x3, y3 = points[2]
return (y2 - y1) * (x3 - x2) != (y3 - y2) * (x2 - x1)
4.7.854 - 2025-08-02 09:15:14 +0300 MSK
Links
Code
class Solution:
def allCellsDistOrder(self, rows: int, cols: int, rCenter: int, cCenter: int) -> List[List[int]]:
res = []
for row in range(rows):
for col in range(cols):
res.append((row, col))
def key(point: tuple[int, int]) -> int:
row, col = point
return abs(row - rCenter) + abs(col - cCenter)
res.sort(key=key)
return res
4.7.855 - 2025-08-02 09:11:31 +0300 MSK
Links
Code
class Solution:
def allCellsDistOrder(self, rows: int, cols: int, rCenter: int, cCenter: int) -> List[List[int]]:
res = []
for row in range(rows):
for col in range(cols):
dist = abs(row - rCenter) + abs(col - cCenter)
res.append((dist, row, col))
res.sort()
for i in range(len(res)):
res[i] = res[i][1:]
return res
4.7.856 - 2025-08-02 09:03:11 +0300 MSK
Links
Code
class Solution:
def divisorGame(self, n: int) -> bool:
return n % 2 == 0
4.7.857 - 2025-08-02 08:55:10 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def sumRootToLeaf(self, root: Optional[TreeNode]) -> int:
res = 0
queue = [(root, 0)]
while queue:
node, parent = queue.pop()
if node is None:
continue
val = (parent << 1) | node.val
if not node.left and not node.right:
res += val
queue.extend(((node.left, val), (node.right, val)))
return res
4.7.858 - 2025-08-02 08:53:28 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def sumRootToLeaf(self, root: Optional[TreeNode]) -> int:
def dfs(node: Optional[TreeNode], parent: int) -> int:
if node is None:
return 0
cur_val = (parent << 1) | node.val
if not node.left and not node.right:
return cur_val
return dfs(node.left, cur_val) + dfs(node.right, cur_val)
return dfs(root, 0)
4.7.859 - 2025-08-02 08:48:51 +0300 MSK
Links
Code
class Solution:
def removeOuterParentheses(self, s: str) -> str:
res = []
balance = 0
start = 0
for i, char in enumerate(s):
if char == '(':
balance += 1
else:
balance -= 1
if balance == 0:
res.append(s[start + 1:i])
start = i + 1
return "".join(res)
4.7.860 - 2025-08-02 08:38:26 +0300 MSK
Links
Code
class Solution:
def prefixesDivBy5(self, nums: List[int]) -> List[bool]:
cur = 0
for i in range(len(nums)):
cur <<= 1
cur |= nums[i]
nums[i] = cur % 5 == 0
return nums
4.7.861 - 2025-08-02 08:34:40 +0300 MSK
Links
Code
class Solution:
def canThreePartsEqualSum(self, arr: List[int]) -> bool:
total = sum(arr)
if total % 3 != 0:
return False
length = len(arr)
target = total // 3
cur = 0
count = 0
for i, num in enumerate(arr):
cur += num
if cur == target:
cur = 0
count += 1
if count == 2 and i + 1 < length:
return True
return False
4.7.862 - 2025-08-01 21:34:49 +0300 MSK
Links
Code
class Solution:
def bitwiseComplement(self, n: int) -> int:
if n == 0:
return 1
res, count = 0, 0
while n > 0:
if n & 1 == 0:
res += 2 ** count
count += 1
n >>= 1
return res
4.7.863 - 2025-08-01 21:23:46 +0300 MSK
Links
Code
class Solution:
def largestSumAfterKNegations(self, nums: List[int], k: int) -> int:
nums.sort()
for i in range(len(nums)):
num = nums[i]
if num < 0 and k > 0:
nums[i] = -num
k -= 1
else:
break
if k == 0 or k % 2 == 0:
return sum(nums)
nums.sort()
nums[0] = -nums[0]
return sum(nums)
4.7.864 - 2025-08-01 20:49:53 +0300 MSK
Links
Code
class Solution:
def numRookCaptures(self, board: List[List[str]]) -> int:
bishop_row, bishop_col = -1, -1
length = len(board)
delta = (
(0, 1), (0, -1), (1, 0), (-1, 0)
)
for row in range(length):
for col in range(length):
if board[row][col] == "R":
bishop_row, bishop_col = row, col
break
if bishop_row != -1:
break
count = 0
for delta_row, delta_col in delta:
row, col = bishop_row, bishop_col
while 0 <= row < length and 0 <= col < length:
char = board[row][col]
if char == "p":
count += 1
break
elif char == "B":
break
row, col = row + delta_row, col + delta_col
return count
4.7.865 - 2025-08-01 20:14:01 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def isCousins(self, root: Optional[TreeNode], x: int, y: int) -> bool:
def dfs(node: Optional[TreeNode], depth: int) -> tuple[int, int]:
if node is None:
return 0, 0
if node.val == x:
return depth, 0
if node.val == y:
return 0, depth
depth1_x, depth1_y = dfs(node.left, depth + 1)
depth2_x, depth2_y = dfs(node.right, depth + 1)
depth1, depth2 = depth1_x or depth2_x, depth1_y or depth2_y
if depth1 and depth2 and depth1 == depth + 1:
return 0, 0
return depth1, depth2
depth1, depth2 = dfs(root, 0)
return depth1 == depth2 and depth1 > 1
4.7.866 - 2025-08-01 19:32:18 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def isUnivalTree(self, root: Optional[TreeNode]) -> bool:
queue = [root]
while queue:
node = queue.pop()
if node.right and node.val != node.right.val:
return False
if node.left and node.val != node.left.val:
return False
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
return True
4.7.867 - 2025-08-01 19:30:30 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def isUnivalTree(self, root: Optional[TreeNode]) -> bool:
def dfs(node: Optional[TreeNode]) -> bool:
if node is None:
return True
if node.left and node.val != node.left.val:
return False
if node.right and node.val != node.right.val:
return False
return dfs(node.left) and dfs(node.right)
return dfs(root)
4.7.868 - 2025-08-01 19:27:17 +0300 MSK
Links
Code
class Solution:
def repeatedNTimes(self, nums: List[int]) -> int:
length = len(nums)
for k in range(1, 4):
for i in range(length - k):
if nums[i] == nums[i+k]:
return nums[i]
raise Exception
4.7.869 - 2025-08-01 19:18:48 +0300 MSK
Links
Code
class Solution:
def repeatedNTimes(self, nums: List[int]) -> int:
enc = set()
for num in nums:
if num in enc:
return num
enc.add(num)
raise Exception
4.7.870 - 2025-08-01 19:16:55 +0300 MSK
Links
Code
class Solution:
def isAlienSorted(self, words: List[str], order: str) -> bool:
pos = {}
for i, char in enumerate(order):
pos[char] = i
for i in range(len(words) - 1):
cur, nxt = words[i], words[i + 1]
cur_length, nxt_length = len(cur), len(nxt)
for j in range(cur_length):
if j >= nxt_length:
return False
cur_char, nxt_char = cur[j], nxt[j]
if cur_char == nxt_char:
continue
if pos[cur_char] > pos[nxt_char]:
return False
break
return True
4.7.871 - 2025-08-01 17:46:26 +0300 MSK
Links
Code
class Solution:
def minDeletionSize(self, strs: List[str]) -> int:
res = 0
for col in range(len(strs[0])):
prev = 0
for row in range(len(strs)):
char = ord(strs[row][col])
if char >= prev:
prev = char
else:
res += 1
break
return res
4.7.872 - 2025-08-01 17:40:59 +0300 MSK
Links
Code
class Solution:
def diStringMatch(self, s: str) -> List[int]:
length = len(s)
res = [None] * (length + 1)
num_i, num_d = 0, length
for i, char in enumerate(s):
if char == "I":
res[i] = num_i
num_i += 1
else:
res[i] = num_d
num_d -= 1
res[-1] = num_i
return res
4.7.873 - 2025-08-01 17:39:13 +0300 MSK
Links
Code
class Solution:
def diStringMatch(self, s: str) -> List[int]:
length = len(s)
res = [None] * (length + 1)
num_i, num_d = 0, length
for i, char in enumerate(s):
is_i = char == "I"
if is_i:
res[i] = num_i
num_i += 1
else:
res[i] = num_d
num_d -= 1
if i != length - 1:
continue
if is_i:
res[i+1] = num_d
else:
res[i+1] = num_i
return res
4.7.874 - 2025-08-01 17:12:58 +0300 MSK
Links
Code
class Solution:
def validMountainArray(self, arr: List[int]) -> bool:
length = len(arr)
if length < 3:
return False
enc_peak = False
prev = arr[0]
for i, num in enumerate(arr[1:], 1):
if num == prev:
return False
if not enc_peak and num < prev:
enc_peak = True
if enc_peak and (num > prev or i == 1):
return False
prev = num
return enc_peak
4.7.875 - 2025-08-01 16:57:25 +0300 MSK
Links
Code
class Solution:
def numUniqueEmails(self, emails: List[str]) -> int:
enc = set()
for email in emails:
name, domain = email.rsplit("@", 1)
name = name.split("+", 1)[0].replace(".", "")
enc.add("@".join((name, domain)))
return len(enc)
4.7.876 - 2025-08-01 16:53:59 +0300 MSK
Links
Code
class Solution:
def isLongPressedName(self, name: str, typed: str) -> bool:
name_i, typed_i = 0, 0
name_length, typed_length = len(name), len(typed)
while name_i < name_length and typed_i < typed_length:
if name[name_i] == typed[typed_i]:
name_i += 1
typed_i += 1
elif typed_i >= 1 and typed[typed_i] == typed[typed_i - 1]:
typed_i += 1
else:
return False
if name_i != name_length:
return False
while typed_i < typed_length:
if typed[typed_i] != typed[typed_i - 1]:
return False
typed_i += 1
return True
4.7.877 - 2025-08-01 16:43:05 +0300 MSK
Links
Code
class Solution:
def sortArrayByParityII(self, nums: List[int]) -> List[int]:
res = [None] * len(nums)
i1, i2 = 0, 1
for num in nums:
if num % 2 == 0:
res[i1] = num
i1 += 2
else:
res[i2] = num
i2 += 2
return res
4.7.878 - 2025-08-01 16:39:51 +0300 MSK
Links
Code
class Solution:
def sortArrayByParityII(self, nums: List[int]) -> List[int]:
stack_even, stack_odd = [], []
for num in nums:
if num % 2 == 0:
stack_even.append(num)
else:
stack_odd.append(num)
for i in range(len(nums)):
if i % 2 == 0:
nums[i] = stack_even.pop()
else:
nums[i] = stack_odd.pop()
return nums
4.7.879 - 2025-08-01 16:33:40 +0300 MSK
Links
Code
class Solution:
def reverseOnlyLetters(self, s: str) -> str:
i, j = 0, len(s) - 1
res = [None] * len(s)
while i <= j:
char1, char2 = s[i], s[j]
if not char1.isalpha():
res[i] = char1
i += 1
elif not char2.isalpha():
res[j] = char2
j -= 1
else:
res[i], res[j] = char2, char1
i += 1
j -= 1
return "".join(res)
4.7.880 - 2025-08-01 16:24:11 +0300 MSK
Links
Code
import math
import functools
class Solution:
def hasGroupsSizeX(self, deck: List[int]) -> bool:
freqs = collections.defaultdict(int)
for num in deck:
freqs[num] += 1
gcd = functools.reduce(math.gcd, freqs.values())
return gcd > 1
4.7.881 - 2025-08-01 16:02:30 +0300 MSK
Links
Code
class Solution:
def smallestRangeI(self, nums: List[int], k: int) -> int:
min_num, max_num = min(nums), max(nums)
diff = max_num - min_num
res = max(diff - 2 * k, 0)
return res
4.7.882 - 2025-08-01 16:01:56 +0300 MSK
Links
Code
class Solution:
def smallestRangeI(self, nums: List[int], k: int) -> int:
min_num, max_num = float("inf"), float("-inf")
for num in nums:
if num > max_num:
max_num = num
if num < min_num:
min_num = num
diff = max_num - min_num
res = max(diff - 2 * k, 0)
return res
4.7.883 - 2025-08-01 15:50:58 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def increasingBST(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
if root is None:
return None
def dfs(node: TreeNode) -> tuple[TreeNode, TreeNode]:
if node.left:
root, tail = dfs(node.left)
tail.right = node
tail = node
node.left = None
else:
root, tail = node, node
if node.right:
right_root, right_tail = dfs(node.right)
tail.right = right_root
tail = right_tail
return root, tail
root, tail = dfs(root)
return root
4.7.884 - 2025-08-01 15:30:00 +0300 MSK
Links
Code
class Solution:
def surfaceArea(self, grid: list[list[int]]) -> int:
length = len(grid)
res = 0
adj_delta = (
(-1, 0), (1, 0), (0, -1), (0, 1)
)
for row in range(length):
for col in range(length):
height = grid[row][col]
if height == 0:
continue
res += 2
for row_delta, col_delta in adj_delta:
adj_row, adj_col = row + row_delta, col + col_delta
if 0 <= adj_row < length and 0 <= adj_col < length:
adj_height = grid[adj_row][adj_col]
else:
adj_height = 0
if height > adj_height:
res += grid[row][col] - adj_height
return res
4.7.885 - 2025-08-01 14:50:20 +0300 MSK
Links
Code
class Solution:
def fairCandySwap(self, aliceSizes: List[int], bobSizes: List[int]) -> List[int]:
count1, count2 = sum(aliceSizes), sum(bobSizes)
delta = (count2 - count1) // 2
set2 = set(bobSizes)
for ex1 in aliceSizes:
ex2 = ex1 + delta
if ex2 in set2:
return ex1, ex2
raise Exception
4.7.886 - 2025-08-01 13:28:24 +0300 MSK
Links
Code
class Solution:
def uncommonFromSentences(self, s1: str, s2: str) -> List[str]:
freqs = collections.defaultdict(int)
res = []
for word in s1.split():
freqs[word] += 1
for word in s2.split():
freqs[word] += 1
for word, freq in freqs.items():
if freq == 1:
res.append(word)
return res
4.7.887 - 2025-08-01 13:24:00 +0300 MSK
Links
Code
class Solution:
def uncommonFromSentences(self, s1: str, s2: str) -> List[str]:
freqs1, freqs2 = defaultdict(int), defaultdict(int)
words1, words2 = s1.split(" "), s2.split(" ")
for word in words1:
freqs1[word] += 1
for word in words2:
freqs2[word] += 1
res = []
for word, freq in freqs1.items():
if freq != 1 or word in freqs2:
continue
res.append(word)
for word, freq in freqs2.items():
if freq != 1 or word in freqs1:
continue
res.append(word)
return res
4.7.888 - 2025-08-01 13:12:38 +0300 MSK
Links
Code
class Solution:
def projectionArea(self, grid: list[list[int]]) -> int:
res = 0
length = len(grid)
for i in range(length):
best_row = 0
best_col = 0
for j in range(length):
if grid[i][j]:
res += 1
best_row = max(best_row, grid[i][j])
best_col = max(best_col, grid[j][i])
res += best_row + best_col
return res
4.7.889 - 2025-08-01 09:59:43 +0300 MSK
Links
Code
class Solution:
def lemonadeChange(self, bills: List[int]) -> bool:
change_5, change_10 = 0, 0
for bill in bills:
if bill == 5:
change_5 += 1
elif bill == 10 and change_5 > 0:
change_5 -= 1
change_10 += 1
elif bill == 10 and change_5 <= 0:
return False
elif bill == 20 and change_10 > 0 and change_5 > 0:
change_10 -= 1
change_5 -= 1
elif bill == 20 and change_5 >= 3:
change_5 -= 3
else:
return False
return True
4.7.890 - 2025-08-01 09:40:56 +0300 MSK
Links
Code
class Solution:
def isRectangleOverlap(self, rec1: List[int], rec2: List[int]) -> bool:
def intersect(p_left: int, p_right: int, q_left: int, q_right: int) -> bool:
return min(p_right, q_right) > max(p_left, q_left)
return (
intersect(rec1[0], rec1[2], rec2[0], rec2[2]) # width > 0
and intersect(rec1[1], rec1[3], rec2[1], rec2[3]) # height > 0
)
4.7.891 - 2025-08-01 08:25:54 +0300 MSK
Links
Code
class Solution:
def flipAndInvertImage(self, image: List[List[int]]) -> List[List[int]]:
for row in image:
row.reverse()
for i in range(len(row)):
row[i] ^= 1
return image
4.7.892 - 2025-08-01 08:21:20 +0300 MSK
Links
Code
class Solution:
def flipAndInvertImage(self, image: List[List[int]]) -> List[List[int]]:
for row in image:
row.reverse()
for i in range(len(row)):
if row[i] == 0:
row[i] = 1
else:
row[i] = 0
return image
4.7.893 - 2025-08-01 08:13:47 +0300 MSK
Links
Code
class Solution:
def largeGroupPositions(self, s: str) -> List[List[int]]:
res = []
start = 0
prev = s[0]
for i, char in enumerate(itertools.chain(s[1:], " "), 1):
if char == prev:
continue
if i - 1 - start >= 2:
res.append((start, i - 1))
start = i
prev = char
return res
4.7.894 - 2025-08-01 07:59:37 +0300 MSK
Links
Code
class Solution:
def toGoatLatin(self, sentence: str) -> str:
cur_word = []
res = []
i = 0
for char in itertools.chain(sentence, " "):
if char != " ":
cur_word.append(char)
continue
if not cur_word:
continue
i += 1
if cur_word[0].lower() in ("a", "e", "i", "o", "u"):
cur_word.append("ma")
else:
cur_word.append(cur_word[0])
cur_word.append("ma")
cur_word[0] = ""
cur_word.append("a" * i)
res.append("".join(cur_word))
cur_word.clear()
return " ".join(res)
4.7.895 - 2025-08-01 07:51:03 +0300 MSK
Links
Code
class Solution:
def shortestToChar(self, s: str, c: str) -> List[int]:
indexes = []
for i, char in enumerate(s):
if char == c:
indexes.append(i)
length = len(indexes)
res = []
i = 0
max_diff = float("inf")
for j, char in enumerate(s):
diff1 = abs(indexes[i] - j)
if i + 1 >= length:
diff2 = max_diff
else:
diff2 = abs(indexes[i + 1] - j)
if diff1 <= diff2:
res.append(diff1)
else:
res.append(diff2)
i += 1
return res
4.7.896 - 2025-08-01 07:33:33 +0300 MSK
Links
Code
class Solution:
def mostCommonWord(self, paragraph: str, banned: List[str]) -> str:
freqs = defaultdict(int)
banned_set = set(banned)
cur_word = []
for char in itertools.chain(paragraph, "."):
if char.isalpha():
cur_word.append(char.lower())
continue
if not cur_word:
continue
word = "".join(cur_word)
if word not in banned_set:
freqs[word] += 1
cur_word.clear()
most_freq = ""
most_freq_freq = 0
for word, freq in freqs.items():
if freq > most_freq_freq:
most_freq, most_freq_freq = word, freq
return most_freq
4.7.897 - 2025-08-01 07:15:40 +0300 MSK
Links
Code
class Solution:
def generate(self, numRows: int) -> List[List[int]]:
res = [(1, )]
cur_row = []
for row in range(1, numRows):
cur_row.append(1)
prev_row = res[-1]
for i in range(1, row):
cur_row.append(prev_row[i] + prev_row[i - 1])
cur_row.append(1)
res.append(tuple(cur_row))
cur_row.clear()
return res
4.7.898 - 2025-07-31 21:28:35 +0300 MSK
Links
Code
class Solution:
def largestTriangleArea(self, points: list[int]) -> float:
def area(p: tuple[int, int], q: tuple[int, int], r: tuple[int, int]) -> float:
return 0.5 * abs(
(p[0] * q[1])
+ (q[0] * r[1])
+ (r[0] * p[1])
- (p[1] * q[0])
- (q[1] * r[0])
- (r[1] * p[0])
)
res = max(
area(p, q, r)
for p, q, r in itertools.combinations(points, 3)
)
return res
4.7.899 - 2025-07-31 18:46:45 +0300 MSK
Links
Code
class Solution:
def numberOfLines(self, widths: List[int], s: str) -> List[int]:
line_count = 1
line_width = 0
for char in s:
char_width = widths[ord(char) - 97]
line_width += char_width
if line_width > 100:
line_width = char_width
line_count += 1
return line_count, line_width
4.7.900 - 2025-07-31 18:31:00 +0300 MSK
Links
Code
MORSE = (".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--..")
class Solution:
def uniqueMorseRepresentations(self, words: List[str]) -> int:
enc = set()
for word in words:
enc.add("".join(MORSE[ord(char) - 97] for char in word))
return len(enc)
4.7.901 - 2025-07-31 18:29:59 +0300 MSK
Links
Code
class Solution:
def uniqueMorseRepresentations(self, words: List[str]) -> int:
morse = [".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--.."]
enc = set()
cur_morse = []
for word in words:
cur_morse.clear()
for char in word:
cur_morse.append(morse[ord(char) - 97])
enc.add("".join(cur_morse))
return len(enc)
4.7.902 - 2025-07-31 18:14:30 +0300 MSK
Links
Code
class Solution:
def rotateString(self, s: str, goal: str) -> bool:
if len(s) != len(goal):
return False
return goal in "".join((s, s))
4.7.903 - 2025-07-31 17:53:16 +0300 MSK
Links
Code
class Solution:
def minDiffInBST(self, root: TreeNode) -> int:
self.ans = float('inf')
self.pred = None
self.inorder(root)
return self.ans
def inorder(self, root: TreeNode) -> None:
if root is None:
return
self.inorder(root.left)
if self.pred is not None:
self.ans = min(self.ans, root.val - self.pred)
self.pred = root.val
self.inorder(root.right)
4.7.904 - 2025-07-31 17:18:00 +0300 MSK
Links
Code
class Solution:
def numJewelsInStones(self, jewels: str, stones: str) -> int:
jewels_set = set(jewels)
count = 0
for char in stones:
if char in jewels:
count += 1
return count
4.7.905 - 2025-07-31 17:16:38 +0300 MSK
Links
Code
class Solution:
def isToeplitzMatrix(self, matrix: List[List[int]]) -> bool:
for i in range(1, len(matrix)):
for j in range(1, len(matrix[0])):
if matrix[i-1][j-1] != matrix[i][j]:
return False
return True
4.7.906 - 2025-07-31 17:05:37 +0300 MSK
Links
Code
class Solution:
def shortestCompletingWord(self, licensePlate: str, words: List[str]) -> str:
freq = defaultdict(int)
for char in licensePlate:
if char == " " or char.isnumeric():
continue
freq[char.lower()] += 1
cur_freq = {}
shortest = None
for word in words:
cur_freq.clear()
cur_freq.update(freq)
for char in word:
if not cur_freq:
break
if char not in cur_freq:
continue
new_freq = cur_freq[char] - 1
if new_freq <= 0:
cur_freq.pop(char)
else:
cur_freq[char] = new_freq
if not cur_freq and (shortest is None or len(word) < len(shortest)):
shortest = word
return shortest
4.7.907 - 2025-07-31 14:35:36 +0300 MSK
Links
Code
class Solution:
def dominantIndex(self, nums: List[int]) -> int:
largest1, largest2 = -1, -1
largest_i = -1
for i, num in enumerate(nums):
if num == largest2 or num == largest1:
continue
if num > largest2:
largest1 = largest2
largest2 = num
largest_i = i
elif num > largest1:
largest1 = num
if largest1 * 2 <= largest2:
return largest_i
return -1
4.7.908 - 2025-07-31 13:54:58 +0300 MSK
Links
Code
class Solution:
def floodFill(self, image: List[List[int]], sr: int, sc: int, color: int) -> List[List[int]]:
target_color = image[sr][sc]
if target_color == color:
return image
length_row = len(image)
length_col = len(image[0])
dirs = ((1, 0), (-1, 0), (0, 1), (0, -1))
queue = [(sr, sc)]
while queue:
row, col = queue.pop()
if row < 0 or row >= length_row:
continue
if col < 0 or col >= length_col:
continue
if image[row][col] != target_color:
continue
image[row][col] = color
for row_delta, col_delta in dirs:
queue.append((row + row_delta, col + col_delta))
return image
4.7.909 - 2025-07-31 13:46:42 +0300 MSK
Links
Code
class Solution:
def floodFill(self, image: List[List[int]], sr: int, sc: int, color: int) -> List[List[int]]:
target_color = image[sr][sc]
enc = set()
length_row = len(image)
length_col = len(image[0])
dirs = ((1, 0), (-1, 0), (0, 1), (0, -1))
queue = [(sr, sc)]
while queue:
row, col = queue.pop()
if row < 0 or row >= length_row:
continue
if col < 0 or col >= length_col:
continue
if (row, col) in enc:
continue
if image[row][col] != target_color:
continue
image[row][col] = color
enc.add((row, col))
for row_delta, col_delta in dirs:
queue.append((row + row_delta, col + col_delta))
return image
4.7.910 - 2025-07-31 13:03:46 +0300 MSK
Links
Code
class Solution:
def selfDividingNumbers(self, left: int, right: int) -> List[int]:
def self_dividing(num: int) -> bool:
if num == 0:
return False
cur_num = num
while cur_num > 0:
mod = cur_num % 10
cur_num //= 10
if mod == 0 or num % mod > 0:
return False
return True
ans = []
for n in range(left, right + 1):
if self_dividing(n):
ans.append(n)
return ans
4.7.911 - 2025-07-31 11:07:49 +0300 MSK
Links
Code
class Solution:
def findShortestSubArray(self, nums: List[int]) -> int:
left, right, freq = defaultdict(int), defaultdict(int), defaultdict(int)
max_freq = 0
for i, num in enumerate(nums):
if num not in left:
left[num] = i
right[num] = i
freq[num] += 1
max_freq = max(max_freq, freq[num])
min_length = len(nums)
for num, num_freq in freq.items():
if num_freq != max_freq:
continue
min_length = min(min_length, right[num] - left[num] + 1)
return min_length
4.7.912 - 2025-07-31 11:00:20 +0300 MSK
Links
Code
class Solution:
def countBinarySubstrings(self, s: str) -> int:
groups = [1]
for i in range(1, len(s)):
if s[i-1] != s[i]:
groups.append(1)
else:
groups[-1] += 1
ans = 0
for i in range(1, len(groups)):
ans += min(groups[i-1], groups[i])
return ans
4.7.913 - 2025-07-31 10:28:31 +0300 MSK
Links
Code
class Solution:
def calPoints(self, operations: List[str]) -> int:
stack = []
stack_sum = 0
for op in operations:
if op.isnumeric() or op.startswith("-"):
new_score = int(op)
stack.append(new_score)
stack_sum += new_score
elif op == "+":
new_score = stack[-1] + stack[-2]
stack_sum += new_score
stack.append(new_score)
elif op == "D":
new_score = stack[-1] * 2
stack_sum += new_score
stack.append(new_score)
elif op == "C":
stack_sum -= stack[-1]
stack.pop()
else:
raise Exception(op)
return stack_sum
4.7.914 - 2025-07-31 10:04:49 +0300 MSK
Links
Code
class Solution:
def subarrayBitwiseORs(self, arr: List[int]) -> int:
ors = set()
cur = {0}
for num in arr:
cur = {num | cur_num for cur_num in cur} | {num}
ors |= cur
return len(ors)
4.7.915 - 2025-07-30 22:05:38 +0300 MSK
Links
Code
class Solution:
def validPalindrome(self, s: str) -> bool:
def check(i: int, j: int) -> bool:
while i < j:
if s[i] != s[j]:
return False
i, j = i + 1, j - 1
return True
i, j = 0, len(s) - 1
while i < j:
if s[i] != s[j]:
return check(i + 1, j) or check(i, j - 1)
i, j = i + 1, j - 1
return True
4.7.916 - 2025-07-30 22:00:12 +0300 MSK
Links
Code
class Solution:
def findLengthOfLCIS(self, nums: List[int]) -> int:
prev = nums[0]
length = 1
max_length = 1
for num in nums[1:]:
if num > prev:
length += 1
else:
max_length = max(length, max_length)
length = 1
prev = num
return max(length, max_length)
4.7.917 - 2025-07-30 21:55:12 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def findSecondMinimumValue(self, root):
self.ans = float('inf')
min1 = root.val
def dfs(node):
if node:
if min1 < node.val < self.ans:
self.ans = node.val
elif node.val == min1:
dfs(node.left)
dfs(node.right)
dfs(root)
return self.ans if self.ans < float('inf') else -1
4.7.918 - 2025-07-30 21:02:37 +0300 MSK
Links
Code
class Solution:
def judgeCircle(self, moves: str) -> bool:
row, col = 0, 0
coords = {
"R": (0, 1),
"L": (0, -1),
"U": (1, 0),
"D": (-1, 0)
}
for move in moves:
row_delta, col_delta = coords[move]
row += row_delta
col += col_delta
return row == 0 and col == 0
4.7.919 - 2025-07-30 20:59:49 +0300 MSK
Links
Code
class Solution:
def maximumProduct(self, nums: List[int]) -> int:
nums.sort()
pos_res = nums[-1] * nums[-2] * nums[-3]
if nums[0] >= 0:
return pos_res
neg_res = nums[0] * nums[1] * nums[-1]
return max(pos_res, neg_res)
4.7.920 - 2025-07-30 20:52:44 +0300 MSK
Links
Code
UPDATE
Salary
SET
sex = (
CASE
WHEN
sex = 'f'
THEN
'm'
ELSE
'f'
END
);
4.7.921 - 2025-07-30 20:47:51 +0300 MSK
Links
Code
SELECT
id, movie, description, rating
FROM
Cinema
WHERE
description != 'boring'
AND id % 2 != 0
ORDER BY
rating DESC;
4.7.922 - 2025-07-30 20:42:31 +0300 MSK
Links
Code
WITH nums AS (
SELECT
num
FROM
MyNumbers
GROUP BY
num
HAVING
COUNT(num) = 1
)
SELECT
MAX(num) AS num
FROM
nums;
4.7.923 - 2025-07-30 20:35:12 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def mergeTrees(self, root1: Optional[TreeNode], root2: Optional[TreeNode]) -> Optional[TreeNode]:
if root1 is None:
return root2
if root2 is None:
return root1
queue = [(root1, root2)]
while queue:
node1, node2 = queue.pop()
if node1 is None or node2 is None:
continue
node1.val += node2.val
if node1.left is None:
node1.left = node2.left
else:
queue.append((node1.left, node2.left))
if node1.right is None:
node1.right = node2.right
else:
queue.append((node1.right, node2.right))
return root1
4.7.924 - 2025-07-30 20:27:09 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def mergeTrees(self, root1: Optional[TreeNode], root2: Optional[TreeNode]) -> Optional[TreeNode]:
def dfs(node1: Optional[TreeNode], node2: Optional[TreeNode]) -> None:
if node1 is None:
return node2
if node2 is None:
return node1
node1.val += node2.val
node1.left = dfs(node1.left, node2.left)
node1.right = dfs(node1.right, node2.right)
return node1
return dfs(root1, root2)
4.7.925 - 2025-07-30 20:12:39 +0300 MSK
Links
Code
SELECT
x, y, z, (
CASE
WHEN
((x+y+z) - GREATEST(x,y,z)) > GREATEST(x,y,z)
THEN
'Yes'
ELSE
'No'
END
) AS triangle
FROM
Triangle;
4.7.926 - 2025-07-30 20:09:55 +0300 MSK
Links
Code
(
SELECT
x, y, z, 'Yes' AS triangle
FROM
Triangle
WHERE
(x + y > z) AND (y + z > x) AND (z + x > y)
) UNION (
SELECT
x, y, z, 'No' AS triangle
FROM
Triangle
WHERE (x + y <= z) OR (y + z <= x) OR (z + x <= y)
);
4.7.927 - 2025-07-30 20:05:18 +0300 MSK
Links
Code
SELECT
sales_person.name
FROM (
Orders orders
JOIN
Company company
ON
orders.com_id = company.com_id
AND company.name = 'RED'
RIGHT JOIN
SalesPerson sales_person
ON
sales_person.sales_id = orders.sales_id
)
WHERE
orders.sales_id IS NULL;
4.7.928 - 2025-07-30 19:52:43 +0300 MSK
Links
Code
class Solution:
def findRestaurant(self, list1: List[str], list2: List[str]) -> List[str]:
indexes = {}
res = []
if len(list1) > len(list2):
first, second = list2, list1
else:
first, second = list1, list2
for i, string in enumerate(first):
indexes[string] = i
min_sum = float("inf")
res = []
for j, string in enumerate(second):
if string not in indexes:
continue
cur_sum = indexes[string] + j
if cur_sum < min_sum:
res.clear()
res.append(string)
min_sum = cur_sum
elif cur_sum == min_sum:
res.append(string)
return res
4.7.929 - 2025-07-30 19:27:05 +0300 MSK
Links
Code
class Solution:
def maxCount(self, m: int, n: int, ops: List[List[int]]) -> int:
min_row = m
min_col = n
for range_row, range_col in ops:
min_row = min(min_row, range_row)
min_col = min(min_col, range_col)
return min_row * min_col
4.7.930 - 2025-07-30 19:18:29 +0300 MSK
Links
Code
SELECT
class
FROM
Courses
GROUP BY
class
HAVING
COUNT(class) >= 5;
4.7.931 - 2025-07-30 19:14:46 +0300 MSK
Links
Code
SELECT
World.name, World.population, World.area
FROM
World
WHERE
World.area >= 3000000
OR World.population >= 25000000;
4.7.932 - 2025-07-30 19:11:57 +0300 MSK
Links
Code
class Solution:
def findLHS(self, nums):
freq = defaultdict(int)
max_length = 0
for num in nums:
freq[num] += 1
for num in freq:
nxt = num + 1
if nxt not in freq:
continue
cur_length = freq[num] + freq[nxt]
max_length = max(max_length, cur_length)
return max_length
4.7.933 - 2025-07-30 18:59:58 +0300 MSK
Links
Code
"""
# Definition for a Node.
class Node:
def __init__(self, val: Optional[int] = None, children: Optional[List['Node']] = None):
self.val = val
self.children = children
"""
class Solution:
def postorder(self, root: 'Node') -> List[int]:
if root is None:
return []
res = []
queue = [root]
while queue:
node = queue.pop()
res.append(node.val)
for child in node.children:
queue.append(child)
res.reverse()
return res
4.7.934 - 2025-07-30 18:49:52 +0300 MSK
Links
Code
"""
# Definition for a Node.
class Node:
def __init__(self, val: Optional[int] = None, children: Optional[List['Node']] = None):
self.val = val
self.children = children
"""
class Solution:
def postorder(self, root: 'Node') -> List[int]:
res = []
def dfs(node: Node, res: list[int]) -> None:
if node is None:
return
for child in node.children:
dfs(child, res)
res.append(node.val)
dfs(root, res)
return res
4.7.935 - 2025-07-30 18:45:39 +0300 MSK
Links
Code
"""
# Definition for a Node.
class Node:
def __init__(self, val: Optional[int] = None, children: Optional[List['Node']] = None):
self.val = val
self.children = children
"""
class Solution:
def preorder(self, root: 'Node') -> List[int]:
if root is None:
return []
res = []
queue = [root]
while queue:
node = queue.pop()
res.append(node.val)
queue.extend(reversed(node.children))
return res
4.7.936 - 2025-07-30 18:44:00 +0300 MSK
Links
Code
"""
# Definition for a Node.
class Node:
def __init__(self, val: Optional[int] = None, children: Optional[List['Node']] = None):
self.val = val
self.children = children
"""
class Solution:
def preorder(self, root: 'Node') -> List[int]:
if root is None:
return []
res = []
queue = deque((root, ))
while queue:
node = queue.popleft()
res.append(node.val)
queue.extendleft(reversed(node.children))
return res
4.7.937 - 2025-07-30 18:35:45 +0300 MSK
Links
Code
"""
# Definition for a Node.
class Node:
def __init__(self, val: Optional[int] = None, children: Optional[List['Node']] = None):
self.val = val
self.children = children
"""
class Solution:
def preorder(self, root: 'Node') -> List[int]:
res = []
def dfs(node: Optional[Node], res: list[int]) -> None:
if node is None:
return
res.append(node.val)
for child in node.children:
dfs(child, res)
dfs(root, res)
return res
4.7.938 - 2025-07-30 18:32:15 +0300 MSK
Links
Code
SELECT
Orders.customer_number
FROM
Orders
GROUP BY
Orders.customer_number
ORDER BY
COUNT(Orders.customer_number) DESC
LIMIT
1;
4.7.939 - 2025-07-30 18:31:28 +0300 MSK
Links
Code
SELECT
Orders.customer_number
FROM
Orders
GROUP BY
Orders.customer_number
ORDER BY
COUNT(*) DESC
LIMIT
1;
4.7.940 - 2025-07-30 18:25:43 +0300 MSK
Links
Code
SELECT
Customer.name
FROM
Customer
WHERE
Customer.referee_id != 2
OR Customer.referee_id IS NULL
4.7.941 - 2025-07-30 18:19:10 +0300 MSK
Links
Code
SELECT
Employee.name, Bonus.bonus
FROM
Employee
LEFT JOIN
Bonus
ON
Employee.empId = Bonus.empId
WHERE
Bonus.bonus IS NULL
OR Bonus.bonus < 1000
4.7.942 - 2025-07-30 18:07:19 +0300 MSK
Links
Code
class Solution:
def distributeCandies(self, candyType: List[int]) -> int:
types = set()
max_length = len(candyType) // 2
for candy in candyType:
types.add(candy)
if len(types) >= max_length:
return max_length
return len(types)
4.7.943 - 2025-07-30 17:54:50 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def isSubtree(self, root: Optional[TreeNode], subRoot: Optional[TreeNode]) -> bool:
def dfs(node: Optional[TreeNode], sub_node: Optional[TreeNode]) -> bool:
if not node and not sub_node:
return True
if not node or not sub_node:
return False
if node.val != sub_node.val:
return False
return dfs(node.left, sub_node.left) and dfs(node.right, sub_node.right)
def dfs2(node: Optional[TreeNode], sub_node: Optional[TreeNode]) -> bool:
if dfs(node, sub_node):
return True
if not node or not sub_node:
return False
return dfs2(node.left, sub_node) or dfs2(node.right, sub_node)
return dfs2(root, subRoot)
4.7.944 - 2025-07-30 17:36:45 +0300 MSK
Links
Code
class Solution:
def matrixReshape(self, mat: List[List[int]], r: int, c: int) -> List[List[int]]:
if len(mat) * len(mat[0]) != r * c:
return mat
new_mat = [[None] * c for _ in range(r)]
new_row = 0
new_col = 0
for row in mat:
for col in row:
if new_col == c:
new_col = 0
new_row += 1
new_mat[new_row][new_col] = col
new_col += 1
return new_mat
4.7.945 - 2025-07-30 16:27:11 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def findTilt(self, root: Optional[TreeNode]) -> int:
def dfs(node: Optional[TreeNode]) -> tuple[int, int]:
if node is None:
return 0, 0
left_sum, left_tilt = dfs(node.left)
right_sum, right_tilt = dfs(node.right)
tilt_sum = left_tilt + right_tilt + abs(left_sum - right_sum)
node_sum = node.val + left_sum + right_sum
return node_sum, tilt_sum
_, tilt_sum = dfs(root)
return tilt_sum
4.7.946 - 2025-07-30 16:07:35 +0300 MSK
Links
Code
class Solution:
def arrayPairSum(self, nums: List[int]) -> int:
nums.sort()
length = len(nums)
i = 0
sum = 0
while i < length:
sum += nums[i]
i += 2
return sum
4.7.947 - 2025-07-30 16:04:16 +0300 MSK
Links
Code
"""
# Definition for a Node.
class Node:
def __init__(self, val: Optional[int] = None, children: Optional[List['Node']] = None):
self.val = val
self.children = children
"""
class Solution:
def maxDepth(self, root: 'Node') -> int:
if root is None:
return 0
queue: deque[tuple[Node, int]] = deque(((root, 1),))
max_depth = 0
while queue:
node, depth = queue.popleft()
max_depth = depth
for child in node.children:
queue.append((child, 1 + depth))
return max_depth
4.7.948 - 2025-07-30 15:53:02 +0300 MSK
Links
Code
"""
# Definition for a Node.
class Node:
def __init__(self, val: Optional[int] = None, children: Optional[List['Node']] = None):
self.val = val
self.children = children
"""
class Solution:
def maxDepth(self, root: 'Node') -> int:
def dfs(node: Node) -> int:
if not node:
return 0
if not node.children:
return 1
return 1 + max(dfs(child) for child in node.children)
return dfs(root)
4.7.949 - 2025-07-30 15:50:06 +0300 MSK
Links
Code
class Solution:
def checkRecord(self, s: str) -> bool:
a_count = 0
l_count = 0
for char in s:
if char == "P":
l_count = 0
elif char == "A":
a_count += 1
l_count = 0
elif char == "L":
l_count += 1
if l_count >= 3 or a_count >= 2:
return False
return True
4.7.950 - 2025-07-30 15:40:51 +0300 MSK
Links
Code
class Solution:
def reverseStr(self, s: str, k: int) -> str:
length = len(s)
if length == 1:
return s
if length <= k:
return s[::-1]
res = []
i = 0
while i < length:
new_i = i + 2 * k
res.append(s[i+k-1:i:-1])
res.append(s[i])
res.append(s[i+k:new_i])
i = new_i
return "".join(res)
4.7.951 - 2025-07-30 15:11:27 +0300 MSK
Links
Code
class Solution:
def findLUSlength(self, a: str, b: str) -> int:
if a == b:
return -1
else:
return max(len(a), len(b))
4.7.952 - 2025-07-30 15:08:16 +0300 MSK
Links
Code
class Solution:
def longestSubarray(self, nums: List[int]) -> int:
max_val = ans = current_streak = 0
for num in nums:
if max_val < num:
max_val = num
ans = current_streak = 0
if max_val == num:
current_streak += 1
else:
current_streak = 0
ans = max(ans, current_streak)
return ans
4.7.953 - 2025-07-30 15:06:29 +0300 MSK
Links
Code
class Solution:
def longestSubarray(self, nums: List[int]) -> int:
max_and = max(nums)
max_length = 0
cur_length = 0
for num in nums:
if num == max_and:
cur_length += 1
else:
max_length = max(max_length, cur_length)
cur_length = 0
return max(max_length, cur_length)
4.7.954 - 2025-07-30 14:49:28 +0300 MSK
Links
Code
class Solution:
def detectCapitalUse(self, word: str) -> bool:
length = len(word)
if length == 1:
return True
def is_cap(char: str) -> bool:
res = 65 <= ord(char) <= 90
return res
first_cap, second_cap = is_cap(word[0]), is_cap(word[1])
if first_cap and second_cap:
should_be_cap = True
elif first_cap and not second_cap:
should_be_cap = False
elif not first_cap and second_cap:
return False
elif not first_cap and not second_cap:
should_be_cap = False
else:
raise Exception
for char in word[2:]:
if is_cap(char) != should_be_cap:
return False
return True
4.7.955 - 2025-07-29 21:27:41 +0300 MSK
Links
Code
SELECT
player_id, MIN(event_date) as "first_login"
FROM
Activity
GROUP BY
player_id
4.7.956 - 2025-07-29 21:05:02 +0300 MSK
Links
Code
class Solution:
def checkPerfectNumber(self, num: int) -> bool:
if num == 1:
return False
count = 1
for i in range(2, int(num**0.5) + 1):
if num % i == 0:
count += i + (num // i)
return num == count
4.7.957 - 2025-07-29 20:50:01 +0300 MSK
Links
Code
class Solution:
def convertToBase7(self, num: int) -> str:
if num > -7 and num < 7:
return str(num)
res_arr = []
sign = ""
if num < 0:
sign = "-"
num = -num
while num:
res_arr.append(str(num % 7))
num //= 7
res = sign + "".join(reversed(res_arr))
return res
4.7.958 - 2025-07-29 20:45:22 +0300 MSK
Links
Code
class Solution:
def nextGreaterElement(self, nums1: list[int], nums2: list[int]) -> list[int]:
stack = []
greater = {}
for num in nums2:
while stack and num > stack[-1]:
greater[stack.pop()] = num
stack.append(num)
for num in stack:
greater[num] = -1
return [greater[num] for num in nums1]
4.7.959 - 2025-07-29 19:17:54 +0300 MSK
Links
Code
class Solution:
def findPoisonedDuration(self, timeSeries: List[int], duration: int) -> int:
total = 0
cur_end = -1
for second in timeSeries:
if second > cur_end:
total += duration
else:
total += duration - (cur_end - second) - 1
cur_end = second + duration - 1
return total
4.7.960 - 2025-07-29 18:55:38 +0300 MSK
Links
Code
class Solution:
def hammingDistance(self, x: int, y: int) -> int:
count = 0
while x or y:
if x % 2 != y % 2:
count += 1
x //= 2
y //= 2
return count
4.7.961 - 2025-07-29 18:52:23 +0300 MSK
Links
Code
class Solution:
def countSegments(self, s: str) -> int:
length = len(s)
count = 0
is_segment = False
for char in s:
is_space = char == " "
if not is_segment and not is_space:
is_segment = True
count += 1
elif is_space:
is_segment = False
return count
4.7.962 - 2025-07-29 18:27:23 +0300 MSK
Links
Code
class Solution:
def toHex(self, num: int) -> str:
if num >=0 and num < 10:
return str(num)
if num < 0:
num = (1 << 32) + num
symbols = "0123456789abcdef"
res = []
while num > 0:
mod = num % 16
res.append(symbols[mod])
num //= 16
return "".join(reversed(res))
4.7.963 - 2025-07-29 17:59:54 +0300 MSK
Links
Code
class Solution:
def readBinaryWatch(self, num: int) -> list[str]:
times = []
for h in range(12):
for m in range(60):
hOnes = bin(h).count('1')
mOnes = bin(m).count('1')
if hOnes + mOnes == num:
times.append(f"{h}:{m:02d}")
return times
4.7.964 - 2025-07-29 17:38:44 +0300 MSK
Links
Code
class Solution:
def canWinNim(self, n: int) -> bool:
return n % 4 != 0
4.7.965 - 2025-07-29 17:38:31 +0300 MSK
Links
Code
class Solution:
def canWinNim(self, n: int) -> bool:
if n < 3:
return True
True, True, True, False, True, True, True
1, 2, 3, 4, 5, 6, 7
return n % 4 != 0
4.7.966 - 2025-07-29 16:37:09 +0300 MSK
Links
Code
DELETE FROM
Person
WHERE
id NOT IN (
SELECT MIN(id) FROM Person
GROUP BY email
)
;
4.7.967 - 2025-07-29 16:11:49 +0300 MSK
Links
Code
SELECT
today.id
FROM
Weather today
CROSS JOIN
Weather yesterday
WHERE
(today.recordDate - yesterday.recordDate = 1)
AND today.temperature > yesterday.temperature
4.7.968 - 2025-07-29 13:59:48 +0300 MSK
Links
Code
class Solution:
def smallestSubarrays(self, nums: List[int]) -> List[int]:
n = len(nums)
pos = [-1] * 31
ans = [0] * n
for i in range(n - 1, -1, -1):
j = i
for bit in range(31):
if (nums[i] & (1 << bit)) == 0:
if pos[bit] != -1:
j = max(j, pos[bit])
else:
pos[bit] = i
ans[i] = j - i + 1
return ans
4.7.969 - 2025-07-28 20:06:14 +0300 MSK
Links
Code
SELECT employee.name AS Employee
FROM Employee employee
JOIN Employee manager
ON employee.managerId = manager.id
WHERE employee.salary > manager.salary;
4.7.971 - 2025-07-28 16:53:12 +0300 MSK
Links
Code
awk '
/^[0-9]{3}-[0-9]{3}-[0-9]{4}$/ { print $0 }
/^\([0-9]{3}\) [0-9]{3}-[0-9]{4}$/ { print $0 }
' file.txt
4.7.972 - 2025-07-28 16:52:43 +0300 MSK
Links
Code
cat file.txt | awk '
/^[0-9]{3}-[0-9]{3}-[0-9]{4}$/ { print $0 }
/^\([0-9]{3}\) [0-9]{3}-[0-9]{4}$/ { print $0 }
'
4.7.973 - 2025-07-28 16:45:20 +0300 MSK
Links
Code
SELECT name as "Customers"
FROM Customers
WHERE id NOT IN (
SELECT customerId
FROM Orders
);
4.7.974 - 2025-07-28 16:35:55 +0300 MSK
Links
Code
SELECT email FROM Person
GROUP BY email
HAVING COUNT(email) > 1;
4.7.975 - 2025-07-28 16:25:34 +0300 MSK
Links
Code
class Solution:
def countMaxOrSubsets(self, nums: List[int]) -> int:
max_or_value = 0
n = len(nums)
for num in nums:
max_or_value |= num
memo = [[-1] * (max_or_value + 1) for _ in range(n)]
return self._count_subsets_recursive(nums, 0, 0, max_or_value, memo)
def _count_subsets_recursive(
self,
nums: List[int],
index: int,
current_or: int,
target_or: int,
memo: List[List[int]],
) -> int:
if index == len(nums):
return 1 if current_or == target_or else 0
if memo[index][current_or] != -1:
return memo[index][current_or]
count_without = self._count_subsets_recursive(
nums, index + 1, current_or, target_or, memo
)
count_with = self._count_subsets_recursive(
nums, index + 1, current_or | nums[index], target_or, memo
)
res = count_without + count_with
memo[index][current_or] = res
return res
4.7.976 - 2025-07-27 19:03:38 +0300 MSK
Links
Code
class Solution:
def countHillValley(self, nums: List[int]) -> int:
res = 0
length = len(nums)
for i in range(1, length - 1):
if nums[i] == nums[i - 1]:
continue
left = 0
for j in range(i - 1, -1, -1):
if nums[j] > nums[i]:
left = 1
break
elif nums[j] < nums[i]:
left = -1
break
right = 0
for j in range(i + 1, length):
if nums[j] > nums[i]:
right = 1
break
elif nums[j] < nums[i]:
right = -1
break
if left == right and left != 0:
res += 1
return res
4.7.977 - 2025-07-26 18:50:49 +0300 MSK
Links
Code
class Solution:
def maxSubarrays(self, n: int, conflictingPairs: List[List[int]]) -> int:
bMin1 = [2**31 - 1] * (n + 1)
bMin2 = [2**31 - 1] * (n + 1)
for pair in conflictingPairs:
a = min(pair[0], pair[1])
b = max(pair[0], pair[1])
if bMin1[a] > b:
bMin2[a] = bMin1[a]
bMin1[a] = b
elif bMin2[a] > b:
bMin2[a] = b
res = 0
ib1 = n
b2 = 0x3FFFFFFF
delCount = [0] * (n + 1)
for i in range(n, 0, -1):
if bMin1[ib1] > bMin1[i]:
b2 = min(b2, bMin1[ib1])
ib1 = i
else:
b2 = min(b2, bMin1[i])
res += min(bMin1[ib1], n + 1) - i
delCount[ib1] += min(min(b2, bMin2[ib1]), n + 1) - min(
bMin1[ib1], n + 1
)
return res + max(delCount)
4.7.978 - 2025-07-26 18:48:20 +0300 MSK
Links
Code
class Solution(object):
def isUgly(self, n):
if n <= 0:
return False
while n % 2 == 0:
n //= 2
while n % 3 == 0:
n //= 3
while n % 5 == 0:
n //= 5
return n == 1
4.7.979 - 2025-07-25 13:23:28 +0300 MSK
Links
Code
class Solution(object):
def isOneBitCharacter(self, bits):
i = 0
while i < len(bits) - 1:
i += bits[i] + 1
return i == len(bits) - 1
4.7.980 - 2025-07-25 13:15:13 +0300 MSK
Links
Code
class Solution:
def toLowerCase(self, s: str) -> str:
return s.lower()
4.7.981 - 2025-07-25 13:14:11 +0300 MSK
Links
Code
class KthLargest:
def __init__(self, k: int, nums: List[int]):
if len(nums) < k:
nums.extend((float("-inf"),) * (k - len(nums)))
nums.sort()
self._nums: list[int] = nums[-k:]
self._k: int = k
def add(self, val: int) -> int:
if val > self._nums[0]:
self._nums[0] = val
self._nums.sort()
return self._nums[-self._k]
# Your KthLargest object will be instantiated and called as such:
# obj = KthLargest(k, nums)
# param_1 = obj.add(val)
4.7.982 - 2025-07-25 12:37:39 +0300 MSK
Links
Code
class Solution:
def busyStudent(self, startTime: List[int], endTime: List[int], queryTime: int) -> int:
count = 0
for start, end in zip(startTime, endTime):
if queryTime >= start and queryTime <= end:
count += 1
return count
4.7.983 - 2025-07-25 12:29:53 +0300 MSK
Links
Code
class Solution:
def countNegatives(self, grid: List[List[int]]) -> int:
count = 0
for i, row in enumerate(grid):
for j, num in enumerate(row):
if num < 0:
count += len(row) - j
break
return count
4.7.984 - 2025-07-25 12:18:12 +0300 MSK
Links
Code
SELECT firstName, lastName, city, state
FROM Person LEFT JOIN Address
ON Person.personId = Address.personId
4.7.985 - 2025-07-25 12:07:53 +0300 MSK
Links
Code
class Solution:
def makeFancyString(self, s: str) -> str:
length = len(s)
if length < 3:
return s
prev_char, prev_char_count = "", 0
res = []
for char in s:
if char != prev_char:
prev_char = char
prev_char_count = 1
res.append(char)
elif prev_char_count < 2:
prev_char_count += 1
res.append(char)
return "".join(res)
4.7.986 - 2025-07-25 11:57:05 +0300 MSK
Links
Code
class Solution:
def maximumUniqueSubarray(self, nums: List[int]) -> int:
sub: deque[int] = deque()
sub_nums: set[int] = set()
cur_sum: int = 0
max_sum: int = 0
for num in nums:
while num in sub_nums:
sub_num = sub.popleft()
sub_nums.remove(sub_num)
cur_sum -= sub_num
sub.append(num)
sub_nums.add(num)
cur_sum += num
max_sum = max(cur_sum, max_sum)
return max_sum
4.7.987 - 2025-07-25 09:50:01 +0300 MSK
Links
Code
class Solution:
def maxSum(self, nums: List[int]) -> int:
if len(nums) == 1:
return nums[0]
nums.sort()
if nums[-1] <= 0:
return nums[-1]
res = 0
if nums[0] > 0:
res = nums[0]
for i, num in enumerate(nums[1:], 1):
if num <= 0 or num == nums[i - 1]:
continue
res += num
return res
4.7.988 - 2025-07-24 18:52:24 +0300 MSK
Links
Code
class Solution:
def maximumGain(self, s: str, x: int, y: int) -> int:
total_score = 0
high_priority_pair = "ab" if x > y else "ba"
low_priority_pair = "ba" if high_priority_pair == "ab" else "ab"
# First pass: remove high priority pair
string_after_first_pass = self.remove_substring(s, high_priority_pair)
removed_pairs_count = (len(s) - len(string_after_first_pass)) // 2
# Calculate score from first pass
total_score += removed_pairs_count * max(x, y)
# Second pass: remove low priority pair
string_after_second_pass = self.remove_substring(
string_after_first_pass, low_priority_pair
)
removed_pairs_count = (
len(string_after_first_pass) - len(string_after_second_pass)
) // 2
# Calculate score from second pass
total_score += removed_pairs_count * min(x, y)
return total_score
def remove_substring(self, input: str, target_pair: str) -> str:
char_stack = []
# Iterate through each character in the input string
for current_char in input:
# Check if current character forms the target pair with the top of the stack
if (
current_char == target_pair[1]
and char_stack
and char_stack[-1] == target_pair[0]
):
char_stack.pop() # Remove the matching character from the stack
else:
char_stack.append(current_char)
# Reconstruct the remaining string after removing target pairs
return "".join(char_stack)
4.7.989 - 2025-07-24 17:40:53 +0300 MSK
Links
Code
class Solution:
def calc(self, part1: int, part2: int, part3: int) -> int:
return max(part1, part2, part3) - min(part1, part2, part3)
def minimumScore(self, nums: List[int], edges: List[List[int]]) -> int:
length = len(nums)
parent_to_child: list[int] = [[] for _ in range(length)]
for node_1, node_2 in edges:
parent_to_child[node_1].append(node_2)
parent_to_child[node_2].append(node_1)
total = 0
for num in nums:
total ^= num
res = float("inf")
def dfs2(node: int, parent: int, oth: int, anc: int) -> int:
son = nums[node]
for child in parent_to_child[node]:
if child == parent:
continue
son ^= dfs2(child, node, oth, anc)
if parent == anc:
return son
nonlocal res
res = min(res, self.calc(oth, son, total ^ oth ^ son))
return son
def dfs(node: int, parent: int) -> int:
son = nums[node]
for child in parent_to_child[node]:
if child == parent:
continue
son ^= dfs(child, node)
for child in parent_to_child[node]:
if child == parent:
dfs2(child, node, son, node)
return son
dfs(0, -1)
return res
4.7.990 - 2025-07-20 16:53:28 +0300 MSK
Links
Code
class Trie:
serial: str = ""
children: dict[str, "Trie"]
def __init__(self) -> None:
self.children = dict()
class Solution:
def deleteDuplicateFolder(self, paths: List[List[str]]) -> List[List[str]]:
root = Trie()
freq = Counter()
for path in paths:
cur = root
for node in path:
if node not in cur.children:
cur.children[node] = Trie()
cur = cur.children[node]
def construct(node: Trie) -> None:
if not node.children:
return
serial: list[str] = []
for folder, child in node.children.items():
construct(child)
serial.append(f"{folder}({child.serial})")
serial.sort()
node.serial = "".join(serial)
freq[node.serial] += 1
construct(root)
ans = list()
path = list()
def operate(node: Trie) -> None:
if freq[node.serial] > 1:
return
if path:
ans.append(path[:])
for folder, child in node.children.items():
path.append(folder)
operate(child)
path.pop()
operate(root)
return ans
4.7.991 - 2025-04-15 16:14:06 +0300 MSK
Links
Code
from sortedcontainers import SortedList
from typing import List
class Solution:
def goodTriplets(self, nums1: List[int], nums2: List[int]) -> int:
index_map = {num: i for i, num in enumerate(nums2)}
indices = [index_map[num] for num in nums1]
left_counts = []
left_sorted = SortedList()
for idx in indices:
left_counts.append(left_sorted.bisect_left(idx))
left_sorted.add(idx)
right_counts = []
right_sorted = SortedList()
for idx in reversed(indices):
right_counts.append(len(right_sorted) - right_sorted.bisect_right(idx))
right_sorted.add(idx)
right_counts.reverse()
return sum(left * right for left, right in zip(left_counts, right_counts))
4.7.992 - 2025-04-14 19:45:07 +0300 MSK
Links
Code
class Solution:
def countGoodTriplets(self, arr: List[int], a: int, b: int, c: int) -> int:
ans = 0
n = len(arr)
total = [0] * 1001
for j in range(n):
for k in range(j + 1, n):
if abs(arr[j] - arr[k]) <= b:
lj, rj = arr[j] - a, arr[j] + a
lk, rk = arr[k] - c, arr[k] + c
l = max(0, lj, lk)
r = min(1000, rj, rk)
if l <= r:
ans += total[r] if l == 0 else total[r] - total[l - 1]
for k in range(arr[j], 1001):
total[k] += 1
return ans
4.7.993 - 2025-04-13 17:10:23 +0300 MSK
Links
Code
class Solution:
def countGoodNumbers(self, n: int) -> int:
mod = 10**9 + 7
# use fast exponentiation to calculate x^y % mod
def quickmul(x: int, y: int) -> int:
ret, mul = 1, x
while y > 0:
if y % 2 == 1:
ret = ret * mul % mod
mul = mul * mul % mod
y //= 2
return ret
return quickmul(5, (n + 1) // 2) * quickmul(4, n // 2) % mod
4.7.994 - 2025-04-12 19:10:13 +0300 MSK
Links
Code
class Solution(object):
def __init__(self):
self.res = 0
self.visited = set()
def vectorToNumber(self, digits):
return int(''.join(map(str, digits)))
def totalPermutations(self, freqMap, total):
res = factorial(total)
for count in freqMap.values():
res //= factorial(count)
return res
def permsWithZero(self, freqMap, total):
if freqMap.get(0, 0) == 0:
return 0
freqMap[0] -= 1
res = factorial(total - 1)
for count in freqMap.values():
res //= factorial(count)
return res
def genPal(self, palin, left, right, divisor, total):
if left > right:
palinVal = self.vectorToNumber(palin)
if palinVal % divisor == 0:
freq = Counter(palin)
key = tuple(sorted(freq.items()))
if key not in self.visited:
self.res += self.totalPermutations(freq, total) - self.permsWithZero(freq.copy(), total)
self.visited.add(key)
return
for dig in range(1 if left == 0 else 0, 10):
palin[left] = palin[right] = dig
self.genPal(palin, left + 1, right - 1, divisor, total)
def countGoodIntegers(self, n, k):
self.res = 0
self.visited.clear()
self.genPal([0] * n, 0, n - 1, k, n)
return self.res
4.7.995 - 2025-04-11 20:06:54 +0300 MSK
Links
Code
class Solution:
def countSymmetricIntegers(self, low: int, high: int) -> int:
count = 0
for num in range(low, high + 1):
s = str(num)
if len(s) % 2 == 0:
mid = len(s) // 2
if sum(map(int, s[:mid])) == sum(map(int, s[mid:])):
count += 1
return count
4.7.996 - 2025-04-10 19:50:16 +0300 MSK
Links
Code
class Solution:
def numberOfPowerfulInt(self, start: int, finish: int, limit: int, suffix: str) -> int:
def count_powerful_up_to(num: int) -> int:
num_str = str(num)
suffix_len = len(suffix)
prefix_len = len(num_str) - suffix_len
if prefix_len < 0:
return 0
dp = [[0] * 2 for _ in range(prefix_len + 1)]
dp[prefix_len][0] = 1
suffix_from_num = num_str[prefix_len:]
dp[prefix_len][1] = int(suffix_from_num) >= int(suffix)
for i in range(prefix_len - 1, -1, -1):
digit = int(num_str[i])
dp[i][0] = (limit + 1) * dp[i + 1][0]
if digit <= limit:
dp[i][1] = digit * dp[i + 1][0] + dp[i + 1][1]
else:
dp[i][1] = (limit + 1) * dp[i + 1][0]
return dp[0][1]
return count_powerful_up_to(finish) - count_powerful_up_to(start - 1)
4.7.997 - 2025-04-09 19:33:13 +0300 MSK
Links
Code
class Solution:
def minOperations(self, nums: List[int], k: int) -> int:
if not nums:
return -1
nums.sort(reverse=True)
if nums[-1] < k:
return -1
prev = nums[0]
if prev == k:
return 0
ops = 0
for num in nums[1:]:
if num == prev:
continue
ops += 1
prev = num
if num == k:
return ops
return ops + 1
4.7.998 - 2024-06-28 19:53:30 +0300 MSK
Links
Code
class Solution:
def maximumImportance(self, n: int, roads: List[List[int]]) -> int:
res = 0
cost = 1
conn = [0] * n
for road in roads:
conn[road[0]] += 1
conn[road[1]] += 1
conn.sort()
for con in conn:
res += con * cost
cost += 1
return res
4.7.999 - 2024-06-26 18:39:14 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def balanceBST(self, root: TreeNode) -> TreeNode:
self.sortedArr = []
self.inorderTraverse(root)
return self.sortedArrayToBST(0, len(self.sortedArr) - 1)
def inorderTraverse(self, root: TreeNode) -> None:
if not root:
return
self.inorderTraverse(root.left)
self.sortedArr.append(root)
self.inorderTraverse(root.right)
def sortedArrayToBST(self, start: int, end: int) -> TreeNode:
if start > end:
return None
mid = (start + end) // 2
root = self.sortedArr[mid]
root.left = self.sortedArrayToBST(start, mid - 1)
root.right = self.sortedArrayToBST(mid + 1, end)
return root
4.7.1000 - 2024-06-25 20:07:01 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def bstToGst(self, root: TreeNode) -> TreeNode:
self.val = 0
def dfs(node):
if not node:
return
dfs(node.right)
self.val += node.val
node.val = self.val
dfs(node.left)
dfs(root)
return root
4.7.1001 - 2024-06-24 15:55:17 +0300 MSK
Links
Code
class Solution:
def minKBitFlips(self, A: List[int], K: int) -> int:
n, flipped, res = len(A), 0, 0
fp = [0] * n
for i in range(n):
if i >= K:
flipped ^= fp[i - K]
if flipped == A[i]:
if i + K > n:
return -1
fp[i] = 1
flipped ^= 1
res += 1
return res
4.7.1002 - 2024-06-23 14:38:18 +0300 MSK
Links
Code
class Solution:
def longestSubarray(self, nums: List[int], limit: int) -> int:
decQ = collections.deque()
incQ = collections.deque()
ans = 0
left = 0
for right, num in enumerate(nums):
while decQ and num > decQ[-1]:
decQ.pop()
decQ.append(num)
while incQ and num < incQ[-1]:
incQ.pop()
incQ.append(num)
while decQ[0] - incQ[0] > limit:
if decQ[0] == nums[left]:
decQ.popleft()
if incQ[0] == nums[left]:
incQ.popleft()
left += 1
ans = max(ans, right - left + 1)
return ans
4.7.1003 - 2024-06-22 16:33:20 +0300 MSK
Links
Code
class Solution:
def numberOfSubarrays(self, nums: List[int], k: int) -> int:
for i in range(len(nums)):
nums[i] %= 2
prefix_count = [0] * (len(nums) + 1)
prefix_count[0] = 1
s = 0
ans = 0
for num in nums:
s += num
if s >= k:
ans += prefix_count[s - k]
prefix_count[s] += 1
return ans
4.7.1004 - 2024-06-21 19:21:07 +0300 MSK
Links
Code
class Solution:
def maxSatisfied(self, customers: List[int], grumpy: List[int], minutes: int) -> int:
ans = 0
total = sum((1 - grumpy[i]) * customers[i] for i in range(len(customers)))
window_all = 0
window_partial = 0
for i in range(len(customers)):
window_all += customers[i]
window_partial += (1 - grumpy[i]) * customers[i]
if i + 1 >= minutes:
ans = max(ans, total - window_partial + window_all)
left = i - minutes + 1
window_all -= customers[left]
window_partial -= (1 - grumpy[left]) * customers[left]
return ans
4.7.1005 - 2024-06-19 19:59:31 +0300 MSK
Links
Code
class Solution:
def minDays(self, bloomDay: List[int], m: int, k: int) -> int:
n=len(bloomDay)
if m*k>n: return -1
def f(d):
len, bouquet=0, 0
i=0
while i<n:
while i<n and bloomDay[i]<=d:
len+=1
if len==k:
bouquet+=1
len=0
i+=1
if i<n and bloomDay[i]>d: len=0
if bouquet>m: return True
i+=1
return bouquet>=m
l, r = min(bloomDay), max(bloomDay)
while l < r:
mid = l + (r - l) // 2
if f(mid):
r = mid
else:
l = mid + 1
return l
4.7.1006 - 2024-06-17 15:39:57 +0300 MSK
Links
Code
from math import sqrt
class Solution:
def judgeSquareSum(self, c: int) -> bool:
for a in range(int(sqrt(c)) + 1): # Iterate through all possible values of `a`
b = sqrt(c - a * a) # Compute `b` as the square root of `c - a^2`
if b == int(b): # Check if `b` is an integer
return True # If `b` is an integer, return true
return False # If no such pair `(a, b)` is found, return false
4.7.1007 - 2024-06-15 13:32:54 +0300 MSK
Links
Code
class Solution:
def findMaximizedCapital(
self, k: int, w: int, profits: List[int], capital: List[int]
) -> int:
n = len(profits)
projects = [(capital[i], profits[i]) for i in range(n)]
projects.sort()
maxHeap = []
i = 0
for _ in range(k):
while i < n and projects[i][0] <= w:
heapq.heappush(maxHeap, -projects[i][1])
i += 1
if not maxHeap:
break
w -= heapq.heappop(maxHeap)
return w
4.7.1008 - 2024-06-14 18:54:35 +0300 MSK
Links
Code
class Solution:
def minIncrementForUnique(self, nums: List[int]) -> int:
# nums = [3,2,1,2,1,7]
# [1,1,2,2,3,7]
# mySet = set({ num for num in nums }), 2+4
nums.sort()
numTracker = 0
minIncreament = 0
for num in nums:
numTracker = max(numTracker, num)
minIncreament += numTracker - num
numTracker += 1
return minIncreament
4.7.1009 - 2024-06-13 10:32:12 +0300 MSK
Links
Code
class Solution:
def minMovesToSeat(self, seats: List[int], students: List[int]) -> int:
seats.sort()
students.sort()
moves = 0
for i in range(len(seats)) :
moves += abs(seats[i] - students[i])
return moves
4.7.1010 - 2024-06-12 19:59:15 +0300 MSK
Links
Code
class Solution:
def sortColors(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
zeros, ones, n = 0, 0, len(nums)
for num in nums:
if num == 0:
zeros += 1
elif num == 1:
ones += 1
for i in range(0, zeros):
nums[i] = 0
for i in range(zeros, zeros + ones):
nums[i] = 1
for i in range(zeros + ones, n):
nums[i] = 2
4.7.1011 - 2024-06-11 20:57:06 +0300 MSK
Links
Code
class Solution:
def relativeSortArray(self, arr1, arr2):
result = []
for i in range(len(arr2)):
for j in range(len(arr1)):
if arr1[j] == arr2[i]:
result.append(arr1[j])
arr1[j] = -1
arr1.sort()
for num in arr1:
if num != -1:
result.append(num)
return result
4.7.1012 - 2024-06-10 13:15:44 +0300 MSK
Links
Code
class Solution:
def heightChecker(self, heights: List[int]) -> int:
return sum(h!=s for h, s in zip(heights, sorted(heights)))
4.7.1013 - 2024-06-09 13:56:45 +0300 MSK
Links
Code
class Solution:
def subarraysDivByK(self, nums: List[int], k: int) -> int:
count = 0
prefix_sum = 0
prefix_map = {0: 1}
for num in nums:
prefix_sum += num
mod = prefix_sum % k
if mod < 0:
mod += k
if mod in prefix_map:
count += prefix_map[mod]
prefix_map[mod] += 1
else:
prefix_map[mod] = 1
return count
4.7.1014 - 2024-06-08 22:13:27 +0300 MSK
Links
Code
class Solution:
def checkSubarraySum(self, nums: List[int], k: int) -> bool:
remainder_map = {0: -1}
cumulative_sum = 0
for i, num in enumerate(nums):
cumulative_sum += num
remainder = cumulative_sum % k
if remainder in remainder_map:
if i - remainder_map[remainder] > 1:
return True
else:
remainder_map[remainder] = i
return False
4.7.1015 - 2024-06-07 18:18:51 +0300 MSK
Links
Code
class Solution:
def replaceWords(self, dict: List[str], sentence: str) -> str:
roots = set(dict)
words = sentence.split()
result = []
for word in words:
for i in range(len(word) + 1):
prefix = word[:i]
if prefix in roots:
result.append(prefix)
break
else:
result.append(word)
return ' '.join(result)
4.7.1016 - 2024-06-06 18:22:03 +0300 MSK
Links
Code
class Solution:
def isNStraightHand(self, hand: List[int], groupSize: int) -> bool:
# Step 1: Check if grouping is possible
if len(hand) % groupSize != 0:
return False
# Step 2: Count the occurrences of each card
count = Counter(hand)
# Step 3: Sort the unique card values
sorted_keys = sorted(count.keys())
# Step 4: Form consecutive groups
for key in sorted_keys:
if count[key] > 0: # If this card is still available
start_count = count[key]
# Check and form a group starting from `key`
for i in range(key, key + groupSize):
if count[i] < start_count:
return False
count[i] -= start_count
# Step 5: Return True if all groups are formed successfully
return True
4.7.1017 - 2024-06-05 10:32:36 +0300 MSK
Links
Code
class Solution:
def commonChars(self, words: List[str]) -> List[str]:
result = []
# Check each character from 'a' to 'z'
for char in range(ord('a'), ord('z') + 1):
char = chr(char)
min_count = float('inf') # Start with a very high number
# Find the minimum count of the character in all words
for word in words:
count = word.count(char) # Count the current character in the current word
min_count = min(min_count, count) # Keep track of the smallest count
if min_count == 0:
break # If the character is not in one of the words, we can skip further checking
# Add the character to the result list the required number of times
result.extend([char] * min_count)
return result
4.7.1018 - 2024-06-03 15:40:20 +0300 MSK
Links
Code
class Solution:
def appendCharacters(self, s: str, t: str) -> int:
i, j = 0, 0 # Start both pointers at the beginning of s and t
while i < len(s) and j < len(t): # Continue until one of the strings is fully scanned
if s[i] == t[j]: # If characters match
j += 1 # Move the pointer in t forward
i += 1 # Always move the pointer in s forward
return len(t) - j # The number of characters in t not matched in s
4.7.1019 - 2024-06-02 21:31:18 +0300 MSK
Links
Code
class Solution:
def checkRecord(self, n: int) -> int:
# Recursion + Cache
mod=10**9+7
#only @cache will lead to MLE
dp=[[[-1]*3 for _ in range(2)] for _ in range(n+1)]
def f(i, absent, late):
if absent>=2 or late>=3: return 0
if i==0: return 1
if dp[i][absent][late]!=-1:
return dp[i][absent][late]
ans=f(i-1, absent, 0)
ans+=f(i-1, absent, late+1)
ans+=f(i-1, absent+1, 0)
dp[i][absent][late]=ans%mod
return dp[i][absent][late]
return f(n, 0, 0)
4.7.1020 - 2024-06-01 22:04:19 +0300 MSK
Links
Code
class Solution:
def singleNumber(self, nums: list[int]) -> list[int]:
n: int = len(nums)
result: list[int] = [0, 0]
index = 0
for i in range(n):
found = False
for j in range(n):
if i != j and nums[i] == nums[j]:
found = True
break
if not found:
result[index] = nums[i]
index += 1
if index == 2:
break
return result
4.7.1021 - 2024-06-01 22:04:02 +0300 MSK
Links
Code
class Solution:
def countTriplets(self, arr: List[int]) -> int:
n = len(arr)
prefix = [0] * (n + 1)
for i in range(n):
prefix[i + 1] = prefix[i] ^ arr[i]
count = 0
for i in range(n):
for k in range(i + 1, n):
if prefix[i] == prefix[k + 1]:
count += (k - i)
return count
4.7.1022 - 2024-06-01 22:03:45 +0300 MSK
Links
Code
class Solution:
def maxScoreWords(
self, words: List[str], letters: List[str], score: List[int]
) -> int:
lettersCounter = Counter(letters)
totalScore = 0
def explore(index, letterCounter, currScore):
nonlocal totalScore
totalScore = max(totalScore, currScore)
if index == len(words):
return
for i in range(index, len(words)):
tmpCounter = copy.deepcopy(letterCounter)
word = words[i]
wordScore = 0
isValid = True
for ch in word:
if ch in tmpCounter and tmpCounter[ch] > 0:
tmpCounter[ch] -= 1
wordScore += score[ord(ch) - ord("a")]
else:
isValid = False
break
if isValid:
explore(i + 1, tmpCounter, currScore + wordScore)
explore(0, lettersCounter, 0)
return totalScore
4.7.1023 - 2024-06-01 22:01:30 +0300 MSK
Links
Code
class Solution:
def scoreOfString(self, s: str) -> int:
score = 0
for i in range(len(s) - 1):
score += abs(ord(s[i]) - ord(s[i + 1]))
return score
4.7.1024 - 2024-05-29 12:47:46 +0300 MSK
Links
Code
class Solution:
def numSteps(self, s: str) -> int:
steps = 0
carry = 0
n = len(s) - 1
for i in range(n, 0, -1):
if int(s[i]) + carry == 1:
carry = 1
steps += 2
else:
steps += 1
return steps + carry
4.7.1025 - 2024-05-28 20:05:20 +0300 MSK
Links
Code
class Solution:
def equalSubstring(self, s: str, t: str, maxCost: int) -> int:
n = len(s)
start = 0
current_cost = 0
max_length = 0
for end in range(n):
current_cost += abs(ord(s[end]) - ord(t[end]))
while current_cost > maxCost:
current_cost -= abs(ord(s[start]) - ord(t[start]))
start += 1
max_length = max(max_length, end - start + 1)
return max_length
4.7.1026 - 2024-05-27 10:56:18 +0300 MSK
Links
Code
class Solution:
def specialArray(self, nums: list[int]) -> int:
nums.sort()
n: int = len(nums)
def find_number_of_nums(cur_num) -> int:
left: int = 0
right: int = n - 1
first_index: int = n
while left <= right:
mid: int = (left + right) // 2
if nums[mid] >= cur_num:
first_index = mid
right = mid - 1
else:
left = mid + 1
return n - first_index
for candidate_number in range(1, n + 1, 1):
if candidate_number == find_number_of_nums(candidate_number):
return candidate_number
return -1
4.7.1027 - 2024-05-26 20:44:15 +0300 MSK
Links
Code
class Solution:
def checkRecord(self, n: int) -> int:
temp: list[list[list[int]]] = [
[[-1 for _ in range(3)] for _ in range(2)] for _ in range(n)
] # temp[cur_ind][count_a][count_l]
MOD: int = 10**9 + 7
def check_all_records(cur_ind, count_a, count_l) -> int:
if cur_ind == n:
return 1
if temp[cur_ind][count_a][count_l] != -1:
return temp[cur_ind][count_a][count_l]
with_a_next: int = check_all_records(cur_ind + 1, count_a + 1, 0) if count_a == 0 else 0
with_l_next: int = 0 if count_l == 2 else check_all_records(cur_ind + 1, count_a, count_l + 1)
with_p_next: int = check_all_records(cur_ind + 1, count_a, 0)
total: int = (with_a_next + with_l_next + with_p_next) % MOD
temp[cur_ind][count_a][count_l] = total
return total
return check_all_records(0, 0, 0)
4.7.1028 - 2024-05-25 22:59:58 +0300 MSK
Links
Code
class Solution:
def wordBreak(self, s: str, wordDict: List[str]) -> List[str]:
wordSet = set(wordDict)
@cache
def helper(t):
combos = []
if not t:
return [""]
for i, _ in enumerate(t):
w = t[:i+1]
if w in wordSet:
combos.extend([
f'{w} {sentence}' if sentence else w
for sentence in helper(t[i+1:])
])
return combos
return helper(s)
4.7.1029 - 2024-05-21 21:02:08 +0300 MSK
Links
Code
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
def backtrack(start, path):
result.append(path)
for i in range(start, len(nums)):
backtrack(i + 1, path + [nums[i]])
result = []
backtrack(0, [])
return result
4.7.1030 - 2024-05-20 13:28:49 +0300 MSK
Links
Code
class Solution:
def subsetXORSum(self, nums: List[int]) -> int:
return reduce(operator.or_, nums) * 1 << (len(nums) - 1)
4.7.1031 - 2024-05-19 15:08:43 +0300 MSK
Links
Code
class Solution:
def maximumValueSum(self, nums: list[int], k: int, edges: list[list[int]]) -> int:
n: int = len(nums)
temp: list[list[int]] = [[-1 for _ in range(2)] for _ in range(n)] # temp[current_index(node)][is_even]
def calculate_max(cur_ind, is_even) -> int: # cur_ind -> cur_index of the tree and is_even represents whether we have already changed (XOR) even or odd number of nodes
if cur_ind == n: # if we go to node which doesn't exist
return 0 if is_even else -float("inf")
if temp[cur_ind][is_even] != -1: # if we've already encountered this state
return temp[cur_ind][is_even]
# checking all possible variants (no XOR or XOR)
no_xor = nums[cur_ind] + calculate_max(cur_ind + 1, is_even) # we don't change the number of XOR nodes
with_xor = (nums[cur_ind] ^ k) + calculate_max(cur_ind + 1, not is_even) # we added 1 XORed node
mx_possible = max(no_xor, with_xor)
temp[cur_ind][is_even] = mx_possible
return mx_possible
return calculate_max(0, 1) # is_even == 1 because we have XORed 0 nodes which is even
4.7.1032 - 2024-05-18 20:24:14 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def distributeCoins(self, root: Optional[TreeNode]) -> int:
#move coins to parent DFS
def f(root, parent):
if root==None: return 0
moves=f(root.left, root)+f(root.right, root)
x=root.val-1
if parent!=None: parent.val+=x
moves+=abs(x)
return moves
return f(root, None)
4.7.1033 - 2024-05-17 21:25:39 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution(object):
def removeLeafNodes(self, root, target):
"""
:type root: TreeNode
:type target: int
:rtype: TreeNode
"""
if not root:
return None
root.left = self.removeLeafNodes(root.left, target)
root.right = self.removeLeafNodes(root.right, target)
if not root.left and not root.right and root.val == target:
return None
return root
4.7.1034 - 2024-05-16 18:11:33 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def helper(self, root):
if root.val == 0 or root.val == 1:
return root.val == 1
elif root.val == 2:
return self.helper(root.left) or self.helper(root.right)
elif root.val == 3:
return self.helper(root.left) and self.helper(root.right)
return False
def evaluateTree(self, root: Optional[TreeNode]) -> bool:
return self.helper(root)
4.7.1035 - 2024-05-14 12:06:07 +0300 MSK
Links
Code
class Solution:
roww = [1, -1, 0, 0]
coll = [0, 0, -1, 1]
def dfs(self, grid, x, y, n, m):
if x < 0 or x >= n or y < 0 or y >= m or grid[x][y] == 0:
return 0
curr = grid[x][y]
grid[x][y] = 0
localMaxGold = curr
for i in range(4):
newX = x + self.roww[i]
newY = y + self.coll[i]
localMaxGold = max(localMaxGold, curr + self.dfs(grid, newX, newY, n, m))
grid[x][y] = curr
return localMaxGold
def getMaximumGold(self, grid):
n = len(grid)
m = len(grid[0])
maxGold = 0
for i in range(n):
for j in range(m):
if grid[i][j] != 0:
maxGold = max(maxGold, self.dfs(grid, i, j, n, m))
return maxGold
4.7.1036 - 2024-05-13 10:22:15 +0300 MSK
Links
Code
class Solution:
def matrixScore(self, grid: List[List[int]]) -> int:
n, m = len(grid), len(grid[0])
res = (1 << (m - 1)) * n
for j in range(1, m):
val = 1 << (m - 1 - j)
set_count = 0
for i in range(n):
if grid[i][j] == grid[i][0]:
set_count += 1
res += max(set_count, n - set_count) * val
return res
4.7.1037 - 2024-05-12 21:39:08 +0300 MSK
Links
Code
class Solution:
def largestLocal(self, grid: List[List[int]]) -> List[List[int]]:
n, res = len(grid), []
for i in range(1, n - 1):
temp_row = []
for j in range(1, n - 1):
temp = 0
for k in range(i - 1, i + 2):
for l in range(j - 1, j + 2):
temp = max(temp, grid[k][l])
temp_row.append(temp)
res.append(temp_row)
return res
4.7.1038 - 2024-05-08 10:50:28 +0300 MSK
Links
Code
import heapq
class Solution:
def findRelativeRanks(self, score: List[int]) -> List[str]:
heap = []
length = len(score)
scores = [0] * length
for i in range(length):
scores[i] = (score[i], i)
scores.sort(reverse=True)
ranks = {0: "Gold Medal", 1: "Silver Medal", 2: "Bronze Medal"}
for i in range(length):
_, idx = scores[i]
score[idx] = ranks.get(i, str(i + 1))
return score
4.7.1039 - 2024-05-08 10:39:08 +0300 MSK
Links
Code
import heapq
class Solution:
def findRelativeRanks(self, score: List[int]) -> List[str]:
heap = []
for i, athlete_score in enumerate(score):
heapq.heappush(heap, (-athlete_score, i))
i = 0
ranks = {0: "Gold Medal", 1: "Silver Medal", 2: "Bronze Medal"}
while heap:
_, athlete = heapq.heappop(heap)
rank = ranks.get(i, str(i + 1))
score[athlete] = rank
i += 1
return score
4.7.1040 - 2024-05-07 10:56:39 +0300 MSK
Links
Code
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def doubleIt(self, head: Optional[ListNode]) -> Optional[ListNode]:
def func(head):
a=head.val*2
if head.next:
a+=func(head.next)
head.val=a%10
return a//10
a=func(head)
if a:
return ListNode(a,head)
return head
4.7.1041 - 2024-05-06 16:47:26 +0300 MSK
Links
Code
class Solution:
def removeNodes(self, head: Optional[ListNode]) -> Optional[ListNode]:
cur = head
stack = []
while cur:
while stack and stack[-1].val < cur.val:
stack.pop()
stack.append(cur)
cur = cur.next
nxt = None
while stack:
cur = stack.pop()
cur.next = nxt
nxt = cur
return cur
4.7.1042 - 2024-05-04 18:08:36 +0300 MSK
Links
Code
func numRescueBoats(people []int, limit int) int {
sort.Ints(people)
numberOfBouts := 0
start := 0
end := len(people)-1
for start < end {
if people[start] + people[end] <= limit {
numberOfBouts++
start++
}else{
numberOfBouts++
}
end--
}
if start == end {
numberOfBouts++
}
return numberOfBouts
}
4.7.1043 - 2024-05-03 17:41:51 +0300 MSK
Links
Code
func compareVersion(version1 string, version2 string) int {
rev1 := strings.Split(version1, ".")
rev2 := strings.Split(version2, ".")
// fmt.Println(rev1, rev2)
revInt1 := make([]int, len(rev1))
revInt2 := make([]int, len(rev2))
for i := 0; i < len(rev1); i++ {
revInt1[i], _ = strconv.Atoi(rev1[i])
}
for i := 0; i < len(rev2); i++ {
revInt2[i], _ = strconv.Atoi(rev2[i])
}
// fmt.Println(revInt1, revInt2)
i := 0
j := 0
for i < len(revInt1) && j < len(revInt2) {
if revInt1[i] < revInt2[j] {
return -1
} else if revInt1[i] > revInt2[j] {
return 1
}
i++
j++
}
for i < len(revInt1) {
if revInt1[i] > 0 {
return 1
}
i++
}
for j < len(revInt2) {
if revInt2[j] > 0 {
return -1
}
j++
}
return 0
}
4.7.1044 - 2024-05-02 19:49:20 +0300 MSK
Links
Code
func findMaxK(nums []int) int {
alreadySeenNums := map[int]bool{}
res := -1
for _, num := range nums {
numAbs := int(math.Abs(float64(num)))
if numAbs < res {
continue
}
if alreadySeenNums[-num] {
res = numAbs
} else {
alreadySeenNums[num] = true
}
}
return res
}
4.7.1045 - 2024-05-01 12:05:11 +0300 MSK
Links
Code
type UnionFind struct {
parent []int
rank []int
}
func NewUnionFind(n int) *UnionFind {
parent := make([]int, n)
rank := make([]int, n)
for i := 0; i < n; i++ {
parent[i] = i
}
return &UnionFind{parent, rank}
}
func (uf *UnionFind) Find(u int) int {
if uf.parent[u] != u {
uf.parent[u] = uf.Find(uf.parent[u])
}
return uf.parent[u]
}
func (uf *UnionFind) UnionByRank(u, v int) {
i := uf.Find(u)
j := uf.Find(v)
if i == j {
return
}
if uf.rank[i] < uf.rank[j] {
uf.parent[i] = j
} else if uf.rank[i] > uf.rank[j] {
uf.parent[j] = i
} else {
uf.parent[i] = j
uf.rank[j]++
}
}
func validPath(n int, edges [][]int, source int, destination int) bool {
uf := NewUnionFind(n)
for _, edge := range edges {
u, v := edge[0], edge[1]
uf.UnionByRank(u, v)
}
return uf.Find(source) == uf.Find(destination)
}
4.7.1046 - 2024-05-01 12:04:46 +0300 MSK
Links
Code
func get(c rune) int {
return int(c - 'a')
}
func wonderfulSubstrings(word string) int64 {
cnt := make([]int64, 1024)
cnt[0] = 1
curState := 0
res := int64(0)
for _, c := range word {
curState ^= 1 << get(c)
res += cnt[curState]
for odd := 'a'; odd <= 'j'; odd++ {
oddState := curState ^ (1 << get(odd))
res += cnt[oddState]
}
cnt[curState]++
}
return res
}
4.7.1047 - 2024-05-01 12:04:24 +0300 MSK
Links
Code
func sumOfDistancesInTree(n int, edges [][]int) []int {
graph := make(map[int][]int)
count := make([]int, n)
res := make([]int, n)
for _, edge := range edges {
u, v := edge[0], edge[1]
graph[u] = append(graph[u], v)
graph[v] = append(graph[v], u)
}
var dfs1 func(cur, parent int)
dfs1 = func(cur, parent int) {
count[cur] = 1
for _, child := range graph[cur] {
if child != parent {
dfs1(child, cur)
count[cur] += count[child]
res[cur] += res[child] + count[child]
}
}
}
var dfs2 func(cur, parent int)
dfs2 = func(cur, parent int) {
for _, child := range graph[cur] {
if child != parent {
res[child] = res[cur] + n - 2*count[child]
dfs2(child, cur)
}
}
}
dfs1(0, -1)
dfs2(0, -1)
return res
}
4.7.1048 - 2024-05-01 12:02:52 +0300 MSK
Links
Code
func reversePrefix(word string, ch byte) string {
var natija string
for i := 0; i < len(word); i++ {
if word[i] == ch {
ch_index := i
for i >= 0 {
natija += string(word[i])
i--
}
return natija + word[ch_index + 1 : ]
}
}
return word
}
4.7.1049 - 2024-04-29 21:04:33 +0300 MSK
Links
Code
func minOperations(nums []int, k int) int {
res := k
for _, n := range nums {
res ^= n
}
var ans int
for res > 0 {
ans += res%2
res = res >> 1
}
return ans
}
4.7.1050 - 2024-04-26 10:34:22 +0300 MSK
Links
Code
type Triplet struct {
minSum int
secondMinSum int
minSumIndex int
}
func minFallingPathSum(grid [][]int) int {
return minFallingPathSumHelper(0, grid).minSum
}
func minFallingPathSumHelper(row int, grid [][]int) Triplet {
if row == len(grid) {
return Triplet{0, 0, 0}
}
nextRowTriplet := minFallingPathSumHelper(row+1, grid)
currentTriplet := Triplet{math.MaxInt32, math.MaxInt32, -1}
for col := 0; col < len(grid[0]); col++ {
var value int
if col != nextRowTriplet.minSumIndex {
value = grid[row][col] + nextRowTriplet.minSum
} else {
value = grid[row][col] + nextRowTriplet.secondMinSum
}
if value <= currentTriplet.minSum {
currentTriplet.secondMinSum = currentTriplet.minSum
currentTriplet.minSum = value
currentTriplet.minSumIndex = col
} else if value < currentTriplet.secondMinSum {
currentTriplet.secondMinSum = value
}
}
return currentTriplet
}
4.7.1051 - 2024-04-25 20:32:24 +0300 MSK
Links
Code
func longestIdealString(s string, k int) int {
dp := make([]int, 27)
n := len(s)
for i := n - 1; i >= 0; i-- {
cc := s[i]
idx := int(cc - 'a')
maxi := -1 << 31
left := max(idx-k, 0)
right := min(idx+k, 26)
for j := left; j <= right; j++ {
maxi = max(maxi, dp[j])
}
dp[idx] = maxi + 1
}
max := -1 << 31
for _, val := range dp {
if val > max {
max = val
}
}
return max
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
4.7.1052 - 2024-04-24 15:06:12 +0300 MSK
Links
Code
func tribonacci(n int) int {
if n < 2 {
return n
}
dp := []int{0, 1, 1}
for i := 3; i <= n; i++ {
next := dp[0] + dp[1] + dp[2]
dp[0], dp[1], dp[2] = dp[1], dp[2], next
}
return dp[2]
}
4.7.1053 - 2024-04-23 18:14:09 +0300 MSK
Links
Code
func findMinHeightTrees(n int, edges [][]int) []int {
counts := make([]int, n)
links := make([]int, n)
for _, edge := range edges {
links[edge[0]] ^= edge[1]
counts[edge[0]]++
links[edge[1]] ^= edge[0]
counts[edge[1]]++
}
Qu := make([]int, 0)
dists := make([]int, n)
for i := 0; i < n; i++ {
if counts[i] == 1 {
Qu = append(Qu, i)
}
}
stp := 1
for len(Qu) > 0 {
size := len(Qu)
for j := 0; j < size; j++ {
tmp := Qu[0]
Qu = Qu[1:]
links[links[tmp]] ^= tmp
counts[links[tmp]]--
if counts[links[tmp]] == 1 {
dists[links[tmp]] = int(math.Max(float64(stp), float64(dists[links[tmp]])))
Qu = append(Qu, links[tmp])
}
}
stp++
}
maxDist := 0
for _, dist := range dists {
if dist > maxDist {
maxDist = dist
}
}
res := make([]int, 0)
for i, dist := range dists {
if dist == maxDist {
res = append(res, i)
}
}
return res
}
4.7.1054 - 2024-04-22 10:35:20 +0300 MSK
Links
Code
type UnionFind struct {
parent []int
rank []int
}
func NewUnionFind(n int) *UnionFind {
parent := make([]int, n)
rank := make([]int, n)
for i := 0; i < n; i++ {
parent[i] = i
}
return &UnionFind{parent, rank}
}
func (uf *UnionFind) Find(u int) int {
if uf.parent[u] != u {
uf.parent[u] = uf.Find(uf.parent[u])
}
return uf.parent[u]
}
func (uf *UnionFind) UnionByRank(u, v int) {
i := uf.Find(u)
j := uf.Find(v)
if i == j {
return
}
if uf.rank[i] < uf.rank[j] {
uf.parent[i] = j
} else if uf.rank[i] > uf.rank[j] {
uf.parent[j] = i
} else {
uf.parent[i] = j
uf.rank[j]++
}
}
func validPath(n int, edges [][]int, source int, destination int) bool {
uf := NewUnionFind(n)
for _, edge := range edges {
u, v := edge[0], edge[1]
uf.UnionByRank(u, v)
}
return uf.Find(source) == uf.Find(destination)
}
4.7.1055 - 2024-04-22 10:16:09 +0300 MSK
Links
Code
import "strconv"
func openLock(deadends []string, target string) int {
pow10 := []int{1, 10, 100, 1000}
visit := make([]int, 10000) // 0: not visited, 1: visited through forward direction, -1: visited through backward direction, 2: deadends
for _, dead := range deadends {
num, _ := strconv.Atoi(dead)
visit[num] = 2
}
src := 0
dest, _ := strconv.Atoi(target)
steps := 0
dir := 1
if visit[src] == 2 || visit[dest] == 2 {
return -1
}
if src == dest {
return 0
}
forward := make([]int, 0)
backward := make([]int, 0)
forward = append(forward, src)
visit[src] = 1
backward = append(backward, dest)
visit[dest] = -1
for len(forward) > 0 && len(backward) > 0 {
if len(forward) > len(backward) {
forward, backward = backward, forward
dir = -dir
}
steps++
size := len(forward)
for j := 0; j < size; j++ {
cur := forward[0]
forward = forward[1:]
for _, p := range pow10 {
d := (cur / p) % 10
for _, i := range []int{-1, 1} {
z := d + i
if z == -1 {
z = 9
} else if z == 10 {
z = 0
}
next := cur + (z-d)*p
if visit[next] == -dir {
return steps
}
if visit[next] == 0 {
forward = append(forward, next)
visit[next] = dir
}
}
}
}
}
return -1
}
4.7.1056 - 2024-04-20 21:02:52 +0300 MSK
Links
Code
func findFarmland(land [][]int) [][]int {
result := [][]int{}
m, n := len(land), len(land[0])
findFarmlandCoordinates := func(row, col int) []int {
coordinates := []int{row, col}
r, c := row, col
for r < m && land[r][col] == 1 {
r++
}
for c < n && land[row][c] == 1 {
c++
}
coordinates = append(coordinates, r-1, c-1)
for i := row; i < r; i++ {
for j := col; j < c; j++ {
land[i][j] = 0
}
}
return coordinates
}
for i := 0; i < m; i++ {
for j := 0; j < n; j++ {
if land[i][j] == 1 {
result = append(result, findFarmlandCoordinates(i, j))
}
}
}
return result
}
4.7.1057 - 2024-04-19 10:37:47 +0300 MSK
Links
Code
func islandPerimeter(grid [][]int) int {
islands := 0
neighbors := 0
for i := 0; i < len(grid); i++ {
for j := 0; j < len(grid[0]); j++ {
if grid[i][j] == 1 {
islands++
if i-1 >= 0 && grid[i-1][j] == 1 {
neighbors++
}
if j-1 >= 0 && grid[i][j-1] == 1 {
neighbors++
}
}
}
}
return islands*4 - neighbors*2
}
4.7.1058 - 2024-04-19 10:37:20 +0300 MSK
Links
Code
func numIslands(grid [][]byte) int {
if len(grid) == 0 || len(grid[0]) == 0 {
return 0
}
rows := len(grid)
cols := len(grid[0])
islands := 0
var dfs func(row, col int)
dfs = func(row, col int) {
if row < 0 || col < 0 || row >= rows || col >= cols || grid[row][col] != '1' {
return
}
grid[row][col] = '0'
dfs(row-1, col)
dfs(row+1, col)
dfs(row, col-1)
dfs(row, col+1)
}
for row := 0; row < rows; row++ {
for col := 0; col < cols; col++ {
if grid[row][col] == '1' {
dfs(row, col)
islands++
}
}
}
return islands
}
4.7.1059 - 2024-04-17 10:49:35 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func smallestFromLeaf(root *TreeNode) string {
ans := ""
var dfs func(node *TreeNode, text string)
dfs = func(node *TreeNode, text string) {
if node == nil {
return
}
text = string(rune(node.Val + 97)) + text
if node.Right == nil && node.Left == nil {
if ans == "" || ans > text {
ans = text
}
return
}
dfs(node.Left, text)
dfs(node.Right, text)
}
dfs(root, "")
return ans
}
4.7.1060 - 2024-04-16 22:16:34 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func addOneRow(root *TreeNode, val int, depth int) *TreeNode {
if root == nil {
return nil
}
if depth == 1 {
root = &TreeNode{Val: val, Left: root}
} else if (depth == 2) {
root.Left = &TreeNode{Val: val, Left: root.Left}
root.Right = &TreeNode{Val: val, Right: root.Right}
} else {
addOneRow(root.Left, val, depth - 1)
addOneRow(root.Right, val, depth - 1)
}
return root;
}
4.7.1061 - 2024-04-15 09:51:02 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func sumNumbers(root *TreeNode) int {
return dfs(root, 0)
}
func dfs(node *TreeNode, num int) int {
if node == nil {
return 0
}
if node.Left == nil && node.Right == nil {
return num * 10 + node.Val
}
return dfs(node.Left, num * 10 + node.Val) + dfs(node.Right, num * 10 + node.Val)
}
4.7.1062 - 2024-04-15 09:49:56 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func sumOfLeftLeaves(root *TreeNode) int {
if root == nil {
return 0
}
left := 0
if root.Left != nil && root.Left.Left == nil && root.Left.Right == nil {
left = root.Left.Val
}
return left + sumOfLeftLeaves(root.Left) + sumOfLeftLeaves(root.Right)
}
4.7.1063 - 2024-04-13 18:32:47 +0300 MSK
Links
Code
func maximalRectangle(matrix [][]byte) int {
heights := make([]int, len(matrix[0]) + 1)
heights[len(heights)-1] = -1
mx := 0
for _, row := range matrix {
for i := range row {
if row[i] == '1' {
heights[i]++
} else {
heights[i] = 0
}
}
stack := []int{}
for i, currentHeight := range heights {
for len(stack) > 0 && heights[stack[len(stack)-1]] > currentHeight {
prev := heights[stack[len(stack)-1]]
stack = stack[:len(stack)-1]
width := i
if len(stack) > 0 {
width = i - stack[len(stack)-1] - 1
}
mx = max(mx, prev * width)
}
stack = append(stack, i)
}
}
return mx
}
4.7.1064 - 2024-04-12 10:40:19 +0300 MSK
Links
Code
func trap(height []int) int {
var waterStored int
leftElevationPoint, rightElevationPoint := 0, len(height)-1 // pointers for left and right elevations
maxLeftElevation, maxRightElevation := height[leftElevationPoint], height[rightElevationPoint] // max value of left and right elevation points
for leftElevationPoint < rightElevationPoint { // until left elevation point reaches right elevation point or right elevation point reaches left elevation point
if maxLeftElevation < maxRightElevation { // if max left elevation is smaller than max right elevation
leftElevationPoint++ // move the left elevation point by 1
if height[leftElevationPoint] > maxLeftElevation { // if height of current left elevation after moving is greater than max left elevation
maxLeftElevation = height[leftElevationPoint] // swap the max left elevation with current left elevation point value
}
waterStored += maxLeftElevation - height[leftElevationPoint] // store water with delta of max left elevation and current left elevation
} else {
rightElevationPoint-- // decrease the right elevation by 1
if height[rightElevationPoint] > maxRightElevation { // if height of current right elevation after decreasing is greater than max right elevation
maxRightElevation = height[rightElevationPoint] // swap the max right elevation with current right elevation point value
}
waterStored += maxRightElevation - height[rightElevationPoint] // store water with delta of max right elevation and current right elevation
}
}
return waterStored
}
4.7.1065 - 2024-04-11 13:44:41 +0300 MSK
Links
Code
func removeKdigits(num string, k int) string {
res := make([]rune, 0)
for _, c := range num {
for len(res) > 0 && res[len(res) - 1] > c && k > 0 {
res = res[:len(res) - 1]
k--
}
if len(res) > 0 || c != '0' {
res = append(res, c)
}
}
for len(res) > 0 && k > 0 {
res = res[:len(res) - 1]
k--
}
if len(res) == 0 {
return "0"
}
return string(res)
}
4.7.1066 - 2024-04-10 13:25:18 +0300 MSK
Links
Code
func deckRevealedIncreasing(deck []int) []int {
n := len(deck)
sort.Ints(deck)
res := make([]int, n)
queue := make([]int, n)
for i := range queue {
queue[i] = i
}
for _, card := range deck {
idx := queue[0]
queue = queue[1:]
res[idx] = card
if len(queue) > 0 {
queue = append(queue, queue[0])
queue = queue[1:]
}
}
return res
}
4.7.1067 - 2024-04-09 14:21:46 +0300 MSK
Links
Code
func timeRequiredToBuy(tickets []int, k int) int {
n := len(tickets)
d := tickets[k]
res := 0
for i := 0; i <= k; i++ {
res += min(d, tickets[i])
}
for i := k + 1; i < n; i++ {
res += min(d - 1, tickets[i])
}
return res
}
4.7.1068 - 2024-04-08 11:25:34 +0300 MSK
Links
Code
func countStudents(students []int, sandwiches []int) int {
req := make([]int, 2)
for _, student := range students {
req[student]++
}
for _, sandwich := range sandwiches {
if req[sandwich] == 0 {
return req[1 - sandwich]
} else {
req[sandwich]--
}
}
return 0
}
4.7.1069 - 2024-04-07 11:42:18 +0300 MSK
Links
Code
func checkValidString(s string) bool {
open := 0
openMax := 0
for _, char := range s {
switch char {
case '(':
open++
openMax++
case ')':
open--
openMax--
default:
open--
openMax++
}
if openMax < 0 {
return false
}
if open < 0 {
open = 0
}
}
return open == 0
}
4.7.1070 - 2024-04-07 11:41:54 +0300 MSK
Links
Code
type stack struct {
top int
v []byte
index []int
}
func minRemoveToMakeValid(s string) string {
stc := stack{top: -1}
// collect bad brackets
for i, v := range s {
if v == '(' {
stc.v = append(stc.v, '(')
stc.index = append(stc.index, i)
stc.top++
} else if v == ')' {
if stc.top > -1 && stc.v[stc.top] == '(' {
stc.v = stc.v[:stc.top]
stc.index = stc.index[:stc.top]
stc.top--
} else {
stc.v = append(stc.v, ')')
stc.index = append(stc.index, i)
stc.top++
}
}
}
// remove them
res := []byte{}
i := 0
for _, v := range stc.index {
res = append(res, s[i:v]...)
i = v + 1
}
// checking of end
if len(res) + len(stc.index) < len(s) {
res = append(res, s[i:]...)
}
return string(res)
}
4.7.1071 - 2024-04-05 17:17:39 +0300 MSK
Links
Code
func makeGood(s string) string {
stack := make([]byte, 0, len(s))
stack = append(stack, s[0])
for i := 1; i < len(s); i++ {
if len(stack) > 0 && getDiff(stack[len(stack)-1], s[i]) == 32 {
stack = stack[:len(stack)-1]
continue
}
stack = append(stack, s[i])
}
return string(stack)
}
func getDiff(a, b uint8) uint8 {
if b > a {
return b - a
}
return a - b
}
4.7.1072 - 2024-04-04 16:06:45 +0300 MSK
Links
Code
func maxDepth(s string) int {
maxDepth := 0
curDepth := 0
for _, ch := range s {
if ch == '(' {
curDepth++
maxDepth = max(maxDepth, curDepth)
} else if ch == ')' {
curDepth--
}
}
return maxDepth
}
4.7.1073 - 2024-04-03 10:52:54 +0300 MSK
Links
Code
func exist(board [][]byte, word string) bool {
if nLetters := len(board) * len(board[0]); nLetters < len(word) {
return false
}
for i := range board {
for j := range board[i] {
if dfs(i, j, 0, board, word, make(map[pair]struct{})) {
return true
}
}
}
return false
}
type pair struct {
r, c int
}
func dfs(r, c, i int, board [][]byte, word string, visited map[pair]struct{}) bool {
if i == len(word) {
return true
}
inBounds := r >= 0 && r < len(board) && c >= 0 && c < len(board[0])
if _, ok := visited[pair{r, c}]; !inBounds || ok || word[i] != board[r][c] {
return false
}
visited[pair{r, c}] = struct{}{}
up := dfs(r+1, c, i+1, board, word, visited)
down := dfs(r-1, c, i+1, board, word, visited)
right := dfs(r, c+1, i+1, board, word, visited)
left := dfs(r, c-1, i+1, board, word, visited)
delete(visited, pair{r, c})
return up || down || right || left
}
4.7.1074 - 2024-04-02 17:28:57 +0300 MSK
Links
Code
func isIsomorphic(s string, t string) bool {
map1 := make([]int, 128) // Stores frequency of s
map2 := make([]int, 128) // Stores frequency of t
for i := 0; i < len(s); i++ {
sCh := s[i]
tCh := t[i]
if map1[sCh] == 0 && map2[tCh] == 0 {
map1[sCh] = int(tCh)
map2[tCh] = int(sCh)
} else if map1[sCh] != int(tCh) || map2[tCh] != int(sCh) {
return false
}
}
return true
}
4.7.1075 - 2024-04-01 18:03:03 +0300 MSK
Links
Code
func lengthOfLastWord(s string) int {
length := len(s)
count := 0
for i := length - 1; i >= 0; i-- {
isSpace := s[i] == ' '
if isSpace && count != 0 {
return count
} else if isSpace {
continue
}
count++
}
return count
}
4.7.1076 - 2024-03-31 10:58:30 +0300 MSK
Links
Code
func countSubarrays(nums []int, minK int, maxK int) int64 {
var res int64
left := 0
pmin := -1
pmax := -1
for right, num := range nums {
if num < minK || num > maxK {
left = right + 1
pmin = -1
pmax = -1
} else {
if num == minK {
pmin = right
}
if num == maxK {
pmax = right
}
res += int64(max(0, min(pmin, pmax) - left + 1))
}
}
return res
}
4.7.1077 - 2024-03-30 19:24:47 +0300 MSK
Links
Code
func subarraysWithAtMostKDistinct(nums []int, k int) int {
if k == 0 {
return 0
}
countOccurrence := make(map[int]int)
differentIntegers := 0
left := 0
result := 0
for right := 0; right < len(nums); right++ {
countOccurrence[nums[right]]++
if countOccurrence[nums[right]] == 1 {
differentIntegers++
}
for differentIntegers > k {
countOccurrence[nums[left]]--
if countOccurrence[nums[left]] == 0 {
differentIntegers--
}
left++
}
result += right - left + 1
}
return result
}
func subarraysWithKDistinct(nums []int, k int) int {
return subarraysWithAtMostKDistinct(nums, k) - subarraysWithAtMostKDistinct(nums, k-1)
}
4.7.1078 - 2024-03-29 14:30:16 +0300 MSK
Links
Code
func countSubarrays(nums []int, k int) int64 {
maxValue := 0
var maxValueIds []int
var ans int64
for i, x := range nums {
if x > maxValue {
maxValue, ans, maxValueIds = x, 0, []int{}
}
if x == maxValue {
maxValueIds = append(maxValueIds, i)
}
if len(maxValueIds) >= k {
ans += int64(maxValueIds[len(maxValueIds)-k]) + 1
}
}
return ans
}
4.7.1079 - 2024-03-28 19:02:58 +0300 MSK
Links
Code
func maxSubarrayLength(nums []int, k int) int {
i := 0
j := 0
n := len(nums)
ans := 1
mp := make(map[int]int)
for i < n {
mp[nums[i]]++
for mp[nums[i]] > k {
mp[nums[j]]--
j++
}
if i-j+1 > ans {
ans = i - j + 1
}
i++
}
return ans
}
4.7.1080 - 2024-03-27 18:55:43 +0300 MSK
Links
Code
func numSubarrayProductLessThanK(nums []int, k int) int {
if k <= 1 {
return 0
}
l := 0
p := 1
res := 0
for r, num := range nums {
p *= num
for p >= k {
p /= nums[l]
l++
}
res += r - l + 1
}
return res
}
4.7.1081 - 2024-03-26 10:04:37 +0300 MSK
Links
Code
func firstMissingPositive(nums []int) int {
n := len(nums)
for i := 0; i < n; i++ {
if nums[i] <= 0 || nums[i] > n {
nums[i] = n + 1
}
}
for i := 0; i < n; i++ {
val := abs(nums[i])
if val >= 1 && val <= n {
flagIndex := val - 1
if nums[flagIndex] > 0 {
nums[flagIndex] *= -1
}
}
}
for i := 1; i <= n; i++ {
if nums[i - 1] > 0 {
return i
}
}
return n + 1
}
func abs(x int) int {
if x < 0 {
return -x
}
return x
}
4.7.1082 - 2024-03-25 19:23:11 +0300 MSK
Links
Code
func findDuplicates(nums []int) []int {
output := []int{}
for _, num := range nums {
idx := abs(num)
if nums[idx-1] < 0 {
output = append(output, idx)
} else {
nums[idx-1] *= -1
}
}
return output
}
func abs(num int) int {
if num < 0 {
return -num
}
return num
}
4.7.1083 - 2024-03-24 14:27:34 +0300 MSK
Links
Code
func findDuplicate(nums []int) int {
seen := make(map[int]struct{})
for _, num := range nums {
if _, ok := seen[num]; ok {
return num
}
seen[num] = struct{}{}
}
return -1
}
4.7.1084 - 2024-03-24 14:27:17 +0300 MSK
Links
Code
func findDuplicate(nums []int) int {
seen := make(map[int]struct{}, len(nums) - 1)
for _, num := range nums {
if _, ok := seen[num]; ok {
return num
}
seen[num] = struct{}{}
}
return -1
}
4.7.1085 - 2024-03-23 20:51:44 +0300 MSK
Links
Code
func reorderList(head *ListNode) {
if head == nil || head.Next == nil {
return
}
middle := midNode(head)
newHead := middle.Next
middle.Next = nil
newHead = reverseLinkedList(newHead)
c1 := head
c2 := newHead
var f1, f2 *ListNode
for c1 != nil && c2 != nil {
// Backup
f1 = c1.Next
f2 = c2.Next
// Linking
c1.Next = c2
c2.Next = f1
// Move
c1 = f1
c2 = f2
}
}
func midNode(head *ListNode) *ListNode {
slow := head
fast := head
for fast.Next != nil && fast.Next.Next != nil {
slow = slow.Next
fast = fast.Next.Next
}
return slow
}
func reverseLinkedList(head *ListNode) *ListNode {
var prev, curr, forw *ListNode = nil, head, nil
for curr != nil {
forw = curr.Next
curr.Next = prev
prev = curr
curr = forw
}
return prev
}
4.7.1086 - 2024-03-22 11:45:00 +0300 MSK
Links
Code
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func isPalindrome(head *ListNode) bool {
nodes := []int{}
for head != nil {
nodes = append(nodes, head.Val)
head = head.Next
}
length := len(nodes)
for i := range(length / 2) {
start, end := nodes[i], nodes[length-i-1]
if start != end {
return false
}
}
return true
}
4.7.1087 - 2024-03-22 11:41:12 +0300 MSK
Links
Code
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func reverseList(head *ListNode) *ListNode {
if head == nil {
return nil
}
cur, next := head, head.Next
head.Next = nil
for next != nil {
cur, next, next.Next = next, next.Next, cur
}
return cur
}
4.7.1088 - 2024-03-21 14:09:24 +0300 MSK
Links
Code
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func reverseList(head *ListNode) *ListNode {
if head == nil {
return nil
}
cur, next := head, head.Next
head.Next = nil
for next != nil {
cur, next, next.Next = next, next.Next, cur
}
return cur
}
4.7.1089 - 2024-03-21 14:05:27 +0300 MSK
Links
Code
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func reverseList(head *ListNode) *ListNode {
if head == nil {
return nil
}
cur, next := head, head.Next
cur.Next = nil
for next != nil {
cur, next, next.Next = next, next.Next, cur
}
return cur
}
4.7.1090 - 2024-03-21 13:53:28 +0300 MSK
Links
Code
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func mergeInBetween(list1 *ListNode, a int, b int, list2 *ListNode) *ListNode {
if list1 == nil {
return list2
}
list2Head, list2Tail := list2, list2
for list2 != nil {
list2Tail = list2
list2 = list2.Next
}
count := 0
list1Head := list1
for list1 != nil {
next := list1.Next
if count == a - 1 {
list1.Next = list2Head
} else if count == b {
list2Tail.Next = list1.Next
}
list1 = next
count++
}
return list1Head
}
4.7.1091 - 2024-03-20 21:13:36 +0300 MSK
Links
Code
func leastInterval(tasks []byte, n int) int {
if n == 0 {
return len(tasks)
}
cnt := make([]int, 26)
for _, task := range tasks {
cnt[task - 'A']++
}
var maxCount, sameMaxCount int
for _, c := range cnt {
if c > maxCount {
maxCount = c
sameMaxCount = 1
} else if c == maxCount {
sameMaxCount++
}
}
res := (n + 1) * (maxCount - 1) + sameMaxCount
if (res > len(tasks)) {
return res
} else {
return len(tasks)
}
}
4.7.1092 - 2024-03-20 21:12:54 +0300 MSK
Links
Code
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func mergeInBetween(list1 *ListNode, a int, b int, list2 *ListNode) *ListNode {
l := list1
for i := 1; i <= a - 1; i++ {
l = l.Next
}
prev := l
r := l
for i := a; i <= b + 1; i++ {
r = r.Next
prev.Next = nil
prev = r
}
list2Tail := list2
for list2Tail.Next != nil {
list2Tail = list2Tail.Next
}
l.Next = list2
list2Tail.Next = r
return list1
}
4.7.1093 - 2024-03-18 19:30:56 +0300 MSK
Links
Code
func findMinArrowShots(points [][]int) int {
// Sort the balloons based on their end coordinates
sort.Slice(points, func(i, j int) bool {
return points[i][1] < points[j][1]
})
arrows := 1
prevEnd := points[0][1]
// Count the number of non-overlapping intervals
for i := 1; i < len(points); i++ {
if points[i][0] > prevEnd {
arrows++
prevEnd = points[i][1]
}
}
return arrows
}
4.7.1094 - 2024-03-17 12:32:47 +0300 MSK
Links
Code
func findMaxLength(nums []int) int {
hashmap := make(map[int]int)
zeros, ones, maxLen := 0, 0, 0
hashmap[0] = -1
for i, num := range nums {
if num == 0 {
zeros++
} else {
ones++
}
diff := zeros - ones
if val, ok := hashmap[diff]; ok {
maxLen = max(maxLen, i - val)
} else {
hashmap[diff] = i
}
}
return maxLen
}
4.7.1095 - 2024-03-17 12:32:06 +0300 MSK
Links
Code
func insert(intervals [][]int, newInterval []int) [][]int {
var result [][]int
// Iterate through intervals and add non-overlapping intervals before newInterval
i := 0
for i < len(intervals) && intervals[i][1] < newInterval[0] {
result = append(result, intervals[i])
i++
}
// Merge overlapping intervals
for i < len(intervals) && intervals[i][0] <= newInterval[1] {
newInterval[0] = int(math.Min(float64(newInterval[0]), float64(intervals[i][0])))
newInterval[1] = int(math.Max(float64(newInterval[1]), float64(intervals[i][1])))
i++
}
// Add merged newInterval
result = append(result, newInterval)
// Add non-overlapping intervals after newInterval
for i < len(intervals) {
result = append(result, intervals[i])
i++
}
return result
}
4.7.1096 - 2024-03-15 20:15:18 +0300 MSK
Links
Code
func productExceptSelf(nums []int) []int {
n := len(nums)
res := make([]int, n)
preProduct := 1
for i := 0; i < n; i++ {
res[i] = preProduct
preProduct *= nums[i]
}
sufProduct := 1
for i := n - 1; i >= 0; i-- {
res[i] *= sufProduct
sufProduct *= nums[i]
}
return res
}
4.7.1097 - 2024-03-14 19:06:22 +0300 MSK
Links
Code
func numSubarraysWithSum(nums []int, goal int) int {
hashmap := make(map[int]int)
hashmap[0] = 1
sum := 0
count := 0
for _, num := range nums {
sum += num
rem := sum - goal
if val, ok := hashmap[rem]; ok {
count += val
}
hashmap[sum]++
}
return count
}
4.7.1098 - 2024-03-13 19:53:19 +0300 MSK
Links
Code
func getSum(x int) int {
return x * (x + 1) / 2
}
func pivotInteger(n int) int {
sum := getSum(n)
l, r := 1, n
for l <= r {
m := (l + r) / 2
firstPart := getSum(m)
secondPart := sum - firstPart + m
if firstPart == secondPart {
return m
} else if firstPart > secondPart {
r = m - 1
} else {
l = m + 1
}
}
return -1
}
4.7.1099 - 2024-03-12 19:08:41 +0300 MSK
Links
Code
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func removeZeroSumSublists(head *ListNode) *ListNode {
dummy := &ListNode{0, head}
prefixSumToNode := make(map[int]*ListNode)
prefixSum := 0
for current := dummy; current != nil; current = current.Next {
prefixSum += current.Val
if prev, found := prefixSumToNode[prefixSum]; found {
toRemove := prev.Next
p := prefixSum
if toRemove != nil {
p += toRemove.Val
}
for toRemove != nil && p != prefixSum {
delete(prefixSumToNode, p)
toRemove = toRemove.Next
if toRemove != nil {
p += toRemove.Val
}
}
prev.Next = current.Next
} else {
prefixSumToNode[prefixSum] = current
}
}
return dummy.Next
}
4.7.1100 - 2024-03-11 19:30:24 +0300 MSK
Links
Code
func customSortString(order string, s string) string {
count := make([]int, 26)
for _, c := range s {
count[c-'a']++
}
var result strings.Builder
for _, c := range order {
result.WriteString(strings.Repeat(string(c), count[c-'a']))
count[c-'a'] = 0
}
for i := 0; i < 26; i++ {
result.WriteString(strings.Repeat(string('a'+i), count[i]))
}
// UPVOTE :)
return result.String()
}
4.7.1101 - 2024-03-10 22:58:44 +0300 MSK
Links
Code
func intersection(nums1 []int, nums2 []int) []int {
seen := make([]int, 1000)
for i := range nums1 {
seen[nums1[i]]++
}
res := make([]int, 0)
for i := range nums2 {
if seen[nums2[i]] > 0 {
res = append(res, nums2[i])
seen[nums2[i]] = 0
}
}
return res
}
4.7.1102 - 2024-03-09 19:01:11 +0300 MSK
Links
Code
func maxFrequencyElements(nums []int) int {
mapCount := make(map[int]int)
for _, val := range nums {
mapCount[val]++
}
count := 0
max := -1
for _, freq := range mapCount {
if freq > max {
max = freq
}
}
for _, freq := range mapCount {
if freq == max {
count += max
}
}
return count
}
4.7.1103 - 2024-03-09 18:59:53 +0300 MSK
Links
Code
func getCommon(nums1 []int, nums2 []int) int {
var l, r int
for l < len(nums1) && r < len(nums2) {
switch {
case nums1[l] == nums2[r]:
return nums1[l]
case nums1[l] < nums2[r]:
l++
default:
r++
}
}
return -1
}
4.7.1104 - 2024-03-07 19:08:46 +0300 MSK
Links
Code
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func middleNode(head *ListNode) *ListNode {
if head.Next == nil {
return head
}
slow, fast := head, head.Next
move := true
for fast.Next != nil {
if move {
slow = slow.Next
move = false
} else {
move = true
}
fast = fast.Next
}
if move {
return slow.Next
}
return slow
}
4.7.1105 - 2024-03-07 19:07:46 +0300 MSK
Links
Code
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func middleNode(head *ListNode) *ListNode {
if head.Next == nil {
return head
}
slow, fast := head, head.Next
move := true
for fast.Next != nil {
if move {
slow = slow.Next
move = false
} else {
move = true
}
fast = fast.Next
}
if move {
slow = slow.Next
}
return slow
}
4.7.1106 - 2024-03-06 16:05:23 +0300 MSK
Links
Code
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func hasCycle(head *ListNode) bool {
nodes := map[*ListNode]struct{}{}
for head != nil {
if _, ok := nodes[head]; ok {
return true
}
nodes[head] = struct{}{}
head = head.Next
}
return false
}
4.7.1107 - 2024-03-05 11:52:38 +0300 MSK
Links
Code
func minimumLength(s string) int {
left := 0
right := len(s) - 1
for left < right {
lc := s[left]
rc := s[right]
if lc != rc {
return right - left + 1
}
for left + 1 < right && lc == s[left + 1] {
left++
}
for left < right - 1 && rc == s[right - 1] {
right--
}
right--
left++
}
return right - left + 1
}
4.7.1108 - 2024-03-04 16:21:41 +0300 MSK
Links
Code
func bagOfTokensScore(tokens []int, power int) int {
n := len(tokens)
sort.Ints(tokens)
res := 0
l := 0
r := n - 1
for l <= r {
for l <= r && power >= tokens[l] {
power -= tokens[l]
l++
res++
}
if res == 0 {
break
}
if r - l + 1 <= 2 {
break
}
power += tokens[r]
r--
res--
}
return res
}
4.7.1109 - 2024-03-03 10:57:46 +0300 MSK
Links
Code
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func removeNthFromEnd(head *ListNode, n int) *ListNode {
res := &ListNode{0, head}
lead := res
for i := 0; i <= n; i++ {
lead = lead.Next
}
cur := res
for lead != nil {
cur = cur.Next
lead = lead.Next
}
cur.Next = cur.Next.Next
return res.Next
}
4.7.1110 - 2024-03-02 15:59:13 +0300 MSK
Links
Code
func sortedSquares(nums []int) []int {
for i, num := range nums {
if num < 0 {
nums[i] = -num
} else {
break
}
}
slices.Sort(nums)
for i, num := range nums {
nums[i] = num * num
}
return nums
}
4.7.1111 - 2024-03-02 15:57:16 +0300 MSK
Links
Code
func sortedSquares(nums []int) []int {
for i, num := range nums {
nums[i] = num * num
}
slices.Sort(nums)
return nums
}
4.7.1112 - 2024-03-02 15:56:40 +0300 MSK
Links
Code
func sortedSquares(nums []int) []int {
for i, num := range nums {
if num < 0 {
nums[i] = -num
}
}
slices.Sort(nums)
for i, num := range nums {
nums[i] = num * num
}
return nums
}
4.7.1113 - 2024-03-01 18:28:31 +0300 MSK
Links
Code
func maximumOddBinaryNumber(s string) string {
l := len(s)
res := make([]byte, l)
index0, index1 := l-2, l-1
for i := 0; i < l; i++ {
if s[i] == '0' {
res[index0] = '0'
index0--
} else {
res[index1] = '1'
index1 = (index1 + 1) % l
}
}
return string(res)
}
4.7.1114 - 2024-02-29 17:38:44 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func isEvenOddTree(root *TreeNode) bool {
q := []*TreeNode{root}
for i:= 0; len(q) > 0; i++ {
var prev *TreeNode
for _, node := range q {
q = q[1:]
if i % 2 == 0 && node.Val % 2 != 1 {
return false
}
if i % 2 == 1 && node.Val % 2 != 0 {
return false
}
if prev != nil && i % 2 == 0 && prev.Val >= node.Val {
return false
}
if prev != nil && i % 2 == 1 && prev.Val <= node.Val {
return false
}
prev = node
if node.Left != nil {
q = append(q, node.Left)
}
if node.Right != nil {
q = append(q, node.Right)
}
}
}
return true
}
4.7.1115 - 2024-02-28 12:31:13 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func findBottomLeftValue(root *TreeNode) int {
_, val := getBottomLeft(root)
return val
}
func getBottomLeft(root *TreeNode) (int, int) {
left, right := root.Left, root.Right
if right == nil && left == nil {
return 0, root.Val
}
if right == nil {
depth, val := getBottomLeft(root.Left)
return 1 + depth, val
}
if left == nil {
depth, val := getBottomLeft(root.Right)
return 1 + depth, val
}
leftDepth, leftVal := getBottomLeft(root.Left)
rightDepth, rightVal := getBottomLeft(root.Right)
if rightDepth > leftDepth {
return 1 + rightDepth, rightVal
}
return 1 + leftDepth, leftVal
}
4.7.1116 - 2024-02-27 19:25:53 +0300 MSK
Links
Code
var maxD int
func diameterOfBinaryTree(root *TreeNode) int {
maxD = 0
find(root)
return maxD
}
func find(root *TreeNode) int {
if root == nil {
return 0
}
left := find(root.Left)
right := find(root.Right)
localMax := left + right
maxD = max(maxD, localMax)
return max(left, right) + 1
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
4.7.1117 - 2024-02-26 19:57:46 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func isSameTree(p *TreeNode, q *TreeNode) bool {
if p == nil && q == nil {
return true
}
if p == nil || q == nil || p.Val != q.Val {
return false
}
return isSameTree(p.Left, q.Left) && isSameTree(p.Right, q.Right)
}
4.7.1118 - 2024-02-25 20:04:05 +0300 MSK
Links
Code
func canTraverseAllPairs(nums []int) bool {
if len(nums) == 1 {
return true
}
n := len(nums)
maxElement := nums[0]
minElement := nums[0]
for _, num := range nums {
if num > maxElement {
maxElement = num
}
if num < minElement {
minElement = num
}
}
if minElement == 1 {
return false
}
factorArray := factorsCalculator(maxElement)
parent := make([]int, maxElement+1)
rank := make([]int, maxElement+1)
for i := 0; i <= maxElement; i++ {
parent[i] = i
rank[i] = 1
}
for _, num := range nums {
x := num
for x > 1 {
p := factorArray[x]
union(parent, rank, p, num)
for x%p == 0 {
x = x / p
}
}
}
p := find(parent, nums[0])
for i := 1; i < n; i++ {
if find(parent, nums[i]) != p {
return false
}
}
return true
}
func factorsCalculator(n int) []int {
dp := make([]int, n+2)
for i := 0; i < len(dp); i++ {
dp[i] = i
}
for i := 2; i <= n; i++ {
if dp[i] == i {
for j := i * 2; j <= n; j += i {
if dp[j] == j {
dp[j] = i
}
}
}
}
return dp
}
func find(parent []int, a int) int {
if parent[a] == a {
return a
}
parent[a] = find(parent, parent[a])
return parent[a]
}
func union(parent []int, rank []int, a int, b int) {
a = find(parent, a)
b = find(parent, b)
if a == b {
return
}
if rank[a] < rank[b] {
a, b = b, a
}
parent[b] = a
rank[a] += rank[b]
}
4.7.1119 - 2024-02-24 15:45:37 +0300 MSK
Links
Code
package main
import (
"sort"
)
func find(groups []int, index int) int {
for index != groups[index] {
index = groups[index]
}
return index
}
func findAllPeople(n int, meetings [][]int, firstPerson int) []int {
groups := make([]int, 100000)
var result []int
var temp []int
for i := 0; i < n; i++ {
groups[i] = i
}
groups[firstPerson] = 0
sort.Slice(meetings, func(i, j int) bool {
return meetings[i][2] < meetings[j][2]
})
i := 0
for i < len(meetings) {
currentTime := meetings[i][2]
temp = temp[:0]
for i < len(meetings) && meetings[i][2] == currentTime {
g1 := find(groups, meetings[i][0])
g2 := find(groups, meetings[i][1])
groups[max(g1, g2)] = min(g1, g2)
temp = append(temp, meetings[i][0], meetings[i][1])
i++
}
for _, j := range temp {
if find(groups, j) != 0 {
groups[j] = j
}
}
}
for j := 0; j < n; j++ {
if find(groups, j) == 0 {
result = append(result, j)
}
}
return result
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
4.7.1120 - 2024-02-23 12:30:25 +0300 MSK
Links
Code
type Connection struct {
city int
cost int
}
type queue []Connection
func (q *queue) push(c Connection) {
q1 := []Connection{c}
*q = append(*q, q1...)
}
func (q *queue) pop() (bool, Connection) {
if q.isEmpty() {
return false, Connection{}
} else {
elem := (*q)[0]
*q = (*q)[1:]
return true, elem
}
}
func (q queue) isEmpty() bool {
return q.size() <= 0
}
func (q queue) size() int {
return len(q)
}
func findCheapestPrice(n int, flights [][]int, src int, dst int, k int) int {
minCost := math.MaxInt64
fQueue := new(queue)
fQueue.push(Connection{src, 0})
maxStops := k + 1
costOfFlights := make([][]int, n)
for i := range costOfFlights {
costOfFlights[i] = make([]int, n)
}
flightsMap := make(map[int][]int)
for _, v := range flights {
if _, ok := flightsMap[v[0]]; ok {
flightsMap[v[0]] = append(flightsMap[v[0]], v[1])
} else {
flightsMap[v[0]] = []int{v[1]}
}
costOfFlights[v[0]][v[1]] = v[2]
}
cityPathCost := make([]int, n) // path cost from source
for i := range cityPathCost {
cityPathCost[i] = math.MaxInt64
}
cityPathCost[src] = 0
for !fQueue.isEmpty() && maxStops >= 0 {
size := fQueue.size()
maxStops--
for size > 0 {
_, c := fQueue.pop()
size--
if c.city == dst {
if minCost > c.cost {
minCost = c.cost
}
continue
}
for _, v := range flightsMap[c.city] {
newCost := c.cost + costOfFlights[c.city][v]
if cityPathCost[v] > newCost {
fQueue.push(Connection{v, newCost})
cityPathCost[v] = newCost
}
}
}
}
if minCost == math.MaxInt64 {
minCost = -1
}
return minCost
}
4.7.1121 - 2024-02-22 11:20:36 +0300 MSK
Links
Code
func findJudge(n int, trust [][]int) int {
fromTo := make([][]int, n)
toFrom := make([][]int, n)
for _, trustArray := range trust {
from, to := trustArray[0], trustArray[1]
fromTo[from-1] = append(fromTo[from-1], to)
toFrom[to-1] = append(toFrom[to-1], from)
}
for i, from := range toFrom {
if len(from) == n - 1 && len(fromTo[i]) == 0 {
return i + 1
}
}
return -1
}
4.7.1122 - 2024-02-21 11:42:07 +0300 MSK
Links
Code
class Solution:
def rangeBitwiseAnd(self, left: int, right: int) -> int:
shift = 0
while left != right:
left >>= 1
right >>= 1
shift += 1
return left << shift
4.7.1123 - 2024-02-20 18:21:21 +0300 MSK
Links
Code
import operator
class Solution:
def missingNumber(self, nums: List[int]) -> int:
return reduce(
operator.xor,
nums,
reduce(operator.xor, tuple(range(len(nums) + 1)), 0)
)
4.7.1124 - 2024-02-20 18:19:05 +0300 MSK
Links
Code
import operator
class Solution:
def missingNumber(self, nums: List[int]) -> int:
nums.extend(range(len(nums) + 1))
return reduce(operator.xor, nums, 0)
4.7.1125 - 2024-02-20 18:16:37 +0300 MSK
Links
Code
import operator
class Solution:
def missingNumber(self, nums: List[int]) -> int:
length = len(nums)
return reduce(operator.xor, range(length), reduce(operator.xor, nums, length))
4.7.1126 - 2024-02-20 15:10:36 +0300 MSK
Links
Code
class Solution:
def missingNumber(self, nums: List[int]) -> int:
def xor(total: int, i: int) -> int:
return total ^ nums[i] ^ (i + 1)
return reduce(xor, chain((0, ), range(len(nums))))
4.7.1127 - 2024-02-19 11:56:55 +0300 MSK
Links
Code
class Solution:
def isPowerOfTwo(self, n: int) -> bool:
return n > 0 and n & (n - 1) == 0
4.7.1128 - 2024-02-18 12:45:46 +0300 MSK
Links
Code
class Solution:
def mostBooked(self, n: int, meetings: List[List[int]]) -> int:
unused_rooms, used_rooms = list(range(n)), []
heapify(unused_rooms)
meeting_count = [0] * n
for start, end in sorted(meetings):
while used_rooms and used_rooms[0][0] <= start:
_, room = heappop(used_rooms)
heappush(unused_rooms, room)
if unused_rooms:
room = heappop(unused_rooms)
heappush(used_rooms, [end, room])
else:
room_availability_time, room = heappop(used_rooms)
heappush(
used_rooms,
[room_availability_time + end - start, room]
)
meeting_count[room] += 1
return meeting_count.index(max(meeting_count))
4.7.1129 - 2024-02-17 15:07:38 +0300 MSK
Links
Code
class Solution:
def furthestBuilding(self, heights: List[int], bricks: int, ladders: int) -> int:
heap = []
i = 0
length = len(heights)
for i in range(length - 1):
diff = heights[i + 1] - heights[i]
if diff <= 0:
continue
bricks -= diff
heapq.heappush(heap, -diff)
if bricks < 0:
bricks += -heapq.heappop(heap)
ladders -= 1
if ladders < 0:
return i
return length - 1
4.7.1130 - 2024-02-17 15:03:52 +0300 MSK
Links
Code
class Solution:
def furthestBuilding(self, h: List[int], b: int, l: int) -> int:
p = []
i = 0
for i in range(len(h) - 1):
diff = h[i + 1] - h[i]
if diff <= 0:
continue
b -= diff
x = heapq.heappush(p, -diff)
print(x)
if b < 0:
b += -heapq.heappop(p)
l -= 1
if l < 0:
return i
return len(h)-1
4.7.1131 - 2024-02-16 18:29:09 +0300 MSK
Links
Code
class Solution:
def findLeastNumOfUniqueInts(self, arr: List[int], k: int) -> int:
counter = defaultdict(int)
for num in arr:
counter[num] += 1
nums = [(count, num) for num, count in counter.items()]
nums.sort()
removed = 0
for count, num in nums:
if k < count:
break
k -= count
removed += 1
return len(counter) - removed
4.7.1132 - 2024-02-15 12:51:25 +0300 MSK
Links
Code
class Solution:
def largestPerimeter(self, nums: List[int]) -> int:
nums.sort()
previous_elements_sum = 0
ans = -1
for num in nums:
if num < previous_elements_sum:
ans = num + previous_elements_sum
previous_elements_sum += num
return ans
4.7.1133 - 2024-02-14 10:48:17 +0300 MSK
Links
Code
class Solution:
def rearrangeArray(self, nums: List[int]) -> List[int]:
res = []
pos, neg = [], []
length = len(nums)
for i in range(length):
num = nums[i]
if num > 0:
pos.append(num)
else:
neg.append(num)
pos.reverse()
neg.reverse()
while pos and neg:
res.extend((pos.pop(), neg.pop()))
return res
4.7.1134 - 2024-02-13 16:10:55 +0300 MSK
Links
Code
class Solution:
def firstPalindrome(self, words: List[str]) -> str:
for s in words:
for i in range(len(s) // 2):
if s[i] != s[-i - 1]:
break
else:
return s
return ""
4.7.1135 - 2024-02-12 12:50:44 +0300 MSK
Links
Code
class Solution:
def majorityElement(self, nums: List[int]) -> int:
counter = defaultdict(int)
half = len(nums) // 2
for num in nums:
counter[num] += 1
if counter[num] > half:
return num
raise Exception()
4.7.1136 - 2024-02-11 16:20:27 +0300 MSK
Links
Code
class Solution:
def cherryPickup(self, grid: List[List[int]]) -> int:
n = len(grid)
m = len(grid[0])
# Create 3D DP table with initial values of 0
dp = [[[0] * m for _ in range(m)] for _ in range(n)]
# Set the starting point value (top-left and top-right corner)
cherries = 0
dp[0][0][m - 1] = grid[0][0] + grid[0][m - 1]
# Iterate through each row from second onwards
for i in range(1, n):
# Iterate through each column for robot 1
for j in range(m):
# Iterate through each column for robot 2
for k in range(m):
# Skip invalid states:
# - Both robots in the same row (j > i)
# - Robot 2 left of robot 1 (k < m - i - 1)
# - Robot 1 further right than robot 2 (j > k)
if j > i or k < m - i - 1 or j > k:
continue
# Base case: no moves possible, use previous state
dp[i][j][k] = dp[i - 1][j][k]
# Explore moves for robot 1:
# - Up-diagonal with robot 2 at same position
if j - 1 >= 0:
dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j - 1][k])
# - Up-diagonal with robot 2 one step left/right
if j - 1 >= 0 and k - 1 >= 0:
dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j - 1][k - 1])
if j - 1 >= 0 and k + 1 < m:
dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j - 1][k + 1])
# Explore moves for robot 2:
# - Up-diagonal with robot 1 at same position
if j + 1 < m:
dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j + 1][k])
# - Up-diagonal with robot 1 one step left/right
if j + 1 < m and k - 1 >= 0:
dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j + 1][k - 1])
if j + 1 < m and k + 1 < m:
dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j + 1][k + 1])
# Explore horizontal moves for both robots:
# - Both robots move left
if k - 1 >= 0:
dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j][k - 1])
# - Both robots move right
if k + 1 < m:
dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j][k + 1])
# Add cherries only if robots are in different positions
if j != k:
dp[i][j][k] += grid[i][j] + grid[i][k]
else:
dp[i][j][k] += grid[i][j] # Only one robot picks if they land in the same cell
# Update maximum cherries collected so far
cherries = max(cherries, dp[i][j][k])
return cherries
4.7.1137 - 2024-02-10 15:12:54 +0300 MSK
Links
Code
class Solution:
def countSubstrings(self, s: str) -> int:
n = len(s)
palindrome = [[False] * n for _ in range(n)]
ans = 0
for i in range(n):
palindrome[i][i] = True
ans += 1
for i in range(n - 1):
if s[i] == s[i + 1]:
palindrome[i][i + 1] = True
ans += 1
for length in range(3, n + 1):
for i in range(n - length + 1):
if s[i] == s[i + length - 1] and palindrome[i + 1][i + length - 2]:
palindrome[i][i + length - 1] = True
ans += 1
return ans
4.7.1138 - 2024-02-09 19:12:32 +0300 MSK
Links
Code
class Solution:
def largestDivisibleSubset(self, nums: List[int]) -> List[int]:
nums.sort()
n = len(nums)
dp = [1] * n
max_size, max_index = 1, 0
for i in range(1, n):
for j in range(i):
if nums[i] % nums[j] == 0:
dp[i] = max(dp[i], dp[j] + 1)
if dp[i] > max_size:
max_size = dp[i]
max_index = i
result = []
num = nums[max_index]
for i in range(max_index, -1, -1):
if num % nums[i] == 0 and dp[i] == max_size:
result.append(nums[i])
num = nums[i]
max_size -= 1
return result
4.7.1139 - 2024-02-08 15:50:03 +0300 MSK
Links
Code
class Solution:
def numSquares(self, n: int) -> int:
dp = [float('inf')] * (n + 1)
dp[0] = 0
for i in range(1, n + 1):
min_val = float('inf')
j = 1
while j * j <= i:
min_val = min(min_val, dp[i - j * j] + 1)
j += 1
dp[i] = min_val
return dp[n]
4.7.1140 - 2024-02-07 10:59:44 +0300 MSK
Links
Code
class Solution:
def frequencySort(self, s: str) -> str:
counter = defaultdict(int)
for char in s:
counter[char] += 1
pq = [(-freq, char) for char, freq in counter.items()]
heapq.heapify(pq)
result = []
while pq:
freq, char = heapq.heappop(pq)
result.append(char * -freq)
return "".join(result)
4.7.1141 - 2024-02-07 10:54:21 +0300 MSK
Links
Code
class Solution:
def frequencySort(self, s: str) -> str:
counter = {}
for char in s:
if char not in counter:
counter[char] = -ord(char)
counter[char] -= 100
return "".join(sorted(s, key=lambda val: counter[val]))
4.7.1142 - 2024-02-07 10:52:55 +0300 MSK
Links
Code
class Solution:
def frequencySort(self, s: str) -> str:
counter = {}
for char in s:
if char not in counter:
counter[char] = ord(char)
counter[char] += 100
return "".join(sorted(s, key=lambda val: -counter[val]))
4.7.1143 - 2024-02-07 10:49:08 +0300 MSK
Links
Code
class Solution:
def frequencySort(self, s: str) -> str:
counter = defaultdict(int)
for char in s:
counter[char] += 1
return "".join(sorted(s, key=lambda val: -(ord(val) + counter[val] * 100)))
4.7.1144 - 2024-02-06 09:02:52 +0300 MSK
Links
Code
class Solution:
def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
anagrams = defaultdict(list)
for anagram in strs:
anagrams[tuple(sorted(anagram))].append(anagram)
return anagrams.values()
4.7.1145 - 2024-02-05 10:12:58 +0300 MSK
Links
Code
class Solution:
def firstUniqChar(self, s: str) -> int:
counter = [0] * 26
for char in s:
idx = ord(char) - ord('a')
if counter[idx] in (0, 1):
counter[idx] += 1
for i in range(len(s)):
if counter[ord(s[i]) - ord('a')] == 1:
return i
return -1
4.7.1146 - 2024-02-04 15:38:07 +0300 MSK
Links
Code
class Solution:
def maxSumAfterPartitioning(self, arr: List[int], k: int) -> int:
min_num = -1
length = len(arr)
last_idx = length - 1
cache = [-1] * length
def dp(start: int) -> int:
cached = cache[start]
if cached != -1:
return cached
max_num = min_num
max_sum = 0
for i in range(start, min(start + k, length)):
max_num = max(max_num, arr[i])
cur_sum = max_num * (i - start + 1)
if i != last_idx:
cur_sum += dp(i + 1)
max_sum = max(max_sum, cur_sum)
cache[start] = max_sum
return max_sum
return dp(0)
4.7.1147 - 2024-02-04 15:17:08 +0300 MSK
Links
Code
class Solution:
def minWindow(self, s: str, t: str) -> str:
if not s or not t:
return ""
dictT = defaultdict(int)
for c in t:
dictT[c] += 1
required = len(dictT)
l, r = 0, 0
formed = 0
windowCounts = defaultdict(int)
ans = [-1, 0, 0]
while r < len(s):
c = s[r]
windowCounts[c] += 1
if c in dictT and windowCounts[c] == dictT[c]:
formed += 1
while l <= r and formed == required:
c = s[l]
if ans[0] == -1 or r - l + 1 < ans[0]:
ans[0] = r - l + 1
ans[1] = l
ans[2] = r
windowCounts[c] -= 1
if c in dictT and windowCounts[c] < dictT[c]:
formed -= 1
l += 1
r += 1
return "" if ans[0] == -1 else s[ans[1]:ans[2] + 1]
4.7.1148 - 2024-02-02 19:53:06 +0300 MSK
Links
Code
class Solution:
def divideArray(self, nums, k):
size = len(nums)
if size % 3 != 0:
return []
nums.sort()
result = []
group_index = 0
for i in range(0, size, 3):
if i + 2 < size and nums[i + 2] - nums[i] <= k:
result.append([nums[i], nums[i + 1], nums[i + 2]])
group_index += 1
else:
return []
return result
4.7.1149 - 2024-02-02 19:52:11 +0300 MSK
Links
Code
class Solution:
def divideArray(self, nums, k):
size = len(nums)
if size % 3 != 0:
return []
nums.sort()
result = []
group_index = 0
for i in range(0, size, 3):
if i + 2 < size and nums[i + 2] - nums[i] <= k:
result.append([nums[i], nums[i + 1], nums[i + 2]])
group_index += 1
else:
return []
return result
4.7.1150 - 2024-02-02 19:51:07 +0300 MSK
Links
Code
class Solution:
def sequentialDigits(self, low, high):
a = []
for i in range(1, 10):
num = i
next_digit = i + 1
while num <= high and next_digit <= 9:
num = num * 10 + next_digit
if low <= num <= high:
a.append(num)
next_digit += 1
a.sort()
return a
4.7.1151 - 2024-01-31 11:09:51 +0300 MSK
Links
Code
class Solution:
def dailyTemperatures(self, temperatures: List[int]) -> List[int]:
temps_left = defaultdict(list)
to_pop = []
length = len(temperatures)
ans = [0] * length
for i in range(length):
temp = temperatures[i]
for temp_left, ids in temps_left.items():
if temp <= temp_left:
continue
for id in ids:
ans[id] = i - id
to_pop.append(temp_left)
temps_left[temp].append(i)
for temp in to_pop:
temps_left.pop(temp)
to_pop.clear()
return ans
4.7.1152 - 2024-01-30 15:36:53 +0300 MSK
Links
Code
class Solution:
def evalRPN(self, tokens: List[str]) -> int:
stack: list[int] = []
for token in tokens:
match token:
case "+":
stack.append(stack.pop() + stack.pop())
case "-":
last, prev = stack.pop(), stack.pop()
stack.append(prev - last)
case "*":
stack.append(stack.pop() * stack.pop())
case "/":
last, prev = stack.pop(), stack.pop()
stack.append(int(prev / last))
case _:
stack.append(int(token))
return stack[0]
4.7.1153 - 2024-01-29 09:44:33 +0300 MSK
Links
Code
class MyQueue:
def __init__(self):
self.stack_in = []
self.stack_out = []
def push(self, x: int) -> None:
self.stack_in.append(x)
def pop(self) -> int:
self.peek()
return self.stack_out.pop()
def peek(self) -> int:
if self.stack_out:
return self.stack_out[-1]
while self.stack_in:
self.stack_out.append(self.stack_in.pop())
return self.stack_out[-1]
def empty(self) -> bool:
return not self.stack_out and not self.stack_in
# Your MyQueue object will be instantiated and called as such:
# obj = MyQueue()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.peek()
# param_4 = obj.empty()
4.7.1154 - 2024-01-28 13:34:03 +0300 MSK
Links
Code
class Solution:
def numSubmatrixSumTarget(self, matrix, target):
m, n = len(matrix), len(matrix[0])
for row in range(m):
for col in range(1, n):
matrix[row][col] += matrix[row][col - 1]
count = 0
for c1 in range(n):
for c2 in range(c1, n):
prefix_sum_count = {0: 1}
sum_val = 0
for row in range(m):
sum_val += matrix[row][c2] - (matrix[row][c1 - 1] if c1 > 0 else 0)
count += prefix_sum_count.get(sum_val - target, 0)
prefix_sum_count[sum_val] = prefix_sum_count.get(sum_val, 0) + 1
return count
4.7.1155 - 2024-01-27 10:05:52 +0300 MSK
Links
Code
class Solution:
def kInversePairs(self, n: int, k: int) -> int:
MOD = 10**9 + 7
dp = [[0] * (k + 1) for _ in range(n + 1)]
for i in range(1, n + 1):
for j in range(k + 1):
if j == 0:
dp[i][j] = 1
else:
val = (dp[i - 1][j] + MOD - (dp[i - 1][j - i] if j - i >= 0 else 0)) % MOD
dp[i][j] = (dp[i][j - 1] + val) % MOD
return (dp[n][k] + MOD - (dp[n][k - 1] if k > 0 else 0)) % MOD
4.7.1156 - 2024-01-26 11:02:15 +0300 MSK
Links
Code
class Solution:
def findPaths(self, m: int, n: int, N: int, x: int, y: int) -> int:
M = 1000000000 + 7
dp = [[0] * n for _ in range(m)]
dp[x][y] = 1
count = 0
for moves in range(1, N + 1):
temp = [[0] * n for _ in range(m)]
for i in range(m):
for j in range(n):
if i == m - 1:
count = (count + dp[i][j]) % M
if j == n - 1:
count = (count + dp[i][j]) % M
if i == 0:
count = (count + dp[i][j]) % M
if j == 0:
count = (count + dp[i][j]) % M
temp[i][j] = (
((dp[i - 1][j] if i > 0 else 0) + (dp[i + 1][j] if i < m - 1 else 0)) % M +
((dp[i][j - 1] if j > 0 else 0) + (dp[i][j + 1] if j < n - 1 else 0)) % M
) % M
dp = temp
return count
4.7.1157 - 2024-01-25 17:31:23 +0300 MSK
Links
Code
class Solution:
def longestCommonSubsequence(self, text1: str, text2: str) -> int:
# Get the lengths of both input strings
len_text1, len_text2 = len(text1), len(text2)
# Initialize a 2D array (list of lists) with zeros for dynamic programming
# The array has (len_text1 + 1) rows and (len_text2 + 1) columns
dp_matrix = [[0] * (len_text2 + 1) for _ in range(len_text1 + 1)]
# Loop through each character index of text1 and text2
for i in range(1, len_text1 + 1):
for j in range(1, len_text2 + 1):
# If the characters match, take the diagonal value and add 1
if text1[i - 1] == text2[j - 1]:
dp_matrix[i][j] = dp_matrix[i - 1][j - 1] + 1
else:
# If the characters do not match, take the maximum of the value from the left and above
dp_matrix[i][j] = max(dp_matrix[i - 1][j], dp_matrix[i][j - 1])
# The bottom-right value in the matrix contains the length of the longest common subsequence
return dp_matrix[len_text1][len_text2]
4.7.1158 - 2024-01-24 10:39:27 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def pseudoPalindromicPaths (self, root: Optional[TreeNode]) -> int:
if not root:
return 0
num_count = defaultdict(int)
perm_count = 0
def traverse(node: TreeNode) -> int:
val, left, right = node.val, node.left, node.right
num_count[val] += 1
res = 0
if not left and not right:
non_even = 0
for num in num_count.values():
if num % 2 == 0:
continue
if non_even == 1:
break
non_even += 1
else:
res += 1
if left:
res += traverse(left)
if right:
res += traverse(right)
num_count[val] = max(0, num_count[val] - 1)
return res
return traverse(root)
4.7.1159 - 2024-01-24 10:27:08 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def pseudoPalindromicPaths (self, root: Optional[TreeNode]) -> int:
if not root:
return 0
num_count = defaultdict(int)
perm_count = 0
def traverse(node: TreeNode) -> int:
if not node:
return 0
val, left, right = node.val, node.left, node.right
num_count[val] += 1
res = 0
if not left and not right:
non_even = 0
for num in num_count.values():
if num % 2 == 0:
continue
non_even += 1
if non_even > 1:
break
else:
res += 1
res += traverse(left) + traverse(right)
num_count[val] = max(0, num_count[val] - 1)
return res
return traverse(root)
4.7.1160 - 2024-01-23 10:54:38 +0300 MSK
Links
Code
class Solution:
def maxLength(self, arr: List[str]) -> int:
cur = set()
length = len(arr)
max_length = 0
def backtrack(start: int) -> None:
nonlocal max_length
for i in range(start, length):
new_subs = arr[i]
new = set(new_subs)
if len(new_subs) != len(new) or len(cur.intersection(new)) != 0:
continue
cur.update(new)
backtrack(i + 1)
cur.difference_update(new)
max_length = max(max_length, len(cur))
backtrack(0)
return max_length
4.7.1161 - 2024-01-22 12:39:06 +0300 MSK
Links
Code
class Solution:
def findErrorNums(self, nums: List[int]) -> List[int]:
length = len(nums)
# dupl_xor_miss = duplicate ^ missing
dupl_xor_miss = reduce(lambda total, i: total ^ i ^ nums[i - 1], range(length + 1))
rightmost_set_bit = dupl_xor_miss & -dupl_xor_miss
xor_group1 = xor_group2 = 0
for i in range(1, length + 1):
if i & rightmost_set_bit:
xor_group1 ^= i
else:
xor_group2 ^= i
if nums[i - 1] & rightmost_set_bit:
xor_group1 ^= nums[i - 1]
else:
xor_group2 ^= nums[i - 1]
for num in nums:
if num == xor_group1:
return num, xor_group2
if num == xor_group2:
return num, xor_group1
raise Exception()
4.7.1162 - 2024-01-21 21:12:22 +0300 MSK
Links
Code
class Solution:
def rob(self, nums: List[int]) -> int:
length = len(nums)
cache = {}
def dp(i: int) -> int:
if i >= length:
return 0
val = nums[i]
if i in cache:
return cache[i]
res = max(dp(i + 1), val + dp(i + 2))
cache[i] = res
return res
return dp(0)
4.7.1163 - 2024-01-20 17:21:44 +0300 MSK
Links
Code
class Solution:
def sumSubarrayMins(self, arr: List[int]) -> int:
n = len(arr)
left = [-1] * n
right = [n] * n
stack = []
for i, value in enumerate(arr):
while stack and arr[stack[-1]] >= value:
stack.pop()
if stack:
left[i] = stack[-1]
stack.append(i)
stack = []
for i in range(n - 1, -1, -1):
while stack and arr[stack[-1]] > arr[i]:
stack.pop()
if stack:
right[i] = stack[-1]
stack.append(i)
mod = 10**9 + 7
result = sum((i - left[i]) * (right[i] - i) * value for i, value in enumerate(arr)) % mod
return result
4.7.1164 - 2024-01-19 11:46:22 +0300 MSK
Links
Code
class Solution:
def minFallingPathSum(self, matrix: List[List[int]]) -> int:
length = len(matrix)
cache = {}
deltas = ((1, 0), (1, 1), (1, -1))
last_row = length - 1
def dp(row: int, col: int) -> int:
if (row, col) in cache:
return cache[(row, col)]
val = matrix[row][col]
if row == last_row:
return val
min_cost = None
for delta_row, delta_col in deltas:
new_row, new_col = row + delta_row, col + delta_col
if new_col == length or new_col == -1:
continue
cost = dp(new_row, new_col)
min_cost = cost if min_cost is None else min(min_cost, cost)
res = val + min_cost
cache[(row, col)] = res
return res
return min(dp(0, col) for col in range(length))
4.7.1165 - 2024-01-19 11:45:33 +0300 MSK
Links
Code
class Solution:
def minFallingPathSum(self, matrix: List[List[int]]) -> int:
length = len(matrix)
max_val = 101 * length * length
cache = {}
deltas = ((1, 0), (1, 1), (1, -1))
last_row = length - 1
def dp(row: int, col: int) -> int:
if (row, col) in cache:
return cache[(row, col)]
val = matrix[row][col]
if row == last_row:
return val
min_cost = max_val
for delta_row, delta_col in deltas:
new_row, new_col = row + delta_row, col + delta_col
if new_col == length or new_col == -1:
continue
cost = dp(new_row, new_col)
min_cost = min(min_cost, cost)
res = val + min_cost
cache[(row, col)] = res
return res
return min(dp(0, col) for col in range(length))
4.7.1166 - 2024-01-18 13:27:10 +0300 MSK
Links
Code
class Solution:
def climbStairs(self, n: int) -> int:
prev, cur = 1, 2
if n == prev:
return prev
if n == cur:
return cur
for i in range(2, n):
new = prev + cur
cur, prev = new, cur
return cur
4.7.1167 - 2024-01-17 19:14:04 +0300 MSK
Links
Code
class Solution:
def uniqueOccurrences(self, arr: List[int]) -> bool:
counts = defaultdict(int)
for num in arr:
counts[num] += 1
viewed = set()
for _, count in counts.items():
if count in viewed:
return False
viewed.add(count)
return True
4.7.1168 - 2024-01-16 11:04:01 +0300 MSK
Links
Code
import random
class RandomizedSet:
def __init__(self):
self._nums_map = {}
self._nums = []
def insert(self, val: int) -> bool:
if val in self._nums_map:
return False
self._nums_map[val] = len(self._nums)
self._nums.append(val)
return True
def remove(self, val: int) -> bool:
if val not in self._nums_map:
return False
last = self._nums[-1]
idx = self._nums_map[val]
self._nums_map[last] = idx
self._nums[idx] = last
self._nums.pop()
self._nums_map.pop(val)
return True
def getRandom(self) -> int:
return random.choice(self._nums)
# Your RandomizedSet object will be instantiated and called as such:
# obj = RandomizedSet()
# param_1 = obj.insert(val)
# param_2 = obj.remove(val)
# param_3 = obj.getRandom()
4.7.1169 - 2024-01-15 11:45:13 +0300 MSK
Links
Code
class Solution:
def findWinners(self, matches):
losses = [0] * 100001
for winner, loser in matches:
if losses[winner] == 0:
losses[winner] = -1
if losses[loser] == -1:
losses[loser] = 1
else:
losses[loser] += 1
zero_loss = [i for i in range(1, 100001) if losses[i] == -1]
one_loss = [i for i in range(1, 100001) if losses[i] == 1]
return [zero_loss, one_loss]
4.7.1170 - 2024-01-14 17:27:29 +0300 MSK
Links
Code
class Solution:
def closeStrings(self, word1: str, word2: str) -> bool:
freq1 = [0] * 26
freq2 = [0] * 26
for ch in word1:
freq1[ord(ch) - ord('a')] += 1
for ch in word2:
freq2[ord(ch) - ord('a')] += 1
for i in range(26):
if (freq1[i] == 0 and freq2[i] != 0) or (freq1[i] != 0 and freq2[i] == 0):
return False
freq1.sort()
freq2.sort()
for i in range(26):
if freq1[i] != freq2[i]:
return False
return True
4.7.1171 - 2024-01-13 17:33:48 +0300 MSK
Links
Code
class Solution:
def minSteps(self, s: str, t: str) -> int:
count_s = [0] * 26
count_t = [0] * 26
for char in s:
count_s[ord(char) - ord('a')] += 1
for char in t:
count_t[ord(char) - ord('a')] += 1
steps = 0
for i in range(26):
steps += abs(count_s[i] - count_t[i])
return steps // 2
4.7.1172 - 2024-01-12 23:55:40 +0300 MSK
Links
Code
class Solution:
def halvesAreAlike(self, s: str) -> bool:
def count_vowels(string):
vowels = set('aeiouAEIOU')
return sum(1 for char in string if char in vowels)
length = len(s)
mid_point = length // 2
first_half = s[:mid_point]
second_half = s[mid_point:]
return count_vowels(first_half) == count_vowels(second_half)
4.7.1173 - 2024-01-11 12:15:51 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution(object):
def maxAncestorDiff(self, root):
if not root:
return 0
self.diff = 0
self.helper(root, root.val, root.val)
return self.diff
def helper(self, root, min_val, max_val):
if not root:
return
self.diff = max(self.diff, max(abs(min_val - root.val), abs(max_val - root.val)))
min_val = min(min_val, root.val)
max_val = max(max_val, root.val)
self.helper(root.left, min_val, max_val)
self.helper(root.right, min_val, max_val)
4.7.1174 - 2024-01-10 11:34:26 +0300 MSK
Links
Code
class Solution:
def amountOfTime(self, root: Optional[TreeNode], start: int) -> int:
def dfs(node):
if node is None:
return
if node.left:
graph[node.val].append(node.left.val)
graph[node.left.val].append(node.val)
if node.right:
graph[node.val].append(node.right.val)
graph[node.right.val].append(node.val)
dfs(node.left)
dfs(node.right)
graph = defaultdict(list)
dfs(root)
visited = set()
queue = deque([start])
time = -1
while queue:
time += 1
for _ in range(len(queue)):
current_node = queue.popleft()
visited.add(current_node)
for neighbor in graph[current_node]:
if neighbor not in visited:
queue.append(neighbor)
return time
4.7.1175 - 2024-01-09 19:45:41 +0300 MSK
Links
Code
class Solution:
def leafSimilar(self, root1, root2):
def dfs(node):
if node:
if not node.left and not node.right:
yield node.val
yield from dfs(node.left)
yield from dfs(node.right)
return list(dfs(root1)) == list(dfs(root2))
4.7.1176 - 2024-01-08 17:44:21 +0300 MSK
Links
Code
class Solution:
def rangeSumBST(self, root: Optional[TreeNode], low: int, high: int) -> int:
def dfs(node):
if not node:
return 0
current_val = 0
if low <= node.val <= high:
current_val = node.val
left_sum = dfs(node.left)
right_sum = dfs(node.right)
return current_val + left_sum + right_sum
return dfs(root)
4.7.1177 - 2024-01-07 12:26:09 +0300 MSK
Links
Code
class Solution:
def jobScheduling(self, startTime: List[int], endTime: List[int], profit: List[int]) -> int:
jobs = sorted(zip(endTime, startTime, profit))
number_of_jobs = len(profit)
dp = [0] * (number_of_jobs + 1)
for i, (current_end_time, current_start_time, current_profit) in enumerate(jobs):
index = bisect_right(jobs, current_start_time, hi=i, key=lambda x: x[0])
dp[i + 1] = max(dp[i], dp[index] + current_profit)
return dp[number_of_jobs]
4.7.1178 - 2024-01-07 12:23:04 +0300 MSK
Links
Code
class Solution:
def numberOfArithmeticSlices(self, nums: List[int]) -> int:
n = len(nums)
total_count = 0
dp = [defaultdict(int) for _ in range(n)]
for i in range(1, n):
for j in range(i):
diff = nums[i] - nums[j]
dp[i][diff] += 1
if diff in dp[j]:
dp[i][diff] += dp[j][diff]
total_count += dp[j][diff]
return total_count
4.7.1179 - 2024-01-05 13:00:49 +0300 MSK
Links
Code
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
if not nums:
return 0
n = len(nums)
dp = [1] * n
for i in range(1, n):
for j in range(i):
if nums[i] > nums[j]:
dp[i] = max(dp[i], dp[j] + 1)
return max(dp)
4.7.1180 - 2024-01-04 14:11:50 +0300 MSK
Links
Code
class Solution:
def minOperations(self, nums: List[int]) -> int:
counter = Counter(nums)
ans = 0
for c in counter.values():
if c == 1:
return -1
ans += ceil(c / 3)
return ans
4.7.1181 - 2024-01-03 14:46:50 +0300 MSK
Links
Code
class Solution:
def numberOfBeams(self, bank):
ans, temp = 0, 0
for s in bank:
n = s.count('1')
if n == 0:
continue
ans += temp * n
temp = n
return ans
4.7.1182 - 2024-01-02 15:20:19 +0300 MSK
Links
Code
class Solution:
def findMatrix(self, v: List[int]) -> List[List[int]]:
um = {}
for i in v:
um[i] = um.get(i, 0) + 1
ans = []
while um:
temp = []
to_erase = []
for f, s in um.items():
temp.append(f)
s -= 1
if s == 0:
to_erase.append(f)
um[f] = s
ans.append(temp)
for i in to_erase:
del um[i]
return ans
4.7.1183 - 2024-01-01 16:10:42 +0300 MSK
Links
Code
class Solution:
def findContentChildren(self, g: List[int], s: List[int]) -> int:
g.sort()
s.sort()
content_children = 0
cookie_index = 0
while cookie_index < len(s) and content_children < len(g):
if s[cookie_index] >= g[content_children]:
content_children += 1
cookie_index += 1
return content_children
4.7.1184 - 2023-12-31 13:19:35 +0300 MSK
Links
Code
class Solution:
def maxLengthBetweenEqualCharacters(self, s: str) -> int:
ans = -1
for left in range(len(s)):
for right in range(left + 1, len(s)):
if s[left] == s[right]:
ans = max(ans, right - left - 1)
return ans
4.7.1185 - 2023-12-30 14:22:38 +0300 MSK
Links
Code
class Solution:
def makeEqual(self, words: List[str]) -> bool:
counts = defaultdict(int)
for word in words:
for c in word:
counts[c] += 1
n = len(words)
for val in counts.values():
if val % n != 0:
return False
return True
4.7.1186 - 2023-12-29 10:09:26 +0300 MSK
Links
Code
class Solution:
def minDifficulty(self, jobDifficulty, days):
length = len(jobDifficulty)
if days > length:
return -1
min_difficulties = [[float('inf')] * length for _ in range(days)]
max_diff = 0
i = 0
while i <= length - days:
max_diff = max(max_diff, jobDifficulty[i])
min_difficulties[0][i] = max_diff
i += 1
current_day = 1
while current_day < days:
to = current_day
while to <= length - days + current_day:
current_job_difficulty = jobDifficulty[to]
result = float('inf')
j = to - 1
while j >= current_day - 1:
result = min(result, min_difficulties[current_day - 1][j] + current_job_difficulty)
current_job_difficulty = max(current_job_difficulty, jobDifficulty[j])
j -= 1
min_difficulties[current_day][to] = result
to += 1
current_day += 1
return min_difficulties[days - 1][length - 1]
4.7.1187 - 2023-12-28 10:12:36 +0300 MSK
Links
Code
class Solution:
def getLengthOfOptimalCompression(self, s: str, k: int) -> int:
n = len(s)
dp = [[9999] * 110 for _ in range(110)]
dp[0][0] = 0
for i in range(1, n + 1):
for j in range(0, k + 1):
cnt, del_ = 0, 0
for l in range(i, 0, -1):
if s[l - 1] == s[i - 1]:
cnt += 1
else:
del_ += 1
if j - del_ >= 0:
dp[i][j] = min(dp[i][j], dp[l - 1][j - del_] + 1 + (3 if cnt >= 100 else 2 if cnt >= 10 else 1 if cnt >= 2 else 0))
if j > 0:
dp[i][j] = min(dp[i][j], dp[i - 1][j - 1])
return dp[n][k]
4.7.1188 - 2023-12-27 11:51:17 +0300 MSK
Links
Code
class Solution:
def minCost(self, colors: str, neededTime: List[int]) -> int:
totalTime = 0
i = 0
j = 0
while i < len(neededTime) and j < len(neededTime):
currTotal = 0
currMax = 0
while j < len(neededTime) and colors[i] == colors[j]:
currTotal += neededTime[j]
currMax = max(currMax, neededTime[j])
j += 1
totalTime += currTotal - currMax
i = j
return totalTime
4.7.1189 - 2023-12-26 11:08:25 +0300 MSK
Links
Code
class Solution:
mod = 10 ** 9 + 7
def numRollsToTarget(self, n: int, k: int, target: int) -> int:
dp = [[-1] * (target + 1) for _ in range(n + 1)]
return self.recursion(dp, n, k, target)
def recursion(self, dp: list, n: int, k: int, target: int) -> int:
if target == 0 and n == 0:
return 1
if n == 0 or target <= 0:
return 0
if dp[n][target] != -1:
return dp[n][target] % self.mod
ways = 0
for i in range(1, k + 1):
ways = (ways + self.recursion(dp, n - 1, k, target - i)) % self.mod
dp[n][target] = ways % self.mod
return dp[n][target]
4.7.1190 - 2023-12-25 10:53:55 +0300 MSK
Links
Code
class Solution:
def numDecodings(self, s):
if s == "0":
return 0
# dp_0 = dp[i]
# dp_1 = dp[i + 1]
# dp_2 = dp[i + 2]
dp_2 = 1
dp_1 = int(s[-1] != "0")
i = len(s) - 2
while i >= 0:
if s[i] == "0":
dp_0 = 0
else:
dp_0 = dp_1
if (s[i] == "1") or (s[i] == "2" and eval(s[i + 1]) < 7):
dp_0 += dp_2
i -= 1
dp_0, dp_1, dp_2 = 0, dp_0, dp_1
return dp_1
4.7.1191 - 2023-12-24 12:54:15 +0300 MSK
Links
Code
class Solution:
def minOperations(self, s: str) -> int:
start0 = 0
start1 = 0
for i in range(len(s)):
if i % 2 == 0:
if s[i] == "0":
start1 += 1
else:
start0 += 1
else:
if s[i] == "1":
start1 += 1
else:
start0 += 1
return min(start0, start1)
4.7.1192 - 2023-12-24 00:41:36 +0300 MSK
Links
Code
class Solution:
def isPathCrossing(self, path: str) -> bool:
moves = {
"N": (0, 1),
"S": (0, -1),
"W": (-1, 0),
"E": (1, 0)
}
visited = {(0, 0)}
x = 0
y = 0
for c in path:
dx, dy = moves[c]
x += dx
y += dy
if (x, y) in visited:
return True
visited.add((x, y))
return False
4.7.1193 - 2023-12-22 11:52:14 +0300 MSK
Links
Code
class Solution:
def maxScore(self, s: str) -> int:
ones = s.count("1")
zeros = 0
ans = 0
for i in range(len(s) - 1):
if s[i] == "1":
ones -= 1
else:
zeros += 1
ans = max(ans, zeros + ones)
return ans
4.7.1194 - 2023-12-21 08:42:34 +0300 MSK
Links
Code
class Solution:
def maxWidthOfVerticalArea(self, points: List[List[int]]) -> int:
points.sort(key=lambda x: x[0])
max_width = 0
for i in range(1, len(points)):
width = points[i][0] - points[i-1][0]
max_width = max(max_width, width)
return max_width
4.7.1195 - 2023-12-20 14:05:16 +0300 MSK
Links
Code
class Solution:
def buyChoco(self, prices: List[int], money: int) -> int:
# Assume the Minimum Cost to be Infinity
min_cost = float('inf')
# Number of Chocolates
n = len(prices)
# Check Every Pair of Chocolates
for first_choco in range(n):
for second_choco in range(first_choco + 1, n):
# Sum of Prices of the Two Chocolates
cost = prices[first_choco] + prices[second_choco]
# If the Sum of Prices is Less than the Minimum Cost
if cost < min_cost:
# Update the Minimum Cost
min_cost = cost
# We can buy chocolates only if we have enough money
if min_cost <= money:
# Return the Amount of Money Left
return money - min_cost
else:
# We cannot buy chocolates. Return the initial amount of money
return money
4.7.1196 - 2023-12-19 11:24:47 +0300 MSK
Links
Code
class Solution:
def imageSmoother(self, img: List[List[int]]) -> List[List[int]]:
# Save the dimensions of the image.
m = len(img)
n = len(img[0])
# Create a new image of the same dimension as the input image.
smooth_img = [[0] * n for _ in range(m)]
# Iterate over the cells of the image.
for i in range(m):
for j in range(n):
# Initialize the sum and count
sum = 0
count = 0
# Iterate over all plausible nine indices.
for x in (i - 1, i, i + 1):
for y in (j - 1, j, j + 1):
# If the indices form valid neighbor
if 0 <= x < m and 0 <= y < n:
sum += img[x][y]
count += 1
# Store the rounded down value in smooth_img[i][j].
smooth_img[i][j] = sum // count
# Return the smooth image.
return smooth_img
4.7.1197 - 2023-12-18 13:27:09 +0300 MSK
Links
Code
class Solution:
def maxProductDifference(self, nums: List[int]) -> int:
nums.sort()
return nums[-1] * nums[-2] - nums[0] * nums[1]
4.7.1198 - 2023-12-17 12:09:37 +0300 MSK
Links
Code
class Food:
def __init__(self, food_rating, food_name):
# Store the food's rating.
self.food_rating = food_rating
# Store the food's name.
self.food_name = food_name
def __lt__(self, other):
# Overload the less than operator for comparison.
# If food ratings are the same, sort based on their name (lexicographically smaller name food will be on top).
if self.food_rating == other.food_rating:
return self.food_name < other.food_name
# Sort based on food rating (bigger rating food will be on top).
return self.food_rating > other.food_rating
class FoodRatings:
def __init__(self, foods: List[str], cuisines: List[str], ratings: List[int]):
# Map food with its rating.
self.food_rating_map = {}
# Map food with the cuisine it belongs to.
self.food_cuisine_map = {}
# Store all food of a cuisine in a priority queue (to sort them on ratings/name).
# Priority queue element -> Food: (food_rating, food_name)
self.cuisine_food_map = defaultdict(list)
for i in range(len(foods)):
# Store 'rating' and 'cuisine' of the current 'food' in 'food_rating_map' and 'food_cuisine_map' maps.
self.food_rating_map[foods[i]] = ratings[i]
self.food_cuisine_map[foods[i]] = cuisines[i]
# Insert the '(rating, name)' element into the current cuisine's priority queue.
heapq.heappush(self.cuisine_food_map[cuisines[i]], Food(ratings[i], foods[i]))
def changeRating(self, food: str, newRating: int) -> None:
# Update food's rating in 'food_rating' map.
self.food_rating_map[food] = newRating
# Insert the '(new rating, name)' element in the respective cuisine's priority queue.
cuisineName = self.food_cuisine_map[food]
heapq.heappush(self.cuisine_food_map[cuisineName], Food(newRating, food))
def highestRated(self, cuisine: str) -> str:
# Get the highest rated 'food' of 'cuisine'.
highest_rated = self.cuisine_food_map[cuisine][0]
# If the latest rating of 'food' doesn't match with the 'rating' on which it was sorted in the priority queue,
# then we discard this element from the priority queue.
while self.food_rating_map[highest_rated.food_name] != highest_rated.food_rating:
heapq.heappop(self.cuisine_food_map[cuisine])
highest_rated = self.cuisine_food_map[cuisine][0]
# Return the name of the highest-rated 'food' of 'cuisine'.
return highest_rated.food_name
4.7.1199 - 2023-12-16 13:01:55 +0300 MSK
Links
Code
class Solution:
def isAnagram(self, s: str, t: str) -> bool:
if (len(s) != len(t)):
return False
letters = [0] * 26
for char in s:
letters[ord(char) - ord('a')] += 1
for char in t:
i = ord(char) - ord('a')
letters[i] -= 1
if letters[i] < 0:
return False
return True
4.7.1200 - 2023-12-15 10:56:18 +0300 MSK
Links
Code
class Solution:
def destCity(self, paths: List[List[str]]) -> str:
paths_from = set()
for path_from, path_to in paths:
paths_from.add(path_from)
ans = ""
for _, path_to in paths:
if path_to not in paths_from:
ans = path_to
break
return ans
4.7.1201 - 2023-12-15 10:54:52 +0300 MSK
Links
Code
class Solution:
def destCity(self, paths: List[List[str]]) -> str:
paths_from, paths_to = set(), set()
for path_from, path_to in paths:
paths_from.add(path_from)
paths_to.add(path_to)
return (paths_to - paths_from).pop()
4.7.1202 - 2023-12-14 12:30:55 +0300 MSK
Links
Code
class Solution:
def onesMinusZeros(self, grid: List[List[int]]) -> List[List[int]]:
m = len(grid)
n = len(grid[0])
rows = {}
for r in range(m):
row_sum = 0
for c in range(n):
row_sum += grid[r][c]
rows[r] = row_sum
cols = {}
for c in range(n):
col_sum = 0
for r in range(m):
col_sum += grid[r][c]
cols[c] = col_sum
res = [[0] * n for _ in range(m)]
for r in range(m):
for c in range(n):
res[r][c] = rows[r] + cols[c] - (m - rows[r]) - (n - cols[c])
return res
4.7.1203 - 2023-12-13 11:11:00 +0300 MSK
Links
Code
class Solution:
def numSpecial(self, mat: List[List[int]]) -> int:
def get_column_sum(col_idx):
return sum(row[col_idx] for row in mat)
special = 0
for row in mat:
if sum(row) == 1:
col_idx = row.index(1)
special += get_column_sum(col_idx) == 1
return special
4.7.1204 - 2023-12-12 10:39:45 +0300 MSK
Links
Code
class Solution:
def maxProduct(self, nums: List[int]) -> int:
biggest = 0
second_biggest = 0
for num in nums:
if num > biggest:
second_biggest = biggest
biggest = num
else:
second_biggest = max(second_biggest, num)
return (biggest - 1) * (second_biggest - 1)
4.7.1205 - 2023-12-11 15:30:35 +0300 MSK
Links
Code
class Solution:
def findWords(self, words: List[str]) -> List[str]:
ans = []
rows = [
set("qwertyuiop"),
set("asdfghjkl"),
set("zxcvbnm")
]
for word in words:
for row in rows:
if len(row.union(word.lower())) == len(row):
ans.append(word)
break
return ans
4.7.1206 - 2023-12-11 10:26:55 +0300 MSK
Links
Code
class Solution:
def findSpecialInteger(self, arr: List[int]) -> int:
prev, count = arr[0], 1
quarter = len(arr) / 4
for num in arr[1:]:
if num == prev:
count += 1
else:
prev = num
count = 1
if count > quarter:
break
return prev
4.7.1207 - 2023-12-10 13:46:54 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> result;
helper(root, result);
return result;
}
void helper(TreeNode* root, vector<int>& result) {
if (root != nullptr) {
helper(root->left, result);
result.push_back(root->val);
helper(root->right, result);
}
}
};
4.7.1208 - 2023-12-10 13:46:22 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> result;
helper(root, result);
return result;
}
void helper(TreeNode* root, vector<int>& result) {
if (root != nullptr) {
helper(root->left, result);
result.push_back(root->val);
helper(root->right, result);
}
}
};
4.7.1209 - 2023-12-10 13:45:46 +0300 MSK
Links
Code
class Solution {
public:
vector<vector<int>> transpose(vector<vector<int>>& matrix) {
int row = matrix.size();
int col = matrix[0].size();
vector<vector<int>> result(col, vector<int>(row, 0));
for (int i = 0; i < col; ++i) {
for (int j = 0; j < row; ++j) {
result[i][j] = matrix[j][i];
}
}
return result;
}
};
4.7.1210 - 2023-12-08 21:03:57 +0300 MSK
Links
Code
class Solution {
public:
string tree2str(TreeNode* root) {
string str = "";
check(root, str);
return str;
}
void check(TreeNode* root, string &str) {
if (root == NULL) {
return;
}
str += to_string(root->val);
if (root->left || root->right) {
str += '(';
check(root->left, str);
str += ')';
}
if (root->right) {
str += '(';
check(root->right, str);
str += ')';
}
}
};
4.7.1211 - 2023-12-07 19:20:48 +0300 MSK
Links
Code
class Solution {
public:
string largestOddNumber(string num) {
size_t length {num.size()};
for (int i = length - 1; i >= 0; --i) {
if ((num[i] - '0') % 2 != 0) {
return num.substr(0, i + 1);
}
}
return "";
}
};
4.7.1212 - 2023-12-06 12:45:40 +0300 MSK
Links
Code
class Solution {
public:
bool isPalindrome(ListNode* head) {
ListNode* slow {head};
ListNode* fast {head};
ListNode* next;
ListNode* prev {new ListNode()};
while(fast && fast->next) {
slow = slow->next;
fast = fast->next->next;
next = head->next;
head->next = prev;
prev = head;
head = next;
}
if (fast) {
slow = slow->next;
}
head = prev;
while (slow) {
if (head->val != slow->val) {
return false;
}
head = head->next;
slow = slow->next;
}
return true;
}
};
4.7.1213 - 2023-12-06 09:43:04 +0300 MSK
Links
Code
class Solution {
public:
int totalMoney(int n) {
int ans {0};
int monday {1};
while (n > 0) {
for (int day {0}; day < min(n, 7); ++day) {
ans += monday + day;
}
n -= 7;
++monday;
}
return ans;
}
};
4.7.1214 - 2023-12-05 16:12:24 +0300 MSK
Links
Code
class Solution {
public:
int numberOfMatches(int n) {
int ans = 0;
while (n > 1) {
if (n % 2 == 0) {
int matches {n / 2};
ans += matches;
n = matches;
} else {
int matches {(n - 1) / 2};
ans += matches;
n = matches + 1;
}
}
return ans;
}
};
4.7.1215 - 2023-12-04 11:09:00 +0300 MSK
Links
Code
class Solution {
public:
string largestGoodInteger(string num) {
int cur {-1};
int max {-1};
int count {0};
for (const char& ch : num) {
int i {ch - '0'};
if (i == cur) {
++count;
} else {
cur = i;
count = 1;
}
if (count == 3) {
max = std::max(i, max);
}
}
if (max == -1) {
return "";
}
std::string ans {std::to_string(max)};
return ans + ans + ans;
}
};
4.7.1216 - 2023-12-03 17:53:13 +0300 MSK
Links
Code
class Solution {
public:
int minTimeToVisitAllPoints(vector<vector<int>>& points) {
int ans = 0;
for (int i = 0; i < points.size() - 1; i++) {
int currX = points[i][0];
int currY = points[i][1];
int targetX = points[i + 1][0];
int targetY = points[i + 1][1];
ans += max(abs(targetX - currX), abs(targetY - currY));
}
return ans;
}
};
4.7.1217 - 2023-12-02 23:40:09 +0300 MSK
Links
Code
class Solution {
public:
int countCharacters(vector<string>& words, string chars) {
std::vector<int> count {};
int ans {};
count.resize(26);
for (const char& ch : chars) {
++count[ch - 'a'];
}
for (const string& word : words) {
std::vector<int> wordCount {};
wordCount.resize(26);
bool failure {false};
for (const char& ch : word) {
int i {ch - 'a'};
int cur {++wordCount[i]};
if (cur > count[i]) {
failure = true;
break;
}
}
if (!failure) {
ans += word.length();
}
}
return ans;
}
};
4.7.1218 - 2023-12-01 11:21:29 +0300 MSK
Links
Code
class Solution {
public:
bool arrayStringsAreEqual(vector<string>& word1, vector<string>& word2) {
string s1 = "";
string s2 = "";
for(const string& s : word1) {
s1 += s;
}
for(const string& s : word2) {
s2 += s;
}
return s1==s2;
}
};
4.7.1219 - 2023-11-30 10:50:12 +0300 MSK
Links
Code
class Solution {
public:
int minimumOneBitOperations(int n) {
if (n == 0) {
return 0;
}
int k = 0;
int curr = 1;
while (curr * 2 <= n) {
curr *= 2;
k++;
}
return (1 << (k + 1)) - 1 - minimumOneBitOperations(n ^ curr);
}
};
4.7.1220 - 2023-11-29 12:01:45 +0300 MSK
Links
Code
class Solution {
public:
int hammingWeight(uint32_t n) {
int ans {};
while (n) {
if (n & 1) {
++ans;
}
n >>= 1;
}
return ans;
}
};
4.7.1221 - 2023-11-28 13:04:41 +0300 MSK
Links
Code
class Solution {
public:
// Store 1000000007 in a variable for convenience
const int MOD = 1e9 + 7;
// Count the number of ways to divide from "index" to the last index
// with "seats" number of "S" in the current section
int count(int index, int seats, string& corridor, int cache[][3]) {
// If we have reached the end of the corridor, then
// the current section is valid only if "seats" is 2
if (index == corridor.length()) {
return seats == 2 ? 1 : 0;
}
// If we have already computed the result of this sub-problem,
// then return the cached result
if (cache[index][seats] != -1) {
return cache[index][seats];
}
// Result of the sub-problem
int result = 0;
// If the current section has exactly 2 "S"
if (seats == 2) {
// If the current element is "S", then we have to close the
// section and start a new section from this index. Next index
// will have one "S" in the current section
if (corridor[index] == 'S') {
result = count(index + 1, 1, corridor, cache);
} else {
// If the current element is "P", then we have two options
// 1. Close the section and start a new section from this index
// 2. Keep growing the section
result = (count(index + 1, 0, corridor, cache) + count(index + 1, 2, corridor, cache)) % MOD;
}
} else {
// Keep growing the section. Increment "seats" if present
// element is "S"
if (corridor[index] == 'S') {
result = count(index + 1, seats + 1, corridor, cache);
} else {
result = count(index + 1, seats, corridor, cache);
}
}
// Memoize the result, and return it
cache[index][seats] = result;
return cache[index][seats];
}
int numberOfWays(string corridor) {
// Cache the result of each sub-problem
int cache[corridor.length()][3];
memset(cache, -1, sizeof(cache));
// Call the count function
return count(0, 0, corridor, cache);
}
};
4.7.1222 - 2023-11-27 10:32:44 +0300 MSK
Links
Code
class Solution {
public:
int largestSubmatrix(vector<vector<int>>& matrix) {
int m = matrix.size();
int n = matrix[0].size();
int ans = 0;
for (int row = 0; row < m; row++) {
for (int col = 0; col < n; col++) {
if (matrix[row][col] != 0 && row > 0) {
matrix[row][col] += matrix[row - 1][col];
}
}
vector<int> currRow = matrix[row];
sort(currRow.begin(), currRow.end(), greater());
for (int i = 0; i < n; i++) {
ans = max(ans, currRow[i] * (i + 1));
}
}
return ans;
}
};
4.7.1223 - 2023-11-27 10:32:13 +0300 MSK
Links
Code
class Solution {
public:
vector<vector<int>> memo;
int n;
int MOD = 1e9 + 7;
vector<vector<int>> jumps = {
{4, 6},
{6, 8},
{7, 9},
{4, 8},
{3, 9, 0},
{},
{1, 7, 0},
{2, 6},
{1, 3},
{2, 4}
};
int dp(int remain, int square) {
if (remain == 0) {
return 1;
}
if (memo[remain][square] != 0) {
return memo[remain][square];
}
int ans = 0;
for (int nextSquare : jumps[square]) {
ans = (ans + dp(remain - 1, nextSquare)) % MOD;
}
memo[remain][square] = ans;
return ans;
}
int knightDialer(int n) {
this->n = n;
memo = vector(n + 1, vector(10, 0));
int ans = 0;
for (int square = 0; square < 10; square++) {
ans = (ans + dp(n - 1, square)) % MOD;
}
return ans;
}
};
4.7.1224 - 2023-11-25 22:00:45 +0300 MSK
Links
Code
class Solution {
public:
vector<int> getSumAbsoluteDifferences(vector<int>& nums) {
int n = nums.size();
int totalSum = accumulate(nums.begin(), nums.end(), 0);
int leftSum = 0;
vector<int> ans;
for (int i = 0; i < n; i++) {
int rightSum = totalSum - leftSum - nums[i];
int leftCount = i;
int rightCount = n - 1 - i;
int leftTotal = leftCount * nums[i] - leftSum;
int rightTotal = rightSum - rightCount * nums[i];
ans.push_back(leftTotal + rightTotal);
leftSum += nums[i];
}
return ans;
}
};
4.7.1225 - 2023-11-25 22:00:22 +0300 MSK
Links
Code
class Solution {
public:
vector<int> getSumAbsoluteDifferences(vector<int>& nums) {
int n = nums.size();
vector<int> prefix = {nums[0]};
for (int i = 1; i < n; i++) {
prefix.push_back(prefix[i - 1] + nums[i]);
}
vector<int> ans;
for (int i = 0; i < n; i++) {
int leftSum = prefix[i] - nums[i];
int rightSum = prefix[n - 1] - prefix[i];
int leftCount = i;
int rightCount = n - 1 - i;
int leftTotal = leftCount * nums[i] - leftSum;
int rightTotal = rightSum - rightCount * nums[i];
ans.push_back(leftTotal + rightTotal);
}
return ans;
}
};
4.7.1226 - 2023-11-24 16:49:32 +0300 MSK
Links
Code
class Solution {
public:
std::vector<bool> kidsWithCandies(std::vector<int>& candies, int extraCandies) {
size_t length {candies.size()};
std::vector<bool> ans {};
ans.resize(length);
const int maxCandy {*std::max_element(candies.begin(), candies.end())};
for (size_t i = 0; i < length; ++i) {
ans[i] = (candies[i] + extraCandies) >= maxCandy;
}
return ans;
}
};
4.7.1227 - 2023-11-24 16:37:41 +0300 MSK
Links
Code
class Solution {
public:
string gcdOfStrings(string str1, string str2) {
if (str1 + str2 == str2 + str1) {
return str1.substr(0, std::gcd(str1.size(), str2.size()));
}
return "";
}
};
4.7.1228 - 2023-11-24 16:36:38 +0300 MSK
Links
Code
class Solution {
public:
string gcdOfStrings(string str1, string str2) {
if (str1 + str2 != str2 + str1) {
return "";
}
unsigned long gcdLength {std::gcd(str1.size(), str2.size())};
return str1.substr(0, gcdLength);
}
};
4.7.1229 - 2023-11-24 16:32:52 +0300 MSK
Links
Code
class Solution {
public:
bool valid(string str1, string str2, size_t k) {
size_t len1 {str1.size()}, len2 {str2.size()};
if (len1 % k != 0 || len2 % k != 0) {
return false;
}
string base = str1.substr(0, k);
size_t n1 {len1 / k}, n2 {len2 / k};
if (n1 == n2) {
return str1 == str2 && joinWords(base, n1) == str1;
}
return str1 == joinWords(base, n1) && str2 == joinWords(base, n2);
}
string joinWords(string str, size_t k) {
string ans = "";
for (size_t i = 0; i < k; ++i) {
ans += str;
}
return ans;
}
string gcdOfStrings(string str1, string str2) {
for (size_t i = min(str1.size(), str2.size()); i > 0; --i) {
if (valid(str1, str2, i)) {
return str1.substr(0, i);
}
}
return "";
}
};
4.7.1230 - 2023-11-24 11:07:37 +0300 MSK
Links
Code
class Solution {
public:
int maxCoins(vector<int>& piles) {
std::sort(piles.begin(), piles.end());
size_t length {piles.size()};
size_t picks {length / 3};
int count {};
for (size_t i {length - 2}; picks > 0; i -= 2, --picks) {
count += piles[i];
}
return count;
}
};
4.7.1231 - 2023-11-23 13:41:25 +0300 MSK
Links
Code
class Solution {
public:
bool check(vector<int>& arr) {
sort(arr.begin(), arr.end());
int diff = arr[1] - arr[0];
for (int i = 2; i < arr.size(); i++) {
if (arr[i] - arr[i - 1] != diff) {
return false;
}
}
return true;
}
vector<bool> checkArithmeticSubarrays(vector<int>& nums, vector<int>& l, vector<int>& r) {
vector<bool> ans;
for (int i = 0; i < l.size(); i++) {
vector<int> arr(begin(nums) + l[i], begin(nums) + r[i] + 1);
ans.push_back(check(arr));
}
return ans;
}
};
4.7.1232 - 2023-11-22 18:49:02 +0300 MSK
Links
Code
class Solution {
public:
vector<int> findDiagonalOrder(vector<vector<int>>& nums) {
unordered_map<int, vector<int>> groups;
for (int row = nums.size() - 1; row >= 0; row--) {
for (int col = 0; col < nums[row].size(); col++) {
int diagonal = row + col;
groups[diagonal].push_back(nums[row][col]);
}
}
vector<int> ans;
int curr = 0;
while (groups.find(curr) != groups.end()) {
for (int num : groups[curr]) {
ans.push_back(num);
}
curr++;
}
return ans;
}
};
4.7.1233 - 2023-11-21 12:51:21 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<string> binaryTreePaths(TreeNode* root) {
vector<string> ans;
dfs(*root, ans, "");
return ans;
}
void dfs(TreeNode& root, vector<string> &ans, string path){
path += (path.size() ? "->" : "") + std::to_string(root.val);
if(!root.left && !root.right) {
ans.push_back(path);
return;
}
if(root.left) {
dfs(*root.left, ans, path);
}
if(root.right) {
dfs(*root.right, ans, path);
}
}
};
4.7.1234 - 2023-11-21 12:44:04 +0300 MSK
Links
Code
class Solution {
public:
int countNicePairs(vector<int>& nums) {
std::unordered_map<int, int> diffs{};
int ans{};
double mod{1e9 + 7};
for (const int& num : nums) {
int revNum{};
int tempNum{num};
while(tempNum) {
revNum = (revNum * 10) + (tempNum % 10);
tempNum /= 10;
}
int diff{num-revNum};
if (diffs.contains(diff)) {
ans = std::fmod(ans + diffs[diff], mod);
}
++diffs[diff];
}
return ans;
}
};
4.7.1235 - 2023-11-21 12:33:13 +0300 MSK
Links
Code
class Solution {
public:
int countNicePairs(vector<int>& nums) {
std::unordered_map<int, int> diffs{};
for (const int& num : nums) {
int revNum{};
int tempNum{num};
while(tempNum) {
revNum = (revNum * 10) + (tempNum % 10);
tempNum /= 10;
}
++diffs[num - revNum];
}
int ans{};
double mod{std::pow(10, 9) + 7};
for (const auto& [num, count] : diffs) {
long pairs{(1L * count * count - count) / 2};
ans = std::fmod(ans + pairs, mod);
}
return ans;
}
};
4.7.1236 - 2023-11-20 18:30:57 +0300 MSK
Links
Code
class Solution {
public:
int titleToNumber(string columnTitle) {
int ans{0};
for (const char& ch : columnTitle) {
ans = (ans * 26) + (ch - 'A') + 1;
}
return ans;
}
};
4.7.1237 - 2023-11-20 14:40:36 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
if (root == nullptr) {
return {};
}
std::vector<int> ans{};
addNodes(*root, ans);
return ans;
}
void addNodes(TreeNode& node, std::vector<int>& ans) {
if (node.left != nullptr) {
addNodes(*node.left, ans);
}
if (node.right != nullptr) {
addNodes(*node.right, ans);
}
ans.push_back(node.val);
}
};
4.7.1238 - 2023-11-20 14:38:40 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
if (root == nullptr) {
return {};
}
std::vector<int> ans{};
addNodes(root, ans);
return ans;
}
void addNodes(TreeNode* node, std::vector<int>& ans) {
auto left{node->left}, right{node->right};
if (left != nullptr) {
addNodes(left, ans);
}
if (right != nullptr) {
addNodes(right, ans);
}
ans.push_back(node->val);
}
};
4.7.1239 - 2023-11-20 14:31:25 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
if (root == nullptr) {
return {};
}
std::vector<int> ans{};
std::vector<TreeNode*> q{root};
while (q.size() != 0) {
auto node = q.back();
auto left{node->left}, right{node->right};
q.pop_back();
ans.push_back(node->val);
if (right != nullptr) {
q.push_back(right);
}
if (left != nullptr) {
q.push_back(left);
}
}
return ans;
}
};
4.7.1240 - 2023-11-20 14:29:40 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
if (root == nullptr) {
return {};
}
std::vector<int> ans{};
std::deque<TreeNode*> q{root};
while (q.size() != 0) {
auto node = q.front();
auto left{node->left}, right{node->right};
q.pop_front();
ans.push_back(node->val);
if (right != nullptr) {
q.push_front(right);
}
if (left != nullptr) {
q.push_front(left);
}
}
return ans;
}
};
4.7.1241 - 2023-11-20 14:27:13 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
std::vector<int> ans{};
std::deque<TreeNode*> q{root};
while (q.size() != 0) {
auto node = q.front();
q.pop_front();
if (node == nullptr) {
continue;
}
ans.push_back(node->val);
q.push_front(node->right);
q.push_front(node->left);
}
return ans;
}
};
4.7.1242 - 2023-11-20 14:11:47 +0300 MSK
Links
Code
class Solution {
public:
int garbageCollection(vector<string>& garbage, vector<int>& travel) {
vector<int> prefixSum(travel.size() + 1, 0);
prefixSum[1] = travel[0];
for (int i = 1; i < travel.size(); i++) {
prefixSum[i + 1] = prefixSum[i] + travel[i];
}
unordered_map<char, int> garbageLastPos;
unordered_map<char, int> garbageCount;
for (int i = 0; i < garbage.size(); i++) {
for (char c : garbage[i]) {
garbageLastPos[c] = i;
garbageCount[c]++;
}
}
char garbageTypes[3] = {'M', 'P', 'G'};
int ans = 0;
for (char c : garbageTypes) {
if (garbageCount[c]) {
ans += prefixSum[garbageLastPos[c]] + garbageCount[c];
}
}
return ans;
}
};
4.7.1243 - 2023-11-19 11:31:05 +0300 MSK
Links
Code
class Solution {
public:
int reductionOperations(vector<int>& nums) {
sort(nums.begin(), nums.end());
int ans = 0;
int up = 0;
auto length {nums.size()};
for (int i = 1; i < length; ++i) {
if (nums[i] != nums[i - 1]) {
++up;
}
ans += up;
}
return ans;
}
};
4.7.1244 - 2023-11-18 19:23:48 +0300 MSK
Links
Code
class Solution {
public:
int maxFrequency(vector<int>& nums, int k) {
sort(nums.begin(), nums.end());
int left = 0;
int ans = 0;
long curr = 0;
for (int right = 0; right < nums.size(); right++) {
long target = nums[right];
curr += target;
while ((right - left + 1) * target - curr > k) {
curr -= nums[left];
left++;
}
ans = max(ans, right - left + 1);
}
return ans;
}
};
4.7.1245 - 2023-11-17 17:25:22 +0300 MSK
Links
Code
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* oddEvenList(ListNode* head) {
if(!head || !head->next || !head->next->next) {
return head;
}
ListNode* odd {head};
ListNode* even {head->next};
ListNode* even_start {head->next};
while(odd->next && even->next) {
ListNode* next {even->next};
odd->next = next;
even->next = next->next;
odd = odd->next;
even = even->next;
}
odd->next = even_start;
return head;
}
};
4.7.1246 - 2023-11-17 16:41:37 +0300 MSK
Links
Code
class Solution {
public:
string predictPartyVictory(string senate) {
std::queue<int> rad, dir;
unsigned long length {senate.size()};
for (int i = 0; i < length; ++i){
if (senate[i] == 'R'){
rad.push(i);
} else {
dir.push(i);
}
}
while (!rad.empty() && !dir.empty()) {
if (rad.front() < dir.front()) {
rad.push(length);
} else {
dir.push(length);
}
++length;
rad.pop();
dir.pop();
}
return rad.empty() ? "Dire" : "Radiant";
}
};
4.7.1247 - 2023-11-17 14:05:35 +0300 MSK
Links
Code
class Solution {
public:
string decodeString(string s) {
return std::get<1>(decode(0, s));
}
std::tuple<int, string> decode(int pos, string s) {
int num {0};
string word {""};
unsigned long length {s.size()};
for(; pos < length; ++pos) {
char c = s[pos];
if(c == '[') {
auto [newPos, repeat] {decode(++pos, s)};
for(; num > 0; --num) {
word += repeat;
}
pos = newPos;
} else if (c >= '0' && c <='9') {
num = num * 10 + (c - '0');
} else if (c == ']') {
return {pos, word};
} else {
word += c;
}
}
return {pos, word};
}
};
4.7.1248 - 2023-11-17 14:02:06 +0300 MSK
Links
Code
class Solution {
public:
string decodeString(string s) {
int pos = 0;
return decode(pos, s);
}
string decode(int& pos, string s) {
int num {0};
string word {""};
unsigned long length {s.size()};
for(; pos < length; ++pos) {
char c = s[pos];
if(c == '[') {
string repeat {decode(++pos, s)};
for(; num > 0; --num) {
word += repeat;
}
} else if (c >= '0' && c <='9') {
num = num * 10 + (c - '0');
} else if (c == ']') {
return word;
} else {
word += c;
}
}
return word;
}
};
4.7.1249 - 2023-11-17 13:13:32 +0300 MSK
Links
Code
class Solution {
public:
string removeStars(string s) {
std::string ans;
int remove {0};
for (int i = s.size() - 1; i >= 0; --i) {
char c = s[i];
if (c == '*') {
++remove;
} else if (remove == 0) {
ans += c;
} else {
--remove;
}
}
std::reverse(ans.begin(), ans.end());
return ans;
}
};
4.7.1250 - 2023-11-17 13:12:34 +0300 MSK
Links
Code
class Solution {
public:
string removeStars(string s) {
std::string ans;
unsigned long length {s.size()};
int remove {0};
for (int i = length - 1; i >= 0; --i) {
char c = s[i];
if (c == '*') {
++remove;
continue;
}
if (remove == 0) {
ans += c;
} else {
--remove;
}
}
std::reverse(ans.begin(), ans.end());
return ans;
}
};
4.7.1251 - 2023-11-17 13:02:26 +0300 MSK
Links
Code
class Solution {
public:
int minPairSum(vector<int>& nums) {
std::sort(nums.begin(), nums.end());
unsigned long length {nums.size()};
int maxSum {0};
for (int i = 0; i < length / 2; ++i) {
maxSum = max(maxSum, nums[i] + nums[length - i - 1]);
}
return maxSum;
}
};
4.7.1252 - 2023-11-16 16:43:00 +0300 MSK
Links
Code
class Solution {
public:
bool uniqueOccurrences(vector<int>& arr) {
std::unordered_map<int, int> counts;
std::unordered_set<int> encountered;
for (int num : arr) {
counts[num] += 1;
}
for (const auto [num, count] : counts) {
if (encountered.find(count) == encountered.end()) {
encountered.insert(count);
} else {
return false;
}
}
return true;
}
};
4.7.1253 - 2023-11-16 16:22:50 +0300 MSK
Links
Code
class Solution {
public:
int tribonacci(int n) {
if (n == 0) {
return 0;
}
if (n == 1 || n == 2) {
return 1;
}
int num1 {0}, num2 {1}, num3 {1};
for (int i = 3; i <= n; ++i) {
int newNum3 = num1 + num2 + num3;
num1 = num2;
num2 = num3;
num3 = newNum3;
}
return num3;
}
};
4.7.1254 - 2023-11-16 14:30:47 +0300 MSK
Links
Code
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
std::sort(nums.begin(), nums.end(), std::greater<int>());
return nums[k-1];
}
};
4.7.1255 - 2023-11-16 14:18:16 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
TreeNode* searchBST(TreeNode* root, int val) {
while (root != nullptr) {
if (root->val == val) {
return root;
}
if (root->val > val) {
root = root->left;
} else {
root = root->right;
}
}
return root;
}
};
4.7.1256 - 2023-11-16 14:15:58 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
TreeNode* searchBST(TreeNode* root, int val) {
if (root == nullptr || root->val == val) {
return root;
}
if (val > root->val) {
return searchBST(root->right, val);
}
return searchBST(root->left, val);
}
};
4.7.1257 - 2023-11-16 14:13:23 +0300 MSK
Links
Code
class Solution {
public:
int pivotIndex(vector<int>& nums) {
int left {0}, right {std::accumulate(nums.begin() + 1, nums.end(), 0)};
unsigned long length {nums.size()};
if (right == 0) {
return 0;
}
for (int i = 1; i < length; ++i) {
left += nums[i-1];
right -= nums[i];
if (left == right) {
return i;
}
}
return -1;
}
};
4.7.1258 - 2023-11-16 14:06:30 +0300 MSK
Links
Code
class Solution {
public:
int largestAltitude(vector<int>& gain) {
int att {0}, maxAtt {0};
for (int num : gain) {
att += num;
maxAtt = max(maxAtt, att);
}
return maxAtt;
}
};
4.7.1259 - 2023-11-16 11:22:37 +0300 MSK
Links
Code
class Solution {
public:
string findDifferentBinaryString(vector<string>& nums) {
unordered_set<int> integers;
for (string num : nums) {
integers.insert(stoi(num, 0, 2));
}
int n = nums.size();
string ans;
for (int num = 0; num <= n; num++) {
if (integers.find(num) == integers.end()) {
ans = bitset<16>(num).to_string();
break;
}
}
return ans.substr(16 - n);
}
};
4.7.1260 - 2023-11-15 16:53:47 +0300 MSK
Links
Code
class Solution {
public:
vector<int> getElementsOnlyInFirstList(vector<int>& nums1, vector<int>& nums2) {
unordered_set<int> onlyInNums1;
for (int num : nums1) {
bool existInNums2 = false;
for (int x : nums2) {
if (x == num) {
existInNums2 = true;
break;
}
}
if (!existInNums2) {
onlyInNums1.insert(num);
}
}
return vector<int> (onlyInNums1.begin(), onlyInNums1.end());
}
vector<vector<int>> findDifference(vector<int>& nums1, vector<int>& nums2) {
return {getElementsOnlyInFirstList(nums1, nums2), getElementsOnlyInFirstList(nums2, nums1)};
}
};
4.7.1261 - 2023-11-15 16:12:27 +0300 MSK
Links
Code
class Solution {
public:
bool increasingTriplet(vector<int>& nums) {
auto length{nums.size()};
int num1{INT_MAX}, num2{INT_MAX};
for (int num : nums) {
if (num <= num1) {
num1 = num;
} else if (num <= num2) {
num2 = num;
} else {
return true;
}
}
return false;
}
};
4.7.1262 - 2023-11-15 15:18:40 +0300 MSK
Links
Code
class Solution {
public:
int maximumElementAfterDecrementingAndRearranging(vector<int>& arr) {
std::sort(arr.begin(), arr.end());
auto length{arr.size()};
int prev{1};
for (int i = 1; i < length; ++i) {
if (arr[i] != prev) {
++prev;
}
}
return prev;
}
};
4.7.1263 - 2023-11-15 15:17:30 +0300 MSK
Links
Code
class Solution {
public:
int maximumElementAfterDecrementingAndRearranging(vector<int>& arr) {
std::sort(arr.begin(), arr.end());
auto length{arr.size()};
int prev{1};
for (int i = 1; i < length; ++i) {
if (arr[i] == prev) {
continue;
}
++prev;
}
return prev;
}
};
4.7.1264 - 2023-11-14 15:39:29 +0300 MSK
Links
Code
class Solution {
public:
int countPalindromicSubsequence(string s) {
unordered_set<char> letters;
for (char c : s) {
letters.insert(c);
}
int ans = 0;
for (char letter : letters) {
int i = -1;
int j = 0;
for (int k = 0; k < s.size(); k++) {
if (s[k] == letter) {
if (i == -1) {
i = k;
}
j = k;
}
}
unordered_set<char> between;
for (int k = i + 1; k < j; k++) {
between.insert(s[k]);
}
ans += between.size();
}
return ans;
}
};
4.7.1265 - 2023-11-13 20:24:55 +0300 MSK
Links
Code
class Solution {
public:
bool isVowel(char ch) {
return ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u' ||
ch == 'A' || ch == 'E' || ch == 'I' || ch == 'O' || ch == 'U';
}
string reverseVowels(string s) {
unsigned long length{s.size()};
unsigned long left{0}, right{length-1};
while (left < right) {
char chLeft{s[left]};
char chRight{s[right]};
if (!isVowel(chLeft)) {
++left;
} else if (!isVowel(chRight)) {
--right;
} else {
s[left] = chRight;
s[right] = chLeft;
++left;
--right;
}
}
return s;
}
};
4.7.1266 - 2023-11-13 10:42:13 +0300 MSK
Links
Code
class Solution {
public:
// Returns true if the character is a vowel.
bool isVowel(char c) {
return c == 'a' || c == 'e' || c == 'o'|| c == 'u'|| c == 'i'
|| c == 'A' || c == 'E' || c == 'O'|| c == 'U'|| c == 'I';
}
string sortVowels(string s) {
unordered_map<char, int> count;
// Store the frequencies for each character.
for (char c : s) {
if (isVowel(c)) {
count[c]++;
}
}
// Sorted string having all the vowels.
string sortedVowel = "AEIOUaeiou";
string ans;
int j = 0;
for (int i = 0; i < s.size(); i++) {
if (!isVowel(s[i])) {
ans += s[i];
} else {
// Skip to the character which is having remaining count.
while (count[sortedVowel[j]] == 0) {
j++;
}
ans += sortedVowel[j];
count[sortedVowel[j]]--;
}
}
return ans;
}
};
4.7.1267 - 2023-11-13 10:40:23 +0300 MSK
Links
Code
class Solution {
public:
string sortVowels(string s) {
std::map<char, int> vowels{
{'A', 0}, {'E', 0}, {'I', 0}, {'O', 0}, {'U', 0},
{'a', 0}, {'e', 0}, {'i', 0}, {'o', 0}, {'u', 0}
};
unsigned long length{ s.size() };
for (char ch : s) {
if (vowels.contains(ch)) {
++vowels[ch];
}
}
for (int i = 0; i < length; ++i) {
const char ch = s[i];
if (!vowels.contains(ch)) {
continue;
}
for (const auto& [orderChar, count] : vowels) {
if (count > 0) {
s[i] = orderChar;
--vowels[orderChar];
break;
}
}
}
return s;
}
};
4.7.1268 - 2023-11-13 10:38:46 +0300 MSK
Links
Code
class Solution {
public:
string sortVowels(string s) {
std::map<char, int> vowels{
{'A', 0}, {'E', 0}, {'I', 0}, {'O', 0}, {'U', 0},
{'a', 0}, {'e', 0}, {'i', 0}, {'o', 0}, {'u', 0}
};
const char order[10]{ 'A', 'E', 'I', 'O', 'U', 'a', 'e', 'i', 'o', 'u' };
unsigned long length{ s.size() };
for (char ch : s) {
if (vowels.contains(ch)) {
++vowels[ch];
}
}
for (int i = 0; i < length; ++i) {
const char ch = s[i];
if (!vowels.contains(ch)) {
continue;
}
for (char orderChar : order) {
if (vowels[orderChar] > 0) {
s[i] = orderChar;
--vowels[orderChar];
break;
}
}
}
return s;
}
};
4.7.1269 - 2023-11-12 17:00:22 +0300 MSK
Links
Code
class Solution {
public:
double findMaxAverage(vector<int>& nums, int k) {
int length = nums.size();
double sum = std::accumulate(nums.begin(), nums.begin() + k , 0);
double maxSum = sum;
for (int i = k; i < length; ++i) {
sum += nums[i] - nums[i-k];
maxSum = max(sum, maxSum);
}
return maxSum / k;
}
};
4.7.1270 - 2023-11-12 16:08:04 +0300 MSK
Links
Code
class Solution {
public:
int compress(vector<char>& chars) {
int i = 0, res = 0;
int length = chars.size();
while (i < length) {
int groupLength = 1;
while (i + groupLength < length && chars[i + groupLength] == chars[i]) {
groupLength++;
}
chars[res++] = chars[i];
if (groupLength > 1) {
for (char c : to_string(groupLength)) {
chars[res++] = c;
}
}
i += groupLength;
}
return res;
}
};
4.7.1271 - 2023-11-12 15:43:55 +0300 MSK
Links
Code
class Solution {
public:
bool canPlaceFlowers(vector<int>& flowerbed, int n) {
int curZeros = flowerbed[0] == 0 ? 2 : 0;
int length = flowerbed.size();
int ans = 0;
for (int i = 1; i < length; ++i) {
if (flowerbed[i] == 0) {
curZeros += 1;
continue;
}
ans += (curZeros - 1) / 2;
curZeros = 0;
if (ans >= n) {
return true;
}
}
ans += curZeros / 2;
return ans >= n;
}
};
4.7.1272 - 2023-11-12 15:41:26 +0300 MSK
Links
Code
class Solution {
public:
bool canPlaceFlowers(vector<int>& flowerbed, int n) {
int curZeros = 0, length = flowerbed.size();
if (flowerbed[0] == 0) {
curZeros = 2;
}
int ans = 0;
for (int i = 1; i < length; ++i) {
bool isFlower = flowerbed[i] == 1;
if (!isFlower) {
curZeros += 1;
continue;
}
ans += (curZeros - 1) / 2;
curZeros = 0;
if (ans >= n) {
return true;
}
}
ans += curZeros / 2;
return ans >= n;
}
};
4.7.1273 - 2023-11-12 11:40:25 +0300 MSK
Links
Code
class Solution {
public:
int numBusesToDestination(vector<vector<int>>& routes, int source, int target) {
if (source == target) {
return 0;
}
unordered_map<int, vector<int>> adjList;
// Create a map from the bus stop to all the routes that include this stop.
for (int route = 0; route < routes.size(); route++) {
for (auto stop : routes[route]) {
// Add all the routes that have this stop.
adjList[stop].push_back(route);
}
}
queue<int> q;
unordered_set<int> vis;
// Insert all the routes in the queue that have the source stop.
for (auto route : adjList[source]){
q.push(route);
vis.insert(route);
}
int busCount = 1;
while (q.size()) {
int size = q.size();
for (int i = 0; i < size; i++) {
int route = q.front(); q.pop();
// Iterate over the stops in the current route.
for (auto stop: routes[route]) {
// Return the current count if the target is found.
if (stop == target) {
return busCount;
}
// Iterate over the next possible routes from the current stop.
for (auto nextRoute : adjList[stop]) {
if (!vis.count(nextRoute)) {
vis.insert(nextRoute);
q.push(nextRoute);
}
}
}
}
busCount++;
}
return -1;
}
};
4.7.1274 - 2023-11-11 16:10:00 +0300 MSK
Links
Code
class Solution {
public:
int fib(int n) {
if (n < 2) {
return n;
}
int cur = 1, prev = 0;
for (int i = 2; i <= n; ++i) {
int newVal = cur + prev;
prev = cur;
cur = newVal;
}
return cur;
}
};
4.7.1275 - 2023-11-11 16:06:23 +0300 MSK
Links
Code
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
head = new ListNode(-1, head);
auto ans = head;
while (head) {
auto next = head->next;
if (next && next->val == val) {
head->next = next->next;
} else {
head = next;
}
}
return ans->next;
}
};
4.7.1276 - 2023-11-11 16:06:11 +0300 MSK
Links
Code
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
head = new ListNode(-1, head);
auto ans = head;
while (head) {
auto next = head->next;
if (next && next->val == val) {
head->next = next->next;
} else {
head = head->next;
}
}
return ans->next;
}
};
4.7.1277 - 2023-11-11 15:52:58 +0300 MSK
Links
Code
class Solution {
public:
bool isValid(string s) {
std::vector<char> stack;
for (const auto& ch : s) {
switch (ch){
case '[':
case '{':
case '(':
stack.push_back(ch);
break;
case ')':
if (stack.empty() || stack.back() != '(') {
return false;
}
stack.pop_back();
break;
case '}':
if (stack.empty() || stack.back() != '{') {
return false;
}
stack.pop_back();
break;
case ']':
if (stack.empty() || stack.back() != '[') {
return false;
}
stack.pop_back();
break;
}
}
return stack.size() == 0;
}
};
4.7.1278 - 2023-11-11 15:43:36 +0300 MSK
Links
Code
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
std::map<int, int> numToIndex;
int length = nums.size();
std::vector<int> ans;
for (int i = 0; i < length; ++i) {
int num = nums[i];
int diff = target - num;
if (numToIndex.contains(diff)) {
ans = {numToIndex[diff], i};
break;
}
numToIndex[num] = i;
}
return ans;
}
};
4.7.1279 - 2023-11-11 15:32:34 +0300 MSK
Links
Code
class Solution {
public:
string reverseWords(string s) {
string ans = "";
string temp = "";
int length = s.length();
int j = 0;
for (j = 0; s[j] == ' ' && j < length; ++j) { }
for (int i = length - 1; i >= j; --i) {
if(s[i] == ' '){
if(temp != ""){
ans = ans + temp + ' ';
temp = "";
}
continue;
}
else{
temp = s[i] + temp;
}
}
return ans + temp;
}
};
4.7.1280 - 2023-11-11 15:18:39 +0300 MSK
Links
Code
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* prev = NULL;
ListNode* curr = head;
while(curr != NULL){
ListNode* next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
return prev;
}
};
4.7.1281 - 2023-11-11 15:08:55 +0300 MSK
Links
Code
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int length = nums.size();
int lastNonZeroFoundAt = 0;
for (int i = 0; i < length; ++i) {
if (nums[i] != 0) {
swap(nums[lastNonZeroFoundAt], nums[i]);
lastNonZeroFoundAt += 1;
}
}
}
};
4.7.1282 - 2023-11-11 15:06:06 +0300 MSK
Links
Code
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int lastNonZeroFoundAt = 0;
int length = nums.size();
for (int i = 0; i < length; ++i) {
int num = nums[i];
if (num == 0) {
continue;
}
if (i != lastNonZeroFoundAt) {
nums[lastNonZeroFoundAt] = num;
}
lastNonZeroFoundAt += 1;
}
for (int i = lastNonZeroFoundAt; i < length; i++) {
nums[i] = 0;
}
}
};
4.7.1283 - 2023-11-11 14:51:09 +0300 MSK
Links
Code
class Graph {
public:
vector<vector<pair<int, int>>> adjList;
Graph(int n, vector<vector<int>>& edges) {
adjList.resize(n);
for (auto& e: edges)
adjList[e[0]].push_back(make_pair(e[1], e[2]));
}
void addEdge(vector<int> edge) {
adjList[edge[0]].push_back(make_pair(edge[1], edge[2]));
}
int shortestPath(int node1, int node2) {
int n = adjList.size();
priority_queue<vector<int>, vector<vector<int>>, greater<vector<int>>> pq;
vector<int> costForNode(n, INT_MAX);
costForNode[node1] = 0;
pq.push({0, node1});
while (!pq.empty()) {
int currCost = pq.top()[0];
int currNode = pq.top()[1];
pq.pop();
if (currCost > costForNode[currNode]) {
continue;
}
if (currNode == node2) {
return currCost;
}
for (auto& neighbor : adjList[currNode]) {
int neighborNode = neighbor.first;
int cost = neighbor.second;
int newCost = currCost + cost;
if (newCost < costForNode[neighborNode]) {
costForNode[neighborNode] = newCost;
pq.push({newCost, neighborNode});
}
}
}
return -1;
}
};
4.7.1284 - 2023-11-10 19:50:03 +0300 MSK
Links
Code
class Solution {
public:
string mergeAlternately(string word1, string word2) {
int m = word1.size();
int n = word2.size();
string result = "";
for (int i = 0; i < max(m, n); i++) {
if (i < m) {
result.push_back(word1[i]);
}
if (i < n) {
result.push_back(word2[i]);
}
}
return result;
}
};
4.7.1285 - 2023-11-10 19:49:28 +0300 MSK
Links
Code
class Solution {
public:
string mergeAlternately(string word1, string word2) {
int l1 = word1.size(), l2 = word2.size();
string result = "";
int i = 0, j = 0;
while (i < l1 || j < l2) {
if (i < l1) {
result.push_back(word1[i++]);
}
if (j < l2) {
result.push_back(word2[j++]);
}
}
return result;
}
};
4.7.1286 - 2023-11-10 19:47:59 +0300 MSK
Links
Code
class Solution {
public:
string mergeAlternately(string word1, string word2) {
std::stringstream ans;
int l1 = word1.size(), l2 = word2.size();
int lMax = max(l1, l2);
for (int i = 0; i < lMax; ++i) {
if (i < l1) {
ans << word1[i];
} else {
ans << word2.substr(i);
break;
}
if (i < l2) {
ans << word2[i];
} else {
ans << word1.substr(i + 1);
break;
}
}
return ans.str();
}
};
4.7.1287 - 2023-11-10 19:34:50 +0300 MSK
Links
Code
class SubrectangleQueries {
vector<vector<int>> res;
public:
SubrectangleQueries(vector<vector<int>>& rectangle) {
res=rectangle;
}
void updateSubrectangle(int row1, int col1, int row2, int col2, int newValue) {
for(int i = row1; i <= row2; ++i) {
for(int j= col1; j <= col2; ++j) {
res[i][j] = newValue;
}
}
}
int getValue(int row, int col) {
return res[row][col];
}
};
/**
* Your SubrectangleQueries object will be instantiated and called as such:
* SubrectangleQueries* obj = new SubrectangleQueries(rectangle);
* obj->updateSubrectangle(row1,col1,row2,col2,newValue);
* int param_2 = obj->getValue(row,col);
*/
4.7.1288 - 2023-11-10 19:18:28 +0300 MSK
Links
Code
class SubrectangleQueries {
public:
std::vector<std::vector<int>> rectangle;
std::vector<std::array<int, 5>> updates;
SubrectangleQueries(vector<vector<int>>& rectangle) {
this->rectangle = rectangle;
}
void updateSubrectangle(int row1, int col1, int row2, int col2, int newValue) {
this->updates.push_back({row1, col1, row2, col2, newValue});
}
int getValue(int row, int col) {
int length = this->updates.size();
for (int i = length - 1; i >= 0; --i) {
auto const [row1, col1, row2, col2, newValue] = this->updates[i];
if (row < row1 || row > row2 || col < col1 || col > col2) {
continue;
}
return newValue;
}
return this->rectangle[row][col];
}
};
/**
* Your SubrectangleQueries object will be instantiated and called as such:
* SubrectangleQueries* obj = new SubrectangleQueries(rectangle);
* obj->updateSubrectangle(row1,col1,row2,col2,newValue);
* int param_2 = obj->getValue(row,col);
*/
4.7.1289 - 2023-11-10 18:37:59 +0300 MSK
Links
Code
class LockingTree {
public:
std::vector<int> parents, locked;
std::vector<std::vector<int>> children;
LockingTree(vector<int>& parent) {
int length = parent.size();
this->children.resize(length);
this->locked.resize(length, -1);
this->parents = parent;
for (int i = 1; i < length; ++i) {
this->children[this->parents[i]].push_back(i);
}
}
bool lock(int num, int user) {
if (this->locked[num] != -1) {
return false;
}
this->locked[num] = user;
return true;
}
bool unlock(int num, int user) {
if (this->locked[num] != user) {
return false;
}
this->locked[num] = -1;
return true;
}
bool upgrade(int num, int user) {
if (this->locked[num] != -1) {
return false;
}
int parent = this->parents[num];
while (parent != -1) {
if (this->locked[parent] != -1) {
return false;
}
parent = this->parents[parent];
}
if (!this->unlockDesc(num)) {
return false;
}
this->locked[num] = user;
return true;
}
bool unlockDesc(int parent) {
bool hasLocked = false;
for (auto const& child : this->children[parent]) {
if (this->locked[child] != -1) {
this->locked[child] = -1;
hasLocked = true;
}
bool descHasLocked = unlockDesc(child);
if (descHasLocked) {
hasLocked = true;
}
}
return hasLocked;
}
};
/**
* Your LockingTree object will be instantiated and called as such:
* LockingTree* obj = new LockingTree(parent);
* bool param_1 = obj->lock(num,user);
* bool param_2 = obj->unlock(num,user);
* bool param_3 = obj->upgrade(num,user);
*/
4.7.1290 - 2023-11-10 16:30:33 +0300 MSK
Links
Code
class MyStack {
public:
std::vector<int> v;
MyStack() {
this->v = {};
}
void push(int x) {
this->v.push_back(x);
}
int pop() {
int last = this->v.back();
this->v.pop_back();
return last;
}
int top() {
return this->v.back();
}
bool empty() {
return this->v.empty();
}
};
/**
* Your MyStack object will be instantiated and called as such:
* MyStack* obj = new MyStack();
* obj->push(x);
* int param_2 = obj->pop();
* int param_3 = obj->top();
* bool param_4 = obj->empty();
*/
4.7.1291 - 2023-11-10 13:30:38 +0300 MSK
Links
Code
func restoreArray(adjacentPairs [][]int) []int {
// [[2,1],[3,4],[3,2]]
// 1: [2]
// 2: [1, 3]
// 3: [2, 4]
// 4: [3]
// Output: [1,2,3,4]
graph := map[int][]int{}
length := len(adjacentPairs) + 1
ans := make([]int, length)
for _, pair := range adjacentPairs {
num1, num2 := pair[0], pair[1]
graph[num1] = append(graph[num1], num2)
graph[num2] = append(graph[num2], num1)
}
for node, edges := range graph {
if len(edges) == 1 {
ans[0], ans[1] = node, edges[0]
break
}
}
cur, prev := ans[1], ans[0]
for i := 2; i < length; i++ {
for _, target := range graph[cur] {
if target != prev {
ans[i] = target
cur, prev = target, cur
break
}
}
}
return ans
}
4.7.1292 - 2023-11-10 13:24:56 +0300 MSK
Links
Code
func restoreArray(adjacentPairs [][]int) []int {
// [[2,1],[3,4],[3,2]]
// 1: [2]
// 2: [1, 3]
// 3: [2, 4]
// 4: [3]
// Output: [1,2,3,4]
graph := map[int][]int{}
for _, pair := range adjacentPairs {
num1, num2 := pair[0], pair[1]
graph[num1] = append(graph[num1], num2)
graph[num2] = append(graph[num2], num1)
}
length := len(adjacentPairs) + 1
ans := make([]int, length)
for node, edges := range graph {
if len(edges) == 1 {
ans[0], ans[1] = node, edges[0]
break
}
}
for i := 2; i < length; i++ {
cur, prev := ans[i-1], ans[i-2]
for _, target := range graph[cur] {
if target != prev {
ans[i] = target
}
}
}
return ans
}
4.7.1293 - 2023-11-09 10:03:41 +0300 MSK
Links
Code
func countHomogenous(s string) int {
var (
mod int64 = 1000000007
total int64 = 0
count int64 = 0
cur = s[0]
)
for i := 0; i < len(s); i++ {
char := s[i]
if char == cur {
count++
} else {
count = 1
cur = char
}
total += count
}
return int(total % mod)
}
4.7.1294 - 2023-11-08 11:09:02 +0300 MSK
Links
Code
func isReachableAtTime(sx int, sy int, fx int, fy int, t int) bool {
vert := abs(sy, fy)
dist := vert + max(0, abs(sx, fx) - vert)
if dist == 0 && t == 1 {
return false
}
return dist <= t
}
func abs(x, y int) int {
if x > y {
return x - y
}
return y - x
}
4.7.1295 - 2023-11-07 21:56:45 +0300 MSK
Links
Code
type MyHashSet struct {
m map[int]struct{}
}
func Constructor() MyHashSet {
return MyHashSet{map[int]struct{}{}}
}
func (this *MyHashSet) Add(key int) {
this.m[key] = struct{}{}
}
func (this *MyHashSet) Remove(key int) {
delete(this.m, key)
}
func (this *MyHashSet) Contains(key int) bool {
_, ok := this.m[key]
return ok
}
/**
* Your MyHashSet object will be instantiated and called as such:
* obj := Constructor();
* obj.Add(key);
* obj.Remove(key);
* param_3 := obj.Contains(key);
*/
4.7.1296 - 2023-11-07 21:50:49 +0300 MSK
Links
Code
func mergeAlternately(word1 string, word2 string) string {
var sb strings.Builder
length1, length2 := len(word1), len(word2)
for i := 0; i < max(length1, length2); i++ {
if i == length1 {
sb.WriteString(word2[i:length2])
break
}
if i == length2 {
sb.WriteString(word1[i:length1])
break
}
sb.WriteByte(word1[i])
sb.WriteByte(word2[i])
}
return sb.String()
}
4.7.1297 - 2023-11-07 19:07:48 +0300 MSK
Links
Code
func eliminateMaximum(dist []int, speed []int) int {
arrival := []float32{}
length := len(dist)
for i := 0; i < length; i++ {
arrival = append(arrival, float32(dist[i]) / float32(speed[i]))
}
slices.Sort(arrival)
ans := 0
for i := 0; i < length; i++ {
if arrival[i] <= float32(i) {
break
}
ans += 1
}
return ans
}
4.7.1298 - 2023-11-06 18:41:34 +0300 MSK
Links
Code
type MyCircularDeque struct {
list []int
size int
}
func Constructor(k int) MyCircularDeque {
return MyCircularDeque{[]int{}, k}
}
func (this *MyCircularDeque) InsertFront(value int) bool {
if this.IsFull() {
return false
}
this.list = append([]int{value}, this.list...)
return true
}
func (this *MyCircularDeque) InsertLast(value int) bool {
if this.IsFull() {
return false
}
this.list = append(this.list, value)
return true
}
func (this *MyCircularDeque) DeleteFront() bool {
if this.IsEmpty() {
return false
}
this.list = this.list[1:]
return true
}
func (this *MyCircularDeque) DeleteLast() bool {
if this.IsEmpty() {
return false
}
this.list = this.list[:len(this.list) - 1]
return true
}
func (this *MyCircularDeque) GetFront() int {
if this.IsEmpty() {
return -1
}
return this.list[0]
}
func (this *MyCircularDeque) GetRear() int {
if this.IsEmpty() {
return -1
}
return this.list[len(this.list) - 1]
}
func (this *MyCircularDeque) IsEmpty() bool {
return len(this.list) == 0
}
func (this *MyCircularDeque) IsFull() bool {
return len(this.list) == this.size
}
/**
* Your MyCircularDeque object will be instantiated and called as such:
* obj := Constructor(k);
* param_1 := obj.InsertFront(value);
* param_2 := obj.InsertLast(value);
* param_3 := obj.DeleteFront();
* param_4 := obj.DeleteLast();
* param_5 := obj.GetFront();
* param_6 := obj.GetRear();
* param_7 := obj.IsEmpty();
* param_8 := obj.IsFull();
*/
4.7.1299 - 2023-11-06 14:57:33 +0300 MSK
Links
Code
type SeatManager struct {
heap *binaryheap.Heap
}
func Constructor(n int) SeatManager {
heap := binaryheap.NewWithIntComparator()
for i := 1; i <= n; i++ {
heap.Push(i)
}
return SeatManager{heap}
}
func (this *SeatManager) Reserve() int {
val, _ := this.heap.Pop()
return val.(int)
}
func (this *SeatManager) Unreserve(seatNumber int) {
this.heap.Push(seatNumber)
}
/**
* Your SeatManager object will be instantiated and called as such:
* obj := Constructor(n);
* param_1 := obj.Reserve();
* obj.Unreserve(seatNumber);
*/
4.7.1300 - 2023-11-06 14:49:27 +0300 MSK
Links
Code
type SeatManager struct {
seats []bool
}
func Constructor(n int) SeatManager {
return SeatManager{make([]bool, n)}
}
func (this *SeatManager) Reserve() int {
for i, num := range this.seats {
if !num {
this.seats[i] = true
return i + 1
}
}
return -1
}
func (this *SeatManager) Unreserve(seatNumber int) {
this.seats[seatNumber-1] = false
}
/**
* Your SeatManager object will be instantiated and called as such:
* obj := Constructor(n);
* param_1 := obj.Reserve();
* obj.Unreserve(seatNumber);
*/
4.7.1301 - 2023-11-05 21:02:40 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
type Codec struct {
}
func Constructor() Codec {
return Codec{}
}
// Serializes a tree to a single string.
func (this *Codec) serialize(root *TreeNode) string {
if root == nil {
return ""
}
var buffer bytes.Buffer
queue := []*TreeNode{root}
for length := len(queue); length > 0; length = len(queue) {
for i := 0; i < length; i++ {
node := queue[i]
if node != nil {
buffer.WriteString(strconv.Itoa(node.Val))
queue = append(queue, node.Left, node.Right)
}
buffer.WriteString(",")
}
queue = queue[length:]
}
ans := buffer.String()
return ans[:len(ans)-1]
}
// Deserializes your encoded data to tree.
func (this *Codec) deserialize(data string) *TreeNode {
nodes := []*TreeNode{}
for _, str := range strings.Split(data, ",") {
if str == "" {
nodes = append(nodes, nil)
} else {
num, _ := strconv.Atoi(str)
nodes = append(nodes, &TreeNode{num, nil, nil})
}
}
start := 0
length := len(nodes)
for _, node := range nodes {
if node == nil {
continue
}
left, right := 2 * start + 1, 2 * start + 2
if left < length {
node.Left = nodes[left]
}
if right < length {
node.Right = nodes[right]
}
start++
}
return nodes[0]
}
/**
* Your Codec object will be instantiated and called as such:
* ser := Constructor();
* deser := Constructor();
* data := ser.serialize(root);
* ans := deser.deserialize(data);
*/
4.7.1302 - 2023-11-05 12:06:04 +0300 MSK
Links
Code
func getWinner(arr []int, k int) int {
if k == 1 {
return max(arr[0], arr[1])
}
length := len(arr)
if k >= length {
return slices.Max(arr)
}
curWinner, winCount := arr[0], 0
for _, num := range arr[1:] {
if curWinner > num {
winCount++
} else {
curWinner = num
winCount = 1
}
if winCount == k {
return curWinner
}
}
return curWinner
}
4.7.1303 - 2023-11-05 12:01:59 +0300 MSK
Links
Code
func getWinner(arr []int, k int) int {
curMax, winCount := arr[0], 0
i, length := 1, len(arr)
for {
num := arr[i]
if num > curMax {
curMax = num
winCount = 1
} else {
winCount++
}
if winCount == k {
return curMax
}
i = (i + 1) % length
}
return -1
}
4.7.1304 - 2023-11-04 13:31:04 +0300 MSK
Links
Code
type MaxHeap []int
func (m MaxHeap) Len() int { return len(m) }
func (m MaxHeap) Less(i, j int) bool { return m[i] > m[j] }
func (m MaxHeap) Swap(i, j int) { m[i], m[j] = m[j], m[i] }
func (m *MaxHeap) Pop() interface{} {
v := (*m)[len(*m)-1]
*m = (*m)[:len(*m)-1]
return v
}
func (m *MaxHeap) Push(v interface{}) { *m = append(*m, v.(int)) }
func (m MaxHeap) Top() int { return m[0] }
type MinHeap []int
func (m MinHeap) Len() int { return len(m) }
func (m MinHeap) Less(i, j int) bool { return m[i] < m[j] }
func (m MinHeap) Swap(i, j int) { m[i], m[j] = m[j], m[i] }
func (m *MinHeap) Pop() interface{} {
v := (*m)[len(*m)-1]
*m = (*m)[:len(*m)-1]
return v
}
func (m *MinHeap) Push(v interface{}) { *m = append(*m, v.(int)) }
func (m MinHeap) Top() int { return m[0] }
type MedianFinder struct {
left MaxHeap
right MinHeap
}
func Constructor() MedianFinder {
return MedianFinder{}
}
func (mf *MedianFinder) AddNum(num int) {
if len(mf.left) + len(mf.right) == 0 {
heap.Push(&(mf.left), num)
return
}
for {
if len(mf.left) < len(mf.right) {
if num <= mf.right.Top() {
heap.Push(&(mf.left), num)
return
} else {
v := heap.Pop(&(mf.right))
heap.Push(&(mf.left), v)
}
} else {
if num >= mf.left.Top() {
heap.Push(&(mf.right), num)
return
} else {
v := heap.Pop(&(mf.left))
heap.Push(&(mf.right), v)
}
}
}
}
func (mf *MedianFinder) FindMedian() float64 {
if len(mf.left) == len(mf.right) {
return float64(mf.left.Top() + mf.right.Top()) / 2.0
} else if len(mf.left) > len(mf.right) {
return float64(mf.left.Top())
} else {
return float64(mf.right.Top())
}
}
4.7.1305 - 2023-11-04 13:30:46 +0300 MSK
Links
Code
type Project struct {
profit, capital int
}
type IntHeap []int
func (h IntHeap) Len() int { return len(h) }
func (h IntHeap) Less(i, j int) bool { return h[i] > h[j] }
func (h IntHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *IntHeap) Push(x interface{}) { *h = append(*h, x.(int)) }
func (h *IntHeap) Pop() interface{} {
old := *h
n := len(old)
x := old[n-1]
*h = old[0 : n-1]
return x
}
func findMaximizedCapital(k int, w int, profits []int, capital []int) int {
n := len(profits)
projects := make([]Project, n)
for i := range profits {
projects[i] = Project{profits[i], capital[i]}
}
sort.Slice(projects, func (i, j int) bool {
return projects[i].capital < projects[j].capital
})
q := &IntHeap{}
heap.Init(q)
ptr := 0
for i := 0; i < k; i++ {
for ptr < n && projects[ptr].capital <= w {
heap.Push(q, projects[ptr].profit)
ptr++
}
if q.Len() == 0 {
break
}
w += heap.Pop(q).(int)
}
return w
}
4.7.1306 - 2023-11-04 13:30:28 +0300 MSK
Links
Code
func findPeakElement(nums []int) int {
left := 0
right := len(nums) - 1
for left < right {
mid := left + (right - left) / 2
if nums[mid] > nums[mid+1] {
// The peak is in the left half
right = mid
} else {
// The peak is in the right half
left = mid + 1
}
}
return left
}
4.7.1307 - 2023-11-04 13:30:08 +0300 MSK
Links
Code
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func mergeKLists(lists []*ListNode) *ListNode {
n:=len(lists)
if n==0{
return nil
}
curr:=lists[0]
if n==1{
return curr
}
for i:=1;i<n;i++{
curr=mergeList(curr,lists[i])
}
return curr
}
func mergeList(l1,l2 *ListNode) *ListNode {
head:=&ListNode{}
curr:=head
for l1!=nil && l2!=nil{
if l1.Val<l2.Val{
curr.Next=l1
l1=l1.Next
curr=curr.Next
}else{
curr.Next=l2
l2=l2.Next
curr=curr.Next
}
}
if l1 != nil {
curr.Next = l1
} else if l2 != nil {
curr.Next = l2
}
return head.Next
}
4.7.1308 - 2023-11-04 13:29:52 +0300 MSK
Links
Code
/**
* Definition for a QuadTree node.
* type Node struct {
* Val bool
* IsLeaf bool
* TopLeft *Node
* TopRight *Node
* BottomLeft *Node
* BottomRight *Node
* }
*/
func construct(grid [][]int) *Node {
var dfs func(y0, x0, width int) *Node
dfs = func(y0, x0, width int) *Node {
if width == 1 {
return &Node{
Val: grid[y0][x0] == 1,
IsLeaf: true,
}
}
w := width / 2
topLeft := dfs(y0, x0, w)
topRight := dfs(y0, x0+w, w)
bottomLeft := dfs(y0+w, x0, w)
bottomRight := dfs(y0+w, x0+w, w)
var node *Node
if topLeft.Val == topRight.Val && bottomLeft.Val == bottomRight.Val && topLeft.Val == bottomLeft.Val &&
topLeft.IsLeaf && topRight.IsLeaf && bottomLeft.IsLeaf && bottomRight.IsLeaf {
node = &Node{
Val: topLeft.Val,
IsLeaf: true,
}
} else {
node = &Node{
Val: true,
IsLeaf: false,
TopLeft: topLeft,
TopRight: topRight,
BottomLeft: bottomLeft,
BottomRight: bottomRight,
}
}
return node
}
return dfs(0, 0, len(grid))
}
4.7.1309 - 2023-11-04 13:29:35 +0300 MSK
Links
Code
func totalNQueens(n int) int {
sCol:=make([]bool,n)
sD1:=make([]bool,2*n)
sD2:=make([]bool,2*n)
return helper(0,n,sCol,sD1,sD2)
}
func helper(r,n int,sCol,sD1,sD2 []bool) int{
if r==n{
return 1
}
res:=0
for i:=0; i < n; i++ {
if !sCol[i] && !sD1[i+r] && !sD2[(r-i)+n]{
// board[r][i]=true
sCol[i]=true
sD1[i+r]=true
sD2[(r-i)+n]=true
res=res+helper(r+1,n,sCol,sD1,sD2)
// board[r][i]=false
sCol[i]=false
sD1[i+r]=false
sD2[(r-i)+n]=false
}
}
return res
}
4.7.1310 - 2023-11-04 13:29:17 +0300 MSK
Links
Code
type Node struct {
children [26]*Node
word string
}
func (n *Node) Insert(word string) {
cur := n
for _, c := range word {
idx := c - 'a'
if cur.children[idx] == nil {
cur.children[idx] = &Node{}
}
cur = cur.children[idx]
}
cur.word = word
}
func (n *Node) IsEmpty() bool {
for _, child := range n.children {
if child != nil {
return false
}
}
return true
}
func (n *Node) Remove(word string) bool {
if len(word) == 0 {
n.word = ""
return n.IsEmpty()
}
child := n.children[word[0]-'a']
if child.Remove(word[1:]) {
n.children[word[0]-'a'] = nil
return n.IsEmpty()
}
return false
}
func dfs(board [][]byte, r, c int, root, cur *Node, res *[]string) {
rc := board[r][c]
board[r][c] = 0
if cur.word != "" {
*res = append(*res, cur.word)
root.Remove(cur.word)
}
ds := [5]int{0, 1, 0, -1, 0}
for i := 0; i < len(ds)-1; i++ {
dr, dc := r+ds[i], c+ds[i+1]
if dr < 0 || dr >= len(board) || dc < 0 || dc >= len(board[0]) {
continue
}
b := board[dr][dc]
if b == 0 || cur.children[b-'a'] == nil {
continue
}
dfs(board, dr, dc, root, cur.children[b-'a'], res)
}
board[r][c] = rc
}
func findWords(board [][]byte, words []string) []string {
m, n := len(board), len(board[0])
res, trie, has := []string{}, &Node{}, map[string]bool{}
for r := 0; r < m; r++ {
for c := 0; c < n-1; c++ {
p := string(board[r][c]) + string(board[r][c+1])
has[p] = true
}
}
for r := 0; r < m-1; r++ {
for c := 0; c < n; c++ {
p := string(board[r][c]) + string(board[r+1][c])
has[p] = true
}
}
for _, word := range words {
valid := true
for i := 0; i < len(word)-1; i++ {
a, b := string(word[i]), string(word[i+1])
if !has[a+b] && !has[b+a] {
valid = false
break
}
}
if valid {
trie.Insert(word)
}
}
for r := 0; r < m; r++ {
for c := 0; c < n; c++ {
b := board[r][c]
if trie.children[b-'a'] != nil {
dfs(board, r, c, trie, trie.children[b-'a'], &res)
}
}
}
return res
}
4.7.1311 - 2023-11-04 13:28:50 +0300 MSK
Links
Code
func ladderLength(beginWord string, endWord string, wordList []string) int {
set := make(map[string]struct{}, len(wordList))
present := false
for _, v := range wordList {
if endWord == v {
present = true
}
set[v] = struct{}{}
}
if !present {
return 0
}
set[beginWord] = struct{}{}
q := []string{beginWord}
depth := 1
breadth := 0
breadth = len(q)
for ;breadth > 0; {
s := q[0]
if s == endWord {
return depth
}
for i:='a'; i <= 'z'; i += 1 {
for j := 0; j<len(s); j++ {
if rune(s[j]) != i {
temp := s[:j] + string(i) + s[j+1:]
if _, ok := set[temp]; !ok {
continue
}
q = append(q, temp)
delete(set, s)
}
}
}
q = q[1:]
breadth -= 1
if breadth == 0 {
breadth = len(q)
depth += 1
}
}
return 0
}
4.7.1312 - 2023-11-04 13:28:04 +0300 MSK
Links
Code
func findOrder(numCourses int, prerequisites [][]int) []int {
//build the graph
graph := make([][]int,numCourses)
in_degree := make([]int,numCourses)
for _,v := range prerequisites{
graph[v[1]] = append(graph[v[1]], v[0])
in_degree[v[0]]++
}
frontier := []int{}
for i,v := range in_degree{
if v==0{
frontier = append(frontier,i)
}
}
result := []int{}
for len(frontier)!=0{
cur := frontier[0]
frontier = frontier[1:]
result = append(result,cur)
for _,v := range graph[cur]{
in_degree[v]--
if in_degree[v]==0{
frontier = append(frontier,v)
}
}
}
if len(result)==numCourses{
return result
}
return []int{}
}
4.7.1313 - 2023-11-04 13:27:48 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func maxPathSum(root *TreeNode) int {
ans := -1 << 63
maxPath(root, &ans)
return ans
}
func maxPath(root *TreeNode, ans *int) int {
if root == nil {
return 0
}
leftPathSum := maxPath(root.Left, ans)
rightPathSum := maxPath(root.Right, ans)
*ans = max(*ans, leftPathSum + rightPathSum + root.Val)
return max(max(leftPathSum+root.Val, rightPathSum+root.Val), 0)
}
func max(a int, b int) int {
if (a >= b) {
return a
}
return b
}
4.7.1314 - 2023-11-04 13:27:29 +0300 MSK
Links
Code
func buildTree(inorder []int, postorder []int) *TreeNode {
n := len(postorder)
if n == 0 {
return nil
}
pivotId := 0
for pivotId < n && inorder[pivotId] != postorder[n-1] {
pivotId++
}
root := new(TreeNode)
root.Val = postorder[n-1]
root.Left = buildTree(inorder[:pivotId], postorder[:pivotId])
root.Right = buildTree(inorder[pivotId+1:], postorder[pivotId:n-1])
return root
}
4.7.1315 - 2023-11-04 13:27:12 +0300 MSK
Links
Code
func buildTree(preorder []int, inorder []int) *TreeNode {
n := len(inorder)
if n == 0 {
return nil
}
pv := preorder[0]
pi := 0
for pi < n && inorder[pi] != pv {
pi++
}
ans := new(TreeNode)
ans.Val = pv
ans.Left = buildTree(preorder[1:], inorder[:pi])
ans.Right = buildTree(preorder[1+pi:], inorder[pi+1:])
return ans
}
4.7.1316 - 2023-11-04 13:26:43 +0300 MSK
Links
Code
func reverseKGroup(head *ListNode, k int) *ListNode {
node, cnt := head, 0
for cnt < k {
if node == nil {
return head
}
node = node.Next
cnt++
}
prev := reverseKGroup(node, k)
for cnt > 0 {
next := head.Next
head.Next = prev
prev = head
head = next
cnt--
}
return prev
}
4.7.1317 - 2023-11-04 13:25:42 +0300 MSK
Links
Code
func findMinArrowShots(points [][]int) int {
// greedy solution
sort.Slice(points, func(i, j int) bool {
return points[i][1] < points[j][1]
})
count := 1
end := points[0][1]
for i := 1; i < len(points); i++ {
if points[i][0] > end {
count++
end = points[i][1]
}
}
return count
}
4.7.1318 - 2023-11-04 13:25:15 +0300 MSK
Links
Code
func minWindow(s string, t string) string {
m := len(s)
n := len(t)
if m == 0 || n == 0 || m < n {
return ""
}
dict := make(map[byte]int)
for i := 0; i < n; i++ {
dict[t[i]]++
}
// required unique chars
required := len(dict)
actual := 0
window := make(map[byte]int)
minSize := math.MaxInt64
start := 0
left, right := 0, 0
for end := 0; end < m; end++ {
c := s[end]
window[c]++
if value, ok := dict[c]; ok {
if value == window[c] {
actual++
}
}
for start <= end && actual == required {
size := end-start+1
if size < minSize {
minSize = size
left = start
right = end
}
rc := s[start]
window[rc]--
if value, ok := dict[rc]; ok {
if value > window[rc] {
actual--
}
}
start++
}
}
if minSize == math.MaxInt64 {
return ""
}
return s[left:right+1]
}
4.7.1319 - 2023-11-04 13:24:58 +0300 MSK
Links
Code
func findSubstring(s string, words []string) []int {
wordLen := len(words[0])
totalWords := len(words)
mem := make(map[string]int, totalWords)
for _, str := range words {
mem[str] += 1
}
temp := make(map[string]int, totalWords)
var found bool
result := make([]int, 0)
for i:=0; i + wordLen*totalWords <= len(s); {
found = true
temp = make(map[string]int, totalWords)
for j := i; j < i + wordLen*totalWords; j += wordLen {
if _, ok := mem[ s[j:j+wordLen] ]; ok {
temp[ s[j:j+wordLen] ] += 1
} else {
found = false
break
}
}
if found {
for key, _ := range mem {
if val, ok := temp[key]; !ok || val != mem[key]{
i++
found = false
break
}
}
if found {
result = append(result, i)
i += 1
}
} else {
i++
}
}
return result
}
4.7.1320 - 2023-11-04 13:23:30 +0300 MSK
Links
Code
func insert(intervals [][]int, new []int) [][]int {
n := len(intervals)
i := sort.Search(n, func(i int) bool { return intervals[i][0] > new[0] })
j := sort.Search(n, func(j int) bool { return intervals[j][1] > new[1] })
if i >= 1 && new[0] <= intervals[i-1][1] {
new[0] = intervals[i-1][0]
i--
}
if j < n && new[1] >= intervals[j][0] {
new[1] = intervals[j][1]
j++
}
return append(intervals[:i], append([][]int{new}, intervals[j:]...)...)
}
4.7.1321 - 2023-11-04 13:22:41 +0300 MSK
Links
Code
func calculate(s string) int {
result, _ := calculateFrom(s, 0)
return result
}
func calculateFrom(s string, idFrom int) (result, idEnd int) {
result, currNum, sign := 0, 0, 1
for idEnd = idFrom; idEnd < len(s) && s[idEnd] != ')'; idEnd++ {
switch {
case s[idEnd] >= '0':
currNum = currNum*10 + int(s[idEnd]-'0')
case s[idEnd] == '(':
currNum, idEnd = calculateFrom(s, idEnd+1)
case s[idEnd] == '-' || s[idEnd] == '+':
result, currNum = result+currNum*sign, 0
sign = 44 - int(s[idEnd]) // '-'=45; '+'=43
}
}
return result + currNum*sign, idEnd
}
4.7.1322 - 2023-11-04 10:36:18 +0300 MSK
Links
Code
func getLastMoment(n int, left []int, right []int) int {
return max(slices.Max(append(left, 0)), n - slices.Min(append(right, n)))
}
4.7.1323 - 2023-11-04 10:30:12 +0300 MSK
Links
Code
func getLastMoment(n int, left []int, right []int) int {
maxLeft := 0
for _, val := range left {
if val > maxLeft {
maxLeft = val
}
}
minRight := n
for _, val := range right {
if val < minRight {
minRight = val
}
}
return max(maxLeft, n - minRight)
}
4.7.1324 - 2023-11-04 10:29:26 +0300 MSK
Links
Code
func getLastMoment(n int, left []int, right []int) int {
maxLeft := 0
for _, val := range left {
if val > maxLeft {
maxLeft = val
}
}
minRight := n
for _, val := range right {
if val < minRight {
minRight = val
}
}
return max(maxLeft, n - minRight)
}
4.7.1325 - 2023-11-03 15:20:27 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func kthSmallest(root *TreeNode, k int) int {
heap := binaryheap.NewWithIntComparator()
queue := []*TreeNode{root}
for length := len(queue); length > 0; length = len(queue) {
for i := 0; i < length; i++ {
node := queue[i]
if node == nil {
continue
}
heap.Push(node.Val)
queue = append(queue, node.Left, node.Right)
}
queue = queue[length:]
}
var answer any
for i := 0; i < k; i++ {
answer, _ = heap.Pop()
}
return answer.(int)
}
4.7.1326 - 2023-11-03 12:40:06 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func flatten(root *TreeNode) {
if root == nil {
return
}
right := root.Right
root.Right = nil
list := &TreeNode{0, nil, nil}
listTail := flattenNode(root, list)
if right != nil {
flattenNode(right, listTail)
}
}
func flattenNode(node, listTail *TreeNode) *TreeNode {
left, right := node.Left, node.Right
node.Left, node.Right = nil, nil
listTail.Right = node
listTail = listTail.Right
if left != nil {
listTail = flattenNode(left, listTail)
}
if right != nil {
listTail = flattenNode(right, listTail)
}
return listTail
}
4.7.1327 - 2023-11-03 12:14:46 +0300 MSK
Links
Code
func buildArray(target []int, n int) []string {
ops := []string{}
length := len(target)
matchNext, matchNextVal := 0, target[0]
for i := 1; i <= n; i++ {
if i == matchNextVal {
ops = append(ops, "Push")
matchNext += 1
if matchNext == length {
break
}
matchNextVal = target[matchNext]
} else {
ops = append(ops, "Push", "Pop")
}
}
return ops
}
4.7.1328 - 2023-11-03 12:13:05 +0300 MSK
Links
Code
func buildArray(target []int, n int) []string {
ops := []string{}
length := len(target)
matchNext := 0
for i := 1; i <= n; i++ {
if matchNext == length {
break
}
ops = append(ops, "Push")
if i == target[matchNext] {
matchNext += 1
} else {
ops = append(ops, "Pop")
}
}
return ops
}
4.7.1329 - 2023-11-02 14:33:34 +0300 MSK
Links
Code
func sortList(head *ListNode) *ListNode {
if head == nil || head.Next == nil {
return head
}
if head.Next.Next == nil {
a := head
b := head.Next
if a.Val <= b.Val {
a.Next = b
b.Next = nil
return a
} else {
b.Next = a
a.Next = nil
return b
}
}
slow := head
fast := head
for fast != nil && fast.Next != nil {
slow = slow.Next
fast = fast.Next.Next
}
nextList := slow.Next
slow.Next = nil
list1 := sortList(head)
list2 := sortList(nextList)
dummy := &ListNode{Val: -1, Next: nil}
it := dummy
for list1 != nil && list2 != nil {
if list1.Val <= list2.Val {
it.Next = list1
list1 = list1.Next
} else {
it.Next = list2
list2 = list2.Next
}
it = it.Next
}
if list1 != nil {
it.Next = list1
} else {
it.Next = list2
}
return dummy.Next
}
4.7.1330 - 2023-11-02 13:32:46 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func averageOfSubtree(root *TreeNode) int {
_, _, answer := getAverage(root)
return answer
}
func getAverage(root *TreeNode) (int, int, int) {
if root == nil {
return 0, 0, 0
}
sum, count, validNodes := root.Val, 1, 0
leftSum, leftCount, leftValidNodes := getAverage(root.Left)
rightSum, rightCount, rightValidNodes := getAverage(root.Right)
validNodes += leftValidNodes + rightValidNodes
sum += leftSum + rightSum
count += leftCount + rightCount
if sum / count == root.Val {
validNodes += 1
}
return sum, count, validNodes
}
4.7.1331 - 2023-11-01 15:59:19 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
type queueItem struct {
node *TreeNode
sum int
}
func sumNumbers(root *TreeNode) int {
if root == nil {
return 0
}
queue := []queueItem{queueItem{root, 0}}
sum := 0
for length := len(queue); length > 0; length = len(queue) {
for i := 0; i < length; i++ {
item := queue[i]
if item.node == nil {
continue
}
left, right, newVal := item.node.Left, item.node.Right, item.node.Val + item.sum * 10
if left == nil && right == nil {
sum += newVal
} else {
queue = append(queue, queueItem{left, newVal}, queueItem{right, newVal})
}
}
queue = queue[length:]
}
return sum
}
4.7.1332 - 2023-11-01 15:51:19 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func sumNumbers(root *TreeNode) int {
return getSum(root, 0)
}
func getSum(root *TreeNode, parentVal int) int {
if root == nil {
return 0
}
newVal := root.Val + parentVal * 10
if root.Left == nil && root.Right == nil {
return newVal
}
return getSum(root.Left, newVal) + getSum(root.Right, newVal)
}
4.7.1333 - 2023-11-01 15:01:54 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
if root == nil {
return nil
}
if root == p || root == q {
return root
}
left, right := lowestCommonAncestor(root.Left, p, q), lowestCommonAncestor(root.Right, p, q)
if left != nil && right != nil {
return root
}
if left != nil {
return left
}
return right
}
4.7.1334 - 2023-11-01 15:00:05 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
isAncestorMap := map[int][2]bool{}
dfs(root, p, q, isAncestorMap)
isAncestor := func (node *TreeNode) bool {
if node == nil {
return false
}
hasNodes := isAncestorMap[node.Val]
return hasNodes[0] && hasNodes[1]
}
for {
left, right := root.Left, root.Right
if isAncestor(left) {
root = left
} else if isAncestor(right) {
root = right
} else {
break
}
}
return root
}
func dfs(root, p, q *TreeNode, isAncestorMap map[int][2]bool) (bool, bool) {
if root == nil {
return false, false
}
hasPLeft, hasQLeft := dfs(root.Left, p, q, isAncestorMap)
hasPRight, hasQRight := dfs(root.Right, p, q, isAncestorMap)
hasP, hasQ := hasPLeft || hasPRight, hasQLeft || hasQRight
if root == p {
hasP = true
}
if root == q {
hasQ = true
}
isAncestorMap[root.Val] = [2]bool{hasP, hasQ}
return hasP, hasQ
}
4.7.1335 - 2023-11-01 12:34:06 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func findMode(root *TreeNode) []int {
if root == nil {
return []int{}
}
counter := map[int]int{}
queue := []*TreeNode{root}
for length := len(queue); length > 0; length = len(queue) {
for i := 0; i < length; i++ {
node := queue[i]
if node == nil {
continue
}
left, right, val := node.Left, node.Right, node.Val
if _, ok := counter[val]; ok {
counter[val] += 1
} else {
counter[val] = 1
}
queue = append(queue, left, right)
}
queue = queue[length:]
}
maxCount, answer := 0, []int{}
for key, count := range counter {
if count < maxCount {
continue
}
if count > maxCount {
answer = answer[:0]
maxCount = count
}
answer = append(answer, key)
}
return answer
}
4.7.1336 - 2023-11-01 12:32:26 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func findMode(root *TreeNode) []int {
if root == nil {
return []int{}
}
counter := map[int]int{}
queue := []*TreeNode{root}
for length := len(queue); length > 0; length = len(queue) {
for i := 0; i < length; i++ {
node := queue[i]
if node == nil {
continue
}
if val, ok := counter[node.Val]; ok {
counter[node.Val] = val + 1
} else {
counter[node.Val] = 1
}
queue = append(queue, node.Left, node.Right)
}
queue = queue[length:]
}
maxCount, answer := 0, []int{}
for key, count := range counter {
if count < maxCount {
continue
}
if count > maxCount {
answer = answer[:0]
maxCount = count
}
answer = append(answer, key)
}
return answer
}
4.7.1337 - 2023-11-01 12:28:17 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func findMode(root *TreeNode) []int {
if root == nil {
return []int{}
}
counter := map[int]int{}
dfs(root, counter)
maxCount, answer := 0, []int{}
for key, count := range counter {
if count < maxCount {
continue
}
if count > maxCount {
answer = answer[:0]
maxCount = count
}
answer = append(answer, key)
}
return answer
}
func dfs(root *TreeNode, counter map[int]int) {
if root == nil {
return
}
if _, ok := counter[root.Val]; ok {
counter[root.Val] += 1
} else {
counter[root.Val] = 1
}
dfs(root.Left, counter)
dfs(root.Right, counter)
}
4.7.1338 - 2023-11-01 12:20:58 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func findMode(root *TreeNode) []int {
if root == nil {
return []int{}
}
counter := map[int]int{}
queue := []*TreeNode{root}
for length := len(queue); length > 0; length = len(queue) {
for i := 0; i < length; i++ {
node := queue[i]
if _, ok := counter[node.Val]; ok {
counter[node.Val] += 1
} else {
counter[node.Val] = 1
}
if node.Left != nil {
queue = append(queue, node.Left)
}
if node.Right != nil {
queue = append(queue, node.Right)
}
}
queue = queue[length:]
}
maxCount, answer := 0, []int{}
for key, count := range counter {
if count < maxCount {
continue
}
if count > maxCount {
answer = answer[:0]
maxCount = count
}
answer = append(answer, key)
}
return answer
}
4.7.1339 - 2023-10-31 19:12:05 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
type queueItem struct {
node *TreeNode
max *int
min *int
}
func isValidBST(root *TreeNode) bool {
queue := []queueItem{queueItem{root, nil, nil}}
for length := len(queue); length > 0; length = len(queue) {
for i := 0; i < length; i++ {
item := queue[i]
if item.node == nil {
continue
}
node := item.node
if (item.max != nil && node.Val >= *item.max) || (item.min != nil && node.Val <= *item.min) {
return false
}
queue = append(
queue,
queueItem{node.Left, &node.Val, item.min},
queueItem{node.Right, item.max, &node.Val},
)
}
queue = queue[length:]
}
return true
}
4.7.1340 - 2023-10-31 19:11:41 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
type queueItem struct {
node *TreeNode
max *int
min *int
}
func isValidBST(root *TreeNode) bool {
queue := []queueItem{queueItem{root, nil, nil}}
for length := len(queue); length > 0; length = len(queue) {
for i := 0; i < length; i++ {
item := queue[i]
if item.node == nil {
continue
}
node := item.node
if (item.max != nil && node.Val >= *item.max) || (item.min != nil && node.Val <= *item.min) {
return false
}
queue = append(
queue,
queueItem{node.Left, &node.Val, item.min},
queueItem{node.Right, item.max, &node.Val},
)
}
queue = queue[length:]
}
return true
}
4.7.1341 - 2023-10-31 18:59:17 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func isValidBST(root *TreeNode) bool {
if root == nil {
return false
}
return dfs(root.Left, &root.Val, nil) && dfs(root.Right, nil, &root.Val)
}
func dfs(root *TreeNode, max *int, min *int) bool {
if root == nil {
return true
}
if (max != nil && root.Val >= *max) || (min != nil && root.Val <= *min) {
return false
}
return dfs(root.Left, &root.Val, min) && dfs(root.Right, max, &root.Val)
}
4.7.1342 - 2023-10-31 18:18:34 +0300 MSK
Links
Code
func max(a, b int) int {
if a > b {
return a
}
return b
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
func maxSubarraySumCircular(nums []int) int {
var (
max_sum_ending_here = 0
min_sum_ending_here = 0
max_sum_so_far = math.MinInt
min_sum_so_far = math.MaxInt
total = 0
)
for i := 0; i < len(nums); i++ {
num := nums[i]
total += num
max_sum_ending_here += num
min_sum_ending_here += num
max_sum_so_far = max(max_sum_so_far, max_sum_ending_here)
min_sum_so_far = min(min_sum_so_far, min_sum_ending_here)
max_sum_ending_here = max(max_sum_ending_here, 0)
min_sum_ending_here = min(min_sum_ending_here, 0)
}
if max_sum_so_far < 0 {
return max_sum_so_far
}
return max(max_sum_so_far, total - min_sum_so_far)
}
4.7.1343 - 2023-10-31 18:15:28 +0300 MSK
Links
Code
func max(a, b int) int {
if a > b {
return a
}
return b
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
func maxSubarraySumCircular(nums []int) int {
var (
max_sum_ending_here = 0
min_sum_ending_here = 0
max_sum_so_far = math.MinInt
min_sum_so_far = math.MaxInt
total = 0
)
for i := 0; i < len(nums); i++ {
total += nums[i]
max_sum_ending_here += nums[i]
min_sum_ending_here += nums[i]
max_sum_so_far = max(max_sum_so_far, max_sum_ending_here)
min_sum_so_far = min(min_sum_so_far, min_sum_ending_here)
max_sum_ending_here = max(max_sum_ending_here, 0)
min_sum_ending_here = min(min_sum_ending_here, 0)
}
if max_sum_so_far < 0 {
return max_sum_so_far
}
return max(max_sum_so_far, total - min_sum_so_far)
}
4.7.1344 - 2023-10-31 18:13:57 +0300 MSK
Links
Code
func max(a, b int) int {
if a > b {
return a
}
return b
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
func maxSubarraySumCircular(nums []int) int {
var max_sum_ending_here int = 0
var min_sum_ending_here int = 0
var max_sum_so_far int = math.MinInt
var min_sum_so_far int = math.MaxInt
var total = 0
for i := 0; i < len(nums); i++ {
total += nums[i]
max_sum_ending_here += nums[i]
min_sum_ending_here += nums[i]
max_sum_so_far = max(max_sum_so_far, max_sum_ending_here)
min_sum_so_far = min(min_sum_so_far, min_sum_ending_here)
max_sum_ending_here = max(max_sum_ending_here, 0)
min_sum_ending_here = min(min_sum_ending_here, 0)
}
if max_sum_so_far < 0 {
return max_sum_so_far
}
return max(max_sum_so_far, total - min_sum_so_far)
}
4.7.1345 - 2023-10-31 11:33:38 +0300 MSK
Links
Code
func findArray(pref []int) []int {
prev := pref[0]
for i := 1; i < len(pref); i++ {
cur := pref[i]
prev, pref[i] = cur, prev ^ cur
}
return pref
}
4.7.1346 - 2023-10-31 11:32:41 +0300 MSK
Links
Code
func findArray(pref []int) []int {
prev := pref[0]
for i := 1; i < len(pref); i++ {
prev, pref[i] = pref[i], prev ^ pref[i]
}
return pref
}
4.7.1347 - 2023-10-30 16:28:30 +0300 MSK
Links
Code
func trap(height []int) int {
left, right := 0, len(height) - 1
res := 0
leftMax, rightMax := 0, 0
for left < right {
if height[left] < height[right] {
if height[left] >= leftMax {
leftMax = height[left]
} else {
res += (leftMax-height[left])
}
left++
} else {
if height[right] >= rightMax {
rightMax = height[right]
} else {
res += (rightMax-height[right])
}
right--
}
}
return res
}
4.7.1348 - 2023-10-30 16:16:38 +0300 MSK
Links
Code
class Solution:
def searchRange(self, nums: List[int], target: int) -> List[int]:
def binary_search(nums, target, left):
low, high = 0, len(nums) - 1
index = -1
while low <= high:
mid = (low + high) // 2
if nums[mid] == target:
index = mid
if left:
high = mid - 1
else:
low = mid + 1
elif nums[mid] < target:
low = mid + 1
else:
high = mid - 1
return index
left_index = binary_search(nums, target, left=True)
right_index = binary_search(nums, target, left=False)
return [left_index, right_index]
4.7.1349 - 2023-10-30 16:03:18 +0300 MSK
Links
Code
func minMutation(startGene string, endGene string, bank []string) int {
if startGene == endGene {
return 0
}
bank = append(bank, startGene)
isMut := func (gene1 string, gene2 string) bool {
foundDiff := false
for i := 0; i < len(gene1); i++ {
if gene1[i] == gene2[i] {
continue
}
if foundDiff {
return false
}
foundDiff = true
}
return foundDiff
}
graph := map[string][]string{}
for i, gene1 := range bank {
for _, gene2 := range bank[i+1:] {
if !isMut(gene1, gene2) {
continue
}
if _, ok := graph[gene1]; !ok {
graph[gene1] = []string{}
}
if _, ok := graph[gene2]; !ok {
graph[gene2] = []string{}
}
graph[gene1] = append(graph[gene1], gene2)
graph[gene2] = append(graph[gene2], gene1)
}
}
queue, ok := graph[endGene]
if !ok {
return -1
}
delete(graph, endGene)
num := 1
for length := len(queue); length > 0; length = len(queue) {
for i := 0; i < length; i++ {
gene := queue[i]
muts, ok := graph[gene]
if !ok {
continue
}
if gene == startGene {
return num
}
delete(graph, gene)
queue = append(queue, muts...)
}
num += 1
queue = queue[length:]
}
return -1
}
4.7.1350 - 2023-10-30 15:58:41 +0300 MSK
Links
Code
func minMutation(startGene string, endGene string, bank []string) int {
if startGene == endGene {
return 0
}
bank = append(bank, startGene)
isMut := func (gene1 string, gene2 string) bool {
foundDiff := false
for i := 0; i < len(gene1); i++ {
if gene1[i] == gene2[i] {
continue
}
if foundDiff {
return false
}
foundDiff = true
}
return foundDiff
}
graph := map[string][]string{}
for i, gene1 := range bank {
for _, gene2 := range bank[i+1:] {
if !isMut(gene1, gene2) {
continue
}
if _, ok := graph[gene1]; !ok {
graph[gene1] = []string{}
}
if _, ok := graph[gene2]; !ok {
graph[gene2] = []string{}
}
graph[gene1] = append(graph[gene1], gene2)
graph[gene2] = append(graph[gene2], gene1)
}
}
queue, ok := graph[endGene]
if !ok {
return -1
}
visited := map[string]struct{}{endGene: struct{}{}}
num := 1
for length := len(queue); length > 0; length = len(queue) {
for i := 0; i < length; i++ {
gene := queue[i]
if _, ok := visited[gene]; ok {
continue
}
if gene == startGene {
return num
}
visited[gene] = struct{}{}
queue = append(queue, graph[gene]...)
}
num += 1
queue = queue[length:]
}
return -1
}
4.7.1351 - 2023-10-30 14:32:47 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func zigzagLevelOrder(root *TreeNode) [][]int {
if root == nil {
return [][]int{}
}
queue, answer := []*TreeNode{root}, [][]int{}
ltr := true
for length := len(queue); length != 0; length = len(queue) {
answerRow := []int{}
for i := 0; i < length; i++ {
node := queue[i]
if node.Left != nil {
queue = append(queue, node.Left)
}
if node.Right != nil {
queue = append(queue, node.Right)
}
answerRow = append(answerRow, node.Val)
}
if !ltr {
slices.Reverse(answerRow)
}
queue = queue[length:]
ltr = !ltr
answer = append(answer, answerRow)
}
return answer
}
4.7.1352 - 2023-10-30 14:31:36 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func zigzagLevelOrder(root *TreeNode) [][]int {
if root == nil {
return [][]int{}
}
queue, answer := []*TreeNode{root}, [][]int{}
ltr := true
for length := len(queue); length != 0; length = len(queue) {
answerRow := []int{}
for i := 0; i < length; i++ {
node := queue[i]
if node.Left != nil {
queue = append(queue, node.Left)
}
if node.Right != nil {
queue = append(queue, node.Right)
}
if ltr {
answerRow = append(answerRow, node.Val)
} else {
answerRow = append([]int{node.Val}, answerRow...)
}
}
queue = queue[length:]
ltr = !ltr
answer = append(answer, answerRow)
}
return answer
}
4.7.1353 - 2023-10-30 14:14:48 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func zigzagLevelOrder(root *TreeNode) [][]int {
if root == nil {
return [][]int{}
}
queue, answer := []*TreeNode{root}, [][]int{}
leftToRight := true
for length := len(queue); length != 0; length = len(queue) {
answerRow := []int{}
for i := 0; i < length; i++ {
node := queue[0]
queue = queue[1:]
answerRow = append(answerRow, node.Val)
if left := node.Left; left != nil {
queue = append(queue, left)
}
if right := node.Right; right != nil {
queue = append(queue, right)
}
}
if !leftToRight {
slices.Reverse(answerRow)
}
leftToRight = !leftToRight
answer = append(answer, answerRow)
}
return answer
}
4.7.1354 - 2023-10-30 13:59:23 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func levelOrder(root *TreeNode) [][]int {
queue, answer := []*TreeNode{root}, [][]int{}
for length := len(queue); length != 0; length = len(queue) {
answerRow := []int{}
for i := 0; i < length; i++ {
node := queue[0]
queue = queue[1:]
if node == nil {
continue
}
answerRow = append(answerRow, node.Val)
queue = append(queue, node.Left, node.Right)
}
if len(answerRow) != 0 {
answer = append(answer, answerRow)
}
}
return answer
}
4.7.1355 - 2023-10-30 13:51:15 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func levelOrder(root *TreeNode) [][]int {
if root == nil {
return [][]int{}
}
stack, answer := []*TreeNode{root}, [][]int{}
for length := len(stack); length != 0; length = len(stack) {
answerRow := []int{}
for i := 0; i < length; i++ {
node := stack[0]
answerRow = append(answerRow, node.Val)
stack = stack[1:]
if left := node.Left; left != nil {
stack = append(stack, node.Left)
}
if right := node.Right; right != nil {
stack = append(stack, node.Right)
}
}
answer = append(answer, answerRow)
}
return answer
}
4.7.1356 - 2023-10-30 13:39:35 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func rightSideView(root *TreeNode) []int {
if root == nil {
return []int{}
}
queue, answer := []*TreeNode{root}, []int{}
for length := len(queue); length != 0; length = len(queue) {
for i := 0; i < length; i++ {
node := queue[0]
queue = queue[1:]
if i == length - 1 {
answer = append(answer, node.Val)
}
if left := node.Left; left != nil {
queue = append(queue, left)
}
if right := node.Right; right != nil {
queue = append(queue, right)
}
}
}
return answer
}
4.7.1357 - 2023-10-30 13:33:19 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func averageOfLevels(root *TreeNode) []float64 {
if root == nil {
return []float64{}
}
queue, answer := []*TreeNode{root}, []float64{}
for length := len(queue); length != 0; length = len(queue) {
av := 0
for i := 0; i < length; i++ {
node := queue[0]
queue = queue[1:]
av += node.Val
if left := node.Left; left != nil {
queue = append(queue, left)
}
if right := node.Right; right != nil {
queue = append(queue, right)
}
}
answer = append(answer, float64(av) / float64(length))
}
return answer
}
4.7.1358 - 2023-10-30 13:26:37 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func averageOfLevels(root *TreeNode) []float64 {
if root == nil {
return []float64{}
}
qCur, qNext, answer := []*TreeNode{root}, []*TreeNode{}, []float64{}
for len(qCur) != 0 {
av := 0
for _, node := range qCur {
av += node.Val
if left := node.Left; left != nil {
qNext = append(qNext, left)
}
if right := node.Right; right != nil {
qNext = append(qNext, right)
}
}
answer = append(answer, float64(av) / float64(len(qCur)))
qCur = qCur[:0]
qCur, qNext = qNext, qCur
}
return answer
}
4.7.1359 - 2023-10-30 13:17:08 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func rightSideView(root *TreeNode) []int {
if root == nil {
return []int{}
}
q_cur, q_next, answer := []*TreeNode{root}, []*TreeNode{}, []int{}
for len(q_cur) != 0 {
for _, node := range q_cur {
if left := node.Left; left != nil {
q_next = append(q_next, left)
}
if right := node.Right; right != nil {
q_next = append(q_next, right)
}
}
answer = append(answer, q_cur[len(q_cur) - 1].Val)
q_cur = q_cur[:0]
q_cur, q_next = q_next, q_cur
}
return answer
}
4.7.1360 - 2023-10-30 13:16:47 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func rightSideView(root *TreeNode) []int {
if root == nil {
return []int{}
}
q_cur, q_next, answer := []*TreeNode{root}, []*TreeNode{}, []int{}
for len(q_cur) != 0 {
var last int
for _, node := range q_cur {
if left := node.Left; left != nil {
q_next = append(q_next, left)
}
if right := node.Right; right != nil {
q_next = append(q_next, right)
}
last = node.Val
}
answer = append(answer, last)
q_cur = q_cur[:0]
q_cur, q_next = q_next, q_cur
}
return answer
}
4.7.1361 - 2023-10-30 13:16:38 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func rightSideView(root *TreeNode) []int {
if root == nil {
return []int{}
}
q_cur, q_next, answer := []*TreeNode{root}, []*TreeNode{}, []int{}
for len(q_cur) != 0 {
var last int
for _, node := range q_cur {
if left := node.Left; left != nil {
q_next = append(q_next, left)
}
if right := node.Right; right != nil {
q_next = append(q_next, right)
}
last = node.Val
}
answer = append(answer, last)
q_cur = q_cur[:0]
q_cur, q_next = q_next, q_cur
}
return answer
}
4.7.1362 - 2023-10-30 13:13:00 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func rightSideView(root *TreeNode) []int {
if root == nil {
return []int{}
}
q_cur, q_next, answer := []*TreeNode{root}, []*TreeNode{}, []int{}
for length := len(q_cur); length > 0; length = len(q_cur) {
for _, node := range q_cur {
if left := node.Left; left != nil {
q_next = append(q_next, left)
}
if right := node.Right; right != nil {
q_next = append(q_next, right)
}
}
answer = append(answer, q_cur[length - 1].Val)
q_cur = q_cur[:0]
q_cur, q_next = q_next, q_cur
}
return answer
}
4.7.1363 - 2023-10-30 12:17:05 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def rightSideView(self, root: Optional[TreeNode]) -> List[int]:
if not root:
return []
q_cur, q_next, answer = deque(), deque(), []
q_cur.append(root)
while q_cur:
last_val = None
while q_cur:
node = q_cur.popleft()
last_val = node.val
if node.left:
q_next.append(node.left)
if node.right:
q_next.append(node.right)
q_cur, q_next = q_next, q_cur
answer.append(last_val)
return answer
4.7.1364 - 2023-10-30 12:10:35 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def rightSideView(self, root: Optional[TreeNode]) -> List[int]:
if not root:
return []
cur, nxt = [root], []
answer = []
while cur:
last_node = cur.pop()
if last_node.right:
nxt.append(last_node.right)
if last_node.left:
nxt.append(last_node.left)
answer.append(last_node.val)
while cur:
node = cur.pop()
if node.right:
nxt.append(node.right)
if node.left:
nxt.append(node.left)
cur.clear()
nxt.reverse()
cur, nxt = nxt, cur
return answer
4.7.1365 - 2023-10-30 10:51:12 +0300 MSK
Links
Code
class Solution:
def sortByBits(self, arr: List[int]) -> List[int]:
return tuple(num for num in sorted(arr, key=lambda num: (num.bit_count(), num)))
4.7.1366 - 2023-10-29 19:36:33 +0300 MSK
Links
Code
class Solution:
def poorPigs(self, buckets: int, a: int, b: int) -> int:
pigs = 0
while (b / a + 1) ** pigs < buckets:
pigs += 1
return pigs
4.7.1367 - 2023-10-28 17:51:04 +0300 MSK
Links
Code
class Solution:
def countVowelPermutation(self, n: int) -> int:
MOD = 10**9 + 7
a, e, i, o, u = 1, 1, 1, 1, 1
for _ in range(1, n):
a_next = e
e_next = (a + i) % MOD
i_next = (a + e + o + u) % MOD
o_next = (i + u) % MOD
u_next = a
a, e, i, o, u = a_next, e_next, i_next, o_next, u_next
return (a + e + i + o + u) % MOD
4.7.1368 - 2023-10-27 17:47:50 +0300 MSK
Links
Code
class Solution:
def longestPalindrome(self, s: str) -> str:
n = len(s)
dp = [[False] * n for _ in range(n)]
ans = [0, 0]
for i in range(n):
dp[i][i] = True
for i in range(n - 1):
if s[i] == s[i + 1]:
dp[i][i + 1] = True
ans = [i, i + 1]
for diff in range(2, n):
for i in range(n - diff):
j = i + diff
if s[i] == s[j] and dp[i + 1][j - 1]:
dp[i][j] = True
ans = [i, j]
i, j = ans
return s[i:j + 1]
4.7.1369 - 2023-10-26 23:07:22 +0300 MSK
Links
Code
MOD = 10**9 + 7
class Solution:
def numFactoredBinaryTrees(self, arr: List[int]) -> int:
arr.sort()
s = set(arr)
dp = {x: 1 for x in arr}
for i in arr:
for j in arr:
if j > i**0.5:
break
if i % j == 0 and i // j in s:
if i // j == j:
dp[i] += dp[j] * dp[j]
else:
dp[i] += dp[j] * dp[i // j] * 2
dp[i] %= MOD
return sum(dp.values()) % MOD
4.7.1370 - 2023-10-25 13:37:39 +0300 MSK
Links
Code
class TrieNode:
def __init__(self):
self.children = {}
self.is_word = False
class WordDictionary:
def __init__(self):
self.root = TrieNode()
def addWord(self, word: str) -> None:
cur = self.root
for char in word:
cur = cur.children.setdefault(char, TrieNode())
cur.is_word = True
def search(self, word: str) -> bool:
cur, nxt = [self.root], []
for char in word:
if not cur:
return False
if char == ".":
for node in cur:
nxt.extend(node.children.values())
else:
for node in cur:
if char in node.children:
nxt.append(node.children[char])
cur.clear()
cur, nxt = nxt, cur
return any(node.is_word for node in cur)
# Your WordDictionary object will be instantiated and called as such:
# obj = WordDictionary()
# obj.addWord(word)
# param_2 = obj.search(word)
4.7.1371 - 2023-10-25 11:31:06 +0300 MSK
Links
Code
class Solution:
def kthGrammar(self, n: int, k: int) -> int:
def get(row: int, column: int) -> int:
if column == 0 or column == 1:
return column
prev_row_length = 2 ** (row - 1)
if column >= prev_row_length:
return 1 ^ get(row - 1, column - prev_row_length)
return get(row - 1, column)
return get(n - 1, k - 1)
# 0
# 0 1
# 0 1 1 0
# 0 1 1 0 1 0 0 1
# 0 1 1 0 1 0 0 1
4.7.1372 - 2023-10-24 14:55:16 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def largestValues(self, root: Optional[TreeNode]) -> List[int]:
if not root:
return []
largest = []
cur, nxt = [root], []
cur_val = None
while cur or nxt:
while cur:
node = cur.pop()
if cur_val is None or node.val > cur_val:
cur_val = node.val
if node.left:
nxt.append(node.left)
if node.right:
nxt.append(node.right)
largest.append(cur_val)
cur.clear()
cur_val = None
cur, nxt = nxt, cur
return largest
4.7.1373 - 2023-10-23 12:26:07 +0300 MSK
Links
Code
class Solution:
def isPowerOfFour(self, n: int) -> bool:
# Check if the number is greater than zero and is a power of two
if n > 0 and (n & (n - 1)) == 0:
# Check if the number is of the form 4^x
return n & 0x55555555 == n
else:
return False
4.7.1374 - 2023-10-22 13:57:47 +0300 MSK
Links
Code
class Solution:
def maximumScore(self, nums: List[int], k: int) -> int:
n = len(nums)
left = k
right = k
ans = nums[k]
curr_min = nums[k]
while left > 0 or right < n - 1:
if (nums[left - 1] if left else 0) < (nums[right + 1] if right < n - 1 else 0):
right += 1
curr_min = min(curr_min, nums[right])
else:
left -= 1
curr_min = min(curr_min, nums[left])
ans = max(ans, curr_min * (right - left + 1))
return ans
4.7.1375 - 2023-10-21 14:20:53 +0300 MSK
Links
Code
import heapq
class Solution:
def constrainedSubsetSum(self, nums: List[int], k: int) -> int:
heap = [(-nums[0], 0)]
ans = nums[0]
for i in range(1, len(nums)):
while i - heap[0][1] > k:
heapq.heappop(heap)
curr = max(0, -heap[0][0]) + nums[i]
ans = max(ans, curr)
heapq.heappush(heap, (-curr, i))
return ans
4.7.1376 - 2023-10-20 16:11:39 +0300 MSK
Links
Code
# """
# This is the interface that allows for creating nested lists.
# You should not implement it, or speculate about its implementation
# """
#class NestedInteger:
# def isInteger(self) -> bool:
# """
# @return True if this NestedInteger holds a single integer, rather than a nested list.
# """
#
# def getInteger(self) -> int:
# """
# @return the single integer that this NestedInteger holds, if it holds a single integer
# Return None if this NestedInteger holds a nested list
# """
#
# def getList(self) -> [NestedInteger]:
# """
# @return the nested list that this NestedInteger holds, if it holds a nested list
# Return None if this NestedInteger holds a single integer
# """
class NestedIterator:
def __init__(self, nestedList: [NestedInteger]):
self.get_next = self.get_next_gen(nestedList)
self.next_val = next(self.get_next, None)
def get_next_gen(self, nestedList: List[NestedInteger]) -> Generator[None, None, int]:
for ni in nestedList:
if ni.isInteger():
yield ni.getInteger()
else:
yield from self.get_next_gen(ni.getList())
def next(self) -> int:
answer, self.next_val = self.next_val, next(self.get_next, None)
return answer
def hasNext(self) -> bool:
return self.next_val is not None
# Your NestedIterator object will be instantiated and called as such:
# i, v = NestedIterator(nestedList), []
# while i.hasNext(): v.append(i.next())
4.7.1377 - 2023-10-20 16:06:36 +0300 MSK
Links
Code
# """
# This is the interface that allows for creating nested lists.
# You should not implement it, or speculate about its implementation
# """
#class NestedInteger:
# def isInteger(self) -> bool:
# """
# @return True if this NestedInteger holds a single integer, rather than a nested list.
# """
#
# def getInteger(self) -> int:
# """
# @return the single integer that this NestedInteger holds, if it holds a single integer
# Return None if this NestedInteger holds a nested list
# """
#
# def getList(self) -> [NestedInteger]:
# """
# @return the nested list that this NestedInteger holds, if it holds a nested list
# Return None if this NestedInteger holds a single integer
# """
class NestedIterator:
def __init__(self, nestedList: [NestedInteger]):
self.list = []
self.flatten(self.list, nestedList)
self.cur = 0
self.length = len(self.list)
def flatten(self, flatList: List[int], nestedList: List[NestedInteger]):
for ni in nestedList:
if ni.isInteger():
flatList.append(ni.getInteger())
else:
self.flatten(flatList, ni.getList())
def next(self) -> int:
answer = self.list[self.cur]
self.cur += 1
return answer
def hasNext(self) -> bool:
return self.cur < self.length
# Your NestedIterator object will be instantiated and called as such:
# i, v = NestedIterator(nestedList), []
# while i.hasNext(): v.append(i.next())
4.7.1378 - 2023-10-19 17:09:46 +0300 MSK
Links
Code
class Solution:
def backspaceCompare(self, s: str, t: str) -> bool:
i1, i2 = len(s) - 1, len(t) - 1
skip1, skip2 = 0, 0
while i1 >= 0 or i2 >= 0:
char1, char2 = s[i1] if i1 >= 0 else "", t[i2] if i2 >= 0 else ""
if char1 == "#":
i1 -= 1
skip1 += 1
elif char2 == "#":
i2 -= 1
skip2 += 1
elif skip1 > 0:
i1 -= 1
skip1 -= 1
elif skip2 > 0:
i2 -= 1
skip2 -= 1
elif char1 != char2:
return False
else:
i1 -= 1
i2 -= 1
return True
4.7.1379 - 2023-10-18 19:38:53 +0300 MSK
Links
Code
class Solution:
def minimumTime(self, n: int, relations: List[List[int]], time: List[int]) -> int:
graph = defaultdict(list)
indegree = [0] * n
for (x, y) in relations:
graph[x - 1].append(y - 1)
indegree[y - 1] += 1
queue = deque()
max_time = [0] * n
for node in range(n):
if indegree[node] == 0:
queue.append(node)
max_time[node] = time[node]
while queue:
node = queue.popleft()
for neighbor in graph[node]:
max_time[neighbor] = max(max_time[neighbor], max_time[node] + time[neighbor])
indegree[neighbor] -= 1
if indegree[neighbor] == 0:
queue.append(neighbor)
return max(max_time)
4.7.1380 - 2023-10-17 18:45:21 +0300 MSK
Links
Code
class Solution:
def validateBinaryTreeNodes(self, n: int, leftChild: List[int], rightChild: List[int]) -> bool:
parents = [-1] * n
for i in range(n):
left, right = leftChild[i], rightChild[i]
left_valid, right_valid = left != -1, right != -1
if (left_valid and parents[left] != -1) or (
right_valid and parents[right] != -1
):
return False
if left_valid:
parents[left] = i
if right_valid:
parents[right] = i
parent = parents[i]
if parent != -1 and (parent == left or parent == right):
return False
root = None
for i, node in enumerate(parents):
if node == -1 and root is not None:
return False
if node == -1:
root = i
if root is None:
return False
to_visit = [root]
visited = set()
while to_visit:
node = to_visit.pop()
if node in visited:
return False
visited.add(node)
left, right = leftChild[node], rightChild[node]
if left != -1:
to_visit.append(left)
if right != -1:
to_visit.append(right)
return len(visited) == n
4.7.1381 - 2023-10-16 20:32:07 +0300 MSK
Links
Code
class Solution:
def getRow(self, rowIndex: int) -> List[int]:
cur, prev = [], [1]
row = 0
while row < rowIndex:
cur.append(1)
for i in range(1, len(prev)):
cur.append(prev[i] + prev[i-1])
cur.append(1)
prev.clear()
cur, prev = prev, cur
row += 1
return prev
4.7.1382 - 2023-10-15 13:05:28 +0300 MSK
Links
Code
class Solution:
def numWays(self, steps: int, arrLen: int) -> int:
@cache
def dp(curr, remain):
if remain == 0:
if curr == 0:
return 1
return 0
ans = dp(curr, remain - 1)
if curr > 0:
ans = (ans + dp(curr - 1, remain - 1)) % MOD
if curr < arrLen - 1:
ans = (ans + dp(curr + 1, remain - 1)) % MOD
return ans
MOD = 10 ** 9 + 7
return dp(0, steps)
4.7.1383 - 2023-10-14 19:53:26 +0300 MSK
Links
Code
class Solution:
def paintWalls(self, cost: List[int], time: List[int]) -> int:
@cache
def dp(i, remain):
if remain <= 0:
return 0
if i == n:
return inf
paint = cost[i] + dp(i + 1, remain - 1 - time[i])
dont_paint = dp(i + 1, remain)
return min(paint, dont_paint)
n = len(cost)
return dp(0, n)
4.7.1384 - 2023-10-14 10:14:40 +0300 MSK
Links
Code
class Solution:
def minCostClimbingStairs(self, cost):
n = len(cost)
dp = [0] * n
dp[0] = cost[0]
dp[1] = cost[1]
for i in range(2, n):
dp[i] = cost[i] + min(dp[i-1], dp[i-2])
return min(dp[n-1], dp[n-2])
4.7.1385 - 2023-10-12 12:09:45 +0300 MSK
Links
Code
class Solution:
def findInMountainArray(self, target: int, mountain_arr: 'MountainArray') -> int:
# Save the length of the mountain array
length = mountain_arr.length()
# 1. Find the index of the peak element
low = 1
high = length - 2
while low != high:
test_index = (low + high) // 2
if mountain_arr.get(test_index) < mountain_arr.get(test_index + 1):
low = test_index + 1
else:
high = test_index
peak_index = low
# 2. Search in the strictly increasing part of the array
low = 0
high = peak_index
while low != high:
test_index = (low + high) // 2
if mountain_arr.get(test_index) < target:
low = test_index + 1
else:
high = test_index
# Check if the target is present in the strictly increasing part
if mountain_arr.get(low) == target:
return low
# 3. Otherwise, search in the strictly decreasing part
low = peak_index + 1
high = length - 1
while low != high:
test_index = (low + high) // 2
if mountain_arr.get(test_index) > target:
low = test_index + 1
else:
high = test_index
# Check if the target is present in the strictly decreasing part
if mountain_arr.get(low) == target:
return low
# Target is not present in the mountain array
return -1
4.7.1386 - 2023-10-11 16:06:35 +0300 MSK
Links
Code
class Solution:
def fullBloomFlowers(self, flowers: List[List[int]], people: List[int]) -> List[int]:
flowers.sort()
sorted_people = sorted(people)
dic = {}
heap = []
i = 0
for person in sorted_people:
while i < len(flowers) and flowers[i][0] <= person:
heapq.heappush(heap, flowers[i][1])
i += 1
while heap and heap[0] < person:
heapq.heappop(heap)
dic[person] = len(heap)
return [dic[x] for x in people]
4.7.1387 - 2023-10-10 08:23:28 +0300 MSK
Links
Code
class Solution:
def minOperations(self, nums: List[int]) -> int:
n = len(nums)
ans = n
new_nums = sorted(set(nums))
for i in range(len(new_nums)):
left = new_nums[i]
right = left + n - 1
j = bisect_right(new_nums, right)
count = j - i
ans = min(ans, n - count)
return ans
4.7.1388 - 2023-10-09 14:15:25 +0300 MSK
Links
Code
class Solution:
def searchRange(self, nums: List[int], target: int) -> List[int]:
def binary_search(nums, target, left):
low, high = 0, len(nums) - 1
index = -1
while low <= high:
mid = (low + high) // 2
if nums[mid] == target:
index = mid
if left:
high = mid - 1
else:
low = mid + 1
elif nums[mid] < target:
low = mid + 1
else:
high = mid - 1
return index
left_index = binary_search(nums, target, left=True)
right_index = binary_search(nums, target, left=False)
return [left_index, right_index]
4.7.1389 - 2023-10-08 10:39:44 +0300 MSK
Links
Code
class Solution:
def maxDotProduct(self, nums1: List[int], nums2: List[int]) -> int:
@cache
def dp(i, j):
if i == len(nums1) or j == len(nums2):
return 0
use = nums1[i] * nums2[j] + dp(i + 1, j + 1)
return max(use, dp(i + 1, j), dp(i, j + 1))
if max(nums1) < 0 and min(nums2) > 0:
return max(nums1) * min(nums2)
if min(nums1) > 0 and max(nums2) < 0:
return min(nums1) * max(nums2)
return dp(0, 0)
4.7.1390 - 2023-10-07 19:48:10 +0300 MSK
Links
Code
class Solution:
def numOfArrays(self, n: int, m: int, k: int) -> int:
@cache
def dp(i, max_so_far, remain):
if i == n:
if remain == 0:
return 1
return 0
ans = (max_so_far * dp(i + 1, max_so_far, remain)) % MOD
for num in range(max_so_far + 1, m + 1):
ans = (ans + dp(i + 1, num, remain - 1)) % MOD
return ans
MOD = 10 ** 9 + 7
return dp(0, 0, k)
4.7.1391 - 2023-10-06 12:24:39 +0300 MSK
Links
Code
class Solution:
def integerBreak(self, n: int) -> int:
if n < 4:
return n - 1
@cache
def dp(num: int) -> int:
if num <= 3:
return num
ans = num
for i in range(2, num):
ans = max(ans, i * dp(num - i))
return ans
return dp(n)
4.7.1392 - 2023-10-06 12:24:09 +0300 MSK
Links
Code
class Solution:
def integerBreak(self, n: int) -> int:
@cache
def dp(num: int) -> int:
if num <= 3:
return num
ans = num
for i in range(2, num):
ans = max(ans, i * dp(num - i))
return ans
return dp(n) if n > 3 else n - 1
4.7.1393 - 2023-10-05 09:46:37 +0300 MSK
Links
Code
class Solution:
def majorityElement(self, nums: List[int]) -> List[int]:
nums.sort()
threshold = len(nums) // 3
cur_num, cur_count = nums[0], 1
answer = []
for num in nums[1:]:
if num == cur_num:
cur_count += 1
continue
if cur_count > threshold:
answer.append(cur_num)
cur_num, cur_count = num, 1
if cur_count > threshold:
answer.append(cur_num)
return answer
4.7.1394 - 2023-10-04 09:00:01 +0300 MSK
Links
Code
class ListNode:
def __init__(self, key, value):
self.key = key
self.value = value
self.next = None
class MyHashMap:
def __init__(self):
self.size = 1000
self.table = [None] * self.size
def _index(self, key: int) -> int:
return key % self.size
def put(self, key: int, value: int) -> None:
idx = self._index(key)
if not self.table[idx]:
self.table[idx] = ListNode(key, value)
return
current = self.table[idx]
while current:
if current.key == key:
current.value = value
return
if not current.next:
current.next = ListNode(key, value)
return
current = current.next
def get(self, key: int) -> int:
idx = self._index(key)
current = self.table[idx]
while current:
if current.key == key:
return current.value
current = current.next
return -1
def remove(self, key: int) -> None:
idx = self._index(key)
current = self.table[idx]
if not current:
return
if current.key == key:
self.table[idx] = current.next
return
while current.next:
if current.next.key == key:
current.next = current.next.next
return
current = current.next
# Your MyHashMap object will be instantiated and called as such:
# obj = MyHashMap()
# obj.put(key,value)
# param_2 = obj.get(key)
# obj.remove(key)
4.7.1395 - 2023-10-04 08:57:26 +0300 MSK
Links
Code
class MyHashMap:
def __init__(self):
self.data = [None] * 1000001
def put(self, key: int, val: int) -> None:
self.data[key] = val
def get(self, key: int) -> int:
val = self.data[key]
return -1 if val is None else val
def remove(self, key: int) -> None:
self.data[key] = None
# Your MyHashMap object will be instantiated and called as such:
# obj = MyHashMap()
# obj.put(key,value)
# param_2 = obj.get(key)
# obj.remove(key)
4.7.1396 - 2023-10-03 09:14:03 +0300 MSK
Links
Code
class Solution:
def numIdenticalPairs(self, nums: List[int]) -> int:
counter = Counter(nums)
return sum((count ** 2 - count) // 2 for count in counter.values() if count > 1)
4.7.1397 - 2023-10-03 09:13:40 +0300 MSK
Links
Code
class Solution:
def numIdenticalPairs(self, nums: List[int]) -> int:
return sum((count ** 2 - count) // 2 for count in Counter(nums).values() if count > 1)
4.7.1398 - 2023-10-03 09:13:11 +0300 MSK
Links
Code
class Solution:
def numIdenticalPairs(self, nums: List[int]) -> int:
counter = Counter(nums)
return sum((count ** 2 - count) // 2 for count in counter.values() if count > 1)
4.7.1399 - 2023-10-02 15:20:53 +0300 MSK
Links
Code
class Solution:
def winnerOfGame(self, colors: str) -> bool:
cur_char, cur_conseq = colors[0], 1
moves = {"A": 0, "B": 0}
for char in colors[1:]:
if char == cur_char:
cur_conseq += 1
else:
moves[cur_char] += max(0, cur_conseq - 2)
cur_char, cur_conseq = char, 1
if cur_conseq > 2:
moves[cur_char] += cur_conseq - 2
return moves["A"] > moves["B"]
4.7.1400 - 2023-10-01 16:29:08 +0300 MSK
Links
Code
class Solution:
def reverseWords(self, s: str) -> str:
return ' '.join(map(lambda word: word[::-1], s.split()))
4.7.1401 - 2023-09-30 10:17:26 +0300 MSK
Links
Code
class Solution:
def merge(self, intervals: List[List[int]]) -> List[List[int]]:
intervals.sort(key=lambda item: item[0])
merged = []
for start, end in intervals:
# if the list of merged intervals is empty or if the current
# interval does not overlap with the previous, simply append it.
if not merged or merged[-1][1] < start:
merged.append([start, end])
else:
# otherwise, there is overlap, so we merge the current and previous
# intervals.
merged[-1][1] = max(merged[-1][1], end)
return merged
4.7.1402 - 2023-09-30 10:09:04 +0300 MSK
Links
Code
class Solution:
def find132pattern(self, nums: List[int]) -> bool:
if len(nums) < 3:
return False
min_array = [-1] * len(nums)
min_array[0] = nums[0]
for i in range(1, len(nums)):
min_array[i] = min(min_array[i - 1], nums[i])
k = len(nums)
for j in range(len(nums) - 1, -1, -1):
if nums[j] <= min_array[j]:
continue
while k < len(nums) and nums[k] <= min_array[j]:
k += 1
if k < len(nums) and nums[k] < nums[j]:
return True
k -= 1
nums[k] = nums[j]
return False
4.7.1403 - 2023-09-30 10:05:56 +0300 MSK
Links
Code
class Solution:
def find132pattern(self, nums: List[int]) -> bool:
if len(nums) < 3:
return False
stack = []
min_array = [-1] * len(nums)
min_array[0] = nums[0]
for i in range(1, len(nums)):
min_array[i] = min(min_array[i - 1], nums[i])
for j in reversed(range(len(nums))):
if nums[j] <= min_array[j]:
continue
while stack and stack[-1] <= min_array[j]:
stack.pop()
if stack and stack[-1] < nums[j]:
return True
stack.append(nums[j])
return False
4.7.1404 - 2023-09-29 08:36:09 +0300 MSK
Links
Code
class Solution:
def isMonotonic(self, nums: List[int]) -> bool:
length = len(nums)
if length < 3:
return True
is_increasing = None
for i in range(1, length):
cur, prev = nums[i], nums[i-1]
if cur == prev:
continue
is_increasing_cur = cur > prev
if is_increasing is None:
is_increasing = is_increasing_cur
continue
if is_increasing and not is_increasing_cur or (
not is_increasing and is_increasing_cur
):
return False
return True
4.7.1405 - 2023-09-28 10:17:33 +0300 MSK
Links
Code
class Solution:
def sortArrayByParity(self, nums: List[int]) -> List[int]:
left, right = 0, len(nums) - 1
while left < right:
while left < right and nums[left] % 2 == 0:
left += 1
while left < right and nums[right] % 2 == 1:
right -= 1
nums[left], nums[right] = nums[right], nums[left]
return nums
4.7.1406 - 2023-09-28 10:13:16 +0300 MSK
Links
Code
class Solution:
def sortArrayByParity(self, nums: List[int]) -> List[int]:
length = len(nums)
left, right = 0, length - 1
answer = [None] * length
for num in nums:
if num % 2 == 0:
answer[left] = num
left += 1
else:
answer[right] = num
right -= 1
return answer
4.7.1407 - 2023-09-27 18:11:20 +0300 MSK
Links
Code
class Solution:
def decodeAtIndex(self, s: str, k: int) -> str:
length = 0
i = 0
while length < k:
if s[i].isdigit():
length *= int(s[i])
else:
length += 1
i += 1
for j in range(i-1, -1, -1):
char = s[j]
if char.isdigit():
length //= int(char)
k %= length
else:
if k == 0 or k == length:
return char
length -= 1
4.7.1408 - 2023-09-26 13:43:09 +0300 MSK
Links
Code
class Solution:
def removeDuplicateLetters(self, s: str) -> str:
stack = []
seen = set()
last_occ = {char: i for i, char in enumerate(s)}
for i, char in enumerate(s):
if char in seen:
continue
while stack and char < stack[-1] and i < last_occ[stack[-1]]:
seen.discard(stack.pop())
seen.add(char)
stack.append(char)
return ''.join(stack)
4.7.1409 - 2023-09-25 09:17:00 +0300 MSK
Links
Code
class Solution:
def findMin(self, nums: List[int]) -> int:
length = len(nums)
if length == 1:
return nums[0]
first, last = nums[0], nums[-1]
if first < last:
return first
left, right = 0, length - 1
while left <= right:
mid = left + (right - left) // 2
left_num = nums[mid - 1] if mid > 0 else first
mid_num = nums[mid]
right_num = nums[mid + 1] if mid + 1 < length else last
if left_num > mid_num <= right_num:
return mid_num
if left_num > mid_num or (left_num <= mid_num and mid_num >= first):
left = mid + 1
else:
right = mid
return nums[left]
4.7.1410 - 2023-09-25 08:28:38 +0300 MSK
Links
Code
class Solution:
def findTheDifference(self, s: str, t: str) -> str:
return chr(reduce(operator.xor, (ord(char) for char in chain(s, t))))
4.7.1411 - 2023-09-25 08:26:39 +0300 MSK
Links
Code
class Solution:
def findTheDifference(self, s: str, t: str) -> str:
count = Counter(s)
for char in t:
count[char] -= 1
if count[char] == -1:
return char
4.7.1412 - 2023-09-24 14:37:54 +0300 MSK
Links
Code
class Solution:
def rangeBitwiseAnd(self, left: int, right: int) -> int:
shift = 0
while left < right:
left >>= 1
right >>= 1
shift += 1
return left << shift
4.7.1413 - 2023-09-24 13:28:55 +0300 MSK
Links
Code
class Solution:
def maxArea(self, height: List[int]) -> int:
left = 0
right = len(height) - 1
maxArea = 0
while left < right:
currentArea = min(height[left], height[right]) * (right - left)
if currentArea > maxArea:
maxArea = currentArea
if height[left] < height[right]:
left += 1
else:
right -= 1
return maxArea
4.7.1414 - 2023-09-24 13:26:28 +0300 MSK
Links
Code
class Solution:
def maxPoints(self, points: List[List[int]]) -> int:
lines = defaultdict(set)
length = len(points)
if length < 3:
return length
for i in range(length):
x1, y1 = points[i]
for j in range(i + 1, length):
x2, y2 = points[j]
k1, k2 = None, None
if y1 == y2:
k2 = y1
elif x1 == x2:
k1 = x1
else:
k1 = (y2 - y1) / (x2 - x1)
k2 = y1 - k1 * x1
lines[(k1, k2)].update(((x1, y1), (x2, y2)))
return max((len(points) for points in lines.values()), default=0)
4.7.1415 - 2023-09-24 13:00:11 +0300 MSK
Links
Code
class Solution:
def candy(self, ratings: List[int]) -> int:
child_count = len(ratings)
candies = [1] * child_count
for i in range(1, child_count):
if ratings[i] > ratings[i-1]:
candies[i] = candies[i-1] + 1
for i in reversed(range(child_count - 1)):
if ratings[i] > ratings[i+1]:
candies[i] = max(candies[i], candies[i+1] + 1)
return sum(candies)
4.7.1416 - 2023-09-24 12:59:51 +0300 MSK
Links
Code
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
length = len(s)
if length < 2:
return length
max_length, left, charset = 1, 0, set([s[0]])
for right in range(1, length):
letter = s[right]
if letter not in charset:
charset.add(letter)
continue
this_length = right - left
if this_length > max_length:
max_length = this_length
while letter in charset:
charset.remove(s[left])
left += 1
charset.add(letter)
return max(max_length, length - left)
4.7.1417 - 2023-09-24 12:59:24 +0300 MSK
Links
Code
from collections import deque
class Solution:
def connect(self, root: 'Node') -> 'Node':
# Edge case - If the root is None, then return None
if root is None:
return None
# Create a queue and enqueue the root node
q = deque([root])
# Traverse the tree level by level
while q:
# Get the number of nodes of the current level
level_size = len(q)
# Process the nodes of the current level
for i in range(level_size):
# Dequeue a node from the front of the queue
node = q.popleft()
# Assign the next pointer of the node
if i < level_size - 1:
node.next = q[0]
# Enqueue the children of the node (if any)
if node.left is not None:
q.append(node.left)
if node.right is not None:
q.append(node.right)
# Return the root node
return root
4.7.1418 - 2023-09-24 12:56:43 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class BSTIterator:
def __init__(self, root: Optional[TreeNode]):
def generate(node: TreeNode) -> int:
if not node:
return
yield from generate(node.left)
yield node
yield from generate(node.right)
self._generate = generate(root)
self._next = next(self._generate)
def next(self) -> int:
next_val = self._next.val
self._next = next(self._generate, None)
return next_val
def hasNext(self) -> bool:
return self._next is not None
# Your BSTIterator object will be instantiated and called as such:
# obj = BSTIterator(root)
# param_1 = obj.next()
# param_2 = obj.hasNext()
4.7.1419 - 2023-09-24 12:56:22 +0300 MSK
Links
Code
class Trie:
def __init__(self):
self.root = {}
def insert(self, word: str) -> None:
cur = self.root
for char in word:
if char not in cur:
cur[char] = {}
cur = cur[char]
cur["_is_word"] = None
def search(self, word: str) -> bool:
cur = self.root
for char in word:
if char not in cur:
return False
cur = cur[char]
return "_is_word" in cur
def startsWith(self, prefix: str) -> bool:
cur = self.root
for char in prefix:
if char not in cur:
return False
cur = cur[char]
return True
# Your Trie object will be instantiated and called as such:
# obj = Trie()
# obj.insert(word)
# param_2 = obj.search(word)
# param_3 = obj.startsWith(prefix)
4.7.1420 - 2023-09-24 12:55:57 +0300 MSK
Links
Code
class Solution:
def combine(self, n: int, k: int) -> List[List[int]]:
current = []
def backtrack(first: int) -> Generator[None, None, List[int]]:
if len(current) == k:
yield tuple(current[:])
return
for i in range(first, n + 1):
current.append(i)
yield from backtrack(i + 1)
current.pop()
return
return tuple(combination for combination in backtrack(1))
4.7.1421 - 2023-09-24 12:55:41 +0300 MSK
Links
Code
class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
length = len(nums)
current = []
current_contains = [False] * length
def backtrack() -> Generator[None, None, List[int]]:
if len(current) == length:
yield tuple(current[:])
return
for i in range(length):
if current_contains[i]:
continue
current_contains[i] = True
current.append(nums[i])
yield from backtrack()
current_contains[i] = False
current.pop()
return
return tuple(combination for combination in backtrack())
4.7.1422 - 2023-09-24 12:55:19 +0300 MSK
Links
Code
class Solution:
def generateParenthesis(self, n: int) -> List[str]:
current = []
current_max = n * 2
chars = "()"
def backtrack(open: int, closed: int) -> Generator[None, None, List[str]]:
if len(current) == current_max:
yield "".join(current)
if open:
current.append(chars[0])
yield from backtrack(open - 1, closed)
current.pop()
if closed and closed > open:
current.append(chars[1])
yield from backtrack(open, closed - 1)
current.pop()
return tuple(combination for combination in backtrack(n, n))
4.7.1423 - 2023-09-24 12:54:51 +0300 MSK
Links
Code
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
length = len(nums)
if length == 0:
return 0
if length == 1:
return nums[0]
max_cur, max_overall = 0, float("-inf")
for num in nums:
max_cur += num
if max_cur > max_overall:
max_overall = max_cur
if max_cur < 0:
max_cur = 0
return max_overall
4.7.1424 - 2023-09-24 12:53:12 +0300 MSK
Links
Code
class Solution:
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
m, n = len(nums1), len(nums2)
p1, p2 = 0, 0
# Get the smaller value between nums1[p1] and nums2[p2].
def get_min():
nonlocal p1, p2
if p1 < m and p2 < n:
if nums1[p1] < nums2[p2]:
ans = nums1[p1]
p1 += 1
else:
ans = nums2[p2]
p2 += 1
elif p2 == n:
ans = nums1[p1]
p1 += 1
else:
ans = nums2[p2]
p2 += 1
return ans
if (m + n) % 2 == 0:
for _ in range((m + n) // 2 - 1):
_ = get_min()
return (get_min() + get_min()) / 2
else:
for _ in range((m + n) // 2):
_ = get_min()
return get_min()
4.7.1425 - 2023-09-24 12:52:56 +0300 MSK
Links
Code
class Solution:
def search(self, nums: List[int], target: int) -> int:
nums_count = len(nums)
left, right = 0, len(nums) - 1
first_num, last_num = nums[0], nums[-1]
if first_num == target:
return 0
if last_num == target:
return nums_count - 1
# Find the index of the pivot element (the smallest element)
while left <= right:
mid = left + (right - left) // 2
if nums[mid] > last_num:
left = mid + 1
else:
right = mid - 1
pivot_num = nums[left]
if pivot_num == target:
return left
if pivot_num < target < last_num:
right = nums_count - 1
else:
left = 0
while left <= right:
mid = left + (right - left) // 2
mid_num = nums[mid]
if mid_num == target:
return mid
elif mid_num > target:
right = mid - 1
else:
left = mid + 1
return -1
4.7.1426 - 2023-09-24 12:52:34 +0300 MSK
Links
Code
class Solution:
def singleNumber(self, nums: List[int]) -> int:
nums.sort()
length = len(nums)
for i in range(0, length, 3):
if i == length - 1:
return nums[i]
num_1, num_2, num_3 = nums[i], nums[i+1], nums[i+2]
if num_1 == num_2 == num_3:
continue
if num_2 == num_3:
return num_1
if num_1 == num_3:
return num_2
return num_3
4.7.1427 - 2023-09-24 12:52:13 +0300 MSK
Links
Code
class Solution:
def singleNumber(self, nums: List[int]) -> int:
return reduce(xor, nums)
4.7.1428 - 2023-09-24 12:51:48 +0300 MSK
Links
Code
class Solution:
def hammingWeight(self, n: int) -> int:
count = 0
while n > 0:
if n & 1 != 0:
count += 1
n >>= 1
return count
4.7.1429 - 2023-09-24 12:50:52 +0300 MSK
Links
Code
class Solution:
def reverseBits(self, n: int) -> int:
# Initialize the reversed number to 0
reversed_num = 0
# Iterate over all 32 bits of the given number
for i in range(32):
# Left shift the reversed number by 1 and add the last bit of the given number to it
reversed_num = (reversed_num << 1) | (n & 1)
# remove the last bit from the original number
n >>= 1
# Return the reversed number
return reversed_num
4.7.1430 - 2023-09-24 12:50:33 +0300 MSK
Links
Code
class Solution:
def addBinary(self, a: str, b: str) -> str:
answer = []
carry = 0
for char1, char2 in zip_longest(reversed(a), reversed(b)):
num1, num2 = int(char1) if char1 else 0, int(char2) if char2 else 0
cur_sum = num1 + num2 + carry
carry = 0
if cur_sum > 1:
cur_sum -= 2
carry = 1
answer.append(str(cur_sum))
if carry:
answer.append("1")
return "".join(reversed(answer))
4.7.1431 - 2023-09-24 12:47:07 +0300 MSK
Links
Code
class Solution:
def trailingZeroes(self, n: int) -> int:
zeros = 0
while n != 0:
new_n = n // 5
zeros += new_n
n = new_n
return zeros
4.7.1432 - 2023-09-24 12:44:33 +0300 MSK
Links
Code
class Solution:
def trailingZeroes(self, n: int) -> int:
a, b, zeros = 1, 5, 0
while (5**a) <= n:
zeros += n // b
a += 1
b *= 5
return zeros
4.7.1433 - 2023-09-24 12:41:55 +0300 MSK
Links
Code
class Solution:
def myPow(self, x: float, n: int) -> float:
if n == 0:
return 1
if n < 0:
n *= -1
x = 1 / x
result = 1
while n:
if n % 2:
result *= x
n -= 1
x *= x
n //= 2
return result
4.7.1434 - 2023-09-24 12:41:37 +0300 MSK
Links
Code
class Solution:
def plusOne(self, digits: List[int]) -> List[int]:
carry = 1
for i in reversed(range(len(digits))):
new_digit = digits[i] + carry
if new_digit > 9:
carry = 1
new_digit %= 10
else:
carry = 0
digits[i] = new_digit
if carry:
digits.insert(0, carry)
return digits
4.7.1435 - 2023-09-24 12:40:45 +0300 MSK
Links
Code
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def partition(self, head: Optional[ListNode], x: int) -> Optional[ListNode]:
before_head, after_head = ListNode(0), ListNode(0)
before_tail, after_tail = before_head, after_head
while head:
if head.val < x:
before_tail.next, before_tail = head, head
else:
after_tail.next, after_tail = head, head
head = head.next
after_tail.next, before_tail.next = None, after_head.next
return before_head.next
4.7.1436 - 2023-09-24 12:40:14 +0300 MSK
Links
Code
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reverseBetween(self, head: Optional[ListNode], left: int, right: int) -> Optional[ListNode]:
cur_node = 1
left_head, left_tail = head if left > 1 else None, None
while cur_node < left:
cur_node += 1
head, left_tail = head.next, head
cur_node += 1
mid_head, mid_tail, head = head, head, head.next
mid_head.next = None
while cur_node <= right:
cur_node += 1
mid_head, head.next, head = head, mid_head, head.next
mid_tail.next = head
if left_head:
left_tail.next = mid_head
else:
left_head = mid_head
return left_head
4.7.1437 - 2023-09-24 12:39:52 +0300 MSK
Links
Code
"""
# Definition for a Node.
class Node:
def __init__(self, x: int, next: 'Node' = None, random: 'Node' = None):
self.val = int(x)
self.next = next
self.random = random
"""
class Solution:
def copyRandomList(self, head: 'Optional[Node]') -> 'Optional[Node]':
copied = {None: None}
def copy_node(node: Node) -> Node:
if node in copied:
return copied[node]
new_node = Node(node.val)
copied[node] = new_node
new_node.next = copy_node(node.next)
new_node.random = copy_node(node.random)
return new_node
return copy_node(head)
4.7.1438 - 2023-09-24 12:38:31 +0300 MSK
Links
Code
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]:
tail, before_tail = head, None
remove_tail = False
while tail:
if tail.next and tail.val == tail.next.val:
tail.next = tail.next.next
remove_tail = True
continue
if not remove_tail:
before_tail, tail = tail, tail.next
continue
remove_tail = False
if before_tail is None:
tail = head.next
head.next, head = None, head.next
else:
before_tail.next = tail.next
tail = tail.next
return head
4.7.1439 - 2023-09-24 12:09:18 +0300 MSK
Links
Code
class Solution:
def champagneTower(self, poured: int, query_row: int, query_glass: int) -> float:
if query_row == 0:
return min(1, poured)
if query_glass in (0, query_row):
while query_row and poured:
poured = (poured - 1) / 2 if poured > 1 else 0
query_row -= 1
return min(1, poured)
cur_row, next_row = [0] * (query_row + 2), [0] * (query_row + 2)
cur_row[0] = poured
for row in range(query_row + 1):
next_row[0] = 0
for col in range(row + 1):
overflow = (cur_row[col] - 1) / 2
if overflow > 0:
next_row[col] += overflow
next_row[col + 1] = overflow
else:
next_row[col + 1] = 0
cur_row, next_row = next_row, cur_row
return min(1, next_row[query_glass])
4.7.1440 - 2023-09-23 21:54:59 +0300 MSK
Links
Code
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
cur_length, target_length, before_removed = 0, n + 1, head
tail = head
while tail and cur_length != target_length:
tail = tail.next
cur_length += 1
if not tail and cur_length != target_length:
return head.next
while tail:
before_removed = before_removed.next
tail = tail.next
before_removed.next = before_removed.next.next
return head
4.7.1441 - 2023-09-23 18:06:03 +0300 MSK
Links
Code
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def rotateRight(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
if k == 0 or not head:
return head
temp_head, tail, length = head, head, 0
while temp_head:
length += 1
tail, temp_head = temp_head, temp_head.next
rotation = k % length
if rotation == 0:
return head
new_head_idx = length - rotation
new_tail_idx = new_head_idx - 1
i, new_head, new_tail = 0, None, None
temp_head = head
while temp_head:
if i == new_head_idx:
new_head = temp_head
break
if i == new_tail_idx:
new_tail = temp_head
i += 1
temp_head = temp_head.next
tail.next = head
new_tail.next = None
return new_head
4.7.1442 - 2023-09-23 13:19:00 +0300 MSK
Links
Code
class Solution:
def longestStrChain(self, words: List[str]) -> int:
words.sort(key=len)
dp = {}
max_chain = 0
for word in words:
dp[word] = 1
for i in range(len(word)):
prev_word = word[:i] + word[i+1:]
if prev_word in dp:
dp[word] = max(dp[word], dp[prev_word] + 1)
max_chain = max(max_chain, dp[word])
return max_chain
4.7.1443 - 2023-09-22 18:29:58 +0300 MSK
Links
Code
class Solution:
def minBitFlips(self, start: int, goal: int) -> int:
flips_count = 0
while start or goal:
start_is_one, goal_is_one = start & 1, goal & 1
if start_is_one and not goal_is_one or (not start_is_one and goal_is_one):
flips_count += 1
start >>= 1
goal >>= 1
return flips_count
4.7.1444 - 2023-09-22 13:51:50 +0300 MSK
Links
Code
class Solution:
def subsetXORSum(self, nums: List[int]) -> int:
return reduce(operator.or_, nums) * 1 << (len(nums) - 1)
4.7.1445 - 2023-09-22 13:49:11 +0300 MSK
Links
Code
class Solution:
def subsetXORSum(self, nums: List[int]) -> int:
subsets_count = 2**(len(nums) - 1)
return reduce(operator.or_, nums) * subsets_count
4.7.1446 - 2023-09-22 12:14:22 +0300 MSK
Links
Code
class Solution:
def longestNiceSubstring(self, s: str) -> str:
sSet = set(s)
for i in range(len(s)):
if s[i].lower() not in sSet or s[i].upper() not in sSet:
lns1 = self.longestNiceSubstring(s[:i])
lns2 = self.longestNiceSubstring(s[i+1:])
return max(lns1, lns2, key=len)
return s
4.7.1447 - 2023-09-22 11:34:42 +0300 MSK
Links
Code
class Solution:
def countConsistentStrings(self, allowed: str, words: List[str]) -> int:
allowed = set(allowed)
count = 0
for word in words:
if all(char in allowed for char in word):
count += 1
return count
4.7.1448 - 2023-09-22 11:27:41 +0300 MSK
Links
Code
class Solution:
def countConsistentStrings(self, allowed: str, words: List[str]) -> int:
allowed = set(allowed)
count = 0
for word in words:
if not set(word) - allowed:
count += 1
return count
4.7.1449 - 2023-09-22 11:23:55 +0300 MSK
Links
Code
class Solution:
def xorOperation(self, n: int, start: int) -> int:
return reduce(lambda total, i: total ^ (start + 2 * i), chain((0, ), range(n)))
4.7.1450 - 2023-09-22 10:24:39 +0300 MSK
Links
Code
class Solution:
def binaryGap(self, n: int) -> int:
i, first_bit = 0, None
max_distance = 0
while n:
is_one = n & 1 == 1
if is_one and first_bit is None:
first_bit = i
elif is_one:
max_distance, first_bit = max(max_distance, i - first_bit), i
n >>= 1
i += 1
return max_distance
4.7.1451 - 2023-09-22 08:57:07 +0300 MSK
Links
Code
class Solution:
def isSubsequence(self, s: str, t: str) -> bool:
i = 0
length = len(s)
for char in t:
if i == length:
break
if s[i] == char:
i += 1
return i == length
4.7.1452 - 2023-09-22 08:51:25 +0300 MSK
Links
Code
class Solution:
def countPrimeSetBits(self, left: int, right: int) -> int:
prime_bits = (2, 3, 5, 7, 11, 13, 17, 19)
answer = 0
for num in range(left, right + 1):
bit_count = num.bit_count()
if bit_count in prime_bits:
answer += 1
return answer
4.7.1453 - 2023-09-21 19:36:09 +0300 MSK
Links
Code
class Solution:
def findErrorNums(self, nums: List[int]) -> List[int]:
length = len(nums)
# dupl_xor_miss = duplicate ^ missing
dupl_xor_miss = reduce(lambda total, i: total ^ i ^ nums[i - 1], range(length + 1))
rightmost_set_bit = dupl_xor_miss & -dupl_xor_miss
xor_group1 = xor_group2 = 0
for i in range(1, length + 1):
if i & rightmost_set_bit:
xor_group1 ^= i
else:
xor_group2 ^= i
if nums[i - 1] & rightmost_set_bit:
xor_group1 ^= nums[i - 1]
else:
xor_group2 ^= nums[i - 1]
for num in nums:
if num == xor_group1:
return num, xor_group2
if num == xor_group2:
return num, xor_group1
raise Exception()
4.7.1454 - 2023-09-21 19:11:34 +0300 MSK
Links
Code
class Solution:
def findErrorNums(self, nums: List[int]) -> List[int]:
n = len(nums)
dupl_xor_miss = 0
for i in range(1, n+1):
dupl_xor_miss ^= i ^ nums[i-1]
# example for get rightmost set bit
# x: 01110000
# ~x: 10001111
# -x or ~x + 1: 10010000
# x & -x: 00010000
# example for unset rightmost set bit
# x: 01110000
# x-1: 01101111
# x & (x-1): 01100000
rightmost_set_bit = dupl_xor_miss & -dupl_xor_miss
xor_group1 = xor_group2 = 0
for i in range(1, n + 1):
if i & rightmost_set_bit:
xor_group1 ^= i
else:
xor_group2 ^= i
if nums[i-1] & rightmost_set_bit:
xor_group1 ^= nums[i-1]
else:
xor_group2 ^= nums[i-1]
for num in nums:
if num == xor_group1:
return [num, xor_group2]
if num == xor_group2:
return [num, xor_group1]
return []
4.7.1455 - 2023-09-21 18:33:03 +0300 MSK
Links
Code
class Solution:
def findComplement(self, num: int) -> int:
return ~num + (1 << num.bit_length())
4.7.1456 - 2023-09-21 09:51:52 +0300 MSK
Links
Code
class Solution:
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
m, n = len(nums1), len(nums2)
p1, p2 = 0, 0
# Get the smaller value between nums1[p1] and nums2[p2].
def get_min():
nonlocal p1, p2
if p1 < m and p2 < n:
if nums1[p1] < nums2[p2]:
ans = nums1[p1]
p1 += 1
else:
ans = nums2[p2]
p2 += 1
elif p2 == n:
ans = nums1[p1]
p1 += 1
else:
ans = nums2[p2]
p2 += 1
return ans
if (m + n) % 2 == 0:
for _ in range((m + n) // 2 - 1):
_ = get_min()
return (get_min() + get_min()) / 2
else:
for _ in range((m + n) // 2):
_ = get_min()
return get_min()
4.7.1457 - 2023-09-20 22:32:26 +0300 MSK
Links
Code
class Solution:
def sumIndicesWithKSetBits(self, nums: List[int], k: int) -> int:
return sum(num for i, num in enumerate(nums) if i.bit_count() == k)
4.7.1458 - 2023-09-20 22:28:16 +0300 MSK
Links
Code
class Solution:
def sortByBits(self, arr: List[int]) -> List[int]:
return tuple(num for num in sorted(arr, key=lambda num: (num.bit_count(), num)))
4.7.1459 - 2023-09-20 22:22:48 +0300 MSK
Links
Code
class Solution:
def evenOddBit(self, n: int) -> List[int]:
return (n & 0x55555555).bit_count(), (n & 0xaaaaaaaa).bit_count()
4.7.1460 - 2023-09-20 22:20:17 +0300 MSK
Links
Code
class Solution:
def evenOddBit(self, n: int) -> List[int]:
even, odd = n & 0x55555555, n & 0xaaaaaaaa
even_count, odd_count = 0, 0
while even:
if even & 1 == 1:
even_count += 1
even >>= 1
while odd:
if odd & 1 == 1:
odd_count += 1
odd >>= 1
return even_count, odd_count
4.7.1461 - 2023-09-20 19:50:56 +0300 MSK
Links
Code
class Solution:
def hasAlternatingBits(self, n: int) -> bool:
return n & (n >> 1) == 0 and n & (n >> 2) == n >> 2
4.7.1462 - 2023-09-20 19:35:10 +0300 MSK
Links
Code
class Solution:
def isPowerOfThree(self, n: int) -> bool:
# 3 ** 20
return n > 0 and 3486784401 % n == 0
4.7.1463 - 2023-09-20 19:07:10 +0300 MSK
Links
Code
class Solution:
def isPowerOfTwo(self, n: int) -> bool:
return n > 0 and n & (n - 1) == 0
4.7.1464 - 2023-09-20 18:36:36 +0300 MSK
Links
Code
class Solution:
def isPowerOfFour(self, n: int) -> bool:
# Check if the number is greater than zero and is a power of two
if n > 0 and (n & (n - 1)) == 0:
# Check if the number is of the form 4^x
return n & 0x55555555 == n
else:
return False
4.7.1465 - 2023-09-20 18:32:58 +0300 MSK
Links
Code
class Solution:
def isPowerOfFour(self, n: int) -> bool:
return n and not (n & (n - 1)) and (n & 0x55555555)
4.7.1466 - 2023-09-20 18:32:51 +0300 MSK
Links
Code
class Solution:
def isPowerOfFour(self, n: int) -> bool:
return n and not (n & (n - 1)) and (n & 0x55555555)
4.7.1467 - 2023-09-20 18:32:34 +0300 MSK
Links
Code
class Solution:
def isPowerOfFour(self, n: int) -> bool:
return n and not (n & (n - 1)) and (n & 0x55555555)
4.7.1468 - 2023-09-20 18:02:39 +0300 MSK
Links
Code
class Solution:
def missingNumber(self, nums: List[int]) -> int:
def xor(total: int, i: int) -> int:
return total ^ nums[i] ^ (i + 1)
return reduce(xor, chain((0, ), range(len(nums))))
4.7.1469 - 2023-09-20 18:01:50 +0300 MSK
Links
Code
class Solution:
def missingNumber(self, nums: List[int]) -> int:
return reduce(lambda total, i: total ^ nums[i] ^ (i + 1), chain((0, ), range(len(nums))))
4.7.1470 - 2023-09-20 17:28:42 +0300 MSK
Links
Code
class Solution:
def missingNumber(self, nums: List[int]) -> int:
length = len(nums)
return ((length + 1) * length) // 2 - sum(nums)
4.7.1471 - 2023-09-20 17:07:50 +0300 MSK
Links
Code
class Solution:
def reverseBits(self, n: int) -> int:
# Initialize the reversed number to 0
reversed_num = 0
# Iterate over all 32 bits of the given number
for i in range(32):
# Left shift the reversed number by 1 and add the last bit of the given number to it
reversed_num = (reversed_num << 1) | (n & 1)
# remove the last bit from the original number
n >>= 1
# Return the reversed number
return reversed_num
4.7.1472 - 2023-09-20 16:31:32 +0300 MSK
Links
Code
class Solution:
def addBinary(self, a: str, b: str) -> str:
answer = []
carry = 0
for char1, char2 in zip_longest(reversed(a), reversed(b)):
num1, num2 = int(char1) if char1 else 0, int(char2) if char2 else 0
cur_sum = num1 + num2 + carry
carry = 0
if cur_sum > 1:
cur_sum -= 2
carry = 1
answer.append(str(cur_sum))
if carry:
answer.append("1")
return "".join(reversed(answer))
4.7.1473 - 2023-09-20 11:47:24 +0300 MSK
Links
Code
class Solution:
def minOperations(self, nums: List[int], x: int) -> int:
target, length = sum(nums) - x, len(nums)
max_len = cur_sum = left = 0
if target == 0:
return length
for right, val in enumerate(nums):
cur_sum += val
while left <= right and cur_sum > target:
cur_sum -= nums[left]
left += 1
if cur_sum == target:
max_len = max(max_len, right - left + 1)
return length - max_len if max_len else -1
4.7.1474 - 2023-09-19 21:08:16 +0300 MSK
Links
Code
class Bitset:
def __init__(self, size: int):
self.bits = [0] * size
self.ones_count = 0
self.do_flip = False
self.size = size
def fix(self, idx: int) -> None:
cur = self.bits[idx]
if self.do_flip and cur == 1:
self.ones_count -= 1
self.bits[idx] = 0
elif not self.do_flip and cur == 0:
self.ones_count += 1
self.bits[idx] = 1
def unfix(self, idx: int) -> None:
cur = self.bits[idx]
if self.do_flip and cur == 0:
self.ones_count += 1
self.bits[idx] = 1
elif not self.do_flip and cur == 1:
self.ones_count -= 1
self.bits[idx] = 0
def flip(self) -> None:
self.do_flip = not self.do_flip
def all(self) -> bool:
return self.count() == self.size
def one(self) -> bool:
return self.count() > 0
def count(self) -> int:
return self.size - self.ones_count if self.do_flip else self.ones_count
def toString(self) -> str:
target = (bit ^ 1 for bit in self.bits) if self.do_flip else self.bits
return "".join(str(num) for num in target)
# Your Bitset object will be instantiated and called as such:
# obj = Bitset(size)
# obj.fix(idx)
# obj.unfix(idx)
# obj.flip()
# param_4 = obj.all()
# param_5 = obj.one()
# param_6 = obj.count()
# param_7 = obj.toString()
4.7.1475 - 2023-09-19 20:00:19 +0300 MSK
Links
Code
class Solution:
def findDuplicate(self, nums: List[int]) -> int:
freqs = [False] * (10**5 + 1)
for num in nums:
if freqs[num] == True:
return num
freqs[num] = True
raise Exception()
4.7.1476 - 2023-09-19 19:58:37 +0300 MSK
Links
Code
class Solution:
def findDuplicate(self, nums: List[int]) -> int:
freqs = [0] * (10**5 + 1)
for num in nums:
freqs[num] += 1
if freqs[num] > 1:
return num
raise Exception()
4.7.1477 - 2023-09-18 15:46:36 +0300 MSK
Links
Code
class ProductOfNumbers:
def __init__(self):
self.products = [1]
def add(self, num: int) -> None:
if num == 0:
self.products.clear()
self.products.append(1)
return
self.products.append(num * self.products[-1])
def getProduct(self, k: int) -> int:
if len(self.products) - 1 < k:
return 0
return self.products[-1] // self.products[-(k + 1)]
# Your ProductOfNumbers object will be instantiated and called as such:
# obj = ProductOfNumbers()
# obj.add(num)
# param_2 = obj.getProduct(k)
4.7.1478 - 2023-09-18 15:46:14 +0300 MSK
Links
Code
class ProductOfNumbers:
def __init__(self):
self.products = [1]
def add(self, num: int) -> None:
if num == 0:
self.products = [1]
return
self.products.append(num * self.products[-1])
def getProduct(self, k: int) -> int:
if len(self.products) - 1 < k:
return 0
return self.products[-1] // self.products[-(k + 1)]
# Your ProductOfNumbers object will be instantiated and called as such:
# obj = ProductOfNumbers()
# obj.add(num)
# param_2 = obj.getProduct(k)
4.7.1479 - 2023-09-18 15:38:04 +0300 MSK
Links
Code
class ProductOfNumbers:
def __init__(self):
self.products, self.last_zero, self.length = [], -1, 0
def add(self, num: int) -> None:
if num == 0:
self.last_zero = self.length
num = 1
self.products.append(num * (self.products[-1] if self.products else 1))
self.length += 1
def getProduct(self, k: int) -> int:
first_elem = self.length - k
if self.last_zero >= first_elem:
return 0
if first_elem == 0:
return self.products[-1]
return self.products[-1] // self.products[first_elem - 1]
# Your ProductOfNumbers object will be instantiated and called as such:
# obj = ProductOfNumbers()
# obj.add(num)
# param_2 = obj.getProduct(k)
4.7.1480 - 2023-09-18 15:35:47 +0300 MSK
Links
Code
class ProductOfNumbers:
def __init__(self):
self.products, self.zero_indexes = [], []
def add(self, num: int) -> None:
if num == 0:
self.zero_indexes.append(len(self.products))
num = 1
new_product = num * (self.products[-1] if self.products else 1)
self.products.append(new_product)
def getProduct(self, k: int) -> int:
first_elem = len(self.products) - k
if self.zero_indexes and self.zero_indexes[-1] >= first_elem:
return 0
if first_elem == 0:
return self.products[-1]
return self.products[-1] // self.products[first_elem - 1]
# Your ProductOfNumbers object will be instantiated and called as such:
# obj = ProductOfNumbers()
# obj.add(num)
# param_2 = obj.getProduct(k)
4.7.1481 - 2023-09-18 15:12:57 +0300 MSK
Links
Code
class DataStream:
def __init__(self, value: int, k: int):
self.required, self.value, self.value_count = k, value, 0
def consec(self, num: int) -> bool:
if num != self.value:
self.value_count = 0
return False
self.value_count += 1
return self.value_count >= self.required
# Your DataStream object will be instantiated and called as such:
# obj = DataStream(value, k)
# param_1 = obj.consec(num)
4.7.1482 - 2023-09-18 15:12:07 +0300 MSK
Links
Code
class DataStream:
def __init__(self, value: int, k: int):
self.required, self.value, self.value_count = k, value, 0
def consec(self, num: int) -> bool:
if num != self.value:
self.value_count = 0
return False
self.value_count += 1
return self.value_count >= self.required
# Your DataStream object will be instantiated and called as such:
# obj = DataStream(value, k)
# param_1 = obj.consec(num)
4.7.1483 - 2023-09-18 15:00:25 +0300 MSK
Links
Code
class SmallestInfiniteSet:
def __init__(self):
self.heap, self.next_num, self.nums = [], 1, set()
def popSmallest(self) -> int:
if self.heap:
val = heappop(self.heap)
self.nums.remove(val)
return val
self.next_num += 1
return self.next_num - 1
def addBack(self, num: int) -> None:
if num in self.nums or num >= self.next_num:
return
self.nums.add(num)
heappush(self.heap, num)
# Your SmallestInfiniteSet object will be instantiated and called as such:
# obj = SmallestInfiniteSet()
# param_1 = obj.popSmallest()
# obj.addBack(num)
4.7.1484 - 2023-09-18 14:59:16 +0300 MSK
Links
Code
class SmallestInfiniteSet:
def __init__(self):
self.heap, self.next_num, self.nums = [], 1, set()
def popSmallest(self) -> int:
if not self.heap:
self.next_num += 1
return self.next_num - 1
val = heappop(self.heap)
if val < self.next_num:
self.nums.remove(val)
return val
heappush(self.heap, val)
self.next_num += 1
return self.next_num - 1
def addBack(self, num: int) -> None:
if num in self.nums or num >= self.next_num:
return
self.nums.add(num)
heappush(self.heap, num)
# Your SmallestInfiniteSet object will be instantiated and called as such:
# obj = SmallestInfiniteSet()
# param_1 = obj.popSmallest()
# obj.addBack(num)
4.7.1485 - 2023-09-18 14:37:29 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class FindElements:
def __init__(self, root: Optional[TreeNode]):
root.val = 0
nodes = [root]
self.values = set((0, ))
while nodes:
node = nodes.pop()
if node.left:
val = 2 * node.val + 1
node.left.val = val
nodes.append(node.left)
self.values.add(val)
if node.right:
val = 2 * node.val + 2
node.right.val = val
nodes.append(node.right)
self.values.add(val)
def find(self, target: int) -> bool:
return target in self.values
# Your FindElements object will be instantiated and called as such:
# obj = FindElements(root)
# param_1 = obj.find(target)
4.7.1486 - 2023-09-18 14:34:48 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class FindElements:
def __init__(self, root: Optional[TreeNode]):
self.root = root
root.val = 0
nodes = [root]
while nodes:
node = nodes.pop()
new_val = 2 * node.val
if node.left:
node.left.val = new_val + 1
nodes.append(node.left)
if node.right:
node.right.val = new_val + 2
nodes.append(node.right)
def dfs(self, node: TreeNode, target: int) -> bool:
if not node or node.val > target:
return False
if node.val == target:
return True
return self.dfs(node.left, target) or self.dfs(node.right, target)
def find(self, target: int) -> bool:
return self.dfs(self.root, target)
# Your FindElements object will be instantiated and called as such:
# obj = FindElements(root)
# param_1 = obj.find(target)
4.7.1487 - 2023-09-18 13:54:11 +0300 MSK
Links
Code
class RangeFreqQuery:
def __init__(self, arr: List[int]):
self.l = [[] for _ in range(10001)]
for i, v in enumerate(arr):
self.l[v].append(i)
def query(self, left: int, right: int, v: int) -> int:
return bisect_right(self.l[v], right) - bisect_left(self.l[v], left)
# Your RangeFreqQuery object will be instantiated and called as such:
# obj = RangeFreqQuery(arr)
# param_1 = obj.query(left,right,value)
4.7.1488 - 2023-09-18 09:47:53 +0300 MSK
Links
Code
class Solution:
def kWeakestRows(self, mat: List[List[int]], k: int) -> List[int]:
rows_count, cols_count = len(mat), len(mat[0])
heap = []
for i, row in enumerate(mat):
count = 0
for j, val in enumerate(row):
if val == 0:
count = j
break
else:
count = cols_count
heappush(heap, (count, i))
return tuple(item[1] for item in nsmallest(k, heap))
4.7.1489 - 2023-09-17 16:27:05 +0300 MSK
Links
Code
class MagicDictionary:
def __init__(self):
self.dict = []
def buildDict(self, dictionary: List[str]) -> None:
self.dict = dictionary
def search(self, searchWord: str) -> bool:
target_length = len(searchWord)
for word in self.dict:
if len(word) != target_length or word == searchWord:
continue
found_diff = False
for i in range(target_length):
if word[i] == searchWord[i]:
continue
if found_diff:
break
found_diff = True
else:
return True
return False
# Your MagicDictionary object will be instantiated and called as such:
# obj = MagicDictionary()
# obj.buildDict(dictionary)
# param_2 = obj.search(searchWord)
4.7.1490 - 2023-09-17 16:16:53 +0300 MSK
Links
Code
class Codec:
def __init__(self):
self.urls = []
def encode(self, longUrl: str) -> str:
"""Encodes a URL to a shortened URL.
"""
self.urls.append(longUrl)
return len(self.urls)
def decode(self, shortUrl: str) -> str:
"""Decodes a shortened URL to its original URL.
"""
return self.urls[shortUrl - 1]
# Your Codec object will be instantiated and called as such:
# codec = Codec()
# codec.decode(codec.encode(url))
4.7.1491 - 2023-09-17 16:14:59 +0300 MSK
Links
Code
class Codec:
def __init__(self):
self.urls = {}
self.id = 0
def encode(self, longUrl: str) -> str:
"""Encodes a URL to a shortened URL.
"""
id = self.id
self.urls[id] = longUrl
self.id += 1
return id
def decode(self, shortUrl: str) -> str:
"""Decodes a shortened URL to its original URL.
"""
return self.urls[int(shortUrl)]
# Your Codec object will be instantiated and called as such:
# codec = Codec()
# codec.decode(codec.encode(url))
4.7.1492 - 2023-09-17 16:12:53 +0300 MSK
Links
Code
class Codec:
def __init__(self):
self.urls = []
def encode(self, longUrl: str) -> str:
"""Encodes a URL to a shortened URL.
"""
self.urls.append(longUrl)
return str(len(self.urls) - 1)
def decode(self, shortUrl: str) -> str:
"""Decodes a shortened URL to its original URL.
"""
return self.urls[int(shortUrl)]
# Your Codec object will be instantiated and called as such:
# codec = Codec()
# codec.decode(codec.encode(url))
4.7.1493 - 2023-09-17 16:08:12 +0300 MSK
Links
Code
class Twitter:
def __init__(self):
self.tweets = []
self.following = defaultdict(set)
def postTweet(self, userId: int, tweetId: int) -> None:
self.tweets.append((userId, tweetId))
def getNewsFeed(self, userId: int) -> List[int]:
tweets, following = [], self.following[userId]
for poster, tweet in reversed(self.tweets):
if poster != userId and poster not in following:
continue
tweets.append(tweet)
if len(tweets) == 10:
break
return tweets
def follow(self, followerId: int, followeeId: int) -> None:
self.following[followerId].add(followeeId)
def unfollow(self, followerId: int, followeeId: int) -> None:
self.following[followerId].discard(followeeId)
# Your Twitter object will be instantiated and called as such:
# obj = Twitter()
# obj.postTweet(userId,tweetId)
# param_2 = obj.getNewsFeed(userId)
# obj.follow(followerId,followeeId)
# obj.unfollow(followerId,followeeId)
4.7.1494 - 2023-09-17 11:45:39 +0300 MSK
Links
Code
from collections import deque, namedtuple
class Solution:
def shortestPathLength(self, graph):
n = len(graph)
all_mask = (1 << n) - 1
visited = set()
Node = namedtuple('Node', ['node', 'mask', 'cost'])
q = deque()
for i in range(n):
mask_value = (1 << i)
this_node = Node(i, mask_value, 1)
q.append(this_node)
visited.add((i, mask_value))
while q:
curr = q.popleft()
if curr.mask == all_mask:
return curr.cost - 1
for adj in graph[curr.node]:
both_visited_mask = curr.mask | (1 << adj)
this_node = Node(adj, both_visited_mask, curr.cost + 1)
if (adj, both_visited_mask) not in visited:
visited.add((adj, both_visited_mask))
q.append(this_node)
return -1
4.7.1495 - 2023-09-17 11:44:04 +0300 MSK
Links
Code
class Trie:
def __init__(self):
self.root = {}
def insert(self, word: str) -> None:
cur = self.root
for char in word:
if char not in cur:
cur[char] = {}
cur = cur[char]
cur["_is_word"] = None
def search(self, word: str) -> bool:
cur = self.root
for char in word:
if char not in cur:
return False
cur = cur[char]
return "_is_word" in cur
def startsWith(self, prefix: str) -> bool:
cur = self.root
for char in prefix:
if char not in cur:
return False
cur = cur[char]
return True
# Your Trie object will be instantiated and called as such:
# obj = Trie()
# obj.insert(word)
# param_2 = obj.search(word)
# param_3 = obj.startsWith(prefix)
4.7.1496 - 2023-09-17 11:40:01 +0300 MSK
Links
Code
class Node:
def __init__(self):
self.ch, self.is_word = [None] * 128, False
class Trie:
def __init__(self):
self.head = Node()
def insert(self, word: str) -> None:
cur_node = self.head
for i in range(len(word)):
char = ord(word[i])
if cur_node.ch[char] is None:
cur_node.ch[char] = Node()
cur_node = cur_node.ch[char]
cur_node.is_word = True
def search(self, word: str) -> bool:
cur_node = self.head
for i in range(len(word)):
char = ord(word[i])
if cur_node.ch[char] is None:
return False
cur_node = cur_node.ch[char]
return cur_node.is_word
def startsWith(self, prefix: str) -> bool:
cur_node = self.head
for i in range(len(prefix)):
char = ord(prefix[i])
if cur_node.ch[char] is None:
return False
cur_node = cur_node.ch[char]
return True
# Your Trie object will be instantiated and called as such:
# obj = Trie()
# obj.insert(word)
# param_2 = obj.search(word)
# param_3 = obj.startsWith(prefix)
4.7.1497 - 2023-09-16 21:10:06 +0300 MSK
Links
Code
class Cashier:
def __init__(self, n: int, discount: int, products: List[int], prices: List[int]):
self.freq, self.discount = n, (100 - discount) / 100
self.cur = 0
self.products = {id: price for id, price in zip(products, prices)}
def getBill(self, product: List[int], amount: List[int]) -> float:
self.cur += 1
total = sum(amount[i] * self.products[product[i]] for i in range(len(product)))
if self.cur < self.freq:
return total
self.cur = 0
return total * self.discount
# Your Cashier object will be instantiated and called as such:
# obj = Cashier(n, discount, products, prices)
# param_1 = obj.getBill(product,amount)
4.7.1498 - 2023-09-16 21:07:33 +0300 MSK
Links
Code
class Cashier:
def __init__(self, n: int, discount: int, products: List[int], prices: List[int]):
self.freq, self.discount = n, (100 - discount) / 100
self.cur = 0
self.products = {id: price for id, price in zip(products, prices)}
def getBill(self, product: List[int], amount: List[int]) -> float:
self.cur += 1
multiplier = 1
if self.cur == self.freq:
self.cur, multiplier = 0, self.discount
total = sum(amount[i] * self.products[product[i]] for i in range(len(product)))
return total * multiplier
# Your Cashier object will be instantiated and called as such:
# obj = Cashier(n, discount, products, prices)
# param_1 = obj.getBill(product,amount)
4.7.1499 - 2023-09-16 20:44:34 +0300 MSK
Links
Code
class UndergroundSystem:
def __init__(self):
self.from_to = defaultdict(lambda: defaultdict(list))
self.in_transit = {}
def checkIn(self, id: int, stationName: str, t: int) -> None:
self.in_transit[id] = (stationName, t)
def checkOut(self, id: int, stationName: str, t: int) -> None:
station_from, time_from = self.in_transit.pop(id)
self.from_to[station_from][stationName].append(t - time_from)
def getAverageTime(self, startStation: str, endStation: str) -> float:
times = self.from_to[startStation][endStation]
return sum(times) / len(times)
# Your UndergroundSystem object will be instantiated and called as such:
# obj = UndergroundSystem()
# obj.checkIn(id,stationName,t)
# obj.checkOut(id,stationName,t)
# param_3 = obj.getAverageTime(startStation,endStation)
4.7.1500 - 2023-09-16 20:20:21 +0300 MSK
Links
Code
class OrderedStream:
def __init__(self, n: int):
self.data = [None]*n
self.ptr = 0 # 0-indexed
def insert(self, id: int, value: str) -> List[str]:
id -= 1 # 0-indexed
self.data[id] = value
if id > self.ptr: return [] # not reaching ptr
while self.ptr < len(self.data) and self.data[self.ptr]: self.ptr += 1 # update self.ptr
return self.data[id:self.ptr]
# Your OrderedStream object will be instantiated and called as such:
# obj = OrderedStream(n)
# param_1 = obj.insert(idKey,value)
4.7.1501 - 2023-09-16 20:18:19 +0300 MSK
Links
Code
class OrderedStream:
def __init__(self, n: int):
self.values = [None] * n
self.length = n
self.cur = 0
def insert(self, idKey: int, value: str) -> List[str]:
self.values[idKey - 1] = value
for i in range(self.cur, self.length):
if self.values[i] is not None:
continue
self.cur, answer = i, self.values[self.cur:i]
return answer
return self.values[self.cur:]
# Your OrderedStream object will be instantiated and called as such:
# obj = OrderedStream(n)
# param_1 = obj.insert(idKey,value)
4.7.1502 - 2023-09-16 15:46:43 +0300 MSK
Links
Code
class AuthenticationManager:
def __init__(self, timeToLive: int):
self.ttl = timeToLive
self.tokens = {}
def generate(self, tokenId: str, currentTime: int) -> None:
self.tokens[tokenId] = currentTime + self.ttl
def renew(self, tokenId: str, currentTime: int) -> None:
if currentTime < self.tokens.get(tokenId, currentTime):
self.generate(tokenId, currentTime)
else:
self.tokens.pop(tokenId, None)
def countUnexpiredTokens(self, currentTime: int) -> int:
count = 0
remove_tokens = []
for token, expir_time in self.tokens.items():
if currentTime < expir_time:
count += 1
else:
remove_tokens.append(token)
for token in remove_tokens:
self.tokens.pop(token)
return count
# Your AuthenticationManager object will be instantiated and called as such:
# obj = AuthenticationManager(timeToLive)
# obj.generate(tokenId,currentTime)
# obj.renew(tokenId,currentTime)
# param_3 = obj.countUnexpiredTokens(currentTime)
4.7.1503 - 2023-09-16 15:35:37 +0300 MSK
Links
Code
class SeatManager:
def __init__(self, n: int):
self.heap = list(range(1, n + 1))
def reserve(self) -> int:
return heappop(self.heap)
def unreserve(self, seatNumber: int) -> None:
heappush(self.heap, seatNumber)
# Your SeatManager object will be instantiated and called as such:
# obj = SeatManager(n)
# param_1 = obj.reserve()
# obj.unreserve(seatNumber)
4.7.1504 - 2023-09-16 15:34:15 +0300 MSK
Links
Code
class SeatManager:
def __init__(self, n: int):
self.heap = list(range(1, n + 1))
heapify(self.heap)
def reserve(self) -> int:
return heappop(self.heap)
def unreserve(self, seatNumber: int) -> None:
heappush(self.heap, seatNumber)
# Your SeatManager object will be instantiated and called as such:
# obj = SeatManager(n)
# param_1 = obj.reserve()
# obj.unreserve(seatNumber)
4.7.1505 - 2023-09-16 11:35:52 +0300 MSK
Links
Code
class Bank:
def __init__(self, balance: List[int]):
self.balance = balance
self.size = len(balance)
def transfer(self, account1: int, account2: int, money: int) -> bool:
if not 0 < account1 <= self.size or not 0 < account2 <= self.size or (
self.balance[account1-1] < money
):
return False
self.balance[account2-1] += money
self.balance[account1-1] -= money
return True
def deposit(self, account: int, money: int) -> bool:
if not 0 < account <= self.size:
return False
self.balance[account-1] += money
return True
def withdraw(self, account: int, money: int) -> bool:
if not 0 < account <= self.size or self.balance[account-1] < money:
return False
self.balance[account-1] -= money
return True
# Your Bank object will be instantiated and called as such:
# obj = Bank(balance)
# param_1 = obj.transfer(account1,account2,money)
# param_2 = obj.deposit(account,money)
# param_3 = obj.withdraw(account,money)
4.7.1506 - 2023-09-16 11:25:54 +0300 MSK
Links
Code
class Solution:
def minimumEffortPath(self, heights: List[List[int]]) -> int:
rows, cols = len(heights), len(heights[0])
directions = [(0, 1), (0, -1), (1, 0), (-1, 0)]
dist = [[math.inf for _ in range(cols)] for _ in range(rows)]
dist[0][0] = 0
minHeap = [(0, 0, 0)]
while minHeap:
effort, x, y = heappop(minHeap)
if x == rows - 1 and y == cols - 1:
return effort
for dx, dy in directions:
nx, ny = x + dx, y + dy
if 0 <= nx < rows and 0 <= ny < cols:
new_effort = max(effort, abs(heights[x][y] - heights[nx][ny]))
if new_effort < dist[nx][ny]:
dist[nx][ny] = new_effort
heappush(minHeap, (new_effort, nx, ny))
4.7.1507 - 2023-09-15 19:59:56 +0300 MSK
Links
Code
class NumberContainers:
def __init__(self):
self.num_indices = defaultdict(list)
self.num_at_index = {}
def change(self, index: int, number: int) -> None:
self.num_at_index[index] = number
heapq.heappush(self.num_indices[number], index)
def find(self, number: int) -> int:
while self.num_indices[number] and self.num_at_index[self.num_indices[number][0]] != number:
heapq.heappop(self.num_indices[number])
return self.num_indices[number][0] if len(self.num_indices[number]) > 0 else -1
# Your NumberContainers object will be instantiated and called as such:
# obj = NumberContainers()
# obj.change(index,number)
# param_2 = obj.find(number)
4.7.1508 - 2023-09-15 19:53:02 +0300 MSK
Links
Code
import sortedcontainers
class NumberContainers:
def __init__(self):
self._idx_number = {}
self._number_idx = defaultdict(sortedcontainers.SortedSet)
def change(self, index: int, number: int) -> None:
cur_number = self._idx_number.get(index, -1)
if cur_number != -1:
self._number_idx[cur_number].remove(index)
self._idx_number[index] = number
self._number_idx[number].add(index)
def find(self, number: int) -> int:
ids = self._number_idx[number]
return ids[0] if ids else -1
# Your NumberContainers object will be instantiated and called as such:
# obj = NumberContainers()
# obj.change(index,number)
# param_2 = obj.find(number)
4.7.1509 - 2023-09-15 19:34:44 +0300 MSK
Links
Code
class FindSumPairs:
def __init__(self, nums1: List[int], nums2: List[int]):
self._nums1, self._nums2, self._nums2_raw = Counter(nums1), Counter(nums2), nums2
def add(self, index: int, val: int) -> None:
nums2_raw, nums2 = self._nums2_raw, self._nums2
cur_val = nums2_raw[index]
new_val = cur_val + val
if nums2[cur_val] > 0:
nums2[cur_val] -= 1
nums2_raw[index] = new_val
nums2[new_val] += 1
def count(self, tot: int) -> int:
return sum(num1_count * self._nums2.get(tot - num1, 0)
for num1, num1_count in self._nums1.items())
# Your FindSumPairs object will be instantiated and called as such:
# obj = FindSumPairs(nums1, nums2)
# obj.add(index,val)
# param_2 = obj.count(tot)
4.7.1510 - 2023-09-15 19:33:23 +0300 MSK
Links
Code
class FindSumPairs:
def __init__(self, nums1: List[int], nums2: List[int]):
self._nums1, self._nums2, self._nums2_raw = Counter(nums1), Counter(nums2), nums2
def add(self, index: int, val: int) -> None:
nums2_raw, nums2 = self._nums2_raw, self._nums2
cur_val = nums2_raw[index]
new_val = cur_val + val
if nums2[cur_val] > 0:
nums2[cur_val] -= 1
nums2_raw[index] = new_val
nums2[new_val] += 1
def count(self, tot: int) -> int:
sum_count = 0
nums2 = self._nums2
for num1, num1_count in self._nums1.items():
sum_count += num1_count * nums2.get(tot - num1, 0)
return sum_count
# Your FindSumPairs object will be instantiated and called as such:
# obj = FindSumPairs(nums1, nums2)
# obj.add(index,val)
# param_2 = obj.count(tot)
4.7.1511 - 2023-09-15 19:12:52 +0300 MSK
Links
Code
class BrowserHistory:
def __init__(self, homepage: str):
self._history = [homepage]
self._cur = 0
def visit(self, url: str) -> None:
self._history[self._cur+1:] = (url, )
self._cur += 1
def back(self, steps: int) -> str:
self._cur = max(0, self._cur - steps)
return self._history[self._cur]
def forward(self, steps: int) -> str:
self._cur = min(len(self._history) - 1, self._cur + steps)
return self._history[self._cur]
# Your BrowserHistory object will be instantiated and called as such:
# obj = BrowserHistory(homepage)
# obj.visit(url)
# param_2 = obj.back(steps)
# param_3 = obj.forward(steps)
4.7.1512 - 2023-09-15 19:05:16 +0300 MSK
Links
Code
class CustomStack:
def __init__(self, maxSize: int):
self._stack = []
self._max_size = maxSize
def push(self, x: int) -> None:
if len(self._stack) != self._max_size:
self._stack.append(x)
def pop(self) -> int:
return self._stack.pop() if self._stack else -1
def increment(self, k: int, val: int) -> None:
for i in range(min(k, len(self._stack))):
self._stack[i] += val
# Your CustomStack object will be instantiated and called as such:
# obj = CustomStack(maxSize)
# obj.push(x)
# param_2 = obj.pop()
# obj.increment(k,val)
4.7.1513 - 2023-09-15 19:02:42 +0300 MSK
Links
Code
class CustomStack:
def __init__(self, maxSize: int):
self._stack = []
self._max_size = maxSize
self._size = 0
def push(self, x: int) -> None:
if self._size == self._max_size:
return
self._stack.append(x)
self._size += 1
def pop(self) -> int:
if self._size == 0:
return -1
last = self._stack.pop()
self._size -= 1
return last
def increment(self, k: int, val: int) -> None:
for i in range(min(k, self._size)):
self._stack[i] += val
# Your CustomStack object will be instantiated and called as such:
# obj = CustomStack(maxSize)
# obj.push(x)
# param_2 = obj.pop()
# obj.increment(k,val)
4.7.1514 - 2023-09-15 18:53:00 +0300 MSK
Links
Code
class Node:
def __init__(self, val: int = 0, prev_node: 'Node' = None, next_node: 'Node' = None):
self.val, self.prev, self.next = val, prev_node, next_node
class MyLinkedList:
def __init__(self):
self._head, self._tail = Node(float("-inf")), Node(float("inf"))
self._head.next, self._tail.prev = self._tail, self._head
self._length = 0
def _getNode(self, index: int) -> Node:
if not 0 <= index < self._length:
return None
if index == 0:
return self._head.next
if index == self._length - 1:
return self._tail.prev
cur_idx, cur_node = 0, self._head.next
while cur_idx < index:
cur_node = cur_node.next
cur_idx += 1
return cur_node
def get(self, index: int) -> int:
node = self._getNode(index)
return node.val if node else -1
def addAtHead(self, val: int) -> None:
old_first = self._head.next
new_node = Node(val, self._head, old_first)
self._head.next, old_first.prev = new_node, new_node
self._length += 1
def addAtTail(self, val: int) -> None:
old_tail = self._tail.prev
new_node = Node(val, old_tail, self._tail)
self._tail.prev, old_tail.next = new_node, new_node
self._length += 1
def addAtIndex(self, index: int, val: int) -> None:
if not 0 <= index <= self._length:
return
if index == 0:
self.addAtHead(val)
return
if index == self._length:
self.addAtTail(val)
return
target_node = self._getNode(index)
prev_node = target_node.prev
new_node = Node(val, prev_node, target_node)
prev_node.next, target_node.prev = new_node, new_node
self._length += 1
def deleteAtIndex(self, index: int) -> None:
if not 0 <= index < self._length:
return
target_node = self._getNode(index)
old_prev, old_next = target_node.prev, target_node.next
old_prev.next, old_next.prev = old_next, old_prev
self._length -= 1
# Your MyLinkedList object will be instantiated and called as such:
# obj = MyLinkedList()
# param_1 = obj.get(index)
# obj.addAtHead(val)
# obj.addAtTail(val)
# obj.addAtIndex(index,val)
# obj.deleteAtIndex(index)
4.7.1515 - 2023-09-15 17:07:59 +0300 MSK
Links
Code
class NumMatrix:
def __init__(self, matrix: List[List[int]]):
self.dp=[[0] * (len(matrix[0])+1) for _ in range(len(matrix)+1)]
# calculate prefix sum
for r in range(len(self.dp)-1):
for c in range(len(self.dp[0])-1):
self.dp[r+1][c+1]=matrix[r][c] + self.dp[r][c+1] + self.dp[r+1][c] - self.dp[r][c]
def sumRegion(self, row1: int, col1: int, row2: int, col2: int) -> int:
return self.dp[row2+1][col2+1] - self.dp[row1][col2+1] - self.dp[row2+1][col1] + self.dp[row1][col1]
4.7.1516 - 2023-09-15 12:51:11 +0300 MSK
Links
Code
# Below is the interface for Iterator, which is already defined for you.
#
# class Iterator:
# def __init__(self, nums):
# """
# Initializes an iterator object to the beginning of a list.
# :type nums: List[int]
# """
#
# def hasNext(self):
# """
# Returns true if the iteration has more elements.
# :rtype: bool
# """
#
# def next(self):
# """
# Returns the next element in the iteration.
# :rtype: int
# """
class PeekingIterator:
def __init__(self, iterator):
"""
Initialize your data structure here.
:type iterator: Iterator
"""
self._iter = iterator
self._next = iterator.next()
def peek(self):
"""
Returns the next element in the iteration without advancing the iterator.
:rtype: int
"""
return self._next
def next(self):
"""
:rtype: int
"""
cur_next = self._next
self._next = self._iter.next() if self._iter.hasNext() else None
return cur_next
def hasNext(self):
"""
:rtype: bool
"""
return self._next is not None
# Your PeekingIterator object will be instantiated and called as such:
# iter = PeekingIterator(Iterator(nums))
# while iter.hasNext():
# val = iter.peek() # Get the next element but not advance the iterator.
# iter.next() # Should return the same value as [val].
4.7.1517 - 2023-09-15 09:59:15 +0300 MSK
Links
Code
def manhattan_distance(p1: List[int], p2: List[int]) -> int:
return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
class Solution:
def minCostConnectPoints(self, points: List[List[int]]) -> int:
n = len(points)
visited = [False] * n
heap_dict = {0: 0}
min_heap = [(0, 0)]
mst_weight = 0
while min_heap:
w, u = heappop(min_heap)
if visited[u] or heap_dict.get(u, float('inf')) < w:
continue
visited[u] = True
mst_weight += w
for v in range(n):
if not visited[v]:
new_distance = manhattan_distance(points[u], points[v])
if new_distance < heap_dict.get(v, float('inf')):
heap_dict[v] = new_distance
heappush(min_heap, (new_distance, v))
return mst_weight
4.7.1518 - 2023-09-14 19:02:15 +0300 MSK
Links
Code
class FrequencyTracker:
def __init__(self):
self._num_freq = defaultdict(int)
self._freq_nums = defaultdict(set)
def add(self, number: int) -> None:
cur_freq = self._num_freq[number]
self._num_freq[number] = cur_freq + 1
self._freq_nums[cur_freq].discard(number)
self._freq_nums[cur_freq + 1].add(number)
def deleteOne(self, number: int) -> None:
cur_freq = self._num_freq[number]
if cur_freq == 0:
return
self._num_freq[number] = cur_freq - 1
self._freq_nums[cur_freq].discard(number)
if cur_freq != 1:
self._freq_nums[cur_freq - 1].add(number)
def hasFrequency(self, frequency: int) -> bool:
return len(self._freq_nums[frequency]) != 0
# Your FrequencyTracker object will be instantiated and called as such:
# obj = FrequencyTracker()
# obj.add(number)
# obj.deleteOne(number)
# param_3 = obj.hasFrequency(frequency)
4.7.1519 - 2023-09-14 18:45:02 +0300 MSK
Links
Code
class ATM:
def __init__(self):
self._banknotes = (0, ) * 5
self._values = (20, 50, 100, 200, 500)
def deposit(self, banknotesCount: List[int]) -> None:
self._banknotes = tuple(banknotesCount[i] + self._banknotes[i] for i in range(5))
def withdraw(self, amount: int) -> List[int]:
withdrawn = [0] * 5
for i in reversed(range(5)):
value, notes_left = self._values[i], self._banknotes[i]
notes_need = min(notes_left, amount // value)
if notes_need == 0:
continue
amount -= value * notes_need
withdrawn[i] = notes_need
if amount == 0:
self._banknotes = tuple(self._banknotes[i] - withdrawn[i]
for i in range(5))
return withdrawn
return (-1, )
# Your ATM object will be instantiated and called as such:
# obj = ATM()
# obj.deposit(banknotesCount)
# param_2 = obj.withdraw(amount)
4.7.1520 - 2023-09-14 18:44:27 +0300 MSK
Links
Code
class ATM:
def __init__(self):
self._banknotes = (0, ) * 5
self._values = (20, 50, 100, 200, 500)
def deposit(self, banknotesCount: List[int]) -> None:
self._banknotes = tuple(banknotesCount[i] + self._banknotes[i] for i in range(5))
def withdraw(self, amount: int) -> List[int]:
withdrawn = [0] * 5
for i in reversed(range(5)):
value, notes_left = self._values[i], self._banknotes[i]
notes_need = min(notes_left, amount // value)
if notes_need == 0:
continue
amount -= value * notes_need
withdrawn[i] = notes_need
if amount == 0:
self._banknotes = tuple(self._banknotes[i] - withdrawn[i]
for i in range(5))
return withdrawn
return (-1, )
# Your ATM object will be instantiated and called as such:
# obj = ATM()
# obj.deposit(banknotesCount)
# param_2 = obj.withdraw(amount)
4.7.1521 - 2023-09-14 18:40:55 +0300 MSK
Links
Code
class ATM:
def __init__(self):
self._banknotes = [0] * 5
self._values = (20, 50, 100, 200, 500)
def deposit(self, banknotesCount: List[int]) -> None:
for i in range(5):
self._banknotes[i] += banknotesCount[i]
def withdraw(self, amount: int) -> List[int]:
withdrawn = [0] * 5
for i in reversed(range(5)):
value, notes_left = self._values[i], self._banknotes[i]
notes_need = min(notes_left, amount // value)
if notes_need == 0:
continue
amount -= value * notes_need
withdrawn[i] = notes_need
if amount == 0:
for i in range(5):
self._banknotes[i] -= withdrawn[i]
return withdrawn
return [-1]
# Your ATM object will be instantiated and called as such:
# obj = ATM()
# obj.deposit(banknotesCount)
# param_2 = obj.withdraw(amount)
4.7.1522 - 2023-09-14 18:08:10 +0300 MSK
Links
Code
class Allocator:
def __init__(self, n: int):
self._units = [1] * n
self._units[0] = n
self._id_units = defaultdict(list)
self._units_count = n
def find_avail_units(self, start: int, size: int) -> Tuple[int, int]:
i = start
count = 0
while i < self._units_count and i - start < size:
units_avail = self._units[i]
if units_avail < 0:
return i + units_avail if i == start else i, count
i += units_avail
count += units_avail
return i, count
def allocate(self, size: int, mID: int) -> int:
i = 0
units_start, units_count = None, 0
while i < self._units_count and units_count < size:
units_avail = self._units[i]
if units_avail < 0:
i += -units_avail
units_start, units_count = None, 0
continue
if units_start is None:
units_start = i
units_count += units_avail
i += units_avail
if units_count < size:
return -1
self._units[units_start] = -size
if units_count > size:
self._units[units_start + size] = units_count - size
self._id_units[mID].append(units_start)
return units_start
def free(self, mID: int) -> int:
count = 0
conseq_units = self._id_units[mID]
while conseq_units:
units_start = conseq_units.pop()
units_freed = -self._units[units_start]
count += units_freed
self._units[units_start] = units_freed
return count
# Your Allocator object will be instantiated and called as such:
# obj = Allocator(n)
# param_1 = obj.allocate(size,mID)
# param_2 = obj.free(mID)
4.7.1523 - 2023-09-14 14:41:43 +0300 MSK
Links
Code
class Solution:
def findItinerary(self, tickets: List[List[str]]) -> List[str]:
graph = defaultdict(list)
for src, dst in sorted(tickets, reverse=True):
graph[src].append(dst)
itinerary = []
def dfs(airport: str) -> None:
while graph[airport]:
dfs(graph[airport].pop())
itinerary.append(airport)
dfs("JFK")
return itinerary[::-1]
4.7.1524 - 2023-09-13 19:20:05 +0300 MSK
Links
Code
class DetectSquares:
def __init__(self):
self._row_col = defaultdict(lambda: defaultdict(int))
def add(self, point: List[int]) -> None:
self._row_col[point[0]][point[1]] += 1
def count(self, point: List[int]) -> int:
ways_count = 0
row1, col1 = point
for col2, col2_count in self._row_col[row1].items():
if col2 == col1:
continue
side = col2 - col1
for row2 in (row1 + side, row1 - side):
point3_count = self._row_col[row2][col1]
point4_count = self._row_col[row2][col2]
ways_count += col2_count * point3_count * point4_count
return ways_count
# Your DetectSquares object will be instantiated and called as such:
# obj = DetectSquares()
# obj.add(point)
# param_2 = obj.count(point)
4.7.1525 - 2023-09-13 11:18:48 +0300 MSK
Links
Code
class Solution:
def candy(self, ratings: List[int]) -> int:
child_count = len(ratings)
candies = [1] * child_count
for i in range(1, child_count):
if ratings[i] > ratings[i-1]:
candies[i] = candies[i-1] + 1
for i in reversed(range(child_count - 1)):
if ratings[i] > ratings[i+1]:
candies[i] = max(candies[i], candies[i+1] + 1)
return sum(candies)
4.7.1526 - 2023-09-12 19:36:36 +0300 MSK
Links
Code
class TweetCounts:
def __init__(self):
self._tweets = defaultdict(list)
self._chunk_ranges = {
"minute": 60,
"hour": 3600,
"day": 86400
}
def recordTweet(self, tweetName: str, time: int) -> None:
self._tweets[tweetName].append(time)
def getTweetCountsPerFrequency(self, freq: str, tweetName: str, startTime: int, endTime: int) -> List[int]:
chunk_range = self._chunk_ranges[freq]
chunks = [0] * (1 + (endTime - startTime) // chunk_range)
for tweet in self._tweets[tweetName]:
if not startTime <= tweet <= endTime:
continue
chunks[(tweet - startTime) // chunk_range] += 1
return chunks
# Your TweetCounts object will be instantiated and called as such:
# obj = TweetCounts()
# obj.recordTweet(tweetName,time)
# param_2 = obj.getTweetCountsPerFrequency(freq,tweetName,startTime,endTime)
4.7.1527 - 2023-09-12 16:32:10 +0300 MSK
Links
Code
class SnapshotArray:
def __init__(self, length: int):
self._cur_snap = 0
self._elems = [[(0, 0)] for _ in range(length)]
def set(self, index: int, val: int) -> None:
values = self._elems[index]
if values[-1][0] == self._cur_snap:
values.pop()
values.append((self._cur_snap, val))
def snap(self) -> int:
self._cur_snap += 1
return self._cur_snap - 1
def get(self, index: int, snap_id: int) -> int:
for cur_snap_id, val in reversed(self._elems[index]):
if cur_snap_id > snap_id:
continue
return val
return -1
# Your SnapshotArray object will be instantiated and called as such:
# obj = SnapshotArray(length)
# obj.set(index,val)
# param_2 = obj.snap()
# param_3 = obj.get(index,snap_id)
4.7.1528 - 2023-09-12 15:42:35 +0300 MSK
Links
Code
class TimeMap:
def __init__(self):
self._cache = defaultdict(list)
def set(self, key: str, value: str, timestamp: int) -> None:
self._cache[key].append((timestamp, value))
def get(self, key: str, timestamp: int) -> str:
for cur_timestamp, value in reversed(self._cache[key]):
if cur_timestamp > timestamp:
continue
return value
return ""
# Your TimeMap object will be instantiated and called as such:
# obj = TimeMap()
# obj.set(key,value,timestamp)
# param_2 = obj.get(key,timestamp)
4.7.1529 - 2023-09-12 15:27:56 +0300 MSK
Links
Code
class ParkingSystem:
def __init__(self, big: int, medium: int, small: int):
self._slots = [0, big, medium, small]
def addCar(self, carType: int) -> bool:
slots_avail = self._slots[carType]
if not slots_avail:
return False
self._slots[carType] = slots_avail - 1
return True
# Your ParkingSystem object will be instantiated and called as such:
# obj = ParkingSystem(big, medium, small)
# param_1 = obj.addCar(carType)
4.7.1530 - 2023-09-12 15:23:56 +0300 MSK
Links
Code
class ParkingSystem:
def __init__(self, big: int, medium: int, small: int):
self._slots = [big, medium, small]
def addCar(self, carType: int) -> bool:
if self._slots[carType-1] == 0:
return False
self._slots[carType-1] -= 1
return True
# Your ParkingSystem object will be instantiated and called as such:
# obj = ParkingSystem(big, medium, small)
# param_1 = obj.addCar(carType)
4.7.1531 - 2023-09-12 15:21:06 +0300 MSK
Links
Code
class RecentCounter:
def __init__(self):
self._queue = deque()
def ping(self, t: int) -> int:
self._queue.append(t)
while self._queue:
if t - self._queue[0] > 3000:
self._queue.popleft()
else:
break
return len(self._queue)
# Your RecentCounter object will be instantiated and called as such:
# obj = RecentCounter()
# param_1 = obj.ping(t)
4.7.1532 - 2023-09-12 14:23:58 +0300 MSK
Links
Code
class NumArray:
def __init__(self, nums: List[int]):
self._sums = tuple(accumulate(nums))
def sumRange(self, left: int, right: int) -> int:
# [-2, 0, 3, -5, 2, -1], [-2, -2, 1, -4, -2, -3]
# [0, 2] -> 1
if left == 0:
return self._sums[right]
return self._sums[right] - self._sums[left-1]
# Your NumArray object will be instantiated and called as such:
# obj = NumArray(nums)
# param_1 = obj.sumRange(left,right)
4.7.1533 - 2023-09-12 14:12:53 +0300 MSK
Links
Code
class NumArray:
def __init__(self, nums: List[int]):
self._nums = nums
@cache
def sumRange(self, left: int, right: int) -> int:
if right == left:
return self._nums[left]
if right - left == 1:
return self._nums[right] + self._nums[left]
mid = left + (right - left) // 2
return self.sumRange(left, mid) + self.sumRange(mid + 1, right)
# Your NumArray object will be instantiated and called as such:
# obj = NumArray(nums)
# param_1 = obj.sumRange(left,right)
4.7.1534 - 2023-09-12 14:07:17 +0300 MSK
Links
Code
class NumArray:
def __init__(self, nums: List[int]):
self._nums = nums
def sumRange(self, left: int, right: int) -> int:
return sum(self._nums[left:right+1])
# Your NumArray object will be instantiated and called as such:
# obj = NumArray(nums)
# param_1 = obj.sumRange(left,right)
4.7.1535 - 2023-09-12 14:05:44 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class BSTIterator:
def __init__(self, root: Optional[TreeNode]):
def generate(node: TreeNode) -> int:
if not node:
return
yield from generate(node.left)
yield node
yield from generate(node.right)
self._generate = generate(root)
self._next = next(self._generate)
def next(self) -> int:
next_val = self._next.val
self._next = next(self._generate, None)
return next_val
def hasNext(self) -> bool:
return self._next is not None
# Your BSTIterator object will be instantiated and called as such:
# obj = BSTIterator(root)
# param_1 = obj.next()
# param_2 = obj.hasNext()
4.7.1536 - 2023-09-12 14:05:12 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class BSTIterator:
def __init__(self, root: Optional[TreeNode]):
def generate(node: TreeNode) -> int:
if not node:
return
yield from generate(node.left)
yield node
yield from generate(node.right)
self._generate = generate(root)
self._next = next(self._generate)
def next(self) -> int:
next_val = self._next.val
self._next = next(self._generate, None)
return next_val
def hasNext(self) -> bool:
return not self._next is None
# Your BSTIterator object will be instantiated and called as such:
# obj = BSTIterator(root)
# param_1 = obj.next()
# param_2 = obj.hasNext()
4.7.1537 - 2023-09-12 14:01:45 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class BSTIterator:
def __init__(self, root: Optional[TreeNode]):
self._stack = []
while root:
self._stack.append(root)
root = root.left
def next(self) -> int:
node = self._stack.pop()
right = node.right
while right:
self._stack.append(right)
right = right.left
return node.val
def hasNext(self) -> bool:
return self._stack
# Your BSTIterator object will be instantiated and called as such:
# obj = BSTIterator(root)
# param_1 = obj.next()
# param_2 = obj.hasNext()
4.7.1538 - 2023-09-12 11:17:46 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def isBalanced(self, root: Optional[TreeNode]) -> bool:
def get_height(node: TreeNode) -> int:
if not node:
return 0
h_left = get_height(node.left)
if h_left < 0:
return -1
h_right = get_height(node.right)
if h_right < 0 or abs(h_left - h_right) > 1:
return -1
return max(h_left, h_right) + 1
return get_height(root) >= 0
4.7.1539 - 2023-09-12 10:55:04 +0300 MSK
Links
Code
class Solution:
def minDeletions(self, s: str) -> int:
length = len(s)
char_count = Counter(s)
counts = set()
deleted_chars = 0
for char, count in char_count.items():
while count != 0 and count in counts:
count -= 1
deleted_chars += 1
if count != 0:
counts.add(count)
return deleted_chars
4.7.1540 - 2023-09-11 19:32:16 +0300 MSK
Links
Code
class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> Optional[ListNode]:
if not headA or not headB:
return None
tail1, tail2 = headA, headB
while tail1 != tail2:
tail1 = tail1.next if tail1 else headB
tail2 = tail2.next if tail2 else headA
return tail2
4.7.1541 - 2023-09-11 19:31:11 +0300 MSK
Links
Code
class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> Optional[ListNode]:
if headA and headB:
A, B = headA, headB
while A != B:
A = A.next if A else headB
B = B.next if B else headA
return B
4.7.1542 - 2023-09-11 19:16:39 +0300 MSK
Links
Code
class Solution:
def getRow(self, rowIndex: int) -> List[int]:
prev_row = (1,)
for i in range(1, rowIndex + 1):
prev_row = (1, *(prev_row[j] + prev_row[j+1] for j in range(len(prev_row) - 1)), 1)
return prev_row
4.7.1543 - 2023-09-11 19:06:00 +0300 MSK
Links
Code
class Solution:
def singleNumber(self, nums: List[int]) -> int:
return reduce(xor, nums)
4.7.1544 - 2023-09-11 18:58:15 +0300 MSK
Links
Code
class Solution:
def singleNumber(self, nums: List[int]) -> int:
return reduce(lambda total, element: total ^ element, nums)
4.7.1545 - 2023-09-11 18:55:49 +0300 MSK
Links
Code
class Solution:
def singleNumber(self, nums: List[int]) -> int:
nums_count = len(nums)
if nums_count == 1:
return nums[0]
nums.sort()
for i in range(0, nums_count, 2):
if i + 1 == nums_count:
return nums[i]
cur_num, next_num = nums[i], nums[i+1]
if cur_num == next_num:
continue
return cur_num
return 0
4.7.1546 - 2023-09-11 18:46:11 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def minDepth(self, root: Optional[TreeNode]) -> int:
def dfs(node: TreeNode) -> int:
if not node:
return 0
return 1 + min((depth for depth in (dfs(node.left), dfs(node.right)) if depth > 0),
default=0)
return dfs(root)
4.7.1547 - 2023-09-11 18:31:16 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
def get_nodes(root: TreeNode) -> Generator[None, None, TreeNode]:
if not root:
return
yield from get_nodes(root.left)
yield root.val
yield from get_nodes(root.right)
return tuple(get_nodes(root))
4.7.1548 - 2023-09-11 18:30:56 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
def get_nodes(root: TreeNode) -> Generator[None, None, TreeNode]:
if not root:
return
if root.left:
yield from get_nodes(root.left)
yield root.val
if root.right:
yield from get_nodes(root.right)
return tuple(get_nodes(root))
4.7.1549 - 2023-09-11 15:06:55 +0300 MSK
Links
Code
class Solution:
def groupThePeople(self, groupSizes: List[int]) -> List[List[int]]:
answer = []
cur_groups = defaultdict(list)
for i in range(len(groupSizes)):
size = groupSizes[i]
group = cur_groups[size]
group.append(i)
if len(group) == size:
answer.append(group)
del cur_groups[size]
return answer
4.7.1550 - 2023-09-10 12:48:15 +0300 MSK
Links
Code
class Solution:
def countOrders(self, n: int) -> int:
# P1, D1 [01] -> (P1, D1)
# P1, D1, P2, D2 [06] -> (P1, P2, D1, D2), (P1, P2, D2, D1),
# (P1, D1, P2, D2), (P2, P1, D1, D2),
# (P2, P1, D2, D1), (P2, D2, P1, D1).
# P1, D1, P2, D2, P3, D3 [90]
ways_count = 1
mod = 10**9 + 7
for order in range(2, n + 1):
pos_avail_count = 1 + (order - 1) * 2
cur_ways_count = pos_avail_count * (pos_avail_count + 1) // 2
ways_count = (ways_count * cur_ways_count) % mod
return ways_count
4.7.1551 - 2023-09-10 12:37:39 +0300 MSK
Links
Code
class Solution:
def countOrders(self, n: int) -> int:
# P1, D1 [01] -> (P1, D1)
# P1, D1, P2, D2 [06] -> (P1, P2, D1, D2), (P1, P2, D2, D1),
# (P1, D1, P2, D2), (P2, P1, D1, D2),
# (P2, P1, D2, D1), (P2, D2, P1, D1).
# P1, D1, P2, D2, P3, D3 [90]
ways_count = 1
for order in range(2, n + 1):
avail_pos_count = 1 + (order - 1) * 2
ways_count *= sum(avail_pos_count - pos for pos in range(avail_pos_count))
return ways_count % (10**9 + 7)
4.7.1552 - 2023-09-09 20:12:03 +0300 MSK
Links
Code
class Solution:
def numDecodings(self, s: str) -> int:
char_count = len(s)
@cache
def dfs(i: int) -> int:
if i == char_count:
return 1
if s[i] == "0":
return 0
return dfs(i + 1) + (
dfs(i + 2) if i + 1 < char_count and s[i:i+2] < "27" else 0
)
return dfs(0)
4.7.1553 - 2023-09-09 20:11:23 +0300 MSK
Links
Code
class Solution:
def numDecodings(self, s: str) -> int:
char_count = len(s)
@cache
def dfs(i: int) -> int:
if i == char_count:
return 1
if s[i] == "0":
return 0
return dfs(i + 1) + (dfs(i + 2) if i + 1 < char_count and s[i:i+2] < "27" else 0)
return dfs(0)
4.7.1554 - 2023-09-09 20:10:19 +0300 MSK
Links
Code
class Solution:
def numDecodings(self, s: str) -> int:
char_count = len(s)
@cache
def dfs(i: int) -> int:
if i == char_count:
return 1
if s[i] == "0":
return 0
ways_count = dfs(i + 1)
if i + 1 < char_count and s[i:i+2] < "27":
ways_count += dfs(i + 2)
return ways_count
return dfs(0)
4.7.1555 - 2023-09-09 16:06:56 +0300 MSK
Links
Code
class Solution:
def snakesAndLadders(self, board: List[List[int]]) -> int:
n = len(board)
board.reverse()
def intToPos(square):
r = (square - 1) // n
c = (square - 1) % n
if r % 2:
c = n - 1 - c
return [r, c]
q = deque()
q.append([1, 0])
visit = set()
while q:
square, moves = q.popleft()
for i in range(1, 7):
nextSquare = square + i
r, c = intToPos(nextSquare)
if board[r][c] != -1:
nextSquare = board[r][c]
if nextSquare == n * n:
return moves + 1
if nextSquare not in visit:
visit.add(nextSquare)
q.append([nextSquare, moves + 1])
return -1
4.7.1556 - 2023-09-09 10:20:58 +0300 MSK
Links
Code
class Solution:
def combinationSum4(self, nums: List[int], target: int) -> int:
@cache
def dp(cur_sum: int) -> int:
if cur_sum == target:
return 1
if cur_sum > target:
return 0
return sum(dp(cur_sum + num) for num in nums)
return dp(0)
4.7.1557 - 2023-09-09 10:20:26 +0300 MSK
Links
Code
class Solution:
def combinationSum4(self, nums: List[int], target: int) -> int:
@cache
def backtrack(cur_sum: int) -> int:
if cur_sum == target:
return 1
if cur_sum > target:
return 0
return sum(backtrack(cur_sum + num) for num in nums)
return backtrack(0)
4.7.1558 - 2023-09-08 13:41:10 +0300 MSK
Links
Code
class Solution:
def generate(self, numRows: int) -> List[List[int]]:
answer = [[1]]
numRows -= 1
while numRows > 0:
cur, prev = [1], answer[-1]
for i in range(len(prev) - 1):
cur.append(prev[i] + prev[i+1])
cur.append(1)
answer.append(cur)
numRows -= 1
return answer
4.7.1559 - 2023-09-07 20:09:04 +0300 MSK
Links
Code
class Solution:
def exist(self, board: List[List[str]], word: str) -> bool:
row_count, col_count = len(board), len(board[0])
word_length = len(word)
delta = ((0, 1), (0, -1), (1, 0), (-1, 0))
if word_length == 1:
return any(word in row for row in board)
if word_length > row_count * col_count:
return False
visited = set()
def backtrack(row: int, col: int, target: int) -> bool:
if target == word_length:
return True
if not 0 <= row < row_count or not 0 <= col < col_count or (
(row, col) in visited or board[row][col] != word[target]
):
return False
visited.add((row, col))
answer = any(backtrack(row + delta_row, col + delta_col, target + 1)
for delta_row, delta_col in delta)
visited.remove((row, col))
return answer
return any(backtrack(row, col, 0)
for row in range(row_count)
for col in range(col_count))
4.7.1560 - 2023-09-07 20:00:09 +0300 MSK
Links
Code
class Solution:
def exist(self, board: List[List[str]], word: str) -> bool:
row_count, col_count = len(board), len(board[0])
word_length = len(word)
delta = ((0, 1), (0, -1), (1, 0), (-1, 0))
if word_length == 1:
return any(word in row for row in board)
def backtrack(row: int, col: int, visited: Set, target: int) -> bool:
if (row, col) in visited or not 0 <= row < row_count or not 0 <= col < col_count:
return False
if board[row][col] != word[target]:
return False
if target == word_length - 1:
return True
visited.add((row, col))
if any(backtrack(row + delta_row, col + delta_col, visited, target + 1)
for delta_row, delta_col in delta):
return True
visited.remove((row, col))
return False
start_char = word[0]
return any(backtrack(row, col, set(), 0)
for row in range(row_count)
for col in range(col_count)
if board[row][col] == start_char)
4.7.1561 - 2023-09-07 19:55:32 +0300 MSK
Links
Code
class Solution:
def exist(self, board: List[List[str]], word: str) -> bool:
row_count, col_count = len(board), len(board[0])
word_length = len(word)
delta = ((0, 1), (0, -1), (1, 0), (-1, 0))
if word_length == 1:
return any(word in row for row in board)
def backtrack(row: int, col: int, visited: Set, target: int) -> bool:
if (row, col) in visited or not 0 <= row < row_count or not 0 <= col < col_count:
return False
if board[row][col] != word[target]:
return False
if target == word_length - 1:
return True
visited.add((row, col))
if any(backtrack(row + delta_row, col + delta_col, visited, target + 1)
for delta_row, delta_col in delta):
return True
visited.remove((row, col))
return False
for row in range(row_count):
for col in range(col_count):
if backtrack(row, col, set(), 0):
return True
return False
4.7.1562 - 2023-09-07 17:13:51 +0300 MSK
Links
Code
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reverseBetween(self, head: Optional[ListNode], left: int, right: int) -> Optional[ListNode]:
cur_node = 1
left_head, left_tail = head if left > 1 else None, None
while cur_node < left:
cur_node += 1
head, left_tail = head.next, head
cur_node += 1
mid_head, mid_tail, head = head, head, head.next
mid_head.next = None
while cur_node <= right:
cur_node += 1
mid_head, head.next, head = head, mid_head, head.next
mid_tail.next = head
if left_head:
left_tail.next = mid_head
else:
left_head = mid_head
return left_head
4.7.1563 - 2023-09-07 17:13:34 +0300 MSK
Links
Code
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reverseBetween(self, head: Optional[ListNode], left: int, right: int) -> Optional[ListNode]:
cur_node = 1
left_head, left_tail = head if left > 1 else None, None
while cur_node < left:
cur_node += 1
head, left_tail = head.next, head
cur_node += 1
mid_head, mid_tail, head = head, head, head.next
mid_head.next = None
while cur_node <= right:
cur_node += 1
next_node = head.next
mid_head, head.next = head, mid_head
head = next_node
mid_tail.next = head
if left_head:
left_tail.next = mid_head
else:
left_head = mid_head
return left_head
4.7.1564 - 2023-09-07 17:12:50 +0300 MSK
Links
Code
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reverseBetween(self, head: Optional[ListNode], left: int, right: int) -> Optional[ListNode]:
cur_node = 1
left_head, left_tail = head if left > 1 else None, None
while cur_node < left:
cur_node += 1
head, left_tail = head.next, head
cur_node += 1
mid_head, mid_tail, head = head, head, head.next
mid_head.next = None
while cur_node <= right:
cur_node += 1
next_node = head.next
head.next = mid_head
mid_head = head
head = next_node
mid_tail.next = head
if left_head:
left_tail.next = mid_head
else:
left_head = mid_head
return left_head
4.7.1565 - 2023-09-06 14:59:03 +0300 MSK
Links
Code
class Solution:
def splitListToParts(self, head: Optional[ListNode], k: int) -> List[Optional[ListNode]]:
nodes_count = 0
tail = head
while tail:
tail = tail.next
nodes_count += 1
quotient, remainder = divmod(nodes_count, k)
answer = []
for i in range(k):
size = quotient + 1 if (remainder := remainder - 1) >= 0 else quotient
answer.append(head)
last = None
while size > 0:
last = head
head = head.next
size -= 1
if last:
last.next = None
return answer
4.7.1566 - 2023-09-05 11:41:23 +0300 MSK
Links
Code
"""
# Definition for a Node.
class Node:
def __init__(self, x: int, next: 'Node' = None, random: 'Node' = None):
self.val = int(x)
self.next = next
self.random = random
"""
class Solution:
def copyRandomList(self, head: 'Optional[Node]') -> 'Optional[Node]':
copied = {None: None}
def copy_node(node: Node) -> Node:
if node in copied:
return copied[node]
new_node = Node(node.val)
copied[node] = new_node
new_node.next = copy_node(node.next)
new_node.random = copy_node(node.random)
return new_node
return copy_node(head)
4.7.1567 - 2023-09-04 15:54:45 +0300 MSK
Links
Code
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
result = set()
cur_nums = []
def backtrack(cur_sum: int) -> None:
if cur_sum == target:
result.add(tuple(sorted(cur_nums[:])))
if cur_sum >= target:
return
for num in candidates:
cur_nums.append(num)
backtrack(num + cur_sum)
cur_nums.pop()
backtrack(0)
return result
4.7.1568 - 2023-09-04 12:44:01 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def sortedArrayToBST(self, nums: List[int]) -> Optional[TreeNode]:
nums_count = len(nums)
if nums_count == 0:
return None
mid = nums_count // 2
return TreeNode(nums[mid],
self.sortedArrayToBST(nums[:mid]),
self.sortedArrayToBST(nums[mid+1:]))
4.7.1569 - 2023-09-04 09:37:09 +0300 MSK
Links
Code
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def hasCycle(self, head: Optional[ListNode]) -> bool:
slow_p, fast_p = head, head.next if head else None
while fast_p and fast_p.next:
if slow_p == fast_p:
return True
slow_p, fast_p = slow_p.next, fast_p.next.next
return False
4.7.1570 - 2023-09-03 20:06:29 +0300 MSK
Links
Code
class Solution:
def gameOfLife(self, board: List[List[int]]) -> None:
"""
Do not return anything, modify board in-place instead.
"""
rows_count, cols_count = len(board), len(board[0])
moves = ((0, 1), (0, -1), (1, 0), (-1, 0), (1, 1), (1, -1), (-1, 1), (-1, -1))
flip_cells = set()
for row in range(rows_count):
for col in range(cols_count):
live_neighbors = 0
is_alive = board[row][col] == 1
for row_delta, col_delta in moves:
new_row, new_col = row + row_delta, col + col_delta
if not 0 <= new_row < rows_count or not 0 <= new_col < cols_count:
continue
if board[new_row][new_col] == 1:
live_neighbors += 1
if (is_alive and (live_neighbors < 2 or live_neighbors > 3)) or (
not is_alive and live_neighbors == 3
):
flip_cells.add((row, col))
while flip_cells:
row, col = flip_cells.pop()
board[row][col] = 0 if board[row][col] == 1 else 1
4.7.1571 - 2023-09-03 19:49:38 +0300 MSK
Links
Code
class Solution:
def setZeroes(self, matrix: List[List[int]]) -> None:
"""
Do not return anything, modify matrix in-place instead.
"""
rows_count, cols_count = len(matrix), len(matrix[0])
flip_rows, flip_cols = set(), set()
for row in range(rows_count):
for col in range(cols_count):
if matrix[row][col] == 0:
flip_rows.add(row)
flip_cols.add(col)
while flip_rows:
row = flip_rows.pop()
for col in range(cols_count):
if matrix[row][col] != 0:
matrix[row][col] = 0
while flip_cols:
col = flip_cols.pop()
for row in range(rows_count):
if matrix[row][col] != 0:
matrix[row][col] = 0
4.7.1572 - 2023-09-03 11:23:58 +0300 MSK
Links
Code
class Solution:
def uniquePaths(self, m: int, n: int) -> int:
@cache
def dp(row: int, col: int) -> int:
if not 0 <= row < m or not 0 <= col < n:
return 0
if row == m - 1 and col == n - 1:
return 1
return dp(row + 1, col) + dp(row, col + 1)
return dp(0, 0)
4.7.1573 - 2023-09-02 16:26:14 +0300 MSK
Links
Code
class Solution:
def rotate(self, matrix: List[List[int]]) -> None:
"""
Do not return anything, modify matrix in-place instead.
"""
side_length = len(matrix)
for row in range(side_length // 2):
matrix[row], matrix[-row-1] = matrix[-row-1], matrix[row]
for i in range(side_length):
for j in range(i):
matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]
4.7.1574 - 2023-09-02 10:50:42 +0300 MSK
Links
Code
class Solution:
def minExtraChar(self, s: str, dictionary: List[str]) -> int:
chars_count = len(s)
@cache
def dp(i: int) -> int:
chars_left = chars_count - i
if chars_left == 0:
return 0
min_extra_chars = chars_left
for word in dictionary:
word_length = len(word)
if word_length > chars_left or s[i:i+word_length] != word:
continue
if word_length == chars_left:
return 0
min_extra_chars = min(min_extra_chars, dp(i + word_length))
return min(min_extra_chars, 1 + dp(i + 1))
return dp(0)
4.7.1575 - 2023-09-01 18:41:17 +0300 MSK
Links
Code
class Solution:
def fullJustify(self, words: List[str], maxWidth: int) -> List[str]:
words_count = len(words)
def get_line(word_idx: int) -> Tuple[List[str], int]:
line = []
line_length = 0
for i in range(word_idx, words_count):
word = words[i]
word_length = len(word)
if line_length + word_length > maxWidth:
break
line.append(word)
line_length += word_length + 1
return line, line_length
def create_line(line: List[str], line_length: int, word_idx: int) -> str:
base_length = line_length - 1
extra_spaces = maxWidth - base_length
if len(line) == 1 or word_idx == words_count:
return " ".join(line) + " " * extra_spaces
word_count = len(line) - 1
spaces_per_word = extra_spaces // word_count
needs_extra_space = extra_spaces % word_count
for j in range(needs_extra_space):
line[j] += " "
for j in range(word_count):
line[j] += " " * spaces_per_word
return " ".join(line)
result = []
i = 0
while i < words_count:
line, line_length = get_line(i)
i += len(line)
result.append(create_line(line, line_length, i))
return result
4.7.1576 - 2023-09-01 18:38:28 +0300 MSK
Links
Code
class Solution:
def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
nodes = [[] for _ in range(numCourses)]
for target, required in prerequisites:
nodes[target].append(required)
visited = set()
@cache
def dfs(course: int) -> bool:
if course in visited:
return False
edges = nodes[course]
if not edges:
return True
visited.add(course)
return all(dfs(edge) for edge in edges)
for course in range(numCourses):
if not dfs(course):
return False
visited.clear()
return True
4.7.1577 - 2023-09-01 18:37:48 +0300 MSK
Links
Code
class Solution:
def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
nodes = [[] for _ in range(numCourses)]
for target, required in prerequisites:
nodes[target].append(required)
visited = set()
@cache
def dfs(course: int) -> bool:
if course in visited:
return False
edges = nodes[course]
if not edges:
return True
visited.add(course)
return all(dfs(edge) for edge in edges)
for course in range(numCourses):
if not dfs(course):
return False
visited.clear()
return True
4.7.1578 - 2023-09-01 09:58:21 +0300 MSK
Links
Code
class Solution:
def countBits(self, n: int) -> List[int]:
ans = [0] * (n + 1)
for i in range(1, n + 1):
ans[i] = ans[i >> 1] + (i & 1)
return ans
4.7.1579 - 2023-09-01 09:55:13 +0300 MSK
Links
Code
class Solution:
def countBits(self, n: int) -> List[int]:
return tuple(bin(i).count("1") for i in range(n + 1))
4.7.1580 - 2023-08-31 22:14:58 +0300 MSK
Links
Code
class Solution:
def calcEquation(self, equations: List[List[str]], values: List[float], queries: List[List[str]]) -> List[float]:
equations_count = len(equations)
queries_count = len(queries)
edges = defaultdict(dict)
seen_nodes = set()
invalid = -1.0
def dfs(val1: str, val2: str) -> float:
if val1 == val2:
return 1.0
if val2 in edges[val1]:
return edges[val1][val2]
if val1 in seen_nodes:
return invalid
seen_nodes.add(val1)
for connected_node in edges[val1]:
new_edge_res = dfs(connected_node, val2)
if new_edge_res == invalid:
continue
new_edge_res *= edges[val1][connected_node]
edges[val1][val2] = new_edge_res
return new_edge_res
return invalid
for i in range(equations_count):
(val1, val2), res = equations[i], values[i]
edges[val1][val2], edges[val2][val1] = res, 1 / res
for i in range(queries_count):
res, (val1, val2) = -1, queries[i]
if val1 in edges and val2 in edges:
seen_nodes.clear()
res = dfs(val1, val2)
queries[i] = res
return queries
4.7.1581 - 2023-08-31 20:45:02 +0300 MSK
Links
Code
"""
# Definition for a Node.
class Node:
def __init__(self, val = 0, neighbors = None):
self.val = val
self.neighbors = neighbors if neighbors is not None else []
"""
class Solution:
def cloneGraph(self, node: 'Node') -> 'Node':
old_to_new = {}
def clone(node: Node) -> Node:
if node in old_to_new:
return old_to_new[node]
new_node = Node(node.val)
old_to_new[node] = new_node
new_node.neighbors = [clone(neighbor) for neighbor in node.neighbors]
return new_node
return clone(node) if node else node
4.7.1582 - 2023-08-31 20:35:52 +0300 MSK
Links
Code
class Solution:
def solve(self, board: List[List[str]]) -> None:
"""
Do not return anything, modify board in-place instead.
"""
row_count, col_count = len(board), len(board[0])
moves = ((0, 1), (0, -1), (1, 0), (-1, 0))
ignore_cells = set()
def bfs(row: int, col: int) -> None:
if not 0 <= row < row_count or not 0 <= col < col_count:
return
if (row, col) in ignore_cells or board[row][col] == "X":
return
ignore_cells.add((row, col))
for row_delta, col_delta in moves:
bfs(row + row_delta, col + col_delta)
for row, col in itertools.chain(
((0, col) for col in range(col_count)),
((row_count - 1, col) for col in range(col_count)),
((row, 0) for row in range(row_count)),
((row, col_count - 1) for row in range(row_count))
):
bfs(row, col)
for row in range(1, row_count - 1):
for col in range(1, col_count - 1):
if (row, col) in ignore_cells:
continue
board[row][col] = "X"
4.7.1583 - 2023-08-31 20:35:00 +0300 MSK
Links
Code
class Solution:
def solve(self, board: List[List[str]]) -> None:
"""
Do not return anything, modify board in-place instead.
"""
row_count, col_count = len(board), len(board[0])
moves = ((0, 1), (0, -1), (1, 0), (-1, 0))
ignore_stack = set()
def bfs(row: int, col: int) -> None:
if not 0 <= row < row_count or not 0 <= col < col_count:
return
if (row, col) in ignore_stack or board[row][col] == "X":
return
ignore_stack.add((row, col))
for row_delta, col_delta in moves:
bfs(row + row_delta, col + col_delta)
for row, col in itertools.chain(
((0, col) for col in range(col_count)),
((row_count - 1, col) for col in range(col_count)),
((row, 0) for row in range(row_count)),
((row, col_count - 1) for row in range(row_count))
):
bfs(row, col)
flip_x = True
for row in range(1, row_count - 1):
for col in range(1, col_count - 1):
if (row, col) in ignore_stack:
continue
board[row][col] = "X"
4.7.1584 - 2023-08-31 20:34:31 +0300 MSK
Links
Code
class Solution:
def solve(self, board: List[List[str]]) -> None:
"""
Do not return anything, modify board in-place instead.
"""
row_count, col_count = len(board), len(board[0])
moves = ((0, 1), (0, -1), (1, 0), (-1, 0))
ignore_stack = set()
@cache
def bfs(row: int, col: int) -> None:
if not 0 <= row < row_count or not 0 <= col < col_count:
return
if (row, col) in ignore_stack or board[row][col] == "X":
return
ignore_stack.add((row, col))
for row_delta, col_delta in moves:
bfs(row + row_delta, col + col_delta)
for row, col in itertools.chain(
((0, col) for col in range(col_count)),
((row_count - 1, col) for col in range(col_count)),
((row, 0) for row in range(row_count)),
((row, col_count - 1) for row in range(row_count))
):
bfs(row, col)
flip_x = True
for row in range(1, row_count - 1):
for col in range(1, col_count - 1):
if (row, col) in ignore_stack:
continue
board[row][col] = "X"
4.7.1585 - 2023-08-31 15:29:43 +0300 MSK
Links
Code
class Solution:
def minTaps(self, n: int, ranges: List[int]) -> int:
inf = float("inf")
dp = [inf] * (n + 1)
dp[0] = 0
for i in range(n + 1):
cur_range = ranges[i]
tap_start, tap_end = max(0, i - cur_range), min(n, i + cur_range)
for j in range(tap_start, tap_end + 1):
dp[tap_end] = min(dp[tap_end], dp[j] + 1)
min_taps = dp[n]
return -1 if min_taps == inf else min_taps
4.7.1586 - 2023-08-31 12:14:40 +0300 MSK
Links
Code
class Solution:
def minTaps(self, n: int, ranges: List[int]) -> int:
arr = [0] * (n + 1)
for i, r in enumerate(ranges):
if r == 0:
continue
left = max(0, i - r)
arr[left] = max(arr[left], i + r)
end, far_can_reach, cnt = 0, 0, 0
for i, reach in enumerate(arr):
if i > end:
if far_can_reach <= end:
return -1
end, cnt = far_can_reach, cnt + 1
far_can_reach = max(far_can_reach, reach)
return cnt + (end < n)
4.7.1587 - 2023-08-30 19:06:25 +0300 MSK
Links
Code
class Solution:
def minimumReplacement(self, nums: List[int]) -> int:
nums_count = len(nums)
operations_count = 0
for i in reversed(range(nums_count - 1)):
cur, prev = nums[i], nums[i+1]
if cur <= prev:
continue
elements_count = (cur + prev - 1) // prev
operations_count += elements_count - 1
nums[i] //= elements_count
return operations_count
4.7.1588 - 2023-08-29 19:00:49 +0300 MSK
Links
Code
class Solution:
def numIslands(self, grid: List[List[str]]) -> int:
row_count, col_count = len(grid), len(grid[0])
island_count = 0
moves = ((0, 1), (0, -1), (1, 0), (-1, 0))
@cache
def dfs(row: int, col: int) -> None:
if not 0 <= row < row_count or not 0 <= col < col_count or grid[row][col] == "0":
return
grid[row][col] = "0"
for row_delta, col_delta in moves:
dfs(row + row_delta, col + col_delta)
for row in range(row_count):
for col in range(col_count):
if grid[row][col] == "0":
continue
dfs(row, col)
island_count += 1
return island_count
4.7.1589 - 2023-08-29 18:48:22 +0300 MSK
Links
Code
class Solution:
def numIslands(self, grid: List[List[str]]) -> int:
row_count, col_count = len(grid), len(grid[0])
island_count = 0
moves = ((0, 1), (0, -1), (1, 0), (-1, 0))
queue = set((row, col)
for row in range(row_count)
for col in range(col_count)
if grid[row][col] == "1")
@cache
def remove_island(row: int, col: int) -> None:
if not 0 <= row < row_count or not 0 <= col < col_count:
return
for row_delta, col_delta in moves:
new_cell = (row + row_delta, col + col_delta)
if new_cell in queue:
queue.remove(new_cell)
remove_island(*new_cell)
while queue:
remove_island(*queue.pop())
island_count += 1
return island_count
4.7.1590 - 2023-08-29 18:48:09 +0300 MSK
Links
Code
class Solution:
def numIslands(self, grid: List[List[str]]) -> int:
row_count, col_count = len(grid), len(grid[0])
island_count = 0
moves = ((0, 1), (0, -1), (1, 0), (-1, 0))
queue = set((row, col)
for row in range(row_count)
for col in range(col_count)
if grid[row][col] == "1")
@cache
def remove_island(row: int, col: int) -> None:
if not 0 <= row < row_count or not 0 <= col < col_count:
return
for row_delta, col_delta in moves:
new_cell = (row + row_delta, col + col_delta)
if new_cell in queue:
queue.remove(new_cell)
remove_island(*new_cell)
while queue:
remove_island(*queue.pop())
island_count += 1
return island_count
4.7.1591 - 2023-08-29 18:44:17 +0300 MSK
Links
Code
class Solution:
def numIslands(self, grid: List[List[str]]) -> int:
row_count, col_count = len(grid), len(grid[0])
island_count = 0
moves = ((0, 1), (0, -1), (1, 0), (-1, 0))
queue = set((row, col)
for row in range(row_count)
for col in range(col_count)
if grid[row][col] == "1")
def remove_island(row: int, col: int) -> None:
if not 0 <= row < row_count or not 0 <= col < col_count or (row, col) not in queue:
return
queue.remove((row, col))
for row_delta, col_delta in moves:
remove_island(row + row_delta, col + col_delta)
while queue:
remove_island(*next(iter(queue)))
island_count += 1
return island_count
4.7.1592 - 2023-08-29 18:43:22 +0300 MSK
Links
Code
class Solution:
def numIslands(self, grid: List[List[str]]) -> int:
row_count, col_count = len(grid), len(grid[0])
island_count = 0
moves = ((0, 1), (0, -1), (1, 0), (-1, 0))
queue = set((row, col)
for row in range(row_count)
for col in range(col_count)
if grid[row][col] == "1")
@cache
def remove_island(row: int, col: int) -> None:
if not 0 <= row < row_count or not 0 <= col < col_count or (row, col) not in queue:
return
queue.remove((row, col))
for row_delta, col_delta in moves:
remove_island(row + row_delta, col + col_delta)
while queue:
remove_island(*next(iter(queue)))
island_count += 1
return island_count
4.7.1593 - 2023-08-29 11:50:54 +0300 MSK
Links
Code
class Solution:
def bestClosingTime(self, customers: str) -> int:
# Start with closing at hour 0, the penalty equals all 'Y' in closed hours.
cur_penalty = min_penalty = customers.count("Y")
earliest_hour = 0
for hour, customer in enumerate(customers):
# If status in hour i is 'Y', moving it to open hours decrement
# penalty by 1. Otherwise, moving 'N' to open hours increment
# penatly by 1.
cur_penalty += 1 if customer == "N" else -1
# Update earliest_hour if a smaller penatly is encountered
if cur_penalty < min_penalty:
earliest_hour = hour + 1
min_penalty = cur_penalty
return earliest_hour
4.7.1594 - 2023-08-28 13:37:58 +0300 MSK
Links
Code
class MapSum:
def __init__(self):
self._map = {}
def insert(self, key: str, val: int) -> None:
self._map[key] = val
def sum(self, prefix: str) -> int:
return sum(value for key, value in self._map.items() if key.startswith(prefix))
# Your MapSum object will be instantiated and called as such:
# obj = MapSum()
# obj.insert(key,val)
# param_2 = obj.sum(prefix)
4.7.1595 - 2023-08-28 13:35:54 +0300 MSK
Links
Code
class MyStack:
def __init__(self):
self._queue = []
def push(self, x: int) -> None:
self._queue.append(x)
def pop(self) -> int:
return self._queue.pop()
def top(self) -> int:
return self._queue[-1]
def empty(self) -> bool:
return len(self._queue) == 0
# Your MyStack object will be instantiated and called as such:
# obj = MyStack()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.top()
# param_4 = obj.empty()
4.7.1596 - 2023-08-27 18:09:36 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def getMinimumDifference(self, root: Optional[TreeNode]) -> int:
def min_node_diff(node: TreeNode, low: int, high: int) -> int:
if not node:
return high - low
return min(min_node_diff(node.left, low, node.val),
min_node_diff(node.right, node.val, high))
return min_node_diff(root, -maxsize, maxsize)
4.7.1597 - 2023-08-27 18:03:23 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def getMinimumDifference(self, root: Optional[TreeNode]) -> int:
values = []
def fall(node: TreeNode) -> None:
if not node:
return
values.append(node.val)
if node.left:
fall(node.left)
if node.right:
fall(node.right)
fall(root)
values.sort()
min_diff = abs(values[1] - values[0])
for i in range(1, len(values) - 1):
min_diff = min(min_diff, abs(values[i] - values[i+1]))
return min_diff
4.7.1598 - 2023-08-27 17:55:09 +0300 MSK
Links
Code
class Solution:
def canCross(self, stones: List[int]) -> bool:
m = set(stones)
@cache
def dfs(i, j):
if i == stones[-1]: return True
return any(x and x + i in m and dfs(x + i, x) for x in range(j - 1, j + 2))
return dfs(0, 0)
4.7.1599 - 2023-08-26 16:17:44 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def countNodes(self, root: Optional[TreeNode]) -> int:
def left_height(root: TreeNode) -> int:
return 0 if not root else 1 + left_height(root.left)
def right_height(root: TreeNode) -> int:
return 0 if not root else 1 + right_height(root.right)
left, right = left_height(root), right_height(root)
if left > right:
return 1 + self.countNodes(root.left) + self.countNodes(root.right)
return 2**left - 1
4.7.1600 - 2023-08-26 16:17:28 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def countNodes(self, root: Optional[TreeNode]) -> int:
def left_height(root: TreeNode) -> int:
return 0 if not root else 1 + left_height(root.left)
def right_height(root: TreeNode) -> int:
return 0 if not root else 1+ right_height(root.right)
left, right = left_height(root), right_height(root)
if left > right:
return 1 + self.countNodes(root.left) + self.countNodes(root.right)
return 2**left - 1
4.7.1601 - 2023-08-26 16:16:46 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def countNodes(self, root: Optional[TreeNode]) -> int:
if not root:
return 0
def left_height(root: TreeNode) -> int:
return 0 if not root else 1 + left_height(root.left)
def right_height(root: TreeNode) -> int:
return 0 if not root else 1+ right_height(root.right)
left, right = left_height(root), right_height(root)
if left > right:
return 1 + self.countNodes(root.left) + self.countNodes(root.right)
return 2**left - 1
4.7.1602 - 2023-08-26 16:06:04 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
node_stack = [(root, 0)]
while node_stack:
node, curr_sum = node_stack.pop()
if not node:
continue
new_sum = curr_sum + node.val
if new_sum == targetSum and not node.left and not node.right:
return True
node_stack.extend(((node.left, new_sum), (node.right, new_sum)))
return False
4.7.1603 - 2023-08-26 15:38:12 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def isSymmetric(self, root: Optional[TreeNode]) -> bool:
comparison_stack = [(root.left, root.right)]
while comparison_stack:
left, right = comparison_stack.pop()
if not left and not right:
continue
if not left or not right or left.val != right.val:
return False
comparison_stack.extend(((left.left, right.right), (left.right, right.left)))
return True
4.7.1604 - 2023-08-26 15:24:31 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def isSymmetric(self, root: Optional[TreeNode]) -> bool:
return self.check(root.left, root.right)
def check(self, left: TreeNode, right: TreeNode) -> bool:
if not left and not right:
return True
if not left or not right or left.val != right.val:
return False
return self.check(left.left, right.right) and self.check(left.right, right.left)
4.7.1605 - 2023-08-26 15:20:18 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
if root:
root.left, root.right = self.invertTree(root.right), self.invertTree(root.left)
return root
4.7.1606 - 2023-08-26 15:20:08 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
if root:
root.left, root.right = self.invertTree(root.right), self.invertTree(root.left)
return root
4.7.1607 - 2023-08-26 15:19:33 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
if not root:
return None
root.left, root.right = self.invertTree(root.right), self.invertTree(root.left)
return root
4.7.1608 - 2023-08-26 15:18:57 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
if not root:
return None
self.invertTree(root.left)
self.invertTree(root.right)
root.left, root.right = root.right, root.left
return root
4.7.1609 - 2023-08-26 12:16:27 +0300 MSK
Links
Code
class Solution:
def findLongestChain(self, pairs: List[List[int]]) -> int:
pairs_count = len(pairs)
if pairs_count < 2:
return pairs_count
pairs.sort()
@cache
def dp(curr_pair: int) -> int:
right = pairs[curr_pair][1]
max_length = 1
for new_pair in range(curr_pair + 1, pairs_count):
new_left = pairs[new_pair][0]
new_length = dp(new_pair) + (1 if new_left > right else 0)
if new_length > max_length:
max_length = new_length
return max_length
return dp(0)
4.7.1610 - 2023-08-25 10:04:50 +0300 MSK
Links
Code
class Solution:
def isInterleave(self, s1: str, s2: str, s3: str) -> bool:
length_1, length_2, length_3 = len(s1), len(s2), len(s3)
if length_1 + length_2 != length_3:
return False
@cache
def dp(i_1: int, i_2: int, i_3: int) -> bool:
if i_3 == length_3:
return True
target = s3[i_3]
return (
i_1 != length_1 and s1[i_1] == target and dp(i_1 + 1, i_2, i_3 + 1)
) or (
i_2 != length_2 and s2[i_2] == target and dp(i_1, i_2 + 1, i_3 + 1)
)
return dp(0, 0, 0)
4.7.1611 - 2023-08-24 16:42:07 +0300 MSK
Links
Code
class Solution:
def kSmallestPairs(self, nums1: List[int], nums2: List[int], k: int) -> List[List[int]]:
nums1_count, nums2_count = len(nums1), len(nums2)
result = []
visited = set(((0, 0)))
min_heap = [(nums1[0] + nums2[0], (0, 0))]
count = 0
while k > 0 and min_heap:
_, (i, j) = heappop(min_heap)
new_i, new_j = i + 1, j + 1
new_pair1, new_pair2 = (new_i, j), (i, new_j)
num1, num2 = nums1[i], nums2[j]
result.append((num1, num2))
if new_i < nums1_count and new_pair1 not in visited:
heappush(min_heap, (nums1[new_i] + num2, new_pair1))
visited.add(new_pair1)
if new_j < nums2_count and new_pair2 not in visited:
heappush(min_heap, (num1 + nums2[new_j], new_pair2))
visited.add(new_pair2)
k -= 1
return result
4.7.1612 - 2023-08-24 13:45:42 +0300 MSK
Links
Code
class Solution:
def fullJustify(self, words: List[str], maxWidth: int) -> List[str]:
words_count = len(words)
def get_line(word_idx: int) -> Tuple[List[str], int]:
line = []
line_length = 0
for i in range(word_idx, words_count):
word = words[i]
word_length = len(word)
if line_length + word_length > maxWidth:
break
line.append(word)
line_length += word_length + 1
return line, line_length
def create_line(line: List[str], line_length: int, word_idx: int) -> str:
base_length = line_length - 1
extra_spaces = maxWidth - base_length
if len(line) == 1 or word_idx == words_count:
return " ".join(line) + " " * extra_spaces
word_count = len(line) - 1
spaces_per_word = extra_spaces // word_count
needs_extra_space = extra_spaces % word_count
for j in range(needs_extra_space):
line[j] += " "
for j in range(word_count):
line[j] += " " * spaces_per_word
return " ".join(line)
result = []
i = 0
while i < words_count:
line, line_length = get_line(i)
i += len(line)
result.append(create_line(line, line_length, i))
return result
4.7.1613 - 2023-08-23 22:56:37 +0300 MSK
Links
Code
class Solution:
def summaryRanges(self, nums: List[int]) -> List[str]:
nums_count = len(nums)
if nums_count == 0:
return []
if nums_count == 1:
return [str(nums[0])]
ranges = [[nums[0]] * 2]
for i, num in enumerate(nums[1:]):
if ranges[-1][1] == num - 1:
ranges[-1][1] = num
else:
ranges.append([num, num])
return [f"{start}->{end}" if start != end else str(start) for start, end in ranges]
4.7.1614 - 2023-08-23 12:45:05 +0300 MSK
Links
Code
class Solution:
def reorganizeString(self, s: str) -> str:
result = []
# Min heap ordered by character counts, so we will use
# negative values for count
priority_queue = [(-count, char) for char, count in Counter(s).items()]
heapify(priority_queue)
while priority_queue:
count_first, char_first = heappop(priority_queue)
if not result or char_first != result[-1]:
result.append(char_first)
if count_first != -1:
heappush(priority_queue, (count_first + 1, char_first))
continue
if not priority_queue:
return ""
count_second, char_second = heappop(priority_queue)
result.append(char_second)
if count_second != -1:
heappush(priority_queue, (count_second + 1, char_second))
heappush(priority_queue, (count_first, char_first))
return "".join(result)
4.7.1615 - 2023-08-22 10:32:27 +0300 MSK
Links
Code
class Solution:
def convertToTitle(self, columnNumber: int) -> str:
result = []
while columnNumber:
columnNumber, remainder = divmod(columnNumber - 1, 26)
result.append(chr(65 + remainder))
return ''.join(reversed(result))
4.7.1616 - 2023-08-21 23:38:46 +0300 MSK
Links
Code
class Solution:
def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
row_count, col_count = len(matrix), len(matrix[0])
if row_count == 1:
return matrix[0]
if col_count == 1:
return [row[0] for row in matrix]
result = []
top, bot, left, right = 0, row_count - 1, 0, col_count - 1
capacity = row_count * col_count
while len(result) < capacity:
for col in range(left, right + 1):
result.append(matrix[top][col])
top += 1
for row in range(top, bot + 1):
result.append(matrix[row][right])
right -= 1
if top <= bot:
for col in range(right, left - 1, -1):
result.append(matrix[bot][col])
bot -= 1
if left <= right:
for row in range(bot, top - 1, -1):
result.append(matrix[row][left])
left += 1
return result
4.7.1617 - 2023-08-21 21:08:48 +0300 MSK
Links
Code
class Solution:
def isValidSudoku(self, board: List[List[str]]) -> bool:
row_count, column_count = 9, 9
row_counters = [defaultdict(bool) for _ in range(row_count)]
column_counters = [defaultdict(bool) for _ in range(column_count)]
subbox_counters = [[defaultdict(bool) for _ in range(column_count//3)]
for _ in range(row_count//3)]
for row in range(row_count):
for column in range(column_count):
char = board[row][column]
if char == ".":
continue
counters = (
row_counters[row], column_counters[column],
subbox_counters[row//3][column//3]
)
for counter in counters:
if counter[char]:
return False
counter[char] = True
return True
4.7.1618 - 2023-08-21 21:08:11 +0300 MSK
Links
Code
class Solution:
def isValidSudoku(self, board: List[List[str]]) -> bool:
row_count, column_count = 9, 9
row_counters = [defaultdict(bool) for _ in range(row_count)]
column_counters = [defaultdict(bool) for _ in range(column_count)]
subbox_counters = [[defaultdict(bool) for _ in range(column_count//3)]
for _ in range(row_count//3)]
for row in range(row_count):
for column in range(column_count):
char = board[row][column]
if char == ".":
continue
counters = (
row_counters[row], column_counters[column],
subbox_counters[row//3][column//3]
)
for counter in counters:
if counter[char]:
return False
counter[char] = True
return True
4.7.1619 - 2023-08-21 09:29:54 +0300 MSK
Links
Code
class Solution:
def repeatedSubstringPattern(self, s: str) -> bool:
length = len(s)
for i in range(1, length // 2 + 1):
if length % i != 0:
continue
if s == s[:i] * (length // i):
return True
return False
4.7.1620 - 2023-08-20 14:34:41 +0300 MSK
Links
Code
class Solution:
def sortItems(self, n, m, group, beforeItems):
# If an item belongs to zero group, assign it a unique group id.
group_id = m
for i in range(n):
if group[i] == -1:
group[i] = group_id
group_id += 1
# Sort all item regardless of group dependencies.
item_graph = [[] for _ in range(n)]
item_indegree = [0] * n
# Sort all groups regardless of item dependencies.
group_graph = [[] for _ in range(group_id)]
group_indegree = [0] * group_id
for curr in range(n):
for prev in beforeItems[curr]:
# Each (prev -> curr) represents an edge in the item graph.
item_graph[prev].append(curr)
item_indegree[curr] += 1
# If they belong to different groups, add an edge in the group graph.
if group[curr] != group[prev]:
group_graph[group[prev]].append(group[curr])
group_indegree[group[curr]] += 1
# Tologlogical sort nodes in graph, return [] if a cycle exists.
def topologicalSort(graph, indegree):
visited = []
stack = [node for node in range(len(graph)) if indegree[node] == 0]
while stack:
cur = stack.pop()
visited.append(cur)
for neib in graph[cur]:
indegree[neib] -= 1
if indegree[neib] == 0:
stack.append(neib)
return visited if len(visited) == len(graph) else []
item_order = topologicalSort(item_graph, item_indegree)
group_order = topologicalSort(group_graph, group_indegree)
if not item_order or not group_order:
return []
# Items are sorted regardless of groups, we need to
# differentiate them by the groups they belong to.
ordered_groups = collections.defaultdict(list)
for item in item_order:
ordered_groups[group[item]].append(item)
# Concatenate sorted items in all sorted groups.
# [group 1, group 2, ... ] -> [(item 1, item 2, ...), (item 1, item 2, ...), ...]
answer = []
for group_index in group_order:
answer += ordered_groups[group_index]
return answer
4.7.1621 - 2023-08-19 18:48:22 +0300 MSK
Links
Code
class Solution:
def minimumOperations(self, nums: List[int]) -> int:
nums_count = len(nums)
if nums_count == 1:
return 0
@cache
def dp(i: int, start_group: int) -> int:
if i == nums_count:
return 0
curr_group = nums[i] - 1
actions_min = None
for group_available in range(start_group, 3):
actions = dp(i + 1, group_available) + (0 if group_available == curr_group else 1)
if actions_min is None or actions < actions_min:
actions_min = actions
return actions_min
return dp(0, 0)
4.7.1622 - 2023-08-19 18:13:19 +0300 MSK
Links
Code
class Solution:
def canMakeSubsequence(self, str1: str, str2: str) -> bool:
length1, length2 = len(str1), len(str2)
for i in range(length1):
if i + length2 > length1:
break
idx2 = 0
for idx1 in range(i, length1):
if ord(str2[idx2]) - ord(str1[idx1]) in (0, 1, -25):
idx2 += 1
if idx2 == length2:
return True
return False
4.7.1623 - 2023-08-19 17:36:50 +0300 MSK
Links
Code
class Solution:
def countPairs(self, nums: List[int], target: int) -> int:
pairs_count = 0
nums_count = len(nums)
for i in range(nums_count):
num1 = nums[i]
for j in range(i + 1, nums_count):
if num1 + nums[j] < target:
pairs_count += 1
return pairs_count
4.7.1624 - 2023-08-19 17:13:39 +0300 MSK
Links
Code
class Solution:
class UnionFind:
def __init__(self, n):
self.parent = list(range(n))
self.size = [1] * n
self.max_size = 1
def find(self, x):
# Finds the root of x
if x != self.parent[x]:
self.parent[x] = self.find(self.parent[x])
return self.parent[x]
def union(self, x, y):
# Connects x and y
root_x = self.find(x)
root_y = self.find(y)
if root_x != root_y:
if self.size[root_x] < self.size[root_y]:
root_x, root_y = root_y, root_x
self.parent[root_y] = root_x
self.size[root_x] += self.size[root_y]
self.max_size = max(self.max_size, self.size[root_x])
return True
return False
def findCriticalAndPseudoCriticalEdges(self, n, edges):
new_edges = [edge.copy() for edge in edges]
# Add index to edges for tracking
for i, edge in enumerate(new_edges):
edge.append(i)
# Sort edges based on weight
new_edges.sort(key=lambda x: x[2])
# Find MST weight using union-find
uf_std = self.UnionFind(n)
std_weight = 0
for u, v, w, _ in new_edges:
if uf_std.union(u, v):
std_weight += w
# Check each edge for critical and pseudo-critical
critical = []
pseudo_critical = []
for (u, v, w, i) in new_edges:
# Ignore this edge and calculate MST weight
uf_ignore = self.UnionFind(n)
ignore_weight = 0
for (x, y, w_ignore, j) in new_edges:
if i != j and uf_ignore.union(x, y):
ignore_weight += w_ignore
# If the graph is disconnected or the total weight is greater,
# the edge is critical
if uf_ignore.max_size < n or ignore_weight > std_weight:
critical.append(i)
continue
# Force this edge and calculate MST weight
uf_force = self.UnionFind(n)
force_weight = w
uf_force.union(u, v)
for (x, y, w_force, j) in new_edges:
if i != j and uf_force.union(x, y):
force_weight += w_force
# If total weight is the same, the edge is pseudo-critical
if force_weight == std_weight:
pseudo_critical.append(i)
return [critical, pseudo_critical]
4.7.1625 - 2023-08-18 10:52:33 +0300 MSK
Links
Code
class Solution:
def maximalNetworkRank(self, n: int, roads: List[List[int]]) -> int:
city_roads = [set() for _ in range(n)]
for city_one, city_two in roads:
city_roads[city_one].add(city_two)
city_roads[city_two].add(city_one)
max_rank = 0
for city_one in range(n):
for city_two in range(city_one + 1, n):
rank = len(city_roads[city_one]) + len(city_roads[city_two])
if city_one in city_roads[city_two]:
rank -= 1
if rank > max_rank:
max_rank = rank
return max_rank
4.7.1626 - 2023-08-17 16:52:59 +0300 MSK
Links
Code
class Solution:
def updateMatrix(self, mat: List[List[int]]) -> List[List[int]]:
if not mat or not mat[0]:
return []
row_count, column_count = len(mat), len(mat[0])
queue = set()
MAX_VALUE = row_count * column_count
# Initialize the queue with all 0s and set cells with 1s to MAX_VALUE.
for row in range(row_count):
for column in range(column_count):
if mat[row][column] == 0:
queue.add((row, column))
else:
mat[row][column] = MAX_VALUE
directions = ((1, 0), (-1, 0), (0, 1), (0, -1))
while queue:
center_row, center_column = queue.pop()
distance_from_center = mat[center_row][center_column] + 1
for delta_row, delta_column in directions:
new_row, new_column = center_row + delta_row, center_column + delta_column
if not 0 <= new_row < row_count or not 0 <= new_column < column_count:
continue
if mat[new_row][new_column] > distance_from_center:
queue.add((new_row, new_column))
mat[new_row][new_column] = distance_from_center
return mat
4.7.1627 - 2023-08-16 14:36:21 +0300 MSK
Links
Code
import sortedcontainers
class Solution:
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
nums_count = len(nums)
if nums_count <= k:
return [max(nums)]
counter = defaultdict(int)
elems = sortedcontainers.SortedSet()
for num in nums[:k]:
counter[num] += 1
elems.add(num)
result = [elems[-1]]
for i in range(k, nums_count):
new_num = nums[i]
remove_num = nums[i-k]
counter[new_num] += 1
elems.add(new_num)
counter[remove_num] -= 1
if counter[remove_num] == 0:
elems.discard(remove_num)
result.append(elems[-1])
return result
4.7.1628 - 2023-08-15 17:06:49 +0300 MSK
Links
Code
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def partition(self, head: Optional[ListNode], x: int) -> Optional[ListNode]:
before_head, after_head = ListNode(0), ListNode(0)
before_tail, after_tail = before_head, after_head
while head:
if head.val < x:
before_tail.next, before_tail = head, head
else:
after_tail.next, after_tail = head, head
head = head.next
after_tail.next, before_tail.next = None, after_head.next
return before_head.next
4.7.1629 - 2023-08-15 17:02:49 +0300 MSK
Links
Code
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def partition(self, head: Optional[ListNode], x: int) -> Optional[ListNode]:
first_left, last_left, first_right, last_right = None, None, None, None
while head:
is_left = head.val < x
is_right = not is_left
next_node = head.next
head.next = first_right if is_left else None
if is_left and last_left:
last_left.next = head
last_left = head
elif is_left and not first_left:
first_left, last_left = head, head
if is_right and first_right:
last_right.next = head
last_right = head
elif is_right and not first_right:
first_right, last_right = head, head
if last_left:
last_left.next = head
head = next_node
return first_left if first_left else first_right
4.7.1630 - 2023-08-14 11:17:39 +0300 MSK
Links
Code
class Solution:
def findKthLargest(self, nums, k):
heap = []
for num in nums:
heapq.heappush(heap, num)
if len(heap) > k:
heapq.heappop(heap)
return heap[0]
4.7.1631 - 2023-08-13 18:35:13 +0300 MSK
Links
Code
class Solution:
def validPartition(self, nums: List[int]) -> bool:
n = len(nums)
dp = [True] + [False] * n
# Determine if the prefix array nums[0 ~ i] has a valid partition
for i in range(n):
dp_index = i + 1
# Check 3 possibilities
if i > 0 and nums[i] == nums[i - 1]:
dp[dp_index] |= dp[dp_index - 2]
if i > 1 and nums[i] == nums[i - 1] == nums[i - 2]:
dp[dp_index] |= dp[dp_index - 3]
if i > 1 and nums[i] == nums[i - 1] + 1 == nums[i - 2] + 2:
dp[dp_index] |= dp[dp_index - 3]
return dp[n]
4.7.1632 - 2023-08-12 17:50:41 +0300 MSK
Links
Code
class Solution:
def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
row_count = len(obstacleGrid)
column_count = len(obstacleGrid[0])
if obstacleGrid[0][0] == 1 or obstacleGrid[-1][-1] == 1:
return 0
dp = [[0] * column_count for _ in range(row_count)]
dp[0][0] = 1
for column in range(1, column_count):
if obstacleGrid[0][column] == 1:
break
dp[0][column] = dp[0][column-1]
for row in range(1, row_count):
if obstacleGrid[row][0] == 0:
dp[row][0] = dp[row-1][0]
for column in range(1, column_count):
if obstacleGrid[row][column] == 1:
continue
dp[row][column] = dp[row-1][column] + dp[row][column-1]
return dp[-1][-1]
4.7.1633 - 2023-08-11 17:52:07 +0300 MSK
Links
Code
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
result = set()
#1. Split nums into three lists: negative numbers, positive numbers, and zeros
negatives, positives, zeros = [], [], []
for num in nums:
if num > 0:
positives.append(num)
elif num < 0:
negatives.append(num)
else:
zeros.append(num)
#2. Create a separate set for negatives and positives for O(1) look-up times
negatives_count, positives_count, zeros_count = len(negatives), len(positives), len(zeros)
negatives_set, positives_set = set(negatives), set(positives)
#3. If there is at least 1 zero in the list, add all cases where -num exists in N and num exists in P
# i.e. (-3, 0, 3) = 0
for num in positives_set if zeros else []:
negative = -1 * num
if negative in negatives_set:
result.add((negative, 0, num))
#3. If there are at least 3 zeros in the list then also include (0, 0, 0) = 0
if zeros_count >= 3:
result.add((0, 0, 0))
#4. For all pairs of negative numbers (-3, -1), check to see if their complement (4)
# exists in the positive number set
for i in range(negatives_count):
negative_1 = negatives[i]
for j in range(i + 1, negatives_count):
negative_2 = negatives[j]
target = -1 * (negative_1 + negative_2)
if target in positives_set:
result.add(tuple(sorted([negative_1, negative_2, target])))
#5. For all pairs of positive numbers (1, 1), check to see if their complement (-2)
# exists in the negative number set
for i in range(positives_count):
positive_1 = positives[i]
for j in range(i + 1, positives_count):
positive_2 = positives[j]
target = -1 * (positive_1 + positive_2)
if target in negatives_set:
result.add(tuple(sorted([positive_1, positive_2, target])))
return result
4.7.1634 - 2023-08-11 12:05:33 +0300 MSK
Links
Code
class Solution:
def productExceptSelf(self, nums: List[int]) -> List[int]:
nums_count = len(nums)
result = [1] * nums_count
prefix = 1
postfix = 1
for i in range(nums_count):
result[i] *= prefix
prefix *= nums[i]
from_end = -1 * (i + 1)
result[from_end] *= postfix
postfix *= nums[from_end]
return result
4.7.1635 - 2023-08-11 12:01:50 +0300 MSK
Links
Code
class Solution:
def productExceptSelf(self, nums: List[int]) -> List[int]:
nums_count = len(nums)
result = [1] * nums_count
prefix = 1
postfix = 1
for i in range(nums_count):
result[i] *= prefix
prefix *= nums[i]
result[nums_count-i-1] *= postfix
postfix *= nums[nums_count-i-1]
return result
4.7.1636 - 2023-08-11 11:17:35 +0300 MSK
Links
Code
class Solution:
def change(self, amount: int, coins: List[int]) -> int:
n = len(coins)
dp = [[0] * (amount + 1) for _ in range(n + 1)]
for i in range(n):
dp[i][0] = 1
for i in range(n - 1, -1, -1):
for j in range(1, amount + 1):
if coins[i] > j:
dp[i][j] = dp[i + 1][j]
else:
dp[i][j] = dp[i + 1][j] + dp[i][j - coins[i]]
return dp[0][amount]
4.7.1637 - 2023-08-11 11:12:31 +0300 MSK
Links
Code
class Solution:
def change(self, amount: int, coins: List[int]) -> int:
coins_count = len(coins)
memo = [[-1] * (amount + 1) for _ in range(coins_count)]
def dp(i: int, amount: int) -> int:
if amount == 0:
return 1
if i == coins_count:
return 0
if memo[i][amount] != -1:
return memo[i][amount]
value = None
if coins[i] > amount:
value = dp(i + 1, amount)
else:
value = dp(i, amount - coins[i]) + dp(i + 1, amount)
memo[i][amount] = value
return value
return dp(0, amount)
4.7.1638 - 2023-08-10 17:04:38 +0300 MSK
Links
Code
class Solution:
def search(self, nums: List[int], target: int) -> bool:
left, right = 0, len(nums) - 1
while left <= right:
mid = (left + right) // 2
if nums[mid] == target:
return True
if nums[mid] == nums[left]:
left += 1
continue
if nums[left] <= nums[mid]:
if nums[left] <= target < nums[mid]:
right = mid - 1
else:
left = mid + 1
else:
if nums[mid] < target <= nums[right]:
left = mid + 1
else:
right = mid - 1
return False
4.7.1639 - 2023-08-09 15:13:28 +0300 MSK
Links
Code
class Solution:
def maxProfit(self, k: int, prices: List[int]) -> int:
# no transaction, no profit
if k == 0: return 0
# dp[k][0] = min cost you need to spend at most k transactions
# dp[k][1] = max profit you can achieve at most k transactions
dp = [[1000, 0] for _ in range(k + 1)]
for price in prices:
for i in range(1, k + 1):
# price - dp[i - 1][1] is how much you need to spend
# i.e use the profit you earned from previous transaction to buy the stock
# we want to minimize it
dp[i][0] = min(dp[i][0], price - dp[i - 1][1])
# price - dp[i][0] is how much you can achieve from previous min cost
# we want to maximize it
dp[i][1] = max(dp[i][1], price - dp[i][0])
# return max profit at most k transactions
# or you can write `return dp[-1][1]`
return dp[k][1]
4.7.1640 - 2023-08-09 12:05:47 +0300 MSK
Links
Code
class Solution:
def minimizeMax(self, nums: List[int], p: int) -> int:
nums.sort()
nums_count = len(nums)
# Find the number of valid pairs by greedy approach
def countValidPairs(threshold: int) -> int:
index, count = 0, 0
while index < nums_count - 1:
# If a valid pair is found, skip both numbers.
if nums[index + 1] - nums[index] <= threshold:
count += 1
index += 1
index += 1
return count
left, right = 0, nums[-1] - nums[0]
while left < right:
mid = left + (right - left) // 2
# If there are enough pairs, look for a smaller threshold.
# Otherwise, look for a larger threshold.
if countValidPairs(mid) >= p:
right = mid
else:
left = mid + 1
return left
4.7.1641 - 2023-08-08 23:40:50 +0300 MSK
Links
Code
class Solution:
def maxProfit(self, prices: List[int]) -> int:
'''
dp_2_hold: max profit with 2 transactions, and in hold state
dp_2_not_hold: max profit with 2 transactions, and not in hold state
dp_1_hold: max profit with 1 transaction, and in hold state
dp_1_not_hold: max profit with 1 transaction, and not in hold state
Note: it is impossible to have stock in hand and sell on first day, therefore -infinity is set as initial profit value for hold state
'''
dp_2_hold, dp_2_not_hold = -float('inf'), 0
dp_1_hold, dp_1_not_hold = -float('inf'), 0
for stock_price in prices:
# either keep being in not-hold state, or sell with stock price today
dp_2_not_hold = max( dp_2_not_hold, dp_2_hold + stock_price )
# either keep being in hold state, or just buy with stock price today ( add one more transaction )
dp_2_hold = max( dp_2_hold, dp_1_not_hold - stock_price )
# either keep being in not-hold state, or sell with stock price today
dp_1_not_hold = max( dp_1_not_hold, dp_1_hold + stock_price )
# either keep being in hold state, or just buy with stock price today ( add one more transaction )
dp_1_hold = max( dp_1_hold, 0 - stock_price )
return dp_2_not_hold
4.7.1642 - 2023-08-08 23:36:48 +0300 MSK
Links
Code
class Solution:
def maxProfit(self, prices: List[int]) -> int:
if not prices:
return 0
# initialize variables for first buy, first sell, second buy, and second sell
buy1, buy2 = float('inf'), float('inf')
sell1, sell2 = 0, 0
# iterate over prices to update buy and sell values
for price in prices:
# update first buy and sell values
buy1 = min(buy1, price)
sell1 = max(sell1, price - buy1)
# update second buy and sell values
buy2 = min(buy2, price - sell1)
sell2 = max(sell2, price - buy2)
return sell2
4.7.1643 - 2023-08-08 22:57:16 +0300 MSK
Links
Code
class Solution:
def longestPalindrome(self, s: str) -> str:
n = len(s)
dp = [[False] * n for _ in range(n)]
ans = [0, 0]
for i in range(n):
dp[i][i] = True
for i in range(n - 1):
if s[i] == s[i + 1]:
dp[i][i + 1] = True
ans = [i, i + 1]
for diff in range(2, n):
for i in range(n - diff):
j = i + diff
if s[i] == s[j] and dp[i + 1][j - 1]:
dp[i][j] = True
ans = [i, j]
i, j = ans
return s[i:j + 1]
4.7.1644 - 2023-08-08 22:56:36 +0300 MSK
Links
Code
class Solution:
def maximalSquare(self, matrix: List[List[str]]) -> int:
row_count, column_count = len(matrix), len(matrix[0])
dp = [[0] * column_count for _ in range(row_count)]
max_size = 0
for column in range(column_count):
if matrix[0][column] == "0":
continue
dp[0][column] = 1
max_size = 1
for row in range(row_count):
if matrix[row][0] == "0":
continue
dp[row][0] = 1
max_size = 1
for row in range(1, row_count):
for column in range(1, column_count):
if matrix[row][column] == "0":
continue
value = min(dp[row-1][column], dp[row][column-1], dp[row-1][column-1]) + 1
dp[row][column] = value
max_size = max(max_size, value)
return max_size * max_size
4.7.1645 - 2023-08-08 21:50:31 +0300 MSK
Links
Code
class Solution:
def minDistance(self, word1: str, word2: str) -> int:
length1, length2 = len(word1), len(word2)
@cache
def dp(i1: int, i2: int) -> int:
if i1 == length1:
return length2 - (i2 + 1)
if i2 == length2:
return length1 - (i1 + 1)
if word1[i1] == word2[i2]:
return dp(i1 + 1, i2 + 1)
return 1 + min((
# replace or insert
dp(i1 + 1, i2 + 1),
# remove from i1
dp(i1 + 1, i2),
# remove from i2
dp(i1, i2 + 1)
))
return dp(0, 0) + 1
4.7.1646 - 2023-08-08 21:27:42 +0300 MSK
Links
Code
class Solution:
def isInterleave(self, s1: str, s2: str, s3: str) -> bool:
length_1, length_2, length_3 = len(s1), len(s2), len(s3)
if length_1 + length_2 != length_3:
return False
@cache
def dp(i_1: int, i_2: int, i_3: int) -> bool:
if i_3 == length_3:
return True
target = s3[i_3]
return (
i_1 != length_1 and s1[i_1] == target and dp(i_1 + 1, i_2, i_3 + 1)
) or (
i_2 != length_2 and s2[i_2] == target and dp(i_1, i_2 + 1, i_3 + 1)
)
return dp(0, 0, 0)
4.7.1647 - 2023-08-08 21:02:11 +0300 MSK
Links
Code
class Solution:
def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
row_count = len(obstacleGrid)
column_count = len(obstacleGrid[0])
if obstacleGrid[0][0] == 1 or obstacleGrid[-1][-1] == 1:
return 0
dp = [[0] * column_count for _ in range(row_count)]
dp[0][0] = 1
for column in range(1, column_count):
if obstacleGrid[0][column] == 1:
break
dp[0][column] = dp[0][column-1]
for row in range(1, row_count):
if obstacleGrid[row][0] == 0:
dp[row][0] = dp[row-1][0]
for column in range(1, column_count):
if obstacleGrid[row][column] == 1:
continue
dp[row][column] = dp[row-1][column] + dp[row][column-1]
return dp[-1][-1]
4.7.1648 - 2023-08-08 20:47:19 +0300 MSK
Links
Code
class Solution:
def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
row_count = len(obstacleGrid)
column_count = len(obstacleGrid[0])
# dp = [[0] * column_count for _ in range(row_count)]
# for row in range(row_count):
# for column in range(column_count):
@cache
def dp(row: int, column: int) -> int:
if row == row_count or column == column_count or obstacleGrid[row][column] == 1:
return 0
if row == row_count - 1 and column == column_count - 1:
return 1
return dp(row + 1, column) + dp(row, column + 1)
return dp(0, 0)
4.7.1649 - 2023-08-08 20:31:21 +0300 MSK
Links
Code
class Solution:
def minPathSum(self, grid: List[List[int]]) -> int:
row_count = len(grid)
column_count = len(grid[0]) if grid else None
if not row_count or not column_count:
return 0
dp = [[0] * column_count for _ in range(row_count)]
dp[0][0] = grid[0][0]
for column in range(1, column_count):
dp[0][column] = grid[0][column] + dp[0][column - 1]
for row in range(1, row_count):
dp[row][0] = grid[row][0] + dp[row - 1][0]
for column in range(1, column_count):
dp[row][column] = grid[row][column] + min(
dp[row - 1][column], dp[row][column-1]
)
# @cache
# def dp(row: int, column: int) -> int:
# if row == row_count or column == column_count:
# return 0
# return grid[row][column] + min(dp(row + 1, column), dp(row, column + 1))
#return dp(0, 0)
return dp[-1][-1]
4.7.1650 - 2023-08-08 19:53:50 +0300 MSK
Links
Code
class Solution:
def minimumTotal(self, triangle: List[List[int]]) -> int:
row_count = len(triangle)
dp = [[0] * row_count for _ in range(row_count)]
dp[0][0] = triangle[0][0]
for row in range(1, row_count):
dp[row][0] = triangle[row][0] + dp[row-1][0]
dp[row][row] = triangle[row][row] + dp[row-1][row-1]
for column in range(1, row):
dp[row][column] = triangle[row][column] + min(
dp[row-1][column], dp[row-1][column-1]
)
return min(dp[-1])
4.7.1651 - 2023-08-08 19:34:48 +0300 MSK
Links
Code
class Solution:
def minimumTotal(self, triangle: List[List[int]]) -> int:
row_count = len(triangle)
@cache
def dp(row: int, column: int) -> int:
if row == row_count or column == row + 1:
return 0
return triangle[row][column] + min(dp(row + 1, column), dp(row + 1, column + 1))
return dp(0, 0)
4.7.1652 - 2023-08-08 14:36:45 +0300 MSK
Links
Code
class Solution:
def findKthLargest(self, nums, k):
heap = []
for num in nums:
heapq.heappush(heap, num)
if len(heap) > k:
heapq.heappop(heap)
return heap[0]
4.7.1653 - 2023-08-08 13:55:40 +0300 MSK
Links
Code
class Solution:
def search(self, nums: List[int], target: int) -> int:
nums_count = len(nums)
left, right = 0, len(nums) - 1
first_num, last_num = nums[0], nums[-1]
if first_num == target:
return 0
if last_num == target:
return nums_count - 1
# Find the index of the pivot element (the smallest element)
while left <= right:
mid = left + (right - left) // 2
if nums[mid] > last_num:
left = mid + 1
else:
right = mid - 1
pivot_num = nums[left]
if pivot_num == target:
return left
if pivot_num < target < last_num:
right = nums_count - 1
else:
left = 0
while left <= right:
mid = left + (right - left) // 2
mid_num = nums[mid]
if mid_num == target:
return mid
elif mid_num > target:
right = mid - 1
else:
left = mid + 1
return -1
4.7.1654 - 2023-08-08 13:55:01 +0300 MSK
Links
Code
class Solution:
def search(self, nums: List[int], target: int) -> int:
nums_count = len(nums)
left, right = 0, len(nums) - 1
first_num, last_num = nums[0], nums[-1]
if first_num == target:
return 0
if last_num == target:
return nums_count - 1
# Find the index of the pivot element (the smallest element)
while left <= right:
mid = left + (right - left) // 2
if nums[mid] > last_num:
left = mid + 1
else:
right = mid - 1
pivot_num = nums[left]
if pivot_num == target:
return left
if pivot_num < target < last_num:
right = nums_count - 1
else:
left = 0
while left <= right:
mid = (left + right) // 2
mid_num = nums[mid]
if mid_num == target:
return mid
elif mid_num > target:
right = mid - 1
else:
left = mid + 1
return -1
4.7.1655 - 2023-08-07 17:24:07 +0300 MSK
Links
Code
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
nums_count = len(nums)
dp = [0] * nums_count
dp[0] = 1
for i in range(1, nums_count):
length = 0
start = nums[i]
for j in range(0, i):
if start > nums[j]:
length = max(length, dp[j])
dp[i] = 1 + length
return max(dp)
4.7.1656 - 2023-08-07 14:39:05 +0300 MSK
Links
Code
class Solution:
def coinChange(self, coins: List[int], amount: int) -> int:
dp = [amount + 1] * (amount + 1)
dp[0] = 0
for current_amount in range(1, amount + 1):
for coin in coins:
diff = current_amount - coin
if diff < 0:
continue
dp[current_amount] = min(dp[current_amount], dp[diff] + 1)
return dp[-1] if dp[-1] != amount + 1 else -1
4.7.1657 - 2023-08-07 14:27:07 +0300 MSK
Links
Code
class Solution:
def coinChange(self, coins: List[int], amount: int) -> int:
if amount == 0:
return 0
@cache
def dp(coins_value: int) -> int:
if coins_value == amount:
return 0
if coins_value > amount:
return -1
min_coins_count = -1
for coin in coins:
new_count = 1 + dp(coin + coins_value)
if new_count == 0:
continue
if min_coins_count == -1 or new_count < min_coins_count:
min_coins_count = new_count
return min_coins_count
return dp(0)
4.7.1658 - 2023-08-07 13:27:10 +0300 MSK
Links
Code
class Solution:
def wordBreak(self, s: str, wordDict: List[str]) -> bool:
n = len(s)
words = set(wordDict)
dp = [False] * (n + 1)
dp[0] = True
for i in range(1, n + 1):
for j in range(i):
if dp[j] and s[j:i] in words:
dp[i] = True
break
return dp[-1]
4.7.1659 - 2023-08-07 13:25:04 +0300 MSK
Links
Code
class Solution:
def wordBreak(self, s: str, wordDict: List[str]) -> bool:
@cache
def dp(i):
if i < 0:
return True
for word in wordDict:
if s[i - len(word) + 1:i + 1] == word and dp(i - len(word)):
return True
return False
return dp(len(s) - 1)
4.7.1660 - 2023-08-07 13:10:04 +0300 MSK
Links
Code
class Solution:
def rob(self, nums: List[int]) -> int:
house_count = len(nums)
prev_1, prev_2 = 0, 0
for house in range(0, house_count):
prev_1, prev_2 = max(prev_2 + nums[house], prev_1), prev_1
return prev_1
4.7.1661 - 2023-08-07 13:07:20 +0300 MSK
Links
Code
class Solution:
def rob(self, nums: List[int]) -> int:
house_count = len(nums)
dp = [0 for _ in range(house_count + 1)]
dp[1] = nums[0]
for house in range(1, house_count):
dp[house+1] = max(dp[house-1] + nums[house], dp[house])
return dp[-1]
4.7.1662 - 2023-08-07 12:57:18 +0300 MSK
Links
Code
class Solution:
def rob(self, nums: List[int]) -> int:
house_count = len(nums)
@cache
def dp(house: int) -> int:
if house >= house_count:
return 0
return max(dp(house + 1), nums[house] + dp(house + 2))
return dp(0)
4.7.1663 - 2023-08-07 12:49:57 +0300 MSK
Links
Code
class Solution:
def climbStairs(self, n: int) -> int:
if n < 3:
return n
minus_one, minus_two = 2, 1
for step in range(3, n + 1):
minus_one, minus_two = minus_one + minus_two, minus_one
return minus_one
4.7.1664 - 2023-08-07 12:45:54 +0300 MSK
Links
Code
class Solution:
def climbStairs(self, n: int) -> int:
@cache
def dp(step: int) -> int:
if step <= 2:
return step
return dp(step - 1) + dp(step - 2)
return dp(n)
4.7.1665 - 2023-08-07 12:17:58 +0300 MSK
Links
Code
class Solution:
def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
length_vertical, length_horizontal = len(matrix), len(matrix[0])
left, right = 0, length_vertical - 1
while left <= right:
mid = left + (right - left) // 2
mid_number = matrix[mid][0]
if mid_number == target:
return True
if mid_number > target:
right = mid - 1
else:
left = mid + 1
vertical_index = right
left, right = 0, length_horizontal - 1
while left <= right:
mid = left + (right - left) // 2
mid_number = matrix[vertical_index][mid]
if mid_number == target:
return True
if mid_number > target:
right = mid - 1
else:
left = mid + 1
return False
4.7.1666 - 2023-08-06 18:05:41 +0300 MSK
Links
Code
class Solution:
def finalString(self, s: str) -> str:
result = []
for char in s:
if char == "i":
result.reverse()
else:
result.append(char)
return "".join(result)
4.7.1667 - 2023-08-06 18:00:12 +0300 MSK
Links
Code
class Solution:
def maxValue(self, events: List[List[int]], k: int) -> int:
events.sort()
n = len(events)
starts = [start for start, end, value in events]
dp = [[-1] * n for _ in range(k + 1)]
def dfs(cur_index, count):
if count == 0 or cur_index == n:
return 0
if dp[count][cur_index] != -1:
return dp[count][cur_index]
# Find the nearest available event after attending event 0.
next_index = bisect_right(starts, events[cur_index][1])
dp[count][cur_index] = max(dfs(cur_index + 1, count), events[cur_index][2] + dfs(next_index, count - 1))
return dp[count][cur_index]
return dfs(0, k)
4.7.1668 - 2023-08-06 17:37:57 +0300 MSK
Links
Code
class Solution:
def numMusicPlaylists(self, n: int, goal: int, k: int) -> int:
MOD = 10**9 + 7
# Initialize the DP table
dp = [[0 for _ in range(n + 1)] for _ in range(goal + 1)]
dp[0][0] = 1
for i in range(1, goal + 1):
for j in range(1, min(i, n) + 1):
# The i-th song is a new song
dp[i][j] = dp[i - 1][j - 1] * (n - j + 1) % MOD
# The i-th song is a song we have played before
if j > k:
dp[i][j] = (dp[i][j] + dp[i - 1][j] * (j - k)) % MOD
return dp[goal][n]
4.7.1669 - 2023-08-06 17:18:41 +0300 MSK
Links
Code
class Solution:
def smallestSufficientTeam(self, req_skills: List[str], people: List[List[str]]) -> List[int]:
req_skills_count = len(req_skills)
skill_to_people = defaultdict(set)
for i, person in enumerate(people):
for skill in person:
skill_to_people[skill].add(i)
current = set()
def backtrack(skill: int) -> Tuple[int]:
if skill == req_skills_count:
return tuple(current)
suff_team = None
people_with_skill = skill_to_people[req_skills[skill]]
if current & people_with_skill:
return backtrack(skill + 1)
for person in people_with_skill:
current.add(person)
new_team = backtrack(skill + 1)
current.remove(person)
if suff_team is None or len(new_team) < len(suff_team):
suff_team = new_team
return suff_team
return backtrack(0)
4.7.1670 - 2023-08-05 17:53:24 +0300 MSK
Links
Code
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:
root = head
while head and head.next:
next = head.next
new_node = ListNode(math.gcd(head.val, head.next.val), next)
head.next = new_node
head = next
return root
4.7.1671 - 2023-08-05 17:40:38 +0300 MSK
Links
Code
class Solution:
def accountBalanceAfterPurchase(self, purchaseAmount: int) -> int:
remainder = purchaseAmount % 10
if remainder == 0:
return 100 - purchaseAmount
if remainder >= 5:
return 100 - ((purchaseAmount // 10) + 1) * 10
return 100 - (purchaseAmount // 10) * 10
4.7.1672 - 2023-08-05 12:39:41 +0300 MSK
Links
Code
class Solution:
def generateTrees(self, n: int) -> List[Optional[TreeNode]]:
@cache
def generate_trees(l, r):
return [None] if l > r else [
TreeNode(val, left, right)
for val in range(l, r + 1)
for left in generate_trees(l, val - 1)
for right in generate_trees(val + 1, r)
]
return generate_trees(1, n)
4.7.1673 - 2023-08-04 19:40:16 +0300 MSK
Links
Code
class Solution:
def maximumRequests(self, n, requests):
current = [0] * n
length = len(requests)
def backtrack(req_index: int, count: int) -> int:
if req_index == length:
return 0 if any(current) else count
req_from, req_to = requests[req_index]
current[req_from] -= 1
current[req_to] += 1
take = backtrack(req_index + 1, count + 1)
current[req_from] += 1
current[req_to] -= 1
non_take = backtrack(req_index + 1, count)
return max(take, non_take)
return backtrack(0, 0)
4.7.1674 - 2023-08-04 19:38:00 +0300 MSK
Links
Code
class Solution:
def wordBreak(self, s: str, wordDict: List[str]) -> bool:
@cache
def calculate(i: int) -> bool:
if i < 0:
return True
for word in wordDict:
length = len(word)
if s[i-length+1:i+1] == word and calculate(i-length):
return True
return False
return calculate(len(s) - 1)
4.7.1675 - 2023-08-04 19:37:15 +0300 MSK
Links
Code
class Solution:
def wordBreak(self, s: str, wordDict: List[str]) -> bool:
words = set(wordDict)
@cache
def calculate(i: int) -> bool:
if i < 0:
return True
for word in wordDict:
length = len(word)
if s[i-length+1:i+1] == word and calculate(i-length):
return True
return False
return calculate(len(s) - 1)
4.7.1676 - 2023-08-03 12:33:31 +0300 MSK
Links
Code
class Solution:
def letterCombinations(self, digits: str) -> List[str]:
length = len(digits)
if length == 0:
return []
digit_map: Dict[int, str] = {
"1": [],
"2": ["a", "b", "c"],
"3": ["d", "e", "f"],
"4": ["g", "h", "i"],
"5": ["j", "k", "l"],
"6": ["m", "n", "o"],
"7": ["p", "q", "r", "s"],
"8": ["t", "u", "v"],
"9": ["w", "x", "y", "z"],
"0": [" "]
}
current = []
def backtrack(digit: int) -> Generator[None, None, str]:
if digit == length:
yield "".join(current[:])
return
for char in digit_map[digits[digit]]:
current.append(char)
yield from backtrack(digit + 1)
current.pop()
return tuple(combination for combination in backtrack(0))
4.7.1677 - 2023-08-03 12:32:00 +0300 MSK
Links
Code
class Solution:
def letterCombinations(self, digits: str) -> List[str]:
length = len(digits)
if length == 0:
return []
digit_map: Dict[int, str] = {
"1": [],
"2": ["a", "b", "c"],
"3": ["d", "e", "f"],
"4": ["g", "h", "i"],
"5": ["j", "k", "l"],
"6": ["m", "n", "o"],
"7": ["p", "q", "r", "s"],
"8": ["t", "u", "v"],
"9": ["w", "x", "y", "z"],
"0": [" "]
}
current = []
def backtrack(digit: int) -> Generator[None, None, str]:
if digit == length:
yield "".join(current[:])
return
for char in digit_map[digits[digit]]:
current.append(char)
yield from backtrack(digit + 1)
current.pop()
return tuple(combination for combination in backtrack(0))
4.7.1678 - 2023-08-02 19:02:58 +0300 MSK
Links
Code
class Solution:
def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
courses = defaultdict(set)
for course, prereq in prerequisites:
courses[course].add(prereq)
if not courses:
return True
stack = set()
@cache
def check(course: int) -> bool:
if course not in courses:
return True
if course in stack:
return False
prereqs = courses[course]
if prereqs & stack:
return False
stack.add(course)
for prereq in prereqs:
if not check(prereq):
return False
stack.remove(course)
return True
for course in courses:
if not check(course):
return False
return True
4.7.1679 - 2023-08-02 18:11:45 +0300 MSK
Links
Code
class Solution:
def eventualSafeNodes(self, graph: List[List[int]]) -> List[int]:
length = len(graph)
indegree = [0] * length
adj = [[] for _ in range(length)]
for i in range(length):
for edge in graph[i]:
adj[edge].append(i)
indegree[i] += 1
q = deque()
# Push all the nodes with indegree zero in the queue.
for i in range(length):
if indegree[i] == 0:
q.append(i)
safe = [False] * length
while q:
node = q.popleft()
safe[node] = True
for neighbor in adj[node]:
# Delete the edge "node -> neighbor".
indegree[neighbor] -= 1
if indegree[neighbor] == 0:
q.append(neighbor)
safe_nodes = []
for i in range(length):
if safe[i]:
safe_nodes.append(i)
return safe_nodes
4.7.1680 - 2023-08-02 17:33:24 +0300 MSK
Links
Code
class Solution:
def maxConsecutiveAnswers(self, answerKey: str, k: int) -> int:
length = len(answerKey)
char_t, char_f = "T", "F"
max_size = k
count = defaultdict(int)
for char in answerKey[:k]:
count[char] += 1
left = 0
for right in range(k, length):
count[answerKey[right]] += 1
while min(count[char_t], count[char_f]) > k:
count[answerKey[left]] -= 1
left += 1
size = right - left + 1
if size > max_size:
max_size = size
return max_size
4.7.1681 - 2023-08-02 11:09:23 +0300 MSK
Links
Code
class Solution:
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
left = 0
sum_of_subarray = 0
min_length = float('inf')
for right in range(len(nums)):
sum_of_subarray += nums[right]
while sum_of_subarray >= target:
min_length = min(min_length, right - left + 1)
sum_of_subarray -= nums[left]
left += 1
if min_length == float('inf'):
return 0
return min_length
4.7.1682 - 2023-08-02 11:07:07 +0300 MSK
Links
Code
class Solution:
def singleNumber(self, nums: List[int]) -> int:
nums.sort()
length = len(nums)
for i in range(0, length, 3):
if i == length - 1:
return nums[i]
num_1, num_2, num_3 = nums[i], nums[i+1], nums[i+2]
if num_1 == num_2 == num_3:
continue
if num_2 == num_3:
return num_1
if num_1 == num_3:
return num_2
return num_3
4.7.1683 - 2023-08-02 11:00:07 +0300 MSK
Links
Code
class Solution:
def buddyStrings(self, s: str, goal: str) -> bool:
length_1, length_2 = len(s), len(goal)
if length_1 != length_2:
return False
if s == goal:
freq = defaultdict(int)
for char in s:
freq[char] += 1
if freq[char] == 2:
return True
return False
swap_1, swap_2 = -1, -1
for i in range(length_1):
char_1, char_2 = s[i], goal[i]
if char_1 == char_2:
continue
if swap_1 == -1:
swap_1 = i
elif swap_2 == -1:
swap_2 = i
else:
return False
return swap_2 != -1 and s[swap_1] == goal[swap_2] and s[swap_2] == goal[swap_1]
4.7.1684 - 2023-08-02 10:39:16 +0300 MSK
Links
Code
class Solution:
def generateParenthesis(self, n: int) -> List[str]:
current = []
current_max = n * 2
chars = "()"
def backtrack(open: int, closed: int) -> Generator[None, None, List[str]]:
if len(current) == current_max:
yield "".join(current)
if open:
current.append(chars[0])
yield from backtrack(open - 1, closed)
current.pop()
if closed and closed > open:
current.append(chars[1])
yield from backtrack(open, closed - 1)
current.pop()
return tuple(combination for combination in backtrack(n, n))
4.7.1685 - 2023-08-02 10:26:02 +0300 MSK
Links
Code
class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
length = len(nums)
current = []
current_contains = [False] * length
def backtrack() -> Generator[None, None, List[int]]:
if len(current) == length:
yield tuple(current[:])
return
for i in range(length):
if current_contains[i]:
continue
current_contains[i] = True
current.append(nums[i])
yield from backtrack()
current_contains[i] = False
current.pop()
return
return tuple(combination for combination in backtrack())
4.7.1686 - 2023-08-01 20:38:09 +0300 MSK
Links
Code
class Solution:
def maximumRequests(self, n, requests):
current = [0] * n
length = len(requests)
def backtrack(req_index: int, count: int) -> int:
if req_index == length:
return 0 if any(current) else count
req_from, req_to = requests[req_index]
current[req_from] -= 1
current[req_to] += 1
take = backtrack(req_index + 1, count + 1)
current[req_from] += 1
current[req_to] -= 1
non_take = backtrack(req_index + 1, count)
return max(take, non_take)
return backtrack(0, 0)
4.7.1687 - 2023-08-01 20:19:26 +0300 MSK
Links
Code
class Solution:
def __init__(self):
self.ans = 0
def helper(self, start, requests, indegree, n, count):
if start == len(requests):
for i in range(n):
if indegree[i] != 0:
return
self.ans = max(self.ans, count)
return
# Take
indegree[requests[start][0]] -= 1
indegree[requests[start][1]] += 1
self.helper(start + 1, requests, indegree, n, count + 1)
# Not-take
indegree[requests[start][0]] += 1
indegree[requests[start][1]] -= 1
self.helper(start + 1, requests, indegree, n, count)
def maximumRequests(self, n, requests):
indegree = [0] * n
self.helper(0, requests, indegree, n, 0)
return self.ans
4.7.1688 - 2023-08-01 18:39:03 +0300 MSK
Links
Code
class Solution:
def countCompleteSubarrays(self, nums: List[int]) -> int:
length = len(nums)
elems_count = len(set(nums))
if elems_count == length:
return 1
if elems_count == 1:
return length + sum(i for i in range(1, length))
result, elems, min_j = 0, defaultdict(int), 0
for i in range(length):
left = nums[i]
for j in range(min_j, length):
right = nums[j]
elems[right] += 1
if len(elems) != elems_count:
continue
if elems[right] == 1:
elems.pop(right)
else:
elems[right] -= 1
result += length - j
min_j = j
break
else:
return result
if elems[left] == 1:
elems.pop(left)
else:
elems[left] -= 1
return result
4.7.1689 - 2023-08-01 17:52:16 +0300 MSK
Links
Code
class Solution:
def numberOfEmployeesWhoMetTarget(self, hours: List[int], target: int) -> int:
count = 0
for hour in hours:
if hour < target:
continue
count += 1
return count
4.7.1690 - 2023-08-01 17:35:47 +0300 MSK
Links
Code
class Solution:
def combine(self, n: int, k: int) -> List[List[int]]:
current = []
def backtrack(first: int) -> Generator[None, None, List[int]]:
if len(current) == k:
yield tuple(current[:])
return
for i in range(first, n + 1):
current.append(i)
yield from backtrack(i + 1)
current.pop()
return
return tuple(combination for combination in backtrack(1))
4.7.1691 - 2023-08-01 17:33:23 +0300 MSK
Links
Code
class Solution:
def combine(self, n: int, k: int) -> List[List[int]]:
current, result = [], []
def backtrack(first: int) -> None:
if len(current) == k:
result.append(tuple(current[:]))
return
for i in range(first, n + 1):
current.append(i)
backtrack(i + 1)
current.pop()
return
backtrack(1)
return result
4.7.1692 - 2023-08-01 17:14:55 +0300 MSK
Links
Code
class Solution:
def combine(self, n: int, k: int) -> List[List[int]]:
def generate_combinations(elems: List[int], num: int):
total = len(elems)
if num > total:
return
curr_indices = list(range(num))
reversed_num = tuple(reversed(range(num)))
while True:
yield list(elems[i] for i in curr_indices)
for idx in reversed_num:
if curr_indices[idx] != idx + total - num:
break
else:
return
curr_indices[idx] += 1
for j in range(idx+1, num):
curr_indices[j] = curr_indices[j-1] + 1
return [combination for combination in generate_combinations(tuple(range(1, n+1)), k)]
4.7.1693 - 2023-07-31 19:28:12 +0300 MSK
Links
Code
class Solution:
def maxArea(self, height: List[int]) -> int:
left = 0
right = len(height) - 1
maxArea = 0
while left < right:
currentArea = min(height[left], height[right]) * (right - left)
if currentArea > maxArea:
maxArea = currentArea
if height[left] < height[right]:
left += 1
else:
right -= 1
return maxArea
4.7.1694 - 2023-07-31 17:17:46 +0300 MSK
Links
Code
class Solution:
def longestPalindrome(self, s: str) -> str:
n = len(s)
dp = [[False] * n for _ in range(n)]
ans = [0, 0]
for i in range(n):
dp[i][i] = True
for i in range(n - 1):
if s[i] == s[i + 1]:
dp[i][i + 1] = True
ans = [i, i + 1]
for diff in range(2, n):
for i in range(n - diff):
j = i + diff
if s[i] == s[j] and dp[i + 1][j - 1]:
dp[i][j] = True
ans = [i, j]
i, j = ans
return s[i:j + 1]
4.7.1695 - 2023-07-31 14:46:40 +0300 MSK
Links
Code
class Solution:
def minimumDeleteSum(self, s1: str, s2: str) -> int:
length_1, length_2 = len(s1), len(s2)
@cache
def calculate(i: int, j: int) -> int:
if i >= length_1 and j >= length_2:
return 0
if i >= length_1:
return sum(ord(char) for char in s2[j:])
if j >= length_2:
return sum(ord(char) for char in s1[i:])
if s1[i] == s2[j]:
return calculate(i + 1, j + 1)
return min(
ord(s1[i]) + calculate(i + 1, j),
ord(s2[j]) + calculate(i, j + 1)
)
return calculate(0, 0)
4.7.1696 - 2023-07-30 20:11:15 +0300 MSK
Links
Code
class Solution:
def strangePrinter(self, s: str) -> int:
n = len(s)
dp = [[n] * n for _ in range(n)]
for length in range(1, n + 1):
for left in range(n - length + 1):
right = left + length - 1
j = -1
for i in range(left, right):
if s[i] != s[right] and j == -1:
j = i
if j != -1:
dp[left][right] = min(dp[left][right], 1 + dp[j][i] + dp[i + 1][right])
if j == -1:
dp[left][right] = 0
return dp[0][n - 1] + 1
4.7.1697 - 2023-07-30 10:12:02 +0300 MSK
Links
Code
class Solution:
def PredictTheWinner(self, nums: List[int]) -> bool:
length = len(nums)
is_even = length % 2 == 0
if length < 3:
return True
@cache
def max_diff(left: int, right: int) -> int:
left_num, right_num = nums[left], nums[right]
if left == right:
return left_num
score_by_left = left_num - max_diff(left + 1, right)
score_by_right = right_num - max_diff(left, right - 1)
return max(score_by_left, score_by_right)
return max_diff(0, length - 1) >= 0
4.7.1698 - 2023-07-29 18:54:20 +0300 MSK
Links
Code
class Solution:
def PredictTheWinner(self, nums: List[int]) -> bool:
length = len(nums)
is_even = length % 2 == 0
if length < 3:
return True
@cache
def max_diff(left: int, right: int) -> int:
left_num, right_num = nums[left], nums[right]
if left == right:
return left_num
score_by_left = left_num - max_diff(left + 1, right)
score_by_right = right_num - max_diff(left, right - 1)
return max(score_by_left, score_by_right)
return max_diff(0, length - 1) >= 0
4.7.1699 - 2023-07-29 18:51:41 +0300 MSK
Links
Code
class Solution:
def PredictTheWinner(self, nums: List[int]) -> bool:
length = len(nums)
is_even = length % 2 == 0
if length < 3:
return True
def max_diff(left: int, right: int) -> int:
left_num, right_num = nums[left], nums[right]
if left == right:
return left_num
score_by_left = left_num - max_diff(left + 1, right)
score_by_right = right_num - max_diff(left, right - 1)
return max(score_by_left, score_by_right)
return max_diff(0, length - 1) >= 0
4.7.1700 - 2023-07-29 13:24:33 +0300 MSK
Links
Code
class Solution:
def soupServings(self, n: int) -> float:
servings = ceil(n / 25)
states = defaultdict(dict)
moves = [[-4, 0], [-3, -1], [-2, -2], [-1, -3]]
@cache
def calculate(soup_a: int, soup_b: int) -> float:
if soup_a <= 0 and soup_b <= 0:
return 0.5
if soup_a <= 0:
return 1.0
if soup_b <= 0:
return 0.0
if soup_a in states and soup_b in states[soup_a]:
return states[soup_a][soup_b]
state = sum(calculate(soup_a + move[0], soup_b + move[1]) for move in moves) / 4.0
states[soup_a][soup_b] = state
return state
max_probability = 1 - 1e-5
for serving in range(1, servings + 1):
state = calculate(serving, serving)
if state > max_probability:
return 1.0
return calculate(servings, servings)
4.7.1701 - 2023-07-27 11:41:11 +0300 MSK
Links
Code
class Solution:
def distributeCookies(self, cookies: List[int], k: int) -> int:
cur = [0] * k
n = len(cookies)
def dfs(i, zero_count):
# If there are not enough cookies remaining, return `float('inf')`
# as it leads to an invalid distribution.
if n - i < zero_count:
return float('inf')
# After distributing all cookies, return the unfairness of this
# distribution.
if i == n:
return max(cur)
# Try to distribute the i-th cookie to each child, and update answer
# as the minimum unfairness in these distributions.
answer = float('inf')
for j in range(k):
zero_count -= int(cur[j] == 0)
cur[j] += cookies[i]
# Recursively distribute the next cookie.
answer = min(answer, dfs(i + 1, zero_count))
cur[j] -= cookies[i]
zero_count += int(cur[j] == 0)
return answer
return dfs(0, k)
4.7.1702 - 2023-07-27 11:39:36 +0300 MSK
Links
Code
class Solution:
def distributeCookies(self, cookies: List[int], k: int) -> int:
cur = [0] * k
n = len(cookies)
def dfs(i, zero_count):
# If there are not enough cookies remaining, return `float('inf')`
# as it leads to an invalid distribution.
if n - i < zero_count:
return float('inf')
# After distributing all cookies, return the unfairness of this
# distribution.
if i == n:
return max(cur)
# Try to distribute the i-th cookie to each child, and update answer
# as the minimum unfairness in these distributions.
answer = float('inf')
for j in range(k):
zero_count -= int(cur[j] == 0)
cur[j] += cookies[i]
# Recursively distribute the next cookie.
answer = min(answer, dfs(i + 1, zero_count))
cur[j] -= cookies[i]
zero_count += int(cur[j] == 0)
return answer
return dfs(0, k)
4.7.1703 - 2023-07-27 11:28:33 +0300 MSK
Links
Code
class Solution:
# n = 2, batteries = [3,3,3], Output: 4
# n = 2, batteries = [1,1,1,1], Output: 2
def maxRunTime(self, n: int, batteries: List[int]) -> int:
length = len(batteries)
if length < n:
return 0
if length == n:
return min(batteries)
batteries.sort()
extra = sum(batteries[:-n])
live = batteries[-n:]
# We increase the total running time using 'extra' by increasing
# the running time of the computer with the smallest battery.
for i in range(n - 1):
# If the target running time is between live[i] and live[i + 1].
if extra // (i + 1) < live[i + 1] - live[i]:
return live[i] + extra // (i + 1)
# Reduce 'extra' by the total power used.
extra -= (i + 1) * (live[i + 1] - live[i])
# If there is power left, we can increase the running time
# of all computers.
return live[-1] + extra // n
4.7.1704 - 2023-07-26 22:56:56 +0300 MSK
Links
Code
class Solution:
def minSpeedOnTime(self, dist: List[int], hour: float) -> int:
length = len(dist)
if hour >= sum(dist):
return 1
if hour <= length - 1:
return -1
time_remaining = hour - length + 1
max_speed = int(max(
max(dist), dist[-1] // time_remaining + 1
))
min_speed = 1
result = -1
while min_speed < max_speed:
speed = min_speed + (max_speed - min_speed) // 2
time = dist[-1] / speed + sum(
(distance + speed - 1) // speed
for distance in dist[:-1]
)
if time > hour:
min_speed = speed + 1
else:
max_speed = speed
return min_speed
4.7.1705 - 2023-07-25 16:45:40 +0300 MSK
Links
Code
class Solution:
# [0,3,2,1,0]
def peakIndexInMountainArray(self, arr: List[int]) -> int:
length = len(arr)
left, right = 0, length - 1
while left < right:
mid = left + (right - left) // 2
if arr[mid] < arr[mid + 1]:
left = mid + 1
else:
right = mid
return left
4.7.1706 - 2023-07-25 16:38:25 +0300 MSK
Links
Code
class Solution:
# [0,3,2,1,0]
def peakIndexInMountainArray(self, arr: List[int]) -> int:
length = len(arr)
left, right = 0, length - 1
while left <= right:
peak = left + (right - left) // 2
left_val, right_val = arr[peak-1], arr[peak+1]
peak_val = arr[peak]
if left_val < peak_val > right_val:
return peak
if right_val > peak_val:
left = peak + 1
else:
right = peak - 1
return left
4.7.1707 - 2023-07-24 21:17:10 +0300 MSK
Links
Code
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
length = len(s)
if length < 2:
return length
max_length, left, charset = 1, 0, set([s[0]])
for right in range(1, length):
letter = s[right]
if letter not in charset:
charset.add(letter)
continue
this_length = right - left
if this_length > max_length:
max_length = this_length
while letter in charset:
charset.remove(s[left])
left += 1
charset.add(letter)
return max(max_length, length - left)
4.7.1708 - 2023-07-24 21:04:18 +0300 MSK
Links
Code
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
length = len(s)
if length < 2:
return length
max_length = 0
start = 0
indexes = {s[0]: 0}
for end in range(1, length):
letter = s[end]
if letter not in indexes:
indexes[letter] = end
continue
this_length = end - start
if this_length > max_length:
max_length = this_length
letter_index = indexes[letter]
for remove_letter in s[start:letter_index]:
indexes.pop(remove_letter)
indexes[letter], start = end, letter_index + 1
return max(max_length, length - start)
4.7.1709 - 2023-07-24 20:07:58 +0300 MSK
Links
Code
class Solution:
def constructRectangle(self, area: int) -> List[int]:
return next([area//width, width]
for width in range(int(area**0.5), 0, -1)
if area % width == 0)
4.7.1710 - 2023-07-24 19:52:59 +0300 MSK
Links
Code
class Solution:
def findMaxConsecutiveOnes(self, nums: List[int]) -> int:
max_count, count = 0, 0
for number in nums:
if not number:
max_count = max(max_count, count)
count = 0
continue
count += 1
return max(max_count, count)
4.7.1711 - 2023-07-24 19:34:48 +0300 MSK
Links
Code
class Solution:
def licenseKeyFormatting(self, s: str, k: int) -> str:
result = []
count = 0
for letter in reversed(s):
if letter == "-":
continue
if count == k:
result.append("-")
count = 0
count += 1
result.append(letter.upper())
return "".join(reversed(result))
4.7.1712 - 2023-07-24 19:02:15 +0300 MSK
Links
Code
class Solution:
# "5F3Z-2e-9-w" -> "5F3Z2E9W" -> "5F3Z2E9W"
def licenseKeyFormatting(self, s: str, k: int) -> str:
letters = s.replace("-", "").upper()
result = []
end = len(letters)
while end > 0:
start = end - k
if start < 0:
start = 0
result.append(letters[start:end])
end -= k
return "-".join(reversed(result))
4.7.1713 - 2023-07-24 18:47:17 +0300 MSK
Links
Code
class Solution:
def islandPerimeter(self, grid: List[List[int]]) -> int:
perimeter = 0
last_row = len(grid) - 1
last_cell = len(grid[0]) - 1
for i, row in enumerate(grid):
for j, cell in enumerate(row):
if cell == 0:
continue
if j == 0 or row[j-1] == 0:
perimeter += 1
if j == last_cell or row[j+1] == 0:
perimeter += 1
if i == 0 or grid[i-1][j] == 0:
perimeter += 1
if i == last_row or grid[i+1][j] == 0:
perimeter += 1
return perimeter
4.7.1714 - 2023-07-24 16:56:56 +0300 MSK
Links
Code
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
return set(nums1).intersection(nums2)
4.7.1715 - 2023-07-24 16:56:13 +0300 MSK
Links
Code
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
return set(nums1) & set(nums2)
4.7.1716 - 2023-07-24 16:54:39 +0300 MSK
Links
Code
class Solution:
def findTheDifference(self, s: str, t: str) -> str:
letters = defaultdict(int)
for letter in s:
letters[letter] += 1
for letter in t:
if letters[letter] == 0:
return letter
letters[letter] -= 1
return None
4.7.1717 - 2023-07-24 16:51:33 +0300 MSK
Links
Code
class Solution:
def firstUniqChar(self, s: str) -> int:
counts = defaultdict(int)
repeated_index = len(s)
for letter in s:
counts[letter] += 1
for i, letter in enumerate(s):
if counts[letter] != 1:
continue
return i
return -1
4.7.1718 - 2023-07-24 16:49:38 +0300 MSK
Links
Code
class Solution:
def firstUniqChar(self, s: str) -> int:
counts = {}
repeated_index = len(s)
for i, letter in enumerate(s):
if letter in counts:
counts[letter] = repeated_index
continue
counts[letter] = i
result = repeated_index
for letter, index in counts.items():
if index == repeated_index:
continue
if index < result:
result = index
return result if result != repeated_index else -1
4.7.1719 - 2023-07-24 16:32:14 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def sumOfLeftLeaves(self, root: Optional[TreeNode]) -> int:
nodes = set([root])
result = 0
while nodes:
node = nodes.pop()
if node.left and not node.left.left and not node.left.right:
result += node.left.val
elif node.left:
nodes.add(node.left)
if node.right:
nodes.add(node.right)
return result
4.7.1720 - 2023-07-24 16:19:40 +0300 MSK
Links
Code
class Solution:
def longestPalindrome(self, s: str) -> int:
counts = defaultdict(int)
for letter in s:
counts[letter] += 1
result = sum(count if count % 2 == 0 else count - 1
for symbol, count in counts.items())
if result < len(s):
result += 1
return result
4.7.1721 - 2023-07-24 16:17:10 +0300 MSK
Links
Code
class Solution:
def longestPalindrome(self, s: str) -> int:
counts = defaultdict(int)
for letter in s:
counts[letter] += 1
result = 0
used_odd_letter = False
for letter, count in counts.items():
is_odd = count % 2 != 0
if is_odd and used_odd_letter:
result -= 1
elif is_odd:
used_odd_letter = True
result += count
return result
4.7.1722 - 2023-07-24 13:04:29 +0300 MSK
Links
Code
class Solution:
def thirdMax(self, nums: List[int]) -> int:
nums.sort(reverse=True)
number_max = nums[0]
count = 1
for i in range(1, len(nums)):
number = nums[i]
if number == nums[i-1]:
continue
count += 1
if count == 3:
return number
return number_max
4.7.1723 - 2023-07-24 13:03:31 +0300 MSK
Links
Code
class Solution:
def thirdMax(self, nums: List[int]) -> int:
nums.sort(reverse=True)
number_max = nums[0]
count = 1
for i in range(1, len(nums)):
number = nums[i]
if number == nums[i-1]:
continue
count += 1
if count == 3:
return number
if number > number_max:
number_max = number
return number_max
4.7.1724 - 2023-07-24 12:58:41 +0300 MSK
Links
Code
class Solution:
def addStrings(self, num1: str, num2: str) -> str:
result = []
index_1, index_2 = len(num1) - 1, len(num2) - 1
carry = 0
while index_1 >= 0 or index_2 >= 0 or carry:
digit_1 = num1[index_1] if index_1 >= 0 else 0
digit_2 = num2[index_2] if index_2 >= 0 else 0
digit = int(digit_1) + int(digit_2) + carry
if digit > 9:
carry = 1
digit %= 10
else:
carry = 0
result.append(str(digit))
index_1 -= 1
index_2 -= 1
return "".join(reversed(result))
4.7.1725 - 2023-07-24 12:56:22 +0300 MSK
Links
Code
class Solution:
def addStrings(self, num1: str, num2: str) -> str:
result = []
length_1, length_2 = len(num1), len(num2)
index_1, index_2 = length_1 - 1, length_2 - 1
carry = 0
while index_1 >= 0 or index_2 >= 0 or carry:
digit_1 = num1[index_1] if index_1 >= 0 else 0
digit_2 = num2[index_2] if index_2 >= 0 else 0
digit = int(digit_1) + int(digit_2) + carry
if digit > 9:
carry = 1
digit %= 10
else:
carry = 0
result.append(str(digit))
index_1 -= 1
index_2 -= 1
return "".join(reversed(result))
4.7.1726 - 2023-07-24 12:44:43 +0300 MSK
Links
Code
class Solution:
def findContentChildren(self, g: List[int], s: List[int]) -> int:
g.sort(reverse=True)
s.sort(reverse=True)
count = 0
cookie_index = 0
cookie_count = len(s)
for greed in g:
if cookie_index >= cookie_count or greed > s[cookie_index]:
continue
count += 1
cookie_index += 1
return count
4.7.1727 - 2023-07-24 12:40:04 +0300 MSK
Links
Code
class Solution:
def findContentChildren(self, g: List[int], s: List[int]) -> int:
greed = 0
g.sort(reverse=True)
s.sort(reverse=True)
children_count = len(g)
count = 0
for cookie_size in s:
while greed < children_count and g[greed] > cookie_size:
greed += 1
if greed >= children_count:
break
count += 1
greed += 1
return count
4.7.1728 - 2023-07-24 11:13:00 +0300 MSK
Links
Code
class Solution:
def myPow(self, x: float, n: int) -> float:
if n == 0:
return 1
if n < 0:
n *= -1
x = 1 / x
result = 1
while n:
if n % 2:
result *= x
n -= 1
x *= x
n //= 2
return result
4.7.1729 - 2023-07-23 21:12:51 +0300 MSK
Links
Code
class Solution:
# [1,1,3,4], [1,2,3,4] -> [2]
def findDisappearedNumbers(self, nums: List[int]) -> List[int]:
for number in nums:
index = abs(number) - 1
nums[index] = -1 * abs(nums[index])
return [number
for number in range(1, len(nums) + 1)
if nums[number-1] > 0]
4.7.1730 - 2023-07-23 21:01:06 +0300 MSK
Links
Code
class Solution:
# [1,1,3,4], [1,2,3,4] -> [2]
def findDisappearedNumbers(self, nums: List[int]) -> List[int]:
result = {number: True for number in range(1, len(nums) + 1)}
for number in nums:
result[number] = False
return [number for number, valid in result.items() if valid]
4.7.1731 - 2023-07-23 20:55:57 +0300 MSK
Links
Code
class Solution:
# [1,1,3,4], [1,2,3,4] -> [2]
def findDisappearedNumbers(self, nums: List[int]) -> List[int]:
nums.sort()
result = []
length = len(nums)
j = 0
for i in range(1, length + 1):
while j < length and nums[j] < i:
j += 1
if j < length and nums[j] == i:
continue
result.append(i)
return result
4.7.1732 - 2023-07-23 20:18:00 +0300 MSK
Links
Code
class Solution:
def arrangeCoins(self, n: int) -> int:
left, right = 0, n
while left <= right:
middle = left + (right - left) // 2
coins = middle * (middle + 1) // 2
if coins == n:
return middle
if coins > n:
right = middle - 1
else:
left = middle + 1
return right
4.7.1733 - 2023-07-23 20:03:43 +0300 MSK
Links
Code
class Solution:
def arrangeCoins(self, n: int) -> int:
count = 0
row = 1
while n >= row:
n -= row
row += 1
count += 1
return count
4.7.1734 - 2023-07-23 19:57:13 +0300 MSK
Links
Code
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def middleNode(self, head: Optional[ListNode]) -> Optional[ListNode]:
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
return slow
4.7.1735 - 2023-07-23 19:55:42 +0300 MSK
Links
Code
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def middleNode(self, head: Optional[ListNode]) -> Optional[ListNode]:
middle = head.next if head else None
tail = middle.next if middle else None
move = True
while tail and tail.next:
tail = tail.next
if move:
middle = middle.next
move = not move
return middle if middle else head
4.7.1736 - 2023-07-23 16:50:34 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def allPossibleFBT(self, n: int) -> List[TreeNode]:
if n % 2 == 0:
return []
if n == 1:
return [TreeNode()]
res = []
for i in range(1, n, 2):
left = self.allPossibleFBT(i)
right = self.allPossibleFBT(n - i - 1)
for l in left:
for r in right:
root = TreeNode(0, l, r)
res.append(root)
return res
4.7.1737 - 2023-07-22 19:09:00 +0300 MSK
Links
Code
class Solution:
# y x x
# x x x
# x x x: (2 / 8) * (4 / 16) = 0.0625
# (1/8, 1/8), (2/8, 2/8)
#
# x x x
# x y x
# x x x: 0
def __init__(self):
self.available_moves = (
(2, 1), (1, 2), (-2, 1), (-1, 2), (2, -1), (1, -2),
(-2, -1), (-1, -2)
)
def knightProbability(self, n: int, k: int, row: int, column: int) -> float:
if k < 1:
return 1
if n < 3:
return 0
return self.calculate(row, column, n, k)
@cache
def calculate(self, row: int, column: int, size: int,
moves_left: int) -> float:
if moves_left < 1:
return 1
probability = 0
for row_add, column_add in self.available_moves:
new_row = row_add + row
new_column = column_add + column
if new_row < 0 or new_row >= size or (
new_column < 0 or new_column >= size
):
continue
probability += self.calculate(
new_row, new_column, size, moves_left - 1
) / 8
return probability
4.7.1738 - 2023-07-22 17:36:35 +0300 MSK
Links
Code
class Solution:
def knightProbability(self, n: int, k: int, row: int, column: int) -> float:
# Define possible directions for the knight's moves
directions = [(1, 2), (1, -2), (-1, 2), (-1, -2),
(2, 1), (2, -1), (-2, 1), (-2, -1)]
# Initialize the dynamic programming table
dp = [[[0] * n for _ in range(n)] for _ in range(k + 1)]
dp[0][row][column] = 1
# Iterate over the number of moves
for moves in range(1, k + 1):
# Iterate over the cells on the chessboard
for i in range(n):
for j in range(n):
# Iterate over possible directions
for direction in directions:
prev_i, prev_j = i - direction[0], j - direction[1]
# Check if the previous cell is within the chessboard
if 0 <= prev_i < n and 0 <= prev_j < n:
# Add the previous probability
dp[moves][i][j] += dp[moves - 1][prev_i][prev_j]
# Divide by 8
dp[moves][i][j] /= 8
# Calculate total probability by summing probabilities for all cells
total_probability = sum(
dp[k][i][j]
for i in range(n)
for j in range(n)
)
return total_probability
4.7.1739 - 2023-07-21 16:55:34 +0300 MSK
Links
Code
class Solution:
def repeatedSubstringPattern(self, s: str) -> bool:
length = len(s)
for i in range(1, length // 2 + 1):
if length % i != 0:
continue
if s == s[:i] * (length // i):
return True
return False
4.7.1740 - 2023-07-21 16:53:22 +0300 MSK
Links
Code
class Solution:
def repeatedSubstringPattern(self, s: str) -> bool:
length = len(s)
for i in range(length-1):
if length % (i + 1) != 0:
continue
if s == s[:i+1] * (length // (i + 1)):
return True
return False
4.7.1741 - 2023-07-21 16:40:56 +0300 MSK
Links
Code
class Solution:
def addDigits(self, num: int) -> int:
sum = 0
while num > 0:
sum += num % 10
num //= 10
if num == 0 and sum > 9:
num, sum = sum, 0
return sum
4.7.1742 - 2023-07-21 16:40:33 +0300 MSK
Links
Code
class Solution:
def addDigits(self, num: int) -> int:
sum = 0
while num > 0:
sum += num % 10
num //= 10
if num == 0 and sum > 9:
num, sum = sum, 0
return sum
4.7.1743 - 2023-07-21 16:40:14 +0300 MSK
Links
Code
class Solution:
def addDigits(self, num: int) -> int:
sum = 0
while num > 0:
sum += num % 10
num //= 10
if num == 0 and sum > 9:
num, sum = sum, 0
return sum
4.7.1744 - 2023-07-21 16:36:57 +0300 MSK
Links
Code
class Solution:
def addDigits(self, num: int) -> int:
sum = num
while sum > 9:
current_number, current_sum = sum, 0
while current_number:
current_sum += current_number % 10
current_number //= 10
sum = current_sum
return sum
4.7.1745 - 2023-07-21 16:30:39 +0300 MSK
Links
Code
class MyQueue:
def __init__(self):
self.stack_in = []
self.stack_out = []
def push(self, x: int) -> None:
self.stack_in.append(x)
def pop(self) -> int:
self.peek()
return self.stack_out.pop()
def peek(self) -> int:
if self.stack_out:
return self.stack_out[-1]
while self.stack_in:
self.stack_out.append(self.stack_in.pop())
return self.stack_out[-1]
def empty(self) -> bool:
return not self.stack_out and not self.stack_in
# Your MyQueue object will be instantiated and called as such:
# obj = MyQueue()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.peek()
# param_4 = obj.empty()
4.7.1746 - 2023-07-21 16:20:49 +0300 MSK
Links
Code
class MyQueue:
def __init__(self):
self.queue = []
def push(self, x: int) -> None:
self.queue.insert(0, x)
def pop(self) -> int:
return self.queue.pop()
def peek(self) -> int:
return self.queue[-1]
def empty(self) -> bool:
return len(self.queue) == 0
# Your MyQueue object will be instantiated and called as such:
# obj = MyQueue()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.peek()
# param_4 = obj.empty()
4.7.1747 - 2023-07-21 16:09:40 +0300 MSK
Links
Code
class MyQueue:
def __init__(self):
self.queue = deque()
def push(self, x: int) -> None:
self.queue.appendleft(x)
def pop(self) -> int:
return self.queue.pop()
def peek(self) -> int:
return self.queue[-1]
def empty(self) -> bool:
return len(self.queue) == 0
# Your MyQueue object will be instantiated and called as such:
# obj = MyQueue()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.peek()
# param_4 = obj.empty()
4.7.1748 - 2023-07-21 16:06:08 +0300 MSK
Links
Code
class Solution:
def isPowerOfTwo(self, n: int) -> bool:
if n == 1:
return True
while n > 2 and not n % 2:
n //= 2
return n == 2
4.7.1749 - 2023-07-21 15:59:33 +0300 MSK
Links
Code
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]:
result = head
while head and head.next:
if head.next.val == head.val:
head.next = head.next.next
continue
head = head.next
return result
4.7.1750 - 2023-07-21 15:52:55 +0300 MSK
Links
Code
class Solution:
# 1: 1
# 2: 2
# 3: 3 [2(2), 1(1)]
# 4: 5 [3(3), (2)]
def climbStairs(self, n: int) -> int:
if n < 3:
return n
count, count_prev = 2, 1
for number in range(3, n + 1):
count, count_prev = count + count_prev, count
return count
4.7.1751 - 2023-07-21 15:33:25 +0300 MSK
Links
Code
class Solution:
def plusOne(self, digits: List[int]) -> List[int]:
carry = 1
for i in reversed(range(len(digits))):
new_digit = digits[i] + carry
if new_digit > 9:
carry = 1
new_digit %= 10
else:
carry = 0
digits[i] = new_digit
if carry:
digits.insert(0, carry)
return digits
4.7.1752 - 2023-07-21 13:34:45 +0300 MSK
Links
Code
class Solution:
def numberOfSteps(self, num: int) -> int:
count = 0
while num:
count += 1
if num % 2 == 0:
num /= 2
else:
num -= 1
return count
4.7.1753 - 2023-07-21 13:33:01 +0300 MSK
Links
Code
class Solution:
def fizzBuzz(self, n: int) -> List[str]:
result = []
for i in range(1, n + 1):
div_by_3, div_by_5 = i % 3 == 0, i % 5 == 0
value = None
if div_by_3 and div_by_5:
value = "FizzBuzz"
elif div_by_3:
value = "Fizz"
elif div_by_5:
value = "Buzz"
else:
value = str(i)
result.append(value)
return result
4.7.1754 - 2023-07-21 13:26:34 +0300 MSK
Links
Code
class Solution:
def maximumWealth(self, accounts: List[List[int]]) -> int:
max_wealth = 0
for i in range(len(accounts)):
wealth = 0
for j in range(len(accounts[i])):
wealth += accounts[i][j]
if wealth > max_wealth:
max_wealth = wealth
return max_wealth
4.7.1755 - 2023-07-21 13:23:06 +0300 MSK
Links
Code
class Solution:
def runningSum(self, nums: List[int]) -> List[int]:
for i in range(1, len(nums)):
nums[i] += nums[i-1]
return nums
4.7.1756 - 2023-07-21 13:19:55 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def checkTree(self, root: Optional[TreeNode]) -> bool:
return root.val == (root.left.val + root.right.val)
4.7.1757 - 2023-07-21 13:18:37 +0300 MSK
Links
Code
class Solution:
def sum(self, num1: int, num2: int) -> int:
return num1 + num2
4.7.1758 - 2023-07-21 13:11:37 +0300 MSK
Links
Code
class Solution:
def findNumberOfLIS(self, nums: List[int]) -> int:
n = len(nums)
if n <= 1:
return n
lengths = [1] * n
counts = [1] * n
for i in range(1, n):
for j in range(i):
if nums[i] > nums[j]:
if lengths[j] + 1 > lengths[i]:
lengths[i] = lengths[j] + 1
counts[i] = counts[j]
elif lengths[j] + 1 == lengths[i]:
counts[i] += counts[j]
max_length = max(lengths)
return sum(count for length, count in zip(lengths, counts) if length == max_length)
4.7.1759 - 2023-07-20 12:12:22 +0300 MSK
Links
Code
class Solution:
def asteroidCollision(self, asteroids: List[int]) -> List[int]:
stack = []
for asteroid in asteroids:
if asteroid > 0:
stack.append(asteroid)
continue
asteroid_abs = abs(asteroid)
while stack and stack[-1] > 0 and stack[-1] < asteroid_abs:
stack.pop()
if stack and stack[-1] == asteroid_abs:
stack.pop()
elif not stack or stack[-1] < 0:
stack.append(asteroid)
return stack
4.7.1760 - 2023-07-20 11:41:51 +0300 MSK
Links
Code
class Solution:
def asteroidCollision(self, asteroids: List[int]) -> List[int]:
length = len(asteroids)
if length < 2:
return asteroids
stack = [asteroids[0]]
for i in range(1, length):
asteroid = asteroids[i]
asteroid_last = stack[-1] if stack else 0
stack.append(asteroid)
if asteroid > 0 or (
asteroid < 0 and asteroid_last < 0
):
continue
while len(stack) >= 2 and stack[-1] < 0 and stack[-2] > 0:
last, prev = abs(stack[-1]), abs(stack[-2])
if last == prev:
stack.pop()
elif last > prev:
stack[-1], stack[-2] = stack[-2], stack[-1]
stack.pop()
return stack
4.7.1761 - 2023-07-19 14:35:52 +0300 MSK
Links
Code
class Solution:
def maxProfit(self, prices: List[int]) -> int:
# It is impossible to sell stock on first day, set -infinity as initial value for cur_hold
cur_hold, cur_not_hold = -float('inf'), 0
for stock_price in prices:
prev_hold, prev_not_hold = cur_hold, cur_not_hold
# either keep hold, or buy in stock today at stock price
cur_hold = max(prev_hold, prev_not_hold - stock_price)
# either keep not-hold, or sell out stock today at stock price
cur_not_hold = max(prev_not_hold,
prev_hold + stock_price)
# maximum profit must be in not-hold state
return cur_not_hold
4.7.1762 - 2023-07-19 14:26:39 +0300 MSK
Links
Code
class Solution:
def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
if sum(gas) < sum(cost):
return -1
tank, idx = 0, 0
for i in range(len(gas)):
tank += gas[i] - cost[i]
if tank < 0:
tank, idx = 0, i+1
return idx
4.7.1763 - 2023-07-19 14:19:51 +0300 MSK
Links
Code
class Solution:
def jump(self, nums: List[int]) -> int:
length = len(nums)
result = 0
end = 0
farthest = 0
for i in range(length - 1):
number = nums[i]
max_jump = i + number
if max_jump > farthest:
farthest = max_jump
if farthest >= length - 1:
result += 1
break
if i == end:
result += 1
end = farthest
return result
4.7.1764 - 2023-07-19 14:19:26 +0300 MSK
Links
Code
class Solution:
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
left = 0
sum_of_subarray = 0
min_length = float('inf')
for right in range(len(nums)):
sum_of_subarray += nums[right]
while sum_of_subarray >= target:
min_length = min(min_length, right - left + 1)
sum_of_subarray -= nums[left]
left += 1
if min_length == float('inf'):
return 0
return min_length
4.7.1765 - 2023-07-19 13:39:31 +0300 MSK
Links
Code
class Solution:
# [3,0,6,1,5]
# [0,1,3,5,6]
def hIndex(self, citations: List[int]) -> int:
citations = sorted(citations)
length = len(citations)
h = 0
for i in reversed(range(length)):
citations_count = citations[i]
published_count = length - i
if citations_count == 0 or published_count < h:
break
if published_count <= citations_count:
h = published_count
return h
4.7.1766 - 2023-07-19 12:33:23 +0300 MSK
Links
Code
class Solution:
def convert(self, s: str, numRows: int) -> str:
if numRows < 2:
return s
result: List[List[str]] = [[] for _ in range(numRows)]
row, is_ascending, last = 0, True, numRows - 1
for symbol in s:
result[row].append(symbol)
if is_ascending and row < last:
row += 1
elif is_ascending:
is_ascending = False
if is_ascending:
continue
if row > 0:
row -= 1
else:
is_ascending = True
row = 1
return "".join("".join(row) for row in result)
4.7.1767 - 2023-07-19 11:49:03 +0300 MSK
Links
Code
class RandomizedSet:
def __init__(self):
self._set = set()
self._items = []
self._indexes = {}
def insert(self, val: int) -> bool:
is_in = val in self._set
if not is_in:
self._set.add(val)
self._items.append(val)
self._indexes[val] = len(self._items) - 1
return not is_in
def remove(self, val: int) -> bool:
if val not in self._set:
return False
last = self._items[-1]
val_index = self._indexes[val]
self._items[val_index] = last
self._indexes[last] = val_index
self._set.remove(val)
self._items.pop()
self._indexes.pop(val)
return True
def getRandom(self) -> int:
return random.choice(self._items)
# Your RandomizedSet object will be instantiated and called as such:
# obj = RandomizedSet()
# param_1 = obj.insert(val)
# param_2 = obj.remove(val)
# param_3 = obj.getRandom()
4.7.1768 - 2023-07-19 11:34:17 +0300 MSK
Links
Code
class Solution:
def canJump(self, nums: List[int]) -> bool:
length = len(nums)
if length < 2:
return True
current = nums[0]
for i in range(1, length):
if current == 0:
return False
current -= 1
current = max(current, nums[i])
return True
4.7.1769 - 2023-07-19 11:26:05 +0300 MSK
Links
Code
class Solution:
def letterCombinations(self, digits: str) -> List[str]:
length = len(digits)
if length == 0:
return []
digit_map: Dict[int, str] = {
1: [],
2: ["a", "b", "c"],
3: ["d", "e", "f"],
4: ["g", "h", "i"],
5: ["j", "k", "l"],
6: ["m", "n", "o"],
7: ["p", "q", "r", "s"],
8: ["t", "u", "v"],
9: ["w", "x", "y", "z"],
0: [" "]
}
result: List[List[str]] = [
digit_map[int(digit)] for digit in digits
]
return ["".join(i) for i in product(*result)]
4.7.1770 - 2023-07-19 11:25:19 +0300 MSK
Links
Code
class Solution:
def letterCombinations(self, digits: str) -> List[str]:
length = len(digits)
if length == 0:
return []
digit_map: Dict[int, str] = {
1: [],
2: ["a", "b", "c"],
3: ["d", "e", "f"],
4: ["g", "h", "i"],
5: ["j", "k", "l"],
6: ["m", "n", "o"],
7: ["p", "q", "r", "s"],
8: ["t", "u", "v"],
9: ["w", "x", "y", "z"],
0: [" "]
}
result: List[List[str]] = [
digit_map[int(digit)] for digit in digits
]
return ["".join(i) for i in product(*result)]
4.7.1771 - 2023-07-19 11:14:44 +0300 MSK
Links
Code
class Solution:
def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:
intervals = sorted(intervals, key=lambda element: element[1])
length = len(intervals)
prev, count = 0, 1
for i in range(1, length):
if intervals[i][0] < intervals[prev][1]:
continue
prev = i
count += 1
return length - count
4.7.1772 - 2023-07-18 18:51:03 +0300 MSK
Links
Code
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
# create the result pointer that points towards one of the lists
# create the result root pointer that will point towards the root of the result list
# 1. start infinite loop
# 2. if result is false - break, we reached the end
# 3. get values from non-empty pointers
# 4. add values together, store the carry in a variable
# 5. store the value in the result pointer
# 6. move the result pointer to the next node, if there is no next node, use a node from
# another list
# 7. move list pointers
# 8. if we have a carry left, add a node to the result list
def addTwoNumbers(self, l1: Optional[ListNode],
l2: Optional[ListNode]) -> Optional[ListNode]:
carry = 0
result, result_root = l1, l1
while True:
if not l1 and not l2:
break
number_1 = l1.val if l1 else 0
number_2 = l2.val if l2 else 0
result_val = number_1 + number_2 + carry
if result_val > 9:
carry, result_val = 1, result_val - 10
else:
carry = 0
result.val = result_val
if not result.next and l2:
l1 = None
result.next = l2.next
if result.next:
result = result.next
if l1:
l1 = l1.next
if l2:
l2 = l2.next
if carry:
result.next = ListNode(carry)
return result_root
4.7.1773 - 2023-07-18 18:50:17 +0300 MSK
Links
Code
class LRUCache:
class Node:
def __init__(self, key: str, val: int) -> None:
self.key = key
self.val = val
self.prev: Node = None
self.next: Node = None
def __init__(self, capacity: int) -> None:
self.cap = capacity
self.head = self.Node(-1, -1)
self.tail = self.Node(-1, -1)
self.head.next = self.tail
self.tail.prev = self.head
self.cache = {}
def add_node(self, new_node: Node) -> None:
old_first_node = self.head.next
new_node.next = old_first_node
new_node.prev = self.head
self.head.next = new_node
old_first_node.prev = new_node
def delete_node(self, delete_node: Node) -> None:
prev = delete_node.prev
next = delete_node.next
prev.next = next
next.prev = prev
def get(self, key: int) -> int:
if key not in self.cache:
return -1
result_node = self.cache[key]
result = result_node.val
del self.cache[key]
self.delete_node(result_node)
self.add_node(result_node)
self.cache[key] = self.head.next
return result
def put(self, key: int, value: int) -> None:
if key in self.cache:
current = self.cache[key]
del self.cache[key]
self.delete_node(current)
if len(self.cache) == self.cap:
del self.cache[self.tail.prev.key]
self.delete_node(self.tail.prev)
self.add_node(self.Node(key, value))
self.cache[key] = self.head.next
# Your LRUCache object will be instantiated and called as such:
# obj = LRUCache(capacity)
# param_1 = obj.get(key)
# obj.put(key,value)
4.7.1774 - 2023-07-18 18:39:57 +0300 MSK
Links
Code
class LRUCache:
class Node:
def __init__(self, key: str, val: int) -> None:
self.key = key
self.val = val
self.prev: Node = None
self.next: Node = None
def __init__(self, capacity: int) -> None:
self.cap = capacity
self.head = self.Node(-1, -1)
self.tail = self.Node(-1, -1)
self.head.next = self.tail
self.tail.prev = self.head
self.cache = {}
def add_node(self, new_node: Node) -> None:
old_first_node = self.head.next
new_node.next = old_first_node
new_node.prev = self.head
self.head.next = new_node
old_first_node.prev = new_node
def delete_node(self, delete_node: Node) -> None:
prev = delete_node.prev
next = delete_node.next
prev.next = next
next.prev = prev
def get(self, key: int) -> int:
if key not in self.cache:
return -1
result_node = self.cache[key]
result = result_node.val
del self.cache[key]
self.delete_node(result_node)
self.add_node(result_node)
self.cache[key] = self.head.next
return result
def put(self, key: int, value: int) -> None:
if key in self.cache:
current = self.cache[key]
del self.cache[key]
self.delete_node(current)
if len(self.cache) == self.cap:
del self.cache[self.tail.prev.key]
self.delete_node(self.tail.prev)
self.add_node(self.Node(key, value))
self.cache[key] = self.head.next
# Your LRUCache object will be instantiated and called as such:
# obj = LRUCache(capacity)
# param_1 = obj.get(key)
# obj.put(key,value)
4.7.1775 - 2023-07-18 18:25:23 +0300 MSK
Links
Code
class Solution:
def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
length_vertical, length_horizontal = len(matrix), len(matrix[0])
left, right = 0, length_vertical - 1
while left <= right:
mid = left + (right - left) // 2
mid_number = matrix[mid][0]
if mid_number == target:
return True
if mid_number > target:
right = mid - 1
else:
left = mid + 1
vertical_index = right
left, right = 0, length_horizontal - 1
while left <= right:
mid = left + (right - left) // 2
mid_number = matrix[vertical_index][mid]
if mid_number == target:
return True
if mid_number > target:
right = mid - 1
else:
left = mid + 1
return False
4.7.1776 - 2023-07-18 18:14:47 +0300 MSK
Links
Code
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
length = len(nums)
left, right = 0, length - 1
while left <= right:
mid = left + (right - left) // 2
mid_number = nums[mid]
if mid_number == target:
return mid
if mid_number > target:
right = mid - 1
else:
left = mid + 1
return left
4.7.1777 - 2023-07-18 18:10:20 +0300 MSK
Links
Code
class Solution:
def mySqrt(self, x: int) -> int:
if x == 0 or x == 1:
return x
left, right = 1, x
while left <= right:
mid = left + (right - left) // 2
square = mid * mid
if square == x:
return mid
if square > x:
right = mid - 1
else:
left = mid + 1
return right
4.7.1778 - 2023-07-18 18:02:32 +0300 MSK
Links
Code
class Solution:
def isPalindrome(self, x: int) -> bool:
if x < 0:
return False
if x < 10:
return True
number = []
while x:
remainder = x % 10
x = x // 10
number.append(remainder)
length = len(number)
half_index = length // 2
for i, digit in enumerate(number):
last_digit = number[length - i - 1]
if digit != last_digit:
return False
if i != half_index:
continue
return True
4.7.1779 - 2023-07-18 18:01:12 +0300 MSK
Links
Code
class Solution:
def isPalindrome(self, x: int) -> bool:
if x < 0:
return False
if x < 10:
return True
number = []
while x:
remainder = x % 10
x = x // 10
number.append(remainder)
length = len(number)
half_index = length // 2
for i, digit in enumerate(number):
last_digit = number[length - i - 1]
if digit != last_digit:
return False
if i != half_index:
continue
return True
4.7.1780 - 2023-07-18 17:58:35 +0300 MSK
Links
Code
class Solution:
def evalRPN(self, tokens: List[str]) -> int:
stack = []
operations = {
"+": lambda first, second: first + second,
"-": lambda first, second: first - second,
"*": lambda first, second: first * second,
"/": lambda first, second: int(first / second)
}
for token in tokens:
if token not in operations:
stack.append(int(token))
continue
second, first = stack.pop(), stack.pop()
result = operations[token](first, second)
stack.append(result)
return stack[-1]
4.7.1781 - 2023-07-18 17:57:21 +0300 MSK
Links
Code
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reverse(self, head: ListNode) -> ListNode:
previous = None
while head:
next, head.next = head.next, previous
previous, head = head, next
return previous
def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
l1, l2 = self.reverse(l1), self.reverse(l2)
head, tail, carry = l1, l1, 0
while l1 or l2 or carry:
val_1 = l1.val if l1 else 0
val_2 = l2.val if l2 else 0
sum = val_1 + val_2 + carry
if sum > 9:
carry = 1
sum %= 10
else:
carry = 0
tail.val = sum
l1, l2 = l1.next if l1 else None, l2.next if l2 else None
if not tail.next and l2:
tail.next = l2
l1 = None
if not tail.next and carry:
tail.next = ListNode(carry)
carry = 0
l2 = None
if tail.next:
tail = tail.next
return self.reverse(head)
4.7.1782 - 2023-07-18 17:10:30 +0300 MSK
Links
Code
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
previous = None
while head:
next, head.next = head.next, previous
previous, head = head, next
return previous
4.7.1783 - 2023-07-18 16:55:29 +0300 MSK
Links
Code
class Solution:
def twoSum(self, numbers: List[int], target: int) -> List[int]:
numbers_map: Dict[str, int] = {}
for i, number in enumerate(numbers):
diff = target - number
if diff in numbers_map:
return [numbers_map[diff] + 1, i + 1]
numbers_map[number] = i
return []
4.7.1784 - 2023-07-18 16:41:40 +0300 MSK
Links
Code
class Solution:
def reverseWords(self, s: str) -> str:
return " ".join(s.split()[::-1])
4.7.1785 - 2023-07-18 16:37:43 +0300 MSK
Links
Code
class Solution:
def intToRoman(self, num: int) -> str:
result: List[str] = []
stack: List[int] = deque([
1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000
])
values = {
1000: "M",
900: "CM",
500: "D",
400: "CD",
100: "C",
90: "XC",
50: "L",
40: "XL",
10: "X",
9: "IX",
5: "V",
4: "IV",
1: "I"
}
while num:
roman = stack[-1]
if num < roman:
stack.pop()
continue
result.append(values[roman])
num -= roman
return "".join(result)
4.7.1786 - 2023-07-18 16:15:43 +0300 MSK
Links
Code
class Solution:
def evalRPN(self, tokens: List[str]) -> int:
stack = []
operations = {
"+": lambda first, second: first + second,
"-": lambda first, second: first - second,
"*": lambda first, second: first * second,
"/": lambda first, second: int(first / second)
}
for token in tokens:
if token not in operations:
stack.append(int(token))
continue
second, first = stack.pop(), stack.pop()
result = operations[token](first, second)
stack.append(result)
return stack[-1]
4.7.1787 - 2023-07-18 15:49:17 +0300 MSK
Links
Code
from sortedcontainers import sortedset
class MinStack:
def __init__(self):
self.stack: List[int] = []
self.min_stack: List[int] = []
def push(self, val: int) -> None:
self.stack.append(val)
if not self.min_stack or val <= self.min_stack[-1]:
self.min_stack.append(val)
def pop(self) -> None:
if not self.stack:
return
pop = self.stack.pop()
if pop == self.min_stack[-1]:
self.min_stack.pop()
def top(self) -> int:
return self.stack[-1]
def getMin(self) -> int:
return self.min_stack[-1]
# Your MinStack object will be instantiated and called as such:
# obj = MinStack()
# obj.push(val)
# obj.pop()
# param_3 = obj.top()
# param_4 = obj.getMin()
4.7.1788 - 2023-07-18 15:46:05 +0300 MSK
Links
Code
from sortedcontainers import sortedset
class MinStack:
class Node:
def __init__(self, val: int, prev: 'Node'):
self.val = val
self.prev = prev
def __init__(self):
self.stack: List[Node] = []
self.min_node = None
def push(self, val: int) -> None:
new_node = self.Node(val, None)
self.stack.append(new_node)
if self.min_node is None or val <= self.min_node.val:
new_node.prev = self.min_node
self.min_node = new_node
def pop(self) -> None:
pop = self.stack.pop()
if pop == self.min_node:
self.min_node = self.min_node.prev
def top(self) -> int:
return self.stack[-1].val
def getMin(self) -> int:
return self.min_node.val
# Your MinStack object will be instantiated and called as such:
# obj = MinStack()
# obj.push(val)
# obj.pop()
# param_3 = obj.top()
# param_4 = obj.getMin()
4.7.1789 - 2023-07-18 15:23:22 +0300 MSK
Links
Code
class Solution:
def simplifyPath(self, path: str) -> str:
canonical = []
for directory in path.split("/"):
if not directory or directory == ".":
continue
if directory != "..":
canonical.append(directory)
continue
if len(canonical):
canonical.pop()
return "/" + "/".join(canonical)
4.7.1790 - 2023-07-18 15:15:34 +0300 MSK
Links
Code
class Solution:
def longestConsecutive(self, nums: List[int]) -> int:
length = len(nums)
if length < 2:
return length
nums = set(nums)
longest = 1
for number in nums:
if number - 1 in nums:
continue
consequent = 1
while number + consequent in nums:
consequent += 1
longest = max(longest, consequent)
return longest
4.7.1791 - 2023-07-18 15:08:44 +0300 MSK
Links
Code
from sortedcontainers import SortedSet
class Solution:
def longestConsecutive(self, nums: List[int]) -> int:
nums = SortedSet(nums)
longest, current = 0, 0
for number in nums:
if number - 1 in nums:
current += 1
continue
if current > longest:
longest = current
current = 1
return max(current, longest)
4.7.1792 - 2023-07-18 14:53:17 +0300 MSK
Links
Code
class Solution:
def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
anagrams: Dict[str, List[str]] = defaultdict(list)
for string in strs:
anagrams["".join(sorted(string))].append(string)
return anagrams.values()
4.7.1793 - 2023-07-18 14:46:38 +0300 MSK
Links
Code
class LRUCache:
class Node:
def __init__(self, key: str, val: int) -> None:
self.key = key
self.val = val
self.prev: Node = None
self.next: Node = None
def __init__(self, capacity: int) -> None:
self.cap = capacity
self.head = self.Node(-1, -1)
self.tail = self.Node(-1, -1)
self.head.next = self.tail
self.tail.prev = self.head
self.cache = {}
def add_node(self, new_node: Node) -> None:
old_first_node = self.head.next
new_node.next = old_first_node
new_node.prev = self.head
self.head.next = new_node
old_first_node.prev = new_node
def delete_node(self, delete_node: Node) -> None:
prev = delete_node.prev
next = delete_node.next
prev.next = next
next.prev = prev
def get(self, key: int) -> int:
if key not in self.cache:
return -1
result_node = self.cache[key]
result = result_node.val
del self.cache[key]
self.delete_node(result_node)
self.add_node(result_node)
self.cache[key] = self.head.next
return result
def put(self, key: int, value: int) -> None:
if key in self.cache:
current = self.cache[key]
del self.cache[key]
self.delete_node(current)
if len(self.cache) == self.cap:
del self.cache[self.tail.prev.key]
self.delete_node(self.tail.prev)
self.add_node(self.Node(key, value))
self.cache[key] = self.head.next
# Your LRUCache object will be instantiated and called as such:
# obj = LRUCache(capacity)
# param_1 = obj.get(key)
# obj.put(key,value)
4.7.1794 - 2023-07-18 13:48:20 +0300 MSK
Links
Code
class Solution:
def rotate(self, nums: List[int], k: int) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
length = len(nums)
k %= length
nums[length - k:] = nums[length - k:][::-1]
nums[:length - k] = nums[:length - k][::-1]
nums[:] = nums[::-1]
4.7.1795 - 2023-07-16 19:26:31 +0300 MSK
Links
Code
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
length = len(nums)
if length < 2:
return length
current_index = 2
for number in nums[2:]:
if number == nums[current_index-2]:
continue
nums[current_index] = number
current_index += 1
return current_index
4.7.1796 - 2023-07-16 19:19:33 +0300 MSK
Links
Code
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
length = len(nums)
if length < 2:
return length
current_number, unique, current_index = nums[0], True, 1
for number in nums[1:]:
if current_number != number:
current_number = number
unique = True
nums[current_index] = number
current_index += 1
continue
if unique:
nums[current_index] = number
current_index += 1
unique = False
return current_index
4.7.1797 - 2023-07-16 18:35:46 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def isSameTree(self, p: Optional[TreeNode], q: Optional[TreeNode]) -> bool:
if p and not q or (q and not p):
return False
if not p and not q:
return True
if p.val != q.val:
return False
return self.isSameTree(p.left, q.left) and self.isSameTree(p.right, q.right)
4.7.1798 - 2023-07-16 15:06:38 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def maxDepth(self, root: Optional[TreeNode], depth: int = 0) -> int:
if not root:
return depth
return max(self.maxDepth(root.left, depth + 1), self.maxDepth(root.right, depth + 1))
4.7.1799 - 2023-07-16 15:04:36 +0300 MSK
Links
Code
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def maxDepth(self, root: Optional[TreeNode], count: int = 0) -> int:
if not root:
return 0
if not root.left and not root.right:
return count + 1
return max(self.maxDepth(root.left, count + 1), self.maxDepth(root.right, count + 1))
4.7.1800 - 2023-07-16 13:34:50 +0300 MSK
Links
Code
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
if not list1:
return list2
if not list2:
return list1
head = None
if list1.val < list2.val:
head, list1 = list1, list1.next
else:
head, list2 = list2, list2.next
current = head
while list1 and list2:
if list1.val < list2.val:
current.next, list1 = list1, list1.next
else:
current.next, list2 = list2, list2.next
current = current.next
if list1 or list2:
current.next = list1 if list1 else list2
return head
4.7.1801 - 2023-07-16 12:53:42 +0300 MSK
Links
Code
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def hasCycle(self, head: Optional[ListNode]) -> bool:
slow_p, fast_p = head, head.next if head else None
while fast_p and fast_p.next:
if slow_p == fast_p:
return True
slow_p, fast_p = slow_p.next, fast_p.next.next
return False
4.7.1802 - 2023-07-16 12:51:01 +0300 MSK
Links
Code
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def hasCycle(self, head: Optional[ListNode]) -> bool:
slow_p, fast_p = head, head.next if head else None
while slow_p and fast_p:
if slow_p == fast_p:
return True
slow_p = slow_p.next
fast_p = fast_p.next if fast_p else None
fast_p = fast_p.next if fast_p else None
return False
4.7.1803 - 2023-07-16 12:38:36 +0300 MSK
Links
Code
class Solution:
def isValid(self, s: str) -> bool:
length = len(s)
if length < 2:
return False
brackets_open = {
"{": "}",
"(": ")",
"[": "]"
}
brackets_close = brackets_open.values()
stack = [s[0]]
for bracket in s[1:]:
if bracket not in brackets_close:
stack.append(bracket)
continue
if len(stack) == 0 or brackets_open.get(stack[-1]) != bracket:
return False
stack.pop()
return not len(stack)
4.7.1804 - 2023-07-16 12:17:02 +0300 MSK
Links
Code
class Solution:
def containsNearbyDuplicate(self, nums: List[int], k: int) -> bool:
indexes = {}
for i, number in enumerate(nums):
if number in indexes and abs(i - indexes[number]) <= k:
return True
indexes[number] = i
return False
4.7.1805 - 2023-07-16 12:16:10 +0300 MSK
Links
Code
class Solution:
def containsNearbyDuplicate(self, nums: List[int], k: int) -> bool:
indexes = defaultdict(set)
for i, number in enumerate(nums):
if number in indexes and any(abs(i - j) <= k for j in indexes[number]):
return True
indexes[number].add(i)
return False
4.7.1806 - 2023-07-16 10:47:21 +0300 MSK
Links
Code
class Solution:
def isHappy(self, n: int) -> bool:
sums = set()
while n != 1:
if n in sums:
return False
sums.add(n)
sum = 0
while n > 0:
sum += (n % 10 )**2
n = n // 10
n = sum
return True
4.7.1807 - 2023-07-16 10:41:43 +0300 MSK
Links
Code
class Solution:
def isHappy(self, n: int) -> bool:
while True:
sum = 0
while n > 0:
sum += (n % 10 )**2
n = n // 10
n = sum
if sum < 10:
break
return n in [1, 7]
4.7.1808 - 2023-07-16 10:41:26 +0300 MSK
Links
Code
class Solution:
def isHappy(self, n: int) -> bool:
while True:
sum = 0
while n > 0:
sum += (n % 10 )**2
n = n // 10
n = sum
print(n)
if sum < 10:
break
return n in [1, 7]
4.7.1809 - 2023-07-15 21:24:48 +0300 MSK
Links
Code
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
indexes = {}
for i, number in enumerate(nums):
diff = target - number
if diff in indexes:
return [indexes[diff], i]
indexes[number] = i
4.7.1810 - 2023-07-15 21:22:16 +0300 MSK
Links
Code
class Solution:
def isAnagram(self, s: str, t: str) -> bool:
s_length, t_length = len(s), len(t)
if s_length != t_length:
return False
count = defaultdict(int)
for i, s_symbol in enumerate(s):
t_symbol = t[i]
count[s_symbol] += 1
count[t_symbol] -= 1
return not any((i != 0 for i in count.values()))
4.7.1811 - 2023-07-15 21:11:36 +0300 MSK
Links
Code
class Solution:
def wordPattern(self, pattern: str, s: str) -> bool:
words = s.split()
words_length, pattern_length = len(words), len(pattern)
if words_length != pattern_length:
return False
symbol_to_word = {}
word_to_symbol = {}
for i, symbol in enumerate(pattern):
word = words[i]
symbol_in, word_in = symbol in symbol_to_word, word in word_to_symbol
if symbol_in and word_in and symbol_to_word[symbol] == word:
continue
if not symbol_in and not word_in:
symbol_to_word[symbol] = word
word_to_symbol[word] = symbol
continue
return False
return True
4.7.1812 - 2023-07-15 20:53:31 +0300 MSK
Links
Code
class Solution:
def isIsomorphic(self, s: str, t: str) -> bool:
s_length, t_length = len(s), len(t)
if s_length != t_length:
return False
s_to_t = {}
t_to_s = {}
for i, s_symbol in enumerate(s):
t_symbol = t[i]
if s_symbol not in s_to_t and t_symbol not in t_to_s:
s_to_t[s_symbol] = t_symbol
t_to_s[t_symbol] = s_symbol
elif s_symbol in s_to_t and s_to_t[s_symbol] == t_symbol:
continue
else:
return False
return True
4.7.1813 - 2023-07-15 20:49:31 +0300 MSK
Links
Code
class Solution:
def isIsomorphic(self, s: str, t: str) -> bool:
return list(map(s.index, s)) == list(map(t.index, t))
4.7.1814 - 2023-07-15 20:05:44 +0300 MSK
Links
Code
class Solution:
def canConstruct(self, ransomNote: str, magazine: str) -> bool:
ransom_i, magazine_i = 0, 0
ransom_length, magazine_length = len(ransomNote), len(magazine)
if magazine_length < ransom_length:
return False
if ransom_length == 1:
return ransomNote in magazine
symbols = [0 for _ in range(26)]
for symbol in magazine:
symbols[ord(symbol)-97] += 1
for symbol in ransomNote:
symbols[ord(symbol)-97] -= 1
return not any((count < 0 for count in symbols))
4.7.1815 - 2023-07-15 19:55:32 +0300 MSK
Links
Code
class Solution:
# two indexes: ransom_i, magazine_i
# sort both ransomNote and magazine (ascending order)
# while indexes have not reached the end:
# - if ransom symbol is equal to the magazine_symbol: increase both indexes
# - if it is not equal, increase only magazine index
# return wheter the ranson index is equal to the length of the ransom
def canConstruct(self, ransomNote: str, magazine: str) -> bool:
ransom_i, magazine_i = 0, 0
ransom_length, magazine_length = len(ransomNote), len(magazine)
if magazine_length < ransom_length:
return False
if ransom_length == 1:
return ransomNote in magazine
ransomNote = sorted(ransomNote)
magazine = sorted(magazine)
while ransom_i < ransom_length and magazine_i < magazine_length:
ransom_symbol, magazine_symbol = ransomNote[ransom_i], magazine[magazine_i]
if magazine_symbol > ransom_symbol:
return False
if ransom_symbol == magazine_symbol:
ransom_i += 1
magazine_i += 1
return ransom_i == ransom_length
4.7.1816 - 2023-07-15 19:35:16 +0300 MSK
Links
Code
class Solution:
# two indexes: ransom_i, magazine_i
# sort both ransomNote and magazine (ascending order)
# while indexes have not reached the end:
# - if ransom symbol is equal to the magazine_symbol: increase both indexes
# - if it is not equal, increase only magazine index
# return wheter the ranson index is equal to the length of the ransom
def canConstruct(self, ransomNote: str, magazine: str) -> bool:
ransom_i, magazine_i = 0, 0
ransom_length, magazine_length = len(ransomNote), len(magazine)
ransomNote = sorted(ransomNote)
magazine = sorted(magazine)
if magazine_length < ransom_length:
return False
while ransom_i < ransom_length and magazine_i < magazine_length:
ransom_symbol, magazine_symbol = ransomNote[ransom_i], magazine[magazine_i]
if ransom_symbol == magazine_symbol:
ransom_i += 1
magazine_i += 1
return ransom_i == ransom_length
4.7.1817 - 2023-07-13 21:11:33 +0300 MSK
Links
Code
class Solution:
# create two pointers, original and sub, both are zero
# while either of those pointers have not reached the end:
# - if original symbol is equal to the sub, move both pointer to the right
# - if not, move original pointer to the right
# if sub pointer reached the end, return True, otherwise False
def isSubsequence(self, s: str, t: str) -> bool:
original, sub = 0, 0
original_length, sub_length = len(t), len(s)
while original < original_length and sub < sub_length:
if s[sub] == t[original]:
original += 1
sub += 1
continue
original += 1
return sub == sub_length
4.7.1818 - 2023-07-13 20:57:51 +0300 MSK
Links
Code
class Solution:
def longestCommonPrefix(self, strs: List[str]) -> str:
if len(strs) == 1:
return strs[0]
min_length = min([len(string) for string in strs])
prefix = strs[0][0:min_length]
for string in strs:
if not prefix:
return ""
while not string.startswith(prefix):
prefix = prefix[0:-1]
return prefix
4.7.1819 - 2023-07-13 20:49:03 +0300 MSK
Links
Code
class Solution:
def longestCommonPrefix(self, strs: List[str]) -> str:
if len(strs) == 1:
return strs[0]
min_length = min([len(string) for string in strs])
for i in range(min_length, -1, -1):
current = strs[0][0:i+1]
for string in strs[1:]:
if string[0:i+1] != current:
break
else:
return current
return ""
4.7.1820 - 2023-07-13 20:34:54 +0300 MSK
Links
Code
class Solution:
def romanToInt(self, input_numbers: str) -> int:
result = 0
previous = None
values = {
"I": 1,
"V": 5,
"X": 10,
"L": 50,
"C": 100,
"D": 500,
"M": 1000,
}
subtractions = set(["IV", "IX", "XL", "XC", "CD", "CM"])
for number in input_numbers:
if f"{previous}{number}" in subtractions:
result += values[number] - values[previous] * 2
else:
result += values[number]
previous = number
return result
4.7.1821 - 2023-07-13 20:32:03 +0300 MSK
Links
Code
class Solution:
def majorityElement(self, nums: List[int]) -> int:
return sorted(nums)[len(nums)//2]
4.7.1822 - 2023-07-13 20:30:18 +0300 MSK
Links
Code
class Solution:
# Input: prices = [7,1,5,3,6,4]
# Output: 5
# Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5.
# Note that buying on day 2 and selling on day 1 is not allowed because you must buy
# before you sell.
def maxProfit(self, prices: List[int]) -> int:
length = len(prices)
if length < 2:
return 0
left, right, profit = 0, 1, 0
while right < length:
current_profit = prices[right] - prices[left]
is_profitable = current_profit > 0
if is_profitable and current_profit > profit:
profit = current_profit
elif not is_profitable:
left = right
right += 1
return profit
4.7.1823 - 2023-07-13 20:19:45 +0300 MSK
Links
Code
class Solution:
# Input: prices = [7,1,5,3,6,4]
# Output: 5
# Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5.
# Note that buying on day 2 and selling on day 1 is not allowed because you must buy
# before you sell.
def maxProfit(self, prices: List[int]) -> int:
length = len(prices)
if length < 2:
return 0
left, right, profit = 0, 1, 0
while right < length:
current_profit = prices[right] - prices[left]
if current_profit > 0:
profit = max(current_profit, profit)
else:
left = right
right += 1
return profit
4.7.1824 - 2023-07-13 19:37:36 +0300 MSK
Links
Code
class Solution:
def majorityElement(self, nums: List[int]) -> int:
return sorted(nums)[len(nums)//2]
4.7.1825 - 2023-07-13 19:13:31 +0300 MSK
Links
Code
class Solution:
# non-decreasing order, so to remove the duplicates we just need to remove all
# consequent duplicates
# create replace index, set it to 1 - the first element is always unique
# check if length is more than 1 to avoid out-of-bounds -
# if the length is one, just return 1
# iterate over nums starting from the second element:
# - if the current number is not equal to the previous,
# set nums[replace] to it, move the replace index
# - if the current number is equal to the previous one, continue
# return replace
def removeDuplicates(self, nums: List[int]) -> int:
replace = 1
for i, number in enumerate(nums[1:], 1):
if number == nums[i-1]:
continue
nums[replace] = number
replace += 1
return replace
4.7.1826 - 2023-07-13 19:03:15 +0300 MSK
Links
Code
class Solution:
# non-decreasing order, so to remove the duplicates we just need to remove all
# consequent duplicates
# create replace index, set it to 0
# create a set of duplicates
# iterate over nums:
# - if the number is in the set, continue
# - if the number is not in the set, set nums[replace] to that number, add it to the set
# return replace
def removeDuplicates(self, nums: List[int]) -> int:
replace, duplicates = 0, set()
for i, number in enumerate(nums):
if number in duplicates:
continue
nums[replace] = number
replace += 1
duplicates.add(number)
return replace
4.7.1827 - 2023-07-13 18:52:44 +0300 MSK
Links
Code
class Solution:
# create replace index
# iterate over nums:
# - if the current number is equal to val, continue
# - set nums[replace] to that number, increase the index
def removeElement(self, nums: List[int], val: int) -> int:
replace = 0
for i, number in enumerate(nums):
if number == val:
continue
nums[replace] = number
replace += 1
return replace
4.7.1828 - 2023-07-13 18:46:43 +0300 MSK
Links
Code
class Solution:
# create two indexes, current and replace
# create non_val_count
# while to-be-replaced has not reached the end:
# - if the current number is a regular number, move the current index,
# increase non_val_count
# - if the replace index is equal or less than the current, move it and continue
# - if the replace number is a non-regular number, move the replace index and continue
# - if the current number is a non-regular, replace it with the replace number,
# replace the replace number with val, move both indexes
# return the current index + 1
def removeElement(self, nums: List[int], val: int) -> int:
current, replace, val_count, length = 0, 0, 0, len(nums)
non_val_count = 0
while replace < length and current < length:
current_number, replace_number = nums[current], nums[replace]
if current_number != val:
current += 1
non_val_count += 1
continue
if replace <= current:
replace = current + 1
continue
if replace_number == val:
replace += 1
continue
nums[current], nums[replace] = replace_number, val
replace += 1
current += 1
non_val_count += 1
return non_val_count
4.7.1829 - 2023-07-12 20:34:00 +0300 MSK
Links
Code
class Solution:
# have three indexes: nums1 (end of array 1), nums2 (from the end),
# and current (nums1 from the end)
# if nums2 number is bigger or equal than nums1 number, put the number at the current index,
# move both indexes
# if nums1 number is smaller than nums2 number, put the number at the current index,
# move both indexes
def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
"""
Do not return anything, modify nums1 in-place instead.
"""
nums1_i, nums2_i = m - 1, n - 1
for i in range(m + n - 1, -1, -1):
nums1_number = nums1[nums1_i] if nums1_i >= 0 else nums2[0] - 1
nums2_number = nums2[nums2_i] if nums2_i >= 0 else nums1[0] - 1
if nums1_number >= nums2_number:
nums1[i] = nums1_number
nums1_i -= 1
continue
nums1[i] = nums2_number
nums2_i -= 1
4.7.1830 - 2023-07-11 17:42:28 +0300 MSK
Links
Code
class Solution:
def isPalindrome(self, s: str) -> bool:
length = len(s)
# if the sring has only one symbol and it is alphanumeric, it is a palyndrom
if s.isalnum() and length == 1:
return True
i, j = 0, length - 1
# iterate from the start and from the end using two indexes:
# - if one the symbols is not alphanumeric, move the corresponding index
# - if symbols are alphanumeric and not equal, return False
# - move indexes
while i < j:
symbol_start, symbol_end = s[i].lower(), s[j].lower()
if not symbol_start.isalnum():
i += 1
continue
if not symbol_end.isalnum():
j -= 1
continue
if symbol_start != symbol_end:
return False
i += 1
j -= 1
return True
4.7.1831 - 2023-07-11 17:40:20 +0300 MSK
Links
Code
class Solution:
def isPalindrome(self, s: str) -> bool:
length = len(s)
# if the sring has only one symbol and it is alphanumeric, it is a palyndrom
if s.isalnum() and length == 1:
return True
i, j = 0, length - 1
# iterate from start and from end:
# - if the symbol is not alphanumeric, skip
# - if the symbol is alphanumeric, compare
# - if indexes are equal or reversed, return
while i < j:
symbol_start, symbol_end = s[i].lower(), s[j].lower()
if not symbol_start.isalnum():
i += 1
continue
if not symbol_end.isalnum():
j -= 1
continue
if symbol_start != symbol_end:
return False
i += 1
j -= 1
return True
4.7.1832 - 2023-07-10 15:59:08 +0300 MSK
Links
Code
class Solution:
# check edge cases:
# - if length of the needle is less than the length of the haystack: -1
# - if strings are equal: 0
# - if length of the needle is equal to the length of the haystack, but
# strings are not equal: -1
# iterate over haystack and needle cheking if a substring starting with the current symbol
# is equal to the needle
def strStr(self, haystack: str, needle: str) -> int:
length_needle, length_haystack = len(needle), len(haystack)
last_needle_index = length_needle - 1
if length_needle > length_haystack:
return -1
if haystack == needle:
return 0
if length_needle == length_haystack:
return -1
if needle == haystack:
return 0
for i, _ in enumerate(haystack):
current_needle = haystack[i:i+length_needle]
if current_needle == needle:
return i
return -1
4.7.1833 - 2023-07-10 15:57:30 +0300 MSK
Links
Code
class Solution:
# check edge cases:
# - if length of the needle is less than the length of the haystack: -1
# - if strings are equal: 0
# - if length of the needle is equal to the length of the haystack, but
# strings are not equal: -1
# iterate over haystack and needle cheking if a symbol from haystack
# corresponds to the symbol in needle
def strStr(self, haystack: str, needle: str) -> int:
length_needle, length_haystack = len(needle), len(haystack)
last_needle_index = length_needle - 1
if length_needle > length_haystack:
return -1
if haystack == needle:
return 0
if length_needle == length_haystack:
return -1
if needle == haystack:
return 0
j = length_needle
for i, _ in enumerate(haystack):
current_needle = haystack[i:j]
if current_needle == needle:
return i
j += 1
return -1
4.7.1834 - 2023-07-10 15:49:18 +0300 MSK
Links
Code
class Solution:
# check edge cases:
# - if length of the needle is less than the length of the haystack: -1
# - if strings are equal: 0
# - if length of the needle is equal to the length of the haystack, but
# strings are not equal: -1
# iterate over haystack and needle cheking if a symbol from haystack
# corresponds to the symbol in needle
def strStr(self, haystack: str, needle: str) -> int:
length_needle, length_haystack = len(needle), len(haystack)
last_needle_index = length_needle - 1
if length_needle > length_haystack:
return -1
if haystack == needle:
return 0
if length_needle == length_haystack:
return -1
if needle == haystack:
return 0
i, j = 0, length_needle
while j <= len(haystack):
current_needle = haystack[i:j]
if current_needle == needle:
return i
i += 1
j += 1
return -1
4.7.1835 - 2023-07-08 18:57:18 +0300 MSK
Links
Code
class Solution:
# we need to iterate over the string searching for words
# add a whitespace to the end to avoid the situation when the last symbol is non-whitespace
# possible combinations:
# 1. a whitespace after a symbol: end of the word
# 2. a whitespace after a whitespace: ignore
# 3. a symbol after a symbol: ignore
def lengthOfLastWord(self, s: str) -> int:
s += " "
result, word_length = 0, 0
for i, symbol in enumerate(s):
if symbol != " ":
word_length += 1
continue
if word_length > 0:
result = word_length
word_length = 0
return result
4.7.1836 - 2023-07-08 18:48:01 +0300 MSK
Links
Code
class Solution:
# we need to iterate over the string searching for words
# possible combinations:
# 1. a whitespace after a symbol: end of the word
# 2. a whitespace after a whitespace: ignore
# 3. a symbol after a symbol, but it's the last symbol: end of the last word
# 4. a symbol after a symbol: ignore
def lengthOfLastWord(self, s: str) -> int:
length = len(s)
if length == 1:
return 1
word_start, word_end, in_word = 0, 0, False
for i, symbol in enumerate(s):
is_whitespace = symbol == " "
is_last = i == length - 1
if is_whitespace and in_word:
in_word = False
word_end = i - 1
continue
if is_whitespace and not in_word:
continue
if not is_whitespace and in_word and is_last:
word_end = i
continue
if not is_whitespace and not in_word and is_last:
word_end = i
word_start = i
continue
if not is_whitespace and in_word:
continue
if not is_whitespace and not in_word:
word_start = i
in_word = True
continue
return word_end - word_start + 1
4.7.1837 - 2023-07-08 18:25:39 +0300 MSK
Links
Code
class Solution:
def lengthOfLastWord(self, s: str) -> int:
return len(s.split()[-1])
4.7.1838 - 2023-07-06 20:44:21 +0300 MSK
Links
Code
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
# create the result pointer that points towards one of the lists
# create the result root pointer that will point towards the root of the result list
# 1. start infinite loop
# 2. if result is false - break, we reached the end
# 3. get values from non-empty pointers
# 4. add values together, store the carry in a variable
# 5. store the value in the result pointer
# 6. move the result pointer to the next node, if there is no next node, use a node from
# another list
# 7. move list pointers
# 8. if we have a carry left, add a node to the result list
def addTwoNumbers(self, l1: Optional[ListNode],
l2: Optional[ListNode]) -> Optional[ListNode]:
carry = 0
result, result_root = l1, l1
while True:
if not l1 and not l2:
break
number_1 = l1.val if l1 else 0
number_2 = l2.val if l2 else 0
result_val = number_1 + number_2 + carry
if result_val > 9:
carry, result_val = 1, result_val - 10
else:
carry = 0
result.val = result_val
if not result.next and l2:
l1 = None
result.next = l2.next
if result.next:
result = result.next
if l1:
l1 = l1.next
if l2:
l2 = l2.next
if carry:
result.next = ListNode(carry)
return result_root
4.7.1839 - 2023-07-06 15:43:40 +0300 MSK
Links
Code
class Solution:
def romanToInt(self, input_numbers: str) -> int:
result = 0
previous = None
values = {
"I": 1,
"V": 5,
"X": 10,
"L": 50,
"C": 100,
"D": 500,
"M": 1000,
}
subtractions = set(["IV", "IX", "XL", "XC", "CD", "CM"])
for number in input_numbers:
if f"{previous}{number}" in subtractions:
result = result - values[previous] * 2 + values[number]
else:
result += values[number]
previous = number
return result
4.7.1840 - 2023-05-24 13:25:03 +0300 MSK
Links
Code
class Solution:
def removeElement(self, nums: List[int], val: int) -> int:
length = len(nums)
if not length:
return 0
first = nums[0]
if length == 1 and first == val:
nums.pop()
return 0
if length == 1 and first != val:
return 1
not_equal_index = -1 if first == val else 0
for i, number in enumerate(nums[1:], 1):
if number == val:
continue
not_equal_index += 1
nums[not_equal_index] = number
return not_equal_index + 1
4.7.1841 - 2023-05-24 13:11:40 +0300 MSK
Links
Code
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
length = len(nums)
if length == 1:
return 1
unique_count = 1
last_unique_index = 0
for i, number in enumerate(nums[1:], 1):
last_unique = nums[last_unique_index]
if number == last_unique:
continue
unique_count += 1
last_unique_index += 1
nums[last_unique_index] = number
nums = nums[:last_unique_index+1]
return unique_count
4.7.1842 - 2023-05-24 12:54:30 +0300 MSK
Links
Code
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
result = ListNode()
current = result
while list1 and list2:
if list1.val < list2.val:
current.next = list1
list1, current = list1.next, list1
continue
current.next = list2
list2, current = list2.next, list2
if list1 or list2:
current.next = list1 if list1 else list2
return result.next
4.7.1843 - 2023-05-24 12:13:29 +0300 MSK
Links
Code
class Solution:
def isValid(self, s: str) -> bool:
brackets = []
symbols = {
"{": "}",
"(": ")",
"[": "]"
}
open = symbols.keys()
closed = symbols.values()
for bracket in s:
if bracket in open:
brackets.append(bracket)
continue
if not brackets:
return False
last_bracket = brackets[-1]
if last_bracket in closed:
return False
correct_closing_bracket = symbols[last_bracket]
if bracket != correct_closing_bracket:
return False
brackets.pop()
return not len(brackets)
4.7.1844 - 2023-05-24 11:52:15 +0300 MSK
Links
Code
class Solution:
def isPalindrome(self, x: int) -> bool:
if x < 0:
return False
if x < 10:
return True
number = []
while True:
remainder = x % 10
x = int(x / 10)
number.append(remainder)
if not x:
break
number.reverse()
print(number)
length = len(number)
half_index = int(length / 2)
for i, digit in enumerate(number):
last_digit = number[length - i - 1]
if digit != last_digit:
return False
if i != half_index:
continue
return True
4.7.1845 - 2023-05-24 11:37:01 +0300 MSK
Links
Code
class Solution:
def longestCommonPrefix(self, strs: List[str]) -> str:
answer = []
strings = sorted(strs)
first = strings[0]
last = strings[-1]
min_length = min(len(first), len(last))
for i in range(min_length):
first_symbol = first[i]
last_symbol = last[i]
if first_symbol == last_symbol:
answer.append(first_symbol)
continue
return "".join(answer)
return "".join(answer)
4.7.1846 - 2023-05-24 11:26:20 +0300 MSK
Links
Code
class Solution:
def romanToInt(self, s: str) -> int:
result = 0
skip = False
values = {
"I": 1,
"V": 5,
"X": 10,
"L": 50,
"C": 100,
"D": 500,
"M": 1000
}
special_cases = {
"I": ["V", "X"],
"X": ["L", "C"],
"C": ["D", "M"]
}
for i, symbol in enumerate(s):
if skip:
skip = False
continue
next = None
if i < (len(s) - 1):
next = s[i+1]
if next in special_cases.get(symbol, []):
skip = True
result += values[next] - values[symbol]
continue
result += values[symbol]
return result
4.7.1847 - 2023-05-24 11:15:01 +0300 MSK
Links
Code
class Solution:
def romanToInt(self, s: str) -> int:
result = 0
skip = False
for i, symbol in enumerate(s):
if skip:
skip = False
continue
next = ""
if i < len(s) - 1:
next = s[i+1]
if symbol == "I" and next == "V":
result += 4
skip = True
continue
if symbol == "I" and next == "X":
result += 9
skip = True
continue
if symbol == "I":
result += 1
continue
if symbol == "X" and next == "L":
result += 40
skip = True
continue
if symbol == "X" and next == "C":
result += 90
skip = True
continue
if symbol == "X":
result += 10
continue
if symbol == "C" and next == "D":
result += 400
skip = True
continue
if symbol == "C" and next == "M":
result += 900
skip = True
continue
if symbol == "C":
result += 100
continue
if symbol == "V":
result += 5
continue
if symbol == "D":
result += 500
continue
if symbol == "M":
result += 1000
continue
if symbol == "L":
result += 50
continue
raise Exception(f"unexpected situation: {symbol}, {next}")
return result
4.7.1848 - 2023-05-23 12:36:30 +0300 MSK
Links
Code
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
indexes = {}
for i, number in enumerate(nums):
diff = target - number
if diff in indexes:
return [indexes[diff], i]
indexes[number] = i
4.7.1849 - 2023-05-23 12:30:44 +0300 MSK
Links
Code
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
for i, number in enumerate(nums):
for j, number_inner in enumerate(nums[i+1:]):
if number + number_inner == target:
return [i, i+j+1]
4.7.1850 - 2022-05-17 07:59:02 +0300 MSK
Links
Code
class Solution {
TreeNode ans;
public void inorder(TreeNode c,TreeNode target) {
if (c != null) {
inorder(c.left, target);
if (c.val == target.val) {
ans = c;
}
inorder(c.right, target);
}
}
public final TreeNode getTargetCopy(final TreeNode original, final TreeNode cloned, final TreeNode target)
{
inorder(cloned,target);
return ans;
}
}
4.7.1851 - 2022-05-15 18:44:33 +0300 MSK
Links
Code
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public int deepestLeavesSum(TreeNode root) {
MaxDepthInfo maxDepthInfo = new MaxDepthInfo(0 ,0);
sumAtLevel(root, 0, maxDepthInfo);
return maxDepthInfo.getSumAtMaxDepth();
}
public void sumAtLevel(TreeNode root, int currentDepth, MaxDepthInfo maxDepthInfo) {
if (root == null) return;
if (currentDepth > maxDepthInfo.getMaxDepth()) {
maxDepthInfo.setMaxDepth(currentDepth);
maxDepthInfo.setSumAtMaxDepth(root.val);
}
else if (currentDepth == maxDepthInfo.getMaxDepth())
maxDepthInfo.setSumAtMaxDepth(maxDepthInfo.getSumAtMaxDepth() + root.val);
sumAtLevel(root.left, currentDepth + 1, maxDepthInfo);
sumAtLevel(root.right, currentDepth + 1, maxDepthInfo);
}
public static class MaxDepthInfo {
private int maxDepth;
private int sumAtMaxDepth;
public MaxDepthInfo(int maxDepth, int sumAtMaxDepth) {
this.maxDepth = maxDepth;
this.sumAtMaxDepth = sumAtMaxDepth;
}
public int getMaxDepth() { return maxDepth;}
public void setMaxDepth(int maxDepth) { this.maxDepth = maxDepth;}
public int getSumAtMaxDepth() { return sumAtMaxDepth;}
public void setSumAtMaxDepth(int sumAtMaxDepth) { this.sumAtMaxDepth = sumAtMaxDepth;}
}
}
4.7.1852 - 2022-05-14 15:28:36 +0300 MSK
Links
Code
class Solution {
private final Map<Integer, List<Node>> connected = new HashMap<>();
public int networkDelayTime(int[][] times, int n, int k) {
for (int[] time : times) {
connected.putIfAbsent(time[0], new ArrayList<>());
connected.get(time[0]).add(new Node(time[2], time[1]));
}
connected.forEach((source, nodes) -> nodes.sort(Comparator.comparing(Node::travelTime)));
int[] receivedTime = new int[n + 1]; Arrays.fill(receivedTime, 1, receivedTime.length, Integer.MAX_VALUE);
dfs(receivedTime, 0, k);
int max = Arrays.stream(receivedTime).max().orElseThrow(RuntimeException::new);
return max == Integer.MAX_VALUE ? -1 : max;
}
private void dfs(int[] receivedTime, int currentTime, int currentNode) {
if (receivedTime[currentNode] <= currentTime) return;
receivedTime[currentNode] = currentTime;
if (connected.containsKey(currentNode))
connected.get(currentNode).forEach(node -> dfs(receivedTime, currentTime + node.travelTime(), node.destination()));
}
public record Node(int travelTime, int destination) {}
}
4.7.1853 - 2022-05-13 07:19:10 +0300 MSK
Links
Code
class Solution {
public List<String> letterCombinations(String digits) {
if(digits.length() == 0){
List<String> result = new ArrayList<>();
return result;
}
List<String> res = combine(digits);
return res;
}
public List<String> combine(String digit){
if(digit.length() == 0 ){
List<String> result = new ArrayList<>();
result.add("");
return result;
}
String[] codes = {"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
char c = digit.charAt(0);
String digits_left = digit.substring(1);
List<String> res = combine(digits_left);
List<String> result = new ArrayList<>();
String code_for_current_digit = codes[c-'0'];
for(int i=0;i<code_for_current_digit.length();i++){
char code_char = code_for_current_digit.charAt(i);
if(!res.isEmpty()){
for(String s : res){
result.add(code_char + s);
}
}
else{
res.add(String.valueOf(code_char));
}
}
return result;
}
}
4.7.1854 - 2022-05-13 07:17:45 +0300 MSK
Links
Code
class Solution {
public Node connect(Node root) {
Node leftMost = root;
while (leftMost != null) {
Node cur = leftMost;
leftMost = null;
Node pre = null;
while (cur != null) {
if (leftMost == null) {
leftMost = cur.left == null ? cur.right: cur.left;
}
if (pre != null) {
pre.next = cur.left == null ? cur.right : cur.left;
}
if (cur.left != null && cur.right != null) {
cur.left.next = cur.right;
}
pre = cur.right == null ? (cur.left == null ? pre : cur.left) : cur.right;
cur = cur.next;
}
}
return root;
}
}
4.7.1855 - 2022-05-12 18:05:33 +0300 MSK
Links
Code
class Solution {
public List<List<Integer>> permuteUnique(int[] nums) {
List<List<Integer>> permutations = new ArrayList<>();
Arrays.sort(nums);
backtracking(permutations, new ArrayList<>(), nums, new boolean[nums.length]);
return permutations;
}
private void backtracking(List<List<Integer>> permutations, List<Integer> current, int[] nums, boolean[] used) {
if (current.size() == nums.length)
permutations.add(new ArrayList<>(current));
else {
for (int i = 0; i < nums.length; i++) {
if (used[i] || (i > 0 && nums[i] == nums[i - 1] && !used[i - 1])) continue;
current.add(nums[i]);
used[i] = true;
backtracking(permutations, current, nums, used);
used[i] = false;
current.remove(current.size() - 1);
}
}
}
}
4.7.1856 - 2022-05-11 18:03:06 +0300 MSK
Links
Code
class Solution {
public int countVowelStrings(int n) {
int a,e,i,o,u;
a = e = i = o = u = 1;
for(int t = 1; t < n; t++){
a = a + e + i + o + u;
e = e + i + o + u;
i = i + o + u;
o = o + u;
u = u;
}
return a + e + i + o + u;
}
}
4.7.1857 - 2022-05-08 17:27:21 +0300 MSK
Links
Code
public class NestedIterator implements Iterator<Integer> {
private List<Integer> integerList = new ArrayList<>();
private int index = 0;
public NestedIterator(List<NestedInteger> nestedList) {
for (NestedInteger nestedInteger : nestedList) {
flatten(nestedInteger);
}
}
private void flatten(NestedInteger nested) {
if (nested.isInteger())
integerList.add(nested.getInteger());
else
for (NestedInteger nestedFromList : nested.getList()) {
flatten(nestedFromList);
}
}
@Override
public boolean hasNext() {
return index < integerList.size();
}
@Override
public Integer next() {
return integerList.get(index++);
}
}
4.7.1858 - 2022-05-07 13:44:16 +0300 MSK
Links
Code
func find132pattern(numbers []int) bool {
length := len(numbers)
if length < 3 {
// if the array doesn't have at least three numbers, it cannot have
// '123' pattern
return false
}
list, third_element := list.List{}, math.MinInt
for index := length - 1; index >= 0; index-- {
current := numbers[index]
if current < third_element {
return true
}
for list.Len() != 0 && list.Front().Value.(int) < current {
third_element = list.Front().Value.(int)
list.Remove(list.Front())
}
list.PushFront(current)
}
return false
}
4.7.1859 - 2022-05-07 13:05:13 +0300 MSK
Links
Code
func backspaceCompare(string_1 string, string_2 string) bool {
length_1, length_2 := len(string_1), len(string_2)
list_1, list_2, length_biggest := list.List{}, list.List{}, length_1
if length_2 > length_1 {
length_biggest = length_2
}
for index := 0; index < length_biggest; index++ {
if index < length_1 {
backspace_action(&list_1, string_1[index])
}
if index < length_2 {
backspace_action(&list_2, string_2[index])
}
}
// lists are not equal, there is no need to check
if list_1.Len() != list_2.Len() {
return false
}
// checking elements after all deletions
element_1, element_2 := list_1.Back(), list_2.Back()
for element_1 != nil {
if element_1.Value != element_2.Value {
// elements are not equal -> strings are not equal
return false
}
element_1, element_2 = element_1.Next(), element_2.Next()
}
// checked all elements, strings are equal
return true
}
func backspace_action(list *list.List, character byte) {
switch {
case character == '#' && list.Len() != 0:
// delete last character
list.Remove(list.Front())
fallthrough
case character == '#' && list.Len() == 0:
// just return if the list is empty
return
}
list.PushFront(character)
}
4.7.1860 - 2022-05-06 20:02:58 +0300 MSK
Links
Code
class Solution {
public boolean backspaceCompare(String S, String T) {
return build(S).equals(build(T));
}
public String build(String S) {
Stack<Character> ans = new Stack();
for (char c: S.toCharArray()) {
if (c != '#')
ans.push(c);
else if (!ans.empty())
ans.pop();
}
return String.valueOf(ans);
}
}
4.7.1861 - 2022-05-06 19:50:38 +0300 MSK
Links
Code
func removeDuplicates(numbers []int) int {
// ensure there are at least two numbers
length := len(numbers)
if length == 1 {
return 1
}
index_non_duplicate := 1
for index := 1; index < length; index++ {
current, previous := numbers[index], numbers[index-1]
if current == previous {
// it is a duplicate - ignore it
continue
}
// it is not a duplicate -> place it and move the index
numbers[index_non_duplicate] = current
index_non_duplicate++
}
return index_non_duplicate
}
4.7.1862 - 2022-05-06 19:25:00 +0300 MSK
Links
Code
class Solution {
public String removeDuplicates(String s, int k) {
Stack<int []> Master = new Stack<>();
for(char ch : s.toCharArray()){
if(!Master.isEmpty() && Master.peek()[0] == ch){
Master.peek()[1]++;
}
else Master.push(new int[]{ch, 1});
if(Master.peek()[1] == k) Master.pop();
}
StringBuilder sb = new StringBuilder();
while(!Master.isEmpty()){
int top[] = Master.pop();
while(top[1] --> 0)
sb.append((char)top[0]);
}
return sb.reverse().toString();
}
}
4.7.1863 - 2022-05-05 18:39:53 +0300 MSK
Links
Code
func arraySign(numbers []int) int {
negative_count := 0
for _, number := range numbers {
switch {
// the number is 0 -> product of all numbers is definitely zero
case number == 0:
return 0
// the number is negative -> add to count
case number < 0:
negative_count++
}
}
// even amount of negative numbers -> result is positive
if negative_count&1 == 0 {
return 1
}
// uneven amount of negative numbers -> result is negative
return -1
}
4.7.1864 - 2022-05-05 18:26:39 +0300 MSK
Links
Code
func nextGreatestLetter(letters []byte, target byte) byte {
length := len(letters)
left, right := 0, length-1
for right >= left {
index := left + (right-left)/2
character := letters[index]
// the character is bigger, we found at least one result
// smaller characters are to the left -> discard right
if character > target {
right = index - 1
continue
}
// character is either equal or smaller -> there is no results to the
// left -> discard left
left = index + 1
}
return letters[left%length]
}
4.7.1865 - 2022-05-05 15:37:11 +0300 MSK
Links
Code
func mySqrt(number int) int {
left, right := 0, number
for right >= left {
current := left + (right-left)/2
square_current := current * current
square_next := (current + 1) * (current + 1)
switch {
case square_current <= number && square_next > number:
// found the target
return current
case square_current > number:
// target is to the left -> discard right
right = current - 1
case square_current < number:
// target is to the right -> discard left
left = current + 1
}
}
return -1
}
4.7.1866 - 2022-05-05 15:10:54 +0300 MSK
Links
Code
func reverseWords(_string string) string {
index_word_start, length, result := 0, len(_string), []rune(_string)
for index, character := range result {
// ignore normal characters
if character != ' ' {
continue
}
// word ended -> reverse characters from the start of the word to the
//end of it
reverse_word(result, length, index_word_start, index)
index_word_start = index + 1
}
reverse_word(result, length, index_word_start, length)
return string(result)
}
func reverse_word(_string []rune, length int, start int, end int) {
//fmt.Println("reversing", string(_string), start, "->", end)
length_word := end - start
for index := start; index < start+length_word/2; index++ {
index_last := end - (index - start) - 1
current, last := _string[index], _string[index_last]
_string[index], _string[index_last] = last, current
}
//fmt.Println("result", string(_string), start, "->", end)
}
4.7.1867 - 2022-05-05 13:50:33 +0300 MSK
Links
Code
func reverseString(characters []byte) {
length := len(characters)
for index := 0; index < length/2; index++ {
index_last := length - index -1
current, last := characters[index], characters[index_last]
characters[index_last] = current
characters[index] = last
}
}
4.7.1868 - 2022-05-05 13:43:47 +0300 MSK
Links
Code
func twoSum(numbers []int, target int) []int {
numbers_len := len(numbers)
for index, number := range numbers {
for index_inner := index + 1; index_inner < numbers_len; index_inner++ {
if numbers[index_inner]+number == target {
return []int{index + 1, index_inner + 1}
}
}
}
return []int{}
}
4.7.1869 - 2022-05-05 13:39:30 +0300 MSK
Links
Code
func moveZeroes(numbers []int) {
index_zero := -1
// sliding window algorithm
for index, number := range numbers {
// if index_zero is not set, then the first zero is index_zero
if index_zero == -1 && number == 0 {
index_zero = index
}
// there is no need to move numbers if there were no zeros before
// there is no need to move zeros
if index_zero == -1 || number == 0 {
continue
}
// after some zeros we encounter a non-zero number
// moving that number to the beginning of zeros
numbers[index_zero] = number
// current number becomes zero
numbers[index] = 0
// moving the index
index_zero++
}
}
4.7.1870 - 2022-05-05 13:39:06 +0300 MSK
Links
Code
func moveZeroes(nums []int) {
count:=0
for i:=0; i<len(nums);i++{
if nums[i] == 0{
count++
}else{
nums[i-count]=nums[i]
}
}
for count>0{
nums[len(nums)-count] = 0
count--
}
}
4.7.1871 - 2022-05-05 13:38:25 +0300 MSK
Links
Code
func moveZeroes(nums []int) {
if len(nums) < 2 {
return
}
for z, p := 0, 1; p < len(nums) && z < len(nums); {
if nums[z] == 0 && nums[p] != 0 {
if p > z {
nums[z], nums[p] = nums[p], nums[z]
z++
}
p = z+1
} else {
if nums[z] != 0 {
z++
}
if nums[p] == 0 {
p++
}
}
}
}
4.7.1872 - 2022-05-05 13:32:58 +0300 MSK
Links
Code
func moveZeroes(numbers []int) {
index_zero := -1
// sliding window algorithm
for index, number := range numbers {
// if index_zero is not set, then the first zero is index_zero
if index_zero == -1 && number == 0 {
index_zero = index
}
// there is no need to move numbers if there were no zeros before
// there is no need to move zeros
if index_zero == -1 || number == 0 {
continue
}
// after some zeros we encounter a non-zero number
// moving that number to the beginning of zeros
numbers[index_zero] = number
// current number becomes zero
numbers[index] = 0
// moving the index
index_zero++
}
}
4.7.1873 - 2022-05-05 13:14:51 +0300 MSK
Links
Code
func moveZeroes(numbers []int) {
// ensure there are at least two numbers
length := len(numbers)
if length == 1 {
return
}
result, index_result := make([]int, length), 0
for _, number := range numbers {
if number == 0 {
continue
}
result[index_result] = number
index_result++
}
copy(numbers, result)
}
4.7.1874 - 2022-05-05 07:01:33 +0300 MSK
Links
Code
type MyStack struct{ queue *list.List }
func Constructor() MyStack { return MyStack{&list.List{}} }
func (this *MyStack) Push(value int) { this.queue.PushFront(value) }
func (this *MyStack) Top() int { return this.queue.Front().Value.(int) }
func (this *MyStack) Empty() bool { return this.queue.Len() == 0 }
func (this *MyStack) Pop() int {
return this.queue.Remove(this.queue.Front()).(int)
}
4.7.1875 - 2022-05-04 13:13:54 +0300 MSK
Links
Code
func maxProfit(prices []int) int {
profit, index_buy := 0, 0
for index, price := range prices {
if prices[index_buy] > price {
index_buy = index
}
new_profit := price - prices[index_buy]
if new_profit > profit {
profit = new_profit
}
}
return profit
}
4.7.1876 - 2022-05-04 12:54:11 +0300 MSK
Links
Code
func intersect(numbers_1 []int, numbers_2 []int) (result []int) {
// 0 <= nums1[i], nums2[i] <= 1000
count := make([]int, 1001)
// counting how many times a number occured in the first array
for _, number := range numbers_1 {
count[number]++
}
for _, number := range numbers_2 {
// the number did not occur in the first array
// -> ignoring it
if count[number] <= 0 {
continue
}
count[number]--
result = append(result, number)
}
return
}
4.7.1877 - 2022-05-04 12:36:38 +0300 MSK
Links
Code
func intersect(numbers_1 []int, numbers_2 []int) []int {
length_1, length_2 := len(numbers_1), len(numbers_2)
length_biggest, result := length_1, make([]int, length_1+length_2)
if length_2 > length_1 {
length_biggest = length_2
}
occurences := make(map[int][]int, length_biggest)
for index := 0; index < length_biggest; index++ {
if index < length_1 {
add_to_occurences(numbers_1[index], 0, occurences)
}
if index < length_2 {
add_to_occurences(numbers_2[index], 1, occurences)
}
}
index := 0
for number, occurence := range occurences {
repeat := occurence[0]
if occurence[1] < repeat {
repeat = occurence[1]
}
for ; repeat > 0; repeat-- {
result[index] = number
index++
}
}
return result[0 : index]
}
func add_to_occurences(number int, index int, occurences map[int][]int) {
if _, occured := occurences[number]; !occured {
occurences[number] = make([]int, 2)
}
occurences[number][index]++
}
4.7.1878 - 2022-05-04 08:33:36 +0300 MSK
Links
Code
func merge(array1 []int, length1 int, array2 []int, length2 int) {
if length2 == 0 {
return
}
if length1 == 0 {
for index, number := range array2 {
array1[index] = number
}
return
}
index1, index2, array1Copy := 0, 0, make([]int, length1)
copy(array1Copy, array1)
for index := 0; index < length1+length2; index++ {
fmt.Println(index, index1, index2, array1, array2)
for index2 < length2 && (index1 >= length1 || array2[index2] <= array1Copy[index1]) {
array1[index] = array2[index2]
index2++
index++
}
if index1 >= length1 {
continue
}
array1[index] = array1Copy[index1]
index1++
}
}
4.7.1879 - 2022-05-04 08:32:16 +0300 MSK
Links
Code
func twoSum(numbers []int, target int) []int {
numbers_len := len(numbers)
for index, number := range numbers {
for index_inner := index + 1; index_inner < numbers_len; index_inner++ {
if numbers[index_inner]+number == target {
return []int{index, index_inner}
}
}
}
return []int{}
}
4.7.1880 - 2022-05-04 08:30:20 +0300 MSK
Links
Code
func findTheDistanceValue(array_1 []int, array_2 []int, target int) int {
// sorting it to use binary search
sort.Ints(array_2)
length_2, count := len(array_2), 0
for _, current_1 := range array_1 {
left, right, add_to_count := 0, length_2-1, true
for right >= left {
index := left + (right-left)/2
current_2 := array_2[index]
if abs(current_1, current_2) <= target {
// current_1 is inside |arr1[i]-arr2[j]| <= d
// -> ignore it
add_to_count = false
break
}
switch {
case current_2 > current_1:
// current_2 is bigger than current_1
// -> all numbers to the right are bigger
// -> discard right, add to count
right = index - 1
case current_2 < current_1:
// current_2 is smaller than current_1
// -> all numbers to the left are smaller
// -> discard left, add to count
left = index + 1
}
}
if add_to_count {
count++
}
}
return count
}
func abs(number_1 int, number_2 int) int {
difference := number_1 - number_2
if difference < 0 {
return difference * -1
}
return difference
}
4.7.1881 - 2022-05-04 07:34:24 +0300 MSK
Links
Code
func isPerfectSquare(number int) bool {
left, right := 1, number
for right >= left {
current := left + (right-left)/2
square := current * current
switch {
case square == number:
// found the target
return true
case square > number:
// square is bigger -> root is to the left -> discard right
right = current - 1
case square < number:
// square is smaller -> root is to the right -> discard left
left = current + 1
}
}
return false
}
4.7.1882 - 2022-05-04 07:03:31 +0300 MSK
Links
Code
func nearestValidPoint(x int, y int, points [][]int) int {
point_target, smallest_distance, smallest_index := []int{x, y}, math.MaxInt, -1
for index, point := range points {
// ignore the point if it is not valid
if !valid(point_target, point) {
continue
}
distance := distance(point_target, point)
// ignore the point if its Manhattan distance is bigger
if distance >= smallest_distance {
continue
}
// the distance is smaller, update the index and the distance
smallest_index, smallest_distance = index, distance
}
// there are no valid points
if smallest_index == -1 {
return -1
}
return smallest_index
}
func valid(point_target []int, point []int) bool {
switch {
case point_target[0] == point[0]:
fallthrough
case point_target[1] == point[1]:
return true
default:
return false
}
}
func distance(point_target []int, point []int) int {
return abs(point_target[0]-point[0]) + abs(point_target[1]-point[1])
}
func abs(number int) int {
if number < 0 {
return number * -1
}
return number
}
4.7.1883 - 2022-05-04 06:39:29 +0300 MSK
Links
Code
func largestPerimeter(numbers []int) int {
sort.Ints(numbers)
for index := len(numbers) - 1; index > 1; index-- {
current, sum_previous := numbers[index], numbers[index-1]+numbers[index-2]
if current >= sum_previous {
continue
}
return current + sum_previous
}
return 0
}
4.7.1884 - 2022-05-04 06:26:24 +0300 MSK
Links
Code
func maxOperations(numbers []int, sum int) int {
count, previous := 0, make(map[int]int, len(numbers))
for _, current := range numbers {
target := sum - current
target_unmatched, target_occured := previous[target]
// if the current number has not occured before, then it is not in the map
// -> it needs to be initialized
if _, current_occured := previous[current]; !current_occured {
previous[current] = 0
}
// number of duplicates of the current number has increased
previous[current]++
switch {
case target_occured && target_unmatched == 0:
// the target has occured before but there are no unmatched duplicates
fallthrough
case !target_occured:
// in order to get the sum we need the target, but it has not appeared yet
continue
case target_occured && target_unmatched > 0:
// the target has appeared before and there are some unmached duplicates left
// -> removing the current number and the target from possible matches
previous[current]--
previous[target]--
count++
}
}
return count
}
4.7.1885 - 2022-05-04 05:57:55 +0300 MSK
Links
Code
func subtractProductAndSum(number int) int {
fist_digit := number % 10
factorial, sum := fist_digit, fist_digit
number /= 10
for number > 0 {
digit := number % 10
factorial *= digit
sum += digit
number /= 10
}
return factorial - sum
}
4.7.1886 - 2022-05-04 05:49:11 +0300 MSK
Links
Code
func hammingWeight(number uint32) (result int) {
for number > 0 {
if number&1 != 0 {
result++
}
number >>= 1
}
return
}
4.7.1887 - 2022-05-03 18:34:04 +0300 MSK
Links
Code
func peakIndexInMountainArray(array []int) int {
left, right := 0, len(array)-1
for right > left {
// overflow protection
index := left + (right-left)/2
// next element is bigger -> top is to the right -> discard left
if array[index+1] > array[index] {
left = index + 1
continue
}
// next element is equal or smaller -> discard right
// 'index' could be the answer, so it should not be discarded
right = index
}
return right
}
4.7.1888 - 2022-05-03 17:44:29 +0300 MSK
Links
Code
func searchInsert(numbers []int, target int) int {
// checking edge cases
length := len(numbers)
if numbers[0] == target {
return 0
} else if numbers[length-1] == target {
return length - 1
}
left, right, index, was_bigger := 0, length-1, 0, false
for right >= left {
// overflow protection
index = left + (right-left)/2
number := numbers[index]
//fmt.Println("index", index, "left", left, "right", right)
switch {
case number == target:
// found the target
return index
case number > target:
// the number is bigger -> the target is to the left -> discard right
right = index - 1
was_bigger = true
case number < target:
// the number is smaller -> the target is to the right -> discard left
left = index + 1
was_bigger = false
}
}
// the target is not in the array
// the last number was bigger -> target should be to the left
if was_bigger {
return index
}
// the last number was smaller -> target should be to the right
return index + 1
}
4.7.1889 - 2022-05-03 17:39:58 +0300 MSK
Links
Code
func rotate(numbers []int, steps int) {
length := len(numbers)
// removing unnecessary steps
if steps >= length {
steps %= length
}
// checking edge cases
if length == 1 || steps == 0 {
return
}
results := make([]int, length)
for index, number := range numbers {
results[(index+steps)%length] = number
}
copy(numbers, results)
}
4.7.1890 - 2022-05-03 15:28:52 +0300 MSK
Links
Code
func rotate(numbers []int, steps int) {
length := len(numbers)
// removing unnecessary steps
if steps >= length {
steps %= length
}
// checking edge cases
if length == 1 || steps == 0 {
return
}
remainder, rotation_start := make([]int, steps), length-steps
// copy everything that needs to be shifted to another array
copy(remainder, numbers[rotation_start:])
// move everything to the right
copy(numbers[steps:], numbers[0:rotation_start])
// move shifted elements to the beginning
copy(numbers[0:steps], remainder)
}
4.7.1891 - 2022-05-03 15:08:53 +0300 MSK
Links
Code
func sortedSquares(numbers []int) []int {
length := len(numbers)
if length == 0 || length == 1 {
return square(numbers, false)
}
negativesIndex := -1
for index, number := range numbers {
if number >= 0 {
negativesIndex = index
break
}
}
if negativesIndex == 0 || negativesIndex == -1 {
return square(numbers, negativesIndex == -1)
}
// fmt.Println("negativesIndex", negativesIndex)
result, resultIndex, negativesIndex := make([]int, length), 0, negativesIndex-1
for positivesIndex := negativesIndex + 1; resultIndex < length; positivesIndex++ {
positiveOverflow := positivesIndex >= length
for {
if negativesIndex < 0 || resultIndex >= length {
break
}
if !positiveOverflow && numbers[negativesIndex]*-1 > numbers[positivesIndex] {
break
}
result[resultIndex] = numbers[negativesIndex]
resultIndex++
// fmt.Println("negative", negativesIndex, resultIndex, numbers[negativesIndex], result, numbers)
negativesIndex--
}
if resultIndex < length && !positiveOverflow {
// fmt.Println("positivesIndex", positivesIndex, resultIndex, numbers[positivesIndex], result, numbers)
result[resultIndex] = numbers[positivesIndex]
resultIndex++
}
}
return square(result, false)
}
func square(array []int, reverse bool) []int {
if reverse {
length := len(array)
reversed := make([]int, length)
for index := length - 1; index >= 0; index-- {
reversed[length-index-1] = array[index] * array[index]
}
return reversed
} else {
for index, number := range array {
array[index] = number * number
}
return array
}
}
4.7.1892 - 2022-05-03 15:05:02 +0300 MSK
Links
Code
func sortedSquares(numbers []int) []int {
length := len(numbers)
switch length {
case 0:
return numbers
case 1:
return []int{numbers[0] * numbers[0]}
}
index_left, index_right := 0, length-1
results := make([]int, length)
for index := index_right; index_left <= index_right; index-- {
left_square := numbers[index_left] * numbers[index_left]
right_square := numbers[index_right] * numbers[index_right]
if right_square > left_square {
results[index] = right_square
index_right--
continue
}
results[index] = left_square
index_left++
}
return results
}
4.7.1893 - 2022-05-03 13:17:41 +0300 MSK
Links
Code
func findUnsortedSubarray(numbers []int) int {
length := len(numbers)
// checking edge cases
if length == 1 {
return 0
}
result := make([]int, length)
// initializing to MaxInt because zeros will impact future sorting
for index := range result {
result[index] = math.MaxInt
}
index_sort_start, index_sort_end := length, length
result[0] = numbers[0]
for index := 1; index < length; index++ {
// fmt.Println(result, index_sort_start, "->", index_sort_end)
// current is not sorted -> from numbers
// previous is sorted -> from result
current, previous := numbers[index], result[index-1]
// just push the current number in the result array because if it is
// bigger
if current >= previous {
result[index] = current
continue
}
// current number is not sorted -> moving the end index
index_sort_end = index + 1
// current < previous -> find the number bigger than the current
//
// the current number is smaller than the starting number of the unsorted subarray
// (or the starting index is not set)
// -> start index is invalid, finding new start index in numbers
if index_sort_start == length || current < result[index_sort_start] {
// insert the number in the correct place and move index_sort_start
// to the correct place
if index_sort_start == length {
// index_sort_start is not set -> setting to the last sorted number
index_sort_start = index - 1
}
index_sort_start = insert_smaller(result, current, index_sort_start, 0)
continue
}
// the current number is bigger than the starting number of the unsorted
// subarray, so it should be placed inside of it
insert_smaller(result, current, index, index_sort_start)
// set start index (if not already set)
if index < index_sort_start {
index_sort_start = index - 1
}
}
// fmt.Println(result, index_sort_start, "->", index_sort_end)
// return length of the sorted subarray
return index_sort_end - index_sort_start
}
func insert_smaller(numbers []int, target int, index_start int, index_end int) int {
index_result := index_end
for index := index_start; index >= index_end; index-- {
if target >= numbers[index] {
// target is bigger -> it should be placed after this index
index_result = index + 1
break
}
}
// fmt.Println("index for", target, "-", index_result)
// target should be placed after index_result, so move everything after
// it to the right and insert the current number
// if index_result is the last item, then just push it
copy(numbers[index_result+1:], numbers[index_result:])
numbers[index_result] = target
return index_result
}
4.7.1894 - 2022-05-03 13:17:21 +0300 MSK
Links
Code
func findUnsortedSubarray(numbers []int) int {
length := len(numbers)
// checking edge cases
if length == 1 {
return 0
}
result := make([]int, length)
// initializing to MaxInt because zeros will impact future sorting
for index := range result {
result[index] = math.MaxInt
}
index_sort_start, index_sort_end := length, length
result[0] = numbers[0]
for index := 1; index < length; index++ {
// fmt.Println(result, index_sort_start, "->", index_sort_end)
// current is not sorted -> from numbers
// previous is sorted -> from result
current, previous := numbers[index], result[index-1]
// just push the current number in the result array because if it is
// bigger
if current >= previous {
result[index] = current
continue
}
// current number is not sorted -> moving the end index
index_sort_end = index + 1
// current < previous -> find the number bigger than the current
//
// the current number is smaller than the starting number of the unsorted subarray
// (or the starting index is not set)
// -> start index is invalid, finding new start index in numbers
if index_sort_start == length || current < result[index_sort_start] {
// insert the number in the correct place and move index_sort_start
// to the correct place
if index_sort_start == length {
// index_sort_start is not set -> setting to the last sorted number
index_sort_start = index - 1
}
index_sort_start = insert_smaller(result, current, index_sort_start, 0)
continue
}
// the current number is bigger than the starting number of the unsorted
// subarray, so it should be placed inside of it
insert_smaller(result, current, index, index_sort_start)
// set start index (if not already set)
if index < index_sort_start {
index_sort_start = index - 1
}
}
// fmt.Println(result, index_sort_start, "->", index_sort_end)
// return length of the sorted subarray
return index_sort_end - index_sort_start
}
func insert_smaller(numbers []int, target int, index_start int, index_end int) int {
index_result := index_end
for index := index_start; index >= index_end; index-- {
if target >= numbers[index] {
// target is bigger -> it should be placed after this index
index_result = index + 1
break
}
}
// fmt.Println("index for", target, "-", index_result)
// target should be placed after index_result, so move everything after
// it to the right and insert the current number
// if index_result is the last item, then just push it
copy(numbers[index_result+1:], numbers[index_result:])
numbers[index_result] = target
return index_result
}
4.7.1895 - 2022-05-02 19:07:40 +0300 MSK
Links
Code
func sortArrayByParity(numbers []int) []int {
length := len(numbers)
if length == 1 {
return numbers
}
results, index_even, index_odd := make([]int, length), 0, length-1
for _, number := range numbers {
if (number & 1) == 0 {
// number is even -> place it from the beginning
results[index_even] = number
index_even++
} else {
// number is odd -> place it from the end
results[index_odd] = number
index_odd--
}
}
return results
}
4.7.1896 - 2022-05-02 18:49:07 +0300 MSK
Links
Code
func searchInsert(numbers []int, target int) int {
// checking edge cases
length := len(numbers)
if numbers[0] == target {
return 0
} else if numbers[length-1] == target {
return length - 1
}
left, right, index, was_bigger := 0, length-1, 0, false
for right >= left {
// overflow protection
index = left + (right-left)/2
number := numbers[index]
//fmt.Println("index", index, "left", left, "right", right)
switch {
case number == target:
// found the target
return index
case number > target:
// the number is bigger -> the target is to the left -> discard right
right = index - 1
was_bigger = true
case number < target:
// the number is smaller -> the target is to the right -> discard left
left = index + 1
was_bigger = false
}
}
// the target is not in the array
// the last number was bigger -> target should be to the left
if was_bigger {
return index
}
// the last number was smaller -> target should be to the right
return index + 1
}
4.7.1897 - 2022-05-02 18:02:36 +0300 MSK
Links
Code
func firstBadVersion(n int) int {
// checking edge cases
if isBadVersion(1) {
return 1
}
left, right, bad_version := 1, n, math.MaxInt
for right >= left {
// overflow protection
version := left + (right-left)/2
switch isBadVersion(version) {
case false:
// it is good -> versions to the left are good -> discard left
left = version + 1
case true:
// it is bad -> the first bad version is either this one or to the left
// discard right
bad_version = version
right = version - 1
}
}
// the search space is empty
return bad_version
}
4.7.1898 - 2022-05-02 17:51:33 +0300 MSK
Links
Code
/* https://leetcode.com/problems/binary-search/
Given an array of integers nums which is sorted in ascending order, and an integer target, write a function to search target in nums. If target exists, then return its index. Otherwise, return -1.
You must write an algorithm with O(log n) runtime complexity.
Example 1:
Input: nums = [-1,0,3,5,9,12], target = 9
Output: 4
Explanation: 9 exists in nums and its index is 4
Example 2:
Input: nums = [-1,0,3,5,9,12], target = 2
Output: -1
Explanation: 2 does not exist in nums so return -1
Constraints:
1 <= nums.length <= 104
-104 < nums[i], target < 104
All the integers in nums are unique.
nums is sorted in ascending order.
*/
package main
func search(numbers []int, target int) int {
length := len(numbers)
switch {
case numbers[0] > target:
// smallet number > target = there is no target in the array
fallthrough
case numbers[length-1] < target:
// biggest number < target = there is no target in the array
return -1
case numbers[length-1] == target:
// checking just in case, can save time
return length - 1
case numbers[0] == target:
// checking just in case, can save time
return 0
}
left, right := 0, length-1
for right >= left {
// overflow protection
index := left + (right-left)/2
number := numbers[index]
switch {
case number == target:
// found the target
return index
case number > target:
// array is in the ascending order, the number is bigger
// -> the target is to the left -> discard right
right = index - 1
case number < target:
// array is in the ascending order, the number is smaller
// -> the target is to the right -> discard left
left = index + 1
}
}
// search space is empty, there is no target
return -1
}
4.7.1899 - 2022-05-02 17:49:22 +0300 MSK
Links
Code
func guessNumber(n int) int {
// checking edge cases
if guess(1) == 0 {
return 1
} else if guess(n) == 0 {
return n
}
left, right := 1, n
for right >= left {
// overflow protection
number := left + (right-left)/2
switch guess(number) {
case 0:
// found the target
return number
case -1:
// the number is bigger -> the target is to the left -> discard right
right = number - 1
case 1:
// the number is smaller -> the target is to the right -> discard left
left = number + 1
}
}
// ide shows an error, this return is unreachable in this issue
return 0
}
4.7.1900 - 2022-05-02 17:34:04 +0300 MSK
Links
Code
/* https://leetcode.com/problems/binary-search/
Given an array of integers nums which is sorted in ascending order, and an integer target, write a function to search target in nums. If target exists, then return its index. Otherwise, return -1.
You must write an algorithm with O(log n) runtime complexity.
Example 1:
Input: nums = [-1,0,3,5,9,12], target = 9
Output: 4
Explanation: 9 exists in nums and its index is 4
Example 2:
Input: nums = [-1,0,3,5,9,12], target = 2
Output: -1
Explanation: 2 does not exist in nums so return -1
Constraints:
1 <= nums.length <= 104
-104 < nums[i], target < 104
All the integers in nums are unique.
nums is sorted in ascending order.
*/
package main
func search(numbers []int, target int) int {
length := len(numbers)
switch {
case numbers[0] > target:
// smallet number > target = there is no target in the array
fallthrough
case numbers[length-1] < target:
// biggest number < target = there is no target in the array
return -1
case numbers[length-1] == target:
// checking just in case, can save time
return length - 1
case numbers[0] == target:
// checking just in case, can save time
return 0
}
left, right := 0, length-1
for right >= left {
// overflow protection
index := left + (right-left)/2
number := numbers[index]
switch {
case number == target:
// found the target
return index
case number > target:
// array is in the ascending order, the number is bigger
// -> the target is to the left -> discard right
right = index - 1
case number < target:
// array is in the ascending order, the number is smaller
// -> the target is to the right -> discard left
left = index + 1
}
}
// search space is empty, there is no target
return -1
}
4.7.1901 - 2022-05-02 16:35:35 +0300 MSK
Links
Code
func average(salary []int) float64 {
length := len(salary)
highest, lowest := math.MinInt, math.MaxInt
result := 0
for _, number := range salary {
result += number
if number > highest {
highest = number
}
if number < lowest {
lowest = number
}
}
return float64(result-highest-lowest) / float64(length-2)
}
4.7.1902 - 2022-05-02 16:28:49 +0300 MSK
Links
Code
func countOdds(low int, high int) int {
low_even, high_even, half := (low&1) == 0, (high&1) == 0, (high-low)/2
if low_even && high_even {
return half
}
return half + 1
}
4.7.1903 - 2022-05-02 14:58:45 +0300 MSK
Links
Code
func maxSubArray(numbers []int) int {
length := len(numbers)
switch length {
case 0:
return 0
case 1:
return numbers[0]
}
maxCurrent, maxOverall := 0, math.MinInt
for _, number := range numbers {
maxCurrent += number
if maxCurrent > maxOverall {
maxOverall = maxCurrent
}
if maxCurrent < 0 {
maxCurrent = 0
}
}
return maxOverall
}
4.7.1904 - 2022-05-02 07:24:29 +0300 MSK
Links
Code
func containsDuplicate(numbers []int) bool {
if len(numbers) == 0 || len(numbers) == 1 {
return false
}
occured := make(map[int]bool)
for _, number := range numbers {
_, isDuplicate := occured[number]
if isDuplicate {
return true
}
occured[number] = true
}
return false
}
4.7.1905 - 2022-05-01 16:23:58 +0300 MSK
Links
Code
func addToArrayForm(number1 []int, add int) []int {
if add == 0 {
return number1
}
if len(number1) == 0 {
return convert(add)
}
number2 := convert(add)
length1, length2, carry := len(number1), len(number2), 0
hightest := length1
if length2 > length1 {
hightest = length2
}
result := make([]int, hightest)
index1, index2, indexResult := length1-1, 0, hightest-1
for {
index1Valid, index2Valid := index1 >= 0, index2 < length2
if !index1Valid && !index2Valid && carry==0 {
break
}
digit1, digit2 := 0, 0
if index1Valid {
digit1 = number1[index1]
index1--
}
if index2Valid {
digit2 = number2[index2]
index2++
}
digitResult := digit1 + digit2 + carry
if digitResult > 9 {
carry = 1
digitResult -= 10
} else {
carry = 0
}
if indexResult == -1 {
result = append(result, 0)
copy(result[1:], result[0:hightest])
indexResult=0
}
result[indexResult] = digitResult
indexResult--
}
return result
}
func convert(number int) (result []int) {
for {
if number == 0 {
return
}
result = append(result, number%10)
number /= 10
}
}
4.7.1906 - 2022-05-01 15:41:08 +0300 MSK
Links
Code
func sortedSquares(numbers []int) []int {
length := len(numbers)
if length == 0 || length == 1 {
return square(numbers, false)
}
negativesIndex := -1
for index, number := range numbers {
if number >= 0 {
negativesIndex = index
break
}
}
if negativesIndex == 0 || negativesIndex == -1 {
return square(numbers, negativesIndex == -1)
}
//fmt.Println("negativesIndex", negativesIndex)
result, resultIndex, negativesIndex := make([]int, length), 0, negativesIndex-1
for positivesIndex := negativesIndex + 1; resultIndex < length; positivesIndex++ {
positiveOverflow := positivesIndex >= length
for {
if negativesIndex < 0 || resultIndex >= length {
break
}
if !positiveOverflow && numbers[negativesIndex]*-1 > numbers[positivesIndex] {
break
}
result[resultIndex] = numbers[negativesIndex]
resultIndex++
//fmt.Println("negative", negativesIndex, resultIndex, numbers[negativesIndex], result, numbers)
negativesIndex--
}
if resultIndex < length && !positiveOverflow {
// fmt.Println("positivesIndex", positivesIndex, resultIndex, numbers[positivesIndex], result, numbers)
result[resultIndex] = numbers[positivesIndex]
resultIndex++
}
}
return square(result, false)
}
func square(array []int, reverse bool) []int {
if reverse {
length := len(array)
reversed := make([]int, length)
for index := length - 1; index >= 0; index-- {
reversed[length-index-1] = array[index] * array[index]
}
return reversed
} else {
for index, number := range array {
array[index] = number * number
}
return array
}
}
4.7.1907 - 2022-05-01 13:28:32 +0300 MSK
Links
Code
func merge(array1 []int, length1 int, array2 []int, length2 int) {
if length2 == 0 {
return
}
if length1 == 0 {
for index, number := range array2 {
array1[index] = number
}
return
}
index1, index2, array1Copy := 0, 0, make([]int, length1)
copy(array1Copy, array1)
for index := 0; index < length1+length2; index++ {
//fmt.Println(index, index1, index2, array1, array2)
for index2 < length2 && (index1 >= length1 || array2[index2] <= array1Copy[index1]) {
array1[index] = array2[index2]
index2++
index++
}
if index1 >= length1 {
continue
}
array1[index] = array1Copy[index1]
index1++
}
}
4.7.1908 - 2022-05-01 13:12:45 +0300 MSK
Links
Code
func merge(array1 []int, length1 int, array2 []int, length2 int) {
index1, index2, array1Copy := 0, 0, make([]int, length1)
copy(array1Copy, array1)
for index := 0; index < length1+length2; index++ {
fmt.Println(index, index1, index2, array1, array2)
if index2 < length2 && (index1 >= length1 || array2[index2] <= array1Copy[index1]) {
array1[index] = array2[index2]
index2++
continue
}
array1[index] = array1Copy[index1]
index1++
}
}
4.7.1909 - 2022-05-01 09:06:49 +0300 MSK
Links
Code
func mergeTwoLists(list1 *ListNode, list2 *ListNode) *ListNode {
// ensure both lists are valid
switch {
case list1 == nil && list2 == nil:
return nil
case list1 == nil && list2 != nil:
return list2
case list1 != nil && list2 == nil:
return list1
}
var root *ListNode
if list1.Val < list2.Val {
root = &ListNode{list1.Val, nil}
list1 = list1.Next
} else {
root = &ListNode{list2.Val, nil}
list2 = list2.Next
}
current := &root
for {
switch {
case list1 == nil && list2 == nil:
return root
case list1 != nil && list2 != nil && list1.Val <= list2.Val:
fallthrough
case list1 != nil && list2 == nil:
fmt.Println("1", list1.Val)
updateResult(¤t, &list1)
case list1 != nil && list2 != nil && list1.Val > list2.Val:
fallthrough
case list1 == nil && list2 != nil:
fmt.Println("2", list2.Val)
updateResult(¤t, &list2)
}
}
}
func updateResult(current ***ListNode, node **ListNode) {
// modify the current result node
(**current).Next = &ListNode{(*node).Val, nil}
// move the current pointer
*current = &(**current).Next
// there is no next node -> nill it
// there is next -> move it
if (*node).Next == nil {
*node = nil
} else {
*node = (*node).Next
}
}
4.7.1910 - 2022-04-30 22:06:12 +0300 MSK
Links
Code
func isValid(inputString string) bool {
if len(inputString) == 0 || (len(inputString)&1) != 0 {
return false
}
occurences := []rune{}
ends := map[rune]rune{')': '(', '}': '{', ']': '['}
for _, character := range inputString {
length := len(occurences)
last_valid, is_end := ends[character]
if (is_end && length == 0) || (is_end && occurences[length-1] != last_valid) {
return false
}
if is_end {
occurences = occurences[0 : length-1]
} else {
occurences = append(occurences, character)
}
}
if len(occurences) > 0 {
return false
}
return true
}
4.7.1911 - 2022-04-30 20:27:04 +0300 MSK
Links
Code
func kthPalindrome(queries []int, intLength int) (answer []int64) {
for _, query := range queries {
answer = append(answer, getPalindrom(query, intLength))
}
return
}
func getPalindrom(query int, length int) (result int64) {
is_even := (length & 1) == 0
power := length / 2
if is_even {
power -= 1
}
palindrome := int64(math.Pow10(power)) + int64(query) - 1
result = palindrome
if !is_even {
palindrome /= 10
}
for palindrome > 0 {
result = result*10 + palindrome%10
palindrome /= 10
}
if len(fmt.Sprint(result)) != length {
return -1
}
return
}
4.7.1912 - 2022-04-30 18:34:48 +0300 MSK
Links
Code
class Solution {
public long[] kthPalindrome(int[] queries, int intLength) {
long[] res= new long[queries.length];
for(int i=0;i<queries.length;i++){
res[i]=nthPalindrome(queries[i],intLength);
}
return res;
}
public long nthPalindrome(int nth, int kdigit)
{
long temp = (kdigit & 1)!=0 ? (kdigit / 2) : (kdigit/2 - 1);
long palindrome = (long)Math.pow(10, temp);
palindrome += nth - 1;
long res1=palindrome;
if ((kdigit & 1)>0)
palindrome /= 10;
while (palindrome>0)
{
res1=res1*10+(palindrome % 10);
palindrome /= 10;
}
String g="";
g+=res1;
if(g.length()!=kdigit)
return -1;
return res1;
}
}
4.7.1913 - 2022-04-30 09:12:31 +0300 MSK
Links
Code
func isPalindrome(number int) (result bool) {
if number < 0 {
return false
} else if number/10 == 0 {
return true
}
current := number
digits := []int{}
for {
if current == 0 {
break
}
digit := current % 10
current /= 10
digits = append(digits, digit)
}
digits_length := len(digits)
skip := -1
if digits_length%2 != 0 {
skip = digits_length / 2
}
for index, digit := range digits {
if index != skip && digit != digits[digits_length-index-1] {
return false
}
}
return true
}
4.7.1914 - 2022-04-30 08:49:48 +0300 MSK
Links
Code
import "sort"
func construct(root *TreeNode, results map[int]int) {
if root == nil {
return
}
if results[root.Val] < 2 {
results[root.Val] += 1
}
construct(root.Left, results)
construct(root.Right, results)
}
func sorted(input_map map[int]int) (results []int) {
for key := range input_map {
results = append(results, key)
}
return
}
func findTarget(root *TreeNode, target int) bool {
if root == nil {
return false
}
results := map[int]int{}
construct(root, results)
if target%2 == 0 && results[target/2] == 2 {
return true
}
results_sorted := sorted(results)
results_sorted_len := len(results_sorted)
sort.Ints(results_sorted)
for index, number := range results_sorted {
for index_inner := index + 1; index_inner < results_sorted_len; index_inner++ {
if number+results_sorted[index_inner] == target {
return true
}
}
}
return false
}
4.7.1915 - 2022-04-30 08:49:00 +0300 MSK
Links
Code
import "sort"
func construct(root *TreeNode, results map[int]bool, doubles map[int]bool) {
if root == nil {
return
}
_, exists := results[root.Val]
if !exists {
results[root.Val] = true
} else if _, double := doubles[root.Val]; exists && double {
doubles[root.Val] = true
}
construct(root.Left, results, doubles)
construct(root.Right, results, doubles)
}
func sorted(input_map map[int]bool) (results []int) {
for key := range input_map {
results = append(results, key)
}
return
}
func findTarget(root *TreeNode, target int) bool {
if root == nil {
return false
}
results := map[int]bool{}
doubles := map[int]bool{}
construct(root, results, doubles)
if _, double_exists := doubles[target/2]; target%2 == 0 && double_exists {
return true
}
results_sorted := sorted(results)
results_sorted_len := len(results_sorted)
sort.Ints(results_sorted)
for index, number := range results_sorted {
for index_inner := index + 1; index_inner < results_sorted_len; index_inner++ {
if number+results_sorted[index_inner] == target {
return true
}
}
}
return false
}
4.7.1916 - 2022-04-30 08:30:40 +0300 MSK
Links
Code
import "sort"
func construct(root *TreeNode, results map[int]int) {
if root == nil {
return
}
if results[root.Val] < 2 {
results[root.Val] += 1
}
construct(root.Left, results)
construct(root.Right, results)
}
func sorted(input_map map[int]int) (results []int) {
for key := range input_map {
results = append(results, key)
}
return
}
func findTarget(root *TreeNode, target int) bool {
if root == nil {
return false
}
results := map[int]int{}
construct(root, results)
if target%2 == 0 && results[target/2] == 2 {
return true
}
results_sorted := sorted(results)
results_sorted_len := len(results_sorted)
sort.Ints(results_sorted)
for index, number := range results_sorted {
for index_inner := index + 1; index_inner < results_sorted_len; index_inner++ {
if number+results_sorted[index_inner] == target {
return true
}
}
}
return false
}
4.7.1917 - 2022-04-30 07:52:06 +0300 MSK
Links
Code
func construct(root *TreeNode, results map[int]int) {
if root == nil {
return
}
if results[root.Val] < 2 {
results[root.Val] += 1
}
construct(root.Left, results)
construct(root.Right, results)
}
func findTarget(root *TreeNode, target int) bool {
results := map[int]int{}
construct(root, results)
for number, count := range results {
if count == 2 && number*2 == target {
return true
}
for number_inner := range results {
if number_inner <= number {
continue
}
if number+number_inner == target {
return true
}
}
}
return false
}
4.7.1918 - 2022-04-30 06:41:23 +0300 MSK
Links
Code
func twoSum(numbers []int, target int) []int {
numbers_len := len(numbers)
for index, number := range numbers {
for index_inner := index + 1; index_inner < numbers_len; index_inner++ {
if numbers[index_inner]+number == target {
return []int{index + 1, index_inner + 1}
}
}
}
return []int{}
}
4.7.1919 - 2022-04-30 06:29:16 +0300 MSK
Links
Code
func twoSum(numbers []int, target int) []int {
numbers_len := len(numbers)
for index, number := range numbers {
for index_inner := index + 1; index_inner < numbers_len; index_inner++ {
if numbers[index_inner]+number == target {
return []int{index, index_inner}
}
}
}
return []int{}
}
4.7.1920 - 2022-04-30 05:36:04 +0300 MSK
Links
Code
func reverse(list *ListNode) *ListNode {
if list == nil || list.Next == nil {
return list
}
result := &ListNode{list.Val, nil}
current := list.Next
for {
if current == nil {
return result
}
result = &ListNode{current.Val, result}
current = current.Next
}
}
func addTwoNumbers(list_1 *ListNode, list_2 *ListNode) *ListNode {
current_1, current_2, result := reverse(list_1), reverse(list_2), &ListNode{}
var carry int
result_current := result
for {
var value_1, value_2 int
if current_1 != nil {
value_1 = current_1.Val
current_1 = current_1.Next
}
if current_2 != nil {
value_2 = current_2.Val
current_2 = current_2.Next
}
sum := value_1 + value_2 + carry
if sum > 9 {
sum -= 10
carry = 1
} else {
carry = 0
}
result_current.Val = sum
if current_1 == nil && current_2 == nil && carry == 0 {
result_current.Next = nil
return reverse(result)
} else if current_1 == nil && current_2 == nil && carry != 0 {
current_1 = &ListNode{}
}
result_current.Next = &ListNode{}
result_current = result_current.Next
}
}
4.7.1921 - 2022-04-29 22:10:38 +0300 MSK
Links
Code
func addTwoNumbers(list_1 *ListNode, list_2 *ListNode) *ListNode {
current_1, current_2, result := list_1, list_2, &ListNode{}
var carry int
result_current := result
for {
var value_1, value_2 int
if current_1 != nil {
value_1 = current_1.Val
current_1 = current_1.Next
}
if current_2 != nil {
value_2 = current_2.Val
current_2 = current_2.Next
}
sum := value_1 + value_2 + carry
if sum > 9 {
sum -= 10
carry = 1
} else {
carry = 0
}
result_current.Val = sum
if current_1 == nil && current_2 == nil && carry == 0 {
result_current.Next = nil
return result
} else if current_1 == nil && current_2 == nil && carry != 0 {
current_1 = &ListNode{}
}
result_current.Next = &ListNode{}
result_current = result_current.Next
}
}
4.7.1922 - 2022-04-29 19:52:46 +0300 MSK
Links
Code
func longestCommonPrefix(strings []string) string {
switch len(strings) {
case 0:
return ""
case 1:
return strings[0]
}
result := strings[0]
for index := 1; index < len(strings); index++ {
current := strings[index]
previous := strings[index-1]
current_max := len(current)
result_max := len(result)
var slice_max int
if result_max > current_max {
slice_max = current_max
result = result[0:slice_max]
} else {
slice_max = result_max
}
for ; slice_max >= 0; slice_max-- {
current_slice := current[0:slice_max]
if current_slice == previous[0:slice_max] {
result = current_slice
break
}
if slice_max == 0 {
return ""
}
}
}
return result
}
4.7.1923 - 2022-04-29 18:51:04 +0300 MSK
Links
Code
func substrings(input string) map[string]bool {
results := make(map[string]bool)
for index := range input {
results[input[0:index+1]] = true
}
return results
}
func string_in_maps(
source map[string]bool,
target map[string]bool,
results map[string]bool) {
for string := range source {
is_valid, exists_in_results := results[string]
_, exists_in_target := target[string]
switch {
case !exists_in_target:
fallthrough
case exists_in_target && (is_valid || !exists_in_results):
results[string] = exists_in_target
}
}
}
func longestCommonPrefix(strings []string) (result string) {
results := make(map[string]bool)
var previous map[string]bool
for index, string := range strings {
current := substrings(string)
if index == 0 {
previous = current
}
string_in_maps(previous, current, results)
string_in_maps(current, previous, results)
previous = current
}
for string, valid := range results {
if valid && len(string) > len(result) {
result = string
}
}
return
}
4.7.1924 - 2022-04-29 18:09:02 +0300 MSK
Links
Code
import "fmt"
func substrings(input string) map[string]bool {
results := make(map[string]bool)
for index := range input {
results[string(input[0:index+1])] = true
}
return results
}
func string_in_maps(
source map[string]bool,
target map[string]bool,
results map[string]bool) {
for string := range source {
if result, exists_in_results := results[string]; exists_in_results && !result {
continue
}
_, exists_in_target := target[string]
results[string] = exists_in_target
}
}
func longestCommonPrefix(strings []string) (result string) {
results := make(map[string]bool)
previous := make(map[string]bool)
for index, string := range strings {
current := substrings(string)
if index == 0 {
previous = current
}
string_in_maps(current, previous, results)
string_in_maps(previous, current, results)
fmt.Println("current string", string, current, "results", results)
previous = current
}
for string, valid := range results {
if !valid || len(string) < len(result) {
continue
}
if len(string) == len(result) && string < result {
result = string
continue
}
result = string
}
fmt.Println("result", result)
return
}
4.7.1925 - 2022-04-28 09:04:20 +0300 MSK
Links
Code
func romanToInt(input string) int {
var result int
types := map[rune]int{
'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000,
}
var previous rune
for _, character := range input {
result += types[character]
switch {
case previous == 'I' && (character == 'V' || character == 'X'):
fallthrough
case previous == 'X' && (character == 'L' || character == 'C'):
fallthrough
case previous == 'C' && (character == 'D' || character == 'M'):
result -= types[previous] * 2
}
previous = character
}
return result
}
4.7.1926 - 2022-04-28 08:59:35 +0300 MSK
Links
Code
func in(character rune, targets string) bool {
for _, target := range targets {
if character == target {
return true
}
}
return false
}
func romanToInt(roman string) int {
type dict map[rune]int
var result int
input := []rune(roman)
types := dict{
'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000,
}
var previous rune
for _, character := range input {
result += types[character]
switch {
case previous == 'I' && in(character, "VX"):
fallthrough
case previous == 'X' && in(character, "LC"):
fallthrough
case previous == 'C' && in(character, "DM"):
result -= types[previous] * 2
}
previous = character
}
return result
}
4.7.1927 - 2022-04-28 08:59:06 +0300 MSK
Links
Code
func in(character rune, targets string) bool {
for _, target := range targets {
if character == target {
return true
}
}
return false
}
func romanToInt(roman string) int {
type dict map[rune]int
var result int
types := dict{
'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000,
}
for index, character := range roman {
result += types[character]
if index < 1 {
continue}
switch {
case roman[index-1] == 'I' && in(character, "VX"):
fallthrough
case roman[index-1] == 'X' && in(character, "LC"):
fallthrough
case roman[index-1] == 'C' && in(character, "DM"):
result -= types[rune(roman[index-1])] * 2
}
}
return result
}
4.7.1928 - 2022-04-28 08:55:16 +0300 MSK
Links
Code
func in(character rune, targets string) bool {
for _, target := range targets {
if character == target {
return true
}
}
return false
}
func romanToInt(roman string) int {
type dict map[rune]int
var result int
input := []rune(roman)
types := dict{
'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000,
}
var previous rune
for _, character := range input {
result += types[character]
switch {
case previous == 'I' && in(character, "VX"):
fallthrough
case previous == 'X' && in(character, "LC"):
fallthrough
case previous == 'C' && in(character, "DM"):
result -= types[previous] * 2
}
previous = character
}
return result
}
4.8 - Mullvad
Device limit
Mullvad will invalidate a key If a host connects to many vpns with it at the same time
4.10 - Pgp
Openpgp with Yubikey
https://support.yubico.com/s/article/Using-Your-YubiKey-with-OpenPGP
Advanced Yubikey with openpgp guide
4.11 - Ping
sendmsg: operation not permitted
This problem can be caused by vpns with “kill-switch” enabled, so you might need to disable them.
Disable Mullvad VPN:
sudo systemctl disable --now mullvad-daemon
4.13 - Repo
Setup
- Install packages:
sudo dnf install \ clang clang-tools-extra java-latest-openjdk-devel rust cargo mesa-libGL-devel \ go Xvfb python3 gmp-devel patch podman git git-lfs fuse fuse-libs pcsc-lite pcsc-lite-devel \ openssl gnutls-utils opensc openssl-pkcs11 libdnet qemu-kvm qemu-img - Install bazelisk: https://bazel.build/install/bazelisk
- Symlink bazel:
ln -s ~/.local/bin/bazelisk ~/.local/bin/bazel - Install git hooks:
bazel run //:write_git_hooks - Install android tools:
The empty repository environment is required for the first installation so Bazel does not try to load the SDK before
ANDROID_HOME="${HOME}/Android/Sdk" \ bazel run --config=agent \ --repo_env=ANDROID_HOME= \ //tools/android:installsdkmanagerinstalls it. Afterwards, exportANDROID_HOMEandANDROID_NDK_HOME, or set both with--repo_envin the ignoreduser.bazelrc. The repository dotfiles export the expected paths. - Setup dotfiles (optional):
bazel run //projects/dotfiles:install - Install nvm: https://github.com/nvm-sh/nvm
- Install node:
nvm install node - Qt is downloaded by Bazel; no host installation is required.
Vault login
bazel run //tools/vault -- login --method=userpass username="${USER}"
Setup .bzlenv
. "$(bazel run //tools/bzlenv)"
Compile commands
Build compile_commands.json:
bazel run :refresh_compile_commands
Build everything
This requires around 90G
bazel build //...
Test everything
bazel test //...
Replace a rule with another one
find \
"(" -name "*.bazel" -o -name "*.bzl" -o -name ".bazelrc" -o -name "*.md" ")" \
-type f \
-exec sed -i 's|//bzl/rules/txt|//tools/txt|g' "{}" ";"`
Parse a tar manifest
bazel build //projects/alwaldend.com:site_source_archive && \
cat bazel-bin/projects/alwaldend.com/site_source_archive.manifest | \
jq -r --slurp ". | flatten | .[].dest" | \
grep "^content"
Remove a rule
find -name "BUILD.bazel" -type f -exec sed -i '/al_readme(/,/)/d' "{}" ";"
Find all public targets (ignores default_visibility)
bazel query 'attr(visibility, "//visibility:public", //...)'
Adding a bazel module
mkdir projects/project_name
cd projects/project_name
ln -s ../../.bazelignore
ln -s ../../.bazeliskrc
ln -s ../../tools/bazelrc/bzl_project.bazelrc .bazelrc
Ssh key using Yubikey’s pgp doesn’t work
Agent restart helps:
gpg-connect-agent updatestartuptty /bye
Check the key:
bazel run //tools/ykman -- info
Remote timeout
If some repo rules are timing out (java ones, for example), you can add
--remote_timeout 1000000
Update pnpm lock
bazel run //tools/pnpm -- --dir "${PWD}" install
Documentation: https://github.com/aspect-build/rules_js/blob/main/docs/pnpm.md#update_pnpm_lock
Ssh config
Proxmox VMs have Kerberos enabled, which slows SSH down, you need to disable it locally
~/.ssh/config.d/config:
GSSAPIAuthentication no
Update certificates on Fedora
sudo cp infra/vault/tf/output/pki_ca_servers.crt /etc/pki/ca-trust/source/anchors/
sudo update-ca-trust
Run go mod tidy
find -name "go.mod" -exec sh -c 'cd "$(dirname "{}")" && bazel run @rules_go//go -- mod tidy' ";"
4.14 - Rfc
4.14.1 - Rfc2119
Html
Txt
- Original: https://www.rfc-editor.org/rfc/rfc2119.txt
- Local: ./rfc.txt
Network Working Group S. Bradner
Request for Comments: 2119 Harvard University
BCP: 14 March 1997
Category: Best Current Practice
Key words for use in RFCs to Indicate Requirement Levels
Status of this Memo
This document specifies an Internet Best Current Practices for the
Internet Community, and requests discussion and suggestions for
improvements. Distribution of this memo is unlimited.
Abstract
In many standards track documents several words are used to signify
the requirements in the specification. These words are often
capitalized. This document defines these words as they should be
interpreted in IETF documents. Authors who follow these guidelines
should incorporate this phrase near the beginning of their document:
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL
NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and
"OPTIONAL" in this document are to be interpreted as described in
RFC 2119.
Note that the force of these words is modified by the requirement
level of the document in which they are used.
1. MUST This word, or the terms "REQUIRED" or "SHALL", mean that the
definition is an absolute requirement of the specification.
2. MUST NOT This phrase, or the phrase "SHALL NOT", mean that the
definition is an absolute prohibition of the specification.
3. SHOULD This word, or the adjective "RECOMMENDED", mean that there
may exist valid reasons in particular circumstances to ignore a
particular item, but the full implications must be understood and
carefully weighed before choosing a different course.
4. SHOULD NOT This phrase, or the phrase "NOT RECOMMENDED" mean that
there may exist valid reasons in particular circumstances when the
particular behavior is acceptable or even useful, but the full
implications should be understood and the case carefully weighed
before implementing any behavior described with this label.
Bradner Best Current Practice [Page 1]
RFC 2119 RFC Key Words March 1997
5. MAY This word, or the adjective "OPTIONAL", mean that an item is
truly optional. One vendor may choose to include the item because a
particular marketplace requires it or because the vendor feels that
it enhances the product while another vendor may omit the same item.
An implementation which does not include a particular option MUST be
prepared to interoperate with another implementation which does
include the option, though perhaps with reduced functionality. In the
same vein an implementation which does include a particular option
MUST be prepared to interoperate with another implementation which
does not include the option (except, of course, for the feature the
option provides.)
6. Guidance in the use of these Imperatives
Imperatives of the type defined in this memo must be used with care
and sparingly. In particular, they MUST only be used where it is
actually required for interoperation or to limit behavior which has
potential for causing harm (e.g., limiting retransmisssions) For
example, they must not be used to try to impose a particular method
on implementors where the method is not required for
interoperability.
7. Security Considerations
These terms are frequently used to specify behavior with security
implications. The effects on security of not implementing a MUST or
SHOULD, or doing something the specification says MUST NOT or SHOULD
NOT be done may be very subtle. Document authors should take the time
to elaborate the security implications of not following
recommendations or requirements as most implementors will not have
had the benefit of the experience and discussion that produced the
specification.
8. Acknowledgments
The definitions of these terms are an amalgam of definitions taken
from a number of RFCs. In addition, suggestions have been
incorporated from a number of people including Robert Ullmann, Thomas
Narten, Neal McBurnett, and Robert Elz.
Bradner Best Current Practice [Page 2]
RFC 2119 RFC Key Words March 1997
9. Author's Address
Scott Bradner
Harvard University
1350 Mass. Ave.
Cambridge, MA 02138
phone - +1 617 495 3864
email - sob@harvard.edu
Bradner Best Current Practice [Page 3]
4.15 - Shell
Deactivate venv in subshell
A subshell doesn’t have the deactivate function, so you have to use a
workaround:
. .venv/bin/activate
(
echo "subshell, still in venv: $(which python)" && \
. "$(dirname "$(which python)")/activate" && \
deactivate && \
echo "subshell, out of venv: $(which python)"
)
A subshell () is different from a subprocess
https://unix.stackexchange.com/a/138498
A subshell starts out as an almost identical copy of the original shell process. Under the hood, the shell calls the fork system call1, which creates a new process whose code and memory are copies2. When the subshell is created, there are very few differences between it and its parent. In particular, they have the same variables. Even the $$ special variable keeps the same value in subshells: it’s the original shell’s process ID. Similarly $PPID is the PID of the parent of the original shell.
A few shells change a few variables in the subshell. Bash ≥4.0 sets BASHPID to the PID of the shell process, which changes in subshells. Bash, zsh and mksh arrange for $RANDOM to yield different values in the parent and in the subshell. But apart from built-in special cases like these, all variables have the same value in the subshell as in the original shell, the same export status, the same read-only status, etc. All function definitions, alias definitions, shell options and other settings are inherited as well.
A subshell created by (…) has the same file descriptors as its creator. Some other means of creating subshells modify some file descriptors before executing user code; for example, the left-hand side of a pipe runs in a subshell3 with standard output connected to the pipe. The subshell also starts out with the same current directory, the same signal mask, etc. One of the few exceptions is that subshells do not inherit custom traps: ignored signals (trap ’’ SIGNAL) remain ignored in the subshell, but other traps (trap CODE SIGNAL) are reset to the default action4.
A subshell is thus different from executing a script. A script is a separate program. This separate program might coincidentally be also a script which is executed by the same interpreter as the parent, but this coincidence doesn’t give the separate program any special visibility on internal data of the parent. Non-exported variables are internal data, so when the interpreter for the child shell script is executed, it doesn’t see these variables. Exported variables, i.e. environment variables, are transmitted to executed programs.
4.17 - Ssl
- How to create your own CA: https://arminreiter.com/2022/01/create-your-own-certificate-authority-ca-using-openssl/
- Vault PKI: https://developer.hashicorp.com/vault/tutorials/pki/pki-engine
4.18 - Todo
Setup proper issue tracking
Setup API docs for python, go, lua
Codify build restrictions
//projects builds should not depend on //tools, etc
Maybe wth aspects, aspect hints? Or check deps using genquery?
Fix infinitime build in //projects/infinitime
Add missing code for //projects/nexus_security_plugin and //projects/ci_platform
Setup java language server
Setup a script that adds bazel tools to ${PATH}
Write firefox extension for //projects/leetcode_downloader
Write tool to sync remote repos with local FS
Rewrite python checkers to aspects
Add prettier checks
4.19 - Vault
Manual certificate creation
https://arminreiter.com/2022/01/create-your-own-certificate-authority-ca-using-openssl/
Unseal process
- Get the encrypted unseal key
- Unencrypt it:
cat unseal.txt | base64 --decode | gpg -dq - Run
vault operator unseal
4.20 - Waydroid
Links
Shared folder and copying files
chmod 777 file
sudo cp file ~/.local/share/waydroid/data/media/0/Download/
5 - Data
This tree contains repository-owned data and documentation assets. All tracked content follows the repository’s public-source policy. Actual credentials, personal information, and secret-bearing generated values remain prohibited.
Requirements
- Bazel targets MUST use repository-internal visibility.
- The tree MUST NOT be independently published as a product artifact.
- Data and documentation assets MAY be used in builds and MAY be embedded in an explicitly owned published artifact when that owner permits it.
5.2 - Books
Books
[[book]]
title = "Reverend Insanity"
alt_titles = ["Gu Daoist Master", "蛊真人"]
thumbnail = "https://cdn.novelupdates.com/images/2025/06/Reverend-Insanity.jpg"
quality = "Peak"
reading = "Finished available, C2334"
authors = ["gu-zhen-ren"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/reverend-insanity/" },
]
[[book]]
title = "Virtuous Sons"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/41330-virtuous-sons-a-greco-roman-xianxia.jpg"
quality = "Peak"
reading = "Finished available (hiatus), C2.22"
authors = ["ya-boy"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/41330/virtuous-sons-a-greco-roman-xianxia" },
]
[[book]]
title = "My Longevity Simulation"
thumbnail = "https://cdn.novelupdates.com/images/2024/08/My-Longevity-Simulation.jpg"
quality = "Good"
reading = "Dropped, C838"
authors = ["angry-squid"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/my-longevity-simulation/" },
{ title = "novelbin", url = "https://novelbin.com/b/my-longevity-simulation/chapter-724" },
]
[[book]]
title = "Unintended Immortality"
alt_titles = ["The Unintentional Path to Immortality", "我本无意成仙"]
thumbnail = "https://cdn.novelupdates.com/images/2024/11/The-Unintentional-Path-to-Immortality.jpg"
quality = "Good"
reading = "Finished, C713"
authors = ["golden-jasmine"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/the-unintentional-path-to-immortality/" },
{ title = "novelfile", url = "https://novelfire.net/book/unintended-immortality/chapter-447" },
]
[[book]]
title = "Lord of the Mysteries"
thumbnail = "https://cdn.novelupdates.com/images/2018/11/Lord-of-the-Mysteries.jpeg"
quality = "Good"
reading = "Finished volume 2"
authors = ["cuttlefish-that-loves-diving"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/lord-of-the-mysteries/" },
]
[[book]]
title = "Ze Tian Ji"
alt_titles = ["Way of Choices", "择天记"]
thumbnail = "https://cdn.novelupdates.com/images/2015/06/Zetianji.jpg"
quality = "Good"
reading = "Finished"
authors = ["mao-ni"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/ze-tian-ji/" },
]
[[book]]
title = "The Path Toward Heaven"
alt_titles = ["大道朝天"]
thumbnail = "https://cdn.novelupdates.com/images/2017/10/pathtowardheaven.jpg"
quality = "Good"
reading = "Finished available chapters"
authors = ["mao-ni"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/the-path-toward-heaven/" },
]
[[book]]
title = "Nightfall"
alt_titles = ["Ever Night", "将夜"]
thumbnail = "https://cdn.novelupdates.com/images/2015/06/JiangYe-.jpg"
quality = "Good"
reading = "Finished"
authors = ["mao-ni"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/nightfall/" },
]
[[book]]
title = "The Experimental Log of the Crazy Lich"
alt_titles = ["疯巫妖的实验日志"]
thumbnail = "https://cdn.novelupdates.com/images/2017/11/The-Experimental-Log-of-the-Crazy-Lich.jpg"
quality = "Good"
reading = "Finished volume 1"
authors = ["angry-squirrel"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/the-experimental-log-of-the-crazy-lich/" },
]
[[book]]
title = "The Sage Who Transcended Samsara"
alt_titles = ["一世之尊"]
thumbnail = "https://cdn.novelupdates.com/images/2019/05/17435126d0d51135aa4a70eb4c00f08bc818d0de901c670ce979f03a966bf10f.jpg"
quality = "Good"
reading = "Finished, dropped at the end"
authors = ["cuttlefish-that-loves-diving"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/the-sage-who-transcended-samsara/" },
]
[[book]]
title = "Outside of time"
alt_titles = ["光阴之外"]
thumbnail = "https://cdn.novelupdates.com/images/2024/08/Outside-of-Time.jpg"
quality = "Ok"
reading = "Dropped, C1470"
authors = ["er-gen"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/beyond-the-timescape/" },
]
[[book]]
title = "Archfiend"
alt_titles = ["最强妖孽"]
thumbnail = "https://cdn.novelupdates.com/images/2017/11/strongest-evildoer.jpeg"
quality = "Decent"
reading = "Finished translated chapters, chapter 528"
authors = ["nocturnal-stranger"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/archfiend/" },
]
[[book]]
title = "Godclads"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/59663-godclads.jpg"
quality = "Good, a bit too dramatic"
reading = "Dropped, C37-11"
authors = ["ostensible-mammal"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/59663/godclads" },
]
[[book]]
title = "Defiance of the Fall"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/24709-defiance-of-the-fall.jpg"
quality = "Decent"
reading = "Dropped, C1370"
authors = ["thefirstdefier"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/24709/defiance-of-the-fall" },
]
[[book]]
title = "Matabar"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/matabar-aaaa9rj72ru.jpg"
quality = "Good"
reading = "Dropped, chapter 120"
authors = ["kirill-klevanski"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/94398/matabar" },
]
[[book]]
title = "Renegade Immortal"
thumbnail = "https://cdn.novelupdates.com/images/2016/03/xianni-1.jpg"
quality = "Good"
reading = "Finished"
authors = ["er-gen"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/renegade-immortal/" },
]
[[book]]
title = "The Years of Apocalypse"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/the-years-of-apocalypse-a-time-loop-progression.jpg"
quality = "Decent"
reading = "Dropped, C226"
authors = ["uraniumphoenix"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/81002/the-years-of-apocalypse-a-time-loop-progression" },
]
[[book]]
title = "Downtown Druid"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/79173-downtown-druid.jpg"
quality = "Decent"
reading = "Finished volume 1"
authors = ["seersucker"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/79173/downtown-druid-book-1-stubbed" },
]
[[book]]
title = "A Practical Guide to Sorcery"
thumbnail = "https://www.azaleaellis.com/wp-content/uploads/2022/10/A-Conjuring-of-Ravens-Web-800w-683x1024.jpg"
quality = "Decent, slow upload"
reading = "Dropped, C262"
authors = ["azalea-ellis"]
links = [
{ title = "azaleaellis", url = "https://www.azaleaellis.com/a-practical-guide-to-sorcery/" },
]
[[book]]
title = "Dungeon Crawler Carl"
thumbnail = "https://www.royalroadcdn.com/public/covers-full/29358-dungeon-crawler-carl.jpg"
quality = "Good"
reading = "Finished available, B7"
authors = ["doctorhepa"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/29358/dungeon-crawler-carl-book-6-the-ghosts-of-earth" },
]
[[book]]
title = "Beware Of Chicken"
thumbnail = "https://www.royalroadcdn.com/public/covers-full/beware-of-chicken-aacav1xoeg8.jpg"
quality = "Decent"
reading = "Dropped, V4(V6)C68"
authors = ["casualfarmer"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/39408/beware-of-chicken" },
]
[[book]]
title = "I Shall Seal the Heavens"
thumbnail = "https://cdn.novelupdates.com/images/2015/06/15_ISSTH.jpg"
quality = "Good"
reading = "Finished"
authors = ["er-gen"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/i-shall-seal-the-heavens/" },
]
[[book]]
title = "World of Cultivation"
alt_titles = ["修真世界"]
quality = "Good"
reading = "Finished"
authors = ["fang-xiang"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/world-of-cultivation/" },
]
[[book]]
title = "Return of the Runebound Professor"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/68679-return-of-the-runebound-professor.jpg"
quality = "Ok"
reading = "Reading, B7C749"
authors = ["actus"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/68679/return-of-the-runebound-professor-book-6-stubbed" },
]
[[book]]
title = "I Am Become Death"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/109537-i-am-become-death-a-progression-fantasy.jpg"
quality = "Decent"
summary = "Nothing exceptional"
reading = "Dropped, chapter 55"
authors = ["clarke"]
links = [
{ title = "royalroard", url = "https://www.royalroad.com/fiction/109537/i-am-become-death-a-progression-fantasy-cultivation-based" },
]
[[book]]
title = "Ghost of the Truthseeker"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/56136-ghost-of-the-truthseeker.jpg"
quality = "Ok"
reading = "Dropped, chapter 220"
authors = ["strungbound"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/56136/ghost-of-the-truthseeker-book-4-being-released" },
]
[[book]]
title = "The Beginning After the End"
thumbnail = "https://upload.wikimedia.org/wikipedia/en/c/cc/The_Beginning_After_the_End_webtoon_volume_1_cover.jpg"
quality = "Bad, isekai slop"
reading = "Dropped, volume 1, chapter 13"
authors = ["turtleme"]
links = [
{ title = "wikipedia", url = "https://en.wikipedia.org/wiki/The_Beginning_After_the_End" },
]
[[book]]
title = "Rise of the Living Forge"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/79094-rise-of-the-living-forge-stubbing-in-october.jpg"
quality = "Ok"
reading = "Dropped, C509"
authors = ["actus"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/79094/rise-of-the-living-forge-a-blacksmith-litrpg" },
]
[[book]]
title = "Vigor Mortis"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/40373-vigor-mortis.jpg"
quality = "Ok"
reading = "Dropped, V4C27"
authors = ["thundamoo"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/40373/vigor-mortis" },
]
[[book]]
title = "Ultimate Level 1"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/76259-ultimate-level-1-litrpg-book-8-stubs-531.jpg"
quality = "Bad, litrpg slop"
reading = "Dropped, V1C17"
authors = ["dads-bedtime-stories"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/76259/ultimate-level-1-litrpg" },
]
[[book]]
title = "If It’s for My Daughter, I’d Even Defeat a Demon Lord"
thumbnail = "https://cdn.novelupdates.com/images/2020/05/uchimusuLNv2.jpg"
quality = "Bad, Japanese slice-of-life litrpg fantasy slop"
reading = "Dropped, V4C2"
authors = ["chirolu"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/if-its-for-my-daughter-id-even-defeat-a-demon-lord/" },
]
[[book]]
title = "Mark of the Fool"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/41618-mark-of-the-fool.jpg"
quality = "Decent, not enough progression"
reading = "Finished"
authors = ["clarke"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/41618/mark-of-the-fool" },
]
[[book]]
title = "DIE. RESPAWN. REPEAT."
thumbnail = "https://www.royalroadcdn.com/public/covers-large/66643-die-respawn-repeat.jpg"
quality = "Decent, a bit bland"
reading = "Dropped, volume 4, chapter 8 (chapter 222)"
authors = ["silverlinings"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/66643/die-respawn-repeat" },
]
[[book]]
title = "System Breaker"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/89249-system-breaker-xianxia-system-apocalypse.jpg"
quality = "Decent, MC is a bit immature"
reading = "Dropped, volume 2, chapter 55"
authors = ["ostensiblemammal"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/89249/system-breaker-xianxia-system-apocalypse-litrpg" },
]
[[book]]
title = "Reborn as a Demonic Tree"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/62881-reborn-as-a-demonic-tree.jpg"
quality = "Ok, mediocre"
reading = "Dropped, volume 8, chapter 421"
authors = ["xkarnation"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/62881/reborn-as-a-demonic-tree" },
]
[[book]]
title = "Accel World"
thumbnail = "https://cdn.novelupdates.com/images/2023/08/Accel-World.jpg"
quality = "Bad, japanese slop"
reading = "Dropped at some point"
authors = ["kawahara-reki"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/accel-world/" },
]
[[book]]
title = "The Jester of Apocalypse"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/62411-the-jester-of-apocalypse.jpg"
quality = "Ok, basic and a bit edgy"
reading = "Finished available chapters"
authors = ["robert-blaise"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/62411/the-jester-of-apocalypse" },
]
[[book]]
title = "Throne of Magical Arcana"
thumbnail = "https://cdn.novelupdates.com/images/2017/04/Throne-of-Magical-Arcana.jpg"
quality = "Decent, a bit mediocre"
reading = "Dropped near the end when the main plot ended"
authors = ["cuttlefish-that-loves-diving"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/throne-of-magical-arcana/" },
]
[[book]]
title = "The Charm of Soul Pets"
thumbnail = "https://cdn.novelupdates.com/images/2016/08/The-Charm-of-Soul-Pets-1.jpg"
quality = "Don't remember"
reading = "Dropped, chapter 42"
authors = ["chaos"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/the-charm-of-soul-pets/" },
]
[[book]]
title = "12 Miles Below"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/42367-12-miles-below.jpg"
quality = "Decent"
reading = "Dropped at some point"
authors = ["mark-arrows"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/42367/12-miles-below" },
]
[[book]]
title = "Worm"
thumbnail = "https://parahumans.wordpress.com/wp-content/uploads/2011/06/cityscape2.jpg"
quality = "Decent"
reading = "Finished"
authors = ["wildbow"]
links = [{ title = "website", url = "https://parahumans.wordpress.com/" }]
[[book]]
title = "Full Murderhobo"
thumbnail = "https://i.gr-assets.com/images/S/compressed.photo.goodreads.com/books/1598478055i/55134991._SX120_.jpg"
quality = "Ok, a bit basic"
reading = "Finished, volume 3"
authors = ["dakota-krout"]
links = [
{ title = "goodreads", url = "https://www.goodreads.com/series/298351-full-murderhobo" },
]
[[book]]
title = "The Divine Dungeon"
thumbnail = "https://images-na.ssl-images-amazon.com/images/S/compressed.photo.goodreads.com/books/1476063034i/32509131.jpg"
quality = "Ok, a bit basic"
reading = "Finished"
authors = ["dakota-krout"]
links = [
{ title = "goodreads", url = "https://www.goodreads.com/series/192510-the-divine-dungeon" },
]
[[book]]
title = "SSS-Class Suicide Hunter"
thumbnail = "https://cdn.novelupdates.com/images/2021/05/SSSClass-Suicide-Hunter.jpg"
quality = "Ok, too much emotional bullshit"
reading = "Dropped at some point"
authors = ["sinnoa"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/sss-class-suicide-hunter" },
]
[[book]]
title = "Corpo Age"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/75446-corpo-age-cyberpunk-progression-litrpg.jpg"
quality = "Ok, feels basic"
reading = "Dropped, volume 1, chapter 2"
authors = ["randombluecat"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/75446/corpo-age" },
]
[[book]]
title = "Shen Yin Wang Zuo"
alt_titles = ["Sealed Divine Throne", "神印王座"]
thumbnail = "https://cdn.novelupdates.com/images/2015/06/sywz.jpg"
quality = "Bad, too bland"
reading = "Dropped, chapter 101"
authors = ["tang-jia-san-shao"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/shen-yin-wang-zuo/" },
]
[[book]]
title = "Warlock of the Magus World"
thumbnail = "https://cdn.novelupdates.com/images/2022/05/Warlock-of-the-Magus-World_1653417756.jpg"
quality = "Bad, edgy slop, too much 'AI chip, do the thing'"
reading = "Dropped, chapter 58"
authors = ["the-plagiarist"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/warlock-of-the-magus-world/" },
]
[[book]]
title = "Perfect World"
thumbnail = "https://cdn.novelupdates.com/images/2018/03/perfectworld.jpeg"
quality = "Don't remember, children are boring"
reading = "Dropped, chapter 75"
authors = ["chen-dong"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/perfect-world/" },
]
[[book]]
title = "Trash of the Count’s Family"
thumbnail = "https://cdn.novelupdates.com/images/2022/10/Trash-of-the-Counts-Family.jpg"
quality = "Bad"
summary = "Korean slop, the same stuff happens over and over again, endless saving of useless garbage, humble bragging"
reading = "Dropped, chapter 215"
authors = ["yu-ryeo-han"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/trash-of-the-counts-family/" },
]
[[book]]
title = "Forty Millenniums of Cultivation"
alt_titles = ["Forty Thousand Years Of Cultivation", "修真四万年"]
thumbnail = "https://cdn.novelupdates.com/images/2017/03/Forty-Millenniums-of-Cultivation.jpg"
quality = "Ok"
summary = "Good worldbuilding, but too many empty exclamations and not enough substance"
reading = "Dropped, chapter 2935"
authors = ["the-enlightened-master-crouching-cow"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/forty-millenniums-of-cultivation/" },
]
[[book]]
title = "The Empty Box and Zeroth Maria"
alt_titles = ["Utsuro no Hako to Zero no Maria", "空ろの箱と零のマリア"]
thumbnail = "https://cdn.novelupdates.com/images/2023/04/Utsuro-no-Hako-to-Zero-no-Maria.jpg"
quality = "Decent?"
summary = "Don't remember"
reading = "Finished"
authors = ["mikage-eiji"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/utsuro-no-hako-to-zero-no-maria/" },
]
[[book]]
title = "Rune Seeker"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/73095-rune-seeker-a-progression-fantasy-litrpg.jpg"
quality = "Ok"
summary = "Shallow"
reading = "Dropped, volume 2, chapter 12"
authors = ["clarke"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/73095/rune-seeker-a-progression-fantasy-litrpg-book" },
]
[[book]]
title = "Chrysalis"
thumbnail = "https://www.royalroadcdn.com/public/covers-full/22518-chrysalis.jpg"
quality = "Ok"
reading = "Dropped, C1654"
authors = ["rinoz"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/22518/chrysalis" },
]
[[book]]
title = "My House of Horrors"
alt_titles = ["我有一座冒险屋"]
thumbnail = "https://cdn.novelupdates.com/images/2024/09/My-House-of-Horrors.jpg"
quality = "Ok"
summary = "Repetitive"
reading = "Dropped at some point"
authors = ["can-fix-air-conditioners"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/my-house-of-horrors/" },
]
[[book]]
title = "The Spiritual Attainment of Minghe"
alt_titles = ["明和的精神境界"]
thumbnail = "https://cdn.novelupdates.com/images/2018/02/attain1.jpg"
quality = "Ok"
summary = "Shallow, bad translation"
reading = "Dropped, chapter 8"
authors = ["god-loves-the-world"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/the-spiritual-attainment-of-minghe/" },
]
[[book]]
title = "Unbound"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/30321-unbound.jpg"
quality = "Ok"
summary = "Shallow"
reading = "Dropped, finisehd volume 3"
authors = ["necariin"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/30321/unbound" },
]
[[book]]
title = "The Stubborn Skill-Grinder In A Time Loop"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/83294-the-stubborn-skill-grinder-in-a-time-loop.jpg"
quality = "Ok"
summary = "Shallow litrpg slop"
reading = "Dropped, chapter 44"
authors = ["x-rhoden-x"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/83294/the-stubborn-skill-grinder-in-a-time-loop" },
]
[[book]]
title = "I Shall Be Everlasting In the World of Immortals"
alt_titles = ["我在修仙界万古长青"]
thumbnail = "https://cdn.novelupdates.com/images/2024/08/I-Shall-Be-Everlasting-In-the-World-of-Immortals.jpg"
quality = "Ok"
summary = "Shallow"
reading = "Dropped, chapter 241"
authors = ["fast-food-restaurant"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/i-shall-be-everlasting-in-the-world-of-immortals/" },
]
[[book]]
title = "Solo Leveling"
alt_titles = ["我独自升级"]
thumbnail = "https://cdn.novelupdates.com/images/2019/01/Solo-Leveling.jpg"
quality = "Ok"
summary = "Shallow litrpg slop"
reading = "Dropped, chapter 52"
authors = ["chugong"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/solo-leveling/" },
]
[[book]]
title = "The Strongest System"
alt_titles = ["最强的系统"]
thumbnail = "https://cdn.novelupdates.com/images/2022/06/The-Strongest-System.jpg"
quality = "Ok"
summary = "Shallow"
reading = "Dropped, chapter 113"
authors = ["xin-feng"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/the-strongest-system/" },
]
[[book]]
title = "Cultivation Chat Group"
alt_titles = ["修真聊天群"]
thumbnail = "https://cdn.novelupdates.com/images/2017/10/Cultivation-Chat-Group.jpg"
quality = "Decent"
reading = "Finished"
authors = ["legend-of-the-paladin"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/cultivation-chat-group/" },
]
[[book]]
title = "Dao of the Bizarre Immortal"
alt_titles = ["道诡异仙"]
thumbnail = "https://cdn.novelupdates.com/images/2023/10/Mutated-Tao.jpg"
quality = "Decent"
reading = "Finished"
authors = ["foxtail-quill"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/dao-of-the-bizarre-immortal/" },
]
[[book]]
title = "Blood & Fur"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/70234-blood-fur.jpg"
quality = "Good"
reading = "Finished"
authors = ["maxime-j-durand"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/70234/blood-fur" },
]
[[book]]
title = "The Perfect Run"
thumbnail = "https://www.royalroadcdn.com/public/covers-full/36735-the-perfect-run.jpg"
quality = "Decent"
reading = "Finished"
authors = ["maxime-j-durand"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/36735/the-perfect-run" },
]
[[book]]
title = "Dungeon Inspector"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/63331-dungeon-inspector-book-2-complete.jpg"
quality = "Ok, mediocre"
reading = "Dropped, finished volume 1"
authors = ["flossindune"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/63331/dungeon-inspector-book-1-complete-book-2-starts" },
]
[[book]]
title = "Why Are the Talismans I Drawn Banned Again?!"
alt_titles = ["我画的符箓必被禁用"]
thumbnail = "https://cdn.novelupdates.com/images/2024/11/Why-are-the-Talismans-I-Drawn-Banned-Again.jpg"
quality = "Slop, rushed ending"
reading = "Finshed, chapter 258"
authors = ["quiet-support"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/why-are-the-talismans-i-drawn-banned-again/" },
]
[[book]]
title = "Versatile Mage"
alt_titles = ["全职法师"]
thumbnail = "https://cdn.novelupdates.com/images/2017/08/Versatile-Mage.jpg"
quality = "Slop"
reading = "Dropped, chapter 8"
authors = ["chaos"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/versatile-mage/" },
]
[[book]]
title = "1% Lifesteal"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/72301-1-lifesteal.jpg"
quality = "Ok, boring protagonist"
reading = "Dropped, C128 (volume 2)"
authors = ["robert-blaise"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/72301/1-lifesteal" },
]
[[book]]
title = "Saving the school would have been easier as a cafeteria worker"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/86874-saving-the-school-would-have-been-easier.jpg"
quality = "Decent"
reading = "Finished available (hiatus), chapter 90"
authors = ["cluelessrr"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/86874/saving-the-school-would-have-been-easier-as-a" },
]
[[book]]
title = "Theos"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/64789-theos.jpg"
quality = "Decent"
reading = "Hiatus, B3C4"
authors = ["arthur-wordsmith"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/64789/theos" },
]
[[book]]
title = "The System is Abstract, Luckily, So Am I"
thumbnail = "https://cdn.novelupdates.com/images/2025/02/The-System-is-Abstract-Luckily-So-Am-I.png"
quality = "Slop"
reading = "Dropped, C311"
authors = ["pu-jie-tianxian"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/the-system-is-abstract-luckily-so-am-i/" },
]
[[book]]
title = "Kill the Sun"
thumbnail = "https://book-pic.webnovel.com/bookcover/27467949206850305?imageMogr2/thumbnail/180x|imageMogr2/quality/70!&imageId=1732809259404"
quality = "Decent"
reading = "Finished, C992"
authors = ["warmaisach"]
links = [
{ title = "webnovel", url = "https://m.webnovel.com/book/kill-the-sun_27467949206850305" },
]
[[book]]
title = "I Just Want to Slack Off in Cultivation"
thumbnail = "https://cdn.novelupdates.com/images/2023/10/I-just-want-to-slack-off-in-cultivation.jpg"
alt_titles = ["我只想安静的做个苟道中人"]
quality = "Slop"
reading = "Dropped, C54"
authors = ["exploding-small-latte"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/__trashed-43/" },
]
[[book]]
title = "New Life As A Max Level Archmage"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/118891-new-life-as-a-max-level-archmage.jpg"
quality = "Ok"
reading = "Dropped, C44"
authors = ["arcanecadence"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/118891/new-life-as-a-max-level-archmage" },
]
[[book]]
title = "Only at the Mahayana Stage Does the Reversal System Appear"
thumbnail = "https://cdn.novelupdates.com/images/2025/02/Only-at-the-Mahayana-Stage-Does-the-Reversal-System-Appear.jpeg"
quality = "Ok, bad translation"
reading = "Dropped, C164"
authors = ["the-whitest-crow"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/only-at-the-mahayana-stage-does-the-reversal-system-appear/" },
]
[[book]]
title = "Etherious"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/52083-etherious--a-litrpg-story-book-2-stubbing.jpg"
quality = "Ok"
reading = "Dropped, finished V4"
authors = ["emes"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/52083/etherious--a-litrpg-story" },
]
[[book]]
title = "The Shards of Etherious"
thumbnail = "https://images-na.ssl-images-amazon.com/images/S/compressed.photo.goodreads.com/books/1611195421i/56769296.jpg"
quality = "Bad"
reading = "Dropped, V1C9"
authors = ["colin-j-d-crooks"]
links = [
{ title = "goodreads", url = "https://www.goodreads.com/book/show/56769296-arisen" },
]
[[book]]
title = "I Became The Necromancer Of The Academy"
thumbnail = "https://cdn.novelupdates.com/images/2024/03/I-Became-The-Necromancer-Of-The-Academy.jpg"
quality = "Slop"
reading = "Dropped, C37"
authors = ["_172"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/i-became-the-necromancer-of-the-academy/" },
]
[[book]]
title = "Dear Spellbook"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/49881-dear-spellbook.jpg"
quality = "Ok"
reading = "Dropped, V3C13"
authors = ["tk523"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/49881/dear-spellbook" },
]
[[book]]
title = "All the Dust that Falls"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/60292-all-the-dust-that-falls.jpg"
quality = "Ok"
reading = "Finished, V4"
authors = ["zaifyr"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/60292/all-the-dust-that-falls" },
]
[[book]]
title = "Nightmare Realm Summoner"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/89034-nightmare-realm-summoner-stubbing-in-1-week.jpg"
quality = "Ok"
reading = "Dropped, C278"
authors = ["actus"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/89034/nightmare-realm-summoner" },
]
[[book]]
title = "Mage Tank"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/mage-tank-aacalggbnhq.jpg"
quality = "Slop"
reading = "Dropped, V1C50"
authors = ["cornman"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/76463/mage-tank" },
]
[[book]]
title = "Salvage System"
thumbnail = "https://b2419162.smushcdn.com/2419162/wp-content/uploads/2025/09/81bMdsFQzCL._SL1500_-1.jpg?lossy=2&strip=1&webp=1"
quality = "Slop"
reading = "Dropped, V1C11"
authors = ["nicholas_sansbury_smith"]
links = [
{ title = "aethonbooks", url = "https://aethonbooks.com/book/salvage-system/" },
]
[[book]]
title = "Shrouded Seascape"
alt_titles = ["诡秘地海"]
thumbnail = "./shrouded_seascape.jpg"
quality = "Good"
reading = "Finished, C1149"
authors = ["foxtail-quill"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/shrouded-seascape/" },
]
[[book]]
title = "Diary of a Dead Wizard"
alt_titles = ["死亡巫师日记"]
thumbnail = "./diary_of_a_dead_wizard.jpeg"
quality = "Good"
reading = "Finished, C1037"
authors = ["jin-nai"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/diary-of-a-dead-wizard/" },
]
[[book]]
title = "The Crazy Knight’s Age of the Universe"
alt_titles = ["疯骑士的宇宙时代"]
thumbnail = "https://img.wtr-lab.com/cdn/series/V59LQYUDTF-TfhZh1GsBO6WG1VvW3p6MTAOqKYwFyFA.jpeg"
quality = "Ok, lost the vibe of the first book"
reading = "Dropped, C167"
authors = ["angry-squirrel"]
links = [
{ title = "wtr-lab", url = "https://wtr-lab.com/en/novel/21563/the-crazy-knights-age-of-the-universe/" },
]
[[book]]
title = "Are You Even Human"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/are-you-even-human-aabawaw0tbu.jpg"
quality = "Decent"
reading = "Dropped, C54"
authors = ["thundamoo"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/92549/are-you-even-human" },
]
[[book]]
title = "A Gamer's Guide To Beating The Tutorial"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/73205-a-gamers-guide-to-beating-the-tutorial.jpg"
quality = "Ok"
reading = "Dropped, C352"
authors = ["palt"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/73205/a-gamers-guide-to-beating-the-tutorial" },
]
[[book]]
title = "Unsong"
thumbnail = "https://m.media-amazon.com/images/S/compressed.photo.goodreads.com/books/1632785897i/28589297.jpg"
quality = "Good, disgusting ending"
reading = "Finished"
authors = ["scott_alexander"]
links = [{ title = "site", url = "https://unsongbook.com/" }]
[[book]]
title = "Young Master's PoV: Woke Up As A Villain In A Game One Day"
thumbnail = "./young_masters_pov_woke_up_as_a_villain_in_a_game_one_day.jpg"
quality = "Ok"
reading = "Dropped, C293"
authors = ["the-one-who-was"]
links = [
{ title = "webnovel", url = "https://www.webnovel.com/book/young-master's-pov-woke-up-as-a-villain-in-a-game-one-day_30581672200350205" },
]
[[book]]
title = "Throne Hunters"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/85769-throne-hunters-dungeon-focused-progression.jpg"
quality = "Ok"
reading = "Dropped, V1C44"
authors = ["phill_tucker"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/85769/throne-hunters-dungeon-focused-progression-fantasystubbed" },
]
[[book]]
title = "For the Glory of Rome"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/104561-for-the-glory-of-rome-chronicles-of-an.jpg"
quality = "Ok"
reading = "Dropped, V3C12"
authors = ["zaifyr"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/104561/for-the-glory-of-rome-chronicles-of-an-isekaid" },
]
[[book]]
title = "Magical Girl Gunslinger"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/48402-magical-girl-gunslinger.jpg?time=1693597835"
quality = "Ok"
reading = "Finished available (hiatus), C37"
authors = ["mikasane"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/48402/magical-girl-gunslinger" },
]
[[book]]
title = "This Magical Girl is Mine"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/this-magical-girl-is-mine-aacauifwgrc.jpg"
quality = "Ok"
reading = "Dropped, V5C1.2"
authors = ["voravora"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/118714/this-magical-girl-is-mine" },
]
[[book]]
title = "Magical Girl Mechanical Heart"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/magical-girl-mechanical-heart-aadaukdlry.jpg"
quality = "Ok"
reading = "Dropped, C52"
authors = ["thundamoo"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/106438/magical-girl-mechanical-heart" },
]
[[book]]
title = "Grotesqueries of the Old Domain"
alt_titles = ["旧域怪诞", "The Grotesque Old Domain"]
thumbnail = "./grotesqueries_of_the_old_domain.jpg"
quality = "Good?"
reading = "Dropped, C268"
authors = ["foxtail-quill"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/grotesqueries-of-the-old-domain/" },
]
[[book]]
title = "The Hundred Reigns"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/the-hundred-reigns-timeloop-litrpg-aabay6rm6bc.jpg"
quality = "Ok"
reading = "Dropped, C183"
authors = ["maxime-j-durand"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/139212/the-hundred-reigns-timeloop-litrpg" },
]
[[book]]
title = "Afterlife 2.0"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/111416-afterlife-20-litrpg-in-hell.jpg"
quality = "Decent"
reading = "Finished available (hiatus), C86"
authors = ["quickduckling"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/111416/afterlife-20-litrpg-in-hell" },
]
[[book]]
title = "Mask of Humanity"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/80031-mask-of-humanity-grimdark-cultivation-litrpg.jpg"
quality = "Decent"
reading = "Dropped, C366"
authors = ["slaughterbot"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/80031/mask-of-humanity" },
]
[[book]]
title = "Changeling"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/75345-changeling.jpg"
quality = "Decent"
reading = "Dropped, C103"
authors = ["mecanimus"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/75345/changeling" },
]
[[book]]
title = "The Tower of Infinite Evil"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/122142-the-tower-of-infinite-evil-a-litrpg-horror.jpg"
quality = "Decent"
reading = "Dropped, C127"
authors = ["lit-homunculus"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/122142/the-tower-of-infinite-evil-a-litrpg-horror-comedy" },
]
[[book]]
title = "Pale Lights"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/65058-pale-lights.jpg?time=1745679158"
quality = "Good"
reading = "Dropped, V3C37"
authors = ["erraticerrata"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/65058/pale-lights" },
]
[[book]]
title = "Shadow Slave"
thumbnail = "./shadow_slave.jpg"
quality = "Decent"
reading = "Dropped, chapter 2777"
authors = ["guilty-three"]
links = [
{ title = "webnovel", url = "https://www.webnovel.com/book/shadow-slave_22196546206090805" },
]
[[book]]
title = "I Cultivate Legally, Why Call Me a Demon?"
alt_titles = ["我合法修仙,凭什么叫我魔头?"]
thumbnail = "https://cdn.novelupdates.com/images/2025/09/I-Cultivate-Legally-Why-Call-Me-a-Demon.jpg"
quality = "Slop"
reading = "Dropped, C89"
authors = ["一辈子小说家"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/i-cultivate-legally-why-call-me-a-demon/" },
]
[[book]]
title = "I Am a Demon Cultivator, Not a Conscientious Capitalist"
alt_titles = ["我是魔修,不是良心资本家"]
thumbnail = "https://cdn.novelupdates.com/images/2025/09/I-Am-a-Demon-Cultivator-Not-a-Conscientious-Capitalist.jpg"
quality = "Slop"
reading = "Dropped, C19"
authors = ["窗边的鸽子"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/i-am-a-demon-cultivator-not-a-conscientious-capitalist/" },
]
[[book]]
title = "Shan He Ji"
alt_titles = ["山河稷", "Mountains, Rivers, and the Grain God"]
thumbnail = "https://cdn.novelupdates.com/images/2025/07/Shan-He-Ji.jpg"
quality = "Ok"
reading = "Dropped, C27"
authors = ["姬叉"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/shan-he-ji/" },
]
[[book]]
title = "Staring directly at the ancient gods for a whole year"
alt_titles = ["直视古神一整年"]
thumbnail = "https://img.wtr-lab.com/dSO3hnkuy2rqyLSKcLj1gjd_4jLT-ZU_4KetR6Aj99Y/rs:fit:344:0:0/q:80/g:no/czM6Ly93dHJpbWcvc2VyaWVzLzFFdXZOQ0EyS2ZsT2NmUlczYVlQZUEud2VicA"
quality = "Slop"
reading = "Dropped, C100"
authors = ["三藏的左轮"]
links = [
{ title = "wtrlab", url = "https://wtr-lab.com/en/novel/5006/staring-directly-at-the-ancient-gods-for-a-whole-year" },
]
[[book]]
title = "Mysterious Revival"
thumbnail = "https://book-pic.webnovel.com/bookcover/19115759305319405?imageMogr2/thumbnail/180x|imageMogr2/format/webp|imageMogr2/quality/70!&imageId=1721123894271"
quality = "Ok"
reading = "Dropped, C54"
authors = ["offering-flowers-before-the-buddha"]
links = [
{ title = "webnovel", url = "https://m.webnovel.com/book/mysterious-revival_19115759305319405" },
]
[[book]]
title = "Explorer of Edregon"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/100744-explorer-of-edregon.jpg?time=1763178307"
quality = "Ok, bland"
reading = "Dropped, C20"
authors = ["wizardly_dude"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/100744/explorer-of-edregon-book-5-complete" },
]
[[book]]
title = "No More Heroes"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/89019-no-more-heroes-superhero-litrpg.jpg?time=1721951587"
quality = "Ok, boring"
reading = "Dropped, C22"
authors = ["lokithequick"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/89019/no-more-heroes-superhero-litrpg" },
]
[[book]]
title = "DIE TRYING"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/124235-die-trying-a-roguelite-extraction-litrpg.jpg?time=1759079259"
quality = "Ok, bland"
reading = "Dropped, C47"
authors = ["markarrows"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/124235/die-trying-a-roguelite-extraction-litrpg" },
]
[[book]]
title = "Shadow Clone Sorcery"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/117529-shadow-clone-sorcery.jpg?time=1748092724"
quality = "Ok, bland"
reading = "Dropped, C110"
authors = ["jpwrites"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/117529/shadow-clone-sorcery-book-1-complete" },
]
[[book]]
title = "To Walk The Red Path "
thumbnail = "https://www.royalroadcdn.com/public/covers-large/to-walk-the-red-path-a-story-of-dungeon-crawling.jpg?time=1741212789"
quality = "Ok, bland"
reading = "Dropped, F6P2C10"
authors = ["cashen"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/107964/to-walk-the-red-path-a-story-of-dungeon-crawling" },
]
[[book]]
title = "[Grave Robber]"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/178197-grave-robber.jpg?time=1783922076"
quality = "Ok, mediorce"
reading = "Dropped, C6"
authors = ["disheveledvagabond"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/178197/grave-robber" },
]
[[book]]
title = "Throne of Time"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/throne-of-time-aabavht89hg.jpg?time=1780498434"
quality = "Ok, bland"
reading = "Dropped, C23"
authors = ["cognosticon"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/172653/throne-of-time-magical-academy-time-loop-mystery" },
]
[[book]]
title = "Path of the Deathless"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/122502-path-of-the-deathless-book-4-completed.jpg"
quality = "Decent"
reading = "Dropped, C333"
authors = ["ostensiblemammal"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/122502/path-of-the-deathless-book-4-completed" },
]
[[book]]
title = "The Legend of William Oh"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/the-legend-of-william-oh-aadavnw8qxu.jpg"
quality = "Decent"
reading = "Dropped, C264"
authors = ["macronomicon"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/92144/the-legend-of-william-oh" },
]
[[book]]
title = "Re:Cursed"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/104556-recursed.jpg?time=1763017950"
quality = "Decent"
reading = "Dropped, C176"
authors = ["joroboros"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/104556/recursed" },
]
[[book]]
title = "Reforged from Ruin"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/78756-reforged-from-ruin-eldritch-xianxia-cultivation.jpg"
quality = "Decent"
reading = "Dropped, C390"
authors = ["silv3rtongue"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/78756/reforged-from-ruin-eldritch-xianxia-cultivation" },
]
[[book]]
title = "Hell Difficulty Tutorial"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/64916-hell-difficulty-tutorial.jpg"
quality = "Decent"
reading = "Dropped, C841"
authors = ["cerim"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/64916/hell-difficulty-tutorial" },
]
[[book]]
title = "Book Of The Dead"
thumbnail = "https://www.royalroadcdn.com/public/covers-full/47038-book-of-the-dead.jpg"
quality = "Decent"
reading = "Dropped, B6C8"
authors = ["rinoz"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/47038/book-of-the-dead" },
]
[[book]]
title = "The Mirror Legacy"
thumbnail = "https://cdn.novelupdates.com/images/2024/06/The-Mirror-Legacy.jpg"
alt_titles = ["玄鉴仙族"]
quality = "Decent?"
reading = "Dropped, C10"
authors = ["季越人"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/the-mirror-legacy/" },
]
[[book]]
title = "Corpse Retriever"
alt_titles = ["捞尸人"]
thumbnail = "https://cdn.novelupdates.com/images/2025/04/Corpse-Retriever.jpg"
quality = "Decent?"
reading = "Dropped, C26"
authors = ["纯洁滴小龙"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/corpse-retriever/" },
]
[[book]]
title = "How Can You Cultivate Immortality Without Money?"
alt_titles = ["没钱修什么仙?", "No Money to Cultivate Immortality?"]
thumbnail = "https://cdn.novelupdates.com/images/2024/11/No-Money-to-Cultivate-Immortality.png"
quality = "Decent"
reading = "Dropped, C827 (C815)"
authors = ["熊狼狗"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/no-money-to-cultivate-immortality/" },
]
[[book]]
title = "Surviving as a Talent in the Primordial Saint Sect"
alt_titles = [
"苟在初圣魔门当人材",
"Lying Low as the First Saint Demonic Sect’s ‘Top Talent’",
]
thumbnail = "./struggling_to_survive_with_regression_power_in_the_primordial_saint_sect.png"
quality = "Decent"
reading = "Finished, C1537 (C1441)"
authors = ["crane-by-the-moonlit-pond"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/series/struggling-to-survive-with-regression-power-in-the-primordial-saint-sect/" },
]
[[book]]
title = "Girls' Last Tour"
alt_titles = ["少女終末旅行"]
quality = "Good"
reading = "Finished, V6C43.6"
authors = ["tsukumizu"]
links = [
{ title = "wikipedia", url = "https://en.wikipedia.org/wiki/Girls%27_Last_Tour" },
]
[[book]]
title = "Sky Pride"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/107917-sky-pride.jpg"
quality = "Good"
reading = "Dropped, B6C25"
authors = ["warby-picus"]
links = [
{ title = "royalroad", url = "https://www.royalroad.com/fiction/107917/sky-pride" },
]
Authors
[author.mao-ni]
name = "Mao Ni"
alt_names = ["猫腻"]
[author.gu-zhen-ren]
name = "Gu Zhen Ren"
alt_names = ["蛊真人"]
[author.angry-squid]
name = "Angry Squid"
alt_names = ["愤怒的乌贼"]
[author.angry-squirrel]
name = "Angry Squirrel"
alt_names = ["愤怒的松鼠"]
[author.golden-jasmine]
name = "Golden Jasmine"
alt_names = ["金色茉莉花"]
[author.cuttlefish-that-loves-diving]
name = "Cuttlefish That Loves Diving"
alt_names = ["爱潜水的乌贼"]
[author.er-gen]
name = "Er Gen"
alt_names = ["耳根"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/nauthor/er-gen/" },
]
[author.fang-xiang]
name = "Fang Xiang"
alt_names = ["方想"]
[author.chaos]
name = "Chaos"
alt_names = ["乱"]
[author.tang-jia-san-shao]
name = "Tang Jia San Shao"
alt_names = ["唐家三少"]
[author.can-fix-air-conditioners]
name = "Can Fix Air-Conditioners"
alt_names = ["我会修空调"]
[author.thefirstdefier]
name = "TheFirstDefier"
[author.kirill-klevanski]
name = "Kirill Klevanski"
[author.ostensible-mammal]
name = "OstensibleMammal"
links = [
{ title = "royalroad", url = "https://www.royalroad.com/profile/293473" },
]
[author.rinoz]
name = "RinoZ"
links = [
{ title = "royalroad", url = "https://www.royalroad.com/profile/97247" },
]
[author.guilty-three]
name = "Guiltythree"
[author.uraniumphoenix]
name = "UraniumPhoenix"
[author.seersucker]
name = "seersucker"
[author.azalea-ellis]
name = "Azalea Ellis"
[author.doctorhepa]
name = "DoctorHepa"
[author.casualfarmer]
name = "Casualfarmer"
[author.cerim]
name = "Cerim"
[author.actus]
name = "Actus"
[author.clarke]
name = "J.M. Clarke"
alt_names = ["U Juggernaut"]
[author.thundamoo]
name = "Thundamoo"
[author.strungbound]
name = "Strungbound"
[author.mecanimus]
name = "Mecanimus"
[author.turtleme]
name = "TurtleMe"
[author.dads-bedtime-stories]
name = "Dads Bedtime Stories"
[author.chirolu]
name = "Chirolu"
[author.silverlinings]
name = "SilverLinings"
[author.xkarnation]
name = "XKARNATION"
[author.kawahara-reki]
name = "Kawahara Reki"
[author.robert-blaise]
name = "Robert Blaise"
[author.mark-arrows]
name = "Mark Arrows"
[author.wildbow]
name = "Wildbow"
[author.dakota-krout]
name = "Dakota Krout"
[author.sinnoa]
name = "Sinnoa"
[author.randombluecat]
name = "RandomBlueCat"
[author.the-plagiarist]
name = "The Plagiarist"
[author.chen-dong]
name = "Chen Dong"
alt_names = ["辰东"]
[author.yu-ryeo-han]
name = "Yu Ryeo Han"
alt_names = ["유려한"]
[author.the-enlightened-master-crouching-cow]
name = "The Enlightened Master Crouching Cow"
alt_names = ["卧牛真人"]
[author.mikage-eiji]
name = "Mikage Eiji"
[author.nocturnal-stranger]
name = "Nocturnal Stranger"
alt_names = ["厄夜怪客"]
[author.ya-boy]
name = "Ya Boy"
links = [
{ title = "royalroad", url = "https://www.royalroad.com/profile/202632" },
]
[author.god-loves-the-world]
name = "God Loves The World"
alt_names = ["神仙爱凡尘"]
[author.necariin]
name = "Necariin"
links = [
{ title = "royalroad", url = "https://www.royalroad.com/profile/122394" },
]
[author.x-rhoden-x]
name = "X-RHODEN-X"
[author.fast-food-restaurant]
name = "Fast Food Restaurant"
alt_names = ["快餐店"]
[author.chugong]
name = "Chugong"
alt_names = ["추공"]
[author.xin-feng]
name = "Xin Feng"
alt_names = ["新丰"]
[author.legend-of-the-paladin]
name = "Legend of the Paladin"
alt_names = ["圣骑士的传说"]
[author.foxtail-quill]
name = "Foxtail Quill"
alt_names = ["狐尾的笔"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/nauthor/foxtail-quill/" },
]
[author.maxime-j-durand]
name = "Maxime J. Durand"
links = [
{ title = "royalroad", url = "https://www.royalroad.com/profile/107213" },
]
[author.jin-nai]
name = "Jin Nai"
alt_names = ["今奈"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/nauthor/jin-nai/" },
]
[author.warby-picus]
name = "Warby Picus"
links = [
{ title = "royalroad", url = "https://www.royalroad.com/profile/261544" },
]
[author.flossindune]
name = "Flossindune"
links = [
{ title = "royalorad", url = "https://www.royalroad.com/profile/299461" },
]
[author.quiet-support]
name = "Quiet Support"
alt_names = ["安静捧场"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/nauthor/quiet-support/" },
]
[author.cluelessrr]
name = "CluelessRR"
links = [
{ title = "royalroad", url = "https://www.royalroad.com/profile/471901" },
]
[author.arthur-wordsmith]
name = "Arthur Wordsmith"
links = [
{ title = "royalroad", url = "https://www.royalroad.com/profile/323423" },
]
[author.pu-jie-tianxian]
name = "Pū jiē tiānxiàn"
alt_names = ["扑街天线"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/nauthor/%e6%89%91%e8%a1%97%e5%a4%a9%e7%ba%bf/" },
]
[author.warmaisach]
name = "Warmaisach"
links = [
{ title = "webnovel", url = "https://m.webnovel.com/profile/3286855836" },
]
[author.exploding-small-latte]
name = "Exploding Small Latte"
alt_names = ["爆炸小拿铁"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/nauthor/exploding-small-latte/" },
]
[author.arcanecadence]
name = "ArcaneCadence"
links = [
{ title = "royalroad", url = "https://www.royalroad.com/profile/729989" },
]
[author.the-whitest-crow]
name = "The Whitest Crow"
alt_names = ["最白的乌鸦"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/nauthor/%e6%9c%80%e7%99%bd%e7%9a%84%e4%b9%8c%e9%b8%a6/" },
]
[author.emes]
name = "EmEs"
links = [
{ title = "royalroad", url = "https://www.royalroad.com/profile/235726" },
]
[author.colin-j-d-crooks]
name = "Colin J.D. Crooks"
links = [
{ title = "goodreads", url = "https://www.goodreads.com/author/show/21106941.Colin_J_D_Crooks" },
]
[author._172]
name = "_172"
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/nauthor/_172/" },
]
[author.tk523]
name = "TK523"
links = [
{ title = "royalroad", url = "https://www.royalroad.com/profile/112902" },
]
[author.zaifyr]
name = "zaifyr"
links = [
{ title = "royalroad", url = "https://www.royalroad.com/profile/285838" },
]
[author.cornman]
name = "Cornman"
links = [
{ title = "royalroad", url = "https://www.royalroad.com/profile/394190" },
]
[author.the-one-who-was]
name = "The_One_Who_Was"
links = [
{ title = "webnovel", url = "https://www.webnovel.com/profile/4324450853" },
]
[author.lit-homunculus]
name = "Lit Homunculus"
links = [
{ title = "royalroad", url = "https://www.royalroad.com/profile/56125" },
]
[author.macronomicon]
name = "Macronomicon"
links = [
{ title = "royalroad", url = "https://www.royalroad.com/profile/100060" },
]
[author.crane-by-the-moonlit-pond]
name = "Crane by the Moonlit Pond"
alt_names = ["鹤守月满池"]
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/nauthor/crane-by-the-moonlit-pond/" },
]
[author.nicholas_sansbury_smith]
name = "Nicholas Sansbury Smith"
links = [
{ title = "aethonbooks", url = "https://aethonbooks.com/book-author/nicholas-sansbury-smith/" },
]
[author.scott_alexander]
name = "Scott Alexander"
links = [
{ title = "goodreads", url = "https://www.goodreads.com/author/show/10866248.Scott_Alexander" },
]
[author.erraticerrata]
name = "ErraticErrata"
links = [
{ title = "royalroad", url = "https://www.royalroad.com/profile/21586" },
]
[authors.palt]
name = "Palt"
links = [
{ title = "royalroad", url = "https://www.royalroad.com/profile/35937" },
]
[author.phill_tucker]
name = "Phill Tucker"
links = [
{ title = "royalroad", url = "https://www.royalroad.com/profile/73941" },
]
[author.slaughterbot]
name = "SlaughterBot"
links = [
{ title = "royalroad", url = "https://www.royalroad.com/profile/413099" },
]
[author.mikasane]
name = "Mikasane"
links = [
{ title = "royalroad", url = "https://www.royalroad.com/profile/244859" },
]
[author.voravora]
name = "VoraVora"
links = [
{ title = "royalroad", url = "https://www.royalroad.com/profile/236517" },
]
[author.quickduckling]
name = "QuickDuckling"
links = [
{ title = "royalroad", url = "https://www.royalroad.com/profile/472328" },
]
[author."一辈子小说家"]
name = "一辈子小说家"
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/nauthor/%e4%b8%80%e8%be%88%e5%ad%90%e5%b0%8f%e8%af%b4%e5%ae%b6/" },
]
[author."姬叉"]
name = "姬叉"
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/nauthor/%e5%a7%ac%e5%8f%89/" },
]
[author."窗边的鸽子"]
name = "窗边的鸽子"
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/nauthor/%e7%aa%97%e8%be%b9%e7%9a%84%e9%b8%bd%e5%ad%90/" },
]
[author."熊狼狗"]
name = "熊狼狗"
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/nauthor/%e7%86%8a%e7%8b%bc%e7%8b%97/" },
]
[author.joroboros]
name = "Joroboros"
links = [
{ title = "royalroad", url = "https://www.royalroad.com/profile/115230" },
]
[author.silv3rtongue]
name = "Silv3rtongue"
links = [
{ title = "royalroad", url = "https://www.royalroad.com/profile/418109" },
]
[author."纯洁滴小龙"]
name = "纯洁滴小龙"
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/nauthor/%e7%ba%af%e6%b4%81%e6%bb%b4%e5%b0%8f%e9%be%99/" },
]
[author."三藏的左轮"]
name = "三藏的左轮"
links = [
{ title = "wtrlab", url = "https://wtr-lab.com/en/author/%E4%B8%89%E8%97%8F%E7%9A%84%E5%B7%A6%E8%BD%AE" },
]
[author.offering-flowers-before-the-buddha]
name = "Offering flowers before the Buddha"
links = []
[author."季越人"]
name = "季越人"
links = [
{ title = "novelupdates", url = "https://www.novelupdates.com/nauthor/%e5%ad%a3%e8%b6%8a%e4%ba%ba/" },
]
[author.tsukumizu]
name = "Tsukumizu"
alt_names = ["つくみず"]
links = [
{ title = "wikipedia", url = "https://en.wikipedia.org/wiki/Tsukumizu" },
]
[author.wizardly_dude]
name = "Wizardly Dude"
links = [
{ title = "royalroad", url = "https://www.royalroad.com/profile/559659" },
]
[author.lokithequick]
name = "LokiTheQuick"
links = [
{ title = "royalroad", url = "https://www.royalroad.com/profile/456668" },
]
[author.markarrows]
name = "Mark Arrows"
links = [
{ title = "royalroad", url = "https://www.royalroad.com/profile/150899" },
]
[author.jpwrites]
name = "JPwrites "
links = [
{ title = "royalroad", url = "https://www.royalroad.com/profile/9705" },
]
[author.cashen]
name = "Jman8763 C. Ashen"
links = [
{ title = "royalroad", url = "https://www.royalroad.com/profile/210709" },
]
[author.disheveledvagabond]
name = "DisheveledVagabond "
links = [
{ title = "royalroad", url = "https://www.royalroad.com/profile/192594" },
]
[author.cognosticon]
name = "Cognosticon"
links = [
{ title = "royalroad", url = "https://www.royalroad.com/profile/270595" },
]
5.3 - Countries
Countries
# source: https://gist.github.com/ssskip/5a94bfcd2835bf1dea52?permalink_comment_id=4690725#gistcomment-4690725
[AF]
"Country Name" = "Afghanistan"
ISO2 = "AF"
ISO3 = "AFG"
"Top Level Domain" = "af"
FIPS = "AF"
"ISO Numeric" = "004"
GeoNameID = 1_149_361
E164 = 93
"Phone Code" = 93
Continent = "Asia"
Capital = "Kabul"
"Time Zone in Capital" = "Asia/Kabul"
Currency = "Afghani"
"Language Codes" = "fa-AF,ps,uz-AF,tk"
Languages = "Afghan Persian or Dari (official) 50%, Pashto (official) 35%, Turkic languages (primarily Uzbek and Turkmen) 11%, 30 minor languages (primarily Balochi and Pashai) 4%, much bilingualism, but Dari functions as the lingua franca"
"Area KM2" = 647_500
"Internet Hosts" = 223
"Internet Users" = 1_000_000
"Phones (Mobile)" = 18_000_000
"Phones (Landline)" = 13_500
GDP = 20_650_000_000
englishShortName = "Afghanistan"
frenchShortName = "Afghanistan (l')"
numeric = 4
japaneseShortName = "アフガニスタン"
[AL]
"Country Name" = "Albania"
ISO2 = "AL"
ISO3 = "ALB"
"Top Level Domain" = "al"
FIPS = "AL"
"ISO Numeric" = "008"
GeoNameID = 783_754
E164 = 355
"Phone Code" = 355
Continent = "Europe"
Capital = "Tirana"
"Time Zone in Capital" = "Europe/Tirane"
Currency = "Lek"
"Language Codes" = "sq,el"
Languages = "Albanian 98.8% (official - derived from Tosk dialect), Greek 0.5%, other 0.6% (including Macedonian, Roma, Vlach, Turkish, Italian, and Serbo-Croatian), unspecified 0.1% (2011 est.)"
"Area KM2" = 28_748
"Internet Hosts" = 15_528
"Internet Users" = 1_300_000
"Phones (Mobile)" = 3_500_000
"Phones (Landline)" = 312_000
GDP = 12_800_000_000
englishShortName = "Albania"
frenchShortName = "Albanie (l')"
numeric = 8
japaneseShortName = "アルバニア"
[DZ]
"Country Name" = "Algeria"
ISO2 = "DZ"
ISO3 = "DZA"
"Top Level Domain" = "dz"
FIPS = "AG"
"ISO Numeric" = "012"
GeoNameID = 2_589_581
E164 = 213
"Phone Code" = 213
Continent = "Africa"
Capital = "Algiers"
"Time Zone in Capital" = "Africa/Algiers"
Currency = "Dinar"
"Language Codes" = "ar-DZ"
Languages = "Arabic (official), French (lingua franca), Berber dialects: Kabylie Berber (Tamazight), Chaouia Berber (Tachawit), Mzab Berber, Tuareg Berber (Tamahaq)"
"Area KM2" = 2_381_740
"Internet Hosts" = 676
"Internet Users" = 4_700_000
"Phones (Mobile)" = 37_692_000
"Phones (Landline)" = 3_200_000
GDP = 215_700_000_000
englishShortName = "Algeria"
frenchShortName = "Algérie (l')"
numeric = 12
japaneseShortName = "アルジェリア"
[AS]
"Country Name" = "American Samoa"
ISO2 = "AS"
ISO3 = "ASM"
"Top Level Domain" = "as"
FIPS = "AQ"
"ISO Numeric" = "016"
GeoNameID = 5_880_801
E164 = 1
"Phone Code" = "1-684"
Continent = "Oceania"
Capital = "Pago Pago"
"Time Zone in Capital" = "Pacific/Pago_Pago"
Currency = "Dollar"
"Language Codes" = "en-AS,sm,to"
Languages = "Samoan 90.6% (closely related to Hawaiian and other Polynesian languages), English 2.9%, Tongan 2.4%, other Pacific islander 2.1%, other 2%"
"Area KM2" = 199
"Internet Hosts" = 2_387
"Internet Users" = ""
"Phones (Mobile)" = ""
"Phones (Landline)" = 10_000
GDP = 462_200_000
englishShortName = "American Samoa"
frenchShortName = "Samoa américaines (les)"
numeric = 16
japaneseShortName = "アメリカ領サモア"
[AD]
"Country Name" = "Andorra"
ISO2 = "AD"
ISO3 = "AND"
"Top Level Domain" = "ad"
FIPS = "AN"
"ISO Numeric" = "020"
GeoNameID = 3_041_565
E164 = 376
"Phone Code" = 376
Continent = "Europe"
Capital = "Andorra la Vella"
"Time Zone in Capital" = "Europe/Andorra"
Currency = "Euro"
"Language Codes" = "ca"
Languages = "Catalan (official), French, Castilian, Portuguese"
"Area KM2" = 468
"Internet Hosts" = 28_383
"Internet Users" = 67_100
"Phones (Mobile)" = 65_000
"Phones (Landline)" = 39_000
GDP = 4_800_000_000
englishShortName = "Andorra"
frenchShortName = "Andorre (l')"
numeric = 20
japaneseShortName = "アンドラ"
[AO]
"Country Name" = "Angola"
ISO2 = "AO"
ISO3 = "AGO"
"Top Level Domain" = "ao"
FIPS = "AO"
"ISO Numeric" = "024"
GeoNameID = 3_351_879
E164 = 244
"Phone Code" = 244
Continent = "Africa"
Capital = "Luanda"
"Time Zone in Capital" = "Africa/Lagos"
Currency = "Kwanza"
"Language Codes" = "pt-AO"
Languages = "Portuguese (official), Bantu and other African languages"
"Area KM2" = 1_246_700
"Internet Hosts" = 20_703
"Internet Users" = 606_700
"Phones (Mobile)" = 9_800_000
"Phones (Landline)" = 303_000
GDP = 124_000_000_000
englishShortName = "Angola"
frenchShortName = "Angola (l')"
numeric = 24
japaneseShortName = "アンゴラ"
[AI]
"Country Name" = "Anguilla"
ISO2 = "AI"
ISO3 = "AIA"
"Top Level Domain" = "ai"
FIPS = "AV"
"ISO Numeric" = 660
GeoNameID = 3_573_511
E164 = 1
"Phone Code" = "1-264"
Continent = "North America"
Capital = "The Valley"
"Time Zone in Capital" = "America/Port_of_Spain"
Currency = "Dollar"
"Language Codes" = "en-AI"
Languages = "English (official)"
"Area KM2" = 102
"Internet Hosts" = 269
"Internet Users" = 3_700
"Phones (Mobile)" = 26_000
"Phones (Landline)" = 6_000
GDP = 175_400_000
englishShortName = "Anguilla"
frenchShortName = "Anguilla"
numeric = 660
japaneseShortName = "アンギラ"
[AQ]
"Country Name" = "Antarctica"
ISO2 = "AQ"
ISO3 = "ATA"
"Top Level Domain" = "aq"
FIPS = "AY"
"ISO Numeric" = "010"
GeoNameID = 6_697_173
E164 = 672
"Phone Code" = 672
Continent = "Antarctica"
Capital = ""
"Time Zone in Capital" = "Antarctica/Troll"
Currency = ""
"Language Codes" = ""
Languages = ""
"Area KM2" = 14_000_000
"Internet Hosts" = 7_764
"Internet Users" = ""
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = ""
englishShortName = "Antarctica"
frenchShortName = "Antarctique (l')"
numeric = 10
japaneseShortName = "南極大陸"
[AG]
"Country Name" = "Antigua and Barbuda"
ISO2 = "AG"
ISO3 = "ATG"
"Top Level Domain" = "ag"
FIPS = "AC"
"ISO Numeric" = "028"
GeoNameID = 3_576_396
E164 = 1
"Phone Code" = "1-268"
Continent = "North America"
Capital = "St. John's"
"Time Zone in Capital" = "America/Antigua"
Currency = "Dollar"
"Language Codes" = "en-AG"
Languages = "English (official), local dialects"
"Area KM2" = 443
"Internet Hosts" = 11_532
"Internet Users" = 65_000
"Phones (Mobile)" = 179_800
"Phones (Landline)" = 35_000
GDP = 1_220_000_000
englishShortName = "Antigua and Barbuda"
frenchShortName = "Antigua-et-Barbuda"
numeric = 28
japaneseShortName = "アンティグア・バーブーダ"
[AR]
"Country Name" = "Argentina"
ISO2 = "AR"
ISO3 = "ARG"
"Top Level Domain" = "ar"
FIPS = "AR"
"ISO Numeric" = "032"
GeoNameID = 3_865_483
E164 = 54
"Phone Code" = 54
Continent = "South America"
Capital = "Buenos Aires"
"Time Zone in Capital" = "America/Argentina/Buenos_Aires"
Currency = "Peso"
"Language Codes" = "es-AR,en,it,de,fr,gn"
Languages = "Spanish (official), Italian, English, German, French, indigenous (Mapudungun, Quechua)"
"Area KM2" = 2_766_890
"Internet Hosts" = 11_232_000
"Internet Users" = 13_694_000
"Phones (Mobile)" = 58_600_000
"Phones (Landline)" = 1
GDP = 484_600_000_000
englishShortName = "Argentina"
frenchShortName = "Argentine (l')"
numeric = 32
japaneseShortName = "アルゼンチン"
[AM]
"Country Name" = "Armenia"
ISO2 = "AM"
ISO3 = "ARM"
"Top Level Domain" = "am"
FIPS = "AM"
"ISO Numeric" = "051"
GeoNameID = 174_982
E164 = 374
"Phone Code" = 374
Continent = "Asia"
Capital = "Yerevan"
"Time Zone in Capital" = "Asia/Yerevan"
Currency = "Dram"
"Language Codes" = "hy"
Languages = "Armenian (official) 97.9%, Kurdish (spoken by Yezidi minority) 1%, other 1% (2011 est.)"
"Area KM2" = 29_800
"Internet Hosts" = 194_142
"Internet Users" = 208_200
"Phones (Mobile)" = 3_223_000
"Phones (Landline)" = 584_000
GDP = 10_440_000_000
englishShortName = "Armenia"
frenchShortName = "Arménie (l')"
numeric = 51
japaneseShortName = "アルメニア"
[AW]
"Country Name" = "Aruba"
ISO2 = "AW"
ISO3 = "ABW"
"Top Level Domain" = "aw"
FIPS = "AA"
"ISO Numeric" = 533
GeoNameID = 3_577_279
E164 = 297
"Phone Code" = 297
Continent = "North America"
Capital = "Oranjestad"
"Time Zone in Capital" = "America/Curacao"
Currency = "Guilder"
"Language Codes" = "nl-AW,es,en"
Languages = "Papiamento (a Spanish-Portuguese-Dutch-English dialect) 69.4%, Spanish 13.7%, English (widely spoken) 7.1%, Dutch (official) 6.1%, Chinese 1.5%, other 1.7%, unspecified 0.4% (2010 est.)"
"Area KM2" = 193
"Internet Hosts" = 40_560
"Internet Users" = 24_000
"Phones (Mobile)" = 135_000
"Phones (Landline)" = 43_000
GDP = 2_516_000_000
englishShortName = "Aruba"
frenchShortName = "Aruba"
numeric = 533
japaneseShortName = "アルバ"
[AU]
"Country Name" = "Australia"
ISO2 = "AU"
ISO3 = "AUS"
"Top Level Domain" = "au"
FIPS = "AS"
"ISO Numeric" = "036"
GeoNameID = 2_077_456
E164 = 61
"Phone Code" = 61
Continent = "Oceania"
Capital = "Canberra"
"Time Zone in Capital" = "Australia/Sydney"
Currency = "Dollar"
"Language Codes" = "en-AU"
Languages = "English 76.8%, Mandarin 1.6%, Italian 1.4%, Arabic 1.3%, Greek 1.2%, Cantonese 1.2%, Vietnamese 1.1%, other 10.4%, unspecified 5% (2011 est.)"
"Area KM2" = 7_686_850
"Internet Hosts" = 17_081_000
"Internet Users" = 15_810_000
"Phones (Mobile)" = 24_400_000
"Phones (Landline)" = 10_470_000
GDP = 1_488_000_000_000
englishShortName = "Australia"
frenchShortName = "Australie (l')"
numeric = 36
japaneseShortName = "オーストラリア"
[AT]
"Country Name" = "Austria"
ISO2 = "AT"
ISO3 = "AUT"
"Top Level Domain" = "at"
FIPS = "AU"
"ISO Numeric" = "040"
GeoNameID = 2_782_113
E164 = 43
"Phone Code" = 43
Continent = "Europe"
Capital = "Vienna"
"Time Zone in Capital" = "Europe/Vienna"
Currency = "Euro"
"Language Codes" = "de-AT,hr,hu,sl"
Languages = "German (official nationwide) 88.6%, Turkish 2.3%, Serbian 2.2%, Croatian (official in Burgenland) 1.6%, other (includes Slovene, official in Carinthia, and Hungarian, official in Burgenland) 5.3% (2001 census)"
"Area KM2" = 83_858
"Internet Hosts" = 3_512_000
"Internet Users" = 6_143_000
"Phones (Mobile)" = 13_590_000
"Phones (Landline)" = 3_342_000
GDP = 417_900_000_000
englishShortName = "Austria"
frenchShortName = "Autriche (l')"
numeric = 40
japaneseShortName = "オーストリア"
[AZ]
"Country Name" = "Azerbaijan"
ISO2 = "AZ"
ISO3 = "AZE"
"Top Level Domain" = "az"
FIPS = "AJ"
"ISO Numeric" = "031"
GeoNameID = 587_116
E164 = 994
"Phone Code" = 994
Continent = "Asia"
Capital = "Baku"
"Time Zone in Capital" = "Asia/Baku"
Currency = "Manat"
"Language Codes" = "az,ru,hy"
Languages = "Azerbaijani (Azeri) (official) 92.5%, Russian 1.4%, Armenian 1.4%, other 4.7% (2009 est.)"
"Area KM2" = 86_600
"Internet Hosts" = 46_856
"Internet Users" = 2_420_000
"Phones (Mobile)" = 10_125_000
"Phones (Landline)" = 1_734_000
GDP = 76_010_000_000
englishShortName = "Azerbaijan"
frenchShortName = "Azerbaïdjan (l')"
numeric = 31
japaneseShortName = "アゼルバイジャン"
[BS]
"Country Name" = "Bahamas"
ISO2 = "BS"
ISO3 = "BHS"
"Top Level Domain" = "bs"
FIPS = "BF"
"ISO Numeric" = "044"
GeoNameID = 3_572_887
E164 = 1
"Phone Code" = "1-242"
Continent = "North America"
Capital = "Nassau"
"Time Zone in Capital" = "America/Nassau"
Currency = "Dollar"
"Language Codes" = "en-BS"
Languages = "English (official), Creole (among Haitian immigrants)"
"Area KM2" = 13_940
"Internet Hosts" = 20_661
"Internet Users" = 115_800
"Phones (Mobile)" = 254_000
"Phones (Landline)" = 137_000
GDP = 8_373_000_000
englishShortName = "Bahamas (the)"
frenchShortName = "Bahamas (les)"
numeric = 44
japaneseShortName = "バハマ"
[BH]
"Country Name" = "Bahrain"
ISO2 = "BH"
ISO3 = "BHR"
"Top Level Domain" = "bh"
FIPS = "BA"
"ISO Numeric" = "048"
GeoNameID = 290_291
E164 = 973
"Phone Code" = 973
Continent = "Asia"
Capital = "Manama"
"Time Zone in Capital" = "Asia/Bahrain"
Currency = "Dinar"
"Language Codes" = "ar-BH,en,fa,ur"
Languages = "Arabic (official), English, Farsi, Urdu"
"Area KM2" = 665
"Internet Hosts" = 47_727
"Internet Users" = 419_500
"Phones (Mobile)" = 2_125_000
"Phones (Landline)" = 290_000
GDP = 28_360_000_000
englishShortName = "Bahrain"
frenchShortName = "Bahreïn"
numeric = 48
japaneseShortName = "バーレーン"
[BD]
"Country Name" = "Bangladesh"
ISO2 = "BD"
ISO3 = "BGD"
"Top Level Domain" = "bd"
FIPS = "BG"
"ISO Numeric" = "050"
GeoNameID = 1_210_997
E164 = 880
"Phone Code" = 880
Continent = "Asia"
Capital = "Dhaka"
"Time Zone in Capital" = "Asia/Dhaka"
Currency = "Taka"
"Language Codes" = "bn-BD,en"
Languages = "Bangla (official, also known as Bengali), English"
"Area KM2" = 144_000
"Internet Hosts" = 71_164
"Internet Users" = 617_300
"Phones (Mobile)" = 97_180_000
"Phones (Landline)" = 962_000
GDP = 140_200_000_000
englishShortName = "Bangladesh"
frenchShortName = "Bangladesh (le)"
numeric = 50
japaneseShortName = "バングラデシュ"
[BB]
"Country Name" = "Barbados"
ISO2 = "BB"
ISO3 = "BRB"
"Top Level Domain" = "bb"
FIPS = "BB"
"ISO Numeric" = "052"
GeoNameID = 3_374_084
E164 = 1
"Phone Code" = "1-246"
Continent = "North America"
Capital = "Bridgetown"
"Time Zone in Capital" = "America/Barbados"
Currency = "Dollar"
"Language Codes" = "en-BB"
Languages = "English (official), Bajan (English-based creole language, widely spoken in informal settings)"
"Area KM2" = 431
"Internet Hosts" = 1_524
"Internet Users" = 188_000
"Phones (Mobile)" = 347_000
"Phones (Landline)" = 144_000
GDP = 4_262_000_000
englishShortName = "Barbados"
frenchShortName = "Barbade (la)"
numeric = 52
japaneseShortName = "バルバドス"
[BY]
"Country Name" = "Belarus"
ISO2 = "BY"
ISO3 = "BLR"
"Top Level Domain" = "by"
FIPS = "BO"
"ISO Numeric" = 112
GeoNameID = 630_336
E164 = 375
"Phone Code" = 375
Continent = "Europe"
Capital = "Minsk"
"Time Zone in Capital" = "Europe/Minsk"
Currency = "Ruble"
"Language Codes" = "be,ru"
Languages = "Belarusian (official) 23.4%, Russian (official) 70.2%, other 3.1% (includes small Polish- and Ukrainian-speaking minorities), unspecified 3.3% (2009 est.)"
"Area KM2" = 207_600
"Internet Hosts" = 295_217
"Internet Users" = 2_643_000
"Phones (Mobile)" = 10_675_000
"Phones (Landline)" = 4_407_000
GDP = 69_240_000_000
englishShortName = "Belarus"
frenchShortName = "Bélarus (le)"
numeric = 112
japaneseShortName = "ベラルーシ"
[BE]
"Country Name" = "Belgium"
ISO2 = "BE"
ISO3 = "BEL"
"Top Level Domain" = "be"
FIPS = "BE"
"ISO Numeric" = "056"
GeoNameID = 2_802_361
E164 = 32
"Phone Code" = 32
Continent = "Europe"
Capital = "Brussels"
"Time Zone in Capital" = "Europe/Brussels"
Currency = "Euro"
"Language Codes" = "nl-BE,fr-BE,de-BE"
Languages = "Dutch (official) 60%, French (official) 40%, German (official) less than 1%, legally bilingual (Dutch and French)"
"Area KM2" = 30_510
"Internet Hosts" = 5_192_000
"Internet Users" = 8_113_000
"Phones (Mobile)" = 12_880_000
"Phones (Landline)" = 4_631_000
GDP = 507_400_000_000
englishShortName = "Belgium"
frenchShortName = "Belgique (la)"
numeric = 56
japaneseShortName = "ベルギー"
[BZ]
"Country Name" = "Belize"
ISO2 = "BZ"
ISO3 = "BLZ"
"Top Level Domain" = "bz"
FIPS = "BH"
"ISO Numeric" = "084"
GeoNameID = 3_582_678
E164 = 501
"Phone Code" = 501
Continent = "North America"
Capital = "Belmopan"
"Time Zone in Capital" = "America/Belize"
Currency = "Dollar"
"Language Codes" = "en-BZ,es"
Languages = "Spanish 46%, Creole 32.9%, Mayan dialects 8.9%, English 3.9% (official), Garifuna 3.4% (Carib), German 3.3%, other 1.4%, unknown 0.2% (2000 census)"
"Area KM2" = 22_966
"Internet Hosts" = 3_392
"Internet Users" = 36_000
"Phones (Mobile)" = 164_200
"Phones (Landline)" = 25_400
GDP = 1_637_000_000
englishShortName = "Belize"
frenchShortName = "Belize (le)"
numeric = 84
japaneseShortName = "ベリーズ"
[BJ]
"Country Name" = "Benin"
ISO2 = "BJ"
ISO3 = "BEN"
"Top Level Domain" = "bj"
FIPS = "BN"
"ISO Numeric" = 204
GeoNameID = 2_395_170
E164 = 229
"Phone Code" = 229
Continent = "Africa"
Capital = "Porto-Novo"
"Time Zone in Capital" = "Africa/Lagos"
Currency = "Franc"
"Language Codes" = "fr-BJ"
Languages = "French (official), Fon and Yoruba (most common vernaculars in south), tribal languages (at least six major ones in north)"
"Area KM2" = 112_620
"Internet Hosts" = 491
"Internet Users" = 200_100
"Phones (Mobile)" = 8_408_000
"Phones (Landline)" = 156_700
GDP = 8_359_000_000
englishShortName = "Benin"
frenchShortName = "Bénin (le)"
numeric = 204
japaneseShortName = "ベナン"
[BM]
"Country Name" = "Bermuda"
ISO2 = "BM"
ISO3 = "BMU"
"Top Level Domain" = "bm"
FIPS = "BD"
"ISO Numeric" = "060"
GeoNameID = 3_573_345
E164 = 1
"Phone Code" = "1-441"
Continent = "North America"
Capital = "Hamilton"
"Time Zone in Capital" = "Atlantic/Bermuda"
Currency = "Dollar"
"Language Codes" = "en-BM,pt"
Languages = "English (official), Portuguese"
"Area KM2" = 53
"Internet Hosts" = 20_040
"Internet Users" = 54_000
"Phones (Mobile)" = 91_000
"Phones (Landline)" = 69_000
GDP = 5_600_000_000
englishShortName = "Bermuda"
frenchShortName = "Bermudes (les)"
numeric = 60
japaneseShortName = "バミューダ"
[BT]
"Country Name" = "Bhutan"
ISO2 = "BT"
ISO3 = "BTN"
"Top Level Domain" = "bt"
FIPS = "BT"
"ISO Numeric" = "064"
GeoNameID = 1_252_634
E164 = 975
"Phone Code" = 975
Continent = "Asia"
Capital = "Thimphu"
"Time Zone in Capital" = "Asia/Thimphu"
Currency = "Ngultrum"
"Language Codes" = "dz"
Languages = "Sharchhopka 28%, Dzongkha (official) 24%, Lhotshamkha 22%, other 26% (includes foreign languages) (2005 est.)"
"Area KM2" = 47_000
"Internet Hosts" = 14_590
"Internet Users" = 50_000
"Phones (Mobile)" = 560_000
"Phones (Landline)" = 27_000
GDP = 2_133_000_000
englishShortName = "Bhutan"
frenchShortName = "Bhoutan (le)"
numeric = 64
japaneseShortName = "ブータン"
[BO]
"Country Name" = "Bolivia"
ISO2 = "BO"
ISO3 = "BOL"
"Top Level Domain" = "bo"
FIPS = "BL"
"ISO Numeric" = "068"
GeoNameID = 3_923_057
E164 = 591
"Phone Code" = 591
Continent = "South America"
Capital = "Sucre"
"Time Zone in Capital" = "America/La_Paz"
Currency = "Boliviano"
"Language Codes" = "es-BO,qu,ay"
Languages = "Spanish (official) 60.7%, Quechua (official) 21.2%, Aymara (official) 14.6%, Guarani (official), foreign languages 2.4%, other 1.2%"
"Area KM2" = 1_098_580
"Internet Hosts" = 180_988
"Internet Users" = 1_103_000
"Phones (Mobile)" = 9_494_000
"Phones (Landline)" = 880_600
GDP = 30_790_000_000
englishShortName = "Bolivia (Plurinational State of)"
frenchShortName = "Bolivie (État plurinational de)"
numeric = 68
japaneseShortName = "ボリビア"
[BA]
"Country Name" = "Bosnia and Herzegovina"
ISO2 = "BA"
ISO3 = "BIH"
"Top Level Domain" = "ba"
FIPS = "BK"
"ISO Numeric" = "070"
GeoNameID = 3_277_605
E164 = 387
"Phone Code" = 387
Continent = "Europe"
Capital = "Sarajevo"
"Time Zone in Capital" = "Europe/Belgrade"
Currency = "Marka"
"Language Codes" = "bs,hr-BA,sr-BA"
Languages = "Bosnian (official), Croatian (official), Serbian (official)"
"Area KM2" = 51_129
"Internet Hosts" = 155_252
"Internet Users" = 1_422_000
"Phones (Mobile)" = 3_350_000
"Phones (Landline)" = 878_000
GDP = 18_870_000_000
englishShortName = "Bosnia and Herzegovina"
frenchShortName = "Bosnie-Herzégovine (la)"
numeric = 70
japaneseShortName = "ボスニア・ヘルツェゴビナ"
[BW]
"Country Name" = "Botswana"
ISO2 = "BW"
ISO3 = "BWA"
"Top Level Domain" = "bw"
FIPS = "BC"
"ISO Numeric" = "072"
GeoNameID = 933_860
E164 = 267
"Phone Code" = 267
Continent = "Africa"
Capital = "Gaborone"
"Time Zone in Capital" = "Africa/Maputo"
Currency = "Pula"
"Language Codes" = "en-BW,tn-BW"
Languages = "Setswana 78.2%, Kalanga 7.9%, Sekgalagadi 2.8%, English (official) 2.1%, other 8.6%, unspecified 0.4% (2001 census)"
"Area KM2" = 600_370
"Internet Hosts" = 1_806
"Internet Users" = 120_000
"Phones (Mobile)" = 3_082_000
"Phones (Landline)" = 160_500
GDP = 15_530_000_000
englishShortName = "Botswana"
frenchShortName = "Botswana (le)"
numeric = 72
japaneseShortName = "ボツワナ"
[BR]
"Country Name" = "Brazil"
ISO2 = "BR"
ISO3 = "BRA"
"Top Level Domain" = "br"
FIPS = "BR"
"ISO Numeric" = "076"
GeoNameID = 3_469_034
E164 = 55
"Phone Code" = 55
Continent = "South America"
Capital = "Brasilia"
"Time Zone in Capital" = "America/Sao_Paulo"
Currency = "Real"
"Language Codes" = "pt-BR,es,en,fr"
Languages = "Portuguese (official and most widely spoken language)"
"Area KM2" = 8_511_965
"Internet Hosts" = 26_577_000
"Internet Users" = 75_982_000
"Phones (Mobile)" = 248_324_000
"Phones (Landline)" = 44_300_000
GDP = 2_190_000_000_000
englishShortName = "Brazil"
frenchShortName = "Brésil (le)"
numeric = 76
japaneseShortName = "ブラジル"
[IO]
"Country Name" = "British Indian Ocean Territory"
ISO2 = "IO"
ISO3 = "IOT"
"Top Level Domain" = "io"
FIPS = "IO"
"ISO Numeric" = "086"
GeoNameID = 1_282_588
E164 = 246
"Phone Code" = 246
Continent = "Asia"
Capital = "Diego Garcia"
"Time Zone in Capital" = "Indian/Chagos"
Currency = "Dollar"
"Language Codes" = "en-IO"
Languages = "English"
"Area KM2" = 60
"Internet Hosts" = 75_006
"Internet Users" = ""
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = ""
englishShortName = "British Indian Ocean Territory (the)"
frenchShortName = "Indien (le Territoire britannique de l'océan)"
numeric = 86
japaneseShortName = "イギリス領インド洋地域"
[VG]
"Country Name" = "British Virgin Islands"
ISO2 = "VG"
ISO3 = "VGB"
"Top Level Domain" = "vg"
FIPS = "VI"
"ISO Numeric" = "092"
GeoNameID = 3_577_718
E164 = 1
"Phone Code" = "1-284"
Continent = "North America"
Capital = "Road Town"
"Time Zone in Capital" = "America/Port_of_Spain"
Currency = "Dollar"
"Language Codes" = "en-VG"
Languages = "English (official)"
"Area KM2" = 153
"Internet Hosts" = 505
"Internet Users" = 4_000
"Phones (Mobile)" = 48_700
"Phones (Landline)" = 12_268
GDP = 1_095_000_000
englishShortName = "Virgin Islands (British)"
frenchShortName = "Vierges britanniques (les Îles)"
numeric = 92
japaneseShortName = "イギリス領ヴァージン諸島"
[BN]
"Country Name" = "Brunei"
ISO2 = "BN"
ISO3 = "BRN"
"Top Level Domain" = "bn"
FIPS = "BX"
"ISO Numeric" = "096"
GeoNameID = 1_820_814
E164 = 673
"Phone Code" = 673
Continent = "Asia"
Capital = "Bandar Seri Begawan"
"Time Zone in Capital" = "Asia/Brunei"
Currency = "Dollar"
"Language Codes" = "ms-BN,en-BN"
Languages = "Malay (official), English, Chinese"
"Area KM2" = 5_770
"Internet Hosts" = 49_457
"Internet Users" = 314_900
"Phones (Mobile)" = 469_700
"Phones (Landline)" = 70_933
GDP = 16_560_000_000
englishShortName = "Brunei Darussalam"
frenchShortName = "Brunéi Darussalam (le)"
numeric = 96
japaneseShortName = "ブルネイ・ダルサラーム"
[BG]
"Country Name" = "Bulgaria"
ISO2 = "BG"
ISO3 = "BGR"
"Top Level Domain" = "bg"
FIPS = "BU"
"ISO Numeric" = 100
GeoNameID = 732_800
E164 = 359
"Phone Code" = 359
Continent = "Europe"
Capital = "Sofia"
"Time Zone in Capital" = "Europe/Sofia"
Currency = "Lev"
"Language Codes" = "bg,tr-BG"
Languages = "Bulgarian (official) 76.8%, Turkish 8.2%, Roma 3.8%, other 0.7%, unspecified 10.5% (2011 est.)"
"Area KM2" = 110_910
"Internet Hosts" = 976_277
"Internet Users" = 3_395_000
"Phones (Mobile)" = 10_780_000
"Phones (Landline)" = 2_253_000
GDP = 53_700_000_000
englishShortName = "Bulgaria"
frenchShortName = "Bulgarie (la)"
numeric = 100
japaneseShortName = "ブルガリア"
[BF]
"Country Name" = "Burkina Faso"
ISO2 = "BF"
ISO3 = "BFA"
"Top Level Domain" = "bf"
FIPS = "UV"
"ISO Numeric" = 854
GeoNameID = 2_361_809
E164 = 226
"Phone Code" = 226
Continent = "Africa"
Capital = "Ouagadougou"
"Time Zone in Capital" = "Africa/Abidjan"
Currency = "Franc"
"Language Codes" = "fr-BF"
Languages = "French (official), native African languages belonging to Sudanic family spoken by 90% of the population"
"Area KM2" = 274_200
"Internet Hosts" = 1_795
"Internet Users" = 178_100
"Phones (Mobile)" = 9_980_000
"Phones (Landline)" = 141_400
GDP = 12_130_000_000
englishShortName = "Burkina Faso"
frenchShortName = "Burkina Faso (le)"
numeric = 854
japaneseShortName = "ブルキナファソ"
[BI]
"Country Name" = "Burundi"
ISO2 = "BI"
ISO3 = "BDI"
"Top Level Domain" = "bi"
FIPS = "BY"
"ISO Numeric" = 108
GeoNameID = 433_561
E164 = 257
"Phone Code" = 257
Continent = "Africa"
Capital = "Bujumbura"
"Time Zone in Capital" = "Africa/Maputo"
Currency = "Franc"
"Language Codes" = "fr-BI,rn"
Languages = "Kirundi 29.7% (official), Kirundi and other language 9.1%, French (official) and French and other language 0.3%, Swahili and Swahili and other language 0.2% (along Lake Tanganyika and in the Bujumbura area), English and English and other language 0.06%, more than 2 languages 3.7%, unspecified 56.9% (2008 est.)"
"Area KM2" = 27_830
"Internet Hosts" = 229
"Internet Users" = 157_800
"Phones (Mobile)" = 2_247_000
"Phones (Landline)" = 17_400
GDP = 2_676_000_000
englishShortName = "Burundi"
frenchShortName = "Burundi (le)"
numeric = 108
japaneseShortName = "ブルンジ"
[KH]
"Country Name" = "Cambodia"
ISO2 = "KH"
ISO3 = "KHM"
"Top Level Domain" = "kh"
FIPS = "CB"
"ISO Numeric" = 116
GeoNameID = 1_831_722
E164 = 855
"Phone Code" = 855
Continent = "Asia"
Capital = "Phnom Penh"
"Time Zone in Capital" = "Asia/Phnom_Penh"
Currency = "Riels"
"Language Codes" = "km,fr,en"
Languages = "Khmer (official) 96.3%, other 3.7% (2008 est.)"
"Area KM2" = 181_040
"Internet Hosts" = 13_784
"Internet Users" = 78_500
"Phones (Mobile)" = 19_100_000
"Phones (Landline)" = 584_000
GDP = 15_640_000_000
englishShortName = "Cambodia"
frenchShortName = "Cambodge (le)"
numeric = 116
japaneseShortName = "カンボジア"
[CM]
"Country Name" = "Cameroon"
ISO2 = "CM"
ISO3 = "CMR"
"Top Level Domain" = "cm"
FIPS = "CM"
"ISO Numeric" = 120
GeoNameID = 2_233_387
E164 = 237
"Phone Code" = 237
Continent = "Africa"
Capital = "Yaounde"
"Time Zone in Capital" = "Africa/Lagos"
Currency = "Franc"
"Language Codes" = "en-CM,fr-CM"
Languages = "24 major African language groups, English (official), French (official)"
"Area KM2" = 475_440
"Internet Hosts" = 10_207
"Internet Users" = 749_600
"Phones (Mobile)" = 13_100_000
"Phones (Landline)" = 737_400
GDP = 27_880_000_000
englishShortName = "Cameroon"
frenchShortName = "Cameroun (le)"
numeric = 120
japaneseShortName = "カメルーン"
[CA]
"Country Name" = "Canada"
ISO2 = "CA"
ISO3 = "CAN"
"Top Level Domain" = "ca"
FIPS = "CA"
"ISO Numeric" = 124
GeoNameID = 6_251_999
E164 = 1
"Phone Code" = 1
Continent = "North America"
Capital = "Ottawa"
"Time Zone in Capital" = "America/Toronto"
Currency = "Dollar"
"Language Codes" = "en-CA,fr-CA,iu"
Languages = "English (official) 58.7%, French (official) 22%, Punjabi 1.4%, Italian 1.3%, Spanish 1.3%, German 1.3%, Cantonese 1.2%, Tagalog 1.2%, Arabic 1.1%, other 10.5% (2011 est.)"
"Area KM2" = 9_984_670
"Internet Hosts" = 8_743_000
"Internet Users" = 26_960_000
"Phones (Mobile)" = 26_263_000
"Phones (Landline)" = 18_010_000
GDP = 1_825_000_000_000
englishShortName = "Canada"
frenchShortName = "Canada (le)"
numeric = 124
japaneseShortName = "カナダ"
[CV]
"Country Name" = "Cape Verde"
ISO2 = "CV"
ISO3 = "CPV"
"Top Level Domain" = "cv"
FIPS = "CV"
"ISO Numeric" = 132
GeoNameID = 3_374_766
E164 = 238
"Phone Code" = 238
Continent = "Africa"
Capital = "Praia"
"Time Zone in Capital" = "Atlantic/Cape_Verde"
Currency = "Escudo"
"Language Codes" = "pt-CV"
Languages = "Portuguese (official), Crioulo (a blend of Portuguese and West African words)"
"Area KM2" = 4_033
"Internet Hosts" = 38
"Internet Users" = 150_000
"Phones (Mobile)" = 425_300
"Phones (Landline)" = 70_200
GDP = 1_955_000_000
englishShortName = "Cabo Verde"
frenchShortName = "Cabo Verde"
numeric = 132
japaneseShortName = "カーボベルデ"
[KY]
"Country Name" = "Cayman Islands"
ISO2 = "KY"
ISO3 = "CYM"
"Top Level Domain" = "ky"
FIPS = "CJ"
"ISO Numeric" = 136
GeoNameID = 3_580_718
E164 = 1
"Phone Code" = "1-345"
Continent = "North America"
Capital = "George Town"
"Time Zone in Capital" = "America/Cayman"
Currency = "Dollar"
"Language Codes" = "en-KY"
Languages = "English (official) 90.9%, Spanish 4%, Filipino 3.3%, other 1.7%, unspecified 0.1% (2010 est.)"
"Area KM2" = 262
"Internet Hosts" = 23_472
"Internet Users" = 23_000
"Phones (Mobile)" = 96_300
"Phones (Landline)" = 37_400
GDP = 2_250_000_000
englishShortName = "Cayman Islands (the)"
frenchShortName = "Caïmans (les Îles)"
numeric = 136
japaneseShortName = "ケイマン諸島"
[CF]
"Country Name" = "Central African Republic"
ISO2 = "CF"
ISO3 = "CAF"
"Top Level Domain" = "cf"
FIPS = "CT"
"ISO Numeric" = 140
GeoNameID = 239_880
E164 = 236
"Phone Code" = 236
Continent = "Africa"
Capital = "Bangui"
"Time Zone in Capital" = "Africa/Lagos"
Currency = "Franc"
"Language Codes" = "fr-CF,sg,ln,kg"
Languages = "French (official), Sangho (lingua franca and national language), tribal languages"
"Area KM2" = 622_984
"Internet Hosts" = 20
"Internet Users" = 22_600
"Phones (Mobile)" = 1_070_000
"Phones (Landline)" = 5_600
GDP = 2_050_000_000
englishShortName = "Central African Republic (the)"
frenchShortName = "République centrafricaine (la)"
numeric = 140
japaneseShortName = "中央アフリカ共和国"
[TD]
"Country Name" = "Chad"
ISO2 = "TD"
ISO3 = "TCD"
"Top Level Domain" = "td"
FIPS = "CD"
"ISO Numeric" = 148
GeoNameID = 2_434_508
E164 = 235
"Phone Code" = 235
Continent = "Africa"
Capital = "N'Djamena"
"Time Zone in Capital" = "Africa/Ndjamena"
Currency = "Franc"
"Language Codes" = "fr-TD,ar-TD,sre"
Languages = "French (official), Arabic (official), Sara (in south), more than 120 different languages and dialects"
"Area KM2" = 1_284_000
"Internet Hosts" = 6
"Internet Users" = 168_100
"Phones (Mobile)" = 4_200_000
"Phones (Landline)" = 29_900
GDP = 13_590_000_000
englishShortName = "Chad"
frenchShortName = "Tchad (le)"
numeric = 148
japaneseShortName = "チャド"
[CL]
"Country Name" = "Chile"
ISO2 = "CL"
ISO3 = "CHL"
"Top Level Domain" = "cl"
FIPS = "CI"
"ISO Numeric" = 152
GeoNameID = 3_895_114
E164 = 56
"Phone Code" = 56
Continent = "South America"
Capital = "Santiago"
"Time Zone in Capital" = "America/Santiago"
Currency = "Peso"
"Language Codes" = "es-CL"
Languages = "Spanish 99.5% (official), English 10.2%, indigenous 1% (includes Mapudungun, Aymara, Quechua, Rapa Nui), other 2.3%, unspecified 0.2%"
"Area KM2" = 756_950
"Internet Hosts" = 2_152_000
"Internet Users" = 7_009_000
"Phones (Mobile)" = 24_130_000
"Phones (Landline)" = 3_276_000
GDP = 281_700_000_000
englishShortName = "Chile"
frenchShortName = "Chili (le)"
numeric = 152
japaneseShortName = "チリ"
[CN]
"Country Name" = "China"
ISO2 = "CN"
ISO3 = "CHN"
"Top Level Domain" = "cn"
FIPS = "CH"
"ISO Numeric" = 156
GeoNameID = 1_814_991
E164 = 86
"Phone Code" = 86
Continent = "Asia"
Capital = "Beijing"
"Time Zone in Capital" = "Asia/Shanghai"
Currency = "Yuan Renminbi"
"Language Codes" = "zh-CN,yue,wuu,dta,ug,za"
Languages = "Standard Chinese or Mandarin (official; Putonghua, based on the Beijing dialect), Yue (Cantonese), Wu (Shanghainese), Minbei (Fuzhou), Minnan (Hokkien-Taiwanese), Xiang, Gan, Hakka dialects, minority languages"
"Area KM2" = 9_596_960
"Internet Hosts" = 20_602_000
"Internet Users" = 389_000_000
"Phones (Mobile)" = 1_100_000_000
"Phones (Landline)" = 278_860_000
GDP = 9_330_000_000_000
englishShortName = "China"
frenchShortName = "Chine (la)"
numeric = 156
japaneseShortName = "中国"
[CX]
"Country Name" = "Christmas Island"
ISO2 = "CX"
ISO3 = "CXR"
"Top Level Domain" = "cx"
FIPS = "KT"
"ISO Numeric" = 162
GeoNameID = 2_078_138
E164 = 61
"Phone Code" = 61
Continent = "Asia"
Capital = "Flying Fish Cove"
"Time Zone in Capital" = "Indian/Christmas"
Currency = "Dollar"
"Language Codes" = "en,zh,ms-CC"
Languages = "English (official), Chinese, Malay"
"Area KM2" = 135
"Internet Hosts" = 3_028
"Internet Users" = 464
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = ""
englishShortName = "Christmas Island"
frenchShortName = "Christmas (l'Île)"
numeric = 162
japaneseShortName = "クリスマス島"
[CC]
"Country Name" = "Cocos Islands"
ISO2 = "CC"
ISO3 = "CCK"
"Top Level Domain" = "cc"
FIPS = "CK"
"ISO Numeric" = 166
GeoNameID = 1_547_376
E164 = 61
"Phone Code" = 61
Continent = "Asia"
Capital = "West Island"
"Time Zone in Capital" = "Indian/Cocos"
Currency = "Dollar"
"Language Codes" = "ms-CC,en"
Languages = "Malay (Cocos dialect), English"
"Area KM2" = 14
"Internet Hosts" = ""
"Internet Users" = ""
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = ""
englishShortName = "Cocos (Keeling) Islands (the)"
frenchShortName = "Cocos (les Îles)/ Keeling (les Îles)"
numeric = 166
japaneseShortName = "ココス諸島"
[CO]
"Country Name" = "Colombia"
ISO2 = "CO"
ISO3 = "COL"
"Top Level Domain" = "co"
FIPS = "CO"
"ISO Numeric" = 170
GeoNameID = 3_686_110
E164 = 57
"Phone Code" = 57
Continent = "South America"
Capital = "Bogota"
"Time Zone in Capital" = "America/Bogota"
Currency = "Peso"
"Language Codes" = "es-CO"
Languages = "Spanish (official)"
"Area KM2" = 1_138_910
"Internet Hosts" = 4_410_000
"Internet Users" = 22_538_000
"Phones (Mobile)" = 49_066_000
"Phones (Landline)" = 6_291_000
GDP = 369_200_000_000
englishShortName = "Colombia"
frenchShortName = "Colombie (la)"
numeric = 170
japaneseShortName = "コロンビア"
[KM]
"Country Name" = "Comoros"
ISO2 = "KM"
ISO3 = "COM"
"Top Level Domain" = "km"
FIPS = "CN"
"ISO Numeric" = 174
GeoNameID = 921_929
E164 = 269
"Phone Code" = 269
Continent = "Africa"
Capital = "Moroni"
"Time Zone in Capital" = "Indian/Comoro"
Currency = "Franc"
"Language Codes" = "ar,fr-KM"
Languages = "Arabic (official), French (official), Shikomoro (a blend of Swahili and Arabic)"
"Area KM2" = 2_170
"Internet Hosts" = 14
"Internet Users" = 24_300
"Phones (Mobile)" = 250_000
"Phones (Landline)" = 24_000
GDP = 658_000_000
englishShortName = "Comoros (the)"
frenchShortName = "Comores (les)"
numeric = 174
japaneseShortName = "コモロ"
[CK]
"Country Name" = "Cook Islands"
ISO2 = "CK"
ISO3 = "COK"
"Top Level Domain" = "ck"
FIPS = "CW"
"ISO Numeric" = 184
GeoNameID = 1_899_402
E164 = 682
"Phone Code" = 682
Continent = "Oceania"
Capital = "Avarua"
"Time Zone in Capital" = "Pacific/Rarotonga"
Currency = "Dollar"
"Language Codes" = "en-CK,mi"
Languages = "English (official) 86.4%, Cook Islands Maori (Rarotongan) (official) 76.2%, other 8.3%"
"Area KM2" = 240
"Internet Hosts" = 3_562
"Internet Users" = 6_000
"Phones (Mobile)" = 7_800
"Phones (Landline)" = 7_200
GDP = 183_200_000
englishShortName = "Cook Islands (the)"
frenchShortName = "Cook (les Îles)"
numeric = 184
japaneseShortName = "クック諸島"
[CR]
"Country Name" = "Costa Rica"
ISO2 = "CR"
ISO3 = "CRI"
"Top Level Domain" = "cr"
FIPS = "CS"
"ISO Numeric" = 188
GeoNameID = 3_624_060
E164 = 506
"Phone Code" = 506
Continent = "North America"
Capital = "San Jose"
"Time Zone in Capital" = "America/Costa_Rica"
Currency = "Colon"
"Language Codes" = "es-CR,en"
Languages = "Spanish (official), English"
"Area KM2" = 51_100
"Internet Hosts" = 147_258
"Internet Users" = 1_485_000
"Phones (Mobile)" = 6_151_000
"Phones (Landline)" = 1_018_000
GDP = 48_510_000_000
englishShortName = "Costa Rica"
frenchShortName = "Costa Rica (le)"
numeric = 188
japaneseShortName = "コスタリカ"
[HR]
"Country Name" = "Croatia"
ISO2 = "HR"
ISO3 = "HRV"
"Top Level Domain" = "hr"
FIPS = "HR"
"ISO Numeric" = 191
GeoNameID = 3_202_326
E164 = 385
"Phone Code" = 385
Continent = "Europe"
Capital = "Zagreb"
"Time Zone in Capital" = "Europe/Belgrade"
Currency = "Kuna"
"Language Codes" = "hr-HR,sr"
Languages = "Croatian (official) 95.6%, Serbian 1.2%, other 3% (including Hungarian, Czech, Slovak, and Albanian), unspecified 0.2% (2011 est.)"
"Area KM2" = 56_542
"Internet Hosts" = 729_420
"Internet Users" = 2_234_000
"Phones (Mobile)" = 4_970_000
"Phones (Landline)" = 1_640_000
GDP = 59_140_000_000
englishShortName = "Croatia"
frenchShortName = "Croatie (la)"
numeric = 191
japaneseShortName = "クロアチア"
[CU]
"Country Name" = "Cuba"
ISO2 = "CU"
ISO3 = "CUB"
"Top Level Domain" = "cu"
FIPS = "CU"
"ISO Numeric" = 192
GeoNameID = 3_562_981
E164 = 53
"Phone Code" = 53
Continent = "North America"
Capital = "Havana"
"Time Zone in Capital" = "America/Havana"
Currency = "Peso"
"Language Codes" = "es-CU"
Languages = "Spanish (official)"
"Area KM2" = 110_860
"Internet Hosts" = 3_244
"Internet Users" = 1_606_000
"Phones (Mobile)" = 1_682_000
"Phones (Landline)" = 1_217_000
GDP = 72_300_000_000
englishShortName = "Cuba"
frenchShortName = "Cuba"
numeric = 192
japaneseShortName = "キューバ"
[CW]
"Country Name" = "Curacao"
ISO2 = "CW"
ISO3 = "CUW"
"Top Level Domain" = "cw"
FIPS = "UC"
"ISO Numeric" = 531
GeoNameID = 7_626_836
E164 = 599
"Phone Code" = 599
Continent = "North America"
Capital = "Willemstad"
"Time Zone in Capital" = "America/Curacao"
Currency = "Guilder"
"Language Codes" = "nl,pap"
Languages = "Papiamentu (a Spanish-Portuguese-Dutch-English dialect) 81.2%, Dutch (official) 8%, Spanish 4%, English 2.9%, other 3.9% (2001 census)"
"Area KM2" = 444
"Internet Hosts" = ""
"Internet Users" = ""
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = 5_600_000_000
englishShortName = "Curaçao"
frenchShortName = "Curaçao"
numeric = 531
[CY]
"Country Name" = "Cyprus"
ISO2 = "CY"
ISO3 = "CYP"
"Top Level Domain" = "cy"
FIPS = "CY"
"ISO Numeric" = 196
GeoNameID = 146_669
E164 = 357
"Phone Code" = 357
Continent = "Europe"
Capital = "Nicosia"
"Time Zone in Capital" = "Asia/Nicosia"
Currency = "Euro"
"Language Codes" = "el-CY,tr-CY,en"
Languages = "Greek (official) 80.9%, Turkish (official) 0.2%, English 4.1%, Romanian 2.9%, Russian 2.5%, Bulgarian 2.2%, Arabic 1.2%, Filippino 1.1%, other 4.3%, unspecified 0.6% (2011 est.)"
"Area KM2" = 9_250
"Internet Hosts" = 252_013
"Internet Users" = 433_900
"Phones (Mobile)" = 1_110_000
"Phones (Landline)" = 373_200
GDP = 21_780_000_000
englishShortName = "Cyprus"
frenchShortName = "Chypre"
numeric = 196
japaneseShortName = "キプロス"
[CZ]
"Country Name" = "Czech Republic"
ISO2 = "CZ"
ISO3 = "CZE"
"Top Level Domain" = "cz"
FIPS = "EZ"
"ISO Numeric" = 203
GeoNameID = 3_077_311
E164 = 420
"Phone Code" = 420
Continent = "Europe"
Capital = "Prague"
"Time Zone in Capital" = "Europe/Prague"
Currency = "Koruna"
"Language Codes" = "cs,sk"
Languages = "Czech 95.4%, Slovak 1.6%, other 3% (2011 census)"
"Area KM2" = 78_866
"Internet Hosts" = 4_148_000
"Internet Users" = 6_681_000
"Phones (Mobile)" = 12_973_000
"Phones (Landline)" = 2_100_000
GDP = 194_800_000_000
englishShortName = "Czechia"
frenchShortName = "Tchéquie (la)"
numeric = 203
japaneseShortName = "チェコ共和国"
[CD]
"Country Name" = "Democratic Republic of the Congo"
ISO2 = "CD"
ISO3 = "COD"
"Top Level Domain" = "cd"
FIPS = "CG"
"ISO Numeric" = 180
GeoNameID = 203_312
E164 = 243
"Phone Code" = 243
Continent = "Africa"
Capital = "Kinshasa"
"Time Zone in Capital" = "Africa/Lagos"
Currency = "Franc"
"Language Codes" = "fr-CD,ln,kg"
Languages = "French (official), Lingala (a lingua franca trade language), Kingwana (a dialect of Kiswahili or Swahili), Kikongo, Tshiluba"
"Area KM2" = 2_345_410
"Internet Hosts" = 2_515
"Internet Users" = 290_000
"Phones (Mobile)" = 19_487_000
"Phones (Landline)" = 58_200
GDP = 18_560_000_000
englishShortName = "Congo (the Democratic Republic of the)"
frenchShortName = "Congo (la République démocratique du)"
numeric = 180
japaneseShortName = "コンゴ民主共和国"
[DK]
"Country Name" = "Denmark"
ISO2 = "DK"
ISO3 = "DNK"
"Top Level Domain" = "dk"
FIPS = "DA"
"ISO Numeric" = 208
GeoNameID = 2_623_032
E164 = 45
"Phone Code" = 45
Continent = "Europe"
Capital = "Copenhagen"
"Time Zone in Capital" = "Europe/Copenhagen"
Currency = "Krone"
"Language Codes" = "da-DK,en,fo,de-DK"
Languages = "Danish, Faroese, Greenlandic (an Inuit dialect), German (small minority)"
"Area KM2" = 43_094
"Internet Hosts" = 4_297_000
"Internet Users" = 4_750_000
"Phones (Mobile)" = 6_600_000
"Phones (Landline)" = 2_431_000
GDP = 324_300_000_000
englishShortName = "Denmark"
frenchShortName = "Danemark (le)"
numeric = 208
japaneseShortName = "デンマーク"
[DJ]
"Country Name" = "Djibouti"
ISO2 = "DJ"
ISO3 = "DJI"
"Top Level Domain" = "dj"
FIPS = "DJ"
"ISO Numeric" = 262
GeoNameID = 223_816
E164 = 253
"Phone Code" = 253
Continent = "Africa"
Capital = "Djibouti"
"Time Zone in Capital" = "Africa/Djibouti"
Currency = "Franc"
"Language Codes" = "fr-DJ,ar,so-DJ,aa"
Languages = "French (official), Arabic (official), Somali, Afar"
"Area KM2" = 23_000
"Internet Hosts" = 215
"Internet Users" = 25_900
"Phones (Mobile)" = 209_000
"Phones (Landline)" = 18_000
GDP = 1_459_000_000
englishShortName = "Djibouti"
frenchShortName = "Djibouti"
numeric = 262
japaneseShortName = "ジブチ"
[DM]
"Country Name" = "Dominica"
ISO2 = "DM"
ISO3 = "DMA"
"Top Level Domain" = "dm"
FIPS = "DO"
"ISO Numeric" = 212
GeoNameID = 3_575_830
E164 = 1
"Phone Code" = "1-767"
Continent = "North America"
Capital = "Roseau"
"Time Zone in Capital" = "America/Port_of_Spain"
Currency = "Dollar"
"Language Codes" = "en-DM"
Languages = "English (official), French patois"
"Area KM2" = 754
"Internet Hosts" = 723
"Internet Users" = 28_000
"Phones (Mobile)" = 109_300
"Phones (Landline)" = 14_600
GDP = 495_000_000
englishShortName = "Dominica"
frenchShortName = "Dominique (la)"
numeric = 212
japaneseShortName = "ドミニカ"
[DO]
"Country Name" = "Dominican Republic"
ISO2 = "DO"
ISO3 = "DOM"
"Top Level Domain" = "do"
FIPS = "DR"
"ISO Numeric" = 214
GeoNameID = 3_508_796
E164 = 1
"Phone Code" = "1-809, 1-829, 1-849"
Continent = "North America"
Capital = "Santo Domingo"
"Time Zone in Capital" = "America/Santo_Domingo"
Currency = "Peso"
"Language Codes" = "es-DO"
Languages = "Spanish (official)"
"Area KM2" = 48_730
"Internet Hosts" = 404_500
"Internet Users" = 2_701_000
"Phones (Mobile)" = 9_038_000
"Phones (Landline)" = 1_065_000
GDP = 59_270_000_000
englishShortName = "Dominican Republic (the)"
frenchShortName = "dominicaine (la République)"
numeric = 214
japaneseShortName = "ドミニカ共和国"
[TL]
"Country Name" = "East Timor"
ISO2 = "TL"
ISO3 = "TLS"
"Top Level Domain" = "tl"
FIPS = "TT"
"ISO Numeric" = 626
GeoNameID = 1_966_436
E164 = 670
"Phone Code" = 670
Continent = "Oceania"
Capital = "Dili"
"Time Zone in Capital" = "Asia/Dili"
Currency = "Dollar"
"Language Codes" = "tet,pt-TL,id,en"
Languages = "Tetum (official), Portuguese (official), Indonesian, English"
"Area KM2" = 15_007
"Internet Hosts" = 252
"Internet Users" = 2_100
"Phones (Mobile)" = 621_000
"Phones (Landline)" = 3_000
GDP = 6_129_000_000
englishShortName = "Timor-Leste"
frenchShortName = "Timor-Leste (le)"
numeric = 626
japaneseShortName = "東ティモール"
[EC]
"Country Name" = "Ecuador"
ISO2 = "EC"
ISO3 = "ECU"
"Top Level Domain" = "ec"
FIPS = "EC"
"ISO Numeric" = 218
GeoNameID = 3_658_394
E164 = 593
"Phone Code" = 593
Continent = "South America"
Capital = "Quito"
"Time Zone in Capital" = "America/Guayaquil"
Currency = "Dollar"
"Language Codes" = "es-EC"
Languages = "Spanish (Castillian) 93% (official), Quechua 4.1%, other indigenous 0.7%, foreign 2.2%"
"Area KM2" = 283_560
"Internet Hosts" = 170_538
"Internet Users" = 3_352_000
"Phones (Mobile)" = 16_457_000
"Phones (Landline)" = 2_310_000
GDP = 91_410_000_000
englishShortName = "Ecuador"
frenchShortName = "Équateur (l')"
numeric = 218
japaneseShortName = "エクアドル"
[EG]
"Country Name" = "Egypt"
ISO2 = "EG"
ISO3 = "EGY"
"Top Level Domain" = "eg"
FIPS = "EG"
"ISO Numeric" = 818
GeoNameID = 357_994
E164 = 20
"Phone Code" = 20
Continent = "Africa"
Capital = "Cairo"
"Time Zone in Capital" = "Africa/Cairo"
Currency = "Pound"
"Language Codes" = "ar-EG,en,fr"
Languages = "Arabic (official), English and French widely understood by educated classes"
"Area KM2" = 1_001_450
"Internet Hosts" = 200_430
"Internet Users" = 20_136_000
"Phones (Mobile)" = 96_800_000
"Phones (Landline)" = 8_557_000
GDP = 262_000_000_000
englishShortName = "Egypt"
frenchShortName = "Égypte (l')"
numeric = 818
japaneseShortName = "エジプト"
[SV]
"Country Name" = "El Salvador"
ISO2 = "SV"
ISO3 = "SLV"
"Top Level Domain" = "sv"
FIPS = "ES"
"ISO Numeric" = 222
GeoNameID = 3_585_968
E164 = 503
"Phone Code" = 503
Continent = "North America"
Capital = "San Salvador"
"Time Zone in Capital" = "America/El_Salvador"
Currency = "Dollar"
"Language Codes" = "es-SV"
Languages = "Spanish (official), Nahua (among some Amerindians)"
"Area KM2" = 21_040
"Internet Hosts" = 24_070
"Internet Users" = 746_000
"Phones (Mobile)" = 8_650_000
"Phones (Landline)" = 1_060_000
GDP = 24_670_000_000
englishShortName = "El Salvador"
frenchShortName = "El Salvador"
numeric = 222
japaneseShortName = "エルサルバドル"
[GQ]
"Country Name" = "Equatorial Guinea"
ISO2 = "GQ"
ISO3 = "GNQ"
"Top Level Domain" = "gq"
FIPS = "EK"
"ISO Numeric" = 226
GeoNameID = 2_309_096
E164 = 240
"Phone Code" = 240
Continent = "Africa"
Capital = "Malabo"
"Time Zone in Capital" = "Africa/Lagos"
Currency = "Franc"
"Language Codes" = "es-GQ,fr"
Languages = "Spanish (official) 67.6%, other (includes French (official), Fang, Bubi) 32.4% (1994 census)"
"Area KM2" = 28_051
"Internet Hosts" = 7
"Internet Users" = 14_400
"Phones (Mobile)" = 501_000
"Phones (Landline)" = 14_900
GDP = 17_080_000_000
englishShortName = "Equatorial Guinea"
frenchShortName = "Guinée équatoriale (la)"
numeric = 226
japaneseShortName = "赤道ギニア"
[ER]
"Country Name" = "Eritrea"
ISO2 = "ER"
ISO3 = "ERI"
"Top Level Domain" = "er"
FIPS = "ER"
"ISO Numeric" = 232
GeoNameID = 338_010
E164 = 291
"Phone Code" = 291
Continent = "Africa"
Capital = "Asmara"
"Time Zone in Capital" = "Africa/Asmara"
Currency = "Nakfa"
"Language Codes" = "aa-ER,ar,tig,kun,ti-ER"
Languages = "Tigrinya (official), Arabic (official), English (official), Tigre, Kunama, Afar, other Cushitic languages"
"Area KM2" = 121_320
"Internet Hosts" = 701
"Internet Users" = 200_000
"Phones (Mobile)" = 305_300
"Phones (Landline)" = 60_000
GDP = 3_438_000_000
englishShortName = "Eritrea"
frenchShortName = "Érythrée (l')"
numeric = 232
japaneseShortName = "エリトリア"
[EE]
"Country Name" = "Estonia"
ISO2 = "EE"
ISO3 = "EST"
"Top Level Domain" = "ee"
FIPS = "EN"
"ISO Numeric" = 233
GeoNameID = 453_733
E164 = 372
"Phone Code" = 372
Continent = "Europe"
Capital = "Tallinn"
"Time Zone in Capital" = "Europe/Tallinn"
Currency = "Euro"
"Language Codes" = "et,ru"
Languages = "Estonian (official) 68.5%, Russian 29.6%, Ukrainian 0.6%, other 1.2%, unspecified 0.1% (2011 est.)"
"Area KM2" = 45_226
"Internet Hosts" = 865_494
"Internet Users" = 971_700
"Phones (Mobile)" = 2_070_000
"Phones (Landline)" = 448_200
GDP = 24_280_000_000
englishShortName = "Estonia"
frenchShortName = "Estonie (l')"
numeric = 233
japaneseShortName = "エストニア"
[ET]
"Country Name" = "Ethiopia"
ISO2 = "ET"
ISO3 = "ETH"
"Top Level Domain" = "et"
FIPS = "ET"
"ISO Numeric" = 231
GeoNameID = 337_996
E164 = 251
"Phone Code" = 251
Continent = "Africa"
Capital = "Addis Ababa"
"Time Zone in Capital" = "Africa/Addis_Ababa"
Currency = "Birr"
"Language Codes" = "am,en-ET,om-ET,ti-ET,so-ET,sid"
Languages = "Oromo (official working language in the State of Oromiya) 33.8%, Amharic (official national language) 29.3%, Somali (official working language of the State of Sumale) 6.2%, Tigrigna (Tigrinya) (official working language of the State of Tigray) 5.9%, Sidamo 4%, Wolaytta 2.2%, Gurage 2%, Afar (official working language of the State of Afar) 1.7%, Hadiyya 1.7%, Gamo 1.5%, Gedeo 1.3%, Opuuo 1.2%, Kafa 1.1%, other 8.1%, English (major foreign language taught in schools), Arabic (2007 est.)"
"Area KM2" = 1_127_127
"Internet Hosts" = 179
"Internet Users" = 447_300
"Phones (Mobile)" = 20_524_000
"Phones (Landline)" = 797_500
GDP = 47_340_000_000
englishShortName = "Ethiopia"
frenchShortName = "Éthiopie (l')"
numeric = 231
japaneseShortName = "エチオピア"
[FK]
"Country Name" = "Falkland Islands"
ISO2 = "FK"
ISO3 = "FLK"
"Top Level Domain" = "fk"
FIPS = "FK"
"ISO Numeric" = 238
GeoNameID = 3_474_414
E164 = 500
"Phone Code" = 500
Continent = "South America"
Capital = "Stanley"
"Time Zone in Capital" = "Atlantic/Stanley"
Currency = "Pound"
"Language Codes" = "en-FK"
Languages = "English 89%, Spanish 7.7%, other 3.3% (2006 est.)"
"Area KM2" = 12_173
"Internet Hosts" = 110
"Internet Users" = 2_900
"Phones (Mobile)" = 3_450
"Phones (Landline)" = 1_980
GDP = 164_500_000
englishShortName = "Falkland Islands (the) [Malvinas]"
frenchShortName = "Falkland (les Îles)/Malouines (les Îles)"
numeric = 238
japaneseShortName = "フォークランド諸島(マルビナス)"
[FO]
"Country Name" = "Faroe Islands"
ISO2 = "FO"
ISO3 = "FRO"
"Top Level Domain" = "fo"
FIPS = "FO"
"ISO Numeric" = 234
GeoNameID = 2_622_320
E164 = 298
"Phone Code" = 298
Continent = "Europe"
Capital = "Torshavn"
"Time Zone in Capital" = "Atlantic/Faroe"
Currency = "Krone"
"Language Codes" = "fo,da-FO"
Languages = "Faroese (derived from Old Norse), Danish"
"Area KM2" = 1_399
"Internet Hosts" = 7_575
"Internet Users" = 37_500
"Phones (Mobile)" = 61_000
"Phones (Landline)" = 24_000
GDP = 2_320_000_000
englishShortName = "Faroe Islands (the)"
frenchShortName = "Féroé (les Îles)"
numeric = 234
japaneseShortName = "フェロー諸島"
[FJ]
"Country Name" = "Fiji"
ISO2 = "FJ"
ISO3 = "FJI"
"Top Level Domain" = "fj"
FIPS = "FJ"
"ISO Numeric" = 242
GeoNameID = 2_205_218
E164 = 679
"Phone Code" = 679
Continent = "Oceania"
Capital = "Suva"
"Time Zone in Capital" = "Pacific/Fiji"
Currency = "Dollar"
"Language Codes" = "en-FJ,fj"
Languages = "English (official), Fijian (official), Hindustani"
"Area KM2" = 18_270
"Internet Hosts" = 21_739
"Internet Users" = 114_200
"Phones (Mobile)" = 858_800
"Phones (Landline)" = 88_400
GDP = 4_218_000_000
englishShortName = "Fiji"
frenchShortName = "Fidji (les)"
numeric = 242
japaneseShortName = "フィジー"
[FI]
"Country Name" = "Finland"
ISO2 = "FI"
ISO3 = "FIN"
"Top Level Domain" = "fi"
FIPS = "FI"
"ISO Numeric" = 246
GeoNameID = 660_013
E164 = 358
"Phone Code" = 358
Continent = "Europe"
Capital = "Helsinki"
"Time Zone in Capital" = "Europe/Helsinki"
Currency = "Euro"
"Language Codes" = "fi-FI,sv-FI,smn"
Languages = "Finnish (official) 94.2%, Swedish (official) 5.5%, other (small Sami- and Russian-speaking minorities) 0.2% (2012 est.)"
"Area KM2" = 337_030
"Internet Hosts" = 4_763_000
"Internet Users" = 4_393_000
"Phones (Mobile)" = 9_320_000
"Phones (Landline)" = 890_000
GDP = 259_600_000_000
englishShortName = "Finland"
frenchShortName = "Finlande (la)"
numeric = 246
japaneseShortName = "フィンランド"
[FR]
"Country Name" = "France"
ISO2 = "FR"
ISO3 = "FRA"
"Top Level Domain" = "fr"
FIPS = "FR"
"ISO Numeric" = 250
GeoNameID = 3_017_382
E164 = 33
"Phone Code" = 33
Continent = "Europe"
Capital = "Paris"
"Time Zone in Capital" = "Europe/Paris"
Currency = "Euro"
"Language Codes" = "fr-FR,frp,br,co,ca,eu,oc"
Languages = "French (official) 100%, rapidly declining regional dialects and languages (Provencal, Breton, Alsatian, Corsican, Catalan, Basque, Flemish)"
"Area KM2" = 547_030
"Internet Hosts" = 17_266_000
"Internet Users" = 45_262_000
"Phones (Mobile)" = 62_280_000
"Phones (Landline)" = 39_290_000
GDP = 2_739_000_000_000
englishShortName = "France"
frenchShortName = "France (la)"
numeric = 250
japaneseShortName = "フランス"
[PF]
"Country Name" = "French Polynesia"
ISO2 = "PF"
ISO3 = "PYF"
"Top Level Domain" = "pf"
FIPS = "FP"
"ISO Numeric" = 258
GeoNameID = 4_030_656
E164 = 689
"Phone Code" = 689
Continent = "Oceania"
Capital = "Papeete"
"Time Zone in Capital" = "Pacific/Tahiti"
Currency = "Franc"
"Language Codes" = "fr-PF,ty"
Languages = "French (official) 61.1%, Polynesian (official) 31.4%, Asian languages 1.2%, other 0.3%, unspecified 6% (2002 census)"
"Area KM2" = 4_167
"Internet Hosts" = 37_949
"Internet Users" = 120_000
"Phones (Mobile)" = 226_000
"Phones (Landline)" = 55_000
GDP = 5_650_000_000
englishShortName = "French Polynesia"
frenchShortName = "Polynésie française (la)"
numeric = 258
japaneseShortName = "フランス領ポリネシア"
[GA]
"Country Name" = "Gabon"
ISO2 = "GA"
ISO3 = "GAB"
"Top Level Domain" = "ga"
FIPS = "GB"
"ISO Numeric" = 266
GeoNameID = 2_400_553
E164 = 241
"Phone Code" = 241
Continent = "Africa"
Capital = "Libreville"
"Time Zone in Capital" = "Africa/Lagos"
Currency = "Franc"
"Language Codes" = "fr-GA"
Languages = "French (official), Fang, Myene, Nzebi, Bapounou/Eschira, Bandjabi"
"Area KM2" = 267_667
"Internet Hosts" = 127
"Internet Users" = 98_800
"Phones (Mobile)" = 2_930_000
"Phones (Landline)" = 17_000
GDP = 19_970_000_000
englishShortName = "Gabon"
frenchShortName = "Gabon (le)"
numeric = 266
japaneseShortName = "ガボン"
[GM]
"Country Name" = "Gambia"
ISO2 = "GM"
ISO3 = "GMB"
"Top Level Domain" = "gm"
FIPS = "GA"
"ISO Numeric" = 270
GeoNameID = 2_413_451
E164 = 220
"Phone Code" = 220
Continent = "Africa"
Capital = "Banjul"
"Time Zone in Capital" = "Africa/Abidjan"
Currency = "Dalasi"
"Language Codes" = "en-GM,mnk,wof,wo,ff"
Languages = "English (official), Mandinka, Wolof, Fula, other indigenous vernaculars"
"Area KM2" = 11_300
"Internet Hosts" = 656
"Internet Users" = 130_100
"Phones (Mobile)" = 1_526_000
"Phones (Landline)" = 64_200
GDP = 896_000_000
englishShortName = "Gambia (the)"
frenchShortName = "Gambie (la)"
numeric = 270
japaneseShortName = "ガンビア"
[GE]
"Country Name" = "Georgia"
ISO2 = "GE"
ISO3 = "GEO"
"Top Level Domain" = "ge"
FIPS = "GG"
"ISO Numeric" = 268
GeoNameID = 614_540
E164 = 995
"Phone Code" = 995
Continent = "Asia"
Capital = "Tbilisi"
"Time Zone in Capital" = "Asia/Tbilisi"
Currency = "Lari"
"Language Codes" = "ka,ru,hy,az"
Languages = "Georgian (official) 71%, Russian 9%, Armenian 7%, Azeri 6%, other 7%"
"Area KM2" = 69_700
"Internet Hosts" = 357_864
"Internet Users" = 1_300_000
"Phones (Mobile)" = 4_699_000
"Phones (Landline)" = 1_276_000
GDP = 15_950_000_000
englishShortName = "Georgia"
frenchShortName = "Géorgie (la)"
numeric = 268
japaneseShortName = "ジョージア"
[DE]
"Country Name" = "Germany"
ISO2 = "DE"
ISO3 = "DEU"
"Top Level Domain" = "de"
FIPS = "GM"
"ISO Numeric" = 276
GeoNameID = 2_921_044
E164 = 49
"Phone Code" = 49
Continent = "Europe"
Capital = "Berlin"
"Time Zone in Capital" = "Europe/Berlin"
Currency = "Euro"
"Language Codes" = "de"
Languages = "German (official)"
"Area KM2" = 357_021
"Internet Hosts" = 20_043_000
"Internet Users" = 65_125_000
"Phones (Mobile)" = 107_700_000
"Phones (Landline)" = 50_700_000
GDP = 3_593_000_000_000
englishShortName = "Germany"
frenchShortName = "Allemagne (l')"
numeric = 276
japaneseShortName = "ドイツ"
[GH]
"Country Name" = "Ghana"
ISO2 = "GH"
ISO3 = "GHA"
"Top Level Domain" = "gh"
FIPS = "GH"
"ISO Numeric" = 288
GeoNameID = 2_300_660
E164 = 233
"Phone Code" = 233
Continent = "Africa"
Capital = "Accra"
"Time Zone in Capital" = "Africa/Accra"
Currency = "Cedi"
"Language Codes" = "en-GH,ak,ee,tw"
Languages = "Asante 14.8%, Ewe 12.7%, Fante 9.9%, Boron (Brong) 4.6%, Dagomba 4.3%, Dangme 4.3%, Dagarte (Dagaba) 3.7%, Akyem 3.4%, Ga 3.4%, Akuapem 2.9%, other (includes English (official)) 36.1% (2000 census)"
"Area KM2" = 239_460
"Internet Hosts" = 59_086
"Internet Users" = 1_297_000
"Phones (Mobile)" = 25_618_000
"Phones (Landline)" = 285_000
GDP = 45_550_000_000
englishShortName = "Ghana"
frenchShortName = "Ghana (le)"
numeric = 288
japaneseShortName = "ガーナ"
[GI]
"Country Name" = "Gibraltar"
ISO2 = "GI"
ISO3 = "GIB"
"Top Level Domain" = "gi"
FIPS = "GI"
"ISO Numeric" = 292
GeoNameID = 2_411_586
E164 = 350
"Phone Code" = 350
Continent = "Europe"
Capital = "Gibraltar"
"Time Zone in Capital" = "Europe/Gibraltar"
Currency = "Pound"
"Language Codes" = "en-GI,es,it,pt"
Languages = "English (used in schools and for official purposes), Spanish, Italian, Portuguese"
"Area KM2" = 7
"Internet Hosts" = 3_509
"Internet Users" = 20_200
"Phones (Mobile)" = 34_750
"Phones (Landline)" = 23_100
GDP = 1_106_000_000
englishShortName = "Gibraltar"
frenchShortName = "Gibraltar"
numeric = 292
japaneseShortName = "ジブラルタル"
[GR]
"Country Name" = "Greece"
ISO2 = "GR"
ISO3 = "GRC"
"Top Level Domain" = "gr"
FIPS = "GR"
"ISO Numeric" = 300
GeoNameID = 390_903
E164 = 30
"Phone Code" = 30
Continent = "Europe"
Capital = "Athens"
"Time Zone in Capital" = "Europe/Athens"
Currency = "Euro"
"Language Codes" = "el-GR,en,fr"
Languages = "Greek (official) 99%, other (includes English and French) 1%"
"Area KM2" = 131_940
"Internet Hosts" = 3_201_000
"Internet Users" = 4_971_000
"Phones (Mobile)" = 13_354_000
"Phones (Landline)" = 5_461_000
GDP = 243_300_000_000
englishShortName = "Greece"
frenchShortName = "Grèce (la)"
numeric = 300
japaneseShortName = "ギリシャ"
[GL]
"Country Name" = "Greenland"
ISO2 = "GL"
ISO3 = "GRL"
"Top Level Domain" = "gl"
FIPS = "GL"
"ISO Numeric" = 304
GeoNameID = 3_425_505
E164 = 299
"Phone Code" = 299
Continent = "North America"
Capital = "Nuuk"
"Time Zone in Capital" = "America/Godthab"
Currency = "Krone"
"Language Codes" = "kl,da-GL,en"
Languages = "Greenlandic (East Inuit) (official), Danish (official), English"
"Area KM2" = 2_166_086
"Internet Hosts" = 15_645
"Internet Users" = 36_000
"Phones (Mobile)" = 59_455
"Phones (Landline)" = 18_900
GDP = 2_160_000_000
englishShortName = "Greenland"
frenchShortName = "Groenland (le)"
numeric = 304
japaneseShortName = "グリーンランド"
[GD]
"Country Name" = "Grenada"
ISO2 = "GD"
ISO3 = "GRD"
"Top Level Domain" = "gd"
FIPS = "GJ"
"ISO Numeric" = 308
GeoNameID = 3_580_239
E164 = 1
"Phone Code" = "1-473"
Continent = "North America"
Capital = "St. George's"
"Time Zone in Capital" = "America/Port_of_Spain"
Currency = "Dollar"
"Language Codes" = "en-GD"
Languages = "English (official), French patois"
"Area KM2" = 344
"Internet Hosts" = 80
"Internet Users" = 25_000
"Phones (Mobile)" = 128_000
"Phones (Landline)" = 28_500
GDP = 811_000_000
englishShortName = "Grenada"
frenchShortName = "Grenade (la)"
numeric = 308
japaneseShortName = "グレナダ"
[GU]
"Country Name" = "Guam"
ISO2 = "GU"
ISO3 = "GUM"
"Top Level Domain" = "gu"
FIPS = "GQ"
"ISO Numeric" = 316
GeoNameID = 4_043_988
E164 = 1
"Phone Code" = "1-671"
Continent = "Oceania"
Capital = "Hagatna"
"Time Zone in Capital" = "Pacific/Guam"
Currency = "Dollar"
"Language Codes" = "en-GU,ch-GU"
Languages = "English 43.6%, Filipino 21.2%, Chamorro 17.8%, other Pacific island languages 10%, Asian languages 6.3%, other 1.1% (2010 est.)"
"Area KM2" = 549
"Internet Hosts" = 23
"Internet Users" = 90_000
"Phones (Mobile)" = 98_000
"Phones (Landline)" = 67_000
GDP = 4_600_000_000
englishShortName = "Guam"
frenchShortName = "Guam"
numeric = 316
japaneseShortName = "グアム島"
[GT]
"Country Name" = "Guatemala"
ISO2 = "GT"
ISO3 = "GTM"
"Top Level Domain" = "gt"
FIPS = "GT"
"ISO Numeric" = 320
GeoNameID = 3_595_528
E164 = 502
"Phone Code" = 502
Continent = "North America"
Capital = "Guatemala City"
"Time Zone in Capital" = "America/Guatemala"
Currency = "Quetzal"
"Language Codes" = "es-GT"
Languages = "Spanish (official) 60%, Amerindian languages 40%"
"Area KM2" = 108_890
"Internet Hosts" = 357_552
"Internet Users" = 2_279_000
"Phones (Mobile)" = 20_787_000
"Phones (Landline)" = 1_744_000
GDP = 53_900_000_000
englishShortName = "Guatemala"
frenchShortName = "Guatemala (le)"
numeric = 320
japaneseShortName = "グアテマラ"
[GG]
"Country Name" = "Guernsey"
ISO2 = "GG"
ISO3 = "GGY"
"Top Level Domain" = "gg"
FIPS = "GK"
"ISO Numeric" = 831
GeoNameID = 3_042_362
E164 = 44
"Phone Code" = "44-1481"
Continent = "Europe"
Capital = "St Peter Port"
"Time Zone in Capital" = "Europe/London"
Currency = "Pound"
"Language Codes" = "en,fr"
Languages = "English, French, Norman-French dialect spoken in country districts"
"Area KM2" = 78
"Internet Hosts" = 239
"Internet Users" = 48_300
"Phones (Mobile)" = 43_800
"Phones (Landline)" = 45_100
GDP = 2_742_000_000
englishShortName = "Guernsey"
frenchShortName = "Guernesey"
numeric = 831
japaneseShortName = "ガーンジー"
[GN]
"Country Name" = "Guinea"
ISO2 = "GN"
ISO3 = "GIN"
"Top Level Domain" = "gn"
FIPS = "GV"
"ISO Numeric" = 324
GeoNameID = 2_420_477
E164 = 224
"Phone Code" = 224
Continent = "Africa"
Capital = "Conakry"
"Time Zone in Capital" = "Africa/Abidjan"
Currency = "Franc"
"Language Codes" = "fr-GN"
Languages = "French (official)"
"Area KM2" = 245_857
"Internet Hosts" = 15
"Internet Users" = 95_000
"Phones (Mobile)" = 4_781_000
"Phones (Landline)" = 18_000
GDP = 6_544_000_000
englishShortName = "Guinea"
frenchShortName = "Guinée (la)"
numeric = 324
japaneseShortName = "ギニア"
[GW]
"Country Name" = "Guinea-Bissau"
ISO2 = "GW"
ISO3 = "GNB"
"Top Level Domain" = "gw"
FIPS = "PU"
"ISO Numeric" = 624
GeoNameID = 2_372_248
E164 = 245
"Phone Code" = 245
Continent = "Africa"
Capital = "Bissau"
"Time Zone in Capital" = "Africa/Bissau"
Currency = "Franc"
"Language Codes" = "pt-GW,pov"
Languages = "Portuguese (official), Crioulo, African languages"
"Area KM2" = 36_120
"Internet Hosts" = 90
"Internet Users" = 37_100
"Phones (Mobile)" = 1_100_000
"Phones (Landline)" = 5_000
GDP = 880_000_000
englishShortName = "Guinea-Bissau"
frenchShortName = "Guinée-Bissau (la)"
numeric = 624
japaneseShortName = "ギニアビサウ"
[GY]
"Country Name" = "Guyana"
ISO2 = "GY"
ISO3 = "GUY"
"Top Level Domain" = "gy"
FIPS = "GY"
"ISO Numeric" = 328
GeoNameID = 3_378_535
E164 = 592
"Phone Code" = 592
Continent = "South America"
Capital = "Georgetown"
"Time Zone in Capital" = "America/Guyana"
Currency = "Dollar"
"Language Codes" = "en-GY"
Languages = "English, Amerindian dialects, Creole, Caribbean Hindustani (a dialect of Hindi), Urdu"
"Area KM2" = 214_970
"Internet Hosts" = 24_936
"Internet Users" = 189_600
"Phones (Mobile)" = 547_000
"Phones (Landline)" = 154_200
GDP = 3_020_000_000
englishShortName = "Guyana"
frenchShortName = "Guyana (le)"
numeric = 328
japaneseShortName = "ガイアナ"
[HT]
"Country Name" = "Haiti"
ISO2 = "HT"
ISO3 = "HTI"
"Top Level Domain" = "ht"
FIPS = "HA"
"ISO Numeric" = 332
GeoNameID = 3_723_988
E164 = 509
"Phone Code" = 509
Continent = "North America"
Capital = "Port-au-Prince"
"Time Zone in Capital" = "America/Port-au-Prince"
Currency = "Gourde"
"Language Codes" = "ht,fr-HT"
Languages = "French (official), Creole (official)"
"Area KM2" = 27_750
"Internet Hosts" = 555
"Internet Users" = 1_000_000
"Phones (Mobile)" = 6_095_000
"Phones (Landline)" = 50_000
GDP = 8_287_000_000
englishShortName = "Haiti"
frenchShortName = "Haïti"
numeric = 332
japaneseShortName = "ハイチ"
[HN]
"Country Name" = "Honduras"
ISO2 = "HN"
ISO3 = "HND"
"Top Level Domain" = "hn"
FIPS = "HO"
"ISO Numeric" = 340
GeoNameID = 3_608_932
E164 = 504
"Phone Code" = 504
Continent = "North America"
Capital = "Tegucigalpa"
"Time Zone in Capital" = "America/Tegucigalpa"
Currency = "Lempira"
"Language Codes" = "es-HN"
Languages = "Spanish (official), Amerindian dialects"
"Area KM2" = 112_090
"Internet Hosts" = 30_955
"Internet Users" = 731_700
"Phones (Mobile)" = 7_370_000
"Phones (Landline)" = 610_000
GDP = 18_880_000_000
englishShortName = "Honduras"
frenchShortName = "Honduras (le)"
numeric = 340
japaneseShortName = "ホンジュラス"
[HK]
"Country Name" = "Hong Kong"
ISO2 = "HK"
ISO3 = "HKG"
"Top Level Domain" = "hk"
FIPS = "HK"
"ISO Numeric" = 344
GeoNameID = 1_819_730
E164 = 852
"Phone Code" = 852
Continent = "Asia"
Capital = "Hong Kong"
"Time Zone in Capital" = "Asia/Hong_Kong"
Currency = "Dollar"
"Language Codes" = "zh-HK,yue,zh,en"
Languages = "Cantonese (official) 89.5%, English (official) 3.5%, Putonghua (Mandarin) 1.4%, other Chinese dialects 4%, other 1.6% (2011 est.)"
"Area KM2" = 1_092
"Internet Hosts" = 870_041
"Internet Users" = 4_873_000
"Phones (Mobile)" = 16_403_000
"Phones (Landline)" = 4_362_000
GDP = 272_100_000_000
englishShortName = "Hong Kong"
frenchShortName = "Hong Kong"
numeric = 344
japaneseShortName = "香港"
[HU]
"Country Name" = "Hungary"
ISO2 = "HU"
ISO3 = "HUN"
"Top Level Domain" = "hu"
FIPS = "HU"
"ISO Numeric" = 348
GeoNameID = 719_819
E164 = 36
"Phone Code" = 36
Continent = "Europe"
Capital = "Budapest"
"Time Zone in Capital" = "Europe/Budapest"
Currency = "Forint"
"Language Codes" = "hu-HU"
Languages = "Hungarian (official) 99.6%, English 16%, German 11.2%, Russian 1.6%, Romanian 1.3%, French 1.2%, other 4.2%"
"Area KM2" = 93_030
"Internet Hosts" = 3_145_000
"Internet Users" = 6_176_000
"Phones (Mobile)" = 11_580_000
"Phones (Landline)" = 2_960_000
GDP = 130_600_000_000
englishShortName = "Hungary"
frenchShortName = "Hongrie (la)"
numeric = 348
japaneseShortName = "ハンガリー"
[IS]
"Country Name" = "Iceland"
ISO2 = "IS"
ISO3 = "ISL"
"Top Level Domain" = "is"
FIPS = "IC"
"ISO Numeric" = 352
GeoNameID = 2_629_691
E164 = 354
"Phone Code" = 354
Continent = "Europe"
Capital = "Reykjavik"
"Time Zone in Capital" = "Atlantic/Reykjavik"
Currency = "Krona"
"Language Codes" = "is,en,de,da,sv,no"
Languages = "Icelandic, English, Nordic languages, German widely spoken"
"Area KM2" = 103_000
"Internet Hosts" = 369_969
"Internet Users" = 301_600
"Phones (Mobile)" = 346_000
"Phones (Landline)" = 189_000
GDP = 14_590_000_000
englishShortName = "Iceland"
frenchShortName = "Islande (l')"
numeric = 352
japaneseShortName = "アイスランド"
[IN]
"Country Name" = "India"
ISO2 = "IN"
ISO3 = "IND"
"Top Level Domain" = "in"
FIPS = "IN"
"ISO Numeric" = 356
GeoNameID = 1_269_750
E164 = 91
"Phone Code" = 91
Continent = "Asia"
Capital = "New Delhi"
"Time Zone in Capital" = "Asia/Kolkata"
Currency = "Rupee"
"Language Codes" = "en-IN,hi,bn,te,mr,ta,ur,gu,kn,ml,or,pa,as,bh,sat,ks,ne,sd,kok,doi,mni,sit,sa,fr,lus,inc"
Languages = "Hindi 41%, Bengali 8.1%, Telugu 7.2%, Marathi 7%, Tamil 5.9%, Urdu 5%, Gujarati 4.5%, Kannada 3.7%, Malayalam 3.2%, Oriya 3.2%, Punjabi 2.8%, Assamese 1.3%, Maithili 1.2%, other 5.9%"
"Area KM2" = 3_287_590
"Internet Hosts" = 6_746_000
"Internet Users" = 61_338_000
"Phones (Mobile)" = 893_862_000
"Phones (Landline)" = 31_080_000
GDP = 1_670_000_000_000
englishShortName = "India"
frenchShortName = "Inde (l')"
numeric = 356
japaneseShortName = "インド"
[ID]
"Country Name" = "Indonesia"
ISO2 = "ID"
ISO3 = "IDN"
"Top Level Domain" = "id"
FIPS = "ID"
"ISO Numeric" = 360
GeoNameID = 1_643_084
E164 = 62
"Phone Code" = 62
Continent = "Asia"
Capital = "Jakarta"
"Time Zone in Capital" = "Asia/Jakarta"
Currency = "Rupiah"
"Language Codes" = "id,en,nl,jv"
Languages = "Bahasa Indonesia (official, modified form of Malay), English, Dutch, local dialects (of which the most widely spoken is Javanese)"
"Area KM2" = 1_919_440
"Internet Hosts" = 1_344_000
"Internet Users" = 20_000_000
"Phones (Mobile)" = 281_960_000
"Phones (Landline)" = 37_983_000
GDP = 867_500_000_000
englishShortName = "Indonesia"
frenchShortName = "Indonésie (l')"
numeric = 360
japaneseShortName = "インドネシア"
[IR]
"Country Name" = "Iran"
ISO2 = "IR"
ISO3 = "IRN"
"Top Level Domain" = "ir"
FIPS = "IR"
"ISO Numeric" = 364
GeoNameID = 130_758
E164 = 98
"Phone Code" = 98
Continent = "Asia"
Capital = "Tehran"
"Time Zone in Capital" = "Asia/Tehran"
Currency = "Rial"
"Language Codes" = "fa-IR,ku"
Languages = "Persian (official) 53%, Azeri Turkic and Turkic dialects 18%, Kurdish 10%, Gilaki and Mazandarani 7%, Luri 6%, Balochi 2%, Arabic 2%, other 2%"
"Area KM2" = 1_648_000
"Internet Hosts" = 197_804
"Internet Users" = 8_214_000
"Phones (Mobile)" = 58_160_000
"Phones (Landline)" = 28_760_000
GDP = 411_900_000_000
englishShortName = "Iran (Islamic Republic of)"
frenchShortName = "Iran (République Islamique d')"
numeric = 364
japaneseShortName = "イラン"
[IQ]
"Country Name" = "Iraq"
ISO2 = "IQ"
ISO3 = "IRQ"
"Top Level Domain" = "iq"
FIPS = "IZ"
"ISO Numeric" = 368
GeoNameID = 99_237
E164 = 964
"Phone Code" = 964
Continent = "Asia"
Capital = "Baghdad"
"Time Zone in Capital" = "Asia/Baghdad"
Currency = "Dinar"
"Language Codes" = "ar-IQ,ku,hy"
Languages = "Arabic (official), Kurdish (official), Turkmen (a Turkish dialect) and Assyrian (Neo-Aramaic) are official in areas where they constitute a majority of the population), Armenian"
"Area KM2" = 437_072
"Internet Hosts" = 26
"Internet Users" = 325_900
"Phones (Mobile)" = 26_760_000
"Phones (Landline)" = 1_870_000
GDP = 221_800_000_000
englishShortName = "Iraq"
frenchShortName = "Iraq (l')"
numeric = 368
japaneseShortName = "イラク"
[IE]
"Country Name" = "Ireland"
ISO2 = "IE"
ISO3 = "IRL"
"Top Level Domain" = "ie"
FIPS = "EI"
"ISO Numeric" = 372
GeoNameID = 2_963_597
E164 = 353
"Phone Code" = 353
Continent = "Europe"
Capital = "Dublin"
"Time Zone in Capital" = "Europe/Dublin"
Currency = "Euro"
"Language Codes" = "en-IE,ga-IE"
Languages = "English (official, the language generally used), Irish (Gaelic or Gaeilge) (official, spoken mainly in areas along the western coast)"
"Area KM2" = 70_280
"Internet Hosts" = 1_387_000
"Internet Users" = 3_042_000
"Phones (Mobile)" = 4_906_000
"Phones (Landline)" = 2_007_000
GDP = 220_900_000_000
englishShortName = "Ireland"
frenchShortName = "Irlande (l')"
numeric = 372
japaneseShortName = "アイルランド"
[IM]
"Country Name" = "Isle of Man"
ISO2 = "IM"
ISO3 = "IMN"
"Top Level Domain" = "im"
FIPS = "IM"
"ISO Numeric" = 833
GeoNameID = 3_042_225
E164 = 44
"Phone Code" = "44-1624"
Continent = "Europe"
Capital = "Douglas, Isle of Man"
"Time Zone in Capital" = "Europe/London"
Currency = "Pound"
"Language Codes" = "en,gv"
Languages = "English, Manx Gaelic (about 2% of the population has some knowledge)"
"Area KM2" = 572
"Internet Hosts" = 895
"Internet Users" = ""
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = 4_076_000_000
englishShortName = "Isle of Man"
frenchShortName = "Île de Man"
numeric = 833
japaneseShortName = "マン島"
[IL]
"Country Name" = "Israel"
ISO2 = "IL"
ISO3 = "ISR"
"Top Level Domain" = "il"
FIPS = "IS"
"ISO Numeric" = 376
GeoNameID = 294_640
E164 = 972
"Phone Code" = 972
Continent = "Asia"
Capital = "Jerusalem"
"Time Zone in Capital" = "Asia/Jerusalem"
Currency = "Shekel"
"Language Codes" = "he,ar-IL,en-IL,"
Languages = "Hebrew (official), Arabic (used officially for Arab minority), English (most commonly used foreign language)"
"Area KM2" = 20_770
"Internet Hosts" = 2_483_000
"Internet Users" = 4_525_000
"Phones (Mobile)" = 9_225_000
"Phones (Landline)" = 3_594_000
GDP = 272_700_000_000
englishShortName = "Israel"
frenchShortName = "Israël"
numeric = 376
japaneseShortName = "イスラエル"
[IT]
"Country Name" = "Italy"
ISO2 = "IT"
ISO3 = "ITA"
"Top Level Domain" = "it"
FIPS = "IT"
"ISO Numeric" = 380
GeoNameID = 3_175_395
E164 = 39
"Phone Code" = 39
Continent = "Europe"
Capital = "Rome"
"Time Zone in Capital" = "Europe/Rome"
Currency = "Euro"
"Language Codes" = "it-IT,de-IT,fr-IT,sc,ca,co,sl"
Languages = "Italian (official), German (parts of Trentino-Alto Adige region are predominantly German-speaking), French (small French-speaking minority in Valle d'Aosta region), Slovene (Slovene-speaking minority in the Trieste-Gorizia area)"
"Area KM2" = 301_230
"Internet Hosts" = 25_662_000
"Internet Users" = 29_235_000
"Phones (Mobile)" = 97_225_000
"Phones (Landline)" = 21_656_000
GDP = 2_068_000_000_000
englishShortName = "Italy"
frenchShortName = "Italie (l')"
numeric = 380
japaneseShortName = "イタリア"
[CI]
"Country Name" = "Ivory Coast"
ISO2 = "CI"
ISO3 = "CIV"
"Top Level Domain" = "ci"
FIPS = "IV"
"ISO Numeric" = 384
GeoNameID = 2_287_781
E164 = 225
"Phone Code" = 225
Continent = "Africa"
Capital = "Yamoussoukro"
"Time Zone in Capital" = "Africa/Abidjan"
Currency = "Franc"
"Language Codes" = "fr-CI"
Languages = "French (official), 60 native dialects of which Dioula is the most widely spoken"
"Area KM2" = 322_460
"Internet Hosts" = 9_115
"Internet Users" = 967_300
"Phones (Mobile)" = 19_827_000
"Phones (Landline)" = 268_000
GDP = 28_280_000_000
englishShortName = "Côte d'Ivoire"
frenchShortName = "Côte d'Ivoire (la)"
numeric = 384
japaneseShortName = "コートジボワール"
[JM]
"Country Name" = "Jamaica"
ISO2 = "JM"
ISO3 = "JAM"
"Top Level Domain" = "jm"
FIPS = "JM"
"ISO Numeric" = 388
GeoNameID = 3_489_940
E164 = 1
"Phone Code" = "1-876"
Continent = "North America"
Capital = "Kingston"
"Time Zone in Capital" = "America/Jamaica"
Currency = "Dollar"
"Language Codes" = "en-JM"
Languages = "English, English patois"
"Area KM2" = 10_991
"Internet Hosts" = 3_906
"Internet Users" = 1_581_000
"Phones (Mobile)" = 2_665_000
"Phones (Landline)" = 265_000
GDP = 14_390_000_000
englishShortName = "Jamaica"
frenchShortName = "Jamaïque (la)"
numeric = 388
japaneseShortName = "ジャマイカ"
[JP]
"Country Name" = "Japan"
ISO2 = "JP"
ISO3 = "JPN"
"Top Level Domain" = "jp"
FIPS = "JA"
"ISO Numeric" = 392
GeoNameID = 1_861_060
E164 = 81
"Phone Code" = 81
Continent = "Asia"
Capital = "Tokyo"
"Time Zone in Capital" = "Asia/Tokyo"
Currency = "Yen"
"Language Codes" = "ja"
Languages = "Japanese"
"Area KM2" = 377_835
"Internet Hosts" = 64_453_000
"Internet Users" = 99_182_000
"Phones (Mobile)" = 138_363_000
"Phones (Landline)" = 64_273_000
GDP = 5_007_000_000_000
englishShortName = "Japan"
frenchShortName = "Japon (le)"
numeric = 392
japaneseShortName = "日本"
[JE]
"Country Name" = "Jersey"
ISO2 = "JE"
ISO3 = "JEY"
"Top Level Domain" = "je"
FIPS = "JE"
"ISO Numeric" = 832
GeoNameID = 3_042_142
E164 = 44
"Phone Code" = "44-1534"
Continent = "Europe"
Capital = "Saint Helier"
"Time Zone in Capital" = "Europe/London"
Currency = "Pound"
"Language Codes" = "en,pt"
Languages = "English 94.5% (official), Portuguese 4.6%, other 0.9% (2001 census)"
"Area KM2" = 116
"Internet Hosts" = 264
"Internet Users" = 29_500
"Phones (Mobile)" = 108_000
"Phones (Landline)" = 73_800
GDP = 5_100_000_000
englishShortName = "Jersey"
frenchShortName = "Jersey"
numeric = 832
japaneseShortName = "ジャージー"
[JO]
"Country Name" = "Jordan"
ISO2 = "JO"
ISO3 = "JOR"
"Top Level Domain" = "jo"
FIPS = "JO"
"ISO Numeric" = 400
GeoNameID = 248_816
E164 = 962
"Phone Code" = 962
Continent = "Asia"
Capital = "Amman"
"Time Zone in Capital" = "Asia/Amman"
Currency = "Dinar"
"Language Codes" = "ar-JO,en"
Languages = "Arabic (official), English (widely understood among upper and middle classes)"
"Area KM2" = 92_300
"Internet Hosts" = 69_473
"Internet Users" = 1_642_000
"Phones (Mobile)" = 8_984_000
"Phones (Landline)" = 435_000
GDP = 34_080_000_000
englishShortName = "Jordan"
frenchShortName = "Jordanie (la)"
numeric = 400
japaneseShortName = "ヨルダン"
[KZ]
"Country Name" = "Kazakhstan"
ISO2 = "KZ"
ISO3 = "KAZ"
"Top Level Domain" = "kz"
FIPS = "KZ"
"ISO Numeric" = 398
GeoNameID = 1_522_867
E164 = 7
"Phone Code" = 7
Continent = "Asia"
Capital = "Astana"
"Time Zone in Capital" = "Asia/Almaty"
Currency = "Tenge"
"Language Codes" = "kk,ru"
Languages = 'Kazakh (official, Qazaq) 64.4%, Russian (official, used in everyday business, designated the "language of interethnic communication") 95% (2001 est.)'
"Area KM2" = 2_717_300
"Internet Hosts" = 67_464
"Internet Users" = 5_299_000
"Phones (Mobile)" = 28_731_000
"Phones (Landline)" = 4_340_000
GDP = 224_900_000_000
englishShortName = "Kazakhstan"
frenchShortName = "Kazakhstan (le)"
numeric = 398
japaneseShortName = "カザフスタン"
[KE]
"Country Name" = "Kenya"
ISO2 = "KE"
ISO3 = "KEN"
"Top Level Domain" = "ke"
FIPS = "KE"
"ISO Numeric" = 404
GeoNameID = 192_950
E164 = 254
"Phone Code" = 254
Continent = "Africa"
Capital = "Nairobi"
"Time Zone in Capital" = "Africa/Nairobi"
Currency = "Shilling"
"Language Codes" = "en-KE,sw-KE"
Languages = "English (official), Kiswahili (official), numerous indigenous languages"
"Area KM2" = 582_650
"Internet Hosts" = 71_018
"Internet Users" = 3_996_000
"Phones (Mobile)" = 30_732_000
"Phones (Landline)" = 251_600
GDP = 45_310_000_000
englishShortName = "Kenya"
frenchShortName = "Kenya (le)"
numeric = 404
japaneseShortName = "ケニア"
[KI]
"Country Name" = "Kiribati"
ISO2 = "KI"
ISO3 = "KIR"
"Top Level Domain" = "ki"
FIPS = "KR"
"ISO Numeric" = 296
GeoNameID = 4_030_945
E164 = 686
"Phone Code" = 686
Continent = "Oceania"
Capital = "Tarawa"
"Time Zone in Capital" = "Pacific/Tarawa"
Currency = "Dollar"
"Language Codes" = "en-KI,gil"
Languages = "I-Kiribati, English (official)"
"Area KM2" = 811
"Internet Hosts" = 327
"Internet Users" = 7_800
"Phones (Mobile)" = 16_000
"Phones (Landline)" = 9_000
GDP = 173_000_000
englishShortName = "Kiribati"
frenchShortName = "Kiribati"
numeric = 296
japaneseShortName = "キリバス"
[XK]
"Country Name" = "Kosovo"
ISO2 = "XK"
ISO3 = "XKX"
"Top Level Domain" = ""
FIPS = "KV"
"ISO Numeric" = 0
GeoNameID = 831_053
E164 = 383
"Phone Code" = 383
Continent = "Europe"
Capital = "Pristina"
"Time Zone in Capital" = "Europe/Belgrade"
Currency = "Euro"
"Language Codes" = "sq,sr"
Languages = "Albanian (official), Serbian (official), Bosnian, Turkish, Roma"
"Area KM2" = 10_887
"Internet Hosts" = ""
"Internet Users" = ""
"Phones (Mobile)" = 562_000
"Phones (Landline)" = 106_300
GDP = 7_150_000_000
[KW]
"Country Name" = "Kuwait"
ISO2 = "KW"
ISO3 = "KWT"
"Top Level Domain" = "kw"
FIPS = "KU"
"ISO Numeric" = 414
GeoNameID = 285_570
E164 = 965
"Phone Code" = 965
Continent = "Asia"
Capital = "Kuwait City"
"Time Zone in Capital" = "Asia/Kuwait"
Currency = "Dinar"
"Language Codes" = "ar-KW,en"
Languages = "Arabic (official), English widely spoken"
"Area KM2" = 17_820
"Internet Hosts" = 2_771
"Internet Users" = 1_100_000
"Phones (Mobile)" = 5_526_000
"Phones (Landline)" = 510_000
GDP = 179_500_000_000
englishShortName = "Kuwait"
frenchShortName = "Koweït (le)"
numeric = 414
japaneseShortName = "クウェート"
[KG]
"Country Name" = "Kyrgyzstan"
ISO2 = "KG"
ISO3 = "KGZ"
"Top Level Domain" = "kg"
FIPS = "KG"
"ISO Numeric" = 417
GeoNameID = 1_527_747
E164 = 996
"Phone Code" = 996
Continent = "Asia"
Capital = "Bishkek"
"Time Zone in Capital" = "Asia/Bishkek"
Currency = "Som"
"Language Codes" = "ky,uz,ru"
Languages = "Kyrgyz (official) 64.7%, Uzbek 13.6%, Russian (official) 12.5%, Dungun 1%, other 8.2% (1999 census)"
"Area KM2" = 198_500
"Internet Hosts" = 115_573
"Internet Users" = 2_195_000
"Phones (Mobile)" = 6_800_000
"Phones (Landline)" = 489_000
GDP = 7_234_000_000
englishShortName = "Kyrgyzstan"
frenchShortName = "Kirghizistan (le)"
numeric = 417
japaneseShortName = "キルギス"
[LA]
"Country Name" = "Laos"
ISO2 = "LA"
ISO3 = "LAO"
"Top Level Domain" = "la"
FIPS = "LA"
"ISO Numeric" = 418
GeoNameID = 1_655_842
E164 = 856
"Phone Code" = 856
Continent = "Asia"
Capital = "Vientiane"
"Time Zone in Capital" = "Asia/Vientiane"
Currency = "Kip"
"Language Codes" = "lo,fr,en"
Languages = "Lao (official), French, English, various ethnic languages"
"Area KM2" = 236_800
"Internet Hosts" = 1_532
"Internet Users" = 300_000
"Phones (Mobile)" = 6_492_000
"Phones (Landline)" = 112_000
GDP = 10_100_000_000
englishShortName = "Lao People's Democratic Republic (the)"
frenchShortName = "Lao (la République démocratique populaire)"
numeric = 418
japaneseShortName = "ラオス"
[LV]
"Country Name" = "Latvia"
ISO2 = "LV"
ISO3 = "LVA"
"Top Level Domain" = "lv"
FIPS = "LG"
"ISO Numeric" = 428
GeoNameID = 458_258
E164 = 371
"Phone Code" = 371
Continent = "Europe"
Capital = "Riga"
"Time Zone in Capital" = "Europe/Riga"
Currency = "Euro"
"Language Codes" = "lv,ru,lt"
Languages = "Latvian (official) 56.3%, Russian 33.8%, other 0.6% (includes Polish, Ukrainian, and Belarusian), unspecified 9.4% (2011 est.)"
"Area KM2" = 64_589
"Internet Hosts" = 359_604
"Internet Users" = 1_504_000
"Phones (Mobile)" = 2_310_000
"Phones (Landline)" = 501_000
GDP = 30_380_000_000
englishShortName = "Latvia"
frenchShortName = "Lettonie (la)"
numeric = 428
japaneseShortName = "ラトビア"
[LB]
"Country Name" = "Lebanon"
ISO2 = "LB"
ISO3 = "LBN"
"Top Level Domain" = "lb"
FIPS = "LE"
"ISO Numeric" = 422
GeoNameID = 272_103
E164 = 961
"Phone Code" = 961
Continent = "Asia"
Capital = "Beirut"
"Time Zone in Capital" = "Asia/Beirut"
Currency = "Pound"
"Language Codes" = "ar-LB,fr-LB,en,hy"
Languages = "Arabic (official), French, English, Armenian"
"Area KM2" = 10_400
"Internet Hosts" = 64_926
"Internet Users" = 1_000_000
"Phones (Mobile)" = 4_000_000
"Phones (Landline)" = 878_000
GDP = 43_490_000_000
englishShortName = "Lebanon"
frenchShortName = "Liban (le)"
numeric = 422
japaneseShortName = "レバノン"
[LS]
"Country Name" = "Lesotho"
ISO2 = "LS"
ISO3 = "LSO"
"Top Level Domain" = "ls"
FIPS = "LT"
"ISO Numeric" = 426
GeoNameID = 932_692
E164 = 266
"Phone Code" = 266
Continent = "Africa"
Capital = "Maseru"
"Time Zone in Capital" = "Africa/Johannesburg"
Currency = "Loti"
"Language Codes" = "en-LS,st,zu,xh"
Languages = "Sesotho (official) (southern Sotho), English (official), Zulu, Xhosa"
"Area KM2" = 30_355
"Internet Hosts" = 11_030
"Internet Users" = 76_800
"Phones (Mobile)" = 1_312_000
"Phones (Landline)" = 43_100
GDP = 2_457_000_000
englishShortName = "Lesotho"
frenchShortName = "Lesotho (le)"
numeric = 426
japaneseShortName = "レソト"
[LR]
"Country Name" = "Liberia"
ISO2 = "LR"
ISO3 = "LBR"
"Top Level Domain" = "lr"
FIPS = "LI"
"ISO Numeric" = 430
GeoNameID = 2_275_384
E164 = 231
"Phone Code" = 231
Continent = "Africa"
Capital = "Monrovia"
"Time Zone in Capital" = "Africa/Monrovia"
Currency = "Dollar"
"Language Codes" = "en-LR"
Languages = "English 20% (official), some 20 ethnic group languages few of which can be written or used in correspondence"
"Area KM2" = 111_370
"Internet Hosts" = 7
"Internet Users" = 20_000
"Phones (Mobile)" = 2_394_000
"Phones (Landline)" = 3_200
GDP = 1_977_000_000
englishShortName = "Liberia"
frenchShortName = "Libéria (le)"
numeric = 430
japaneseShortName = "リベリア"
[LY]
"Country Name" = "Libya"
ISO2 = "LY"
ISO3 = "LBY"
"Top Level Domain" = "ly"
FIPS = "LY"
"ISO Numeric" = 434
GeoNameID = 2_215_636
E164 = 218
"Phone Code" = 218
Continent = "Africa"
Capital = "Tripolis"
"Time Zone in Capital" = "Africa/Tripoli"
Currency = "Dinar"
"Language Codes" = "ar-LY,it,en"
Languages = "Arabic (official), Italian, English (all widely understood in the major cities); Berber (Nafusi, Ghadamis, Suknah, Awjilah, Tamasheq)"
"Area KM2" = 1_759_540
"Internet Hosts" = 17_926
"Internet Users" = 353_900
"Phones (Mobile)" = 9_590_000
"Phones (Landline)" = 814_000
GDP = 70_920_000_000
englishShortName = "Libya"
frenchShortName = "Libye (la)"
numeric = 434
japaneseShortName = "リビア国"
[LI]
"Country Name" = "Liechtenstein"
ISO2 = "LI"
ISO3 = "LIE"
"Top Level Domain" = "li"
FIPS = "LS"
"ISO Numeric" = 438
GeoNameID = 3_042_058
E164 = 423
"Phone Code" = 423
Continent = "Europe"
Capital = "Vaduz"
"Time Zone in Capital" = "Europe/Zurich"
Currency = "Franc"
"Language Codes" = "de-LI"
Languages = "German 94.5% (official) (Alemannic is the main dialect), Italian 1.1%, other 4.3% (2010 est.)"
"Area KM2" = 160
"Internet Hosts" = 14_278
"Internet Users" = 23_000
"Phones (Mobile)" = 38_000
"Phones (Landline)" = 20_000
GDP = 5_113_000_000
englishShortName = "Liechtenstein"
frenchShortName = "Liechtenstein (le)"
numeric = 438
japaneseShortName = "リヒテンシュタイン"
[LT]
"Country Name" = "Lithuania"
ISO2 = "LT"
ISO3 = "LTU"
"Top Level Domain" = "lt"
FIPS = "LH"
"ISO Numeric" = 440
GeoNameID = 597_427
E164 = 370
"Phone Code" = 370
Continent = "Europe"
Capital = "Vilnius"
"Time Zone in Capital" = "Europe/Vilnius"
Currency = "Euro"
"Language Codes" = "lt,ru,pl"
Languages = "Lithuanian (official) 82%, Russian 8%, Polish 5.6%, other 0.9%, unspecified 3.5% (2011 est.)"
"Area KM2" = 65_200
"Internet Hosts" = 1_205_000
"Internet Users" = 1_964_000
"Phones (Mobile)" = 5_000_000
"Phones (Landline)" = 667_300
GDP = 46_710_000_000
englishShortName = "Lithuania"
frenchShortName = "Lituanie (la)"
numeric = 440
japaneseShortName = "リトアニア"
[LU]
"Country Name" = "Luxembourg"
ISO2 = "LU"
ISO3 = "LUX"
"Top Level Domain" = "lu"
FIPS = "LU"
"ISO Numeric" = 442
GeoNameID = 2_960_313
E164 = 352
"Phone Code" = 352
Continent = "Europe"
Capital = "Luxembourg"
"Time Zone in Capital" = "Europe/Luxembourg"
Currency = "Euro"
"Language Codes" = "lb,de-LU,fr-LU"
Languages = "Luxembourgish (official administrative language and national language (spoken vernacular)), French (official administrative language), German (official administrative language)"
"Area KM2" = 2_586
"Internet Hosts" = 250_900
"Internet Users" = 424_500
"Phones (Mobile)" = 761_300
"Phones (Landline)" = 266_700
GDP = 60_540_000_000
englishShortName = "Luxembourg"
frenchShortName = "Luxembourg (le)"
numeric = 442
japaneseShortName = "ルクセンブルク"
[MO]
"Country Name" = "Macau"
ISO2 = "MO"
ISO3 = "MAC"
"Top Level Domain" = "mo"
FIPS = "MC"
"ISO Numeric" = 446
GeoNameID = 1_821_275
E164 = 853
"Phone Code" = 853
Continent = "Asia"
Capital = "Macao"
"Time Zone in Capital" = "Asia/Macau"
Currency = "Pataca"
"Language Codes" = "zh,zh-MO,pt"
Languages = "Cantonese 83.3%, Mandarin 5%, Hokkien 3.7%, English 2.3%, other Chinese dialects 2%, Tagalog 1.7%, Portuguese 0.7%, other 1.3%"
"Area KM2" = 254
"Internet Hosts" = 327
"Internet Users" = 270_200
"Phones (Mobile)" = 1_613_000
"Phones (Landline)" = 162_500
GDP = 51_680_000_000
englishShortName = "Macao"
frenchShortName = "Macao"
numeric = 446
japaneseShortName = "マカオ"
[MK]
"Country Name" = "Macedonia"
ISO2 = "MK"
ISO3 = "MKD"
"Top Level Domain" = "mk"
FIPS = "MK"
"ISO Numeric" = 807
GeoNameID = 718_075
E164 = 389
"Phone Code" = 389
Continent = "Europe"
Capital = "Skopje"
"Time Zone in Capital" = "Europe/Belgrade"
Currency = "Denar"
"Language Codes" = "mk,sq,tr,rmm,sr"
Languages = "Macedonian (official) 66.5%, Albanian (official) 25.1%, Turkish 3.5%, Roma 1.9%, Serbian 1.2%, other 1.8% (2002 census)"
"Area KM2" = 25_333
"Internet Hosts" = 62_826
"Internet Users" = 1_057_000
"Phones (Mobile)" = 2_235_000
"Phones (Landline)" = 407_900
GDP = 10_650_000_000
englishShortName = "North Macedonia"
frenchShortName = "Macédoine du Nord (la)"
numeric = 807
japaneseShortName = "マケドニア"
[MG]
"Country Name" = "Madagascar"
ISO2 = "MG"
ISO3 = "MDG"
"Top Level Domain" = "mg"
FIPS = "MA"
"ISO Numeric" = 450
GeoNameID = 1_062_947
E164 = 261
"Phone Code" = 261
Continent = "Africa"
Capital = "Antananarivo"
"Time Zone in Capital" = "Indian/Antananarivo"
Currency = "Ariary"
"Language Codes" = "fr-MG,mg"
Languages = "French (official), Malagasy (official), English"
"Area KM2" = 587_040
"Internet Hosts" = 38_392
"Internet Users" = 319_900
"Phones (Mobile)" = 8_564_000
"Phones (Landline)" = 143_700
GDP = 10_530_000_000
englishShortName = "Madagascar"
frenchShortName = "Madagascar"
numeric = 450
japaneseShortName = "マダガスカル"
[MW]
"Country Name" = "Malawi"
ISO2 = "MW"
ISO3 = "MWI"
"Top Level Domain" = "mw"
FIPS = "MI"
"ISO Numeric" = 454
GeoNameID = 927_384
E164 = 265
"Phone Code" = 265
Continent = "Africa"
Capital = "Lilongwe"
"Time Zone in Capital" = "Africa/Maputo"
Currency = "Kwacha"
"Language Codes" = "ny,yao,tum,swk"
Languages = "English (official), Chichewa (common), Chinyanja, Chiyao, Chitumbuka, Chilomwe, Chinkhonde, Chingoni, Chisena, Chitonga, Chinyakyusa, Chilambya"
"Area KM2" = 118_480
"Internet Hosts" = 1_099
"Internet Users" = 716_400
"Phones (Mobile)" = 4_420_000
"Phones (Landline)" = 227_300
GDP = 3_683_000_000
englishShortName = "Malawi"
frenchShortName = "Malawi (le)"
numeric = 454
japaneseShortName = "マラウイ"
[MY]
"Country Name" = "Malaysia"
ISO2 = "MY"
ISO3 = "MYS"
"Top Level Domain" = "my"
FIPS = "MY"
"ISO Numeric" = 458
GeoNameID = 1_733_045
E164 = 60
"Phone Code" = 60
Continent = "Asia"
Capital = "Kuala Lumpur"
"Time Zone in Capital" = "Asia/Kuala_Lumpur"
Currency = "Ringgit"
"Language Codes" = "ms-MY,en,zh,ta,te,ml,pa,th"
Languages = "Bahasa Malaysia (official), English, Chinese (Cantonese, Mandarin, Hokkien, Hakka, Hainan, Foochow), Tamil, Telugu, Malayalam, Panjabi, Thai"
"Area KM2" = 329_750
"Internet Hosts" = 422_470
"Internet Users" = 15_355_000
"Phones (Mobile)" = 41_325_000
"Phones (Landline)" = 4_589_000
GDP = 312_400_000_000
englishShortName = "Malaysia"
frenchShortName = "Malaisie (la)"
numeric = 458
japaneseShortName = "マレーシア"
[MV]
"Country Name" = "Maldives"
ISO2 = "MV"
ISO3 = "MDV"
"Top Level Domain" = "mv"
FIPS = "MV"
"ISO Numeric" = 462
GeoNameID = 1_282_028
E164 = 960
"Phone Code" = 960
Continent = "Asia"
Capital = "Male"
"Time Zone in Capital" = "Indian/Maldives"
Currency = "Rufiyaa"
"Language Codes" = "dv,en"
Languages = "Dhivehi (official, dialect of Sinhala, script derived from Arabic), English (spoken by most government officials)"
"Area KM2" = 300
"Internet Hosts" = 3_296
"Internet Users" = 86_400
"Phones (Mobile)" = 560_000
"Phones (Landline)" = 23_140
GDP = 2_270_000_000
englishShortName = "Maldives"
frenchShortName = "Maldives (les)"
numeric = 462
japaneseShortName = "モルディブ"
[ML]
"Country Name" = "Mali"
ISO2 = "ML"
ISO3 = "MLI"
"Top Level Domain" = "ml"
FIPS = "ML"
"ISO Numeric" = 466
GeoNameID = 2_453_866
E164 = 223
"Phone Code" = 223
Continent = "Africa"
Capital = "Bamako"
"Time Zone in Capital" = "Africa/Abidjan"
Currency = "Franc"
"Language Codes" = "fr-ML,bm"
Languages = "French (official), Bambara 46.3%, Peul/foulfoulbe 9.4%, Dogon 7.2%, Maraka/soninke 6.4%, Malinke 5.6%, Sonrhai/djerma 5.6%, Minianka 4.3%, Tamacheq 3.5%, Senoufo 2.6%, unspecified 0.6%, other 8.5%"
"Area KM2" = 1_240_000
"Internet Hosts" = 437
"Internet Users" = 249_800
"Phones (Mobile)" = 14_613_000
"Phones (Landline)" = 112_000
GDP = 11_370_000_000
englishShortName = "Mali"
frenchShortName = "Mali (le)"
numeric = 466
japaneseShortName = "マリ"
[MT]
"Country Name" = "Malta"
ISO2 = "MT"
ISO3 = "MLT"
"Top Level Domain" = "mt"
FIPS = "MT"
"ISO Numeric" = 470
GeoNameID = 2_562_770
E164 = 356
"Phone Code" = 356
Continent = "Europe"
Capital = "Valletta"
"Time Zone in Capital" = "Europe/Malta"
Currency = "Euro"
"Language Codes" = "mt,en-MT"
Languages = "Maltese (official) 90.1%, English (official) 6%, multilingual 3%, other 0.9% (2005 est.)"
"Area KM2" = 316
"Internet Hosts" = 14_754
"Internet Users" = 240_600
"Phones (Mobile)" = 539_500
"Phones (Landline)" = 229_700
GDP = 9_541_000_000
englishShortName = "Malta"
frenchShortName = "Malte"
numeric = 470
japaneseShortName = "マルタ"
[MH]
"Country Name" = "Marshall Islands"
ISO2 = "MH"
ISO3 = "MHL"
"Top Level Domain" = "mh"
FIPS = "RM"
"ISO Numeric" = 584
GeoNameID = 2_080_185
E164 = 692
"Phone Code" = 692
Continent = "Oceania"
Capital = "Majuro"
"Time Zone in Capital" = "Pacific/Majuro"
Currency = "Dollar"
"Language Codes" = "mh,en-MH"
Languages = "Marshallese (official) 98.2%, other languages 1.8% (1999 census)"
"Area KM2" = 181
"Internet Hosts" = 3
"Internet Users" = 2_200
"Phones (Mobile)" = 3_800
"Phones (Landline)" = 4_400
GDP = 193_000_000
englishShortName = "Marshall Islands (the)"
frenchShortName = "Marshall (les Îles)"
numeric = 584
japaneseShortName = "マーシャル諸島"
[MR]
"Country Name" = "Mauritania"
ISO2 = "MR"
ISO3 = "MRT"
"Top Level Domain" = "mr"
FIPS = "MR"
"ISO Numeric" = 478
GeoNameID = 2_378_080
E164 = 222
"Phone Code" = 222
Continent = "Africa"
Capital = "Nouakchott"
"Time Zone in Capital" = "Africa/Abidjan"
Currency = "Ouguiya"
"Language Codes" = "ar-MR,fuc,snk,fr,mey,wo"
Languages = "Arabic (official and national), Pulaar, Soninke, Wolof (all national languages), French, Hassaniya (a variety of Arabic)"
"Area KM2" = 1_030_700
"Internet Hosts" = 22
"Internet Users" = 75_000
"Phones (Mobile)" = 4_024_000
"Phones (Landline)" = 65_100
GDP = 4_183_000_000
englishShortName = "Mauritania"
frenchShortName = "Mauritanie (la)"
numeric = 478
japaneseShortName = "モーリタニア"
[MU]
"Country Name" = "Mauritius"
ISO2 = "MU"
ISO3 = "MUS"
"Top Level Domain" = "mu"
FIPS = "MP"
"ISO Numeric" = 480
GeoNameID = 934_292
E164 = 230
"Phone Code" = 230
Continent = "Africa"
Capital = "Port Louis"
"Time Zone in Capital" = "Indian/Mauritius"
Currency = "Rupee"
"Language Codes" = "en-MU,bho,fr"
Languages = "Creole 86.5%, Bhojpuri 5.3%, French 4.1%, two languages 1.4%, other 2.6% (includes English, the official language, which is spoken by less than 1% of the population), unspecified 0.1% (2011 est.)"
"Area KM2" = 2_040
"Internet Hosts" = 51_139
"Internet Users" = 290_000
"Phones (Mobile)" = 1_485_000
"Phones (Landline)" = 349_100
GDP = 11_900_000_000
englishShortName = "Mauritius"
frenchShortName = "Maurice"
numeric = 480
japaneseShortName = "モーリシャス"
[YT]
"Country Name" = "Mayotte"
ISO2 = "YT"
ISO3 = "MYT"
"Top Level Domain" = "yt"
FIPS = "MF"
"ISO Numeric" = 175
GeoNameID = 1_024_031
E164 = 262
"Phone Code" = 262
Continent = "Africa"
Capital = "Mamoudzou"
"Time Zone in Capital" = "Indian/Mayotte"
Currency = "Euro"
"Language Codes" = "fr-YT"
Languages = "French"
"Area KM2" = 374
"Internet Hosts" = ""
"Internet Users" = ""
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = ""
englishShortName = "Mayotte"
frenchShortName = "Mayotte"
numeric = 175
japaneseShortName = "マヨット"
[MX]
"Country Name" = "Mexico"
ISO2 = "MX"
ISO3 = "MEX"
"Top Level Domain" = "mx"
FIPS = "MX"
"ISO Numeric" = 484
GeoNameID = 3_996_063
E164 = 52
"Phone Code" = 52
Continent = "North America"
Capital = "Mexico City"
"Time Zone in Capital" = "America/Mexico_City"
Currency = "Peso"
"Language Codes" = "es-MX"
Languages = "Spanish only 92.7%, Spanish and indigenous languages 5.7%, indigenous only 0.8%, unspecified 0.8%"
"Area KM2" = 1_972_550
"Internet Hosts" = 16_233_000
"Internet Users" = 31_020_000
"Phones (Mobile)" = 100_786_000
"Phones (Landline)" = 20_220_000
GDP = 1_327_000_000_000
englishShortName = "Mexico"
frenchShortName = "Mexique (le)"
numeric = 484
japaneseShortName = "メキシコ"
[FM]
"Country Name" = "Micronesia"
ISO2 = "FM"
ISO3 = "FSM"
"Top Level Domain" = "fm"
FIPS = "FM"
"ISO Numeric" = 583
GeoNameID = 2_081_918
E164 = 691
"Phone Code" = 691
Continent = "Oceania"
Capital = "Palikir"
"Time Zone in Capital" = "Pacific/Pohnpei"
Currency = "Dollar"
"Language Codes" = "en-FM,chk,pon,yap,kos,uli,woe,nkr,kpg"
Languages = "English (official and common language), Chuukese, Kosrean, Pohnpeian, Yapese, Ulithian, Woleaian, Nukuoro, Kapingamarangi"
"Area KM2" = 702
"Internet Hosts" = 4_668
"Internet Users" = 17_000
"Phones (Mobile)" = 27_600
"Phones (Landline)" = 8_400
GDP = 339_000_000
englishShortName = "Micronesia (Federated States of)"
frenchShortName = "Micronésie (États fédérés de)"
numeric = 583
japaneseShortName = "ミクロネシア連邦"
[MD]
"Country Name" = "Moldova"
ISO2 = "MD"
ISO3 = "MDA"
"Top Level Domain" = "md"
FIPS = "MD"
"ISO Numeric" = 498
GeoNameID = 617_790
E164 = 373
"Phone Code" = 373
Continent = "Europe"
Capital = "Chisinau"
"Time Zone in Capital" = "Europe/Chisinau"
Currency = "Leu"
"Language Codes" = "ro,ru,gag,tr"
Languages = "Moldovan 58.8% (official; virtually the same as the Romanian language), Romanian 16.4%, Russian 16%, Ukrainian 3.8%, Gagauz 3.1% (a Turkish language), Bulgarian 1.1%, other 0.3%, unspecified 0.4%"
"Area KM2" = 33_843
"Internet Hosts" = 711_564
"Internet Users" = 1_333_000
"Phones (Mobile)" = 4_080_000
"Phones (Landline)" = 1_206_000
GDP = 7_932_000_000
englishShortName = "Moldova (the Republic of)"
frenchShortName = "Moldova (la République de)"
numeric = 498
japaneseShortName = "モルドバ共和国"
[MC]
"Country Name" = "Monaco"
ISO2 = "MC"
ISO3 = "MCO"
"Top Level Domain" = "mc"
FIPS = "MN"
"ISO Numeric" = 492
GeoNameID = 2_993_457
E164 = 377
"Phone Code" = 377
Continent = "Europe"
Capital = "Monaco"
"Time Zone in Capital" = "Europe/Monaco"
Currency = "Euro"
"Language Codes" = "fr-MC,en,it"
Languages = "French (official), English, Italian, Monegasque"
"Area KM2" = 2
"Internet Hosts" = 26_009
"Internet Users" = 23_000
"Phones (Mobile)" = 33_200
"Phones (Landline)" = 44_500
GDP = 5_748_000_000
englishShortName = "Monaco"
frenchShortName = "Monaco"
numeric = 492
japaneseShortName = "モナコ"
[MN]
"Country Name" = "Mongolia"
ISO2 = "MN"
ISO3 = "MNG"
"Top Level Domain" = "mn"
FIPS = "MG"
"ISO Numeric" = 496
GeoNameID = 2_029_969
E164 = 976
"Phone Code" = 976
Continent = "Asia"
Capital = "Ulan Bator"
"Time Zone in Capital" = "Asia/Ulaanbaatar"
Currency = "Tugrik"
"Language Codes" = "mn,ru"
Languages = "Khalkha Mongol 90% (official), Turkic, Russian (1999)"
"Area KM2" = 1_565_000
"Internet Hosts" = 20_084
"Internet Users" = 330_000
"Phones (Mobile)" = 3_375_000
"Phones (Landline)" = 176_700
GDP = 11_140_000_000
englishShortName = "Mongolia"
frenchShortName = "Mongolie (la)"
numeric = 496
japaneseShortName = "モンゴル"
[ME]
"Country Name" = "Montenegro"
ISO2 = "ME"
ISO3 = "MNE"
"Top Level Domain" = "me"
FIPS = "MJ"
"ISO Numeric" = 499
GeoNameID = 3_194_884
E164 = 382
"Phone Code" = 382
Continent = "Europe"
Capital = "Podgorica"
"Time Zone in Capital" = "Europe/Belgrade"
Currency = "Euro"
"Language Codes" = "sr,hu,bs,sq,hr,rom"
Languages = "Serbian 42.9%, Montenegrin (official) 37%, Bosnian 5.3%, Albanian 5.3%, Serbo-Croat 2%, other 3.5%, unspecified 4% (2011 est.)"
"Area KM2" = 14_026
"Internet Hosts" = 10_088
"Internet Users" = 280_000
"Phones (Mobile)" = 1_126_000
"Phones (Landline)" = 163_000
GDP = 4_518_000_000
englishShortName = "Montenegro"
frenchShortName = "Monténégro (le)"
numeric = 499
japaneseShortName = "モンテネグロ"
[MS]
"Country Name" = "Montserrat"
ISO2 = "MS"
ISO3 = "MSR"
"Top Level Domain" = "ms"
FIPS = "MH"
"ISO Numeric" = 500
GeoNameID = 3_578_097
E164 = 1
"Phone Code" = "1-664"
Continent = "North America"
Capital = "Plymouth"
"Time Zone in Capital" = "America/Port_of_Spain"
Currency = "Dollar"
"Language Codes" = "en-MS"
Languages = "English"
"Area KM2" = 102
"Internet Hosts" = 2_431
"Internet Users" = 1_200
"Phones (Mobile)" = 4_000
"Phones (Landline)" = 3_000
GDP = ""
englishShortName = "Montserrat"
frenchShortName = "Montserrat"
numeric = 500
japaneseShortName = "モントセラト"
[MA]
"Country Name" = "Morocco"
ISO2 = "MA"
ISO3 = "MAR"
"Top Level Domain" = "ma"
FIPS = "MO"
"ISO Numeric" = 504
GeoNameID = 2_542_007
E164 = 212
"Phone Code" = 212
Continent = "Africa"
Capital = "Rabat"
"Time Zone in Capital" = "Africa/Casablanca"
Currency = "Dirham"
"Language Codes" = "ar-MA,fr"
Languages = "Arabic (official), Berber languages (Tamazight (official), Tachelhit, Tarifit), French (often the language of business, government, and diplomacy)"
"Area KM2" = 446_550
"Internet Hosts" = 277_338
"Internet Users" = 13_213_000
"Phones (Mobile)" = 39_016_000
"Phones (Landline)" = 3_280_000
GDP = 104_800_000_000
englishShortName = "Morocco"
frenchShortName = "Maroc (le)"
numeric = 504
japaneseShortName = "モロッコ"
[MZ]
"Country Name" = "Mozambique"
ISO2 = "MZ"
ISO3 = "MOZ"
"Top Level Domain" = "mz"
FIPS = "MZ"
"ISO Numeric" = 508
GeoNameID = 1_036_973
E164 = 258
"Phone Code" = 258
Continent = "Africa"
Capital = "Maputo"
"Time Zone in Capital" = "Africa/Maputo"
Currency = "Metical"
"Language Codes" = "pt-MZ,vmw"
Languages = "Emakhuwa 25.3%, Portuguese (official) 10.7%, Xichangana 10.3%, Cisena 7.5%, Elomwe 7%, Echuwabo 5.1%, other Mozambican languages 30.1%, other 4% (1997 census)"
"Area KM2" = 801_590
"Internet Hosts" = 89_737
"Internet Users" = 613_600
"Phones (Mobile)" = 8_108_000
"Phones (Landline)" = 88_100
GDP = 14_670_000_000
englishShortName = "Mozambique"
frenchShortName = "Mozambique (le)"
numeric = 508
japaneseShortName = "モザンビーク"
[MM]
"Country Name" = "Myanmar"
ISO2 = "MM"
ISO3 = "MMR"
"Top Level Domain" = "mm"
FIPS = "BM"
"ISO Numeric" = 104
GeoNameID = 1_327_865
E164 = 95
"Phone Code" = 95
Continent = "Asia"
Capital = "Nay Pyi Taw"
"Time Zone in Capital" = "Asia/Rangoon"
Currency = "Kyat"
"Language Codes" = "my"
Languages = "Burmese (official)"
"Area KM2" = 678_500
"Internet Hosts" = 1_055
"Internet Users" = 110_000
"Phones (Mobile)" = 5_440_000
"Phones (Landline)" = 556_000
GDP = 59_430_000_000
englishShortName = "Myanmar"
frenchShortName = "Myanmar (le)"
numeric = 104
japaneseShortName = "ミャンマー"
[NA]
"Country Name" = "Namibia"
ISO2 = "NA"
ISO3 = "NAM"
"Top Level Domain" = "na"
FIPS = "WA"
"ISO Numeric" = 516
GeoNameID = 3_355_338
E164 = 264
"Phone Code" = 264
Continent = "Africa"
Capital = "Windhoek"
"Time Zone in Capital" = "Africa/Windhoek"
Currency = "Dollar"
"Language Codes" = "en-NA,af,de,hz,naq"
Languages = "Oshiwambo languages 48.9%, Nama/Damara 11.3%, Afrikaans 10.4% (common language of most of the population and about 60% of the white population), Otjiherero languages 8.6%, Kavango languages 8.5%, Caprivi languages 4.8%, English (official) 3.4%, other African languages 2.3%, other 1.7%"
"Area KM2" = 825_418
"Internet Hosts" = 78_280
"Internet Users" = 127_500
"Phones (Mobile)" = 2_435_000
"Phones (Landline)" = 171_000
GDP = 12_300_000_000
englishShortName = "Namibia"
frenchShortName = "Namibie (la)"
numeric = 516
japaneseShortName = "ナミビア"
[NR]
"Country Name" = "Nauru"
ISO2 = "NR"
ISO3 = "NRU"
"Top Level Domain" = "nr"
FIPS = "NR"
"ISO Numeric" = 520
GeoNameID = 2_110_425
E164 = 674
"Phone Code" = 674
Continent = "Oceania"
Capital = "Yaren"
"Time Zone in Capital" = "Pacific/Nauru"
Currency = "Dollar"
"Language Codes" = "na,en-NR"
Languages = "Nauruan 93% (official, a distinct Pacific Island language), English 2% (widely understood, spoken, and used for most government and commercial purposes), other 5% (includes I-Kiribati 2% and Chinese 2%)"
"Area KM2" = 21
"Internet Hosts" = 8_162
"Internet Users" = ""
"Phones (Mobile)" = 6_800
"Phones (Landline)" = 1_900
GDP = ""
englishShortName = "Nauru"
frenchShortName = "Nauru"
numeric = 520
japaneseShortName = "ナウル"
[NP]
"Country Name" = "Nepal"
ISO2 = "NP"
ISO3 = "NPL"
"Top Level Domain" = "np"
FIPS = "NP"
"ISO Numeric" = 524
GeoNameID = 1_282_988
E164 = 977
"Phone Code" = 977
Continent = "Asia"
Capital = "Kathmandu"
"Time Zone in Capital" = "Asia/Kathmandu"
Currency = "Rupee"
"Language Codes" = "ne,en"
Languages = "Nepali (official) 44.6%, Maithali 11.7%, Bhojpuri 6%, Tharu 5.8%, Tamang 5.1%, Newar 3.2%, Magar 3%, Bajjika 3%, Urdu 2.6%, Avadhi 1.9%, Limbu 1.3%, Gurung 1.2%, other 10.4%, unspecified 0.2%"
"Area KM2" = 140_800
"Internet Hosts" = 41_256
"Internet Users" = 577_800
"Phones (Mobile)" = 18_138_000
"Phones (Landline)" = 834_000
GDP = 19_340_000_000
englishShortName = "Nepal"
frenchShortName = "Népal (le)"
numeric = 524
japaneseShortName = "ネパール"
[NL]
"Country Name" = "Netherlands"
ISO2 = "NL"
ISO3 = "NLD"
"Top Level Domain" = "nl"
FIPS = "NL"
"ISO Numeric" = 528
GeoNameID = 2_750_405
E164 = 31
"Phone Code" = 31
Continent = "Europe"
Capital = "Amsterdam"
"Time Zone in Capital" = "Europe/Amsterdam"
Currency = "Euro"
"Language Codes" = "nl-NL,fy-NL"
Languages = "Dutch (official)"
"Area KM2" = 41_526
"Internet Hosts" = 13_699_000
"Internet Users" = 14_872_000
"Phones (Mobile)" = 19_643_000
"Phones (Landline)" = 7_086_000
GDP = 722_300_000_000
englishShortName = "Netherlands (the)"
frenchShortName = "Pays-Bas (les)"
numeric = 528
japaneseShortName = "オランダ王国"
[AN]
"Country Name" = "Netherlands Antilles"
ISO2 = "AN"
ISO3 = "ANT"
"Top Level Domain" = "an"
FIPS = "NT"
"ISO Numeric" = 530
GeoNameID = ""
E164 = 599
"Phone Code" = 599
Continent = "North America"
Capital = "Willemstad"
"Time Zone in Capital" = "America/Curacao"
Currency = "Guilder"
"Language Codes" = "nl-AN,en,es"
Languages = "Dutch, English, Spanish"
"Area KM2" = 960
"Internet Hosts" = ""
"Internet Users" = ""
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = ""
japaneseShortName = "オランダ領アンティル"
[NC]
"Country Name" = "New Caledonia"
ISO2 = "NC"
ISO3 = "NCL"
"Top Level Domain" = "nc"
FIPS = "NC"
"ISO Numeric" = 540
GeoNameID = 2_139_685
E164 = 687
"Phone Code" = 687
Continent = "Oceania"
Capital = "Noumea"
"Time Zone in Capital" = "Pacific/Noumea"
Currency = "Franc"
"Language Codes" = "fr-NC"
Languages = "French (official), 33 Melanesian-Polynesian dialects"
"Area KM2" = 19_060
"Internet Hosts" = 34_231
"Internet Users" = 85_000
"Phones (Mobile)" = 231_000
"Phones (Landline)" = 80_000
GDP = 9_280_000_000
englishShortName = "New Caledonia"
frenchShortName = "Nouvelle-Calédonie (la)"
numeric = 540
japaneseShortName = "ニューカレドニア"
[NZ]
"Country Name" = "New Zealand"
ISO2 = "NZ"
ISO3 = "NZL"
"Top Level Domain" = "nz"
FIPS = "NZ"
"ISO Numeric" = 554
GeoNameID = 2_186_224
E164 = 64
"Phone Code" = 64
Continent = "Oceania"
Capital = "Wellington"
"Time Zone in Capital" = "Pacific/Auckland"
Currency = "Dollar"
"Language Codes" = "en-NZ,mi"
Languages = "English (de facto official) 89.8%, Maori (de jure official) 3.5%, Samoan 2%, Hindi 1.6%, French 1.2%, Northern Chinese 1.2%, Yue 1%, Other or not stated 20.5%, New Zealand Sign Language (de jure official)"
"Area KM2" = 268_680
"Internet Hosts" = 3_026_000
"Internet Users" = 3_400_000
"Phones (Mobile)" = 4_922_000
"Phones (Landline)" = 1_880_000
GDP = 181_100_000_000
englishShortName = "New Zealand"
frenchShortName = "Nouvelle-Zélande (la)"
numeric = 554
japaneseShortName = "ニュージーランド"
[NI]
"Country Name" = "Nicaragua"
ISO2 = "NI"
ISO3 = "NIC"
"Top Level Domain" = "ni"
FIPS = "NU"
"ISO Numeric" = 558
GeoNameID = 3_617_476
E164 = 505
"Phone Code" = 505
Continent = "North America"
Capital = "Managua"
"Time Zone in Capital" = "America/Managua"
Currency = "Cordoba"
"Language Codes" = "es-NI,en"
Languages = "Spanish (official) 95.3%, Miskito 2.2%, Mestizo of the Caribbean coast 2%, other 0.5%"
"Area KM2" = 129_494
"Internet Hosts" = 296_068
"Internet Users" = 199_800
"Phones (Mobile)" = 5_346_000
"Phones (Landline)" = 320_000
GDP = 11_260_000_000
englishShortName = "Nicaragua"
frenchShortName = "Nicaragua (le)"
numeric = 558
japaneseShortName = "ニカラグア"
[NE]
"Country Name" = "Niger"
ISO2 = "NE"
ISO3 = "NER"
"Top Level Domain" = "ne"
FIPS = "NG"
"ISO Numeric" = 562
GeoNameID = 2_440_476
E164 = 227
"Phone Code" = 227
Continent = "Africa"
Capital = "Niamey"
"Time Zone in Capital" = "Africa/Lagos"
Currency = "Franc"
"Language Codes" = "fr-NE,ha,kr,dje"
Languages = "French (official), Hausa, Djerma"
"Area KM2" = 1_267_000
"Internet Hosts" = 454
"Internet Users" = 115_900
"Phones (Mobile)" = 5_400_000
"Phones (Landline)" = 100_500
GDP = 7_304_000_000
englishShortName = "Niger (the)"
frenchShortName = "Niger (le)"
numeric = 562
japaneseShortName = "ニジェール"
[NG]
"Country Name" = "Nigeria"
ISO2 = "NG"
ISO3 = "NGA"
"Top Level Domain" = "ng"
FIPS = "NI"
"ISO Numeric" = 566
GeoNameID = 2_328_926
E164 = 234
"Phone Code" = 234
Continent = "Africa"
Capital = "Abuja"
"Time Zone in Capital" = "Africa/Lagos"
Currency = "Naira"
"Language Codes" = "en-NG,ha,yo,ig,ff"
Languages = "English (official), Hausa, Yoruba, Igbo (Ibo), Fulani, over 500 additional indigenous languages"
"Area KM2" = 923_768
"Internet Hosts" = 1_234
"Internet Users" = 43_989_000
"Phones (Mobile)" = 112_780_000
"Phones (Landline)" = 418_200
GDP = 502_000_000_000
englishShortName = "Nigeria"
frenchShortName = "Nigéria (le)"
numeric = 566
japaneseShortName = "ナイジェリア"
[NU]
"Country Name" = "Niue"
ISO2 = "NU"
ISO3 = "NIU"
"Top Level Domain" = "nu"
FIPS = "NE"
"ISO Numeric" = 570
GeoNameID = 4_036_232
E164 = 683
"Phone Code" = 683
Continent = "Oceania"
Capital = "Alofi"
"Time Zone in Capital" = "Pacific/Niue"
Currency = "Dollar"
"Language Codes" = "niu,en-NU"
Languages = "Niuean (official) 46% (a Polynesian language closely related to Tongan and Samoan), Niuean and English 32%, English (official) 11%, Niuean and others 5%, other 6% (2011 est.)"
"Area KM2" = 260
"Internet Hosts" = 79_508
"Internet Users" = 1_100
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = 10_010_000
englishShortName = "Niue"
frenchShortName = "Niue"
numeric = 570
japaneseShortName = "ニウエ"
[KP]
"Country Name" = "North Korea"
ISO2 = "KP"
ISO3 = "PRK"
"Top Level Domain" = "kp"
FIPS = "KN"
"ISO Numeric" = 408
GeoNameID = 1_873_107
E164 = 850
"Phone Code" = 850
Continent = "Asia"
Capital = "Pyongyang"
"Time Zone in Capital" = "Asia/Pyongyang"
Currency = "Won"
"Language Codes" = "ko-KP"
Languages = "Korean"
"Area KM2" = 120_540
"Internet Hosts" = 8
"Internet Users" = ""
"Phones (Mobile)" = 1_700_000
"Phones (Landline)" = 1_180_000
GDP = 28_000_000_000
englishShortName = "Korea (the Democratic People's Republic of)"
frenchShortName = "Corée (la République populaire démocratique de)"
numeric = 408
japaneseShortName = "北朝鮮"
[MP]
"Country Name" = "Northern Mariana Islands"
ISO2 = "MP"
ISO3 = "MNP"
"Top Level Domain" = "mp"
FIPS = "CQ"
"ISO Numeric" = 580
GeoNameID = 4_041_468
E164 = 1
"Phone Code" = "1-670"
Continent = "Oceania"
Capital = "Saipan"
"Time Zone in Capital" = "Pacific/Saipan"
Currency = "Dollar"
"Language Codes" = "fil,tl,zh,ch-MP,en-MP"
Languages = "Philippine languages 32.8%, Chamorro (official) 24.1%, English (official) 17%, other Pacific island languages 10.1%, Chinese 6.8%, other Asian languages 7.3%, other 1.9% (2010 est.)"
"Area KM2" = 477
"Internet Hosts" = 17
"Internet Users" = ""
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = 733_000_000
englishShortName = "Northern Mariana Islands (the)"
frenchShortName = "Mariannes du Nord (les Îles)"
numeric = 580
japaneseShortName = "北マリアナ諸島"
[NO]
"Country Name" = "Norway"
ISO2 = "NO"
ISO3 = "NOR"
"Top Level Domain" = "no"
FIPS = "NO"
"ISO Numeric" = 578
GeoNameID = 3_144_096
E164 = 47
"Phone Code" = 47
Continent = "Europe"
Capital = "Oslo"
"Time Zone in Capital" = "Europe/Oslo"
Currency = "Krone"
"Language Codes" = "no,nb,nn,se,fi"
Languages = "Bokmal Norwegian (official), Nynorsk Norwegian (official), small Sami- and Finnish-speaking minorities"
"Area KM2" = 324_220
"Internet Hosts" = 3_588_000
"Internet Users" = 4_431_000
"Phones (Mobile)" = 5_732_000
"Phones (Landline)" = 1_465_000
GDP = 515_800_000_000
englishShortName = "Norway"
frenchShortName = "Norvège (la)"
numeric = 578
japaneseShortName = "ノルウェー"
[OM]
"Country Name" = "Oman"
ISO2 = "OM"
ISO3 = "OMN"
"Top Level Domain" = "om"
FIPS = "MU"
"ISO Numeric" = 512
GeoNameID = 286_963
E164 = 968
"Phone Code" = 968
Continent = "Asia"
Capital = "Muscat"
"Time Zone in Capital" = "Asia/Muscat"
Currency = "Rial"
"Language Codes" = "ar-OM,en,bal,ur"
Languages = "Arabic (official), English, Baluchi, Urdu, Indian dialects"
"Area KM2" = 212_460
"Internet Hosts" = 14_531
"Internet Users" = 1_465_000
"Phones (Mobile)" = 5_278_000
"Phones (Landline)" = 305_000
GDP = 81_950_000_000
englishShortName = "Oman"
frenchShortName = "Oman"
numeric = 512
japaneseShortName = "オマーン"
[PK]
"Country Name" = "Pakistan"
ISO2 = "PK"
ISO3 = "PAK"
"Top Level Domain" = "pk"
FIPS = "PK"
"ISO Numeric" = 586
GeoNameID = 1_168_579
E164 = 92
"Phone Code" = 92
Continent = "Asia"
Capital = "Islamabad"
"Time Zone in Capital" = "Asia/Karachi"
Currency = "Rupee"
"Language Codes" = "ur-PK,en-PK,pa,sd,ps,brh"
Languages = "Punjabi 48%, Sindhi 12%, Saraiki (a Punjabi variant) 10%, Pashto (alternate name, Pashtu) 8%, Urdu (official) 8%, Balochi 3%, Hindko 2%, Brahui 1%, English (official; lingua franca of Pakistani elite and most government ministries), Burushaski, and other 8%"
"Area KM2" = 803_940
"Internet Hosts" = 365_813
"Internet Users" = 20_431_000
"Phones (Mobile)" = 125_000_000
"Phones (Landline)" = 5_803_000
GDP = 236_500_000_000
englishShortName = "Pakistan"
frenchShortName = "Pakistan (le)"
numeric = 586
japaneseShortName = "パキスタン"
[PW]
"Country Name" = "Palau"
ISO2 = "PW"
ISO3 = "PLW"
"Top Level Domain" = "pw"
FIPS = "PS"
"ISO Numeric" = 585
GeoNameID = 1_559_582
E164 = 680
"Phone Code" = 680
Continent = "Oceania"
Capital = "Melekeok"
"Time Zone in Capital" = "Pacific/Palau"
Currency = "Dollar"
"Language Codes" = "pau,sov,en-PW,tox,ja,fil,zh"
Languages = "Palauan (official on most islands) 66.6%, Carolinian 0.7%, other Micronesian 0.7%, English (official) 15.5%, Filipino 10.8%, Chinese 1.8%, other Asian 2.6%, other 1.3%"
"Area KM2" = 458
"Internet Hosts" = 4
"Internet Users" = ""
"Phones (Mobile)" = 17_150
"Phones (Landline)" = 7_300
GDP = 221_000_000
englishShortName = "Palau"
frenchShortName = "Palaos (les)"
numeric = 585
japaneseShortName = "パラオ"
[PS]
"Country Name" = "Palestine"
ISO2 = "PS"
ISO3 = "PSE"
"Top Level Domain" = "ps"
FIPS = "WE"
"ISO Numeric" = 275
GeoNameID = 6_254_930
E164 = 970
"Phone Code" = 970
Continent = "Asia"
Capital = "East Jerusalem"
"Time Zone in Capital" = "Asia/Hebron"
Currency = "Shekel"
"Language Codes" = "ar-PS"
Languages = "Arabic, Hebrew, English"
"Area KM2" = 5_970
"Internet Hosts" = ""
"Internet Users" = 1_379_000
"Phones (Mobile)" = 3_041_000
"Phones (Landline)" = 406_000
GDP = 6_641_000_000
englishShortName = "Palestine, State of"
frenchShortName = "Palestine, État de"
numeric = 275
japaneseShortName = "パレスチナ国"
[PA]
"Country Name" = "Panama"
ISO2 = "PA"
ISO3 = "PAN"
"Top Level Domain" = "pa"
FIPS = "PM"
"ISO Numeric" = 591
GeoNameID = 3_703_430
E164 = 507
"Phone Code" = 507
Continent = "North America"
Capital = "Panama City"
"Time Zone in Capital" = "America/Panama"
Currency = "Balboa"
"Language Codes" = "es-PA,en"
Languages = "Spanish (official), English 14%"
"Area KM2" = 78_200
"Internet Hosts" = 11_022
"Internet Users" = 959_800
"Phones (Mobile)" = 6_770_000
"Phones (Landline)" = 640_000
GDP = 40_620_000_000
englishShortName = "Panama"
frenchShortName = "Panama (le)"
numeric = 591
japaneseShortName = "パナマ"
[PG]
"Country Name" = "Papua New Guinea"
ISO2 = "PG"
ISO3 = "PNG"
"Top Level Domain" = "pg"
FIPS = "PP"
"ISO Numeric" = 598
GeoNameID = 2_088_628
E164 = 675
"Phone Code" = 675
Continent = "Oceania"
Capital = "Port Moresby"
"Time Zone in Capital" = "Pacific/Port_Moresby"
Currency = "Kina"
"Language Codes" = "en-PG,ho,meu,tpi"
Languages = "Tok Pisin (official), English (official), Hiri Motu (official), some 836 indigenous languages spoken (about 12% of the world's total); most languages have fewer than 1,000 speakers"
"Area KM2" = 462_840
"Internet Hosts" = 5_006
"Internet Users" = 125_000
"Phones (Mobile)" = 2_709_000
"Phones (Landline)" = 139_000
GDP = 16_100_000_000
englishShortName = "Papua New Guinea"
frenchShortName = "Papouasie-Nouvelle-Guinée (la)"
numeric = 598
japaneseShortName = "パプアニューギニア"
[PY]
"Country Name" = "Paraguay"
ISO2 = "PY"
ISO3 = "PRY"
"Top Level Domain" = "py"
FIPS = "PA"
"ISO Numeric" = 600
GeoNameID = 3_437_598
E164 = 595
"Phone Code" = 595
Continent = "South America"
Capital = "Asuncion"
"Time Zone in Capital" = "America/Asuncion"
Currency = "Guarani"
"Language Codes" = "es-PY,gn"
Languages = "Spanish (official), Guarani (official)"
"Area KM2" = 406_750
"Internet Hosts" = 280_658
"Internet Users" = 1_105_000
"Phones (Mobile)" = 6_790_000
"Phones (Landline)" = 376_000
GDP = 30_560_000_000
englishShortName = "Paraguay"
frenchShortName = "Paraguay (le)"
numeric = 600
japaneseShortName = "パラグアイ"
[PE]
"Country Name" = "Peru"
ISO2 = "PE"
ISO3 = "PER"
"Top Level Domain" = "pe"
FIPS = "PE"
"ISO Numeric" = 604
GeoNameID = 3_932_488
E164 = 51
"Phone Code" = 51
Continent = "South America"
Capital = "Lima"
"Time Zone in Capital" = "America/Lima"
Currency = "Sol"
"Language Codes" = "es-PE,qu,ay"
Languages = "Spanish (official) 84.1%, Quechua (official) 13%, Aymara (official) 1.7%, Ashaninka 0.3%, other native languages (includes a large number of minor Amazonian languages) 0.7%, other (includes foreign languages and sign language) 0.2% (2007 est.)"
"Area KM2" = 1_285_220
"Internet Hosts" = 234_102
"Internet Users" = 9_158_000
"Phones (Mobile)" = 29_400_000
"Phones (Landline)" = 3_420_000
GDP = 210_300_000_000
englishShortName = "Peru"
frenchShortName = "Pérou (le)"
numeric = 604
japaneseShortName = "ペルー"
[PH]
"Country Name" = "Philippines"
ISO2 = "PH"
ISO3 = "PHL"
"Top Level Domain" = "ph"
FIPS = "RP"
"ISO Numeric" = 608
GeoNameID = 1_694_008
E164 = 63
"Phone Code" = 63
Continent = "Asia"
Capital = "Manila"
"Time Zone in Capital" = "Asia/Manila"
Currency = "Peso"
"Language Codes" = "tl,en-PH,fil"
Languages = "Filipino (official; based on Tagalog) and English (official); eight major dialects - Tagalog, Cebuano, Ilocano, Hiligaynon or Ilonggo, Bicol, Waray, Pampango, and Pangasinan"
"Area KM2" = 300_000
"Internet Hosts" = 425_812
"Internet Users" = 8_278_000
"Phones (Mobile)" = 103_000_000
"Phones (Landline)" = 3_939_000
GDP = 272_200_000_000
englishShortName = "Philippines (the)"
frenchShortName = "Philippines (les)"
numeric = 608
japaneseShortName = "フィリピン"
[PN]
"Country Name" = "Pitcairn"
ISO2 = "PN"
ISO3 = "PCN"
"Top Level Domain" = "pn"
FIPS = "PC"
"ISO Numeric" = 612
GeoNameID = 4_030_699
E164 = 64
"Phone Code" = 64
Continent = "Oceania"
Capital = "Adamstown"
"Time Zone in Capital" = "Pacific/Pitcairn"
Currency = "Dollar"
"Language Codes" = "en-PN"
Languages = "English"
"Area KM2" = 47
"Internet Hosts" = ""
"Internet Users" = ""
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = ""
englishShortName = "Pitcairn"
frenchShortName = "Pitcairn"
numeric = 612
japaneseShortName = "ピトケアン"
[PL]
"Country Name" = "Poland"
ISO2 = "PL"
ISO3 = "POL"
"Top Level Domain" = "pl"
FIPS = "PL"
"ISO Numeric" = 616
GeoNameID = 798_544
E164 = 48
"Phone Code" = 48
Continent = "Europe"
Capital = "Warsaw"
"Time Zone in Capital" = "Europe/Warsaw"
Currency = "Zloty"
"Language Codes" = "pl"
Languages = "Polish (official) 96.2%, Polish and non-Polish 2%, non-Polish 0.5%, unspecified 1.3%"
"Area KM2" = 312_685
"Internet Hosts" = 13_265_000
"Internet Users" = 22_452_000
"Phones (Mobile)" = 50_840_000
"Phones (Landline)" = 6_125_000
GDP = 513_900_000_000
englishShortName = "Poland"
frenchShortName = "Pologne (la)"
numeric = 616
japaneseShortName = "ポーランド"
[PT]
"Country Name" = "Portugal"
ISO2 = "PT"
ISO3 = "PRT"
"Top Level Domain" = "pt"
FIPS = "PO"
"ISO Numeric" = 620
GeoNameID = 2_264_397
E164 = 351
"Phone Code" = 351
Continent = "Europe"
Capital = "Lisbon"
"Time Zone in Capital" = "Europe/Lisbon"
Currency = "Euro"
"Language Codes" = "pt-PT,mwl"
Languages = "Portuguese (official), Mirandese (official, but locally used)"
"Area KM2" = 92_391
"Internet Hosts" = 3_748_000
"Internet Users" = 5_168_000
"Phones (Mobile)" = 12_312_000
"Phones (Landline)" = 4_558_000
GDP = 219_300_000_000
englishShortName = "Portugal"
frenchShortName = "Portugal (le)"
numeric = 620
japaneseShortName = "ポルトガル"
[PR]
"Country Name" = "Puerto Rico"
ISO2 = "PR"
ISO3 = "PRI"
"Top Level Domain" = "pr"
FIPS = "RQ"
"ISO Numeric" = 630
GeoNameID = 4_566_966
E164 = 1
"Phone Code" = "1-787, 1-939"
Continent = "North America"
Capital = "San Juan"
"Time Zone in Capital" = "America/Puerto_Rico"
Currency = "Dollar"
"Language Codes" = "en-PR,es-PR"
Languages = "Spanish, English"
"Area KM2" = 9_104
"Internet Hosts" = 469
"Internet Users" = 1_000_000
"Phones (Mobile)" = 3_060_000
"Phones (Landline)" = 780_200
GDP = 93_520_000_000
englishShortName = "Puerto Rico"
frenchShortName = "Porto Rico"
numeric = 630
japaneseShortName = "プエルトリコ"
[QA]
"Country Name" = "Qatar"
ISO2 = "QA"
ISO3 = "QAT"
"Top Level Domain" = "qa"
FIPS = "QA"
"ISO Numeric" = 634
GeoNameID = 289_688
E164 = 974
"Phone Code" = 974
Continent = "Asia"
Capital = "Doha"
"Time Zone in Capital" = "Asia/Qatar"
Currency = "Rial"
"Language Codes" = "ar-QA,es"
Languages = "Arabic (official), English commonly used as a second language"
"Area KM2" = 11_437
"Internet Hosts" = 897
"Internet Users" = 563_800
"Phones (Mobile)" = 2_600_000
"Phones (Landline)" = 327_000
GDP = 213_100_000_000
englishShortName = "Qatar"
frenchShortName = "Qatar (le)"
numeric = 634
japaneseShortName = "カタール"
[CG]
"Country Name" = "Republic of the Congo"
ISO2 = "CG"
ISO3 = "COG"
"Top Level Domain" = "cg"
FIPS = "CF"
"ISO Numeric" = 178
GeoNameID = 2_260_494
E164 = 242
"Phone Code" = 242
Continent = "Africa"
Capital = "Brazzaville"
"Time Zone in Capital" = "Africa/Lagos"
Currency = "Franc"
"Language Codes" = "fr-CG,kg,ln-CG"
Languages = "French (official), Lingala and Monokutuba (lingua franca trade languages), many local languages and dialects (of which Kikongo is the most widespread)"
"Area KM2" = 342_000
"Internet Hosts" = 45
"Internet Users" = 245_200
"Phones (Mobile)" = 4_283_000
"Phones (Landline)" = 14_900
GDP = 14_250_000_000
englishShortName = "Congo (the)"
frenchShortName = "Congo (le)"
numeric = 178
japaneseShortName = "コンゴ"
[RE]
"Country Name" = "Reunion"
ISO2 = "RE"
ISO3 = "REU"
"Top Level Domain" = "re"
FIPS = "RE"
"ISO Numeric" = 638
GeoNameID = 935_317
E164 = 262
"Phone Code" = 262
Continent = "Africa"
Capital = "Saint-Denis"
"Time Zone in Capital" = "Indian/Reunion"
Currency = "Euro"
"Language Codes" = "fr-RE"
Languages = "French"
"Area KM2" = 2_517
"Internet Hosts" = ""
"Internet Users" = ""
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = ""
englishShortName = "Réunion"
frenchShortName = "Réunion (La)"
numeric = 638
japaneseShortName = "レユニオン"
[RO]
"Country Name" = "Romania"
ISO2 = "RO"
ISO3 = "ROU"
"Top Level Domain" = "ro"
FIPS = "RO"
"ISO Numeric" = 642
GeoNameID = 798_549
E164 = 40
"Phone Code" = 40
Continent = "Europe"
Capital = "Bucharest"
"Time Zone in Capital" = "Europe/Bucharest"
Currency = "Leu"
"Language Codes" = "ro,hu,rom"
Languages = "Romanian (official) 85.4%, Hungarian 6.3%, Romany (Gypsy) 1.2%, other 1%, unspecified 6.1% (2011 est.)"
"Area KM2" = 237_500
"Internet Hosts" = 2_667_000
"Internet Users" = 7_787_000
"Phones (Mobile)" = 22_700_000
"Phones (Landline)" = 4_680_000
GDP = 188_900_000_000
englishShortName = "Romania"
frenchShortName = "Roumanie (la)"
numeric = 642
japaneseShortName = "ルーマニア"
[RU]
"Country Name" = "Russia"
ISO2 = "RU"
ISO3 = "RUS"
"Top Level Domain" = "ru"
FIPS = "RS"
"ISO Numeric" = 643
GeoNameID = 2_017_370
E164 = 7
"Phone Code" = 7
Continent = "Europe"
Capital = "Moscow"
"Time Zone in Capital" = "Europe/Moscow"
Currency = "Ruble"
"Language Codes" = "ru,tt,xal,cau,ady,kv,ce,tyv,cv,udm,tut,mns,bua,myv,mdf,chm,ba,inh,tut,kbd,krc,ava,sah,nog"
Languages = "Russian (official) 96.3%, Dolgang 5.3%, German 1.5%, Chechen 1%, Tatar 3%, other 10.3%"
"Area KM2" = 17_100_000
"Internet Hosts" = 14_865_000
"Internet Users" = 40_853_000
"Phones (Mobile)" = 261_900_000
"Phones (Landline)" = 42_900_000
GDP = 2_113_000_000_000
englishShortName = "Russian Federation (the)"
frenchShortName = "Russie (la Fédération de)"
numeric = 643
japaneseShortName = "ロシア連邦"
[RW]
"Country Name" = "Rwanda"
ISO2 = "RW"
ISO3 = "RWA"
"Top Level Domain" = "rw"
FIPS = "RW"
"ISO Numeric" = 646
GeoNameID = 49_518
E164 = 250
"Phone Code" = 250
Continent = "Africa"
Capital = "Kigali"
"Time Zone in Capital" = "Africa/Maputo"
Currency = "Franc"
"Language Codes" = "rw,en-RW,fr-RW,sw"
Languages = "Kinyarwanda only (official, universal Bantu vernacular) 93.2%, Kinyarwanda and other language(s) 6.2%, French (official) and other language(s) 0.1%, English (official) and other language(s) 0.1%, Swahili (or Kiswahili, used in commercial centers) 0.02%, other 0.03%, unspecified 0.3% (2002 est.)"
"Area KM2" = 26_338
"Internet Hosts" = 1_447
"Internet Users" = 450_000
"Phones (Mobile)" = 5_690_000
"Phones (Landline)" = 44_400
GDP = 7_700_000_000
englishShortName = "Rwanda"
frenchShortName = "Rwanda (le)"
numeric = 646
japaneseShortName = "ルワンダ"
[BL]
"Country Name" = "Saint Barthelemy"
ISO2 = "BL"
ISO3 = "BLM"
"Top Level Domain" = "gp"
FIPS = "TB"
"ISO Numeric" = 652
GeoNameID = 3_578_476
E164 = 590
"Phone Code" = 590
Continent = "North America"
Capital = "Gustavia"
"Time Zone in Capital" = "America/Port_of_Spain"
Currency = "Euro"
"Language Codes" = "fr"
Languages = "French (primary), English"
"Area KM2" = 21
"Internet Hosts" = ""
"Internet Users" = ""
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = ""
englishShortName = "Saint Barthélemy"
frenchShortName = "Saint-Barthélemy"
numeric = 652
japaneseShortName = "サン・バルテルミー"
[SH]
"Country Name" = "Saint Helena"
ISO2 = "SH"
ISO3 = "SHN"
"Top Level Domain" = "sh"
FIPS = "SH"
"ISO Numeric" = 654
GeoNameID = 3_370_751
E164 = 290
"Phone Code" = 290
Continent = "Africa"
Capital = "Jamestown"
"Time Zone in Capital" = "Africa/Abidjan"
Currency = "Pound"
"Language Codes" = "en-SH"
Languages = "English"
"Area KM2" = 410
"Internet Hosts" = ""
"Internet Users" = ""
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = ""
englishShortName = "Saint Helena, Ascension and Tristan da Cunha"
frenchShortName = "Sainte-Hélène, Ascension et Tristan da Cunha"
numeric = 654
japaneseShortName = "セントヘレナ"
[KN]
"Country Name" = "Saint Kitts and Nevis"
ISO2 = "KN"
ISO3 = "KNA"
"Top Level Domain" = "kn"
FIPS = "SC"
"ISO Numeric" = 659
GeoNameID = 3_575_174
E164 = 1
"Phone Code" = "1-869"
Continent = "North America"
Capital = "Basseterre"
"Time Zone in Capital" = "America/Port_of_Spain"
Currency = "Dollar"
"Language Codes" = "en-KN"
Languages = "English (official)"
"Area KM2" = 261
"Internet Hosts" = 54
"Internet Users" = 17_000
"Phones (Mobile)" = 84_000
"Phones (Landline)" = 20_000
GDP = 767_000_000
englishShortName = "Saint Kitts and Nevis"
frenchShortName = "Saint-Kitts-et-Nevis"
numeric = 659
japaneseShortName = "セントクリストファー・ネイビス連邦"
[LC]
"Country Name" = "Saint Lucia"
ISO2 = "LC"
ISO3 = "LCA"
"Top Level Domain" = "lc"
FIPS = "ST"
"ISO Numeric" = 662
GeoNameID = 3_576_468
E164 = 1
"Phone Code" = "1-758"
Continent = "North America"
Capital = "Castries"
"Time Zone in Capital" = "America/Port_of_Spain"
Currency = "Dollar"
"Language Codes" = "en-LC"
Languages = "English (official), French patois"
"Area KM2" = 616
"Internet Hosts" = 100
"Internet Users" = 142_900
"Phones (Mobile)" = 227_000
"Phones (Landline)" = 36_800
GDP = 1_377_000_000
englishShortName = "Saint Lucia"
frenchShortName = "Sainte-Lucie"
numeric = 662
japaneseShortName = "セントルシア"
[MF]
"Country Name" = "Saint Martin"
ISO2 = "MF"
ISO3 = "MAF"
"Top Level Domain" = "gp"
FIPS = "RN"
"ISO Numeric" = 663
GeoNameID = 3_578_421
E164 = 1
"Phone Code" = 590
Continent = "North America"
Capital = "Marigot"
"Time Zone in Capital" = "America/Port_of_Spain"
Currency = "Euro"
"Language Codes" = "fr"
Languages = "French (official), English, Dutch, French Patois, Spanish, Papiamento (dialect of Netherlands Antilles)"
"Area KM2" = 53
"Internet Hosts" = ""
"Internet Users" = ""
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = 561_500_000
englishShortName = "Saint Martin (French part)"
frenchShortName = "Saint-Martin (partie française)"
numeric = 663
japaneseShortName = "セント・マーチン"
[PM]
"Country Name" = "Saint Pierre and Miquelon"
ISO2 = "PM"
ISO3 = "SPM"
"Top Level Domain" = "pm"
FIPS = "SB"
"ISO Numeric" = 666
GeoNameID = 3_424_932
E164 = 508
"Phone Code" = 508
Continent = "North America"
Capital = "Saint-Pierre"
"Time Zone in Capital" = "America/Miquelon"
Currency = "Euro"
"Language Codes" = "fr-PM"
Languages = "French (official)"
"Area KM2" = 242
"Internet Hosts" = 15
"Internet Users" = ""
"Phones (Mobile)" = ""
"Phones (Landline)" = 4_800
GDP = 215_300_000
englishShortName = "Saint Pierre and Miquelon"
frenchShortName = "Saint-Pierre-et-Miquelon"
numeric = 666
japaneseShortName = "サンピエール島およびミクロン島"
[VC]
"Country Name" = "Saint Vincent and the Grenadines"
ISO2 = "VC"
ISO3 = "VCT"
"Top Level Domain" = "vc"
FIPS = "VC"
"ISO Numeric" = 670
GeoNameID = 3_577_815
E164 = 1
"Phone Code" = "1-784"
Continent = "North America"
Capital = "Kingstown"
"Time Zone in Capital" = "America/Port_of_Spain"
Currency = "Dollar"
"Language Codes" = "en-VC,fr"
Languages = "English, French patois"
"Area KM2" = 389
"Internet Hosts" = 305
"Internet Users" = 76_000
"Phones (Mobile)" = 135_500
"Phones (Landline)" = 19_400
GDP = 742_000_000
englishShortName = "Saint Vincent and the Grenadines"
frenchShortName = "Saint-Vincent-et-les Grenadines"
numeric = 670
japaneseShortName = "セントビンセント及びグレナディーン諸島"
[WS]
"Country Name" = "Samoa"
ISO2 = "WS"
ISO3 = "WSM"
"Top Level Domain" = "ws"
FIPS = "WS"
"ISO Numeric" = 882
GeoNameID = 4_034_894
E164 = 685
"Phone Code" = 685
Continent = "Oceania"
Capital = "Apia"
"Time Zone in Capital" = "Pacific/Apia"
Currency = "Tala"
"Language Codes" = "sm,en-WS"
Languages = "Samoan (Polynesian) (official), English"
"Area KM2" = 2_944
"Internet Hosts" = 18_013
"Internet Users" = 9_000
"Phones (Mobile)" = 167_400
"Phones (Landline)" = 35_300
GDP = 705_000_000
englishShortName = "Samoa"
frenchShortName = "Samoa (le)"
numeric = 882
japaneseShortName = "サモア"
[SM]
"Country Name" = "San Marino"
ISO2 = "SM"
ISO3 = "SMR"
"Top Level Domain" = "sm"
FIPS = "SM"
"ISO Numeric" = 674
GeoNameID = 3_168_068
E164 = 378
"Phone Code" = 378
Continent = "Europe"
Capital = "San Marino"
"Time Zone in Capital" = "Europe/Rome"
Currency = "Euro"
"Language Codes" = "it-SM"
Languages = "Italian"
"Area KM2" = 61
"Internet Hosts" = 11_015
"Internet Users" = 17_000
"Phones (Mobile)" = 36_000
"Phones (Landline)" = 18_700
GDP = 1_866_000_000
englishShortName = "San Marino"
frenchShortName = "Saint-Marin"
numeric = 674
japaneseShortName = "サンマリノ"
[ST]
"Country Name" = "Sao Tome and Principe"
ISO2 = "ST"
ISO3 = "STP"
"Top Level Domain" = "st"
FIPS = "TP"
"ISO Numeric" = 678
GeoNameID = 2_410_758
E164 = 239
"Phone Code" = 239
Continent = "Africa"
Capital = "Sao Tome"
"Time Zone in Capital" = "Africa/Abidjan"
Currency = "Dobra"
"Language Codes" = "pt-ST"
Languages = "Portuguese 98.4% (official), Forro 36.2%, Cabo Verdian 8.5%, French 6.8%, Angolar 6.6%, English 4.9%, Lunguie 1%, other (including sign language) 2.4%"
"Area KM2" = 1_001
"Internet Hosts" = 1_678
"Internet Users" = 26_700
"Phones (Mobile)" = 122_000
"Phones (Landline)" = 8_000
GDP = 311_000_000
englishShortName = "Sao Tome and Principe"
frenchShortName = "Sao Tomé-et-Principe"
numeric = 678
japaneseShortName = "サントメ・プリンシペ"
[SA]
"Country Name" = "Saudi Arabia"
ISO2 = "SA"
ISO3 = "SAU"
"Top Level Domain" = "sa"
FIPS = "SA"
"ISO Numeric" = 682
GeoNameID = 102_358
E164 = 966
"Phone Code" = 966
Continent = "Asia"
Capital = "Riyadh"
"Time Zone in Capital" = "Asia/Riyadh"
Currency = "Rial"
"Language Codes" = "ar-SA"
Languages = "Arabic (official)"
"Area KM2" = 1_960_582
"Internet Hosts" = 145_941
"Internet Users" = 9_774_000
"Phones (Mobile)" = 53_000_000
"Phones (Landline)" = 4_800_000
GDP = 718_500_000_000
englishShortName = "Saudi Arabia"
frenchShortName = "Arabie saoudite (l')"
numeric = 682
japaneseShortName = "サウジアラビア"
[SN]
"Country Name" = "Senegal"
ISO2 = "SN"
ISO3 = "SEN"
"Top Level Domain" = "sn"
FIPS = "SG"
"ISO Numeric" = 686
GeoNameID = 2_245_662
E164 = 221
"Phone Code" = 221
Continent = "Africa"
Capital = "Dakar"
"Time Zone in Capital" = "Africa/Abidjan"
Currency = "Franc"
"Language Codes" = "fr-SN,wo,fuc,mnk"
Languages = "French (official), Wolof, Pulaar, Jola, Mandinka"
"Area KM2" = 196_190
"Internet Hosts" = 237
"Internet Users" = 1_818_000
"Phones (Mobile)" = 11_470_000
"Phones (Landline)" = 338_200
GDP = 15_360_000_000
englishShortName = "Senegal"
frenchShortName = "Sénégal (le)"
numeric = 686
japaneseShortName = "セネガル"
[RS]
"Country Name" = "Serbia"
ISO2 = "RS"
ISO3 = "SRB"
"Top Level Domain" = "rs"
FIPS = "RI"
"ISO Numeric" = 688
GeoNameID = 6_290_252
E164 = 381
"Phone Code" = 381
Continent = "Europe"
Capital = "Belgrade"
"Time Zone in Capital" = "Europe/Belgrade"
Currency = "Dinar"
"Language Codes" = "sr,hu,bs,rom"
Languages = "Serbian (official) 88.1%, Hungarian 3.4%, Bosnian 1.9%, Romany 1.4%, other 3.4%, undeclared or unknown 1.8%"
"Area KM2" = 88_361
"Internet Hosts" = 1_102_000
"Internet Users" = 4_107_000
"Phones (Mobile)" = 9_138_000
"Phones (Landline)" = 2_977_000
GDP = 43_680_000_000
englishShortName = "Serbia"
frenchShortName = "Serbie (la)"
numeric = 688
japaneseShortName = "セルビア"
[SC]
"Country Name" = "Seychelles"
ISO2 = "SC"
ISO3 = "SYC"
"Top Level Domain" = "sc"
FIPS = "SE"
"ISO Numeric" = 690
GeoNameID = 241_170
E164 = 248
"Phone Code" = 248
Continent = "Africa"
Capital = "Victoria"
"Time Zone in Capital" = "Indian/Mahe"
Currency = "Rupee"
"Language Codes" = "en-SC,fr-SC"
Languages = "Seychellois Creole (official) 89.1%, English (official) 5.1%, French (official) 0.7%, other 3.8%, unspecified 1.4% (2010 est.)"
"Area KM2" = 455
"Internet Hosts" = 247
"Internet Users" = 32_000
"Phones (Mobile)" = 138_300
"Phones (Landline)" = 28_900
GDP = 1_271_000_000
englishShortName = "Seychelles"
frenchShortName = "Seychelles (les)"
numeric = 690
japaneseShortName = "セーシェル"
[SL]
"Country Name" = "Sierra Leone"
ISO2 = "SL"
ISO3 = "SLE"
"Top Level Domain" = "sl"
FIPS = "SL"
"ISO Numeric" = 694
GeoNameID = 2_403_846
E164 = 232
"Phone Code" = 232
Continent = "Africa"
Capital = "Freetown"
"Time Zone in Capital" = "Africa/Abidjan"
Currency = "Leone"
"Language Codes" = "en-SL,men,tem"
Languages = "English (official, regular use limited to literate minority), Mende (principal vernacular in the south), Temne (principal vernacular in the north), Krio (English-based Creole, spoken by the descendants of freed Jamaican slaves who were settled in the Freetown area, a lingua franca and a first language for 10% of the population but understood by 95%)"
"Area KM2" = 71_740
"Internet Hosts" = 282
"Internet Users" = 14_900
"Phones (Mobile)" = 2_210_000
"Phones (Landline)" = 18_000
GDP = 4_607_000_000
englishShortName = "Sierra Leone"
frenchShortName = "Sierra Leone (la)"
numeric = 694
japaneseShortName = "シエラレオネ"
[SG]
"Country Name" = "Singapore"
ISO2 = "SG"
ISO3 = "SGP"
"Top Level Domain" = "sg"
FIPS = "SN"
"ISO Numeric" = 702
GeoNameID = 1_880_251
E164 = 65
"Phone Code" = 65
Continent = "Asia"
Capital = "Singapore"
"Time Zone in Capital" = "Asia/Singapore"
Currency = "Dollar"
"Language Codes" = "cmn,en-SG,ms-SG,ta-SG,zh-SG"
Languages = "Mandarin (official) 36.3%, English (official) 29.8%, Malay (official) 11.9%, Hokkien 8.1%, Tamil (official) 4.4%, Cantonese 4.1%, Teochew 3.2%, other Indian languages 1.2%, other Chinese dialects 1.1%, other 1.1% (2010 est.)"
"Area KM2" = 693
"Internet Hosts" = 1_960_000
"Internet Users" = 3_235_000
"Phones (Mobile)" = 8_063_000
"Phones (Landline)" = 1_990_000
GDP = 295_700_000_000
englishShortName = "Singapore"
frenchShortName = "Singapour"
numeric = 702
japaneseShortName = "シンガポール"
[SX]
"Country Name" = "Sint Maarten"
ISO2 = "SX"
ISO3 = "SXM"
"Top Level Domain" = "sx"
FIPS = "NN"
"ISO Numeric" = 534
GeoNameID = 7_609_695
E164 = 1
"Phone Code" = "1-721"
Continent = "North America"
Capital = "Philipsburg"
"Time Zone in Capital" = "America/Curacao"
Currency = "Guilder"
"Language Codes" = "nl,en"
Languages = "English (official) 67.5%, Spanish 12.9%, Creole 8.2%, Dutch (official) 4.2%, Papiamento (a Spanish-Portuguese-Dutch-English dialect) 2.2%, French 1.5%, other 3.5% (2001 census)"
"Area KM2" = 34
"Internet Hosts" = ""
"Internet Users" = ""
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = 794_700_000
englishShortName = "Sint Maarten (Dutch part)"
frenchShortName = "Saint-Martin (partie néerlandaise)"
numeric = 534
[SK]
"Country Name" = "Slovakia"
ISO2 = "SK"
ISO3 = "SVK"
"Top Level Domain" = "sk"
FIPS = "LO"
"ISO Numeric" = 703
GeoNameID = 3_057_568
E164 = 421
"Phone Code" = 421
Continent = "Europe"
Capital = "Bratislava"
"Time Zone in Capital" = "Europe/Prague"
Currency = "Euro"
"Language Codes" = "sk,hu"
Languages = "Slovak (official) 78.6%, Hungarian 9.4%, Roma 2.3%, Ruthenian 1%, other or unspecified 8.8% (2011 est.)"
"Area KM2" = 48_845
"Internet Hosts" = 1_384_000
"Internet Users" = 4_063_000
"Phones (Mobile)" = 6_095_000
"Phones (Landline)" = 975_000
GDP = 96_960_000_000
englishShortName = "Slovakia"
frenchShortName = "Slovaquie (la)"
numeric = 703
japaneseShortName = "スロバキア"
[SI]
"Country Name" = "Slovenia"
ISO2 = "SI"
ISO3 = "SVN"
"Top Level Domain" = "si"
FIPS = "SI"
"ISO Numeric" = 705
GeoNameID = 3_190_538
E164 = 386
"Phone Code" = 386
Continent = "Europe"
Capital = "Ljubljana"
"Time Zone in Capital" = "Europe/Belgrade"
Currency = "Euro"
"Language Codes" = "sl,sh"
Languages = "Slovenian (official) 91.1%, Serbo-Croatian 4.5%, other or unspecified 4.4%, Italian (official, only in municipalities where Italian national communities reside), Hungarian (official, only in municipalities where Hungarian national communities reside) (2002 census)"
"Area KM2" = 20_273
"Internet Hosts" = 415_581
"Internet Users" = 1_298_000
"Phones (Mobile)" = 2_246_000
"Phones (Landline)" = 825_000
GDP = 46_820_000_000
englishShortName = "Slovenia"
frenchShortName = "Slovénie (la)"
numeric = 705
japaneseShortName = "スロベニア"
[SB]
"Country Name" = "Solomon Islands"
ISO2 = "SB"
ISO3 = "SLB"
"Top Level Domain" = "sb"
FIPS = "BP"
"ISO Numeric" = "090"
GeoNameID = 2_103_350
E164 = 677
"Phone Code" = 677
Continent = "Oceania"
Capital = "Honiara"
"Time Zone in Capital" = "Pacific/Guadalcanal"
Currency = "Dollar"
"Language Codes" = "en-SB,tpi"
Languages = "Melanesian pidgin (in much of the country is lingua franca), English (official but spoken by only 1%-2% of the population), 120 indigenous languages"
"Area KM2" = 28_450
"Internet Hosts" = 4_370
"Internet Users" = 10_000
"Phones (Mobile)" = 302_100
"Phones (Landline)" = 8_060
GDP = 1_099_000_000
englishShortName = "Solomon Islands"
frenchShortName = "Salomon (les Îles)"
numeric = 90
japaneseShortName = "ソロモン諸島"
[SO]
"Country Name" = "Somalia"
ISO2 = "SO"
ISO3 = "SOM"
"Top Level Domain" = "so"
FIPS = "SO"
"ISO Numeric" = 706
GeoNameID = 51_537
E164 = 252
"Phone Code" = 252
Continent = "Africa"
Capital = "Mogadishu"
"Time Zone in Capital" = "Africa/Mogadishu"
Currency = "Shilling"
"Language Codes" = "so-SO,ar-SO,it,en-SO"
Languages = "Somali (official), Arabic (official, according to the Transitional Federal Charter), Italian, English"
"Area KM2" = 637_657
"Internet Hosts" = 186
"Internet Users" = 106_000
"Phones (Mobile)" = 658_000
"Phones (Landline)" = 100_000
GDP = 2_372_000_000
englishShortName = "Somalia"
frenchShortName = "Somalie (la)"
numeric = 706
japaneseShortName = "ソマリア"
[ZA]
"Country Name" = "South Africa"
ISO2 = "ZA"
ISO3 = "ZAF"
"Top Level Domain" = "za"
FIPS = "SF"
"ISO Numeric" = 710
GeoNameID = 953_987
E164 = 27
"Phone Code" = 27
Continent = "Africa"
Capital = "Pretoria"
"Time Zone in Capital" = "Africa/Johannesburg"
Currency = "Rand"
"Language Codes" = "zu,xh,af,nso,en-ZA,tn,st,ts,ss,ve,nr"
Languages = "IsiZulu (official) 22.7%, IsiXhosa (official) 16%, Afrikaans (official) 13.5%, English (official) 9.6%, Sepedi (official) 9.1%, Setswana (official) 8%, Sesotho (official) 7.6%, Xitsonga (official) 4.5%, siSwati (official) 2.5%, Tshivenda (official) 2.4%, isiNdebele (official) 2.1%, sign language 0.5%, other 1.6% (2011 est.)"
"Area KM2" = 1_219_912
"Internet Hosts" = 4_761_000
"Internet Users" = 4_420_000
"Phones (Mobile)" = 68_400_000
"Phones (Landline)" = 4_030_000
GDP = 353_900_000_000
englishShortName = "South Africa"
frenchShortName = "Afrique du Sud (l')"
numeric = 710
japaneseShortName = "南アフリカ"
[KR]
"Country Name" = "South Korea"
ISO2 = "KR"
ISO3 = "KOR"
"Top Level Domain" = "kr"
FIPS = "KS"
"ISO Numeric" = 410
GeoNameID = 1_835_841
E164 = 82
"Phone Code" = 82
Continent = "Asia"
Capital = "Seoul"
"Time Zone in Capital" = "Asia/Seoul"
Currency = "Won"
"Language Codes" = "ko-KR,en"
Languages = "Korean, English (widely taught in junior high and high school)"
"Area KM2" = 98_480
"Internet Hosts" = 315_697
"Internet Users" = 39_400_000
"Phones (Mobile)" = 53_625_000
"Phones (Landline)" = 30_100_000
GDP = 1_198_000_000_000
englishShortName = "Korea (the Republic of)"
frenchShortName = "Corée (la République de)"
numeric = 410
japaneseShortName = "韓国"
[SS]
"Country Name" = "South Sudan"
ISO2 = "SS"
ISO3 = "SSD"
"Top Level Domain" = "ss"
FIPS = "OD"
"ISO Numeric" = 728
GeoNameID = 7_909_807
E164 = 211
"Phone Code" = 211
Continent = "Africa"
Capital = "Juba"
"Time Zone in Capital" = "Africa/Khartoum"
Currency = "Pound"
"Language Codes" = "en"
Languages = "English (official), Arabic (includes Juba and Sudanese variants), regional languages include Dinka, Nuer, Bari, Zande, Shilluk"
"Area KM2" = 644_329
"Internet Hosts" = ""
"Internet Users" = ""
"Phones (Mobile)" = 2_000_000
"Phones (Landline)" = 2_200
GDP = 11_770_000_000
englishShortName = "South Sudan"
frenchShortName = "Soudan du Sud (le)"
numeric = 728
[ES]
"Country Name" = "Spain"
ISO2 = "ES"
ISO3 = "ESP"
"Top Level Domain" = "es"
FIPS = "SP"
"ISO Numeric" = 724
GeoNameID = 2_510_769
E164 = 34
"Phone Code" = 34
Continent = "Europe"
Capital = "Madrid"
"Time Zone in Capital" = "Europe/Madrid"
Currency = "Euro"
"Language Codes" = "es-ES,ca,gl,eu,oc"
Languages = "Castilian Spanish (official) 74%, Catalan 17%, Galician 7%, and Basque 2%"
"Area KM2" = 504_782
"Internet Hosts" = 4_228_000
"Internet Users" = 28_119_000
"Phones (Mobile)" = 50_663_000
"Phones (Landline)" = 19_220_000
GDP = 1_356_000_000_000
englishShortName = "Spain"
frenchShortName = "Espagne (l')"
numeric = 724
japaneseShortName = "スペイン"
[LK]
"Country Name" = "Sri Lanka"
ISO2 = "LK"
ISO3 = "LKA"
"Top Level Domain" = "lk"
FIPS = "CE"
"ISO Numeric" = 144
GeoNameID = 1_227_603
E164 = 94
"Phone Code" = 94
Continent = "Asia"
Capital = "Colombo"
"Time Zone in Capital" = "Asia/Colombo"
Currency = "Rupee"
"Language Codes" = "si,ta,en"
Languages = "Sinhala (official and national language) 74%, Tamil (national language) 18%, other 8%"
"Area KM2" = 65_610
"Internet Hosts" = 9_552
"Internet Users" = 1_777_000
"Phones (Mobile)" = 19_533_000
"Phones (Landline)" = 2_796_000
GDP = 65_120_000_000
englishShortName = "Sri Lanka"
frenchShortName = "Sri Lanka"
numeric = 144
japaneseShortName = "スリランカ"
[SD]
"Country Name" = "Sudan"
ISO2 = "SD"
ISO3 = "SDN"
"Top Level Domain" = "sd"
FIPS = "SU"
"ISO Numeric" = 729
GeoNameID = 366_755
E164 = 249
"Phone Code" = 249
Continent = "Africa"
Capital = "Khartoum"
"Time Zone in Capital" = "Africa/Khartoum"
Currency = "Pound"
"Language Codes" = "ar-SD,en,fia"
Languages = "Arabic (official), English (official), Nubian, Ta Bedawie, Fur"
"Area KM2" = 1_861_484
"Internet Hosts" = 99
"Internet Users" = 4_200_000
"Phones (Mobile)" = 27_659_000
"Phones (Landline)" = 425_000
GDP = 52_500_000_000
englishShortName = "Sudan (the)"
frenchShortName = "Soudan (le)"
numeric = 729
japaneseShortName = "スーダン"
[SR]
"Country Name" = "Suriname"
ISO2 = "SR"
ISO3 = "SUR"
"Top Level Domain" = "sr"
FIPS = "NS"
"ISO Numeric" = 740
GeoNameID = 3_382_998
E164 = 597
"Phone Code" = 597
Continent = "South America"
Capital = "Paramaribo"
"Time Zone in Capital" = "America/Paramaribo"
Currency = "Dollar"
"Language Codes" = "nl-SR,en,srn,hns,jv"
Languages = "Dutch (official), English (widely spoken), Sranang Tongo (Surinamese, sometimes called Taki-Taki, is native language of Creoles and much of the younger population and is lingua franca among others), Caribbean Hindustani (a dialect of Hindi), Javanese"
"Area KM2" = 163_270
"Internet Hosts" = 188
"Internet Users" = 163_000
"Phones (Mobile)" = 977_000
"Phones (Landline)" = 83_000
GDP = 5_009_000_000
englishShortName = "Suriname"
frenchShortName = "Suriname (le)"
numeric = 740
japaneseShortName = "スリナム"
[SJ]
"Country Name" = "Svalbard and Jan Mayen"
ISO2 = "SJ"
ISO3 = "SJM"
"Top Level Domain" = "sj"
FIPS = "SV"
"ISO Numeric" = 744
GeoNameID = 607_072
E164 = 47
"Phone Code" = 47
Continent = "Europe"
Capital = "Longyearbyen"
"Time Zone in Capital" = "Europe/Oslo"
Currency = "Krone"
"Language Codes" = "no,ru"
Languages = "Norwegian, Russian"
"Area KM2" = 62_049
"Internet Hosts" = ""
"Internet Users" = ""
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = ""
englishShortName = "Svalbard and Jan Mayen"
frenchShortName = "Svalbard et l'Île Jan Mayen (le)"
numeric = 744
japaneseShortName = "スヴァールバル諸島およびヤンマイエン島"
[SZ]
"Country Name" = "Swaziland"
ISO2 = "SZ"
ISO3 = "SWZ"
"Top Level Domain" = "sz"
FIPS = "WZ"
"ISO Numeric" = 748
GeoNameID = 934_841
E164 = 268
"Phone Code" = 268
Continent = "Africa"
Capital = "Mbabane"
"Time Zone in Capital" = "Africa/Johannesburg"
Currency = "Lilangeni"
"Language Codes" = "en-SZ,ss-SZ"
Languages = "English (official, used for government business), siSwati (official)"
"Area KM2" = 17_363
"Internet Hosts" = 2_744
"Internet Users" = 90_100
"Phones (Mobile)" = 805_000
"Phones (Landline)" = 48_600
GDP = 3_807_000_000
englishShortName = "Eswatini"
frenchShortName = "Eswatini (l')"
numeric = 748
japaneseShortName = "スワジランド"
[SE]
"Country Name" = "Sweden"
ISO2 = "SE"
ISO3 = "SWE"
"Top Level Domain" = "se"
FIPS = "SW"
"ISO Numeric" = 752
GeoNameID = 2_661_886
E164 = 46
"Phone Code" = 46
Continent = "Europe"
Capital = "Stockholm"
"Time Zone in Capital" = "Europe/Stockholm"
Currency = "Krona"
"Language Codes" = "sv-SE,se,sma,fi-SE"
Languages = "Swedish (official), small Sami- and Finnish-speaking minorities"
"Area KM2" = 449_964
"Internet Hosts" = 5_978_000
"Internet Users" = 8_398_000
"Phones (Mobile)" = 11_643_000
"Phones (Landline)" = 4_321_000
GDP = 552_000_000_000
englishShortName = "Sweden"
frenchShortName = "Suède (la)"
numeric = 752
japaneseShortName = "スウェーデン"
[CH]
"Country Name" = "Switzerland"
ISO2 = "CH"
ISO3 = "CHE"
"Top Level Domain" = "ch"
FIPS = "SZ"
"ISO Numeric" = 756
GeoNameID = 2_658_434
E164 = 41
"Phone Code" = 41
Continent = "Europe"
Capital = "Berne"
"Time Zone in Capital" = "Europe/Zurich"
Currency = "Franc"
"Language Codes" = "de-CH,fr-CH,it-CH,rm"
Languages = "German (official) 64.9%, French (official) 22.6%, Italian (official) 8.3%, Serbo-Croatian 2.5%, Albanian 2.6%, Portuguese 3.4%, Spanish 2.2%, English 4.6%, Romansch (official) 0.5%, other 5.1%"
"Area KM2" = 41_290
"Internet Hosts" = 5_301_000
"Internet Users" = 6_152_000
"Phones (Mobile)" = 10_460_000
"Phones (Landline)" = 4_382_000
GDP = 646_200_000_000
englishShortName = "Switzerland"
frenchShortName = "Suisse (la)"
numeric = 756
japaneseShortName = "スイス"
[SY]
"Country Name" = "Syria"
ISO2 = "SY"
ISO3 = "SYR"
"Top Level Domain" = "sy"
FIPS = "SY"
"ISO Numeric" = 760
GeoNameID = 163_843
E164 = 963
"Phone Code" = 963
Continent = "Asia"
Capital = "Damascus"
"Time Zone in Capital" = "Asia/Damascus"
Currency = "Pound"
"Language Codes" = "ar-SY,ku,hy,arc,fr,en"
Languages = "Arabic (official), Kurdish, Armenian, Aramaic, Circassian (widely understood); French, English (somewhat understood)"
"Area KM2" = 185_180
"Internet Hosts" = 416
"Internet Users" = 4_469_000
"Phones (Mobile)" = 12_928_000
"Phones (Landline)" = 4_425_000
GDP = 64_700_000_000
englishShortName = "Syrian Arab Republic (the)"
frenchShortName = "République arabe syrienne (la)"
numeric = 760
japaneseShortName = "シリア"
[TW]
"Country Name" = "Taiwan"
ISO2 = "TW"
ISO3 = "TWN"
"Top Level Domain" = "tw"
FIPS = "TW"
"ISO Numeric" = 158
GeoNameID = 1_668_284
E164 = 886
"Phone Code" = 886
Continent = "Asia"
Capital = "Taipei"
"Time Zone in Capital" = "Asia/Taipei"
Currency = "Dollar"
"Language Codes" = "zh-TW,zh,nan,hak"
Languages = "Mandarin Chinese (official), Taiwanese (Min), Hakka dialects"
"Area KM2" = 35_980
"Internet Hosts" = 6_272_000
"Internet Users" = 16_147_000
"Phones (Mobile)" = 29_455_000
"Phones (Landline)" = 15_998_000
GDP = 484_700_000_000
englishShortName = "Taiwan (Province of China)"
frenchShortName = "Taïwan (Province de Chine)"
numeric = 158
japaneseShortName = "台湾"
[TJ]
"Country Name" = "Tajikistan"
ISO2 = "TJ"
ISO3 = "TJK"
"Top Level Domain" = "tj"
FIPS = "TI"
"ISO Numeric" = 762
GeoNameID = 1_220_409
E164 = 992
"Phone Code" = 992
Continent = "Asia"
Capital = "Dushanbe"
"Time Zone in Capital" = "Asia/Dushanbe"
Currency = "Somoni"
"Language Codes" = "tg,ru"
Languages = "Tajik (official), Russian widely used in government and business"
"Area KM2" = 143_100
"Internet Hosts" = 6_258
"Internet Users" = 700_000
"Phones (Mobile)" = 6_528_000
"Phones (Landline)" = 393_000
GDP = 8_513_000_000
englishShortName = "Tajikistan"
frenchShortName = "Tadjikistan (le)"
numeric = 762
japaneseShortName = "タジキスタン"
[TZ]
"Country Name" = "Tanzania"
ISO2 = "TZ"
ISO3 = "TZA"
"Top Level Domain" = "tz"
FIPS = "TZ"
"ISO Numeric" = 834
GeoNameID = 149_590
E164 = 255
"Phone Code" = 255
Continent = "Africa"
Capital = "Dodoma"
"Time Zone in Capital" = "Africa/Dar_es_Salaam"
Currency = "Shilling"
"Language Codes" = "sw-TZ,en,ar"
Languages = "Kiswahili or Swahili (official), Kiunguja (name for Swahili in Zanzibar), English (official, primary language of commerce, administration, and higher education), Arabic (widely spoken in Zanzibar), many local languages"
"Area KM2" = 945_087
"Internet Hosts" = 26_074
"Internet Users" = 678_000
"Phones (Mobile)" = 27_220_000
"Phones (Landline)" = 161_100
GDP = 31_940_000_000
englishShortName = "Tanzania, the United Republic of"
frenchShortName = "Tanzanie (la République-Unie de)"
numeric = 834
japaneseShortName = "タンザニア"
[TH]
"Country Name" = "Thailand"
ISO2 = "TH"
ISO3 = "THA"
"Top Level Domain" = "th"
FIPS = "TH"
"ISO Numeric" = 764
GeoNameID = 1_605_651
E164 = 66
"Phone Code" = 66
Continent = "Asia"
Capital = "Bangkok"
"Time Zone in Capital" = "Asia/Bangkok"
Currency = "Baht"
"Language Codes" = "th,en"
Languages = "Thai (official) 90.7%, Burmese 1.3%, other 8%"
"Area KM2" = 514_000
"Internet Hosts" = 3_399_000
"Internet Users" = 17_483_000
"Phones (Mobile)" = 84_075_000
"Phones (Landline)" = 6_391_000
GDP = 400_900_000_000
englishShortName = "Thailand"
frenchShortName = "Thaïlande (la)"
numeric = 764
japaneseShortName = "タイ"
[TG]
"Country Name" = "Togo"
ISO2 = "TG"
ISO3 = "TGO"
"Top Level Domain" = "tg"
FIPS = "TO"
"ISO Numeric" = 768
GeoNameID = 2_363_686
E164 = 228
"Phone Code" = 228
Continent = "Africa"
Capital = "Lome"
"Time Zone in Capital" = "Africa/Abidjan"
Currency = "Franc"
"Language Codes" = "fr-TG,ee,hna,kbp,dag,ha"
Languages = "French (official, the language of commerce), Ewe and Mina (the two major African languages in the south), Kabye (sometimes spelled Kabiye) and Dagomba (the two major African languages in the north)"
"Area KM2" = 56_785
"Internet Hosts" = 1_168
"Internet Users" = 356_300
"Phones (Mobile)" = 3_518_000
"Phones (Landline)" = 225_000
GDP = 4_299_000_000
englishShortName = "Togo"
frenchShortName = "Togo (le)"
numeric = 768
japaneseShortName = "トーゴ"
[TK]
"Country Name" = "Tokelau"
ISO2 = "TK"
ISO3 = "TKL"
"Top Level Domain" = "tk"
FIPS = "TL"
"ISO Numeric" = 772
GeoNameID = 4_031_074
E164 = 690
"Phone Code" = 690
Continent = "Oceania"
Capital = ""
"Time Zone in Capital" = "Pacific/Fakaofo"
Currency = "Dollar"
"Language Codes" = "tkl,en-TK"
Languages = "Tokelauan 93.5% (a Polynesian language), English 58.9%, Samoan 45.5%, Tuvaluan 11.6%, Kiribati 2.7%, other 2.5%, none 4.1%, unspecified 0.6%"
"Area KM2" = 10
"Internet Hosts" = 2_069
"Internet Users" = 800
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = ""
englishShortName = "Tokelau"
frenchShortName = "Tokelau (les)"
numeric = 772
japaneseShortName = "トケラウ"
[TO]
"Country Name" = "Tonga"
ISO2 = "TO"
ISO3 = "TON"
"Top Level Domain" = "to"
FIPS = "TN"
"ISO Numeric" = 776
GeoNameID = 4_032_283
E164 = 676
"Phone Code" = 676
Continent = "Oceania"
Capital = "Nuku'alofa"
"Time Zone in Capital" = "Pacific/Tongatapu"
Currency = "Pa'anga"
"Language Codes" = "to,en-TO"
Languages = "English and Tongan 87%, Tongan (official) 10.7%, English (official) 1.2%, other 1.1%, uspecified 0.03% (2006 est.)"
"Area KM2" = 748
"Internet Hosts" = 5_367
"Internet Users" = 8_400
"Phones (Mobile)" = 56_000
"Phones (Landline)" = 30_000
GDP = 477_000_000
englishShortName = "Tonga"
frenchShortName = "Tonga (les)"
numeric = 776
japaneseShortName = "トンガ王国"
[TT]
"Country Name" = "Trinidad and Tobago"
ISO2 = "TT"
ISO3 = "TTO"
"Top Level Domain" = "tt"
FIPS = "TD"
"ISO Numeric" = 780
GeoNameID = 3_573_591
E164 = 1
"Phone Code" = "1-868"
Continent = "North America"
Capital = "Port of Spain"
"Time Zone in Capital" = "America/Port_of_Spain"
Currency = "Dollar"
"Language Codes" = "en-TT,hns,fr,es,zh"
Languages = "English (official), Caribbean Hindustani (a dialect of Hindi), French, Spanish, Chinese"
"Area KM2" = 5_128
"Internet Hosts" = 241_690
"Internet Users" = 593_000
"Phones (Mobile)" = 1_884_000
"Phones (Landline)" = 287_000
GDP = 27_130_000_000
englishShortName = "Trinidad and Tobago"
frenchShortName = "Trinité-et-Tobago (la)"
numeric = 780
japaneseShortName = "トリニダード・トバゴ"
[TN]
"Country Name" = "Tunisia"
ISO2 = "TN"
ISO3 = "TUN"
"Top Level Domain" = "tn"
FIPS = "TS"
"ISO Numeric" = 788
GeoNameID = 2_464_461
E164 = 216
"Phone Code" = 216
Continent = "Africa"
Capital = "Tunis"
"Time Zone in Capital" = "Africa/Tunis"
Currency = "Dinar"
"Language Codes" = "ar-TN,fr"
Languages = "Arabic (official, one of the languages of commerce), French (commerce), Berber (Tamazight)"
"Area KM2" = 163_610
"Internet Hosts" = 576
"Internet Users" = 3_500_000
"Phones (Mobile)" = 12_840_000
"Phones (Landline)" = 1_105_000
GDP = 48_380_000_000
englishShortName = "Tunisia"
frenchShortName = "Tunisie (la)"
numeric = 788
japaneseShortName = "チュニジア"
[TR]
"Country Name" = "Turkey"
ISO2 = "TR"
ISO3 = "TUR"
"Top Level Domain" = "tr"
FIPS = "TU"
"ISO Numeric" = 792
GeoNameID = 298_795
E164 = 90
"Phone Code" = 90
Continent = "Asia"
Capital = "Ankara"
"Time Zone in Capital" = "Europe/Istanbul"
Currency = "Lira"
"Language Codes" = "tr-TR,ku,diq,az,av"
Languages = "Turkish (official), Kurdish, other minority languages"
"Area KM2" = 780_580
"Internet Hosts" = 7_093_000
"Internet Users" = 27_233_000
"Phones (Mobile)" = 67_680_000
"Phones (Landline)" = 13_860_000
GDP = 821_800_000_000
englishShortName = "Turkey"
frenchShortName = "Turquie (la)"
numeric = 792
japaneseShortName = "トルコ"
[TM]
"Country Name" = "Turkmenistan"
ISO2 = "TM"
ISO3 = "TKM"
"Top Level Domain" = "tm"
FIPS = "TX"
"ISO Numeric" = 795
GeoNameID = 1_218_197
E164 = 993
"Phone Code" = 993
Continent = "Asia"
Capital = "Ashgabat"
"Time Zone in Capital" = "Asia/Ashgabat"
Currency = "Manat"
"Language Codes" = "tk,ru,uz"
Languages = "Turkmen (official) 72%, Russian 12%, Uzbek 9%, other 7%"
"Area KM2" = 488_100
"Internet Hosts" = 714
"Internet Users" = 80_400
"Phones (Mobile)" = 3_953_000
"Phones (Landline)" = 575_000
GDP = 40_560_000_000
englishShortName = "Turkmenistan"
frenchShortName = "Turkménistan (le)"
numeric = 795
japaneseShortName = "トルクメニスタン"
[TC]
"Country Name" = "Turks and Caicos Islands"
ISO2 = "TC"
ISO3 = "TCA"
"Top Level Domain" = "tc"
FIPS = "TK"
"ISO Numeric" = 796
GeoNameID = 3_576_916
E164 = 1
"Phone Code" = "1-649"
Continent = "North America"
Capital = "Cockburn Town"
"Time Zone in Capital" = "America/Grand_Turk"
Currency = "Dollar"
"Language Codes" = "en-TC"
Languages = "English (official)"
"Area KM2" = 430
"Internet Hosts" = 73_217
"Internet Users" = ""
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = ""
englishShortName = "Turks and Caicos Islands (the)"
frenchShortName = "Turks-et-Caïcos (les Îles)"
numeric = 796
japaneseShortName = "タークス・カイコス諸島"
[TV]
"Country Name" = "Tuvalu"
ISO2 = "TV"
ISO3 = "TUV"
"Top Level Domain" = "tv"
FIPS = "TV"
"ISO Numeric" = 798
GeoNameID = 2_110_297
E164 = 688
"Phone Code" = 688
Continent = "Oceania"
Capital = "Funafuti"
"Time Zone in Capital" = "Pacific/Funafuti"
Currency = "Dollar"
"Language Codes" = "tvl,en,sm,gil"
Languages = "Tuvaluan (official), English (official), Samoan, Kiribati (on the island of Nui)"
"Area KM2" = 26
"Internet Hosts" = 145_158
"Internet Users" = 4_200
"Phones (Mobile)" = 2_800
"Phones (Landline)" = 1_450
GDP = 38_000_000
englishShortName = "Tuvalu"
frenchShortName = "Tuvalu (les)"
numeric = 798
japaneseShortName = "ツバル"
[VI]
"Country Name" = "U.S. Virgin Islands"
ISO2 = "VI"
ISO3 = "VIR"
"Top Level Domain" = "vi"
FIPS = "VQ"
"ISO Numeric" = 850
GeoNameID = 4_796_775
E164 = 1
"Phone Code" = "1-340"
Continent = "North America"
Capital = "Charlotte Amalie"
"Time Zone in Capital" = "America/Port_of_Spain"
Currency = "Dollar"
"Language Codes" = "en-VI"
Languages = "English 74.7%, Spanish or Spanish Creole 16.8%, French or French Creole 6.6%, other 1.9% (2000 census)"
"Area KM2" = 352
"Internet Hosts" = 4_790
"Internet Users" = 30_000
"Phones (Mobile)" = 80_300
"Phones (Landline)" = 75_800
GDP = ""
englishShortName = "Virgin Islands (U.S.)"
frenchShortName = "Vierges des États-Unis (les Îles)"
numeric = 850
japaneseShortName = "アメリカ領ヴァージン諸島"
[UG]
"Country Name" = "Uganda"
ISO2 = "UG"
ISO3 = "UGA"
"Top Level Domain" = "ug"
FIPS = "UG"
"ISO Numeric" = 800
GeoNameID = 226_074
E164 = 256
"Phone Code" = 256
Continent = "Africa"
Capital = "Kampala"
"Time Zone in Capital" = "Africa/Kampala"
Currency = "Shilling"
"Language Codes" = "en-UG,lg,sw,ar"
Languages = "English (official national language, taught in grade schools, used in courts of law and by most newspapers and some radio broadcasts), Ganda or Luganda (most widely used of the Niger-Congo languages, preferred for native language publications in the capital and may be taught in school), other Niger-Congo languages, Nilo-Saharan languages, Swahili, Arabic"
"Area KM2" = 236_040
"Internet Hosts" = 32_683
"Internet Users" = 3_200_000
"Phones (Mobile)" = 16_355_000
"Phones (Landline)" = 315_000
GDP = 22_600_000_000
englishShortName = "Uganda"
frenchShortName = "Ouganda (l')"
numeric = 800
japaneseShortName = "ウガンダ"
[UA]
"Country Name" = "Ukraine"
ISO2 = "UA"
ISO3 = "UKR"
"Top Level Domain" = "ua"
FIPS = "UP"
"ISO Numeric" = 804
GeoNameID = 690_791
E164 = 380
"Phone Code" = 380
Continent = "Europe"
Capital = "Kiev"
"Time Zone in Capital" = "Europe/Kiev"
Currency = "Hryvnia"
"Language Codes" = "uk,ru-UA,rom,pl,hu"
Languages = "Ukrainian (official) 67%, Russian (regional language) 24%, other (includes small Romanian-, Polish-, and Hungarian-speaking minorities) 9%"
"Area KM2" = 603_700
"Internet Hosts" = 2_173_000
"Internet Users" = 7_770_000
"Phones (Mobile)" = 59_344_000
"Phones (Landline)" = 12_182_000
GDP = 175_500_000_000
englishShortName = "Ukraine"
frenchShortName = "Ukraine (l')"
numeric = 804
japaneseShortName = "ウクライナ"
[AE]
"Country Name" = "United Arab Emirates"
ISO2 = "AE"
ISO3 = "ARE"
"Top Level Domain" = "ae"
FIPS = "AE"
"ISO Numeric" = 784
GeoNameID = 290_557
E164 = 971
"Phone Code" = 971
Continent = "Asia"
Capital = "Abu Dhabi"
"Time Zone in Capital" = "Asia/Dubai"
Currency = "Dirham"
"Language Codes" = "ar-AE,fa,en,hi,ur"
Languages = "Arabic (official), Persian, English, Hindi, Urdu"
"Area KM2" = 82_880
"Internet Hosts" = 337_804
"Internet Users" = 3_449_000
"Phones (Mobile)" = 13_775_000
"Phones (Landline)" = 1_967_000
GDP = 390_000_000_000
englishShortName = "United Arab Emirates (the)"
frenchShortName = "Émirats arabes unis (les)"
numeric = 784
japaneseShortName = "アラブ首長国連邦"
[GB]
"Country Name" = "United Kingdom"
ISO2 = "GB"
ISO3 = "GBR"
"Top Level Domain" = "uk"
FIPS = "UK"
"ISO Numeric" = 826
GeoNameID = 2_635_167
E164 = 44
"Phone Code" = 44
Continent = "Europe"
Capital = "London"
"Time Zone in Capital" = "Europe/London"
Currency = "Pound"
"Language Codes" = "en-GB,cy-GB,gd"
Languages = "English"
"Area KM2" = 244_820
"Internet Hosts" = 8_107_000
"Internet Users" = 51_444_000
"Phones (Mobile)" = 82_109_000
"Phones (Landline)" = 33_010_000
GDP = 2_490_000_000_000
englishShortName = "United Kingdom of Great Britain and Northern Ireland (the)"
frenchShortName = "Royaume-Uni de Grande-Bretagne et d'Irlande du Nord (le)"
numeric = 826
japaneseShortName = "イギリス"
[US]
"Country Name" = "United States"
ISO2 = "US"
ISO3 = "USA"
"Top Level Domain" = "us"
FIPS = "US"
"ISO Numeric" = 840
GeoNameID = 6_252_001
E164 = 1
"Phone Code" = 1
Continent = "North America"
Capital = "Washington"
"Time Zone in Capital" = "America/New_York"
Currency = "Dollar"
"Language Codes" = "en-US,es-US,haw,fr"
Languages = "English 82.1%, Spanish 10.7%, other Indo-European 3.8%, Asian and Pacific island 2.7%, other 0.7% (2000 census)"
"Area KM2" = 9_629_091
"Internet Hosts" = 505_000_000
"Internet Users" = 245_000_000
"Phones (Mobile)" = 310_000_000
"Phones (Landline)" = 139_000_000
GDP = 16_720_000_000_000
englishShortName = "United States of America (the)"
frenchShortName = "États-Unis d'Amérique (les)"
numeric = 840
japaneseShortName = "アメリカ合衆国"
[UY]
"Country Name" = "Uruguay"
ISO2 = "UY"
ISO3 = "URY"
"Top Level Domain" = "uy"
FIPS = "UY"
"ISO Numeric" = 858
GeoNameID = 3_439_705
E164 = 598
"Phone Code" = 598
Continent = "South America"
Capital = "Montevideo"
"Time Zone in Capital" = "America/Montevideo"
Currency = "Peso"
"Language Codes" = "es-UY"
Languages = "Spanish (official), Portunol, Brazilero (Portuguese-Spanish mix on the Brazilian frontier)"
"Area KM2" = 176_220
"Internet Hosts" = 1_036_000
"Internet Users" = 1_405_000
"Phones (Mobile)" = 5_000_000
"Phones (Landline)" = 1_010_000
GDP = 57_110_000_000
englishShortName = "Uruguay"
frenchShortName = "Uruguay (l')"
numeric = 858
japaneseShortName = "ウルグアイ"
[UZ]
"Country Name" = "Uzbekistan"
ISO2 = "UZ"
ISO3 = "UZB"
"Top Level Domain" = "uz"
FIPS = "UZ"
"ISO Numeric" = 860
GeoNameID = 1_512_440
E164 = 998
"Phone Code" = 998
Continent = "Asia"
Capital = "Tashkent"
"Time Zone in Capital" = "Asia/Tashkent"
Currency = "Som"
"Language Codes" = "uz,ru,tg"
Languages = "Uzbek (official) 74.3%, Russian 14.2%, Tajik 4.4%, other 7.1%"
"Area KM2" = 447_400
"Internet Hosts" = 56_075
"Internet Users" = 4_689_000
"Phones (Mobile)" = 20_274_000
"Phones (Landline)" = 1_963_000
GDP = 55_180_000_000
englishShortName = "Uzbekistan"
frenchShortName = "Ouzbékistan (l')"
numeric = 860
japaneseShortName = "ウズベキスタン"
[VU]
"Country Name" = "Vanuatu"
ISO2 = "VU"
ISO3 = "VUT"
"Top Level Domain" = "vu"
FIPS = "NH"
"ISO Numeric" = 548
GeoNameID = 2_134_431
E164 = 678
"Phone Code" = 678
Continent = "Oceania"
Capital = "Port Vila"
"Time Zone in Capital" = "Pacific/Efate"
Currency = "Vatu"
"Language Codes" = "bi,en-VU,fr-VU"
Languages = "local languages (more than 100) 63.2%, Bislama (official; creole) 33.7%, English (official) 2%, French (official) 0.6%, other 0.5% (2009 est.)"
"Area KM2" = 12_200
"Internet Hosts" = 5_655
"Internet Users" = 17_000
"Phones (Mobile)" = 137_000
"Phones (Landline)" = 5_800
GDP = 828_000_000
englishShortName = "Vanuatu"
frenchShortName = "Vanuatu (le)"
numeric = 548
japaneseShortName = "バヌアツ"
[VA]
"Country Name" = "Vatican"
ISO2 = "VA"
ISO3 = "VAT"
"Top Level Domain" = "va"
FIPS = "VT"
"ISO Numeric" = 336
GeoNameID = 3_164_670
E164 = 39
"Phone Code" = 379
Continent = "Europe"
Capital = "Vatican City"
"Time Zone in Capital" = "Europe/Rome"
Currency = "Euro"
"Language Codes" = "la,it,fr"
Languages = "Latin, Italian, French"
"Area KM2" = 0
"Internet Hosts" = ""
"Internet Users" = ""
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = ""
englishShortName = "Holy See (the)"
frenchShortName = "Saint-Siège (le)"
numeric = 336
japaneseShortName = "バチカン市国"
[VE]
"Country Name" = "Venezuela"
ISO2 = "VE"
ISO3 = "VEN"
"Top Level Domain" = "ve"
FIPS = "VE"
"ISO Numeric" = 862
GeoNameID = 3_625_428
E164 = 58
"Phone Code" = 58
Continent = "South America"
Capital = "Caracas"
"Time Zone in Capital" = "America/Caracas"
Currency = "Bolivar"
"Language Codes" = "es-VE"
Languages = "Spanish (official), numerous indigenous dialects"
"Area KM2" = 912_050
"Internet Hosts" = 1_016_000
"Internet Users" = 8_918_000
"Phones (Mobile)" = 30_520_000
"Phones (Landline)" = 7_650_000
GDP = 367_500_000_000
englishShortName = "Venezuela (Bolivarian Republic of)"
frenchShortName = "Venezuela (République bolivarienne du)"
numeric = 862
japaneseShortName = "ベネズエラ"
[VN]
"Country Name" = "Vietnam"
ISO2 = "VN"
ISO3 = "VNM"
"Top Level Domain" = "vn"
FIPS = "VM"
"ISO Numeric" = 704
GeoNameID = 1_562_822
E164 = 84
"Phone Code" = 84
Continent = "Asia"
Capital = "Hanoi"
"Time Zone in Capital" = "Asia/Ho_Chi_Minh"
Currency = "Dong"
"Language Codes" = "vi,en,fr,zh,km"
Languages = "Vietnamese (official), English (increasingly favored as a second language), some French, Chinese, and Khmer, mountain area languages (Mon-Khmer and Malayo-Polynesian)"
"Area KM2" = 329_560
"Internet Hosts" = 189_553
"Internet Users" = 23_382_000
"Phones (Mobile)" = 134_066_000
"Phones (Landline)" = 10_191_000
GDP = 170_000_000_000
englishShortName = "Viet Nam"
frenchShortName = "Viet Nam (le)"
numeric = 704
japaneseShortName = "ベトナム"
[WF]
"Country Name" = "Wallis and Futuna"
ISO2 = "WF"
ISO3 = "WLF"
"Top Level Domain" = "wf"
FIPS = "WF"
"ISO Numeric" = 876
GeoNameID = 4_034_749
E164 = 681
"Phone Code" = 681
Continent = "Oceania"
Capital = "Mata Utu"
"Time Zone in Capital" = "Pacific/Wallis"
Currency = "Franc"
"Language Codes" = "wls,fud,fr-WF"
Languages = "Wallisian (indigenous Polynesian language) 58.9%, Futunian 30.1%, French (official) 10.8%, other 0.2% (2003 census)"
"Area KM2" = 274
"Internet Hosts" = 2_760
"Internet Users" = 1_300
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = ""
englishShortName = "Wallis and Futuna"
frenchShortName = "Wallis-et-Futuna"
numeric = 876
japaneseShortName = "ウォリス・フツナ"
[EH]
"Country Name" = "Western Sahara"
ISO2 = "EH"
ISO3 = "ESH"
"Top Level Domain" = "eh"
FIPS = "WI"
"ISO Numeric" = 732
GeoNameID = 2_461_445
E164 = 212
"Phone Code" = 212
Continent = "Africa"
Capital = "El-Aaiun"
"Time Zone in Capital" = "Africa/El_Aaiun"
Currency = "Dirham"
"Language Codes" = "ar,mey"
Languages = "Standard Arabic (national), Hassaniya Arabic, Moroccan Arabic"
"Area KM2" = 266_000
"Internet Hosts" = ""
"Internet Users" = ""
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = ""
englishShortName = "Western Sahara*"
frenchShortName = "Sahara occidental (le)*"
numeric = 732
japaneseShortName = "西サハラ"
[YE]
"Country Name" = "Yemen"
ISO2 = "YE"
ISO3 = "YEM"
"Top Level Domain" = "ye"
FIPS = "YM"
"ISO Numeric" = 887
GeoNameID = 69_543
E164 = 967
"Phone Code" = 967
Continent = "Asia"
Capital = "Sanaa"
"Time Zone in Capital" = "Asia/Aden"
Currency = "Rial"
"Language Codes" = "ar-YE"
Languages = "Arabic (official)"
"Area KM2" = 527_970
"Internet Hosts" = 33_206
"Internet Users" = 2_349_000
"Phones (Mobile)" = 13_900_000
"Phones (Landline)" = 1_100_000
GDP = 43_890_000_000
englishShortName = "Yemen"
frenchShortName = "Yémen (le)"
numeric = 887
japaneseShortName = "イエメン"
[ZM]
"Country Name" = "Zambia"
ISO2 = "ZM"
ISO3 = "ZMB"
"Top Level Domain" = "zm"
FIPS = "ZA"
"ISO Numeric" = 894
GeoNameID = 895_949
E164 = 260
"Phone Code" = 260
Continent = "Africa"
Capital = "Lusaka"
"Time Zone in Capital" = "Africa/Maputo"
Currency = "Kwacha"
"Language Codes" = "en-ZM,bem,loz,lun,lue,ny,toi"
Languages = "Bembe 33.4%, Nyanja 14.7%, Tonga 11.4%, Lozi 5.5%, Chewa 4.5%, Nsenga 2.9%, Tumbuka 2.5%, Lunda (North Western) 1.9%, Kaonde 1.8%, Lala 1.8%, Lamba 1.8%, English (official) 1.7%, Luvale 1.5%, Mambwe 1.3%, Namwanga 1.2%, Lenje 1.1%, Bisa 1%, other 9.2%, unspecified 0.4%"
"Area KM2" = 752_614
"Internet Hosts" = 16_571
"Internet Users" = 816_200
"Phones (Mobile)" = 10_525_000
"Phones (Landline)" = 82_500
GDP = 22_240_000_000
englishShortName = "Zambia"
frenchShortName = "Zambie (la)"
numeric = 894
japaneseShortName = "ザンビア"
[ZW]
"Country Name" = "Zimbabwe"
ISO2 = "ZW"
ISO3 = "ZWE"
"Top Level Domain" = "zw"
FIPS = "ZI"
"ISO Numeric" = 716
GeoNameID = 878_675
E164 = 263
"Phone Code" = 263
Continent = "Africa"
Capital = "Harare"
"Time Zone in Capital" = "Africa/Maputo"
Currency = "Dollar"
"Language Codes" = "en-ZW,sn,nr,nd"
Languages = "English (official), Shona, Sindebele (the language of the Ndebele, sometimes called Ndebele), numerous but minor tribal dialects"
"Area KM2" = 390_580
"Internet Hosts" = 30_615
"Internet Users" = 1_423_000
"Phones (Mobile)" = 12_614_000
"Phones (Landline)" = 301_600
GDP = 10_480_000_000
englishShortName = "Zimbabwe"
frenchShortName = "Zimbabwe (le)"
numeric = 716
japaneseShortName = "ジンバブエ"
[AX]
"Country Name" = "Aland Islands"
englishShortName = "Åland Islands"
frenchShortName = "Åland(les Îles)"
numeric = 248
japaneseShortName = "アランド諸島"
[BV]
"Country Name" = "Bouvet Island"
englishShortName = "Bouvet Island"
frenchShortName = "Bouvet (l'Île)"
numeric = 74
japaneseShortName = "ブーベ島"
[GF]
"Country Name" = "French Guiana"
englishShortName = "French Guiana"
frenchShortName = "Guyane française (la )"
numeric = 254
japaneseShortName = "フランス領ギアナ"
[TF]
"Country Name" = "French Southern Territories"
englishShortName = "French Southern Territories (the)"
frenchShortName = "Terres australes françaises (les)"
numeric = 260
japaneseShortName = "フランス領南方領土"
[GP]
"Country Name" = "Guadeloupe"
englishShortName = "Guadeloupe"
frenchShortName = "Guadeloupe (la)"
numeric = 312
japaneseShortName = "グアドループ島"
[HM]
"Country Name" = "Heard Island & Mcdonald Islands"
englishShortName = "Heard Island and McDonald Islands"
frenchShortName = "Heard-et-Îles MacDonald (l'Île)"
numeric = 334
japaneseShortName = "ハード島とマクドナルド諸島"
[MQ]
"Country Name" = "Martinique"
englishShortName = "Martinique"
frenchShortName = "Martinique (la)"
numeric = 474
japaneseShortName = "マルティニーク"
[NF]
"Country Name" = "Norfolk Island"
englishShortName = "Norfolk Island"
frenchShortName = "Norfolk (l'Île)"
numeric = 574
japaneseShortName = "ノーフォーク島"
[GS]
"Country Name" = "South Georgia And Sandwich Isl."
englishShortName = "South Georgia and the South Sandwich Islands"
frenchShortName = "Géorgie du Sud-et-les Îles Sandwich du Sud (la)"
numeric = 239
japaneseShortName = "サウスジョージア・サウスサンドウィッチ諸島"
[UM]
"Country Name" = "United States Outlying Islands"
englishShortName = "United States Minor Outlying Islands (the)"
frenchShortName = "Îles mineures éloignées des États-Unis (les)"
numeric = 581
japaneseShortName = "合衆国領有小離島"
5.4 - Leetcode submissions
5.5 - License
5.6 - Mullvad
Relays
Update relay data:
bazel run //data/mullvad:update_relays
Show active servers
cat data/mullvad/relays.json | jq -r ".wireguard.relays[] | select(.active) | .hostname"
{
"locations": {
"au-adl": {
"country": "Australia",
"city": "Adelaide",
"latitude": -34.92123,
"longitude": 138.599503
},
"nl-ams": {
"country": "Netherlands",
"city": "Amsterdam",
"latitude": 52.35,
"longitude": 4.916667
},
"us-qas": {
"country": "USA",
"city": "Ashburn, VA",
"latitude": 39.043757,
"longitude": -77.487442
},
"gr-ath": {
"country": "Greece",
"city": "Athens",
"latitude": 37.98381,
"longitude": 23.727539
},
"us-atl": {
"country": "USA",
"city": "Atlanta, GA",
"latitude": 33.753746,
"longitude": -84.38633
},
"nz-akl": {
"country": "New Zealand",
"city": "Auckland",
"latitude": -36.848461,
"longitude": 174.763336
},
"th-bkk": {
"country": "Thailand",
"city": "Bangkok",
"latitude": 13.756331,
"longitude": 100.501762
},
"es-bcn": {
"country": "Spain",
"city": "Barcelona",
"latitude": 41.385063,
"longitude": 2.173404
},
"rs-beg": {
"country": "Serbia",
"city": "Belgrade",
"latitude": 44.787197,
"longitude": 20.457273
},
"de-ber": {
"country": "Germany",
"city": "Berlin",
"latitude": 52.520008,
"longitude": 13.404954
},
"co-bog": {
"country": "Colombia",
"city": "Bogota",
"latitude": 4.624335,
"longitude": -74.063644
},
"fr-bod": {
"country": "France",
"city": "Bordeaux",
"latitude": 44.837788,
"longitude": -0.57918
},
"us-bos": {
"country": "USA",
"city": "Boston, MA",
"latitude": 42.361145,
"longitude": -71.057083
},
"sk-bts": {
"country": "Slovakia",
"city": "Bratislava",
"latitude": 48.148598,
"longitude": 17.107748
},
"au-bne": {
"country": "Australia",
"city": "Brisbane",
"latitude": -27.471,
"longitude": 153.0234
},
"be-bru": {
"country": "Belgium",
"city": "Brussels",
"latitude": 50.833333,
"longitude": 4.333333
},
"ro-buh": {
"country": "Romania",
"city": "Bucharest",
"latitude": 44.433333,
"longitude": 26.1
},
"hu-bud": {
"country": "Hungary",
"city": "Budapest",
"latitude": 47.5,
"longitude": 19.083333
},
"ar-bue": {
"country": "Argentina",
"city": "Buenos Aires",
"latitude": -34.474561,
"longitude": -58.664522
},
"ca-yyc": {
"country": "Canada",
"city": "Calgary",
"latitude": 51.037007,
"longitude": -114.058315
},
"us-chi": {
"country": "USA",
"city": "Chicago, IL",
"latitude": 41.881832,
"longitude": -87.623177
},
"dk-cph": {
"country": "Denmark",
"city": "Copenhagen",
"latitude": 55.666667,
"longitude": 12.583333
},
"us-dal": {
"country": "USA",
"city": "Dallas, TX",
"latitude": 32.89748,
"longitude": -97.040443
},
"us-den": {
"country": "USA",
"city": "Denver, CO",
"latitude": 39.739236,
"longitude": -104.990251
},
"us-det": {
"country": "USA",
"city": "Detroit, MI",
"latitude": 42.331389,
"longitude": -83.045833
},
"ie-dub": {
"country": "Ireland",
"city": "Dublin",
"latitude": 53.35014,
"longitude": -6.266155
},
"de-dus": {
"country": "Germany",
"city": "Dusseldorf",
"latitude": 51.233334,
"longitude": 6.783333
},
"br-for": {
"country": "Brazil",
"city": "Fortaleza",
"latitude": -3.732714,
"longitude": -38.526997
},
"de-fra": {
"country": "Germany",
"city": "Frankfurt",
"latitude": 50.110924,
"longitude": 8.682127
},
"gb-glw": {
"country": "UK",
"city": "Glasgow",
"latitude": 55.86515,
"longitude": -4.25763
},
"se-got": {
"country": "Sweden",
"city": "Gothenburg",
"latitude": 57.70887,
"longitude": 11.97456
},
"fi-hel": {
"country": "Finland",
"city": "Helsinki",
"latitude": 60.192059,
"longitude": 24.945831
},
"hk-hkg": {
"country": "Hong Kong",
"city": "Hong Kong",
"latitude": 22.283333,
"longitude": 114.15
},
"us-hou": {
"country": "USA",
"city": "Houston, TX",
"latitude": 29.749907,
"longitude": -95.358421
},
"tr-ist": {
"country": "Turkey",
"city": "Istanbul",
"latitude": 41.00824,
"longitude": 28.978359
},
"id-jpu": {
"country": "Indonesia",
"city": "Jakarta",
"latitude": -6.17511,
"longitude": 106.865036
},
"za-jnb": {
"country": "South Africa",
"city": "Johannesburg",
"latitude": -26.195246,
"longitude": 28.034088
},
"us-mkc": {
"country": "USA",
"city": "Kansas City, MO",
"latitude": 39.099789,
"longitude": -94.57856
},
"my-kul": {
"country": "Malaysia",
"city": "Kuala Lumpur",
"latitude": 3.139003,
"longitude": 101.686852
},
"ua-iev": {
"country": "Ukraine",
"city": "Kyiv",
"latitude": 50.4501,
"longitude": 30.5234
},
"ng-los": {
"country": "Nigeria",
"city": "Lagos",
"latitude": 6.524379,
"longitude": 3.379206
},
"pe-lim": {
"country": "Peru",
"city": "Lima",
"latitude": -12.046373,
"longitude": -77.042755
},
"pt-lis": {
"country": "Portugal",
"city": "Lisbon",
"latitude": 38.736946,
"longitude": -9.142685
},
"si-lju": {
"country": "Slovenia",
"city": "Ljubljana",
"latitude": 46.0569,
"longitude": 14.5057
},
"gb-lon": {
"country": "UK",
"city": "London",
"latitude": 51.514125,
"longitude": -0.093689
},
"us-lax": {
"country": "USA",
"city": "Los Angeles, CA",
"latitude": 34.052235,
"longitude": -118.243683
},
"es-mad": {
"country": "Spain",
"city": "Madrid",
"latitude": 40.408566,
"longitude": -3.69222
},
"se-mma": {
"country": "Sweden",
"city": "Malmö",
"latitude": 55.607075,
"longitude": 13.002716
},
"gb-mnc": {
"country": "UK",
"city": "Manchester",
"latitude": 53.5,
"longitude": -2.216667
},
"ph-mnl": {
"country": "Philippines",
"city": "Manila",
"latitude": 14.599512,
"longitude": 120.984222
},
"fr-mrs": {
"country": "France",
"city": "Marseille",
"latitude": 43.29648,
"longitude": 5.38107
},
"us-txc": {
"country": "USA",
"city": "McAllen, TX",
"latitude": 26.203407,
"longitude": -98.230011
},
"au-mel": {
"country": "Australia",
"city": "Melbourne",
"latitude": -37.815018,
"longitude": 144.946014
},
"us-mia": {
"country": "USA",
"city": "Miami, FL",
"latitude": 25.761681,
"longitude": -80.191788
},
"it-mil": {
"country": "Italy",
"city": "Milan",
"latitude": 45.466667,
"longitude": 9.2
},
"ca-mtr": {
"country": "Canada",
"city": "Montreal",
"latitude": 45.5053,
"longitude": -73.5525
},
"us-nyc": {
"country": "USA",
"city": "New York, NY",
"latitude": 40.73061,
"longitude": -73.935242
},
"cy-nic": {
"country": "Cyprus",
"city": "Nicosia",
"latitude": 35.17025,
"longitude": 33.3587
},
"jp-osa": {
"country": "Japan",
"city": "Osaka",
"latitude": 34.672314,
"longitude": 135.484802
},
"no-osl": {
"country": "Norway",
"city": "Oslo",
"latitude": 59.916667,
"longitude": 10.75
},
"it-pmo": {
"country": "Italy",
"city": "Palermo",
"latitude": 38.115688,
"longitude": 13.361267
},
"fr-par": {
"country": "France",
"city": "Paris",
"latitude": 48.866667,
"longitude": 2.333333
},
"au-per": {
"country": "Australia",
"city": "Perth",
"latitude": -31.953512,
"longitude": 115.857048
},
"us-phx": {
"country": "USA",
"city": "Phoenix, AZ",
"latitude": 33.448376,
"longitude": -112.074036
},
"cz-prg": {
"country": "Czech Republic",
"city": "Prague",
"latitude": 50.083333,
"longitude": 14.466667
},
"mx-qro": {
"country": "Mexico",
"city": "Queretaro",
"latitude": 20.592774,
"longitude": -100.390225
},
"us-rag": {
"country": "USA",
"city": "Raleigh, NC",
"latitude": 35.787743,
"longitude": -78.644257
},
"us-slc": {
"country": "USA",
"city": "Salt Lake City, UT",
"latitude": 40.758701,
"longitude": -111.876183
},
"us-sfo": {
"country": "USA",
"city": "San Francisco, CA",
"latitude": 37.723459,
"longitude": -122.397957
},
"us-sjc": {
"country": "USA",
"city": "San Jose, CA",
"latitude": 37.338208,
"longitude": -121.886329
},
"cl-scl": {
"country": "Chile",
"city": "Santiago",
"latitude": -33.448891,
"longitude": -70.669266
},
"br-sao": {
"country": "Brazil",
"city": "Sao Paulo",
"latitude": -23.533773,
"longitude": -46.62529
},
"us-sea": {
"country": "USA",
"city": "Seattle, WA",
"latitude": 47.608013,
"longitude": -122.335167
},
"us-uyk": {
"country": "USA",
"city": "Secaucus, NJ",
"latitude": 40.789543,
"longitude": -74.0565
},
"sg-sin": {
"country": "Singapore",
"city": "Singapore",
"latitude": 1.293056,
"longitude": 103.855833
},
"bg-sof": {
"country": "Bulgaria",
"city": "Sofia",
"latitude": 42.683333,
"longitude": 23.316667
},
"no-svg": {
"country": "Norway",
"city": "Stavanger",
"latitude": 58.964432,
"longitude": 5.72625
},
"se-sto": {
"country": "Sweden",
"city": "Stockholm",
"latitude": 59.3289,
"longitude": 18.0649
},
"au-syd": {
"country": "Australia",
"city": "Sydney",
"latitude": -33.861481,
"longitude": 151.205475
},
"ee-tll": {
"country": "Estonia",
"city": "Tallinn",
"latitude": 59.436961,
"longitude": 24.753575
},
"il-tlv": {
"country": "Israel",
"city": "Tel Aviv",
"latitude": 32.0853,
"longitude": 34.781768
},
"al-tia": {
"country": "Albania",
"city": "Tirana",
"latitude": 41.327953,
"longitude": 19.819025
},
"jp-tyo": {
"country": "Japan",
"city": "Tokyo",
"latitude": 35.685,
"longitude": 139.751389
},
"ca-tor": {
"country": "Canada",
"city": "Toronto",
"latitude": 43.666667,
"longitude": -79.416667
},
"es-vlc": {
"country": "Spain",
"city": "Valencia",
"latitude": 39.466667,
"longitude": -0.375
},
"ca-van": {
"country": "Canada",
"city": "Vancouver",
"latitude": 49.25,
"longitude": -123.133333
},
"at-vie": {
"country": "Austria",
"city": "Vienna",
"latitude": 48.210033,
"longitude": 16.363449
},
"pl-waw": {
"country": "Poland",
"city": "Warsaw",
"latitude": 52.25,
"longitude": 21.0
},
"us-was": {
"country": "USA",
"city": "Washington DC",
"latitude": 38.889484,
"longitude": -77.035278
},
"hr-zag": {
"country": "Croatia",
"city": "Zagreb",
"latitude": 45.821,
"longitude": 15.973
},
"ch-zrh": {
"country": "Switzerland",
"city": "Zurich",
"latitude": 47.366667,
"longitude": 8.55
}
},
"openvpn": {
"relays": [],
"ports": [
{
"port": 1194,
"protocol": "udp"
},
{
"port": 1195,
"protocol": "udp"
},
{
"port": 1196,
"protocol": "udp"
},
{
"port": 1197,
"protocol": "udp"
},
{
"port": 1300,
"protocol": "udp"
},
{
"port": 1301,
"protocol": "udp"
},
{
"port": 1302,
"protocol": "udp"
},
{
"port": 443,
"protocol": "tcp"
},
{
"port": 80,
"protocol": "tcp"
}
]
},
"wireguard": {
"relays": [
{
"hostname": "al-tia-wg-001",
"location": "al-tia",
"active": true,
"owned": false,
"provider": "iRegister",
"stboot": true,
"ipv4_addr_in": "103.124.165.2",
"include_in_country": true,
"weight": 100,
"public_key": "ofyfRvMPB0PPIGGItNL+5tNdvTKXuWye5CfjPgPNvQ8=",
"ipv6_addr_in": "2a04:27c0:0:e::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"103.124.165.17",
"103.124.165.18",
"103.124.165.19",
"103.124.165.20",
"103.124.165.21",
"103.124.165.22",
"103.124.165.23",
"103.124.165.24",
"103.124.165.25",
"103.124.165.26",
"103.124.165.27",
"2a04:27c0:0:e::b002",
"2a04:27c0:0:e::b003",
"2a04:27c0:0:e::b004",
"2a04:27c0:0:e::b005",
"2a04:27c0:0:e::b006",
"2a04:27c0:0:e::b007",
"2a04:27c0:0:e::b008",
"2a04:27c0:0:e::b009",
"2a04:27c0:0:e::b00a",
"2a04:27c0:0:e::b00b",
"2a04:27c0:0:e::b00c",
"2a04:27c0:0:e::b00d",
"2a04:27c0:0:e::b00e",
"2a04:27c0:0:e::b00f",
"2a04:27c0:0:e::b010",
"2a04:27c0:0:e::b011",
"2a04:27c0:0:e::b012",
"2a04:27c0:0:e::b013",
"2a04:27c0:0:e::b014",
"2a04:27c0:0:e::b015",
"2a04:27c0:0:e::b016",
"2a04:27c0:0:e::b017",
"2a04:27c0:0:e::b018",
"2a04:27c0:0:e::b019",
"2a04:27c0:0:e::b01a",
"2a04:27c0:0:e::b01b",
"2a04:27c0:0:e::b01c",
"2a04:27c0:0:e::b01d",
"2a04:27c0:0:e::b01e",
"2a04:27c0:0:e::b01f"
],
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"103.124.165.6",
"103.124.165.7",
"103.124.165.8",
"103.124.165.9",
"103.124.165.10",
"103.124.165.11",
"103.124.165.12",
"103.124.165.13",
"103.124.165.14",
"103.124.165.15",
"103.124.165.16",
"2a04:27c0:0:e::c002",
"2a04:27c0:0:e::c003",
"2a04:27c0:0:e::c004",
"2a04:27c0:0:e::c005",
"2a04:27c0:0:e::c006",
"2a04:27c0:0:e::c007",
"2a04:27c0:0:e::c008",
"2a04:27c0:0:e::c009",
"2a04:27c0:0:e::c00a",
"2a04:27c0:0:e::c00b",
"2a04:27c0:0:e::c00c",
"2a04:27c0:0:e::c00d",
"2a04:27c0:0:e::c00e",
"2a04:27c0:0:e::c00f",
"2a04:27c0:0:e::c010",
"2a04:27c0:0:e::c011",
"2a04:27c0:0:e::c012",
"2a04:27c0:0:e::c013",
"2a04:27c0:0:e::c014",
"2a04:27c0:0:e::c015",
"2a04:27c0:0:e::c016",
"2a04:27c0:0:e::c017",
"2a04:27c0:0:e::c018",
"2a04:27c0:0:e::c019",
"2a04:27c0:0:e::c01a",
"2a04:27c0:0:e::c01b",
"2a04:27c0:0:e::c01c",
"2a04:27c0:0:e::c01d",
"2a04:27c0:0:e::c01e",
"2a04:27c0:0:e::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "al-tia-wg-001.blockerad.eu"
}
}
},
{
"hostname": "al-tia-wg-003",
"location": "al-tia",
"active": true,
"owned": false,
"provider": "iRegister",
"stboot": true,
"ipv4_addr_in": "103.124.165.130",
"include_in_country": true,
"weight": 100,
"public_key": "rWiQxq5lAWD8v/bws9ITSAvThyZW8cR2x+Ins9ZvvRo=",
"ipv6_addr_in": "2a04:27c0:0:c::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"103.204.123.136"
],
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"103.124.165.135",
"2a04:27c0:0:c::f00a"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "al-tia-wg-003.blockerad.eu"
}
}
},
{
"hostname": "al-tia-wg-004",
"location": "al-tia",
"active": true,
"owned": false,
"provider": "iRegister",
"stboot": true,
"ipv4_addr_in": "103.124.165.191",
"include_in_country": true,
"weight": 100,
"public_key": "x62J1c4gfHu/bF3DSjwIjC0qOE3azRG03i/YW6bOEGY=",
"ipv6_addr_in": "2a04:27c0:0:d::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"103.124.165.197"
],
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"103.124.165.196",
"2a04:27c0:0:d::f00a"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "al-tia-wg-004.blockerad.eu"
}
}
},
{
"hostname": "ar-bue-wg-001",
"location": "ar-bue",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "149.22.83.2",
"include_in_country": true,
"weight": 100,
"public_key": "1WN0Mqa0Azw7cYYEamHPgHXE8SuylNIG2QobZKOaclA=",
"ipv6_addr_in": "2a02:6ea0:f002:1::f001",
"shadowsocks_extra_addr_in": [
"149.22.83.5"
],
"features": {
"quic": {
"addr_in": [
"149.22.83.4"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "ar-bue-wg-001.blockerad.eu"
}
}
},
{
"hostname": "ar-bue-wg-002",
"location": "ar-bue",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "149.22.83.31",
"include_in_country": true,
"weight": 100,
"public_key": "gGrdozNHVCnmcX5x8OPOXfnyZ+TZWqD9GlHl1kRekyA=",
"ipv6_addr_in": "2a02:6ea0:f002:2::f001",
"shadowsocks_extra_addr_in": [
"149.22.83.34"
],
"features": {
"quic": {
"addr_in": [
"149.22.83.33"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "ar-bue-wg-002.blockerad.eu"
}
}
},
{
"hostname": "at-vie-wg-001",
"location": "at-vie",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.116.130",
"include_in_country": true,
"weight": 100,
"public_key": "GLqlOTVJCyRpJx3vgR3ykTPNJLGKNytHXu61zBWIAls=",
"ipv6_addr_in": "2001:ac8:29:b3::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"146.70.116.141",
"146.70.116.142",
"146.70.116.143",
"146.70.116.144",
"146.70.116.145",
"146.70.116.146",
"146.70.116.147",
"146.70.116.148",
"146.70.116.149",
"146.70.116.150",
"2001:ac8:29:b3::b002",
"2001:ac8:29:b3::b003",
"2001:ac8:29:b3::b004",
"2001:ac8:29:b3::b005",
"2001:ac8:29:b3::b006",
"2001:ac8:29:b3::b007",
"2001:ac8:29:b3::b008",
"2001:ac8:29:b3::b009",
"2001:ac8:29:b3::b00a",
"2001:ac8:29:b3::b00b",
"2001:ac8:29:b3::b00c",
"2001:ac8:29:b3::b00d",
"2001:ac8:29:b3::b00e",
"2001:ac8:29:b3::b00f",
"2001:ac8:29:b3::b010",
"2001:ac8:29:b3::b011",
"2001:ac8:29:b3::b012",
"2001:ac8:29:b3::b013",
"2001:ac8:29:b3::b014",
"2001:ac8:29:b3::b015",
"2001:ac8:29:b3::b016",
"2001:ac8:29:b3::b017",
"2001:ac8:29:b3::b018",
"2001:ac8:29:b3::b019",
"2001:ac8:29:b3::b01a",
"2001:ac8:29:b3::b01b",
"2001:ac8:29:b3::b01c",
"2001:ac8:29:b3::b01d",
"2001:ac8:29:b3::b01e",
"2001:ac8:29:b3::b01f"
],
"features": {
"daita": {},
"lwo": {}
}
},
{
"hostname": "at-vie-wg-002",
"location": "at-vie",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "135.136.51.2",
"include_in_country": true,
"weight": 100,
"public_key": "FSGkeqzoy8fWkGcGl5nrYeiQG04C511+qdH5iMramxE=",
"ipv6_addr_in": "2001:ac8:29:b4::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"135.136.51.13",
"135.136.51.14",
"135.136.51.15",
"135.136.51.16",
"135.136.51.17",
"135.136.51.18",
"135.136.51.19",
"135.136.51.20",
"135.136.51.21",
"135.136.51.22",
"2001:ac8:29:b4::b002",
"2001:ac8:29:b4::b003",
"2001:ac8:29:b4::b004",
"2001:ac8:29:b4::b005",
"2001:ac8:29:b4::b006",
"2001:ac8:29:b4::b007",
"2001:ac8:29:b4::b008",
"2001:ac8:29:b4::b009",
"2001:ac8:29:b4::b00a",
"2001:ac8:29:b4::b00b",
"2001:ac8:29:b4::b00c",
"2001:ac8:29:b4::b00d",
"2001:ac8:29:b4::b00e",
"2001:ac8:29:b4::b00f",
"2001:ac8:29:b4::b010",
"2001:ac8:29:b4::b011",
"2001:ac8:29:b4::b012",
"2001:ac8:29:b4::b013",
"2001:ac8:29:b4::b014",
"2001:ac8:29:b4::b015",
"2001:ac8:29:b4::b016",
"2001:ac8:29:b4::b017",
"2001:ac8:29:b4::b018",
"2001:ac8:29:b4::b019",
"2001:ac8:29:b4::b01a",
"2001:ac8:29:b4::b01b",
"2001:ac8:29:b4::b01c",
"2001:ac8:29:b4::b01d",
"2001:ac8:29:b4::b01e",
"2001:ac8:29:b4::b01f"
],
"features": {
"daita": {},
"lwo": {}
}
},
{
"hostname": "at-vie-wg-003",
"location": "at-vie",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "135.136.51.130",
"include_in_country": true,
"weight": 100,
"public_key": "HsWJFTCpoe7niGs8EOMI2/ES4Q4MuhqLIoRc9QLSpSk=",
"ipv6_addr_in": "2001:ac8:29:b5::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"135.136.51.141",
"135.136.51.142",
"135.136.51.143",
"135.136.51.144",
"135.136.51.145",
"135.136.51.146",
"135.136.51.147",
"135.136.51.148",
"135.136.51.149",
"135.136.51.150",
"2001:ac8:29:b5::b002",
"2001:ac8:29:b5::b003",
"2001:ac8:29:b5::b004",
"2001:ac8:29:b5::b005",
"2001:ac8:29:b5::b006",
"2001:ac8:29:b5::b007",
"2001:ac8:29:b5::b008",
"2001:ac8:29:b5::b009",
"2001:ac8:29:b5::b00a",
"2001:ac8:29:b5::b00b",
"2001:ac8:29:b5::b00c",
"2001:ac8:29:b5::b00d",
"2001:ac8:29:b5::b00e",
"2001:ac8:29:b5::b00f",
"2001:ac8:29:b5::b010",
"2001:ac8:29:b5::b011",
"2001:ac8:29:b5::b012",
"2001:ac8:29:b5::b013",
"2001:ac8:29:b5::b014",
"2001:ac8:29:b5::b015",
"2001:ac8:29:b5::b016",
"2001:ac8:29:b5::b017",
"2001:ac8:29:b5::b018",
"2001:ac8:29:b5::b019",
"2001:ac8:29:b5::b01a",
"2001:ac8:29:b5::b01b",
"2001:ac8:29:b5::b01c",
"2001:ac8:29:b5::b01d",
"2001:ac8:29:b5::b01e",
"2001:ac8:29:b5::b01f"
],
"features": {
"daita": {},
"lwo": {}
}
},
{
"hostname": "at-vie-wg-101",
"location": "at-vie",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "185.24.11.130",
"include_in_country": true,
"weight": 100,
"public_key": "dj3qNfJfA4dWXsWokPcDh4oo6xaPtOTPfbr5UzHKZ0M=",
"ipv6_addr_in": "2a02:6ea0:cb1b:1::f001",
"shadowsocks_extra_addr_in": [
"185.24.11.132"
],
"features": {
"lwo": {}
}
},
{
"hostname": "at-vie-wg-102",
"location": "at-vie",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "185.24.11.159",
"include_in_country": true,
"weight": 100,
"public_key": "DANFtH+sFB19BnW1CYEwZ2pOIt7P8nLjSadjpS2rLWE=",
"ipv6_addr_in": "2a02:6ea0:cb1b:2::f001",
"shadowsocks_extra_addr_in": [
"185.24.11.161"
],
"features": {
"lwo": {}
}
},
{
"hostname": "au-adl-wg-301",
"location": "au-adl",
"active": true,
"owned": false,
"provider": "hostuniversal",
"stboot": true,
"ipv4_addr_in": "103.214.20.50",
"include_in_country": true,
"weight": 100,
"public_key": "rm2hpBiN91c7reV+cYKlw7QNkYtME/+js7IMyYBB2Aw=",
"ipv6_addr_in": "2404:f780:0:deb::c1f"
},
{
"hostname": "au-adl-wg-302",
"location": "au-adl",
"active": true,
"owned": false,
"provider": "hostuniversal",
"stboot": true,
"ipv4_addr_in": "103.214.20.130",
"include_in_country": true,
"weight": 100,
"public_key": "e4jouH8n4e8oyi/Z7d6lJLd6975hlPZmnynJeoU+nWM=",
"ipv6_addr_in": "2404:f780:0:dec::c2f"
},
{
"hostname": "au-adl-wg-303",
"location": "au-adl",
"active": true,
"owned": false,
"provider": "hostuniversal",
"stboot": true,
"ipv4_addr_in": "103.214.20.162",
"include_in_country": true,
"weight": 100,
"public_key": "X9vdIZG69ZDU4Wf05T8F+C+NuWeYOgojmOVeASdiIWo=",
"ipv6_addr_in": "2404:f780:0:def::f201",
"features": {
"lwo": {}
}
},
{
"hostname": "au-bne-wg-301",
"location": "au-bne",
"active": true,
"owned": false,
"provider": "hostuniversal",
"stboot": true,
"ipv4_addr_in": "103.216.220.18",
"include_in_country": true,
"weight": 100,
"public_key": "1H/gj8SVNebAIEGlvMeUVC5Rnf274dfVKbyE+v5G8HA=",
"ipv6_addr_in": "2404:f780:4:deb::f001"
},
{
"hostname": "au-bne-wg-302",
"location": "au-bne",
"active": true,
"owned": false,
"provider": "hostuniversal",
"stboot": true,
"ipv4_addr_in": "103.216.220.34",
"include_in_country": true,
"weight": 100,
"public_key": "z+JG0QA4uNd/wRTpjCqn9rDpQsHKhf493omqQ5rqYAc=",
"ipv6_addr_in": "2404:f780:4:dec::a02f"
},
{
"hostname": "au-bne-wg-303",
"location": "au-bne",
"active": true,
"owned": false,
"provider": "hostuniversal",
"stboot": true,
"ipv4_addr_in": "103.216.220.66",
"include_in_country": true,
"weight": 100,
"public_key": "AdUQ6vk1e1SMzlLpgwmg86A0SSj8YGrJE2UWlflGtCg=",
"ipv6_addr_in": "2404:f780:4:def::f201",
"features": {
"lwo": {}
}
},
{
"hostname": "au-mel-wg-401",
"location": "au-mel",
"active": true,
"owned": false,
"provider": "hostuniversal",
"stboot": true,
"ipv4_addr_in": "163.47.16.146",
"include_in_country": true,
"weight": 100,
"public_key": "ju0S2nDmiOrSm1H68SRTB4mtt2U8SKROprE83VCoF1Y=",
"ipv6_addr_in": "2406:d501:f:dfa::f001",
"shadowsocks_extra_addr_in": [
"163.47.16.149",
"91.190.106.11",
"91.190.106.12",
"91.190.106.13",
"91.190.106.14",
"91.190.106.15",
"91.190.106.16",
"91.190.106.17",
"91.190.106.18",
"91.190.106.19",
"91.190.106.20",
"2406:d501:f:dfa::b002",
"2406:d501:f:dfa::b003",
"2406:d501:f:dfa::b004",
"2406:d501:f:dfa::b005",
"2406:d501:f:dfa::b006",
"2406:d501:f:dfa::b007",
"2406:d501:f:dfa::b008",
"2406:d501:f:dfa::b009",
"2406:d501:f:dfa::b00a",
"2406:d501:f:dfa::b00b",
"2406:d501:f:dfa::b00c",
"2406:d501:f:dfa::b00d",
"2406:d501:f:dfa::b00e",
"2406:d501:f:dfa::b00f",
"2406:d501:f:dfa::b010",
"2406:d501:f:dfa::b011",
"2406:d501:f:dfa::b012",
"2406:d501:f:dfa::b013",
"2406:d501:f:dfa::b014",
"2406:d501:f:dfa::b015",
"2406:d501:f:dfa::b016",
"2406:d501:f:dfa::b017",
"2406:d501:f:dfa::b018",
"2406:d501:f:dfa::b019",
"2406:d501:f:dfa::b01a",
"2406:d501:f:dfa::b01b",
"2406:d501:f:dfa::b01c",
"2406:d501:f:dfa::b01d",
"2406:d501:f:dfa::b01e",
"2406:d501:f:dfa::b01f"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"163.47.16.148",
"91.190.106.3",
"91.190.106.4",
"91.190.106.5",
"91.190.106.6",
"91.190.106.7",
"91.190.106.8",
"91.190.106.9",
"91.190.106.10",
"2406:d501:f:dfa::c002",
"2406:d501:f:dfa::c003",
"2406:d501:f:dfa::c004",
"2406:d501:f:dfa::c005",
"2406:d501:f:dfa::c006",
"2406:d501:f:dfa::c007",
"2406:d501:f:dfa::c008",
"2406:d501:f:dfa::c009",
"2406:d501:f:dfa::c00a",
"2406:d501:f:dfa::c00b",
"2406:d501:f:dfa::c00c",
"2406:d501:f:dfa::c00d",
"2406:d501:f:dfa::c00e",
"2406:d501:f:dfa::c00f",
"2406:d501:f:dfa::c010",
"2406:d501:f:dfa::c011",
"2406:d501:f:dfa::c012",
"2406:d501:f:dfa::c013",
"2406:d501:f:dfa::c014",
"2406:d501:f:dfa::c015",
"2406:d501:f:dfa::c016",
"2406:d501:f:dfa::c017",
"2406:d501:f:dfa::c018",
"2406:d501:f:dfa::c019",
"2406:d501:f:dfa::c01a",
"2406:d501:f:dfa::c01b",
"2406:d501:f:dfa::c01c",
"2406:d501:f:dfa::c01d",
"2406:d501:f:dfa::c01e",
"2406:d501:f:dfa::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "au-mel-wg-401.blockerad.eu"
}
}
},
{
"hostname": "au-mel-wg-402",
"location": "au-mel",
"active": false,
"owned": false,
"provider": "hostuniversal",
"stboot": true,
"ipv4_addr_in": "163.47.16.150",
"include_in_country": true,
"weight": 100,
"public_key": "j9xeIW+vE1DQAglbr00Vw1ePp6ueWklZ+Qx+KuyoBwQ=",
"ipv6_addr_in": "2406:d501:f:dfb::f001",
"shadowsocks_extra_addr_in": [
"163.47.16.153",
"91.190.106.100",
"91.190.106.101",
"91.190.106.102",
"91.190.106.103",
"91.190.106.104",
"91.190.106.105",
"91.190.106.106",
"91.190.106.107",
"91.190.106.108",
"91.190.106.109",
"2406:d501:f:dfb::b002",
"2406:d501:f:dfb::b003",
"2406:d501:f:dfb::b004",
"2406:d501:f:dfb::b005",
"2406:d501:f:dfb::b006",
"2406:d501:f:dfb::b007",
"2406:d501:f:dfb::b008",
"2406:d501:f:dfb::b009",
"2406:d501:f:dfb::b00a",
"2406:d501:f:dfb::b00b",
"2406:d501:f:dfb::b00c",
"2406:d501:f:dfb::b00d",
"2406:d501:f:dfb::b00e",
"2406:d501:f:dfb::b00f",
"2406:d501:f:dfb::b010",
"2406:d501:f:dfb::b011",
"2406:d501:f:dfb::b012",
"2406:d501:f:dfb::b013",
"2406:d501:f:dfb::b014",
"2406:d501:f:dfb::b015",
"2406:d501:f:dfb::b016",
"2406:d501:f:dfb::b017",
"2406:d501:f:dfb::b018",
"2406:d501:f:dfb::b019",
"2406:d501:f:dfb::b01a",
"2406:d501:f:dfb::b01b",
"2406:d501:f:dfb::b01c",
"2406:d501:f:dfb::b01d",
"2406:d501:f:dfb::b01e",
"2406:d501:f:dfb::b01f"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"163.47.16.152",
"91.190.106.91",
"91.190.106.92",
"91.190.106.93",
"91.190.106.94",
"91.190.106.95",
"91.190.106.96",
"91.190.106.97",
"91.190.106.98",
"91.190.106.99",
"2406:d501:f:dfb::c002",
"2406:d501:f:dfb::c003",
"2406:d501:f:dfb::c004",
"2406:d501:f:dfb::c005",
"2406:d501:f:dfb::c006",
"2406:d501:f:dfb::c007",
"2406:d501:f:dfb::c008",
"2406:d501:f:dfb::c009",
"2406:d501:f:dfb::c00a",
"2406:d501:f:dfb::c00b",
"2406:d501:f:dfb::c00c",
"2406:d501:f:dfb::c00d",
"2406:d501:f:dfb::c00e",
"2406:d501:f:dfb::c00f",
"2406:d501:f:dfb::c010",
"2406:d501:f:dfb::c011",
"2406:d501:f:dfb::c012",
"2406:d501:f:dfb::c013",
"2406:d501:f:dfb::c014",
"2406:d501:f:dfb::c015",
"2406:d501:f:dfb::c016",
"2406:d501:f:dfb::c017",
"2406:d501:f:dfb::c018",
"2406:d501:f:dfb::c019",
"2406:d501:f:dfb::c01a",
"2406:d501:f:dfb::c01b",
"2406:d501:f:dfb::c01c",
"2406:d501:f:dfb::c01d",
"2406:d501:f:dfb::c01e",
"2406:d501:f:dfb::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "au-mel-wg-402.blockerad.eu"
}
}
},
{
"hostname": "au-mel-wg-403",
"location": "au-mel",
"active": true,
"owned": false,
"provider": "hostuniversal",
"stboot": true,
"ipv4_addr_in": "163.47.16.154",
"include_in_country": true,
"weight": 100,
"public_key": "OQzxEZxEnLI85WF81VFO4tg9+fEBZ1dL+vckw2VYPxk=",
"ipv6_addr_in": "2406:d501:f:dfc::f001",
"shadowsocks_extra_addr_in": [
"163.47.16.157",
"163.47.16.158",
"91.190.106.180",
"91.190.106.181",
"91.190.106.182",
"91.190.106.183",
"91.190.106.184",
"91.190.106.185",
"91.190.106.186",
"91.190.106.187",
"91.190.106.188",
"91.190.106.189",
"2406:d501:f:dfc::b002",
"2406:d501:f:dfc::b003",
"2406:d501:f:dfc::b004",
"2406:d501:f:dfc::b005",
"2406:d501:f:dfc::b006",
"2406:d501:f:dfc::b007",
"2406:d501:f:dfc::b008",
"2406:d501:f:dfc::b009",
"2406:d501:f:dfc::b00a",
"2406:d501:f:dfc::b00b",
"2406:d501:f:dfc::b00c",
"2406:d501:f:dfc::b00d",
"2406:d501:f:dfc::b00e",
"2406:d501:f:dfc::b00f",
"2406:d501:f:dfc::b010",
"2406:d501:f:dfc::b011",
"2406:d501:f:dfc::b012",
"2406:d501:f:dfc::b013",
"2406:d501:f:dfc::b014",
"2406:d501:f:dfc::b015",
"2406:d501:f:dfc::b016",
"2406:d501:f:dfc::b017",
"2406:d501:f:dfc::b018",
"2406:d501:f:dfc::b019",
"2406:d501:f:dfc::b01a",
"2406:d501:f:dfc::b01b",
"2406:d501:f:dfc::b01c",
"2406:d501:f:dfc::b01d",
"2406:d501:f:dfc::b01e",
"2406:d501:f:dfc::b01f"
],
"features": {
"quic": {
"addr_in": [
"163.47.16.156",
"91.190.106.170",
"91.190.106.171",
"91.190.106.172",
"91.190.106.173",
"91.190.106.174",
"91.190.106.175",
"91.190.106.176",
"91.190.106.177",
"91.190.106.178",
"91.190.106.179",
"2406:d501:f:dfc::c002",
"2406:d501:f:dfc::c003",
"2406:d501:f:dfc::c004",
"2406:d501:f:dfc::c005",
"2406:d501:f:dfc::c006",
"2406:d501:f:dfc::c007",
"2406:d501:f:dfc::c008",
"2406:d501:f:dfc::c009",
"2406:d501:f:dfc::c00a",
"2406:d501:f:dfc::c00b",
"2406:d501:f:dfc::c00c",
"2406:d501:f:dfc::c00d",
"2406:d501:f:dfc::c00e",
"2406:d501:f:dfc::c00f",
"2406:d501:f:dfc::c010",
"2406:d501:f:dfc::c011",
"2406:d501:f:dfc::c012",
"2406:d501:f:dfc::c013",
"2406:d501:f:dfc::c014",
"2406:d501:f:dfc::c015",
"2406:d501:f:dfc::c016",
"2406:d501:f:dfc::c017",
"2406:d501:f:dfc::c018",
"2406:d501:f:dfc::c019",
"2406:d501:f:dfc::c01a",
"2406:d501:f:dfc::c01b",
"2406:d501:f:dfc::c01c",
"2406:d501:f:dfc::c01d",
"2406:d501:f:dfc::c01e",
"2406:d501:f:dfc::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "au-mel-wg-403.blockerad.eu"
}
}
},
{
"hostname": "au-per-wg-301",
"location": "au-per",
"active": true,
"owned": false,
"provider": "hostuniversal",
"stboot": true,
"ipv4_addr_in": "103.108.231.50",
"include_in_country": true,
"weight": 100,
"public_key": "hQXsNk/9R2We0pzP1S9J3oNErEu2CyENlwTdmDUYFhg=",
"ipv6_addr_in": "2404:f780:8:deb::a01f"
},
{
"hostname": "au-per-wg-302",
"location": "au-per",
"active": true,
"owned": false,
"provider": "hostuniversal",
"stboot": true,
"ipv4_addr_in": "103.108.231.66",
"include_in_country": true,
"weight": 100,
"public_key": "t3Ly8bBdF2gMHzT3d529bVLDw8Jd2/FFG9GXoBEx01g=",
"ipv6_addr_in": "2404:f780:8:dec::f001"
},
{
"hostname": "au-syd-wg-001",
"location": "au-syd",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.200.2",
"include_in_country": true,
"weight": 100,
"public_key": "4JpfHBvthTFOhCK0f5HAbzLXAVcB97uAkuLx7E8kqW0=",
"ipv6_addr_in": "2001:ac8:84:5::f001"
},
{
"hostname": "au-syd-wg-002",
"location": "au-syd",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.141.194",
"include_in_country": true,
"weight": 100,
"public_key": "lUeDAOy+iAhZDuz5+6zh0Co8wZcs3ahdu2jfqQoDW3E=",
"ipv6_addr_in": "2001:ac8:84:6::2f"
},
{
"hostname": "au-syd-wg-003",
"location": "au-syd",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.200.194",
"include_in_country": true,
"weight": 100,
"public_key": "LXuRwa9JRTt2/UtldklKGlj/IVLORITqgET4II4DRkU=",
"ipv6_addr_in": "2001:ac8:84:4::3f"
},
{
"hostname": "au-syd-wg-101",
"location": "au-syd",
"active": true,
"owned": false,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "103.136.147.3",
"include_in_country": true,
"weight": 100,
"public_key": "NKP4jSvSDZg5HJ3JxpGYMxIYt7QzoxSFrU2F0m1ZxwA=",
"ipv6_addr_in": "2a11:3:500::f001"
},
{
"hostname": "au-syd-wg-102",
"location": "au-syd",
"active": true,
"owned": false,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "103.136.147.65",
"include_in_country": true,
"weight": 100,
"public_key": "w825smx7YI9/SrwSYGdsuwD1Qt5UsS/CyaGTjwSYljU=",
"ipv6_addr_in": "2a11:3:500::f101"
},
{
"hostname": "au-syd-wg-103",
"location": "au-syd",
"active": true,
"owned": false,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "103.136.147.129",
"include_in_country": true,
"weight": 100,
"public_key": "poOHsF6v91yURxDrNe/P/adyNUqsRGzhFIioyBYUPww=",
"ipv6_addr_in": "2a11:3:500::f201",
"features": {
"lwo": {}
}
},
{
"hostname": "au-syd-wg-104",
"location": "au-syd",
"active": true,
"owned": false,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "103.136.147.197",
"include_in_country": true,
"weight": 100,
"public_key": "61Ovy3ObuHqllZK/P/5cOWZnY26SY2csmjzVK1q+fFs=",
"ipv6_addr_in": "2a11:3:500::f301"
},
{
"hostname": "au-syd-wg-301",
"location": "au-syd",
"active": true,
"owned": false,
"provider": "HostRoyale",
"stboot": true,
"ipv4_addr_in": "103.120.6.2",
"include_in_country": true,
"weight": 100,
"public_key": "bQIQLk9zVOZLEGJsQOMu0K3rCMc85gExkS/0b1tSVBk=",
"ipv6_addr_in": "2a06:3040:18:210::f001",
"shadowsocks_extra_addr_in": [
"103.120.6.13"
],
"features": {
"quic": {
"addr_in": [
"103.120.6.12",
"2a06:3040:18:210::f00a"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "au-syd-wg-301.blockerad.eu"
}
}
},
{
"hostname": "au-syd-wg-302",
"location": "au-syd",
"active": true,
"owned": false,
"provider": "HostRoyale",
"stboot": true,
"ipv4_addr_in": "103.120.6.127",
"include_in_country": true,
"weight": 100,
"public_key": "6tTqSMUVPhaMsFFdphijwdura5RnNOzlz33Ekp1oCmc=",
"ipv6_addr_in": "2a06:3040:18:210::f101",
"shadowsocks_extra_addr_in": [
"103.120.6.138"
],
"features": {
"quic": {
"addr_in": [
"103.120.6.137"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "au-syd-wg-302.blockerad.eu"
}
}
},
{
"hostname": "au-syd-wg-303",
"location": "au-syd",
"active": true,
"owned": false,
"provider": "HostRoyale",
"stboot": true,
"ipv4_addr_in": "103.141.60.2",
"include_in_country": true,
"weight": 100,
"public_key": "RK/eoKsyX4fu7iJ9F5mTf07en/WgYOMAtPGivKTntlw=",
"ipv6_addr_in": "2a06:3040:18:210::f201",
"shadowsocks_extra_addr_in": [
"103.141.60.13"
],
"features": {
"quic": {
"addr_in": [
"103.141.60.12"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "au-syd-wg-303.blockerad.eu"
}
}
},
{
"hostname": "au-syd-wg-304",
"location": "au-syd",
"active": true,
"owned": false,
"provider": "HostRoyale",
"stboot": true,
"ipv4_addr_in": "103.141.60.127",
"include_in_country": true,
"weight": 100,
"public_key": "gXZZhcHfOD7FtnwTw8APUnccwMTVQYDNs4bbjHGS3CI=",
"ipv6_addr_in": "2a06:3040:18:210::f301",
"shadowsocks_extra_addr_in": [
"103.141.60.138"
],
"features": {
"quic": {
"addr_in": [
"103.141.60.137"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "au-syd-wg-304.blockerad.eu"
}
}
},
{
"hostname": "be-bru-wg-101",
"location": "be-bru",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "91.90.123.2",
"include_in_country": true,
"weight": 100,
"public_key": "GE2WP6hmwVggSvGVWLgq2L10T3WM2VspnUptK5F4B0U=",
"ipv6_addr_in": "2001:ac8:27:88::a01f"
},
{
"hostname": "be-bru-wg-102",
"location": "be-bru",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "194.110.115.34",
"include_in_country": true,
"weight": 100,
"public_key": "IY+FKw487MEWqMGNyyrT4PnTrJxce8oiGNHT0zifam8=",
"ipv6_addr_in": "2001:ac8:27:89::a02f"
},
{
"hostname": "be-bru-wg-103",
"location": "be-bru",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "194.110.115.2",
"include_in_country": true,
"weight": 100,
"public_key": "b5A1ela+BVI+AbNXz7SWekZHvdWWpt3rqUKTJj0SqCU=",
"ipv6_addr_in": "2001:ac8:27:92::a03f"
},
{
"hostname": "bg-sof-wg-001",
"location": "bg-sof",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.188.130",
"include_in_country": true,
"weight": 100,
"public_key": "J8KysHmHZWqtrVKKOppneDXSks/PDsB1XTlRHpwiABA=",
"ipv6_addr_in": "2001:ac8:30:56::f001"
},
{
"hostname": "bg-sof-wg-002",
"location": "bg-sof",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.188.194",
"include_in_country": true,
"weight": 100,
"public_key": "dg+Fw7GnKvDPBxFpnj1KPoNIu1GakuVoDJjKRni+pRU=",
"ipv6_addr_in": "2001:ac8:30:57::f001"
},
{
"hostname": "br-for-wg-001",
"location": "br-for",
"active": true,
"owned": false,
"provider": "Zenlayer",
"stboot": true,
"ipv4_addr_in": "98.98.12.178",
"include_in_country": true,
"weight": 100,
"public_key": "CiPqGvrQidRVmKc6T8TORsAAZtQbsGzNEAKyd1iVlWY=",
"ipv6_addr_in": "2604:980:e007:100::f001",
"shadowsocks_extra_addr_in": [
"155.2.219.14"
],
"features": {
"quic": {
"addr_in": [
"155.2.219.13",
"2604:980:e007:100::f00a"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "br-for-wg-001.blockerad.eu"
}
}
},
{
"hostname": "br-for-wg-002",
"location": "br-for",
"active": true,
"owned": false,
"provider": "Zenlayer",
"stboot": true,
"ipv4_addr_in": "98.98.12.182",
"include_in_country": true,
"weight": 100,
"public_key": "qXISz0Kl4oC0sypcjD6hIxplv8zzZGIJPQZc4/EGz2k=",
"ipv6_addr_in": "2604:980:e007:100::f101",
"shadowsocks_extra_addr_in": [
"155.2.219.139"
],
"features": {
"quic": {
"addr_in": [
"155.2.219.138",
"2604:980:e007:100::f10a"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "br-for-wg-002.blockerad.eu"
}
}
},
{
"hostname": "br-sao-wg-201",
"location": "br-sao",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "169.150.198.66",
"include_in_country": true,
"weight": 100,
"public_key": "8c9M6w1BQbgMVr/Zgrj4GwSdU6q3qfQfWs17kMLC9y4=",
"ipv6_addr_in": "2a02:6ea0:d00e:1::a01f",
"daita": true,
"features": {
"daita": {}
}
},
{
"hostname": "br-sao-wg-202",
"location": "br-sao",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "169.150.198.79",
"include_in_country": true,
"weight": 100,
"public_key": "jWURoz8SLBUlRTQnAFTA/LDZUTpvlO0ghiVWH7MgaHQ=",
"ipv6_addr_in": "2a02:6ea0:d00e:2::a02f"
},
{
"hostname": "br-sao-wg-302",
"location": "br-sao",
"active": true,
"owned": false,
"provider": "HostRoyale",
"stboot": true,
"ipv4_addr_in": "103.139.178.63",
"include_in_country": true,
"weight": 100,
"public_key": "Xv1QvURPbgywITL6MNVhbYtfZXTm0lR98SPaf3AXeCc=",
"ipv6_addr_in": "2a06:3040:10:610::f101",
"shadowsocks_extra_addr_in": [
"103.139.178.74",
"103.139.178.75"
],
"features": {
"quic": {
"addr_in": [
"103.139.178.73",
"2a06:3040:10:610::f10a"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "br-sao-wg-302.blockerad.eu"
}
}
},
{
"hostname": "br-sao-wg-303",
"location": "br-sao",
"active": true,
"owned": false,
"provider": "HostRoyale",
"stboot": true,
"ipv4_addr_in": "103.139.178.123",
"include_in_country": true,
"weight": 100,
"public_key": "oYrzNmnieX0iZS2nLxdM3mNcDjQZEWn5yaFCtX76qDk=",
"ipv6_addr_in": "2a06:3040:10:610::f201",
"shadowsocks_extra_addr_in": [
"103.139.178.134",
"103.139.178.135"
],
"features": {
"quic": {
"addr_in": [
"103.139.178.133",
"2a06:3040:10:610::f20a"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "br-sao-wg-303.blockerad.eu"
}
}
},
{
"hostname": "br-sao-wg-304",
"location": "br-sao",
"active": true,
"owned": false,
"provider": "HostRoyale",
"stboot": true,
"ipv4_addr_in": "103.139.178.183",
"include_in_country": true,
"weight": 100,
"public_key": "hmO6+lN2CrWMFdpiPtSZ3oPRmcsJlpIi00P+c5p6rQQ=",
"ipv6_addr_in": "2a06:3040:10:610::f301",
"shadowsocks_extra_addr_in": [
"103.139.178.194",
"103.139.178.195"
],
"features": {
"quic": {
"addr_in": [
"103.139.178.193",
"2a06:3040:10:610::f30a"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "br-sao-wg-304.blockerad.eu"
}
}
},
{
"hostname": "ca-mtr-wg-001",
"location": "ca-mtr",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.198.66",
"include_in_country": true,
"weight": 100,
"public_key": "TUCaQc26/R6AGpkDUr8A8ytUs/e5+UVlIVujbuBwlzI=",
"ipv6_addr_in": "2a0d:5600:9:c::f001",
"features": {
"lwo": {},
"quic": {
"addr_in": [
"146.70.198.126",
"2a0d:5600:9:c::c101"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "ca-mtr-wg-001.blockerad.eu"
}
}
},
{
"hostname": "ca-mtr-wg-002",
"location": "ca-mtr",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.198.130",
"include_in_country": true,
"weight": 100,
"public_key": "7X6zOgtJfJAK8w8C3z+hekcS9Yf3qK3Bp4yx56lqxBQ=",
"ipv6_addr_in": "2a0d:5600:9:d::f001"
},
{
"hostname": "ca-mtr-wg-003",
"location": "ca-mtr",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.198.194",
"include_in_country": true,
"weight": 100,
"public_key": "57Zu2qPzRScZWsoC2NhXgz0FiC0HiKkbEa559sbxB3k=",
"ipv6_addr_in": "2a0d:5600:9:e::a02f"
},
{
"hostname": "ca-mtr-wg-004",
"location": "ca-mtr",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "188.241.176.194",
"include_in_country": true,
"weight": 100,
"public_key": "Cc5swfQ9f2tAgLduuIqC3bLbwDVoOFkkETghsE6/twA=",
"ipv6_addr_in": "2a0d:5600:9:16::f001"
},
{
"hostname": "ca-mtr-wg-201",
"location": "ca-mtr",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "62.93.167.130",
"include_in_country": true,
"weight": 100,
"public_key": "m1DF8sQgOBo+vfdl1//sCvu2TnsHKdRzfsiszbBZQzs=",
"ipv6_addr_in": "2a02:6ea0:a03:2::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"62.93.167.132"
],
"features": {
"daita": {}
}
},
{
"hostname": "ca-mtr-wg-202",
"location": "ca-mtr",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "62.93.167.160",
"include_in_country": true,
"weight": 100,
"public_key": "NqU0AZRAYH1p8BDUbirqITPJX47WYJsyxO73RHcEjEQ=",
"ipv6_addr_in": "2a02:6ea0:a03::f001",
"shadowsocks_extra_addr_in": [
"62.93.167.162"
]
},
{
"hostname": "ca-mtr-wg-301",
"location": "ca-mtr",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.120.2",
"include_in_country": true,
"weight": 100,
"public_key": "iV7uZuw8vbqrW/p4YhsxkIxXaUuI4Uj2hTl8TaJZfAA=",
"ipv6_addr_in": "2607:9000:f00:2::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"23.234.120.5",
"23.234.120.6",
"23.234.120.7",
"23.234.120.8",
"23.234.120.9",
"23.234.120.10",
"23.234.120.11",
"23.234.120.12",
"23.234.120.13",
"23.234.120.14",
"23.234.120.15",
"23.234.120.16",
"23.234.120.17",
"23.234.120.18",
"23.234.120.19",
"2607:9000:f00:2::b002",
"2607:9000:f00:2::b003",
"2607:9000:f00:2::b004",
"2607:9000:f00:2::b005",
"2607:9000:f00:2::b006",
"2607:9000:f00:2::b007",
"2607:9000:f00:2::b008",
"2607:9000:f00:2::b009",
"2607:9000:f00:2::b00a",
"2607:9000:f00:2::b00b",
"2607:9000:f00:2::b00c",
"2607:9000:f00:2::b00d",
"2607:9000:f00:2::b00e",
"2607:9000:f00:2::b00f",
"2607:9000:f00:2::b010",
"2607:9000:f00:2::b011",
"2607:9000:f00:2::b012",
"2607:9000:f00:2::b013",
"2607:9000:f00:2::b014",
"2607:9000:f00:2::b015",
"2607:9000:f00:2::b016",
"2607:9000:f00:2::b017",
"2607:9000:f00:2::b018",
"2607:9000:f00:2::b019",
"2607:9000:f00:2::b01a",
"2607:9000:f00:2::b01b",
"2607:9000:f00:2::b01c",
"2607:9000:f00:2::b01d",
"2607:9000:f00:2::b01e",
"2607:9000:f00:2::b01f"
],
"features": {
"daita": {},
"quic": {
"addr_in": [
"23.234.120.20",
"23.234.120.21",
"23.234.120.22",
"23.234.120.23",
"23.234.120.24",
"23.234.120.25",
"23.234.120.26",
"23.234.120.27",
"23.234.120.28",
"23.234.120.29",
"23.234.120.30",
"23.234.120.31",
"23.234.120.32",
"23.234.120.33",
"23.234.120.34",
"2607:9000:f00:2::c002",
"2607:9000:f00:2::c003",
"2607:9000:f00:2::c004",
"2607:9000:f00:2::c005",
"2607:9000:f00:2::c006",
"2607:9000:f00:2::c007",
"2607:9000:f00:2::c008",
"2607:9000:f00:2::c009",
"2607:9000:f00:2::c00a",
"2607:9000:f00:2::c00b",
"2607:9000:f00:2::c00c",
"2607:9000:f00:2::c00d",
"2607:9000:f00:2::c00e",
"2607:9000:f00:2::c00f",
"2607:9000:f00:2::c010",
"2607:9000:f00:2::c011",
"2607:9000:f00:2::c012",
"2607:9000:f00:2::c013",
"2607:9000:f00:2::c014",
"2607:9000:f00:2::c015",
"2607:9000:f00:2::c016",
"2607:9000:f00:2::c017",
"2607:9000:f00:2::c018",
"2607:9000:f00:2::c019",
"2607:9000:f00:2::c01a",
"2607:9000:f00:2::c01b",
"2607:9000:f00:2::c01c",
"2607:9000:f00:2::c01d",
"2607:9000:f00:2::c01e",
"2607:9000:f00:2::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "ca-mtr-wg-301.blockerad.eu"
}
}
},
{
"hostname": "ca-mtr-wg-302",
"location": "ca-mtr",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.120.127",
"include_in_country": true,
"weight": 100,
"public_key": "ihfPUEJ+SOFLzpb6ATGKX1/aAOA2MiTgm36yxmMdNUs=",
"ipv6_addr_in": "2607:9000:f00:3::f001",
"shadowsocks_extra_addr_in": [
"23.234.120.130",
"23.234.120.131",
"23.234.120.132",
"23.234.120.133",
"23.234.120.134",
"23.234.120.135",
"23.234.120.136",
"23.234.120.137",
"23.234.120.138",
"23.234.120.139",
"23.234.120.140",
"23.234.120.141",
"23.234.120.142",
"23.234.120.143",
"23.234.120.144",
"2607:9000:f00:3::b002",
"2607:9000:f00:3::b003",
"2607:9000:f00:3::b004",
"2607:9000:f00:3::b005",
"2607:9000:f00:3::b006",
"2607:9000:f00:3::b007",
"2607:9000:f00:3::b008",
"2607:9000:f00:3::b009",
"2607:9000:f00:3::b00a",
"2607:9000:f00:3::b00b",
"2607:9000:f00:3::b00c",
"2607:9000:f00:3::b00d",
"2607:9000:f00:3::b00e",
"2607:9000:f00:3::b00f",
"2607:9000:f00:3::b010",
"2607:9000:f00:3::b011",
"2607:9000:f00:3::b012",
"2607:9000:f00:3::b013",
"2607:9000:f00:3::b014",
"2607:9000:f00:3::b015",
"2607:9000:f00:3::b016",
"2607:9000:f00:3::b017",
"2607:9000:f00:3::b018",
"2607:9000:f00:3::b019",
"2607:9000:f00:3::b01a",
"2607:9000:f00:3::b01b",
"2607:9000:f00:3::b01c",
"2607:9000:f00:3::b01d",
"2607:9000:f00:3::b01e",
"2607:9000:f00:3::b01f"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"23.234.120.145",
"23.234.120.146",
"23.234.120.147",
"23.234.120.148",
"23.234.120.149",
"23.234.120.150",
"23.234.120.151",
"23.234.120.152",
"23.234.120.153",
"23.234.120.154",
"23.234.120.155",
"23.234.120.156",
"23.234.120.157",
"23.234.120.158",
"23.234.120.159",
"2607:9000:f00:3::c002",
"2607:9000:f00:3::c003",
"2607:9000:f00:3::c004",
"2607:9000:f00:3::c005",
"2607:9000:f00:3::c006",
"2607:9000:f00:3::c007",
"2607:9000:f00:3::c008",
"2607:9000:f00:3::c009",
"2607:9000:f00:3::c00a",
"2607:9000:f00:3::c00b",
"2607:9000:f00:3::c00c",
"2607:9000:f00:3::c00d",
"2607:9000:f00:3::c00e",
"2607:9000:f00:3::c00f",
"2607:9000:f00:3::c010",
"2607:9000:f00:3::c011",
"2607:9000:f00:3::c012",
"2607:9000:f00:3::c013",
"2607:9000:f00:3::c014",
"2607:9000:f00:3::c015",
"2607:9000:f00:3::c016",
"2607:9000:f00:3::c017",
"2607:9000:f00:3::c018",
"2607:9000:f00:3::c019",
"2607:9000:f00:3::c01a",
"2607:9000:f00:3::c01b",
"2607:9000:f00:3::c01c",
"2607:9000:f00:3::c01d",
"2607:9000:f00:3::c01e",
"2607:9000:f00:3::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "ca-mtr-wg-302.blockerad.eu"
}
}
},
{
"hostname": "ca-mtr-wg-303",
"location": "ca-mtr",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.121.2",
"include_in_country": true,
"weight": 100,
"public_key": "jS8Wn97oET0rNFD9yIoJIahbVfMc6aubJq6G7+C1PBs=",
"ipv6_addr_in": "2607:9000:f00:4::f01f",
"shadowsocks_extra_addr_in": [
"23.234.121.5",
"23.234.121.6",
"23.234.121.7",
"23.234.121.8",
"23.234.121.9",
"23.234.121.10",
"23.234.121.11",
"23.234.121.12",
"23.234.121.13",
"23.234.121.14",
"23.234.121.15",
"23.234.121.16",
"23.234.121.17",
"23.234.121.18",
"23.234.121.19",
"2607:9000:f00:4::b002",
"2607:9000:f00:4::b003",
"2607:9000:f00:4::b004",
"2607:9000:f00:4::b005",
"2607:9000:f00:4::b006",
"2607:9000:f00:4::b007",
"2607:9000:f00:4::b008",
"2607:9000:f00:4::b009",
"2607:9000:f00:4::b00a",
"2607:9000:f00:4::b00b",
"2607:9000:f00:4::b00c",
"2607:9000:f00:4::b00d",
"2607:9000:f00:4::b00e",
"2607:9000:f00:4::b00f",
"2607:9000:f00:4::b010",
"2607:9000:f00:4::b011",
"2607:9000:f00:4::b012",
"2607:9000:f00:4::b013",
"2607:9000:f00:4::b014",
"2607:9000:f00:4::b015",
"2607:9000:f00:4::b016",
"2607:9000:f00:4::b017",
"2607:9000:f00:4::b018",
"2607:9000:f00:4::b019",
"2607:9000:f00:4::b01a",
"2607:9000:f00:4::b01b",
"2607:9000:f00:4::b01c",
"2607:9000:f00:4::b01d",
"2607:9000:f00:4::b01e",
"2607:9000:f00:4::b01f"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"23.234.121.20",
"23.234.121.21",
"23.234.121.22",
"23.234.121.23",
"23.234.121.24",
"23.234.121.25",
"23.234.121.26",
"23.234.121.27",
"23.234.121.28",
"23.234.121.29",
"23.234.121.30",
"23.234.121.31",
"23.234.121.32",
"23.234.121.33",
"23.234.121.34",
"2607:9000:f00:4::c002",
"2607:9000:f00:4::c003",
"2607:9000:f00:4::c004",
"2607:9000:f00:4::c005",
"2607:9000:f00:4::c006",
"2607:9000:f00:4::c007",
"2607:9000:f00:4::c008",
"2607:9000:f00:4::c009",
"2607:9000:f00:4::c00a",
"2607:9000:f00:4::c00b",
"2607:9000:f00:4::c00c",
"2607:9000:f00:4::c00d",
"2607:9000:f00:4::c00e",
"2607:9000:f00:4::c00f",
"2607:9000:f00:4::c010",
"2607:9000:f00:4::c011",
"2607:9000:f00:4::c012",
"2607:9000:f00:4::c013",
"2607:9000:f00:4::c014",
"2607:9000:f00:4::c015",
"2607:9000:f00:4::c016",
"2607:9000:f00:4::c017",
"2607:9000:f00:4::c018",
"2607:9000:f00:4::c019",
"2607:9000:f00:4::c01a",
"2607:9000:f00:4::c01b",
"2607:9000:f00:4::c01c",
"2607:9000:f00:4::c01d",
"2607:9000:f00:4::c01e",
"2607:9000:f00:4::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "ca-mtr-wg-303.blockerad.eu"
}
}
},
{
"hostname": "ca-mtr-wg-304",
"location": "ca-mtr",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.121.127",
"include_in_country": true,
"weight": 100,
"public_key": "zY8NKWC/zDdNBBFFtH3acoZAJj2BD/AYZVOUiIRZric=",
"ipv6_addr_in": "2607:9000:f00:5::f001",
"shadowsocks_extra_addr_in": [
"23.234.121.130",
"23.234.121.131",
"23.234.121.132",
"23.234.121.133",
"23.234.121.134",
"23.234.121.135",
"23.234.121.136",
"23.234.121.137",
"23.234.121.138",
"23.234.121.139",
"23.234.121.140",
"23.234.121.141",
"23.234.121.142",
"23.234.121.143",
"23.234.121.144",
"2607:9000:f00:5::b002",
"2607:9000:f00:5::b003",
"2607:9000:f00:5::b004",
"2607:9000:f00:5::b005",
"2607:9000:f00:5::b006",
"2607:9000:f00:5::b007",
"2607:9000:f00:5::b008",
"2607:9000:f00:5::b009",
"2607:9000:f00:5::b00a",
"2607:9000:f00:5::b00b",
"2607:9000:f00:5::b00c",
"2607:9000:f00:5::b00d",
"2607:9000:f00:5::b00e",
"2607:9000:f00:5::b00f",
"2607:9000:f00:5::b010",
"2607:9000:f00:5::b011",
"2607:9000:f00:5::b012",
"2607:9000:f00:5::b013",
"2607:9000:f00:5::b014",
"2607:9000:f00:5::b015",
"2607:9000:f00:5::b016",
"2607:9000:f00:5::b017",
"2607:9000:f00:5::b018",
"2607:9000:f00:5::b019",
"2607:9000:f00:5::b01a",
"2607:9000:f00:5::b01b",
"2607:9000:f00:5::b01c",
"2607:9000:f00:5::b01d",
"2607:9000:f00:5::b01e",
"2607:9000:f00:5::b01f"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"23.234.121.145",
"23.234.121.146",
"23.234.121.147",
"23.234.121.148",
"23.234.121.149",
"23.234.121.150",
"23.234.121.151",
"23.234.121.152",
"23.234.121.153",
"23.234.121.154",
"23.234.121.155",
"23.234.121.156",
"23.234.121.157",
"23.234.121.158",
"23.234.121.159",
"2607:9000:f00:5::c002",
"2607:9000:f00:5::c003",
"2607:9000:f00:5::c004",
"2607:9000:f00:5::c005",
"2607:9000:f00:5::c006",
"2607:9000:f00:5::c007",
"2607:9000:f00:5::c008",
"2607:9000:f00:5::c009",
"2607:9000:f00:5::c00a",
"2607:9000:f00:5::c00b",
"2607:9000:f00:5::c00c",
"2607:9000:f00:5::c00d",
"2607:9000:f00:5::c00e",
"2607:9000:f00:5::c00f",
"2607:9000:f00:5::c010",
"2607:9000:f00:5::c011",
"2607:9000:f00:5::c012",
"2607:9000:f00:5::c013",
"2607:9000:f00:5::c014",
"2607:9000:f00:5::c015",
"2607:9000:f00:5::c016",
"2607:9000:f00:5::c017",
"2607:9000:f00:5::c018",
"2607:9000:f00:5::c019",
"2607:9000:f00:5::c01a",
"2607:9000:f00:5::c01b",
"2607:9000:f00:5::c01c",
"2607:9000:f00:5::c01d",
"2607:9000:f00:5::c01e",
"2607:9000:f00:5::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "ca-mtr-wg-304.blockerad.eu"
}
}
},
{
"hostname": "ca-mtr-wg-305",
"location": "ca-mtr",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.122.2",
"include_in_country": true,
"weight": 100,
"public_key": "vHxqoUcH2dHqphHD6Kj74gf8+SldQ/S2XP1nbasTSkQ=",
"ipv6_addr_in": "2607:9000:f00:6::f001",
"shadowsocks_extra_addr_in": [
"23.234.122.5",
"23.234.122.6",
"23.234.122.7",
"23.234.122.8",
"23.234.122.9",
"23.234.122.10",
"23.234.122.11",
"23.234.122.12",
"23.234.122.13",
"23.234.122.14",
"23.234.122.15",
"23.234.122.16",
"23.234.122.17",
"23.234.122.18",
"23.234.122.19",
"2607:9000:f00:6::b002",
"2607:9000:f00:6::b003",
"2607:9000:f00:6::b004",
"2607:9000:f00:6::b005",
"2607:9000:f00:6::b006",
"2607:9000:f00:6::b007",
"2607:9000:f00:6::b008",
"2607:9000:f00:6::b009",
"2607:9000:f00:6::b00a",
"2607:9000:f00:6::b00b",
"2607:9000:f00:6::b00c",
"2607:9000:f00:6::b00d",
"2607:9000:f00:6::b00e",
"2607:9000:f00:6::b00f",
"2607:9000:f00:6::b010",
"2607:9000:f00:6::b011",
"2607:9000:f00:6::b012",
"2607:9000:f00:6::b013",
"2607:9000:f00:6::b014",
"2607:9000:f00:6::b015",
"2607:9000:f00:6::b016",
"2607:9000:f00:6::b017",
"2607:9000:f00:6::b018",
"2607:9000:f00:6::b019",
"2607:9000:f00:6::b01a",
"2607:9000:f00:6::b01b",
"2607:9000:f00:6::b01c",
"2607:9000:f00:6::b01d",
"2607:9000:f00:6::b01e",
"2607:9000:f00:6::b01f"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"23.234.122.20",
"23.234.122.21",
"23.234.122.22",
"23.234.122.23",
"23.234.122.24",
"23.234.122.25",
"23.234.122.26",
"23.234.122.27",
"23.234.122.28",
"23.234.122.29",
"23.234.122.30",
"23.234.122.31",
"23.234.122.32",
"23.234.122.33",
"23.234.122.34",
"2607:9000:f00:6::c002",
"2607:9000:f00:6::c003",
"2607:9000:f00:6::c004",
"2607:9000:f00:6::c005",
"2607:9000:f00:6::c006",
"2607:9000:f00:6::c007",
"2607:9000:f00:6::c008",
"2607:9000:f00:6::c009",
"2607:9000:f00:6::c00a",
"2607:9000:f00:6::c00b",
"2607:9000:f00:6::c00c",
"2607:9000:f00:6::c00d",
"2607:9000:f00:6::c00e",
"2607:9000:f00:6::c00f",
"2607:9000:f00:6::c010",
"2607:9000:f00:6::c011",
"2607:9000:f00:6::c012",
"2607:9000:f00:6::c013",
"2607:9000:f00:6::c014",
"2607:9000:f00:6::c015",
"2607:9000:f00:6::c016",
"2607:9000:f00:6::c017",
"2607:9000:f00:6::c018",
"2607:9000:f00:6::c019",
"2607:9000:f00:6::c01a",
"2607:9000:f00:6::c01b",
"2607:9000:f00:6::c01c",
"2607:9000:f00:6::c01d",
"2607:9000:f00:6::c01e",
"2607:9000:f00:6::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "ca-mtr-wg-305.blockerad.eu"
}
}
},
{
"hostname": "ca-mtr-wg-306",
"location": "ca-mtr",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.122.127",
"include_in_country": true,
"weight": 100,
"public_key": "R4SOqKLtNuNSPg1L9/4mK56nahUN9uEFleuZorBXOjM=",
"ipv6_addr_in": "2607:9000:f00:7::f001",
"shadowsocks_extra_addr_in": [
"23.234.122.130",
"23.234.122.131",
"23.234.122.132",
"23.234.122.133",
"23.234.122.134",
"23.234.122.135",
"23.234.122.136",
"23.234.122.137",
"23.234.122.138",
"23.234.122.139",
"23.234.122.140",
"23.234.122.141",
"23.234.122.142",
"23.234.122.143",
"23.234.122.144",
"2607:9000:f00:7::b002",
"2607:9000:f00:7::b003",
"2607:9000:f00:7::b004",
"2607:9000:f00:7::b005",
"2607:9000:f00:7::b006",
"2607:9000:f00:7::b007",
"2607:9000:f00:7::b008",
"2607:9000:f00:7::b009",
"2607:9000:f00:7::b00a",
"2607:9000:f00:7::b00b",
"2607:9000:f00:7::b00c",
"2607:9000:f00:7::b00d",
"2607:9000:f00:7::b00e",
"2607:9000:f00:7::b00f",
"2607:9000:f00:7::b010",
"2607:9000:f00:7::b011",
"2607:9000:f00:7::b012",
"2607:9000:f00:7::b013",
"2607:9000:f00:7::b014",
"2607:9000:f00:7::b015",
"2607:9000:f00:7::b016",
"2607:9000:f00:7::b017",
"2607:9000:f00:7::b018",
"2607:9000:f00:7::b019",
"2607:9000:f00:7::b01a",
"2607:9000:f00:7::b01b",
"2607:9000:f00:7::b01c",
"2607:9000:f00:7::b01d",
"2607:9000:f00:7::b01e",
"2607:9000:f00:7::b01f"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"23.234.122.130",
"23.234.122.131",
"23.234.122.132",
"23.234.122.133",
"23.234.122.134",
"23.234.122.135",
"23.234.122.136",
"23.234.122.137",
"23.234.122.138",
"23.234.122.139",
"23.234.122.140",
"23.234.122.141",
"23.234.122.142",
"23.234.122.143",
"23.234.122.144",
"2607:9000:f00:7::b002",
"2607:9000:f00:7::b003",
"2607:9000:f00:7::b004",
"2607:9000:f00:7::b005",
"2607:9000:f00:7::b006",
"2607:9000:f00:7::b007",
"2607:9000:f00:7::b008",
"2607:9000:f00:7::b009",
"2607:9000:f00:7::b00a",
"2607:9000:f00:7::b00b",
"2607:9000:f00:7::b00c",
"2607:9000:f00:7::b00d",
"2607:9000:f00:7::b00e",
"2607:9000:f00:7::b00f",
"2607:9000:f00:7::b010",
"2607:9000:f00:7::b011",
"2607:9000:f00:7::b012",
"2607:9000:f00:7::b013",
"2607:9000:f00:7::b014",
"2607:9000:f00:7::b015",
"2607:9000:f00:7::b016",
"2607:9000:f00:7::b017",
"2607:9000:f00:7::b018",
"2607:9000:f00:7::b019",
"2607:9000:f00:7::b01a",
"2607:9000:f00:7::b01b",
"2607:9000:f00:7::b01c",
"2607:9000:f00:7::b01d",
"2607:9000:f00:7::b01e",
"2607:9000:f00:7::b01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "ca-mtr-wg-306.blockerad.eu"
}
}
},
{
"hostname": "ca-mtr-wg-307",
"location": "ca-mtr",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.123.2",
"include_in_country": true,
"weight": 100,
"public_key": "MRbFe1jzuvCprXrnW2H6TpQnWx5MBwjYS+iIAhtrejc=",
"ipv6_addr_in": "2607:9000:f00:8::f001",
"shadowsocks_extra_addr_in": [
"23.234.123.5",
"23.234.123.6",
"23.234.123.7",
"23.234.123.8",
"23.234.123.9",
"23.234.123.10",
"23.234.123.11",
"23.234.123.12",
"23.234.123.13",
"23.234.123.14",
"23.234.123.15",
"23.234.123.16",
"23.234.123.17",
"23.234.123.18",
"23.234.123.19",
"2607:9000:f00:8::b002",
"2607:9000:f00:8::b003",
"2607:9000:f00:8::b004",
"2607:9000:f00:8::b005",
"2607:9000:f00:8::b006",
"2607:9000:f00:8::b007",
"2607:9000:f00:8::b008",
"2607:9000:f00:8::b009",
"2607:9000:f00:8::b00a",
"2607:9000:f00:8::b00b",
"2607:9000:f00:8::b00c",
"2607:9000:f00:8::b00d",
"2607:9000:f00:8::b00e",
"2607:9000:f00:8::b00f",
"2607:9000:f00:8::b010",
"2607:9000:f00:8::b011",
"2607:9000:f00:8::b012",
"2607:9000:f00:8::b013",
"2607:9000:f00:8::b014",
"2607:9000:f00:8::b015",
"2607:9000:f00:8::b016",
"2607:9000:f00:8::b017",
"2607:9000:f00:8::b018",
"2607:9000:f00:8::b019",
"2607:9000:f00:8::b01a",
"2607:9000:f00:8::b01b",
"2607:9000:f00:8::b01c",
"2607:9000:f00:8::b01d",
"2607:9000:f00:8::b01e",
"2607:9000:f00:8::b01f"
],
"features": {
"quic": {
"addr_in": [
"23.234.123.5",
"23.234.123.6",
"23.234.123.7",
"23.234.123.8",
"23.234.123.9",
"23.234.123.10",
"23.234.123.11",
"23.234.123.12",
"23.234.123.13",
"23.234.123.14",
"23.234.123.15",
"23.234.123.16",
"23.234.123.17",
"23.234.123.18",
"23.234.123.19",
"2607:9000:f00:8::b002",
"2607:9000:f00:8::b003",
"2607:9000:f00:8::b004",
"2607:9000:f00:8::b005",
"2607:9000:f00:8::b006",
"2607:9000:f00:8::b007",
"2607:9000:f00:8::b008",
"2607:9000:f00:8::b009",
"2607:9000:f00:8::b00a",
"2607:9000:f00:8::b00b",
"2607:9000:f00:8::b00c",
"2607:9000:f00:8::b00d",
"2607:9000:f00:8::b00e",
"2607:9000:f00:8::b00f",
"2607:9000:f00:8::b010",
"2607:9000:f00:8::b011",
"2607:9000:f00:8::b012",
"2607:9000:f00:8::b013",
"2607:9000:f00:8::b014",
"2607:9000:f00:8::b015",
"2607:9000:f00:8::b016",
"2607:9000:f00:8::b017",
"2607:9000:f00:8::b018",
"2607:9000:f00:8::b019",
"2607:9000:f00:8::b01a",
"2607:9000:f00:8::b01b",
"2607:9000:f00:8::b01c",
"2607:9000:f00:8::b01d",
"2607:9000:f00:8::b01e",
"2607:9000:f00:8::b01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "ca-mtr-wg-307.blockerad.eu"
}
}
},
{
"hostname": "ca-mtr-wg-308",
"location": "ca-mtr",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.123.127",
"include_in_country": true,
"weight": 100,
"public_key": "lyOeQQ2eGQgEdV+uH/S7UPOPMCsRWkDSQiZhPTUT0AI=",
"ipv6_addr_in": "2607:9000:f00:9::f001",
"shadowsocks_extra_addr_in": [
"23.234.123.130",
"23.234.123.131",
"23.234.123.132",
"23.234.123.133",
"23.234.123.134",
"23.234.123.135",
"23.234.123.136",
"23.234.123.137",
"23.234.123.138",
"23.234.123.139",
"23.234.123.140",
"23.234.123.141",
"23.234.123.142",
"23.234.123.143",
"23.234.123.144",
"2607:9000:f00:9::b002",
"2607:9000:f00:9::b003",
"2607:9000:f00:9::b004",
"2607:9000:f00:9::b005",
"2607:9000:f00:9::b006",
"2607:9000:f00:9::b007",
"2607:9000:f00:9::b008",
"2607:9000:f00:9::b009",
"2607:9000:f00:9::b00a",
"2607:9000:f00:9::b00b",
"2607:9000:f00:9::b00c",
"2607:9000:f00:9::b00d",
"2607:9000:f00:9::b00e",
"2607:9000:f00:9::b00f",
"2607:9000:f00:9::b010",
"2607:9000:f00:9::b011",
"2607:9000:f00:9::b012",
"2607:9000:f00:9::b013",
"2607:9000:f00:9::b014",
"2607:9000:f00:9::b015",
"2607:9000:f00:9::b016",
"2607:9000:f00:9::b017",
"2607:9000:f00:9::b018",
"2607:9000:f00:9::b019",
"2607:9000:f00:9::b01a",
"2607:9000:f00:9::b01b",
"2607:9000:f00:9::b01c",
"2607:9000:f00:9::b01d",
"2607:9000:f00:9::b01e",
"2607:9000:f00:9::b01f"
],
"features": {
"quic": {
"addr_in": [
"23.234.123.130",
"23.234.123.131",
"23.234.123.132",
"23.234.123.133",
"23.234.123.134",
"23.234.123.135",
"23.234.123.136",
"23.234.123.137",
"23.234.123.138",
"23.234.123.139",
"23.234.123.140",
"23.234.123.141",
"23.234.123.142",
"23.234.123.143",
"23.234.123.144",
"2607:9000:f00:9::b002",
"2607:9000:f00:9::b003",
"2607:9000:f00:9::b004",
"2607:9000:f00:9::b005",
"2607:9000:f00:9::b006",
"2607:9000:f00:9::b007",
"2607:9000:f00:9::b008",
"2607:9000:f00:9::b009",
"2607:9000:f00:9::b00a",
"2607:9000:f00:9::b00b",
"2607:9000:f00:9::b00c",
"2607:9000:f00:9::b00d",
"2607:9000:f00:9::b00e",
"2607:9000:f00:9::b00f",
"2607:9000:f00:9::b010",
"2607:9000:f00:9::b011",
"2607:9000:f00:9::b012",
"2607:9000:f00:9::b013",
"2607:9000:f00:9::b014",
"2607:9000:f00:9::b015",
"2607:9000:f00:9::b016",
"2607:9000:f00:9::b017",
"2607:9000:f00:9::b018",
"2607:9000:f00:9::b019",
"2607:9000:f00:9::b01a",
"2607:9000:f00:9::b01b",
"2607:9000:f00:9::b01c",
"2607:9000:f00:9::b01d",
"2607:9000:f00:9::b01e",
"2607:9000:f00:9::b01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "ca-mtr-wg-308.blockerad.eu"
}
}
},
{
"hostname": "ca-tor-wg-001",
"location": "ca-tor",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "178.249.214.2",
"include_in_country": true,
"weight": 100,
"public_key": "HjcUGVDXWdrRkaKNpc/8494RM5eICO6DPyrhCtTv9Ws=",
"ipv6_addr_in": "2a02:6ea0:de08:1::f001",
"daita": true,
"features": {
"daita": {}
}
},
{
"hostname": "ca-tor-wg-002",
"location": "ca-tor",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "178.249.214.15",
"include_in_country": true,
"weight": 100,
"public_key": "iqZSgVlU9H67x/uYE5xsnzLCDXf7FL9iMfyKfl6WsV8=",
"ipv6_addr_in": "2a02:6ea0:de08:2::a29f"
},
{
"hostname": "ca-tor-wg-201",
"location": "ca-tor",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.84.2",
"include_in_country": true,
"weight": 100,
"public_key": "94nJF3WyWKsZQOFhWWco8cjBOrSYADsMSTeivfbWQyw=",
"ipv6_addr_in": "2607:9000:600:31::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"23.234.84.13"
],
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"23.234.84.12",
"2607:9000:600:31::f00a"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "ca-tor-wg-201.blockerad.eu"
}
}
},
{
"hostname": "ca-tor-wg-202",
"location": "ca-tor",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.84.127",
"include_in_country": true,
"weight": 100,
"public_key": "vr/sAm+36c3N8jWfo14Sw6El0xJeSvu/soU/8JWSb3U=",
"ipv6_addr_in": "2607:9000:600:32::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"23.234.84.138"
],
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"23.234.84.137"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "ca-tor-wg-202.blockerad.eu"
}
}
},
{
"hostname": "ca-tor-wg-203",
"location": "ca-tor",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.85.2",
"include_in_country": true,
"weight": 100,
"public_key": "kpXVJa66qgBFlwCmHx6siJT3R9afvtbjdDOTKkkbiUI=",
"ipv6_addr_in": "2607:9000:600:33::f001",
"shadowsocks_extra_addr_in": [
"23.234.85.13"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"23.234.85.12"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "ca-tor-wg-203.blockerad.eu"
}
}
},
{
"hostname": "ca-tor-wg-204",
"location": "ca-tor",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.85.127",
"include_in_country": true,
"weight": 100,
"public_key": "APcoI2H2zdWIMdVYXslcJm4zzgePc4PESsDHgkm0UnQ=",
"ipv6_addr_in": "2607:9000:600:34::f001",
"shadowsocks_extra_addr_in": [
"23.234.85.138"
],
"features": {
"quic": {
"addr_in": [
"23.234.85.137"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "ca-tor-wg-204.blockerad.eu"
}
}
},
{
"hostname": "ca-tor-wg-205",
"location": "ca-tor",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.86.2",
"include_in_country": true,
"weight": 100,
"public_key": "iePZCguBaIxO/7gqQGDDYwl6YzMZj5910nK2Q9bDP14=",
"ipv6_addr_in": "2607:9000:600:35::f001",
"shadowsocks_extra_addr_in": [
"23.234.86.13"
],
"features": {
"quic": {
"addr_in": [
"23.234.86.12"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "ca-tor-wg-205.blockerad.eu"
}
}
},
{
"hostname": "ca-tor-wg-206",
"location": "ca-tor",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.86.127",
"include_in_country": true,
"weight": 100,
"public_key": "PGPyMyMPZ7Lue4pvFK7hlavToQ5FfBODmQBoiaUZ40I=",
"ipv6_addr_in": "2607:9000:600:36::f001",
"shadowsocks_extra_addr_in": [
"23.234.86.138"
],
"features": {
"quic": {
"addr_in": [
"23.234.86.137"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "ca-tor-wg-206.blockerad.eu"
}
}
},
{
"hostname": "ca-tor-wg-207",
"location": "ca-tor",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.87.2",
"include_in_country": true,
"weight": 100,
"public_key": "8VmxIxjz5W44ubaBuIt5JEngh7fKCvdmdG9WBN2oqhw=",
"ipv6_addr_in": "2607:9000:600:37::f001",
"shadowsocks_extra_addr_in": [
"23.234.87.13"
],
"features": {
"quic": {
"addr_in": [
"23.234.87.12",
"2607:9000:600:37::f00a"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "ca-tor-wg-207.blockerad.eu"
}
}
},
{
"hostname": "ca-van-wg-201",
"location": "ca-van",
"active": true,
"owned": false,
"provider": "techfutures",
"stboot": true,
"ipv4_addr_in": "104.193.135.196",
"include_in_country": true,
"weight": 100,
"public_key": "hYbb2NQKB0g2RefngdHl3bfaLImUuzeVIv2i1VCVIlQ=",
"ipv6_addr_in": "2606:9580:103:e::f001"
},
{
"hostname": "ca-van-wg-202",
"location": "ca-van",
"active": true,
"owned": false,
"provider": "techfutures",
"stboot": true,
"ipv4_addr_in": "104.193.135.100",
"include_in_country": true,
"weight": 100,
"public_key": "wGqcNxXH7A3bSptHZo7Dfmymy/Y30Ea/Zd47UkyEbzo=",
"ipv6_addr_in": "2606:9580:103:f::f001"
},
{
"hostname": "ca-van-wg-301",
"location": "ca-van",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "149.22.81.194",
"include_in_country": true,
"weight": 100,
"public_key": "BzYINbABQiSbRLDZIlmgsLgL88offQJCEH3JkcjRGUk=",
"ipv6_addr_in": "2a02:6ea0:5100:1::f001",
"daita": true,
"features": {
"daita": {}
}
},
{
"hostname": "ca-van-wg-302",
"location": "ca-van",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "149.22.81.207",
"include_in_country": true,
"weight": 100,
"public_key": "EOOkxbmbdHmjb8F45s33yKrIzKWH6lGIgJf2kTOxwFw=",
"ipv6_addr_in": "2a02:6ea0:5100:2::f001"
},
{
"hostname": "ca-yyc-wg-201",
"location": "ca-yyc",
"active": true,
"owned": false,
"provider": "techfutures",
"stboot": true,
"ipv4_addr_in": "38.240.225.36",
"include_in_country": true,
"weight": 100,
"public_key": "L4RcVwk0cJJp2u8O9+86sdyUpxfYnr+ME57Ex0RY1Wo=",
"ipv6_addr_in": "2606:9580:438:32::f001",
"shadowsocks_extra_addr_in": [
"2606:9580:438:32::b002",
"2606:9580:438:32::b003",
"2606:9580:438:32::b004",
"2606:9580:438:32::b005",
"2606:9580:438:32::b006",
"2606:9580:438:32::b007",
"2606:9580:438:32::b008",
"2606:9580:438:32::b009",
"2606:9580:438:32::b00a",
"2606:9580:438:32::b00b",
"2606:9580:438:32::b00c",
"2606:9580:438:32::b00d",
"2606:9580:438:32::b00e",
"2606:9580:438:32::b00f",
"2606:9580:438:32::b010",
"2606:9580:438:32::b011",
"2606:9580:438:32::b012",
"2606:9580:438:32::b013",
"2606:9580:438:32::b014",
"2606:9580:438:32::b015",
"2606:9580:438:32::b016",
"2606:9580:438:32::b017",
"2606:9580:438:32::b018",
"2606:9580:438:32::b019",
"2606:9580:438:32::b01a",
"2606:9580:438:32::b01b",
"2606:9580:438:32::b01c",
"2606:9580:438:32::b01d",
"2606:9580:438:32::b01e"
]
},
{
"hostname": "ca-yyc-wg-202",
"location": "ca-yyc",
"active": true,
"owned": false,
"provider": "techfutures",
"stboot": true,
"ipv4_addr_in": "38.240.225.68",
"include_in_country": true,
"weight": 100,
"public_key": "u9J/fzrSqM2aEFjTs91KEKgBsaQ/I/4XkIP1Z/zYkXA=",
"ipv6_addr_in": "2606:9580:438:64::f001",
"shadowsocks_extra_addr_in": [
"2606:9580:438:64::b002",
"2606:9580:438:64::b003",
"2606:9580:438:64::b004",
"2606:9580:438:64::b005",
"2606:9580:438:64::b006",
"2606:9580:438:64::b007",
"2606:9580:438:64::b008",
"2606:9580:438:64::b009",
"2606:9580:438:64::b00a",
"2606:9580:438:64::b00b",
"2606:9580:438:64::b00c",
"2606:9580:438:64::b00d",
"2606:9580:438:64::b00e",
"2606:9580:438:64::b00f",
"2606:9580:438:64::b010",
"2606:9580:438:64::b011",
"2606:9580:438:64::b012",
"2606:9580:438:64::b013",
"2606:9580:438:64::b014",
"2606:9580:438:64::b015",
"2606:9580:438:64::b016",
"2606:9580:438:64::b017",
"2606:9580:438:64::b018",
"2606:9580:438:64::b019",
"2606:9580:438:64::b01a",
"2606:9580:438:64::b01b",
"2606:9580:438:64::b01c",
"2606:9580:438:64::b01d",
"2606:9580:438:64::b01e",
"2606:9580:438:64::b01f"
],
"features": {
"lwo": {}
}
},
{
"hostname": "ch-zrh-wg-001",
"location": "ch-zrh",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "193.32.127.66",
"include_in_country": true,
"weight": 1,
"public_key": "/iivwlyqWqxQ0BVWmJRhcXIFdJeo0WbHQ/hZwuXaN3g=",
"ipv6_addr_in": "2a03:1b20:a:f011::f001",
"shadowsocks_extra_addr_in": [
"2a03:1b20:a:f011::b002",
"2a03:1b20:a:f011::b003",
"2a03:1b20:a:f011::b004",
"2a03:1b20:a:f011::b005",
"2a03:1b20:a:f011::b006",
"2a03:1b20:a:f011::b007",
"2a03:1b20:a:f011::b008",
"2a03:1b20:a:f011::b009",
"2a03:1b20:a:f011::b00a",
"2a03:1b20:a:f011::b00b",
"2a03:1b20:a:f011::b00c",
"2a03:1b20:a:f011::b00d",
"2a03:1b20:a:f011::b00e",
"2a03:1b20:a:f011::b00f",
"2a03:1b20:a:f011::b010",
"2a03:1b20:a:f011::b011",
"2a03:1b20:a:f011::b012",
"2a03:1b20:a:f011::b013",
"2a03:1b20:a:f011::b014",
"2a03:1b20:a:f011::b015",
"2a03:1b20:a:f011::b016",
"2a03:1b20:a:f011::b017",
"2a03:1b20:a:f011::b018",
"2a03:1b20:a:f011::b019",
"2a03:1b20:a:f011::b01a",
"2a03:1b20:a:f011::b01b",
"2a03:1b20:a:f011::b01c",
"2a03:1b20:a:f011::b01d",
"2a03:1b20:a:f011::b01e",
"2a03:1b20:a:f011::b01f"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"193.32.127.99",
"2a03:1b20:a:f011::c002",
"2a03:1b20:a:f011::c003",
"2a03:1b20:a:f011::c004",
"2a03:1b20:a:f011::c005",
"2a03:1b20:a:f011::c006",
"2a03:1b20:a:f011::c007",
"2a03:1b20:a:f011::c008",
"2a03:1b20:a:f011::c009",
"2a03:1b20:a:f011::c00a",
"2a03:1b20:a:f011::c00b",
"2a03:1b20:a:f011::c00c",
"2a03:1b20:a:f011::c00d",
"2a03:1b20:a:f011::c00e",
"2a03:1b20:a:f011::c00f",
"2a03:1b20:a:f011::c010",
"2a03:1b20:a:f011::c011",
"2a03:1b20:a:f011::c012",
"2a03:1b20:a:f011::c013",
"2a03:1b20:a:f011::c014",
"2a03:1b20:a:f011::c015",
"2a03:1b20:a:f011::c016",
"2a03:1b20:a:f011::c017",
"2a03:1b20:a:f011::c018",
"2a03:1b20:a:f011::c019",
"2a03:1b20:a:f011::c01a",
"2a03:1b20:a:f011::c01b",
"2a03:1b20:a:f011::c01c",
"2a03:1b20:a:f011::c01d",
"2a03:1b20:a:f011::c01e",
"2a03:1b20:a:f011::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "ch-zrh-wg-001.blockerad.eu"
}
}
},
{
"hostname": "ch-zrh-wg-002",
"location": "ch-zrh",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "193.32.127.67",
"include_in_country": true,
"weight": 1,
"public_key": "qcvI02LwBnTb7aFrOyZSWvg4kb7zNW9/+rS6alnWyFE=",
"ipv6_addr_in": "2a03:1b20:a:f011::f101",
"shadowsocks_extra_addr_in": [
"2a03:1b20:a:f011::b102",
"2a03:1b20:a:f011::b103",
"2a03:1b20:a:f011::b104",
"2a03:1b20:a:f011::b105",
"2a03:1b20:a:f011::b106",
"2a03:1b20:a:f011::b107",
"2a03:1b20:a:f011::b108",
"2a03:1b20:a:f011::b109",
"2a03:1b20:a:f011::b10a",
"2a03:1b20:a:f011::b10b",
"2a03:1b20:a:f011::b10c",
"2a03:1b20:a:f011::b10d",
"2a03:1b20:a:f011::b10e",
"2a03:1b20:a:f011::b10f",
"2a03:1b20:a:f011::b110",
"2a03:1b20:a:f011::b111",
"2a03:1b20:a:f011::b112",
"2a03:1b20:a:f011::b113",
"2a03:1b20:a:f011::b114",
"2a03:1b20:a:f011::b115",
"2a03:1b20:a:f011::b116",
"2a03:1b20:a:f011::b117",
"2a03:1b20:a:f011::b118",
"2a03:1b20:a:f011::b119",
"2a03:1b20:a:f011::b11a",
"2a03:1b20:a:f011::b11b",
"2a03:1b20:a:f011::b11c",
"2a03:1b20:a:f011::b11d",
"2a03:1b20:a:f011::b11e",
"2a03:1b20:a:f011::b11f"
],
"features": {
"lwo": {}
}
},
{
"hostname": "ch-zrh-wg-003",
"location": "ch-zrh",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "193.32.127.68",
"include_in_country": true,
"weight": 1,
"public_key": "5Ms10UxGjCSzwImTrvEjcygsWY8AfMIdYyRvgFuTqH8=",
"ipv6_addr_in": "2a03:1b20:a:f011::f201",
"shadowsocks_extra_addr_in": [
"2a03:1b20:a:f011::b202",
"2a03:1b20:a:f011::b203",
"2a03:1b20:a:f011::b204",
"2a03:1b20:a:f011::b205",
"2a03:1b20:a:f011::b206",
"2a03:1b20:a:f011::b207",
"2a03:1b20:a:f011::b208",
"2a03:1b20:a:f011::b209",
"2a03:1b20:a:f011::b20a",
"2a03:1b20:a:f011::b20b",
"2a03:1b20:a:f011::b20c",
"2a03:1b20:a:f011::b20d",
"2a03:1b20:a:f011::b20e",
"2a03:1b20:a:f011::b20f",
"2a03:1b20:a:f011::b210",
"2a03:1b20:a:f011::b211",
"2a03:1b20:a:f011::b212",
"2a03:1b20:a:f011::b213",
"2a03:1b20:a:f011::b214",
"2a03:1b20:a:f011::b215",
"2a03:1b20:a:f011::b216",
"2a03:1b20:a:f011::b217",
"2a03:1b20:a:f011::b218",
"2a03:1b20:a:f011::b219",
"2a03:1b20:a:f011::b21a",
"2a03:1b20:a:f011::b21b",
"2a03:1b20:a:f011::b21c",
"2a03:1b20:a:f011::b21d",
"2a03:1b20:a:f011::b21e",
"2a03:1b20:a:f011::b21f"
],
"features": {
"lwo": {}
}
},
{
"hostname": "ch-zrh-wg-004",
"location": "ch-zrh",
"active": false,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "193.32.127.69",
"include_in_country": true,
"weight": 50,
"public_key": "C3jAgPirUZG6sNYe4VuAgDEYunENUyG34X42y+SBngQ=",
"ipv6_addr_in": "2a03:1b20:a:f011::f301",
"daita": true,
"shadowsocks_extra_addr_in": [
"2a03:1b20:a:f011::b302",
"2a03:1b20:a:f011::b303",
"2a03:1b20:a:f011::b304",
"2a03:1b20:a:f011::b305",
"2a03:1b20:a:f011::b306",
"2a03:1b20:a:f011::b307",
"2a03:1b20:a:f011::b308",
"2a03:1b20:a:f011::b309",
"2a03:1b20:a:f011::b30a",
"2a03:1b20:a:f011::b30b",
"2a03:1b20:a:f011::b30c",
"2a03:1b20:a:f011::b30d",
"2a03:1b20:a:f011::b30e",
"2a03:1b20:a:f011::b30f",
"2a03:1b20:a:f011::b310",
"2a03:1b20:a:f011::b311",
"2a03:1b20:a:f011::b312",
"2a03:1b20:a:f011::b313",
"2a03:1b20:a:f011::b314",
"2a03:1b20:a:f011::b315",
"2a03:1b20:a:f011::b316",
"2a03:1b20:a:f011::b317",
"2a03:1b20:a:f011::b318",
"2a03:1b20:a:f011::b319",
"2a03:1b20:a:f011::b31a",
"2a03:1b20:a:f011::b31b",
"2a03:1b20:a:f011::b31c",
"2a03:1b20:a:f011::b31d",
"2a03:1b20:a:f011::b31e",
"2a03:1b20:a:f011::b31f"
],
"features": {
"daita": {},
"lwo": {}
}
},
{
"hostname": "ch-zrh-wg-005",
"location": "ch-zrh",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "193.32.127.70",
"include_in_country": true,
"weight": 50,
"public_key": "dV/aHhwG0fmp0XuvSvrdWjCtdyhPDDFiE/nuv/1xnRM=",
"ipv6_addr_in": "2a03:1b20:a:f011::f401",
"daita": true,
"shadowsocks_extra_addr_in": [
"2a03:1b20:a:f011::b402",
"2a03:1b20:a:f011::b403",
"2a03:1b20:a:f011::b404",
"2a03:1b20:a:f011::b405",
"2a03:1b20:a:f011::b406",
"2a03:1b20:a:f011::b407",
"2a03:1b20:a:f011::b408",
"2a03:1b20:a:f011::b409",
"2a03:1b20:a:f011::b40a",
"2a03:1b20:a:f011::b40b",
"2a03:1b20:a:f011::b40c",
"2a03:1b20:a:f011::b40d",
"2a03:1b20:a:f011::b40e",
"2a03:1b20:a:f011::b40f",
"2a03:1b20:a:f011::b410",
"2a03:1b20:a:f011::b411",
"2a03:1b20:a:f011::b412",
"2a03:1b20:a:f011::b413",
"2a03:1b20:a:f011::b414",
"2a03:1b20:a:f011::b415",
"2a03:1b20:a:f011::b416",
"2a03:1b20:a:f011::b417",
"2a03:1b20:a:f011::b418",
"2a03:1b20:a:f011::b419",
"2a03:1b20:a:f011::b41a",
"2a03:1b20:a:f011::b41b",
"2a03:1b20:a:f011::b41c",
"2a03:1b20:a:f011::b41d",
"2a03:1b20:a:f011::b41e",
"2a03:1b20:a:f011::b41f"
],
"features": {
"daita": {},
"lwo": {}
}
},
{
"hostname": "ch-zrh-wg-006",
"location": "ch-zrh",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "193.32.127.84",
"include_in_country": true,
"weight": 50,
"public_key": "wDjbvO94t0UI1RlimpEFFv7kJ6DngthvuRX6uBN0wAA=",
"ipv6_addr_in": "2a03:1b20:a:f011::f601",
"daita": true,
"shadowsocks_extra_addr_in": [
"2a03:1b20:a:f011::b602",
"2a03:1b20:a:f011::b603",
"2a03:1b20:a:f011::b604",
"2a03:1b20:a:f011::b605",
"2a03:1b20:a:f011::b606",
"2a03:1b20:a:f011::b607",
"2a03:1b20:a:f011::b608",
"2a03:1b20:a:f011::b609",
"2a03:1b20:a:f011::b60a",
"2a03:1b20:a:f011::b60b",
"2a03:1b20:a:f011::b60c",
"2a03:1b20:a:f011::b60d",
"2a03:1b20:a:f011::b60e",
"2a03:1b20:a:f011::b60f",
"2a03:1b20:a:f011::b610",
"2a03:1b20:a:f011::b611",
"2a03:1b20:a:f011::b612",
"2a03:1b20:a:f011::b613",
"2a03:1b20:a:f011::b614",
"2a03:1b20:a:f011::b615",
"2a03:1b20:a:f011::b616",
"2a03:1b20:a:f011::b617",
"2a03:1b20:a:f011::b618",
"2a03:1b20:a:f011::b619",
"2a03:1b20:a:f011::b61a",
"2a03:1b20:a:f011::b61b",
"2a03:1b20:a:f011::b61c",
"2a03:1b20:a:f011::b61d",
"2a03:1b20:a:f011::b61e",
"2a03:1b20:a:f011::b61f"
],
"features": {
"daita": {},
"lwo": {}
}
},
{
"hostname": "ch-zrh-wg-201",
"location": "ch-zrh",
"active": true,
"owned": false,
"provider": "PrivateLayer",
"stboot": true,
"ipv4_addr_in": "179.43.189.66",
"include_in_country": true,
"weight": 100,
"public_key": "66NPINP4+1AlojLP0J6O9GxdloiegNnGMV4Yit9Kzg0=",
"ipv6_addr_in": "2a02:29b8:dc01:1832::f001",
"shadowsocks_extra_addr_in": [
"2a02:29b8:dc01:1831::b002",
"2a02:29b8:dc01:1831::b003",
"2a02:29b8:dc01:1831::b004",
"2a02:29b8:dc01:1831::b005",
"2a02:29b8:dc01:1831::b006",
"2a02:29b8:dc01:1831::b007",
"2a02:29b8:dc01:1831::b008",
"2a02:29b8:dc01:1831::b009",
"2a02:29b8:dc01:1831::b00a",
"2a02:29b8:dc01:1831::b00b",
"2a02:29b8:dc01:1831::b00c",
"2a02:29b8:dc01:1831::b00d",
"2a02:29b8:dc01:1831::b00e",
"2a02:29b8:dc01:1831::b00f",
"2a02:29b8:dc01:1831::b010",
"2a02:29b8:dc01:1831::b011",
"2a02:29b8:dc01:1831::b012",
"2a02:29b8:dc01:1831::b013",
"2a02:29b8:dc01:1831::b014",
"2a02:29b8:dc01:1831::b015",
"2a02:29b8:dc01:1831::b016",
"2a02:29b8:dc01:1831::b017",
"2a02:29b8:dc01:1831::b018",
"2a02:29b8:dc01:1831::b019",
"2a02:29b8:dc01:1831::b01a",
"2a02:29b8:dc01:1831::b01b",
"2a02:29b8:dc01:1831::b01c",
"2a02:29b8:dc01:1831::b01d",
"2a02:29b8:dc01:1831::b01e",
"2a02:29b8:dc01:1831::b01f"
]
},
{
"hostname": "ch-zrh-wg-202",
"location": "ch-zrh",
"active": true,
"owned": false,
"provider": "PrivateLayer",
"stboot": true,
"ipv4_addr_in": "46.19.136.226",
"include_in_country": true,
"weight": 100,
"public_key": "gSLSfY2zNFRczxHndeda258z+ayMvd7DqTlKYlKWJUo=",
"ipv6_addr_in": "2a02:29b8:dc01:1831::f101",
"shadowsocks_extra_addr_in": [
"2a02:29b8:dc01:1831::b102",
"2a02:29b8:dc01:1831::b103",
"2a02:29b8:dc01:1831::b104",
"2a02:29b8:dc01:1831::b105",
"2a02:29b8:dc01:1831::b106",
"2a02:29b8:dc01:1831::b107",
"2a02:29b8:dc01:1831::b108",
"2a02:29b8:dc01:1831::b109",
"2a02:29b8:dc01:1831::b10a",
"2a02:29b8:dc01:1831::b10b",
"2a02:29b8:dc01:1831::b10c",
"2a02:29b8:dc01:1831::b10d",
"2a02:29b8:dc01:1831::b10e",
"2a02:29b8:dc01:1831::b10f",
"2a02:29b8:dc01:1831::b110",
"2a02:29b8:dc01:1831::b111",
"2a02:29b8:dc01:1831::b112",
"2a02:29b8:dc01:1831::b113",
"2a02:29b8:dc01:1831::b114",
"2a02:29b8:dc01:1831::b115",
"2a02:29b8:dc01:1831::b116",
"2a02:29b8:dc01:1831::b117",
"2a02:29b8:dc01:1831::b118",
"2a02:29b8:dc01:1831::b119",
"2a02:29b8:dc01:1831::b11a",
"2a02:29b8:dc01:1831::b11b",
"2a02:29b8:dc01:1831::b11c",
"2a02:29b8:dc01:1831::b11d",
"2a02:29b8:dc01:1831::b11e",
"2a02:29b8:dc01:1831::b11f"
]
},
{
"hostname": "ch-zrh-wg-401",
"location": "ch-zrh",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "138.199.6.194",
"include_in_country": true,
"weight": 80,
"public_key": "45ud3I5O6GmPXTrMJiqkiPMI/ubucDqzGaiq3CHJXk8=",
"ipv6_addr_in": "2a02:6ea0:d406:1::a18f",
"daita": true,
"features": {
"daita": {}
}
},
{
"hostname": "ch-zrh-wg-402",
"location": "ch-zrh",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "138.199.6.207",
"include_in_country": true,
"weight": 80,
"public_key": "7VCMEE+Oljm/qKfQJSUCOYPtRSwdOnuPyqo5Vob+GRY=",
"ipv6_addr_in": "2a02:6ea0:d406:2::a19f"
},
{
"hostname": "ch-zrh-wg-403",
"location": "ch-zrh",
"active": false,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "138.199.6.220",
"include_in_country": true,
"weight": 80,
"public_key": "Jmhds6oPu6/j94hjllJCIaKLDyWu6V+ZNRrVVFhWJkI=",
"ipv6_addr_in": "2a02:6ea0:d406:3::a20f"
},
{
"hostname": "ch-zrh-wg-404",
"location": "ch-zrh",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "138.199.6.233",
"include_in_country": true,
"weight": 80,
"public_key": "zfNQqDyPmSUY8+20wxACe/wpk4Q5jpZm5iBqjXj2hk8=",
"ipv6_addr_in": "2a02:6ea0:d406:4::a21f"
},
{
"hostname": "ch-zrh-wg-502",
"location": "ch-zrh",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "135.136.18.194",
"include_in_country": true,
"weight": 100,
"public_key": "6rXNS6RlZ9YLZQjaEbfzAmt/6izpuMg/8LYI9jBK+i0=",
"ipv6_addr_in": "2001:ac8:28:ab::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"135.136.18.227",
"135.136.18.228",
"135.136.18.229",
"135.136.18.230",
"135.136.18.231",
"135.136.18.232",
"135.136.18.233",
"135.136.18.234",
"135.136.18.235",
"135.136.18.236",
"135.136.18.237",
"135.136.18.238",
"135.136.18.239",
"135.136.18.240",
"135.136.18.241",
"135.136.18.242",
"135.136.18.243",
"135.136.18.244",
"135.136.18.245",
"135.136.18.246",
"135.136.18.247",
"135.136.18.248",
"135.136.18.249",
"135.136.18.250",
"135.136.18.251",
"135.136.18.252",
"135.136.18.253",
"2001:ac8:28:ab::b001",
"2001:ac8:28:ab::b002",
"2001:ac8:28:ab::b003",
"2001:ac8:28:ab::b004",
"2001:ac8:28:ab::b005",
"2001:ac8:28:ab::b006",
"2001:ac8:28:ab::b007",
"2001:ac8:28:ab::b008",
"2001:ac8:28:ab::b009",
"2001:ac8:28:ab::b00a",
"2001:ac8:28:ab::b00b",
"2001:ac8:28:ab::b00c",
"2001:ac8:28:ab::b00d",
"2001:ac8:28:ab::b00e",
"2001:ac8:28:ab::b00f",
"2001:ac8:28:ab::b010",
"2001:ac8:28:ab::b011",
"2001:ac8:28:ab::b012",
"2001:ac8:28:ab::b013",
"2001:ac8:28:ab::b014",
"2001:ac8:28:ab::b015",
"2001:ac8:28:ab::b016",
"2001:ac8:28:ab::b017",
"2001:ac8:28:ab::b018",
"2001:ac8:28:ab::b019",
"2001:ac8:28:ab::b01a",
"2001:ac8:28:ab::b01b",
"2001:ac8:28:ab::b01c",
"2001:ac8:28:ab::b01d",
"2001:ac8:28:ab::b01e",
"2001:ac8:28:ab::b01f"
],
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"135.136.18.206",
"135.136.18.207",
"135.136.18.208",
"135.136.18.209",
"135.136.18.210",
"135.136.18.211",
"135.136.18.212",
"135.136.18.213",
"135.136.18.214",
"135.136.18.215",
"135.136.18.216",
"135.136.18.217",
"135.136.18.218",
"135.136.18.219",
"135.136.18.220",
"135.136.18.221",
"135.136.18.222",
"135.136.18.223",
"135.136.18.224",
"135.136.18.225",
"135.136.18.226",
"2001:ac8:28:ab::c001",
"2001:ac8:28:ab::c002",
"2001:ac8:28:ab::c003",
"2001:ac8:28:ab::c004",
"2001:ac8:28:ab::c005",
"2001:ac8:28:ab::c006",
"2001:ac8:28:ab::c007",
"2001:ac8:28:ab::c008",
"2001:ac8:28:ab::c009",
"2001:ac8:28:ab::c00a",
"2001:ac8:28:ab::c00b",
"2001:ac8:28:ab::c00c",
"2001:ac8:28:ab::c00d",
"2001:ac8:28:ab::c00e",
"2001:ac8:28:ab::c00f",
"2001:ac8:28:ab::c010",
"2001:ac8:28:ab::c011",
"2001:ac8:28:ab::c012",
"2001:ac8:28:ab::c013",
"2001:ac8:28:ab::c014",
"2001:ac8:28:ab::c015",
"2001:ac8:28:ab::c016",
"2001:ac8:28:ab::c017",
"2001:ac8:28:ab::c018",
"2001:ac8:28:ab::c019",
"2001:ac8:28:ab::c01a",
"2001:ac8:28:ab::c01b",
"2001:ac8:28:ab::c01c",
"2001:ac8:28:ab::c01d",
"2001:ac8:28:ab::c01e",
"2001:ac8:28:ab::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "ch-zrh-wg-502.blockerad.eu"
}
}
},
{
"hostname": "ch-zrh-wg-503",
"location": "ch-zrh",
"active": false,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "77.243.184.2",
"include_in_country": true,
"weight": 200,
"public_key": "ybC4yewkIBN+x530P5iiDdZs3mhY6xHIZOlVHMSobg0=",
"ipv6_addr_in": "2001:ac8:28:ac::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"77.243.184.16",
"77.243.184.17",
"77.243.184.18",
"77.243.184.19",
"77.243.184.20",
"77.243.184.21",
"77.243.184.22",
"77.243.184.23",
"77.243.184.24",
"77.243.184.25",
"77.243.184.26",
"2001:ac8:28:ac::b001",
"2001:ac8:28:ac::b002",
"2001:ac8:28:ac::b003",
"2001:ac8:28:ac::b004",
"2001:ac8:28:ac::b005",
"2001:ac8:28:ac::b006",
"2001:ac8:28:ac::b007",
"2001:ac8:28:ac::b008",
"2001:ac8:28:ac::b009",
"2001:ac8:28:ac::b00a",
"2001:ac8:28:ac::b00b",
"2001:ac8:28:ac::b00c",
"2001:ac8:28:ac::b00d",
"2001:ac8:28:ac::b00e",
"2001:ac8:28:ac::b00f",
"2001:ac8:28:ac::b010",
"2001:ac8:28:ac::b011",
"2001:ac8:28:ac::b012",
"2001:ac8:28:ac::b013",
"2001:ac8:28:ac::b014",
"2001:ac8:28:ac::b015",
"2001:ac8:28:ac::b016",
"2001:ac8:28:ac::b017",
"2001:ac8:28:ac::b018",
"2001:ac8:28:ac::b019",
"2001:ac8:28:ac::b01a",
"2001:ac8:28:ac::b01b",
"2001:ac8:28:ac::b01c",
"2001:ac8:28:ac::b01d",
"2001:ac8:28:ac::b01e",
"2001:ac8:28:ac::b01f"
],
"features": {
"daita": {},
"quic": {
"addr_in": [
"77.243.184.5",
"77.243.184.6",
"77.243.184.7",
"77.243.184.8",
"77.243.184.9",
"77.243.184.10",
"77.243.184.11",
"77.243.184.12",
"77.243.184.13",
"77.243.184.14",
"77.243.184.15",
"2001:ac8:28:ac::c001",
"2001:ac8:28:ac::c002",
"2001:ac8:28:ac::c003",
"2001:ac8:28:ac::c004",
"2001:ac8:28:ac::c005",
"2001:ac8:28:ac::c006",
"2001:ac8:28:ac::c007",
"2001:ac8:28:ac::c008",
"2001:ac8:28:ac::c009",
"2001:ac8:28:ac::c00a",
"2001:ac8:28:ac::c00b",
"2001:ac8:28:ac::c00c",
"2001:ac8:28:ac::c00d",
"2001:ac8:28:ac::c00e",
"2001:ac8:28:ac::c00f",
"2001:ac8:28:ac::c010",
"2001:ac8:28:ac::c011",
"2001:ac8:28:ac::c012",
"2001:ac8:28:ac::c013",
"2001:ac8:28:ac::c014",
"2001:ac8:28:ac::c015",
"2001:ac8:28:ac::c016",
"2001:ac8:28:ac::c017",
"2001:ac8:28:ac::c018",
"2001:ac8:28:ac::c019",
"2001:ac8:28:ac::c01a",
"2001:ac8:28:ac::c01b",
"2001:ac8:28:ac::c01c",
"2001:ac8:28:ac::c01d",
"2001:ac8:28:ac::c01e",
"2001:ac8:28:ac::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "ch-zrh-wg-503.blockerad.eu"
}
}
},
{
"hostname": "ch-zrh-wg-504",
"location": "ch-zrh",
"active": false,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "77.243.184.130",
"include_in_country": true,
"weight": 200,
"public_key": "5ioE7vTw80KVx0S/zYOZonR5ZkR+uiNJogR9Pyqtwzg=",
"ipv6_addr_in": "2001:ac8:28:ad::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"77.243.184.144",
"77.243.184.145",
"77.243.184.146",
"77.243.184.147",
"77.243.184.148",
"77.243.184.149",
"77.243.184.150",
"77.243.184.151",
"77.243.184.152",
"77.243.184.153",
"77.243.184.154",
"2001:ac8:28:ad::b001",
"2001:ac8:28:ad::b002",
"2001:ac8:28:ad::b003",
"2001:ac8:28:ad::b004",
"2001:ac8:28:ad::b005",
"2001:ac8:28:ad::b006",
"2001:ac8:28:ad::b007",
"2001:ac8:28:ad::b008",
"2001:ac8:28:ad::b009",
"2001:ac8:28:ad::b00a",
"2001:ac8:28:ad::b00b",
"2001:ac8:28:ad::b00c",
"2001:ac8:28:ad::b00d",
"2001:ac8:28:ad::b00e",
"2001:ac8:28:ad::b00f",
"2001:ac8:28:ad::b010",
"2001:ac8:28:ad::b011",
"2001:ac8:28:ad::b012",
"2001:ac8:28:ad::b013",
"2001:ac8:28:ad::b014",
"2001:ac8:28:ad::b015",
"2001:ac8:28:ad::b016",
"2001:ac8:28:ad::b017",
"2001:ac8:28:ad::b018",
"2001:ac8:28:ad::b019",
"2001:ac8:28:ad::b01a",
"2001:ac8:28:ad::b01b",
"2001:ac8:28:ad::b01c",
"2001:ac8:28:ad::b01d",
"2001:ac8:28:ad::b01e",
"2001:ac8:28:ad::b01f"
],
"features": {
"daita": {},
"quic": {
"addr_in": [
"77.243.184.133",
"77.243.184.134",
"77.243.184.135",
"77.243.184.136",
"77.243.184.137",
"77.243.184.138",
"77.243.184.139",
"77.243.184.140",
"77.243.184.141",
"77.243.184.142",
"77.243.184.143",
"2001:ac8:28:ad::c001",
"2001:ac8:28:ad::c002",
"2001:ac8:28:ad::c003",
"2001:ac8:28:ad::c004",
"2001:ac8:28:ad::c005",
"2001:ac8:28:ad::c006",
"2001:ac8:28:ad::c007",
"2001:ac8:28:ad::c008",
"2001:ac8:28:ad::c009",
"2001:ac8:28:ad::c00a",
"2001:ac8:28:ad::c00b",
"2001:ac8:28:ad::c00c",
"2001:ac8:28:ad::c00d",
"2001:ac8:28:ad::c00e",
"2001:ac8:28:ad::c00f",
"2001:ac8:28:ad::c010",
"2001:ac8:28:ad::c011",
"2001:ac8:28:ad::c012",
"2001:ac8:28:ad::c013",
"2001:ac8:28:ad::c014",
"2001:ac8:28:ad::c015",
"2001:ac8:28:ad::c016",
"2001:ac8:28:ad::c017",
"2001:ac8:28:ad::c018",
"2001:ac8:28:ad::c019",
"2001:ac8:28:ad::c01a",
"2001:ac8:28:ad::c01b",
"2001:ac8:28:ad::c01c",
"2001:ac8:28:ad::c01d",
"2001:ac8:28:ad::c01e",
"2001:ac8:28:ad::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "ch-zrh-wg-504.blockerad.eu"
}
}
},
{
"hostname": "cl-scl-wg-001",
"location": "cl-scl",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "149.88.104.2",
"include_in_country": true,
"weight": 100,
"public_key": "03qeK7CSn6wcMzfqilmVt6Tf81VZIPWnSG04euSkyxM=",
"ipv6_addr_in": "2a02:6ea0:fc02:2::f001"
},
{
"hostname": "cl-scl-wg-002",
"location": "cl-scl",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "149.88.104.15",
"include_in_country": true,
"weight": 100,
"public_key": "rn9O+cXj0WQgZAkGCoYvvWgzaB5GcOaVfke3WKsp1Ro=",
"ipv6_addr_in": "2a02:6ea0:fc02:3::f101"
},
{
"hostname": "co-bog-wg-001",
"location": "co-bog",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "154.47.16.34",
"include_in_country": true,
"weight": 100,
"public_key": "iaMa84nCHK+v4TnQH4h2rxkqwwxemORXM12VbJDRZSU=",
"ipv6_addr_in": "2a02:6ea0:f101:1::f001",
"daita": true,
"features": {
"daita": {},
"lwo": {}
}
},
{
"hostname": "co-bog-wg-002",
"location": "co-bog",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "154.47.16.47",
"include_in_country": true,
"weight": 100,
"public_key": "IZDwbG9C/NrOOGVUrn+fDaPr8ZwD/yhvST7XWGk1ln8=",
"ipv6_addr_in": "2a02:6ea0:f101:2::f001",
"features": {
"lwo": {}
}
},
{
"hostname": "cy-nic-wg-001",
"location": "cy-nic",
"active": true,
"owned": false,
"provider": "HostRoyale",
"stboot": true,
"ipv4_addr_in": "195.47.194.131",
"include_in_country": true,
"weight": 100,
"public_key": "Ae9YcQjcQT+W8MU0EhKXx6KPWo6ticS1NI91e+Zy5GA=",
"ipv6_addr_in": "2a06:3040:f:601::f001",
"shadowsocks_extra_addr_in": [
"195.47.194.133"
]
},
{
"hostname": "cy-nic-wg-002",
"location": "cy-nic",
"active": true,
"owned": false,
"provider": "HostRoyale",
"stboot": true,
"ipv4_addr_in": "195.47.194.161",
"include_in_country": true,
"weight": 100,
"public_key": "LOd1SY9YCHGiJUVT+XdYRdORu6ZMw4CqOKQBW2ElLg8=",
"ipv6_addr_in": "2a06:3040:f:601::f101",
"shadowsocks_extra_addr_in": [
"195.47.194.163"
]
},
{
"hostname": "cz-prg-wg-101",
"location": "cz-prg",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.129.98",
"include_in_country": true,
"weight": 100,
"public_key": "tWVga+pS/Ztrbx/L/PBlaWPGhkI3PCPBzbQlCeXWqn8=",
"ipv6_addr_in": "2001:ac8:33:c::a01f",
"features": {
"lwo": {}
}
},
{
"hostname": "cz-prg-wg-102",
"location": "cz-prg",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.129.130",
"include_in_country": true,
"weight": 100,
"public_key": "cRCJ0vULwKRbTfzuo9W+fIt0fJGQE7DLvojIiURIpiI=",
"ipv6_addr_in": "2001:ac8:33:d::a02f",
"features": {
"lwo": {},
"quic": {
"addr_in": [
"146.70.129.158"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "cz-prg-wg-102.blockerad.eu"
}
}
},
{
"hostname": "cz-prg-wg-201",
"location": "cz-prg",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "178.249.209.162",
"include_in_country": true,
"weight": 100,
"public_key": "5FZW+fNA2iVBSY99HFl+KjGc9AFVNE+UFAedLNhu8lc=",
"ipv6_addr_in": "2a02:6ea0:c201:1::f001"
},
{
"hostname": "cz-prg-wg-202",
"location": "cz-prg",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "178.249.209.175",
"include_in_country": true,
"weight": 100,
"public_key": "ReGrGPKDHri64D7qeXmgcLzjsTJ0B/yM7eekFz1P/34=",
"ipv6_addr_in": "2a02:6ea0:c201:1::f101"
},
{
"hostname": "de-ber-wg-001",
"location": "de-ber",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "193.32.248.66",
"include_in_country": true,
"weight": 50,
"public_key": "0qSP0VxoIhEhRK+fAHVvmfRdjPs2DmmpOCNLFP/7cGw=",
"ipv6_addr_in": "2a03:1b20:b:f011::a01f",
"shadowsocks_extra_addr_in": [
"193.32.248.86",
"151.241.171.20",
"151.241.171.21",
"151.241.171.22",
"151.241.171.23",
"151.241.171.24",
"151.241.171.25",
"151.241.171.26",
"151.241.171.27",
"151.241.171.28",
"151.241.171.29",
"2a03:1b20:b:f011::b002",
"2a03:1b20:b:f011::b003",
"2a03:1b20:b:f011::b004",
"2a03:1b20:b:f011::b005",
"2a03:1b20:b:f011::b006",
"2a03:1b20:b:f011::b007",
"2a03:1b20:b:f011::b008",
"2a03:1b20:b:f011::b009",
"2a03:1b20:b:f011::b00a",
"2a03:1b20:b:f011::b00b",
"2a03:1b20:b:f011::b00c",
"2a03:1b20:b:f011::b00d",
"2a03:1b20:b:f011::b00e",
"2a03:1b20:b:f011::b00f",
"2a03:1b20:b:f011::b010",
"2a03:1b20:b:f011::b011",
"2a03:1b20:b:f011::b012",
"2a03:1b20:b:f011::b013",
"2a03:1b20:b:f011::b014",
"2a03:1b20:b:f011::b015",
"2a03:1b20:b:f011::b016",
"2a03:1b20:b:f011::b017",
"2a03:1b20:b:f011::b018",
"2a03:1b20:b:f011::b019",
"2a03:1b20:b:f011::b01a",
"2a03:1b20:b:f011::b01b",
"2a03:1b20:b:f011::b01c",
"2a03:1b20:b:f011::b01d",
"2a03:1b20:b:f011::b01e",
"2a03:1b20:b:f011::b01f"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"193.32.248.87",
"151.241.171.10",
"151.241.171.11",
"151.241.171.12",
"151.241.171.13",
"151.241.171.14",
"151.241.171.15",
"151.241.171.16",
"151.241.171.17",
"151.241.171.18",
"151.241.171.19",
"2a03:1b20:b:f011::c002",
"2a03:1b20:b:f011::c003",
"2a03:1b20:b:f011::c004",
"2a03:1b20:b:f011::c005",
"2a03:1b20:b:f011::c006",
"2a03:1b20:b:f011::c007",
"2a03:1b20:b:f011::c008",
"2a03:1b20:b:f011::c009",
"2a03:1b20:b:f011::c00a",
"2a03:1b20:b:f011::c00b",
"2a03:1b20:b:f011::c00c",
"2a03:1b20:b:f011::c00d",
"2a03:1b20:b:f011::c00e",
"2a03:1b20:b:f011::c00f",
"2a03:1b20:b:f011::c010",
"2a03:1b20:b:f011::c011",
"2a03:1b20:b:f011::c012",
"2a03:1b20:b:f011::c013",
"2a03:1b20:b:f011::c014",
"2a03:1b20:b:f011::c015",
"2a03:1b20:b:f011::c016",
"2a03:1b20:b:f011::c017",
"2a03:1b20:b:f011::c018",
"2a03:1b20:b:f011::c019",
"2a03:1b20:b:f011::c01a",
"2a03:1b20:b:f011::c01b",
"2a03:1b20:b:f011::c01c",
"2a03:1b20:b:f011::c01d",
"2a03:1b20:b:f011::c01e",
"2a03:1b20:b:f011::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "de-ber-wg-001.blockerad.eu"
}
}
},
{
"hostname": "de-ber-wg-002",
"location": "de-ber",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "193.32.248.67",
"include_in_country": true,
"weight": 50,
"public_key": "8ov1Ws0ut3ixWDh9Chp7/WLVn9qC6/WVHtcBcuWBlgo=",
"ipv6_addr_in": "2a03:1b20:b:f011::a02f",
"shadowsocks_extra_addr_in": [
"193.32.248.88",
"151.241.171.50",
"151.241.171.51",
"151.241.171.52",
"151.241.171.53",
"151.241.171.54",
"151.241.171.55",
"151.241.171.56",
"151.241.171.57",
"151.241.171.58",
"151.241.171.59",
"2a03:1b20:b:f011::b102",
"2a03:1b20:b:f011::b103",
"2a03:1b20:b:f011::b104",
"2a03:1b20:b:f011::b105",
"2a03:1b20:b:f011::b106",
"2a03:1b20:b:f011::b107",
"2a03:1b20:b:f011::b108",
"2a03:1b20:b:f011::b109",
"2a03:1b20:b:f011::b10a",
"2a03:1b20:b:f011::b10b",
"2a03:1b20:b:f011::b10c",
"2a03:1b20:b:f011::b10d",
"2a03:1b20:b:f011::b10e",
"2a03:1b20:b:f011::b10f",
"2a03:1b20:b:f011::b110",
"2a03:1b20:b:f011::b111",
"2a03:1b20:b:f011::b112",
"2a03:1b20:b:f011::b113",
"2a03:1b20:b:f011::b114",
"2a03:1b20:b:f011::b115",
"2a03:1b20:b:f011::b116",
"2a03:1b20:b:f011::b117",
"2a03:1b20:b:f011::b118",
"2a03:1b20:b:f011::b119",
"2a03:1b20:b:f011::b11a",
"2a03:1b20:b:f011::b11b",
"2a03:1b20:b:f011::b11c",
"2a03:1b20:b:f011::b11d",
"2a03:1b20:b:f011::b11e",
"2a03:1b20:b:f011::b11f"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"193.32.248.89",
"151.241.171.40",
"151.241.171.41",
"151.241.171.42",
"151.241.171.43",
"151.241.171.44",
"151.241.171.45",
"151.241.171.46",
"151.241.171.47",
"151.241.171.48",
"151.241.171.49",
"2a03:1b20:b:f011::c102",
"2a03:1b20:b:f011::c103",
"2a03:1b20:b:f011::c104",
"2a03:1b20:b:f011::c105",
"2a03:1b20:b:f011::c106",
"2a03:1b20:b:f011::c107",
"2a03:1b20:b:f011::c108",
"2a03:1b20:b:f011::c109",
"2a03:1b20:b:f011::c10a",
"2a03:1b20:b:f011::c10b",
"2a03:1b20:b:f011::c10c",
"2a03:1b20:b:f011::c10d",
"2a03:1b20:b:f011::c10e",
"2a03:1b20:b:f011::c10f",
"2a03:1b20:b:f011::c110",
"2a03:1b20:b:f011::c111",
"2a03:1b20:b:f011::c112",
"2a03:1b20:b:f011::c113",
"2a03:1b20:b:f011::c114",
"2a03:1b20:b:f011::c115",
"2a03:1b20:b:f011::c116",
"2a03:1b20:b:f011::c117",
"2a03:1b20:b:f011::c118",
"2a03:1b20:b:f011::c119",
"2a03:1b20:b:f011::c11a",
"2a03:1b20:b:f011::c11b",
"2a03:1b20:b:f011::c11c",
"2a03:1b20:b:f011::c11d",
"2a03:1b20:b:f011::c11e",
"2a03:1b20:b:f011::c11f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "de-ber-wg-002.blockerad.eu"
}
}
},
{
"hostname": "de-ber-wg-003",
"location": "de-ber",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "193.32.248.68",
"include_in_country": true,
"weight": 50,
"public_key": "USrMatdHiCL5AKdVMpHuYgWuMiK/GHPwRB3Xx00FhU0=",
"ipv6_addr_in": "2a03:1b20:b:f011::a03f",
"shadowsocks_extra_addr_in": [
"193.32.248.90",
"151.241.171.80",
"151.241.171.81",
"151.241.171.82",
"151.241.171.83",
"151.241.171.84",
"151.241.171.85",
"151.241.171.86",
"151.241.171.87",
"151.241.171.88",
"151.241.171.89",
"2a03:1b20:b:f011::b202",
"2a03:1b20:b:f011::b203",
"2a03:1b20:b:f011::b204",
"2a03:1b20:b:f011::b205",
"2a03:1b20:b:f011::b206",
"2a03:1b20:b:f011::b207",
"2a03:1b20:b:f011::b208",
"2a03:1b20:b:f011::b209",
"2a03:1b20:b:f011::b20a",
"2a03:1b20:b:f011::b20b",
"2a03:1b20:b:f011::b20c",
"2a03:1b20:b:f011::b20d",
"2a03:1b20:b:f011::b20e",
"2a03:1b20:b:f011::b20f",
"2a03:1b20:b:f011::b210",
"2a03:1b20:b:f011::b211",
"2a03:1b20:b:f011::b212",
"2a03:1b20:b:f011::b213",
"2a03:1b20:b:f011::b214",
"2a03:1b20:b:f011::b215",
"2a03:1b20:b:f011::b216",
"2a03:1b20:b:f011::b217",
"2a03:1b20:b:f011::b218",
"2a03:1b20:b:f011::b219",
"2a03:1b20:b:f011::b21a",
"2a03:1b20:b:f011::b21b",
"2a03:1b20:b:f011::b21c",
"2a03:1b20:b:f011::b21d",
"2a03:1b20:b:f011::b21e",
"2a03:1b20:b:f011::b21f"
],
"features": {
"quic": {
"addr_in": [
"193.32.248.91",
"151.241.171.70",
"151.241.171.71",
"151.241.171.72",
"151.241.171.73",
"151.241.171.74",
"151.241.171.75",
"151.241.171.76",
"151.241.171.77",
"151.241.171.78",
"151.241.171.79",
"2a03:1b20:b:f011::c202",
"2a03:1b20:b:f011::c203",
"2a03:1b20:b:f011::c204",
"2a03:1b20:b:f011::c205",
"2a03:1b20:b:f011::c206",
"2a03:1b20:b:f011::c207",
"2a03:1b20:b:f011::c208",
"2a03:1b20:b:f011::c209",
"2a03:1b20:b:f011::c20a",
"2a03:1b20:b:f011::c20b",
"2a03:1b20:b:f011::c20c",
"2a03:1b20:b:f011::c20d",
"2a03:1b20:b:f011::c20e",
"2a03:1b20:b:f011::c20f",
"2a03:1b20:b:f011::c210",
"2a03:1b20:b:f011::c211",
"2a03:1b20:b:f011::c212",
"2a03:1b20:b:f011::c213",
"2a03:1b20:b:f011::c214",
"2a03:1b20:b:f011::c215",
"2a03:1b20:b:f011::c216",
"2a03:1b20:b:f011::c217",
"2a03:1b20:b:f011::c218",
"2a03:1b20:b:f011::c219",
"2a03:1b20:b:f011::c21a",
"2a03:1b20:b:f011::c21b",
"2a03:1b20:b:f011::c21c",
"2a03:1b20:b:f011::c21d",
"2a03:1b20:b:f011::c21e",
"2a03:1b20:b:f011::c21f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "de-ber-wg-003.blockerad.eu"
}
}
},
{
"hostname": "de-ber-wg-004",
"location": "de-ber",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "193.32.248.69",
"include_in_country": true,
"weight": 50,
"public_key": "6PchzRRxzeeHdNLyn3Nz0gmN7pUyjoZMpKmKzJRL4GM=",
"ipv6_addr_in": "2a03:1b20:b:f011::f301",
"shadowsocks_extra_addr_in": [
"193.32.248.92",
"151.241.171.110",
"151.241.171.111",
"151.241.171.112",
"151.241.171.113",
"151.241.171.114",
"151.241.171.115",
"151.241.171.116",
"151.241.171.117",
"151.241.171.118",
"151.241.171.119",
"2a03:1b20:b:f011::b302",
"2a03:1b20:b:f011::b303",
"2a03:1b20:b:f011::b304",
"2a03:1b20:b:f011::b305",
"2a03:1b20:b:f011::b306",
"2a03:1b20:b:f011::b307",
"2a03:1b20:b:f011::b308",
"2a03:1b20:b:f011::b309",
"2a03:1b20:b:f011::b30a",
"2a03:1b20:b:f011::b30b",
"2a03:1b20:b:f011::b30c",
"2a03:1b20:b:f011::b30d",
"2a03:1b20:b:f011::b30e",
"2a03:1b20:b:f011::b30f",
"2a03:1b20:b:f011::b310",
"2a03:1b20:b:f011::b311",
"2a03:1b20:b:f011::b312",
"2a03:1b20:b:f011::b313",
"2a03:1b20:b:f011::b314",
"2a03:1b20:b:f011::b315",
"2a03:1b20:b:f011::b316",
"2a03:1b20:b:f011::b317",
"2a03:1b20:b:f011::b318",
"2a03:1b20:b:f011::b319",
"2a03:1b20:b:f011::b31a",
"2a03:1b20:b:f011::b31b",
"2a03:1b20:b:f011::b31c",
"2a03:1b20:b:f011::b31d",
"2a03:1b20:b:f011::b31e",
"2a03:1b20:b:f011::b31f"
],
"features": {
"quic": {
"addr_in": [
"193.32.248.93",
"151.241.171.100",
"151.241.171.101",
"151.241.171.102",
"151.241.171.103",
"151.241.171.104",
"151.241.171.105",
"151.241.171.106",
"151.241.171.107",
"151.241.171.108",
"151.241.171.109",
"2a03:1b20:b:f011::c302",
"2a03:1b20:b:f011::c303",
"2a03:1b20:b:f011::c304",
"2a03:1b20:b:f011::c305",
"2a03:1b20:b:f011::c306",
"2a03:1b20:b:f011::c307",
"2a03:1b20:b:f011::c308",
"2a03:1b20:b:f011::c309",
"2a03:1b20:b:f011::c30a",
"2a03:1b20:b:f011::c30b",
"2a03:1b20:b:f011::c30c",
"2a03:1b20:b:f011::c30d",
"2a03:1b20:b:f011::c30e",
"2a03:1b20:b:f011::c30f",
"2a03:1b20:b:f011::c310",
"2a03:1b20:b:f011::c311",
"2a03:1b20:b:f011::c312",
"2a03:1b20:b:f011::c313",
"2a03:1b20:b:f011::c314",
"2a03:1b20:b:f011::c315",
"2a03:1b20:b:f011::c316",
"2a03:1b20:b:f011::c317",
"2a03:1b20:b:f011::c318",
"2a03:1b20:b:f011::c319",
"2a03:1b20:b:f011::c31a",
"2a03:1b20:b:f011::c31b",
"2a03:1b20:b:f011::c31c",
"2a03:1b20:b:f011::c31d",
"2a03:1b20:b:f011::c31e",
"2a03:1b20:b:f011::c31f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "de-ber-wg-004.blockerad.eu"
}
}
},
{
"hostname": "de-ber-wg-005",
"location": "de-ber",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "193.32.248.70",
"include_in_country": true,
"weight": 50,
"public_key": "I4Y7e8LrtBC/7DLpUgRd5k+IZk+whOFVAZgbSivoiBI=",
"ipv6_addr_in": "2a03:1b20:b:f011::f401",
"shadowsocks_extra_addr_in": [
"193.32.248.94",
"151.241.171.140",
"151.241.171.141",
"151.241.171.142",
"151.241.171.143",
"151.241.171.144",
"151.241.171.145",
"151.241.171.146",
"151.241.171.147",
"151.241.171.148",
"151.241.171.149",
"2a03:1b20:b:f011::b402",
"2a03:1b20:b:f011::b403",
"2a03:1b20:b:f011::b404",
"2a03:1b20:b:f011::b405",
"2a03:1b20:b:f011::b406",
"2a03:1b20:b:f011::b407",
"2a03:1b20:b:f011::b408",
"2a03:1b20:b:f011::b409",
"2a03:1b20:b:f011::b40a",
"2a03:1b20:b:f011::b40b",
"2a03:1b20:b:f011::b40c",
"2a03:1b20:b:f011::b40d",
"2a03:1b20:b:f011::b40e",
"2a03:1b20:b:f011::b40f",
"2a03:1b20:b:f011::b410",
"2a03:1b20:b:f011::b411",
"2a03:1b20:b:f011::b412",
"2a03:1b20:b:f011::b413",
"2a03:1b20:b:f011::b414",
"2a03:1b20:b:f011::b415",
"2a03:1b20:b:f011::b416",
"2a03:1b20:b:f011::b417",
"2a03:1b20:b:f011::b418",
"2a03:1b20:b:f011::b419",
"2a03:1b20:b:f011::b41a",
"2a03:1b20:b:f011::b41b",
"2a03:1b20:b:f011::b41c",
"2a03:1b20:b:f011::b41d",
"2a03:1b20:b:f011::b41e",
"2a03:1b20:b:f011::b41f"
],
"features": {
"quic": {
"addr_in": [
"193.32.248.95",
"151.241.171.130",
"151.241.171.131",
"151.241.171.132",
"151.241.171.133",
"151.241.171.134",
"151.241.171.135",
"151.241.171.136",
"151.241.171.137",
"151.241.171.138",
"151.241.171.139",
"2a03:1b20:b:f011::c402",
"2a03:1b20:b:f011::c403",
"2a03:1b20:b:f011::c404",
"2a03:1b20:b:f011::c405",
"2a03:1b20:b:f011::c406",
"2a03:1b20:b:f011::c407",
"2a03:1b20:b:f011::c408",
"2a03:1b20:b:f011::c409",
"2a03:1b20:b:f011::c40a",
"2a03:1b20:b:f011::c40b",
"2a03:1b20:b:f011::c40c",
"2a03:1b20:b:f011::c40d",
"2a03:1b20:b:f011::c40e",
"2a03:1b20:b:f011::c40f",
"2a03:1b20:b:f011::c410",
"2a03:1b20:b:f011::c411",
"2a03:1b20:b:f011::c412",
"2a03:1b20:b:f011::c413",
"2a03:1b20:b:f011::c414",
"2a03:1b20:b:f011::c415",
"2a03:1b20:b:f011::c416",
"2a03:1b20:b:f011::c417",
"2a03:1b20:b:f011::c418",
"2a03:1b20:b:f011::c419",
"2a03:1b20:b:f011::c41a",
"2a03:1b20:b:f011::c41b",
"2a03:1b20:b:f011::c41c",
"2a03:1b20:b:f011::c41d",
"2a03:1b20:b:f011::c41e",
"2a03:1b20:b:f011::c41f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "de-ber-wg-005.blockerad.eu"
}
}
},
{
"hostname": "de-ber-wg-006",
"location": "de-ber",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "193.32.248.71",
"include_in_country": true,
"weight": 50,
"public_key": "eprzkkkSbXCANngQDo305DIAvkKAnZaN71IpTNaOoTk=",
"ipv6_addr_in": "2a03:1b20:b:f011::a06f",
"shadowsocks_extra_addr_in": [
"193.32.248.96",
"151.241.171.170",
"151.241.171.171",
"151.241.171.172",
"151.241.171.173",
"151.241.171.174",
"151.241.171.175",
"151.241.171.176",
"151.241.171.177",
"151.241.171.178",
"151.241.171.179",
"2a03:1b20:b:f011::b502",
"2a03:1b20:b:f011::b503",
"2a03:1b20:b:f011::b504",
"2a03:1b20:b:f011::b505",
"2a03:1b20:b:f011::b506",
"2a03:1b20:b:f011::b507",
"2a03:1b20:b:f011::b508",
"2a03:1b20:b:f011::b509",
"2a03:1b20:b:f011::b50a",
"2a03:1b20:b:f011::b50b",
"2a03:1b20:b:f011::b50c",
"2a03:1b20:b:f011::b50d",
"2a03:1b20:b:f011::b50e",
"2a03:1b20:b:f011::b50f",
"2a03:1b20:b:f011::b510",
"2a03:1b20:b:f011::b511",
"2a03:1b20:b:f011::b512",
"2a03:1b20:b:f011::b513",
"2a03:1b20:b:f011::b514",
"2a03:1b20:b:f011::b515",
"2a03:1b20:b:f011::b516",
"2a03:1b20:b:f011::b517",
"2a03:1b20:b:f011::b518",
"2a03:1b20:b:f011::b519",
"2a03:1b20:b:f011::b51a",
"2a03:1b20:b:f011::b51b",
"2a03:1b20:b:f011::b51c",
"2a03:1b20:b:f011::b51d",
"2a03:1b20:b:f011::b51e",
"2a03:1b20:b:f011::b51f"
],
"features": {
"quic": {
"addr_in": [
"193.32.248.97",
"151.241.171.160",
"151.241.171.161",
"151.241.171.162",
"151.241.171.163",
"151.241.171.164",
"151.241.171.165",
"151.241.171.166",
"151.241.171.167",
"151.241.171.168",
"151.241.171.169",
"2a03:1b20:b:f011::c502",
"2a03:1b20:b:f011::c503",
"2a03:1b20:b:f011::c504",
"2a03:1b20:b:f011::c505",
"2a03:1b20:b:f011::c506",
"2a03:1b20:b:f011::c507",
"2a03:1b20:b:f011::c508",
"2a03:1b20:b:f011::c509",
"2a03:1b20:b:f011::c50a",
"2a03:1b20:b:f011::c50b",
"2a03:1b20:b:f011::c50c",
"2a03:1b20:b:f011::c50d",
"2a03:1b20:b:f011::c50e",
"2a03:1b20:b:f011::c50f",
"2a03:1b20:b:f011::c510",
"2a03:1b20:b:f011::c511",
"2a03:1b20:b:f011::c512",
"2a03:1b20:b:f011::c513",
"2a03:1b20:b:f011::c514",
"2a03:1b20:b:f011::c515",
"2a03:1b20:b:f011::c516",
"2a03:1b20:b:f011::c517",
"2a03:1b20:b:f011::c518",
"2a03:1b20:b:f011::c519",
"2a03:1b20:b:f011::c51a",
"2a03:1b20:b:f011::c51b",
"2a03:1b20:b:f011::c51c",
"2a03:1b20:b:f011::c51d",
"2a03:1b20:b:f011::c51e",
"2a03:1b20:b:f011::c51f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "de-ber-wg-006.blockerad.eu"
}
}
},
{
"hostname": "de-ber-wg-007",
"location": "de-ber",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "193.32.248.75",
"include_in_country": true,
"weight": 50,
"public_key": "/ejdxiEsmYbeXXCN6UzvzJ0U/mLuB6baIfQRYKYHWzU=",
"ipv6_addr_in": "2a03:1b20:b:f011::f701",
"shadowsocks_extra_addr_in": [
"193.32.248.98",
"151.241.171.190",
"151.241.171.191",
"151.241.171.192",
"151.241.171.193",
"151.241.171.194",
"151.241.171.195",
"151.241.171.196",
"151.241.171.197",
"151.241.171.198",
"151.241.171.199",
"2a03:1b20:b:f011::b702",
"2a03:1b20:b:f011::b703",
"2a03:1b20:b:f011::b704",
"2a03:1b20:b:f011::b705",
"2a03:1b20:b:f011::b706",
"2a03:1b20:b:f011::b707",
"2a03:1b20:b:f011::b708",
"2a03:1b20:b:f011::b709",
"2a03:1b20:b:f011::b70a",
"2a03:1b20:b:f011::b70b",
"2a03:1b20:b:f011::b70c",
"2a03:1b20:b:f011::b70d",
"2a03:1b20:b:f011::b70e",
"2a03:1b20:b:f011::b70f",
"2a03:1b20:b:f011::b710",
"2a03:1b20:b:f011::b711",
"2a03:1b20:b:f011::b712",
"2a03:1b20:b:f011::b713",
"2a03:1b20:b:f011::b714",
"2a03:1b20:b:f011::b715",
"2a03:1b20:b:f011::b716",
"2a03:1b20:b:f011::b717",
"2a03:1b20:b:f011::b718",
"2a03:1b20:b:f011::b719",
"2a03:1b20:b:f011::b71a",
"2a03:1b20:b:f011::b71b",
"2a03:1b20:b:f011::b71c",
"2a03:1b20:b:f011::b71d",
"2a03:1b20:b:f011::b71e",
"2a03:1b20:b:f011::b71f"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"193.32.248.99",
"151.241.171.180",
"151.241.171.181",
"151.241.171.182",
"151.241.171.183",
"151.241.171.184",
"151.241.171.185",
"151.241.171.186",
"151.241.171.187",
"151.241.171.188",
"151.241.171.189",
"2a03:1b20:b:f011::c702",
"2a03:1b20:b:f011::c703",
"2a03:1b20:b:f011::c704",
"2a03:1b20:b:f011::c705",
"2a03:1b20:b:f011::c706",
"2a03:1b20:b:f011::c707",
"2a03:1b20:b:f011::c708",
"2a03:1b20:b:f011::c709",
"2a03:1b20:b:f011::c70a",
"2a03:1b20:b:f011::c70b",
"2a03:1b20:b:f011::c70c",
"2a03:1b20:b:f011::c70d",
"2a03:1b20:b:f011::c70e",
"2a03:1b20:b:f011::c70f",
"2a03:1b20:b:f011::c710",
"2a03:1b20:b:f011::c711",
"2a03:1b20:b:f011::c712",
"2a03:1b20:b:f011::c713",
"2a03:1b20:b:f011::c714",
"2a03:1b20:b:f011::c715",
"2a03:1b20:b:f011::c716",
"2a03:1b20:b:f011::c717",
"2a03:1b20:b:f011::c718",
"2a03:1b20:b:f011::c719",
"2a03:1b20:b:f011::c71a",
"2a03:1b20:b:f011::c71b",
"2a03:1b20:b:f011::c71c",
"2a03:1b20:b:f011::c71d",
"2a03:1b20:b:f011::c71e",
"2a03:1b20:b:f011::c71f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "de-ber-wg-007.blockerad.eu"
}
}
},
{
"hostname": "de-ber-wg-008",
"location": "de-ber",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "193.32.248.74",
"include_in_country": true,
"weight": 50,
"public_key": "qwXs9gwhwqWgRtLjPiZ+zMphZJA3OStsn/aXcCAd5m0=",
"ipv6_addr_in": "2a03:1b20:b:f011::f801",
"shadowsocks_extra_addr_in": [
"193.32.248.233",
"151.241.171.220",
"151.241.171.221",
"151.241.171.222",
"151.241.171.223",
"151.241.171.224",
"151.241.171.225",
"151.241.171.226",
"151.241.171.227",
"151.241.171.228",
"151.241.171.229",
"2a03:1b20:b:f011::b802",
"2a03:1b20:b:f011::b803",
"2a03:1b20:b:f011::b804",
"2a03:1b20:b:f011::b805",
"2a03:1b20:b:f011::b806",
"2a03:1b20:b:f011::b807",
"2a03:1b20:b:f011::b808",
"2a03:1b20:b:f011::b809",
"2a03:1b20:b:f011::b80a",
"2a03:1b20:b:f011::b80b",
"2a03:1b20:b:f011::b80c",
"2a03:1b20:b:f011::b80d",
"2a03:1b20:b:f011::b80e",
"2a03:1b20:b:f011::b80f",
"2a03:1b20:b:f011::b810",
"2a03:1b20:b:f011::b811",
"2a03:1b20:b:f011::b812",
"2a03:1b20:b:f011::b813",
"2a03:1b20:b:f011::b814",
"2a03:1b20:b:f011::b815",
"2a03:1b20:b:f011::b816",
"2a03:1b20:b:f011::b817",
"2a03:1b20:b:f011::b818",
"2a03:1b20:b:f011::b819",
"2a03:1b20:b:f011::b81a",
"2a03:1b20:b:f011::b81b",
"2a03:1b20:b:f011::b81c",
"2a03:1b20:b:f011::b81d",
"2a03:1b20:b:f011::b81e",
"2a03:1b20:b:f011::b81f"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"193.32.248.232",
"2a03:1b20:b:f011::f80a",
"151.241.171.210",
"151.241.171.211",
"151.241.171.212",
"151.241.171.213",
"151.241.171.214",
"151.241.171.215",
"151.241.171.216",
"151.241.171.217",
"151.241.171.218",
"151.241.171.219",
"2a03:1b20:b:f011::c802",
"2a03:1b20:b:f011::c803",
"2a03:1b20:b:f011::c804",
"2a03:1b20:b:f011::c805",
"2a03:1b20:b:f011::c806",
"2a03:1b20:b:f011::c807",
"2a03:1b20:b:f011::c808",
"2a03:1b20:b:f011::c809",
"2a03:1b20:b:f011::c80a",
"2a03:1b20:b:f011::c80b",
"2a03:1b20:b:f011::c80c",
"2a03:1b20:b:f011::c80d",
"2a03:1b20:b:f011::c80e",
"2a03:1b20:b:f011::c80f",
"2a03:1b20:b:f011::c810",
"2a03:1b20:b:f011::c811",
"2a03:1b20:b:f011::c812",
"2a03:1b20:b:f011::c813",
"2a03:1b20:b:f011::c814",
"2a03:1b20:b:f011::c815",
"2a03:1b20:b:f011::c816",
"2a03:1b20:b:f011::c817",
"2a03:1b20:b:f011::c818",
"2a03:1b20:b:f011::c819",
"2a03:1b20:b:f011::c81a",
"2a03:1b20:b:f011::c81b",
"2a03:1b20:b:f011::c81c",
"2a03:1b20:b:f011::c81d",
"2a03:1b20:b:f011::c81e",
"2a03:1b20:b:f011::c81f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "de-ber-wg-008.blockerad.eu"
}
}
},
{
"hostname": "de-dus-wg-001",
"location": "de-dus",
"active": true,
"owned": false,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "185.254.75.3",
"include_in_country": true,
"weight": 150,
"public_key": "ku1NYeOAGbY65YL/JKZhrqVzDJKXQiVj9USXbfkOBA0=",
"ipv6_addr_in": "2a03:d9c0:3000::a20f"
},
{
"hostname": "de-dus-wg-002",
"location": "de-dus",
"active": true,
"owned": false,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "185.254.75.4",
"include_in_country": true,
"weight": 150,
"public_key": "TPAIPTgu9jIitgX1Bz5xMCZJ9pRRZTdtZEOIxArO0Hc=",
"ipv6_addr_in": "2a03:d9c0:3000::a21f"
},
{
"hostname": "de-dus-wg-003",
"location": "de-dus",
"active": true,
"owned": false,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "185.254.75.5",
"include_in_country": true,
"weight": 150,
"public_key": "XgSe9UwEV4JJNPPzFFOVYS6scMTL4DeNlwqBl32lDw0=",
"ipv6_addr_in": "2a03:d9c0:3000::a22f"
},
{
"hostname": "de-fra-wg-001",
"location": "de-fra",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "185.213.155.73",
"include_in_country": true,
"weight": 25,
"public_key": "HQHCrq4J6bSpdW1fI5hR/bvcrYa6HgGgwaa5ZY749ik=",
"ipv6_addr_in": "2a03:1b20:6:f011::f001",
"shadowsocks_extra_addr_in": [
"2a03:1b20:6:f011::b002",
"2a03:1b20:6:f011::b003",
"2a03:1b20:6:f011::b004",
"2a03:1b20:6:f011::b005",
"2a03:1b20:6:f011::b006",
"2a03:1b20:6:f011::b007",
"2a03:1b20:6:f011::b008",
"2a03:1b20:6:f011::b009",
"2a03:1b20:6:f011::b00a",
"2a03:1b20:6:f011::b00b",
"2a03:1b20:6:f011::b00c",
"2a03:1b20:6:f011::b00d",
"2a03:1b20:6:f011::b00e",
"2a03:1b20:6:f011::b00f",
"2a03:1b20:6:f011::b010",
"2a03:1b20:6:f011::b011",
"2a03:1b20:6:f011::b012",
"2a03:1b20:6:f011::b013",
"2a03:1b20:6:f011::b014",
"2a03:1b20:6:f011::b015",
"2a03:1b20:6:f011::b016",
"2a03:1b20:6:f011::b017",
"2a03:1b20:6:f011::b018",
"2a03:1b20:6:f011::b019",
"2a03:1b20:6:f011::b01a",
"2a03:1b20:6:f011::b01b",
"2a03:1b20:6:f011::b01c",
"2a03:1b20:6:f011::b01d",
"2a03:1b20:6:f011::b01e",
"2a03:1b20:6:f011::b01f"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"185.213.155.99",
"2a03:1b20:6:f011::c002",
"2a03:1b20:6:f011::c003",
"2a03:1b20:6:f011::c004",
"2a03:1b20:6:f011::c005",
"2a03:1b20:6:f011::c006",
"2a03:1b20:6:f011::c007",
"2a03:1b20:6:f011::c008",
"2a03:1b20:6:f011::c009",
"2a03:1b20:6:f011::c00a",
"2a03:1b20:6:f011::c00b",
"2a03:1b20:6:f011::c00c",
"2a03:1b20:6:f011::c00d",
"2a03:1b20:6:f011::c00e",
"2a03:1b20:6:f011::c00f",
"2a03:1b20:6:f011::c010",
"2a03:1b20:6:f011::c011",
"2a03:1b20:6:f011::c012",
"2a03:1b20:6:f011::c013",
"2a03:1b20:6:f011::c014",
"2a03:1b20:6:f011::c015",
"2a03:1b20:6:f011::c016",
"2a03:1b20:6:f011::c017",
"2a03:1b20:6:f011::c018",
"2a03:1b20:6:f011::c019",
"2a03:1b20:6:f011::c01a",
"2a03:1b20:6:f011::c01b",
"2a03:1b20:6:f011::c01c",
"2a03:1b20:6:f011::c01d",
"2a03:1b20:6:f011::c01e",
"2a03:1b20:6:f011::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "de-fra-wg-001.blockerad.eu"
}
}
},
{
"hostname": "de-fra-wg-002",
"location": "de-fra",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "185.213.155.74",
"include_in_country": true,
"weight": 25,
"public_key": "s1c/NsfnqnwQSxao70DY4Co69AFT9e0h88IFuMD5mjs=",
"ipv6_addr_in": "2a03:1b20:6:f011::f101",
"shadowsocks_extra_addr_in": [
"151.241.163.30",
"151.241.163.31",
"151.241.163.32",
"151.241.163.33",
"151.241.163.34",
"151.241.163.35",
"151.241.163.36",
"151.241.163.37",
"151.241.163.38",
"151.241.163.39",
"151.241.163.40",
"151.241.163.41",
"151.241.163.42",
"151.241.163.43",
"151.241.163.44",
"151.241.163.45",
"151.241.163.46",
"151.241.163.47",
"151.241.163.48",
"151.241.163.49",
"2a03:1b20:6:f011::b102",
"2a03:1b20:6:f011::b103",
"2a03:1b20:6:f011::b104",
"2a03:1b20:6:f011::b105",
"2a03:1b20:6:f011::b106",
"2a03:1b20:6:f011::b107",
"2a03:1b20:6:f011::b108",
"2a03:1b20:6:f011::b109",
"2a03:1b20:6:f011::b10a",
"2a03:1b20:6:f011::b10b",
"2a03:1b20:6:f011::b10c",
"2a03:1b20:6:f011::b10d",
"2a03:1b20:6:f011::b10e",
"2a03:1b20:6:f011::b10f",
"2a03:1b20:6:f011::b110",
"2a03:1b20:6:f011::b111",
"2a03:1b20:6:f011::b112",
"2a03:1b20:6:f011::b113",
"2a03:1b20:6:f011::b114",
"2a03:1b20:6:f011::b115",
"2a03:1b20:6:f011::b116",
"2a03:1b20:6:f011::b117",
"2a03:1b20:6:f011::b118",
"2a03:1b20:6:f011::b119",
"2a03:1b20:6:f011::b11a",
"2a03:1b20:6:f011::b11b",
"2a03:1b20:6:f011::b11c",
"2a03:1b20:6:f011::b11d",
"2a03:1b20:6:f011::b11e",
"2a03:1b20:6:f011::b11f"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"151.241.163.20",
"151.241.163.21",
"151.241.163.22",
"151.241.163.23",
"151.241.163.24",
"151.241.163.25",
"151.241.163.26",
"151.241.163.27",
"151.241.163.28",
"151.241.163.29",
"151.241.163.50",
"151.241.163.51",
"151.241.163.52",
"151.241.163.53",
"151.241.163.54",
"151.241.163.55",
"151.241.163.56",
"151.241.163.57",
"151.241.163.58",
"151.241.163.59",
"2a03:1b20:6:f011::c102",
"2a03:1b20:6:f011::c103",
"2a03:1b20:6:f011::c104",
"2a03:1b20:6:f011::c105",
"2a03:1b20:6:f011::c106",
"2a03:1b20:6:f011::c107",
"2a03:1b20:6:f011::c108",
"2a03:1b20:6:f011::c109",
"2a03:1b20:6:f011::c10a",
"2a03:1b20:6:f011::c10b",
"2a03:1b20:6:f011::c10c",
"2a03:1b20:6:f011::c10d",
"2a03:1b20:6:f011::c10e",
"2a03:1b20:6:f011::c10f",
"2a03:1b20:6:f011::c110",
"2a03:1b20:6:f011::c111",
"2a03:1b20:6:f011::c112",
"2a03:1b20:6:f011::c113",
"2a03:1b20:6:f011::c114",
"2a03:1b20:6:f011::c115",
"2a03:1b20:6:f011::c116",
"2a03:1b20:6:f011::c117",
"2a03:1b20:6:f011::c118",
"2a03:1b20:6:f011::c119",
"2a03:1b20:6:f011::c11a",
"2a03:1b20:6:f011::c11b",
"2a03:1b20:6:f011::c11c",
"2a03:1b20:6:f011::c11d",
"2a03:1b20:6:f011::c11e",
"2a03:1b20:6:f011::c11f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "de-fra-wg-002.blockerad.eu"
}
}
},
{
"hostname": "de-fra-wg-003",
"location": "de-fra",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "185.209.196.73",
"include_in_country": true,
"weight": 25,
"public_key": "vVQKs2TeTbdAvl3sH16UWLSESncXAj0oBaNuFIUkLVk=",
"ipv6_addr_in": "2a03:1b20:6:f011::f201",
"shadowsocks_extra_addr_in": [
"151.241.163.100",
"151.241.163.101",
"151.241.163.102",
"151.241.163.103",
"151.241.163.104",
"151.241.163.105",
"151.241.163.106",
"151.241.163.107",
"151.241.163.108",
"151.241.163.109",
"151.241.163.110",
"151.241.163.111",
"151.241.163.112",
"151.241.163.113",
"151.241.163.114",
"151.241.163.115",
"151.241.163.116",
"151.241.163.117",
"151.241.163.118",
"151.241.163.119",
"2a03:1b20:6:f011:3:b:0:1",
"2a03:1b20:6:f011:3:b:0:2",
"2a03:1b20:6:f011:3:b:0:3",
"2a03:1b20:6:f011:3:b:0:4",
"2a03:1b20:6:f011:3:b:0:5",
"2a03:1b20:6:f011:3:b:0:6",
"2a03:1b20:6:f011:3:b:0:7",
"2a03:1b20:6:f011:3:b:0:8",
"2a03:1b20:6:f011:3:b:0:9",
"2a03:1b20:6:f011:3:b:0:a",
"2a03:1b20:6:f011:3:b:0:b",
"2a03:1b20:6:f011:3:b:0:c",
"2a03:1b20:6:f011:3:b:0:d",
"2a03:1b20:6:f011:3:b:0:e",
"2a03:1b20:6:f011:3:b:0:f"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"151.241.163.90",
"151.241.163.91",
"151.241.163.92",
"151.241.163.93",
"151.241.163.94",
"151.241.163.95",
"151.241.163.96",
"151.241.163.97",
"151.241.163.98",
"151.241.163.99",
"151.241.163.80",
"151.241.163.81",
"151.241.163.82",
"151.241.163.83",
"151.241.163.84",
"151.241.163.85",
"151.241.163.86",
"151.241.163.87",
"151.241.163.88",
"151.241.163.89",
"2a03:1b20:6:f011:3:c:0:1",
"2a03:1b20:6:f011:3:c:0:2",
"2a03:1b20:6:f011:3:c:0:3",
"2a03:1b20:6:f011:3:c:0:4",
"2a03:1b20:6:f011:3:c:0:5",
"2a03:1b20:6:f011:3:c:0:6",
"2a03:1b20:6:f011:3:c:0:7",
"2a03:1b20:6:f011:3:c:0:8",
"2a03:1b20:6:f011:3:c:0:9",
"2a03:1b20:6:f011:3:c:0:a",
"2a03:1b20:6:f011:3:c:0:b",
"2a03:1b20:6:f011:3:c:0:c",
"2a03:1b20:6:f011:3:c:0:d",
"2a03:1b20:6:f011:3:c:0:e",
"2a03:1b20:6:f011:3:c:0:f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "de-fra-wg-003.blockerad.eu"
}
}
},
{
"hostname": "de-fra-wg-004",
"location": "de-fra",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "185.209.196.74",
"include_in_country": true,
"weight": 25,
"public_key": "tzYLWgBdwrbbBCXYHRSoYIho4dHtrm+8bdONU1I8xzc=",
"ipv6_addr_in": "2a03:1b20:6:f011::f301",
"daita": true,
"shadowsocks_extra_addr_in": [
"151.241.163.160",
"151.241.163.161",
"151.241.163.162",
"151.241.163.163",
"151.241.163.164",
"151.241.163.165",
"151.241.163.166",
"151.241.163.167",
"151.241.163.168",
"151.241.163.169",
"151.241.163.170",
"151.241.163.171",
"151.241.163.172",
"151.241.163.173",
"151.241.163.174",
"151.241.163.175",
"151.241.163.176",
"151.241.163.177",
"151.241.163.178",
"151.241.163.179",
"2a03:1b20:6:f011::b302",
"2a03:1b20:6:f011::b303",
"2a03:1b20:6:f011::b304",
"2a03:1b20:6:f011::b305",
"2a03:1b20:6:f011::b306",
"2a03:1b20:6:f011::b307",
"2a03:1b20:6:f011::b308",
"2a03:1b20:6:f011::b309",
"2a03:1b20:6:f011::b30a",
"2a03:1b20:6:f011::b30b",
"2a03:1b20:6:f011::b30c",
"2a03:1b20:6:f011::b30d",
"2a03:1b20:6:f011::b30e",
"2a03:1b20:6:f011::b30f",
"2a03:1b20:6:f011::b310",
"2a03:1b20:6:f011::b311",
"2a03:1b20:6:f011::b312",
"2a03:1b20:6:f011::b313",
"2a03:1b20:6:f011::b314",
"2a03:1b20:6:f011::b315",
"2a03:1b20:6:f011::b316",
"2a03:1b20:6:f011::b317",
"2a03:1b20:6:f011::b318",
"2a03:1b20:6:f011::b319",
"2a03:1b20:6:f011::b31a",
"2a03:1b20:6:f011::b31b",
"2a03:1b20:6:f011::b31c",
"2a03:1b20:6:f011::b31d",
"2a03:1b20:6:f011::b31e",
"2a03:1b20:6:f011::b31f"
],
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"151.241.163.140",
"151.241.163.141",
"151.241.163.142",
"151.241.163.143",
"151.241.163.144",
"151.241.163.145",
"151.241.163.146",
"151.241.163.147",
"151.241.163.148",
"151.241.163.149",
"151.241.163.150",
"151.241.163.151",
"151.241.163.152",
"151.241.163.153",
"151.241.163.154",
"151.241.163.155",
"151.241.163.156",
"151.241.163.157",
"151.241.163.158",
"151.241.163.159",
"2a03:1b20:6:f011::c302",
"2a03:1b20:6:f011::c303",
"2a03:1b20:6:f011::c304",
"2a03:1b20:6:f011::c305",
"2a03:1b20:6:f011::c306",
"2a03:1b20:6:f011::c307",
"2a03:1b20:6:f011::c308",
"2a03:1b20:6:f011::c309",
"2a03:1b20:6:f011::c30a",
"2a03:1b20:6:f011::c30b",
"2a03:1b20:6:f011::c30c",
"2a03:1b20:6:f011::c30d",
"2a03:1b20:6:f011::c30e",
"2a03:1b20:6:f011::c30f",
"2a03:1b20:6:f011::c310",
"2a03:1b20:6:f011::c311",
"2a03:1b20:6:f011::c312",
"2a03:1b20:6:f011::c313",
"2a03:1b20:6:f011::c314",
"2a03:1b20:6:f011::c315",
"2a03:1b20:6:f011::c316",
"2a03:1b20:6:f011::c317",
"2a03:1b20:6:f011::c318",
"2a03:1b20:6:f011::c319",
"2a03:1b20:6:f011::c31a",
"2a03:1b20:6:f011::c31b",
"2a03:1b20:6:f011::c31c",
"2a03:1b20:6:f011::c31d",
"2a03:1b20:6:f011::c31e",
"2a03:1b20:6:f011::c31f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "de-fra-wg-004.blockerad.eu"
}
}
},
{
"hostname": "de-fra-wg-005",
"location": "de-fra",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "185.209.196.75",
"include_in_country": true,
"weight": 25,
"public_key": "tpobOO6t18CzHjOg0S3RlZJMxd2tz4+BnRYS7NrjTnM=",
"ipv6_addr_in": "2a03:1b20:6:f011::f401",
"shadowsocks_extra_addr_in": [
"151.241.163.220",
"151.241.163.221",
"151.241.163.222",
"151.241.163.223",
"151.241.163.224",
"151.241.163.225",
"151.241.163.226",
"151.241.163.227",
"151.241.163.228",
"151.241.163.229",
"151.241.163.230",
"151.241.163.231",
"151.241.163.232",
"151.241.163.233",
"151.241.163.234",
"151.241.163.235",
"151.241.163.236",
"151.241.163.237",
"151.241.163.238",
"151.241.163.239",
"151.241.163.240",
"151.241.163.241",
"151.241.163.242",
"151.241.163.243",
"151.241.163.244",
"151.241.163.245",
"151.241.163.246",
"151.241.163.247",
"151.241.163.248",
"151.241.163.249",
"2a03:1b20:6:f011::b402",
"2a03:1b20:6:f011::b403",
"2a03:1b20:6:f011::b404",
"2a03:1b20:6:f011::b405",
"2a03:1b20:6:f011::b406",
"2a03:1b20:6:f011::b407",
"2a03:1b20:6:f011::b408",
"2a03:1b20:6:f011::b409",
"2a03:1b20:6:f011::b40a",
"2a03:1b20:6:f011::b40b",
"2a03:1b20:6:f011::b40c",
"2a03:1b20:6:f011::b40d",
"2a03:1b20:6:f011::b40e",
"2a03:1b20:6:f011::b40f",
"2a03:1b20:6:f011::b410",
"2a03:1b20:6:f011::b411",
"2a03:1b20:6:f011::b412",
"2a03:1b20:6:f011::b413",
"2a03:1b20:6:f011::b414",
"2a03:1b20:6:f011::b415",
"2a03:1b20:6:f011::b416",
"2a03:1b20:6:f011::b417",
"2a03:1b20:6:f011::b418",
"2a03:1b20:6:f011::b419",
"2a03:1b20:6:f011::b41a",
"2a03:1b20:6:f011::b41b",
"2a03:1b20:6:f011::b41c",
"2a03:1b20:6:f011::b41d",
"2a03:1b20:6:f011::b41e",
"2a03:1b20:6:f011::b41f"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"151.241.163.200",
"151.241.163.201",
"151.241.163.202",
"151.241.163.203",
"151.241.163.204",
"151.241.163.205",
"151.241.163.206",
"151.241.163.207",
"151.241.163.208",
"151.241.163.209",
"151.241.163.210",
"151.241.163.210",
"151.241.163.211",
"151.241.163.212",
"151.241.163.213",
"151.241.163.214",
"151.241.163.215",
"151.241.163.216",
"151.241.163.217",
"151.241.163.218",
"151.241.163.219",
"2a03:1b20:6:f011::c402",
"2a03:1b20:6:f011::c403",
"2a03:1b20:6:f011::c404",
"2a03:1b20:6:f011::c405",
"2a03:1b20:6:f011::c406",
"2a03:1b20:6:f011::c407",
"2a03:1b20:6:f011::c408",
"2a03:1b20:6:f011::c409",
"2a03:1b20:6:f011::c40a",
"2a03:1b20:6:f011::c40b",
"2a03:1b20:6:f011::c40c",
"2a03:1b20:6:f011::c40d",
"2a03:1b20:6:f011::c40e",
"2a03:1b20:6:f011::c40f",
"2a03:1b20:6:f011::c410",
"2a03:1b20:6:f011::c411",
"2a03:1b20:6:f011::c412",
"2a03:1b20:6:f011::c413",
"2a03:1b20:6:f011::c414",
"2a03:1b20:6:f011::c415",
"2a03:1b20:6:f011::c416",
"2a03:1b20:6:f011::c417",
"2a03:1b20:6:f011::c418",
"2a03:1b20:6:f011::c419",
"2a03:1b20:6:f011::c41a",
"2a03:1b20:6:f011::c41b",
"2a03:1b20:6:f011::c41c",
"2a03:1b20:6:f011::c41d",
"2a03:1b20:6:f011::c41e",
"2a03:1b20:6:f011::c41f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "de-fra-wg-005.blockerad.eu"
}
}
},
{
"hostname": "de-fra-wg-006",
"location": "de-fra",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "185.209.196.76",
"include_in_country": true,
"weight": 25,
"public_key": "nAF0wrLG2+avwQfqxnXhBGPUBCvc3QCqWKH4nK5PfEU=",
"ipv6_addr_in": "2a03:1b20:6:f011::f501",
"shadowsocks_extra_addr_in": [
"2a03:1b20:6:f011::b502",
"2a03:1b20:6:f011::b503",
"2a03:1b20:6:f011::b504",
"2a03:1b20:6:f011::b505",
"2a03:1b20:6:f011::b506",
"2a03:1b20:6:f011::b507",
"2a03:1b20:6:f011::b508",
"2a03:1b20:6:f011::b509",
"2a03:1b20:6:f011::b50a",
"2a03:1b20:6:f011::b50b",
"2a03:1b20:6:f011::b50c",
"2a03:1b20:6:f011::b50d",
"2a03:1b20:6:f011::b50e",
"2a03:1b20:6:f011::b50f",
"2a03:1b20:6:f011::b510",
"2a03:1b20:6:f011::b511",
"2a03:1b20:6:f011::b512",
"2a03:1b20:6:f011::b513",
"2a03:1b20:6:f011::b514",
"2a03:1b20:6:f011::b515",
"2a03:1b20:6:f011::b516",
"2a03:1b20:6:f011::b517",
"2a03:1b20:6:f011::b518",
"2a03:1b20:6:f011::b519",
"2a03:1b20:6:f011::b51a",
"2a03:1b20:6:f011::b51b",
"2a03:1b20:6:f011::b51c",
"2a03:1b20:6:f011::b51d",
"2a03:1b20:6:f011::b51e",
"2a03:1b20:6:f011::b51f"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"2a03:1b20:6:f011::c502",
"2a03:1b20:6:f011::c503",
"2a03:1b20:6:f011::c504",
"2a03:1b20:6:f011::c505",
"2a03:1b20:6:f011::c506",
"2a03:1b20:6:f011::c507",
"2a03:1b20:6:f011::c508",
"2a03:1b20:6:f011::c509",
"2a03:1b20:6:f011::c50a",
"2a03:1b20:6:f011::c50b",
"2a03:1b20:6:f011::c50c",
"2a03:1b20:6:f011::c50d",
"2a03:1b20:6:f011::c50e",
"2a03:1b20:6:f011::c50f",
"2a03:1b20:6:f011::c510",
"2a03:1b20:6:f011::c511",
"2a03:1b20:6:f011::c512",
"2a03:1b20:6:f011::c513",
"2a03:1b20:6:f011::c514",
"2a03:1b20:6:f011::c515",
"2a03:1b20:6:f011::c516",
"2a03:1b20:6:f011::c517",
"2a03:1b20:6:f011::c518",
"2a03:1b20:6:f011::c519",
"2a03:1b20:6:f011::c51a",
"2a03:1b20:6:f011::c51b",
"2a03:1b20:6:f011::c51c",
"2a03:1b20:6:f011::c51d",
"2a03:1b20:6:f011::c51e",
"2a03:1b20:6:f011::c51f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "de-fra-wg-006.blockerad.eu"
}
}
},
{
"hostname": "de-fra-wg-007",
"location": "de-fra",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "185.209.196.77",
"include_in_country": true,
"weight": 25,
"public_key": "mTmrSuXmTnIC9l2Ur3/QgodGrVEhhIE3pRwOHZpiYys=",
"ipv6_addr_in": "2a03:1b20:6:f011::f601",
"features": {
"lwo": {}
}
},
{
"hostname": "de-fra-wg-008",
"location": "de-fra",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "185.209.196.78",
"include_in_country": true,
"weight": 25,
"public_key": "+DuVLLPwGNlfZFoI24PRPdaTrO4i+WPDlYaOVcavHDo=",
"ipv6_addr_in": "2a03:1b20:6:f011::f701",
"shadowsocks_extra_addr_in": [
"2a03:1b20:6:f011::b702",
"2a03:1b20:6:f011::b703",
"2a03:1b20:6:f011::b704",
"2a03:1b20:6:f011::b705",
"2a03:1b20:6:f011::b706",
"2a03:1b20:6:f011::b707",
"2a03:1b20:6:f011::b708",
"2a03:1b20:6:f011::b709",
"2a03:1b20:6:f011::b70a",
"2a03:1b20:6:f011::b70b",
"2a03:1b20:6:f011::b70c",
"2a03:1b20:6:f011::b70d",
"2a03:1b20:6:f011::b70e",
"2a03:1b20:6:f011::b70f",
"2a03:1b20:6:f011::b710",
"2a03:1b20:6:f011::b711",
"2a03:1b20:6:f011::b712",
"2a03:1b20:6:f011::b713",
"2a03:1b20:6:f011::b714",
"2a03:1b20:6:f011::b715",
"2a03:1b20:6:f011::b716",
"2a03:1b20:6:f011::b717",
"2a03:1b20:6:f011::b718",
"2a03:1b20:6:f011::b719",
"2a03:1b20:6:f011::b71a",
"2a03:1b20:6:f011::b71b",
"2a03:1b20:6:f011::b71c",
"2a03:1b20:6:f011::b71d",
"2a03:1b20:6:f011::b71e",
"2a03:1b20:6:f011::b71f"
],
"features": {
"lwo": {}
}
},
{
"hostname": "de-fra-wg-009",
"location": "de-fra",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "185.213.155.72",
"include_in_country": true,
"weight": 25,
"public_key": "flq7zR8W5FxouHBuZoTRHY0A0qFEMQZF5uAgV4+sHVw=",
"ipv6_addr_in": "2a03:1b20:6:f011::f901",
"shadowsocks_extra_addr_in": [
"2a03:1b20:6:f011::b902",
"2a03:1b20:6:f011::b903",
"2a03:1b20:6:f011::b904",
"2a03:1b20:6:f011::b905",
"2a03:1b20:6:f011::b906",
"2a03:1b20:6:f011::b907",
"2a03:1b20:6:f011::b908",
"2a03:1b20:6:f011::b909",
"2a03:1b20:6:f011::b90a",
"2a03:1b20:6:f011::b90b",
"2a03:1b20:6:f011::b90c",
"2a03:1b20:6:f011::b90d",
"2a03:1b20:6:f011::b90e",
"2a03:1b20:6:f011::b90f",
"2a03:1b20:6:f011::b910",
"2a03:1b20:6:f011::b911",
"2a03:1b20:6:f011::b912",
"2a03:1b20:6:f011::b913",
"2a03:1b20:6:f011::b914",
"2a03:1b20:6:f011::b915",
"2a03:1b20:6:f011::b916",
"2a03:1b20:6:f011::b917",
"2a03:1b20:6:f011::b918",
"2a03:1b20:6:f011::b919",
"2a03:1b20:6:f011::b91a",
"2a03:1b20:6:f011::b91b",
"2a03:1b20:6:f011::b91c",
"2a03:1b20:6:f011::b91d",
"2a03:1b20:6:f011::b91e",
"2a03:1b20:6:f011::b91f"
],
"features": {
"lwo": {}
}
},
{
"hostname": "de-fra-wg-101",
"location": "de-fra",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.117.2",
"include_in_country": true,
"weight": 100,
"public_key": "wxbDlI3xb+Cc05XKb4usdKSzKe1byK7brmsHU2DJB14=",
"ipv6_addr_in": "2001:ac8:20:270:1::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"146.70.117.16",
"146.70.117.17",
"146.70.117.18",
"146.70.117.19",
"146.70.117.20",
"146.70.117.21",
"146.70.117.22",
"146.70.117.23",
"146.70.117.24",
"146.70.117.25",
"146.70.117.26",
"2001:ac8:20:270:1::b002",
"2001:ac8:20:270:1::b003",
"2001:ac8:20:270:1::b004",
"2001:ac8:20:270:1::b005",
"2001:ac8:20:270:1::b006",
"2001:ac8:20:270:1::b007",
"2001:ac8:20:270:1::b008",
"2001:ac8:20:270:1::b009",
"2001:ac8:20:270:1::b00a",
"2001:ac8:20:270:1::b00b",
"2001:ac8:20:270:1::b00c",
"2001:ac8:20:270:1::b00d",
"2001:ac8:20:270:1::b00e",
"2001:ac8:20:270:1::b00f",
"2001:ac8:20:270:1::b010",
"2001:ac8:20:270:1::b011",
"2001:ac8:20:270:1::b012",
"2001:ac8:20:270:1::b013",
"2001:ac8:20:270:1::b014",
"2001:ac8:20:270:1::b015",
"2001:ac8:20:270:1::b016",
"2001:ac8:20:270:1::b017",
"2001:ac8:20:270:1::b018",
"2001:ac8:20:270:1::b019",
"2001:ac8:20:270:1::b01a",
"2001:ac8:20:270:1::b01b",
"2001:ac8:20:270:1::b01c",
"2001:ac8:20:270:1::b01d",
"2001:ac8:20:270:1::b01e",
"2001:ac8:20:270:1::b01f"
],
"features": {
"daita": {},
"quic": {
"addr_in": [
"146.70.117.5",
"146.70.117.6",
"146.70.117.7",
"146.70.117.8",
"146.70.117.9",
"146.70.117.10",
"146.70.117.11",
"146.70.117.12",
"146.70.117.13",
"146.70.117.14",
"146.70.117.15",
"2001:ac8:20:270:1::c002",
"2001:ac8:20:270:1::c003",
"2001:ac8:20:270:1::c004",
"2001:ac8:20:270:1::c005",
"2001:ac8:20:270:1::c006",
"2001:ac8:20:270:1::c007",
"2001:ac8:20:270:1::c008",
"2001:ac8:20:270:1::c009",
"2001:ac8:20:270:1::c00a",
"2001:ac8:20:270:1::c00b",
"2001:ac8:20:270:1::c00c",
"2001:ac8:20:270:1::c00d",
"2001:ac8:20:270:1::c00e",
"2001:ac8:20:270:1::c00f",
"2001:ac8:20:270:1::c010",
"2001:ac8:20:270:1::c011",
"2001:ac8:20:270:1::c012",
"2001:ac8:20:270:1::c013",
"2001:ac8:20:270:1::c014",
"2001:ac8:20:270:1::c015",
"2001:ac8:20:270:1::c016",
"2001:ac8:20:270:1::c017",
"2001:ac8:20:270:1::c018",
"2001:ac8:20:270:1::c019",
"2001:ac8:20:270:1::c01a",
"2001:ac8:20:270:1::c01b",
"2001:ac8:20:270:1::c01c",
"2001:ac8:20:270:1::c01d",
"2001:ac8:20:270:1::c01e",
"2001:ac8:20:270:1::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "de-fra-wg-101.blockerad.eu"
}
}
},
{
"hostname": "de-fra-wg-102",
"location": "de-fra",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.117.130",
"include_in_country": true,
"weight": 100,
"public_key": "inG8qBhgEFhcs2EZsT9PezeWBI6+9p8tXeo0BojhpBQ=",
"ipv6_addr_in": "2001:ac8:20:270:2::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"146.70.117.144",
"146.70.117.145",
"146.70.117.146",
"146.70.117.147",
"146.70.117.148",
"146.70.117.149",
"146.70.117.150",
"146.70.117.151",
"146.70.117.152",
"146.70.117.153",
"146.70.117.154",
"2001:ac8:20:270:2::b002",
"2001:ac8:20:270:2::b003",
"2001:ac8:20:270:2::b004",
"2001:ac8:20:270:2::b005",
"2001:ac8:20:270:2::b006",
"2001:ac8:20:270:2::b007",
"2001:ac8:20:270:2::b008",
"2001:ac8:20:270:2::b009",
"2001:ac8:20:270:2::b00a",
"2001:ac8:20:270:2::b00b",
"2001:ac8:20:270:2::b00c",
"2001:ac8:20:270:2::b00d",
"2001:ac8:20:270:2::b00e",
"2001:ac8:20:270:2::b00f",
"2001:ac8:20:270:2::b010",
"2001:ac8:20:270:2::b011",
"2001:ac8:20:270:2::b012",
"2001:ac8:20:270:2::b013",
"2001:ac8:20:270:2::b014",
"2001:ac8:20:270:2::b015",
"2001:ac8:20:270:2::b016",
"2001:ac8:20:270:2::b017",
"2001:ac8:20:270:2::b018",
"2001:ac8:20:270:2::b019",
"2001:ac8:20:270:2::b01a",
"2001:ac8:20:270:2::b01b",
"2001:ac8:20:270:2::b01c",
"2001:ac8:20:270:2::b01d",
"2001:ac8:20:270:2::b01e",
"2001:ac8:20:270:2::b01f"
],
"features": {
"daita": {},
"quic": {
"addr_in": [
"146.70.117.133",
"146.70.117.134",
"146.70.117.135",
"146.70.117.136",
"146.70.117.137",
"146.70.117.138",
"146.70.117.139",
"146.70.117.140",
"146.70.117.141",
"146.70.117.142",
"146.70.117.143",
"2001:ac8:20:270:2::c002",
"2001:ac8:20:270:2::c003",
"2001:ac8:20:270:2::c004",
"2001:ac8:20:270:2::c005",
"2001:ac8:20:270:2::c006",
"2001:ac8:20:270:2::c007",
"2001:ac8:20:270:2::c008",
"2001:ac8:20:270:2::c009",
"2001:ac8:20:270:2::c00a",
"2001:ac8:20:270:2::c00b",
"2001:ac8:20:270:2::c00c",
"2001:ac8:20:270:2::c00d",
"2001:ac8:20:270:2::c00e",
"2001:ac8:20:270:2::c00f",
"2001:ac8:20:270:2::c010",
"2001:ac8:20:270:2::c011",
"2001:ac8:20:270:2::c012",
"2001:ac8:20:270:2::c013",
"2001:ac8:20:270:2::c014",
"2001:ac8:20:270:2::c015",
"2001:ac8:20:270:2::c016",
"2001:ac8:20:270:2::c017",
"2001:ac8:20:270:2::c018",
"2001:ac8:20:270:2::c019",
"2001:ac8:20:270:2::c01a",
"2001:ac8:20:270:2::c01b",
"2001:ac8:20:270:2::c01c",
"2001:ac8:20:270:2::c01d",
"2001:ac8:20:270:2::c01e",
"2001:ac8:20:270:2::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "de-fra-wg-102.blockerad.eu"
}
}
},
{
"hostname": "de-fra-wg-103",
"location": "de-fra",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "135.136.19.2",
"include_in_country": true,
"weight": 100,
"public_key": "V7g+GpphZny5CWgDdClejTQX3ImrYFRh+CVETeOWRBU=",
"ipv6_addr_in": "2001:ac8:20:271::f001",
"shadowsocks_extra_addr_in": [
"135.136.19.16",
"135.136.19.17",
"135.136.19.18",
"135.136.19.19",
"135.136.19.20",
"135.136.19.21",
"135.136.19.22",
"135.136.19.23",
"135.136.19.24",
"135.136.19.25",
"135.136.19.26",
"2001:ac8:20:271::b002",
"2001:ac8:20:271::b003",
"2001:ac8:20:271::b004",
"2001:ac8:20:271::b005",
"2001:ac8:20:271::b006",
"2001:ac8:20:271::b007",
"2001:ac8:20:271::b008",
"2001:ac8:20:271::b009",
"2001:ac8:20:271::b00a",
"2001:ac8:20:271::b00b",
"2001:ac8:20:271::b00c",
"2001:ac8:20:271::b00d",
"2001:ac8:20:271::b00e",
"2001:ac8:20:271::b00f",
"2001:ac8:20:271::b010",
"2001:ac8:20:271::b011",
"2001:ac8:20:271::b012",
"2001:ac8:20:271::b013",
"2001:ac8:20:271::b014",
"2001:ac8:20:271::b015",
"2001:ac8:20:271::b016",
"2001:ac8:20:271::b017",
"2001:ac8:20:271::b018",
"2001:ac8:20:271::b019",
"2001:ac8:20:271::b01a",
"2001:ac8:20:271::b01b",
"2001:ac8:20:271::b01c",
"2001:ac8:20:271::b01d",
"2001:ac8:20:271::b01e",
"2001:ac8:20:271::b01f"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"135.136.19.5",
"135.136.19.6",
"135.136.19.7",
"135.136.19.8",
"135.136.19.9",
"135.136.19.10",
"135.136.19.11",
"135.136.19.12",
"135.136.19.13",
"135.136.19.14",
"135.136.19.15",
"2001:ac8:20:271::c002",
"2001:ac8:20:271::c003",
"2001:ac8:20:271::c004",
"2001:ac8:20:271::c005",
"2001:ac8:20:271::c006",
"2001:ac8:20:271::c007",
"2001:ac8:20:271::c008",
"2001:ac8:20:271::c009",
"2001:ac8:20:271::c00a",
"2001:ac8:20:271::c00b",
"2001:ac8:20:271::c00c",
"2001:ac8:20:271::c00d",
"2001:ac8:20:271::c00e",
"2001:ac8:20:271::c00f",
"2001:ac8:20:271::c010",
"2001:ac8:20:271::c011",
"2001:ac8:20:271::c012",
"2001:ac8:20:271::c013",
"2001:ac8:20:271::c014",
"2001:ac8:20:271::c015",
"2001:ac8:20:271::c016",
"2001:ac8:20:271::c017",
"2001:ac8:20:271::c018",
"2001:ac8:20:271::c019",
"2001:ac8:20:271::c01a",
"2001:ac8:20:271::c01b",
"2001:ac8:20:271::c01c",
"2001:ac8:20:271::c01d",
"2001:ac8:20:271::c01e",
"2001:ac8:20:271::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "de-fra-wg-103.blockerad.eu"
}
}
},
{
"hostname": "de-fra-wg-104",
"location": "de-fra",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "135.136.19.130",
"include_in_country": true,
"weight": 100,
"public_key": "WPaUZB1eO0W/F4GMDk8uVgqQfS5q4P9F53/pbLmlDjs=",
"ipv6_addr_in": "2001:ac8:20:272::f001",
"shadowsocks_extra_addr_in": [
"135.136.19.144",
"135.136.19.145",
"135.136.19.146",
"135.136.19.147",
"135.136.19.148",
"135.136.19.149",
"135.136.19.150",
"135.136.19.151",
"135.136.19.152",
"135.136.19.153",
"135.136.19.154",
"2001:ac8:20:272::b002",
"2001:ac8:20:272::b003",
"2001:ac8:20:272::b004",
"2001:ac8:20:272::b005",
"2001:ac8:20:272::b006",
"2001:ac8:20:272::b007",
"2001:ac8:20:272::b008",
"2001:ac8:20:272::b009",
"2001:ac8:20:272::b00a",
"2001:ac8:20:272::b00b",
"2001:ac8:20:272::b00c",
"2001:ac8:20:272::b00d",
"2001:ac8:20:272::b00e",
"2001:ac8:20:272::b00f",
"2001:ac8:20:272::b010",
"2001:ac8:20:272::b011",
"2001:ac8:20:272::b012",
"2001:ac8:20:272::b013",
"2001:ac8:20:272::b014",
"2001:ac8:20:272::b015",
"2001:ac8:20:272::b016",
"2001:ac8:20:272::b017",
"2001:ac8:20:272::b018",
"2001:ac8:20:272::b019",
"2001:ac8:20:272::b01a",
"2001:ac8:20:272::b01b",
"2001:ac8:20:272::b01c",
"2001:ac8:20:272::b01d",
"2001:ac8:20:272::b01e",
"2001:ac8:20:272::b01f"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"135.136.19.133",
"135.136.19.134",
"135.136.19.135",
"135.136.19.136",
"135.136.19.137",
"135.136.19.138",
"135.136.19.139",
"135.136.19.140",
"135.136.19.141",
"135.136.19.142",
"135.136.19.143",
"2001:ac8:20:272::c002",
"2001:ac8:20:272::c003",
"2001:ac8:20:272::c004",
"2001:ac8:20:272::c005",
"2001:ac8:20:272::c006",
"2001:ac8:20:272::c007",
"2001:ac8:20:272::c008",
"2001:ac8:20:272::c009",
"2001:ac8:20:272::c00a",
"2001:ac8:20:272::c00b",
"2001:ac8:20:272::c00c",
"2001:ac8:20:272::c00d",
"2001:ac8:20:272::c00e",
"2001:ac8:20:272::c00f",
"2001:ac8:20:272::c010",
"2001:ac8:20:272::c011",
"2001:ac8:20:272::c012",
"2001:ac8:20:272::c013",
"2001:ac8:20:272::c014",
"2001:ac8:20:272::c015",
"2001:ac8:20:272::c016",
"2001:ac8:20:272::c017",
"2001:ac8:20:272::c018",
"2001:ac8:20:272::c019",
"2001:ac8:20:272::c01a",
"2001:ac8:20:272::c01b",
"2001:ac8:20:272::c01c",
"2001:ac8:20:272::c01d",
"2001:ac8:20:272::c01e",
"2001:ac8:20:272::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "de-fra-wg-104.blockerad.eu"
}
}
},
{
"hostname": "de-fra-wg-301",
"location": "de-fra",
"active": true,
"owned": false,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "194.36.25.3",
"include_in_country": true,
"weight": 100,
"public_key": "dNKRyh2MkJGZdg9jyUJtf9w5GHjX3+/fYatg+xi9TUM=",
"ipv6_addr_in": "2a07:fe00:1::a23f",
"features": {
"lwo": {}
}
},
{
"hostname": "de-fra-wg-302",
"location": "de-fra",
"active": false,
"owned": false,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "194.36.25.18",
"include_in_country": true,
"weight": 100,
"public_key": "A3DbIgPycEJhJ1fQ4zzcajLOKTZsJMeawjdPQiWav20=",
"ipv6_addr_in": "2a07:fe00:1::a24f",
"features": {
"lwo": {}
}
},
{
"hostname": "de-fra-wg-303",
"location": "de-fra",
"active": true,
"owned": false,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "194.36.25.33",
"include_in_country": true,
"weight": 100,
"public_key": "2P+9SjwVCEnMDnBiYfZtQLq9p2S2TFhCM0xJBoevYk4=",
"ipv6_addr_in": "2a07:fe00:1::a25f",
"features": {
"lwo": {}
}
},
{
"hostname": "de-fra-wg-304",
"location": "de-fra",
"active": false,
"owned": false,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "194.36.25.48",
"include_in_country": true,
"weight": 100,
"public_key": "VgNcwWy8MRhfEZY+XSisDM1ykX+uXlHQScOLqqGMLkc=",
"ipv6_addr_in": "2a07:fe00:1::a26f"
},
{
"hostname": "de-fra-wg-401",
"location": "de-fra",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "169.150.201.2",
"include_in_country": true,
"weight": 100,
"public_key": "AbM8fnQWmmX6Nv0Tz68LigPbGkamJgNjxgzPfENOdXU=",
"ipv6_addr_in": "2a02:6ea0:c762:1::a35f",
"features": {
"lwo": {}
}
},
{
"hostname": "de-fra-wg-402",
"location": "de-fra",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "169.150.201.15",
"include_in_country": true,
"weight": 100,
"public_key": "6/PBbPtoeWpJA+HZc9Iqg/PPQWD7mGVvZdwQlr1vtRk=",
"ipv6_addr_in": "2a02:6ea0:c762:2::a36f",
"features": {
"lwo": {}
}
},
{
"hostname": "de-fra-wg-403",
"location": "de-fra",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "169.150.201.28",
"include_in_country": true,
"weight": 100,
"public_key": "HWzSNMbQOQafkVp68B7aLRirhNJ6x5Wjw8/y7oUuHW0=",
"ipv6_addr_in": "2a02:6ea0:c762:3::a37f",
"features": {
"lwo": {}
}
},
{
"hostname": "dk-cph-wg-001",
"location": "dk-cph",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "45.129.56.67",
"include_in_country": true,
"weight": 100,
"public_key": "egl+0TkpFU39F5O6r6+hIBMPQLOa8/t5CymOZV6CC3Y=",
"ipv6_addr_in": "2a03:1b20:8:f011::f001",
"shadowsocks_extra_addr_in": [
"2a03:1b20:8:f011::b001",
"2a03:1b20:8:f011::b002",
"2a03:1b20:8:f011::b003",
"2a03:1b20:8:f011::b004",
"2a03:1b20:8:f011::b005",
"2a03:1b20:8:f011::b006",
"2a03:1b20:8:f011::b007",
"2a03:1b20:8:f011::b008",
"2a03:1b20:8:f011::b009",
"2a03:1b20:8:f011::b00a",
"2a03:1b20:8:f011::b00b",
"2a03:1b20:8:f011::b00c",
"2a03:1b20:8:f011::b00d",
"2a03:1b20:8:f011::b00e",
"2a03:1b20:8:f011::b00f",
"2a03:1b20:8:f011::b010",
"2a03:1b20:8:f011::b011",
"2a03:1b20:8:f011::b012",
"2a03:1b20:8:f011::b013",
"2a03:1b20:8:f011::b014",
"2a03:1b20:8:f011::b015",
"2a03:1b20:8:f011::b016",
"2a03:1b20:8:f011::b017",
"2a03:1b20:8:f011::b018",
"2a03:1b20:8:f011::b019",
"2a03:1b20:8:f011::b01a",
"2a03:1b20:8:f011::b01b",
"2a03:1b20:8:f011::b01c",
"2a03:1b20:8:f011::b01d",
"2a03:1b20:8:f011::b01e",
"2a03:1b20:8:f011::b01f"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"141.98.254.99",
"2a03:1b20:8:f011::c001",
"2a03:1b20:8:f011::c002",
"2a03:1b20:8:f011::c003",
"2a03:1b20:8:f011::c004",
"2a03:1b20:8:f011::c005",
"2a03:1b20:8:f011::c006",
"2a03:1b20:8:f011::c007",
"2a03:1b20:8:f011::c008",
"2a03:1b20:8:f011::c009",
"2a03:1b20:8:f011::c00a",
"2a03:1b20:8:f011::c00b",
"2a03:1b20:8:f011::c00c",
"2a03:1b20:8:f011::c00d",
"2a03:1b20:8:f011::c00e",
"2a03:1b20:8:f011::c00f",
"2a03:1b20:8:f011::c010",
"2a03:1b20:8:f011::c011",
"2a03:1b20:8:f011::c012",
"2a03:1b20:8:f011::c013",
"2a03:1b20:8:f011::c014",
"2a03:1b20:8:f011::c015",
"2a03:1b20:8:f011::c016",
"2a03:1b20:8:f011::c017",
"2a03:1b20:8:f011::c018",
"2a03:1b20:8:f011::c019",
"2a03:1b20:8:f011::c01a",
"2a03:1b20:8:f011::c01b",
"2a03:1b20:8:f011::c01c",
"2a03:1b20:8:f011::c01d",
"2a03:1b20:8:f011::c01e",
"2a03:1b20:8:f011::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "dk-cph-wg-001.blockerad.eu"
}
}
},
{
"hostname": "dk-cph-wg-002",
"location": "dk-cph",
"active": false,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "45.129.56.68",
"include_in_country": true,
"weight": 100,
"public_key": "R5LUBgM/1UjeAR4lt+L/yA30Gee6/VqVZ9eAB3ZTajs=",
"ipv6_addr_in": "2a03:1b20:8:f011::f101",
"shadowsocks_extra_addr_in": [
"2a03:1b20:8:f011::b102",
"2a03:1b20:8:f011::b103",
"2a03:1b20:8:f011::b104",
"2a03:1b20:8:f011::b105",
"2a03:1b20:8:f011::b106",
"2a03:1b20:8:f011::b107",
"2a03:1b20:8:f011::b108",
"2a03:1b20:8:f011::b109",
"2a03:1b20:8:f011::b10a",
"2a03:1b20:8:f011::b10b",
"2a03:1b20:8:f011::b10c",
"2a03:1b20:8:f011::b10d",
"2a03:1b20:8:f011::b10e",
"2a03:1b20:8:f011::b10f",
"2a03:1b20:8:f011::b110",
"2a03:1b20:8:f011::b111",
"2a03:1b20:8:f011::b112",
"2a03:1b20:8:f011::b113",
"2a03:1b20:8:f011::b114",
"2a03:1b20:8:f011::b115",
"2a03:1b20:8:f011::b116",
"2a03:1b20:8:f011::b117",
"2a03:1b20:8:f011::b118",
"2a03:1b20:8:f011::b119",
"2a03:1b20:8:f011::b11a",
"2a03:1b20:8:f011::b11b",
"2a03:1b20:8:f011::b11c",
"2a03:1b20:8:f011::b11d",
"2a03:1b20:8:f011::b11e",
"2a03:1b20:8:f011::b11f"
],
"features": {
"lwo": {}
}
},
{
"hostname": "dk-cph-wg-101",
"location": "dk-cph",
"active": false,
"owned": true,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "149.88.109.72",
"include_in_country": true,
"weight": 100,
"public_key": "CrS2Bd2IEVpPlg4DzHwfSCoqpNjrM35oiVdoUVKoxiY=",
"ipv6_addr_in": "2a02:6ea0:470b:0:1::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"158.173.46.12",
"158.173.46.13",
"158.173.46.14",
"158.173.46.15",
"158.173.46.16",
"158.173.46.17",
"158.173.46.18",
"158.173.46.19",
"158.173.46.20",
"2a02:6ea0:470b:0:1::b002",
"2a02:6ea0:470b:0:1::b003",
"2a02:6ea0:470b:0:1::b004",
"2a02:6ea0:470b:0:1::b005",
"2a02:6ea0:470b:0:1::b006",
"2a02:6ea0:470b:0:1::b007",
"2a02:6ea0:470b:0:1::b008",
"2a02:6ea0:470b:0:1::b009",
"2a02:6ea0:470b:0:1::b00a",
"2a02:6ea0:470b:0:1::b00b",
"2a02:6ea0:470b:0:1::b00c",
"2a02:6ea0:470b:0:1::b00d",
"2a02:6ea0:470b:0:1::b00e",
"2a02:6ea0:470b:0:1::b00f",
"2a02:6ea0:470b:0:1::b010",
"2a02:6ea0:470b:0:1::b011",
"2a02:6ea0:470b:0:1::b012",
"2a02:6ea0:470b:0:1::b013",
"2a02:6ea0:470b:0:1::b014",
"2a02:6ea0:470b:0:1::b015",
"2a02:6ea0:470b:0:1::b016",
"2a02:6ea0:470b:0:1::b017",
"2a02:6ea0:470b:0:1::b018",
"2a02:6ea0:470b:0:1::b019",
"2a02:6ea0:470b:0:1::b01a",
"2a02:6ea0:470b:0:1::b01b",
"2a02:6ea0:470b:0:1::b01c",
"2a02:6ea0:470b:0:1::b01d",
"2a02:6ea0:470b:0:1::b01e",
"2a02:6ea0:470b:0:1::b01f"
],
"features": {
"daita": {},
"quic": {
"addr_in": [
"158.173.46.3",
"158.173.46.4",
"158.173.46.5",
"158.173.46.6",
"158.173.46.7",
"158.173.46.8",
"158.173.46.9",
"158.173.46.10",
"158.173.46.11",
"2a02:6ea0:470b:0:1::c002",
"2a02:6ea0:470b:0:1::c003",
"2a02:6ea0:470b:0:1::c004",
"2a02:6ea0:470b:0:1::c005",
"2a02:6ea0:470b:0:1::c006",
"2a02:6ea0:470b:0:1::c007",
"2a02:6ea0:470b:0:1::c008",
"2a02:6ea0:470b:0:1::c009",
"2a02:6ea0:470b:0:1::c00a",
"2a02:6ea0:470b:0:1::c00b",
"2a02:6ea0:470b:0:1::c00c",
"2a02:6ea0:470b:0:1::c00d",
"2a02:6ea0:470b:0:1::c00e",
"2a02:6ea0:470b:0:1::c00f",
"2a02:6ea0:470b:0:1::c010",
"2a02:6ea0:470b:0:1::c011",
"2a02:6ea0:470b:0:1::c012",
"2a02:6ea0:470b:0:1::c013",
"2a02:6ea0:470b:0:1::c014",
"2a02:6ea0:470b:0:1::c015",
"2a02:6ea0:470b:0:1::c016",
"2a02:6ea0:470b:0:1::c017",
"2a02:6ea0:470b:0:1::c018",
"2a02:6ea0:470b:0:1::c019",
"2a02:6ea0:470b:0:1::c01a",
"2a02:6ea0:470b:0:1::c01b",
"2a02:6ea0:470b:0:1::c01c",
"2a02:6ea0:470b:0:1::c01d",
"2a02:6ea0:470b:0:1::c01e",
"2a02:6ea0:470b:0:1::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "dk-cph-wg-101.blockerad.eu"
}
}
},
{
"hostname": "dk-cph-wg-102",
"location": "dk-cph",
"active": true,
"owned": true,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "149.88.109.73",
"include_in_country": true,
"weight": 100,
"public_key": "oFSh/6OxGDc8LY+kCj9SNebPphDGM9UIeln0cseILxs=",
"ipv6_addr_in": "2a02:6ea0:470b:0:2::f001",
"shadowsocks_extra_addr_in": [
"158.173.46.106",
"158.173.46.107",
"158.173.46.108",
"158.173.46.109",
"158.173.46.110",
"158.173.46.111",
"158.173.46.112",
"158.173.46.113",
"158.173.46.114",
"158.173.46.115",
"158.173.46.116",
"158.173.46.117",
"2a02:6ea0:470b:0:2::b002",
"2a02:6ea0:470b:0:2::b003",
"2a02:6ea0:470b:0:2::b004",
"2a02:6ea0:470b:0:2::b005",
"2a02:6ea0:470b:0:2::b006",
"2a02:6ea0:470b:0:2::b007",
"2a02:6ea0:470b:0:2::b008",
"2a02:6ea0:470b:0:2::b009",
"2a02:6ea0:470b:0:2::b00a",
"2a02:6ea0:470b:0:2::b00b",
"2a02:6ea0:470b:0:2::b00c",
"2a02:6ea0:470b:0:2::b00d",
"2a02:6ea0:470b:0:2::b00e",
"2a02:6ea0:470b:0:2::b00f",
"2a02:6ea0:470b:0:2::b010",
"2a02:6ea0:470b:0:2::b011",
"2a02:6ea0:470b:0:2::b012",
"2a02:6ea0:470b:0:2::b013",
"2a02:6ea0:470b:0:2::b014",
"2a02:6ea0:470b:0:2::b015",
"2a02:6ea0:470b:0:2::b016",
"2a02:6ea0:470b:0:2::b017",
"2a02:6ea0:470b:0:2::b018",
"2a02:6ea0:470b:0:2::b019",
"2a02:6ea0:470b:0:2::b01a",
"2a02:6ea0:470b:0:2::b01b",
"2a02:6ea0:470b:0:2::b01c",
"2a02:6ea0:470b:0:2::b01d",
"2a02:6ea0:470b:0:2::b01e",
"2a02:6ea0:470b:0:2::b01f"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"158.173.46.94",
"158.173.46.95",
"158.173.46.96",
"158.173.46.97",
"158.173.46.98",
"158.173.46.99",
"158.173.46.100",
"158.173.46.101",
"158.173.46.102",
"158.173.46.103",
"158.173.46.104",
"158.173.46.105",
"2a02:6ea0:470b:0:2::c002",
"2a02:6ea0:470b:0:2::c003",
"2a02:6ea0:470b:0:2::c004",
"2a02:6ea0:470b:0:2::c005",
"2a02:6ea0:470b:0:2::c006",
"2a02:6ea0:470b:0:2::c007",
"2a02:6ea0:470b:0:2::c008",
"2a02:6ea0:470b:0:2::c009",
"2a02:6ea0:470b:0:2::c00a",
"2a02:6ea0:470b:0:2::c00b",
"2a02:6ea0:470b:0:2::c00c",
"2a02:6ea0:470b:0:2::c00d",
"2a02:6ea0:470b:0:2::c00e",
"2a02:6ea0:470b:0:2::c00f",
"2a02:6ea0:470b:0:2::c010",
"2a02:6ea0:470b:0:2::c011",
"2a02:6ea0:470b:0:2::c012",
"2a02:6ea0:470b:0:2::c013",
"2a02:6ea0:470b:0:2::c014",
"2a02:6ea0:470b:0:2::c015",
"2a02:6ea0:470b:0:2::c016",
"2a02:6ea0:470b:0:2::c017",
"2a02:6ea0:470b:0:2::c018",
"2a02:6ea0:470b:0:2::c019",
"2a02:6ea0:470b:0:2::c01a",
"2a02:6ea0:470b:0:2::c01b",
"2a02:6ea0:470b:0:2::c01c",
"2a02:6ea0:470b:0:2::c01d",
"2a02:6ea0:470b:0:2::c01e",
"2a02:6ea0:470b:0:2::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "dk-cph-wg-102.blockerad.eu"
}
}
},
{
"hostname": "dk-cph-wg-103",
"location": "dk-cph",
"active": false,
"owned": true,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "149.88.109.74",
"include_in_country": true,
"weight": 100,
"public_key": "qwH+UVu3UKbsYiHsvuXmdbvDUs/5pMV6nSCV5eNk7Q8=",
"ipv6_addr_in": "2a02:6ea0:470b:0:3::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"158.173.46.181",
"158.173.46.182",
"158.173.46.183",
"158.173.46.184",
"158.173.46.185",
"158.173.46.186",
"158.173.46.187",
"158.173.46.188",
"158.173.46.189",
"2a02:6ea0:470b:0:3::b002",
"2a02:6ea0:470b:0:3::b003",
"2a02:6ea0:470b:0:3::b004",
"2a02:6ea0:470b:0:3::b005",
"2a02:6ea0:470b:0:3::b006",
"2a02:6ea0:470b:0:3::b007",
"2a02:6ea0:470b:0:3::b008",
"2a02:6ea0:470b:0:3::b009",
"2a02:6ea0:470b:0:3::b00a",
"2a02:6ea0:470b:0:3::b00b",
"2a02:6ea0:470b:0:3::b00c",
"2a02:6ea0:470b:0:3::b00d",
"2a02:6ea0:470b:0:3::b00e",
"2a02:6ea0:470b:0:3::b00f",
"2a02:6ea0:470b:0:3::b010",
"2a02:6ea0:470b:0:3::b011",
"2a02:6ea0:470b:0:3::b012",
"2a02:6ea0:470b:0:3::b013",
"2a02:6ea0:470b:0:3::b014",
"2a02:6ea0:470b:0:3::b015",
"2a02:6ea0:470b:0:3::b016",
"2a02:6ea0:470b:0:3::b017",
"2a02:6ea0:470b:0:3::b018",
"2a02:6ea0:470b:0:3::b019",
"2a02:6ea0:470b:0:3::b01a",
"2a02:6ea0:470b:0:3::b01b",
"2a02:6ea0:470b:0:3::b01c",
"2a02:6ea0:470b:0:3::b01d",
"2a02:6ea0:470b:0:3::b01e",
"2a02:6ea0:470b:0:3::b01f"
],
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"158.173.46.172",
"158.173.46.173",
"158.173.46.174",
"158.173.46.175",
"158.173.46.176",
"158.173.46.177",
"158.173.46.178",
"158.173.46.179",
"158.173.46.180",
"2a02:6ea0:470b:0:3::c002",
"2a02:6ea0:470b:0:3::c003",
"2a02:6ea0:470b:0:3::c004",
"2a02:6ea0:470b:0:3::c005",
"2a02:6ea0:470b:0:3::c006",
"2a02:6ea0:470b:0:3::c007",
"2a02:6ea0:470b:0:3::c008",
"2a02:6ea0:470b:0:3::c009",
"2a02:6ea0:470b:0:3::c00a",
"2a02:6ea0:470b:0:3::c00b",
"2a02:6ea0:470b:0:3::c00c",
"2a02:6ea0:470b:0:3::c00d",
"2a02:6ea0:470b:0:3::c00e",
"2a02:6ea0:470b:0:3::c00f",
"2a02:6ea0:470b:0:3::c010",
"2a02:6ea0:470b:0:3::c011",
"2a02:6ea0:470b:0:3::c012",
"2a02:6ea0:470b:0:3::c013",
"2a02:6ea0:470b:0:3::c014",
"2a02:6ea0:470b:0:3::c015",
"2a02:6ea0:470b:0:3::c016",
"2a02:6ea0:470b:0:3::c017",
"2a02:6ea0:470b:0:3::c018",
"2a02:6ea0:470b:0:3::c019",
"2a02:6ea0:470b:0:3::c01a",
"2a02:6ea0:470b:0:3::c01b",
"2a02:6ea0:470b:0:3::c01c",
"2a02:6ea0:470b:0:3::c01d",
"2a02:6ea0:470b:0:3::c01e",
"2a02:6ea0:470b:0:3::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "dk-cph-wg-103.blockerad.eu"
}
}
},
{
"hostname": "dk-cph-wg-401",
"location": "dk-cph",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.197.194",
"include_in_country": true,
"weight": 100,
"public_key": "Jjml2TSqKlgzW6UzPiJszaun743QYpyl5jQk8UOQYg0=",
"ipv6_addr_in": "2001:ac8:37:97::f001"
},
{
"hostname": "dk-cph-wg-402",
"location": "dk-cph",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.197.130",
"include_in_country": true,
"weight": 100,
"public_key": "ML0NcFPqy+x+ZJg7y9vfh77hXAOtgueIqp1j+CJVrXM=",
"ipv6_addr_in": "2001:ac8:37:96::f001"
},
{
"hostname": "ee-tll-wg-001",
"location": "ee-tll",
"active": true,
"owned": false,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "194.127.167.67",
"include_in_country": true,
"weight": 100,
"public_key": "bdq37KtfoG1Tm7yQcfitdRyGeZOn/c7PwLN+LgG/6nA=",
"ipv6_addr_in": "2a07:d880:2::a01f"
},
{
"hostname": "ee-tll-wg-002",
"location": "ee-tll",
"active": true,
"owned": false,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "194.127.167.87",
"include_in_country": true,
"weight": 100,
"public_key": "vqGmmcERr/PAKDzy6Dxax8g4150rC93kmKYabZuAzws=",
"ipv6_addr_in": "2a07:d880:2::a02f"
},
{
"hostname": "ee-tll-wg-003",
"location": "ee-tll",
"active": true,
"owned": false,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "194.127.167.107",
"include_in_country": true,
"weight": 100,
"public_key": "+8dUgpD7YA4wMPnRQkO7EI7AeYd30QPMKh/hOaaGIXY=",
"ipv6_addr_in": "2a07:d880:2::a03f"
},
{
"hostname": "es-bcn-wg-001",
"location": "es-bcn",
"active": true,
"owned": false,
"provider": "HostRoyale",
"stboot": true,
"ipv4_addr_in": "185.188.61.195",
"include_in_country": true,
"weight": 100,
"public_key": "asbfbY0oP07dBdmVNDSuO3o5rbkGnR56PkXTGXO7YFg=",
"ipv6_addr_in": "2a06:3040:2:210::f001"
},
{
"hostname": "es-bcn-wg-002",
"location": "es-bcn",
"active": true,
"owned": false,
"provider": "HostRoyale",
"stboot": true,
"ipv4_addr_in": "185.188.61.225",
"include_in_country": true,
"weight": 100,
"public_key": "SoTWu5Cf7JSfaPVftMrTVzeyICGc7oc+ODl6GfqzUHA=",
"ipv6_addr_in": "2a06:3040:2:210::f101",
"features": {
"lwo": {}
}
},
{
"hostname": "es-bcn-wg-101",
"location": "es-bcn",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "185.253.99.30",
"include_in_country": true,
"weight": 100,
"public_key": "TQDQ/SUW7pme5aRWFT4ugr9YAABS/uwJNZgqYKTM+iU=",
"ipv6_addr_in": "2001:ac8:17:20::f001",
"features": {
"quic": {
"addr_in": [
"146.70.22.130",
"2001:ac8:17:20::f00a"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "es-bcn-wg-101.blockerad.eu"
}
}
},
{
"hostname": "es-bcn-wg-102",
"location": "es-bcn",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "185.253.99.98",
"include_in_country": true,
"weight": 100,
"public_key": "GqDjspXPQWM3V5nh1M9IhnxgiIwctvxuFyj73oYTRwo=",
"ipv6_addr_in": "2001:ac8:17:20::f101",
"features": {
"quic": {
"addr_in": [
"146.70.22.194",
"2001:ac8:17:20::f10a"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "es-bcn-wg-102.blockerad.eu"
}
}
},
{
"hostname": "es-mad-wg-101",
"location": "es-mad",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "45.134.213.194",
"include_in_country": true,
"weight": 100,
"public_key": "oPpPeyiQhUYqtOxwR387dmFfII8OK5LX2RPyns1rx2U=",
"ipv6_addr_in": "2a02:6ea0:c318:1::a06f",
"features": {
"lwo": {}
}
},
{
"hostname": "es-mad-wg-102",
"location": "es-mad",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "45.134.213.207",
"include_in_country": true,
"weight": 100,
"public_key": "1Wo/cQeVHX2q9k95nxN+48lgkGLsPQ+uesRb/9XdY1Y=",
"ipv6_addr_in": "2a02:6ea0:c318:2::a07f"
},
{
"hostname": "es-mad-wg-201",
"location": "es-mad",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.128.194",
"include_in_country": true,
"weight": 100,
"public_key": "LyO4Xs1eV8JwFr63a1FRnKboQn2Tu/oeMzHhbr7Y6GU=",
"ipv6_addr_in": "2001:ac8:23:85::a01f"
},
{
"hostname": "es-mad-wg-202",
"location": "es-mad",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.128.226",
"include_in_country": true,
"weight": 100,
"public_key": "iehXacO91FbBqni2IFxedEYPlW2Wvvt9GtRPPPMo9zc=",
"ipv6_addr_in": "2001:ac8:23:86::a02f"
},
{
"hostname": "es-vlc-wg-001",
"location": "es-vlc",
"active": true,
"owned": false,
"provider": "HostRoyale",
"stboot": true,
"ipv4_addr_in": "193.19.207.195",
"include_in_country": true,
"weight": 100,
"public_key": "aEObX8ThiHcN/Y40UqY8dXaGMJsVQUWhrEphbpuQRkw=",
"ipv6_addr_in": "2a06:3040:3:210::f001"
},
{
"hostname": "es-vlc-wg-002",
"location": "es-vlc",
"active": true,
"owned": false,
"provider": "HostRoyale",
"stboot": true,
"ipv4_addr_in": "193.19.207.225",
"include_in_country": true,
"weight": 100,
"public_key": "JEDqyG7iGjy/rYsE/9H7y0Sz8Sl+KWYYUvkPG7NnCjk=",
"ipv6_addr_in": "2a06:3040:3:210::f101"
},
{
"hostname": "fi-hel-wg-001",
"location": "fi-hel",
"active": true,
"owned": true,
"provider": "Creanova",
"stboot": true,
"ipv4_addr_in": "185.204.1.203",
"include_in_country": true,
"weight": 100,
"public_key": "veLqpZazR9j/Ol2G8TfrO32yEhc1i543MCN8rpy1FBA=",
"ipv6_addr_in": "2a0c:f040:0:2790::a01f",
"features": {
"quic": {
"addr_in": [
"185.77.218.49",
"2a0c:f040:0:2790::d099"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "fi-hel-wg-001.blockerad.eu"
}
}
},
{
"hostname": "fi-hel-wg-002",
"location": "fi-hel",
"active": true,
"owned": true,
"provider": "Creanova",
"stboot": true,
"ipv4_addr_in": "185.204.1.211",
"include_in_country": true,
"weight": 25,
"public_key": "8BbP3GS01dGkN5ENk1Rgedxfd80friyVOABrdMgD3EY=",
"ipv6_addr_in": "2a0c:f040:0:2790::a02f",
"shadowsocks_extra_addr_in": [
"2a0c:f040:0:2790::b201",
"2a0c:f040:0:2790::b202",
"2a0c:f040:0:2790::b203",
"2a0c:f040:0:2790::b204",
"2a0c:f040:0:2790::b205",
"2a0c:f040:0:2790::b206",
"2a0c:f040:0:2790::b207",
"2a0c:f040:0:2790::b208",
"2a0c:f040:0:2790::b209",
"2a0c:f040:0:2790::b20a",
"2a0c:f040:0:2790::b20b",
"2a0c:f040:0:2790::b20c",
"2a0c:f040:0:2790::b20d",
"2a0c:f040:0:2790::b20e",
"2a0c:f040:0:2790::b20f"
],
"features": {
"quic": {
"addr_in": [
"185.77.218.84",
"2a0c:f040:0:2790::c201",
"2a0c:f040:0:2790::c202",
"2a0c:f040:0:2790::c203",
"2a0c:f040:0:2790::c204",
"2a0c:f040:0:2790::c205",
"2a0c:f040:0:2790::c206",
"2a0c:f040:0:2790::c207",
"2a0c:f040:0:2790::c208",
"2a0c:f040:0:2790::c209",
"2a0c:f040:0:2790::c20a",
"2a0c:f040:0:2790::c20b",
"2a0c:f040:0:2790::c20c",
"2a0c:f040:0:2790::c20d",
"2a0c:f040:0:2790::c20e",
"2a0c:f040:0:2790::c20f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "fi-hel-wg-002.blockerad.eu"
}
}
},
{
"hostname": "fi-hel-wg-003",
"location": "fi-hel",
"active": true,
"owned": true,
"provider": "Creanova",
"stboot": true,
"ipv4_addr_in": "185.204.1.219",
"include_in_country": true,
"weight": 25,
"public_key": "FKodo9V6BehkNphL+neI0g4/G/cjbZyYhoptSWf3Si4=",
"ipv6_addr_in": "2a0c:f040:0:2790::a03f",
"shadowsocks_extra_addr_in": [
"2a0c:f040:0:2790::b31",
"2a0c:f040:0:2790::b32",
"2a0c:f040:0:2790::b33",
"2a0c:f040:0:2790::b34",
"2a0c:f040:0:2790::b35",
"2a0c:f040:0:2790::b36",
"2a0c:f040:0:2790::b37",
"2a0c:f040:0:2790::b38",
"2a0c:f040:0:2790::b39"
],
"features": {
"quic": {
"addr_in": [
"185.77.218.125",
"2a0c:f040:0:2790::c31",
"2a0c:f040:0:2790::c32",
"2a0c:f040:0:2790::c33",
"2a0c:f040:0:2790::c34",
"2a0c:f040:0:2790::c35",
"2a0c:f040:0:2790::c36",
"2a0c:f040:0:2790::c37",
"2a0c:f040:0:2790::c38",
"2a0c:f040:0:2790::c39",
"2a0c:f040:0:2790::c398"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "fi-hel-wg-003.blockerad.eu"
}
}
},
{
"hostname": "fi-hel-wg-101",
"location": "fi-hel",
"active": true,
"owned": true,
"provider": "Blix",
"stboot": true,
"ipv4_addr_in": "193.138.7.137",
"include_in_country": true,
"weight": 100,
"public_key": "2S3G7Sm9DVG6+uJtlDu4N6ed5V97sTbA5dCSkUelWyk=",
"ipv6_addr_in": "2a02:ed04:3581:1::f001",
"features": {
"lwo": {},
"quic": {
"addr_in": [
"193.138.7.156"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "fi-hel-wg-101.blockerad.eu"
}
}
},
{
"hostname": "fi-hel-wg-102",
"location": "fi-hel",
"active": true,
"owned": true,
"provider": "Blix",
"stboot": true,
"ipv4_addr_in": "193.138.7.157",
"include_in_country": true,
"weight": 100,
"public_key": "xeHVhXxyyFqUEE+nsu5Tzd/t9en+++4fVFcSFngpcAU=",
"ipv6_addr_in": "2a02:ed04:3581:2::f001"
},
{
"hostname": "fi-hel-wg-103",
"location": "fi-hel",
"active": true,
"owned": true,
"provider": "Blix",
"stboot": true,
"ipv4_addr_in": "193.138.7.177",
"include_in_country": true,
"weight": 100,
"public_key": "Mlvu14bSD6jb7ajH/CiJ/IO8W+spB8H6VmdGkFGOcUQ=",
"ipv6_addr_in": "2a02:ed04:3581:3::f001"
},
{
"hostname": "fi-hel-wg-104",
"location": "fi-hel",
"active": true,
"owned": true,
"provider": "Blix",
"stboot": true,
"ipv4_addr_in": "193.138.7.197",
"include_in_country": true,
"weight": 100,
"public_key": "keRQGHUbYP2qgDTbYqOsI9byfNb0LOpTZ/KdC67cJiA=",
"ipv6_addr_in": "2a02:ed04:3581:4::f001"
},
{
"hostname": "fi-hel-wg-201",
"location": "fi-hel",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "185.65.133.5",
"include_in_country": true,
"weight": 500,
"public_key": "u+Ir9bnz8PtwXoJGQXvCxz6a+1NChEbBIox8KdWarxk=",
"ipv6_addr_in": "2a03:1b20:d:f011:1::f001",
"shadowsocks_extra_addr_in": [
"185.65.133.7",
"2a03:1b20:d:f011:1::b002",
"2a03:1b20:d:f011:1::b003",
"2a03:1b20:d:f011:1::b004",
"2a03:1b20:d:f011:1::b005",
"2a03:1b20:d:f011:1::b006",
"2a03:1b20:d:f011:1::b007",
"2a03:1b20:d:f011:1::b008",
"2a03:1b20:d:f011:1::b009",
"2a03:1b20:d:f011:1::b00a",
"2a03:1b20:d:f011:1::b00b",
"2a03:1b20:d:f011:1::b00c",
"2a03:1b20:d:f011:1::b00d",
"2a03:1b20:d:f011:1::b00e",
"2a03:1b20:d:f011:1::b00f",
"2a03:1b20:d:f011:1::b010",
"2a03:1b20:d:f011:1::b011",
"2a03:1b20:d:f011:1::b012",
"2a03:1b20:d:f011:1::b013",
"2a03:1b20:d:f011:1::b014",
"2a03:1b20:d:f011:1::b015",
"2a03:1b20:d:f011:1::b016",
"2a03:1b20:d:f011:1::b017",
"2a03:1b20:d:f011:1::b018",
"2a03:1b20:d:f011:1::b019",
"2a03:1b20:d:f011:1::b01a",
"2a03:1b20:d:f011:1::b01b",
"2a03:1b20:d:f011:1::b01c",
"2a03:1b20:d:f011:1::b01d",
"2a03:1b20:d:f011:1::b01e",
"2a03:1b20:d:f011:1::b01f",
"91.206.168.37",
"91.206.168.38",
"91.206.168.39",
"91.206.168.40",
"91.206.168.41",
"91.206.168.42",
"91.206.168.43",
"91.206.168.44",
"91.206.168.45",
"91.206.168.46",
"91.206.168.47",
"91.206.168.48",
"91.206.168.49",
"91.206.168.50",
"91.206.168.51",
"91.206.168.52",
"91.206.168.53",
"91.206.168.54",
"91.206.168.55",
"91.206.168.56",
"91.206.168.57",
"91.206.168.58",
"91.206.168.59",
"91.206.168.60",
"91.206.168.61",
"91.206.168.62",
"91.206.168.63",
"91.206.168.64",
"91.206.168.65",
"91.206.168.66",
"91.206.168.67",
"91.206.168.68",
"91.206.168.69",
"91.206.168.70",
"91.206.168.71",
"91.206.168.72",
"91.206.168.73",
"91.206.168.74",
"91.206.168.75",
"91.206.168.76",
"91.206.168.77",
"91.206.168.78",
"91.206.168.79"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"185.65.133.8",
"2a03:1b20:d:f011:1::c002",
"2a03:1b20:d:f011:1::c003",
"2a03:1b20:d:f011:1::c004",
"2a03:1b20:d:f011:1::c005",
"2a03:1b20:d:f011:1::c006",
"2a03:1b20:d:f011:1::c007",
"2a03:1b20:d:f011:1::c008",
"2a03:1b20:d:f011:1::c009",
"2a03:1b20:d:f011:1::c00a",
"2a03:1b20:d:f011:1::c00b",
"2a03:1b20:d:f011:1::c00c",
"2a03:1b20:d:f011:1::c00d",
"2a03:1b20:d:f011:1::c00e",
"2a03:1b20:d:f011:1::c00f",
"2a03:1b20:d:f011:1::c010",
"2a03:1b20:d:f011:1::c011",
"2a03:1b20:d:f011:1::c012",
"2a03:1b20:d:f011:1::c013",
"2a03:1b20:d:f011:1::c014",
"2a03:1b20:d:f011:1::c015",
"2a03:1b20:d:f011:1::c016",
"2a03:1b20:d:f011:1::c017",
"2a03:1b20:d:f011:1::c018",
"2a03:1b20:d:f011:1::c019",
"2a03:1b20:d:f011:1::c01a",
"2a03:1b20:d:f011:1::c01b",
"2a03:1b20:d:f011:1::c01c",
"2a03:1b20:d:f011:1::c01d",
"2a03:1b20:d:f011:1::c01e",
"2a03:1b20:d:f011:1::c01f",
"91.206.168.11",
"91.206.168.12",
"91.206.168.13",
"91.206.168.14",
"91.206.168.15",
"91.206.168.16",
"91.206.168.17",
"91.206.168.18",
"91.206.168.19",
"91.206.168.20",
"91.206.168.21",
"91.206.168.22",
"91.206.168.23",
"91.206.168.24",
"91.206.168.25",
"91.206.168.26",
"91.206.168.27",
"91.206.168.28",
"91.206.168.29",
"91.206.168.30",
"91.206.168.31",
"91.206.168.32",
"91.206.168.33",
"91.206.168.34",
"91.206.168.35",
"91.206.168.36"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "fi-hel-wg-201.blockerad.eu"
}
}
},
{
"hostname": "fi-hel-wg-202",
"location": "fi-hel",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "185.65.133.85",
"include_in_country": true,
"weight": 500,
"public_key": "hAbVKL5Q0285gJ28nMSfztw7/FXJb+cxiKD2NMgPpTM=",
"ipv6_addr_in": "2a03:1b20:d:f011:2::f001",
"shadowsocks_extra_addr_in": [
"185.65.133.87",
"2a03:1b20:d:f011:2::b002",
"2a03:1b20:d:f011:2::b003",
"2a03:1b20:d:f011:2::b004",
"2a03:1b20:d:f011:2::b005",
"2a03:1b20:d:f011:2::b006",
"2a03:1b20:d:f011:2::b007",
"2a03:1b20:d:f011:2::b008",
"2a03:1b20:d:f011:2::b009",
"2a03:1b20:d:f011:2::b00a",
"2a03:1b20:d:f011:2::b00b",
"2a03:1b20:d:f011:2::b00c",
"2a03:1b20:d:f011:2::b00d",
"2a03:1b20:d:f011:2::b00e",
"2a03:1b20:d:f011:2::b00f",
"2a03:1b20:d:f011:2::b010",
"2a03:1b20:d:f011:2::b011",
"2a03:1b20:d:f011:2::b012",
"2a03:1b20:d:f011:2::b013",
"2a03:1b20:d:f011:2::b014",
"2a03:1b20:d:f011:2::b015",
"2a03:1b20:d:f011:2::b016",
"2a03:1b20:d:f011:2::b017",
"2a03:1b20:d:f011:2::b018",
"2a03:1b20:d:f011:2::b019",
"2a03:1b20:d:f011:2::b01a",
"2a03:1b20:d:f011:2::b01b",
"2a03:1b20:d:f011:2::b01c",
"2a03:1b20:d:f011:2::b01d",
"2a03:1b20:d:f011:2::b01e",
"2a03:1b20:d:f011:2::b01f",
"91.206.168.126",
"91.206.168.127",
"91.206.168.128",
"91.206.168.129",
"91.206.168.130",
"91.206.168.131",
"91.206.168.132",
"91.206.168.133",
"91.206.168.134",
"91.206.168.135",
"91.206.168.136",
"91.206.168.137",
"91.206.168.138",
"91.206.168.139",
"91.206.168.140",
"91.206.168.141",
"91.206.168.142",
"91.206.168.143",
"91.206.168.144",
"91.206.168.145",
"91.206.168.146",
"91.206.168.147",
"91.206.168.148",
"91.206.168.149",
"91.206.168.150",
"91.206.168.151",
"91.206.168.152",
"91.206.168.153",
"91.206.168.154",
"91.206.168.155",
"91.206.168.156",
"91.206.168.157",
"91.206.168.158",
"91.206.168.159"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"185.65.133.88",
"2a03:1b20:d:f011:2::c002",
"2a03:1b20:d:f011:2::c003",
"2a03:1b20:d:f011:2::c004",
"2a03:1b20:d:f011:2::c005",
"2a03:1b20:d:f011:2::c006",
"2a03:1b20:d:f011:2::c007",
"2a03:1b20:d:f011:2::c008",
"2a03:1b20:d:f011:2::c009",
"2a03:1b20:d:f011:2::c00a",
"2a03:1b20:d:f011:2::c00b",
"2a03:1b20:d:f011:2::c00c",
"2a03:1b20:d:f011:2::c00d",
"2a03:1b20:d:f011:2::c00e",
"2a03:1b20:d:f011:2::c00f",
"2a03:1b20:d:f011:2::c010",
"2a03:1b20:d:f011:2::c011",
"2a03:1b20:d:f011:2::c012",
"2a03:1b20:d:f011:2::c013",
"2a03:1b20:d:f011:2::c014",
"2a03:1b20:d:f011:2::c015",
"2a03:1b20:d:f011:2::c016",
"2a03:1b20:d:f011:2::c017",
"2a03:1b20:d:f011:2::c018",
"2a03:1b20:d:f011:2::c019",
"2a03:1b20:d:f011:2::c01a",
"2a03:1b20:d:f011:2::c01b",
"2a03:1b20:d:f011:2::c01c",
"2a03:1b20:d:f011:2::c01d",
"2a03:1b20:d:f011:2::c01e",
"2a03:1b20:d:f011:2::c01f",
"91.206.168.90",
"91.206.168.91",
"91.206.168.92",
"91.206.168.93",
"91.206.168.94",
"91.206.168.95",
"91.206.168.96",
"91.206.168.97",
"91.206.168.98",
"91.206.168.99",
"91.206.168.100",
"91.206.168.101",
"91.206.168.102",
"91.206.168.103",
"91.206.168.104",
"91.206.168.105",
"91.206.168.106",
"91.206.168.107",
"91.206.168.108",
"91.206.168.109",
"91.206.168.110",
"91.206.168.111",
"91.206.168.112",
"91.206.168.113",
"91.206.168.114",
"91.206.168.115",
"91.206.168.116",
"91.206.168.117",
"91.206.168.118",
"91.206.168.119",
"91.206.168.120",
"91.206.168.121",
"91.206.168.122",
"91.206.168.123",
"91.206.168.124",
"91.206.168.125"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "fi-hel-wg-202.blockerad.eu"
}
}
},
{
"hostname": "fi-hel-wg-203",
"location": "fi-hel",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "185.65.133.165",
"include_in_country": true,
"weight": 500,
"public_key": "Ck25URxG+bxlgfJVZ0A6wm7xddltSu5t1yig3CgKBDM=",
"ipv6_addr_in": "2a03:1b20:d:f011:3::f001",
"shadowsocks_extra_addr_in": [
"185.65.133.167",
"2a03:1b20:d:f011:3::b002",
"2a03:1b20:d:f011:3::b003",
"2a03:1b20:d:f011:3::b004",
"2a03:1b20:d:f011:3::b005",
"2a03:1b20:d:f011:3::b006",
"2a03:1b20:d:f011:3::b007",
"2a03:1b20:d:f011:3::b008",
"2a03:1b20:d:f011:3::b009",
"2a03:1b20:d:f011:3::b00a",
"2a03:1b20:d:f011:3::b00b",
"2a03:1b20:d:f011:3::b00c",
"2a03:1b20:d:f011:3::b00d",
"2a03:1b20:d:f011:3::b00e",
"2a03:1b20:d:f011:3::b00f",
"2a03:1b20:d:f011:3::b010",
"2a03:1b20:d:f011:3::b011",
"2a03:1b20:d:f011:3::b012",
"2a03:1b20:d:f011:3::b013",
"2a03:1b20:d:f011:3::b014",
"2a03:1b20:d:f011:3::b015",
"2a03:1b20:d:f011:3::b016",
"2a03:1b20:d:f011:3::b017",
"2a03:1b20:d:f011:3::b018",
"2a03:1b20:d:f011:3::b019",
"2a03:1b20:d:f011:3::b01a",
"2a03:1b20:d:f011:3::b01b",
"2a03:1b20:d:f011:3::b01c",
"2a03:1b20:d:f011:3::b01d",
"2a03:1b20:d:f011:3::b01e",
"2a03:1b20:d:f011:3::b01f",
"91.206.168.206",
"91.206.168.207",
"91.206.168.208",
"91.206.168.209",
"91.206.168.210",
"91.206.168.211",
"91.206.168.212",
"91.206.168.213",
"91.206.168.214",
"91.206.168.215",
"91.206.168.216",
"91.206.168.217",
"91.206.168.218",
"91.206.168.219",
"91.206.168.220",
"91.206.168.221",
"91.206.168.222",
"91.206.168.223",
"91.206.168.224",
"91.206.168.225",
"91.206.168.226",
"91.206.168.227",
"91.206.168.228",
"91.206.168.229",
"91.206.168.230",
"91.206.168.231",
"91.206.168.232",
"91.206.168.233",
"91.206.168.234",
"91.206.168.235",
"91.206.168.236",
"91.206.168.237",
"91.206.168.238",
"91.206.168.239"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"185.65.133.168",
"2a03:1b20:d:f011:3::c002",
"2a03:1b20:d:f011:3::c003",
"2a03:1b20:d:f011:3::c004",
"2a03:1b20:d:f011:3::c005",
"2a03:1b20:d:f011:3::c006",
"2a03:1b20:d:f011:3::c007",
"2a03:1b20:d:f011:3::c008",
"2a03:1b20:d:f011:3::c009",
"2a03:1b20:d:f011:3::c00a",
"2a03:1b20:d:f011:3::c00b",
"2a03:1b20:d:f011:3::c00c",
"2a03:1b20:d:f011:3::c00d",
"2a03:1b20:d:f011:3::c00e",
"2a03:1b20:d:f011:3::c00f",
"2a03:1b20:d:f011:3::c010",
"2a03:1b20:d:f011:3::c011",
"2a03:1b20:d:f011:3::c012",
"2a03:1b20:d:f011:3::c013",
"2a03:1b20:d:f011:3::c014",
"2a03:1b20:d:f011:3::c015",
"2a03:1b20:d:f011:3::c016",
"2a03:1b20:d:f011:3::c017",
"2a03:1b20:d:f011:3::c018",
"2a03:1b20:d:f011:3::c019",
"2a03:1b20:d:f011:3::c01a",
"2a03:1b20:d:f011:3::c01b",
"2a03:1b20:d:f011:3::c01c",
"2a03:1b20:d:f011:3::c01d",
"2a03:1b20:d:f011:3::c01e",
"2a03:1b20:d:f011:3::c01f",
"91.206.168.170",
"91.206.168.171",
"91.206.168.172",
"91.206.168.173",
"91.206.168.174",
"91.206.168.175",
"91.206.168.176",
"91.206.168.177",
"91.206.168.178",
"91.206.168.179",
"91.206.168.180",
"91.206.168.181",
"91.206.168.182",
"91.206.168.183",
"91.206.168.184",
"91.206.168.185",
"91.206.168.186",
"91.206.168.187",
"91.206.168.188",
"91.206.168.189",
"91.206.168.190",
"91.206.168.191",
"91.206.168.192",
"91.206.168.193",
"91.206.168.194",
"91.206.168.195",
"91.206.168.196",
"91.206.168.197",
"91.206.168.198",
"91.206.168.199",
"91.206.168.200",
"91.206.168.201",
"91.206.168.202",
"91.206.168.203",
"91.206.168.204",
"91.206.168.205"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "fi-hel-wg-203.blockerad.eu"
}
}
},
{
"hostname": "fr-bod-wg-001",
"location": "fr-bod",
"active": true,
"owned": false,
"provider": "HostRoyale",
"stboot": true,
"ipv4_addr_in": "45.134.79.67",
"include_in_country": true,
"weight": 100,
"public_key": "y6dcYS7MPeApbLoWLahjku5w5cufnNkwHzj1iwDPpS0=",
"ipv6_addr_in": "2a06:3040:4:610::f001",
"features": {
"lwo": {}
}
},
{
"hostname": "fr-bod-wg-002",
"location": "fr-bod",
"active": true,
"owned": false,
"provider": "HostRoyale",
"stboot": true,
"ipv4_addr_in": "45.134.79.97",
"include_in_country": true,
"weight": 100,
"public_key": "ZBOJ2w5DqG35T1zjV/F1UgrXkDhNxObnwdm2FUwyu2o=",
"ipv6_addr_in": "2a06:3040:4:610::f101"
},
{
"hostname": "fr-mrs-wg-001",
"location": "fr-mrs",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "138.199.15.162",
"include_in_country": true,
"weight": 300,
"public_key": "MOk2OTDEaFFN4vsCAgf+qQi6IlY99nCeDEzpXyo65wg=",
"ipv6_addr_in": "2a02:6ea0:dc05::a15f",
"daita": true,
"features": {
"daita": {}
}
},
{
"hostname": "fr-mrs-wg-002",
"location": "fr-mrs",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "138.199.15.146",
"include_in_country": true,
"weight": 300,
"public_key": "Z0LEgZIPhNj0+/VWknU3roHlVI3qqAfoV6th9NSC0F0=",
"ipv6_addr_in": "2a02:6ea0:dc06::a16f"
},
{
"hostname": "fr-par-wg-001",
"location": "fr-par",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "193.32.126.66",
"include_in_country": true,
"weight": 100,
"public_key": "ov323GyDOEHLT0sNRUUPYiE3BkvFDjpmi1a4fzv49hE=",
"ipv6_addr_in": "2a03:1b20:9:f011::a01f",
"shadowsocks_extra_addr_in": [
"2a03:1b20:9:f011::b002",
"2a03:1b20:9:f011::b003",
"2a03:1b20:9:f011::b004",
"2a03:1b20:9:f011::b005",
"2a03:1b20:9:f011::b006",
"2a03:1b20:9:f011::b007",
"2a03:1b20:9:f011::b008",
"2a03:1b20:9:f011::b009",
"2a03:1b20:9:f011::b00a",
"2a03:1b20:9:f011::b00b",
"2a03:1b20:9:f011::b00c",
"2a03:1b20:9:f011::b00d",
"2a03:1b20:9:f011::b00e",
"2a03:1b20:9:f011::b00f",
"2a03:1b20:9:f011::b010",
"2a03:1b20:9:f011::b011",
"2a03:1b20:9:f011::b012",
"2a03:1b20:9:f011::b013",
"2a03:1b20:9:f011::b014",
"2a03:1b20:9:f011::b015",
"2a03:1b20:9:f011::b016",
"2a03:1b20:9:f011::b017",
"2a03:1b20:9:f011::b018",
"2a03:1b20:9:f011::b019",
"2a03:1b20:9:f011::b01a",
"2a03:1b20:9:f011::b01b",
"2a03:1b20:9:f011::b01c",
"2a03:1b20:9:f011::b01d",
"2a03:1b20:9:f011::b01e",
"2a03:1b20:9:f011::b01f"
]
},
{
"hostname": "fr-par-wg-002",
"location": "fr-par",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "193.32.126.67",
"include_in_country": true,
"weight": 100,
"public_key": "R5Ve+PJD24QjNXi2Dim7szwCiOLnv+6hg+WyTudAYmE=",
"ipv6_addr_in": "2a03:1b20:9:f011::f101"
},
{
"hostname": "fr-par-wg-003",
"location": "fr-par",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "193.32.126.68",
"include_in_country": true,
"weight": 100,
"public_key": "w4r/o6VImF7l0/De3JpOGnpzjAFv9wcCu8Rop5eZkWc=",
"ipv6_addr_in": "2a03:1b20:9:f011::f201"
},
{
"hostname": "fr-par-wg-004",
"location": "fr-par",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "193.32.126.69",
"include_in_country": true,
"weight": 100,
"public_key": "E/KjR7nlFouuRXh1pwGDr7iK2TAZ6c4K0LjjmA1A2Tc=",
"ipv6_addr_in": "2a03:1b20:9:f011::f301"
},
{
"hostname": "fr-par-wg-005",
"location": "fr-par",
"active": false,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "193.32.126.70",
"include_in_country": true,
"weight": 100,
"public_key": "cmqtSjWUa4/0bENQDKxdr0vQqf4nFVDodarHm0Pc0hY=",
"ipv6_addr_in": "2a03:1b20:9:f011::f401"
},
{
"hostname": "fr-par-wg-006",
"location": "fr-par",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "193.32.126.84",
"include_in_country": true,
"weight": 100,
"public_key": "x0k8A2S7Dx7VNX2Yo2qRPZW/VefIogID5bVynklBugE=",
"ipv6_addr_in": "2a03:1b20:9:f011::f501",
"shadowsocks_extra_addr_in": [
"2a03:1b20:9:f011::b502",
"2a03:1b20:9:f011::b503",
"2a03:1b20:9:f011::b504",
"2a03:1b20:9:f011::b505",
"2a03:1b20:9:f011::b506",
"2a03:1b20:9:f011::b507",
"2a03:1b20:9:f011::b508",
"2a03:1b20:9:f011::b509",
"2a03:1b20:9:f011::b50a",
"2a03:1b20:9:f011::b50b",
"2a03:1b20:9:f011::b50c",
"2a03:1b20:9:f011::b50d",
"2a03:1b20:9:f011::b50e",
"2a03:1b20:9:f011::b50f",
"2a03:1b20:9:f011::b510",
"2a03:1b20:9:f011::b511",
"2a03:1b20:9:f011::b512",
"2a03:1b20:9:f011::b513",
"2a03:1b20:9:f011::b514",
"2a03:1b20:9:f011::b515",
"2a03:1b20:9:f011::b516",
"2a03:1b20:9:f011::b517",
"2a03:1b20:9:f011::b518",
"2a03:1b20:9:f011::b519",
"2a03:1b20:9:f011::b51a",
"2a03:1b20:9:f011::b51b",
"2a03:1b20:9:f011::b51c",
"2a03:1b20:9:f011::b51d",
"2a03:1b20:9:f011::b51e",
"2a03:1b20:9:f011::b51f"
]
},
{
"hostname": "fr-par-wg-007",
"location": "fr-par",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "193.32.126.83",
"include_in_country": true,
"weight": 100,
"public_key": "D2o4woLw59apODi8NgvVtsbEJOAF5HRxXCp3R4mzGAs=",
"ipv6_addr_in": "2a03:1b20:9:f011::3f",
"shadowsocks_extra_addr_in": [
"2a03:1b20:9:f011::b602",
"2a03:1b20:9:f011::b603",
"2a03:1b20:9:f011::b604",
"2a03:1b20:9:f011::b605",
"2a03:1b20:9:f011::b606",
"2a03:1b20:9:f011::b607",
"2a03:1b20:9:f011::b608",
"2a03:1b20:9:f011::b609",
"2a03:1b20:9:f011::b60a",
"2a03:1b20:9:f011::b60b",
"2a03:1b20:9:f011::b60c",
"2a03:1b20:9:f011::b60d",
"2a03:1b20:9:f011::b60e",
"2a03:1b20:9:f011::b60f",
"2a03:1b20:9:f011::b610",
"2a03:1b20:9:f011::b611",
"2a03:1b20:9:f011::b612",
"2a03:1b20:9:f011::b613",
"2a03:1b20:9:f011::b614",
"2a03:1b20:9:f011::b615",
"2a03:1b20:9:f011::b616",
"2a03:1b20:9:f011::b617",
"2a03:1b20:9:f011::b618",
"2a03:1b20:9:f011::b619",
"2a03:1b20:9:f011::b61a",
"2a03:1b20:9:f011::b61b",
"2a03:1b20:9:f011::b61c",
"2a03:1b20:9:f011::b61d",
"2a03:1b20:9:f011::b61e",
"2a03:1b20:9:f011::b61f"
]
},
{
"hostname": "fr-par-wg-101",
"location": "fr-par",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.184.2",
"include_in_country": true,
"weight": 100,
"public_key": "py4bg/TO5waXCoytaDpddP/qkI0tS1Wv3yAcgZ/A4wA=",
"ipv6_addr_in": "2001:ac8:25:3a::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"146.70.184.13",
"146.70.184.14",
"146.70.184.15",
"146.70.184.16",
"146.70.184.17",
"146.70.184.18",
"146.70.184.19",
"146.70.184.20",
"146.70.184.21",
"146.70.184.22",
"2001:ac8:25:3a::b002",
"2001:ac8:25:3a::b003",
"2001:ac8:25:3a::b004",
"2001:ac8:25:3a::b005",
"2001:ac8:25:3a::b006",
"2001:ac8:25:3a::b007",
"2001:ac8:25:3a::b008",
"2001:ac8:25:3a::b009",
"2001:ac8:25:3a::b00a",
"2001:ac8:25:3a::b00b",
"2001:ac8:25:3a::b00c",
"2001:ac8:25:3a::b00d",
"2001:ac8:25:3a::b00e",
"2001:ac8:25:3a::b00f",
"2001:ac8:25:3a::b010",
"2001:ac8:25:3a::b011",
"2001:ac8:25:3a::b012",
"2001:ac8:25:3a::b013",
"2001:ac8:25:3a::b014",
"2001:ac8:25:3a::b015",
"2001:ac8:25:3a::b016",
"2001:ac8:25:3a::b017",
"2001:ac8:25:3a::b018",
"2001:ac8:25:3a::b019",
"2001:ac8:25:3a::b01a",
"2001:ac8:25:3a::b01b",
"2001:ac8:25:3a::b01c",
"2001:ac8:25:3a::b01d",
"2001:ac8:25:3a::b01e",
"2001:ac8:25:3a::b01f"
],
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"146.70.184.23",
"146.70.184.24",
"146.70.184.25",
"146.70.184.26",
"146.70.184.27",
"146.70.184.28",
"146.70.184.29",
"146.70.184.30",
"146.70.184.31",
"146.70.184.32",
"2001:ac8:25:3a::c002",
"2001:ac8:25:3a::c003",
"2001:ac8:25:3a::c004",
"2001:ac8:25:3a::c005",
"2001:ac8:25:3a::c006",
"2001:ac8:25:3a::c007",
"2001:ac8:25:3a::c008",
"2001:ac8:25:3a::c009",
"2001:ac8:25:3a::c00a",
"2001:ac8:25:3a::c00b",
"2001:ac8:25:3a::c00c",
"2001:ac8:25:3a::c00d",
"2001:ac8:25:3a::c00e",
"2001:ac8:25:3a::c00f",
"2001:ac8:25:3a::c010",
"2001:ac8:25:3a::c011",
"2001:ac8:25:3a::c012",
"2001:ac8:25:3a::c013",
"2001:ac8:25:3a::c014",
"2001:ac8:25:3a::c015",
"2001:ac8:25:3a::c016",
"2001:ac8:25:3a::c017",
"2001:ac8:25:3a::c018",
"2001:ac8:25:3a::c019",
"2001:ac8:25:3a::c01a",
"2001:ac8:25:3a::c01b",
"2001:ac8:25:3a::c01c",
"2001:ac8:25:3a::c01d",
"2001:ac8:25:3a::c01e",
"2001:ac8:25:3a::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "fr-par-wg-101.blockerad.eu"
}
}
},
{
"hostname": "fr-par-wg-102",
"location": "fr-par",
"active": false,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.184.130",
"include_in_country": true,
"weight": 100,
"public_key": "gx9/WJPB3eu9nbbDA+gku9BPKhpAnJ0heaE2BZEr6Go=",
"ipv6_addr_in": "2001:ac8:25:3b::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"146.70.184.141",
"146.70.184.142",
"146.70.184.143",
"146.70.184.144",
"146.70.184.145",
"146.70.184.146",
"146.70.184.147",
"146.70.184.148",
"146.70.184.149",
"146.70.184.150",
"2001:ac8:25:3b::b002",
"2001:ac8:25:3b::b003",
"2001:ac8:25:3b::b004",
"2001:ac8:25:3b::b005",
"2001:ac8:25:3b::b006",
"2001:ac8:25:3b::b007",
"2001:ac8:25:3b::b008",
"2001:ac8:25:3b::b009",
"2001:ac8:25:3b::b00a",
"2001:ac8:25:3b::b00b",
"2001:ac8:25:3b::b00c",
"2001:ac8:25:3b::b00d",
"2001:ac8:25:3b::b00e",
"2001:ac8:25:3b::b00f",
"2001:ac8:25:3b::b010",
"2001:ac8:25:3b::b011",
"2001:ac8:25:3b::b012",
"2001:ac8:25:3b::b013",
"2001:ac8:25:3b::b014",
"2001:ac8:25:3b::b015",
"2001:ac8:25:3b::b016",
"2001:ac8:25:3b::b017",
"2001:ac8:25:3b::b018",
"2001:ac8:25:3b::b019",
"2001:ac8:25:3b::b01a",
"2001:ac8:25:3b::b01b",
"2001:ac8:25:3b::b01c",
"2001:ac8:25:3b::b01d",
"2001:ac8:25:3b::b01e",
"2001:ac8:25:3b::b01f"
],
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"146.70.184.151",
"146.70.184.152",
"146.70.184.153",
"146.70.184.154",
"146.70.184.155",
"146.70.184.156",
"146.70.184.157",
"146.70.184.158",
"146.70.184.159",
"146.70.184.160",
"2001:ac8:25:3b::c002",
"2001:ac8:25:3b::c003",
"2001:ac8:25:3b::c004",
"2001:ac8:25:3b::c005",
"2001:ac8:25:3b::c006",
"2001:ac8:25:3b::c007",
"2001:ac8:25:3b::c008",
"2001:ac8:25:3b::c009",
"2001:ac8:25:3b::c00a",
"2001:ac8:25:3b::c00b",
"2001:ac8:25:3b::c00c",
"2001:ac8:25:3b::c00d",
"2001:ac8:25:3b::c00e",
"2001:ac8:25:3b::c00f",
"2001:ac8:25:3b::c010",
"2001:ac8:25:3b::c011",
"2001:ac8:25:3b::c012",
"2001:ac8:25:3b::c013",
"2001:ac8:25:3b::c014",
"2001:ac8:25:3b::c015",
"2001:ac8:25:3b::c016",
"2001:ac8:25:3b::c017",
"2001:ac8:25:3b::c018",
"2001:ac8:25:3b::c019",
"2001:ac8:25:3b::c01a",
"2001:ac8:25:3b::c01b",
"2001:ac8:25:3b::c01c",
"2001:ac8:25:3b::c01d",
"2001:ac8:25:3b::c01e",
"2001:ac8:25:3b::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "fr-par-wg-102.blockerad.eu"
}
}
},
{
"hostname": "fr-par-wg-103",
"location": "fr-par",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "185.244.213.2",
"include_in_country": true,
"weight": 100,
"public_key": "BKxcFQnXCpgpGk38nDIWKgl6oeABN3GyyreMrOY7qh4=",
"ipv6_addr_in": "2001:ac8:25:3c::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"185.244.213.13",
"185.244.213.14",
"185.244.213.15",
"185.244.213.16",
"185.244.213.17",
"185.244.213.18",
"185.244.213.19",
"185.244.213.20",
"185.244.213.21",
"185.244.213.22",
"2001:ac8:25:3c::b002",
"2001:ac8:25:3c::b003",
"2001:ac8:25:3c::b004",
"2001:ac8:25:3c::b005",
"2001:ac8:25:3c::b006",
"2001:ac8:25:3c::b007",
"2001:ac8:25:3c::b008",
"2001:ac8:25:3c::b009",
"2001:ac8:25:3c::b00a",
"2001:ac8:25:3c::b00b",
"2001:ac8:25:3c::b00c",
"2001:ac8:25:3c::b00d",
"2001:ac8:25:3c::b00e",
"2001:ac8:25:3c::b00f",
"2001:ac8:25:3c::b010",
"2001:ac8:25:3c::b011",
"2001:ac8:25:3c::b012",
"2001:ac8:25:3c::b013",
"2001:ac8:25:3c::b014",
"2001:ac8:25:3c::b015",
"2001:ac8:25:3c::b016",
"2001:ac8:25:3c::b017",
"2001:ac8:25:3c::b018",
"2001:ac8:25:3c::b019",
"2001:ac8:25:3c::b01a",
"2001:ac8:25:3c::b01b",
"2001:ac8:25:3c::b01c",
"2001:ac8:25:3c::b01d",
"2001:ac8:25:3c::b01e",
"2001:ac8:25:3c::b01f"
],
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"185.244.213.23",
"185.244.213.24",
"185.244.213.25",
"185.244.213.26",
"185.244.213.27",
"185.244.213.28",
"185.244.213.29",
"185.244.213.30",
"185.244.213.31",
"185.244.213.32",
"2001:ac8:25:3c::c002",
"2001:ac8:25:3c::c003",
"2001:ac8:25:3c::c004",
"2001:ac8:25:3c::c005",
"2001:ac8:25:3c::c006",
"2001:ac8:25:3c::c007",
"2001:ac8:25:3c::c008",
"2001:ac8:25:3c::c009",
"2001:ac8:25:3c::c00a",
"2001:ac8:25:3c::c00b",
"2001:ac8:25:3c::c00c",
"2001:ac8:25:3c::c00d",
"2001:ac8:25:3c::c00e",
"2001:ac8:25:3c::c00f",
"2001:ac8:25:3c::c010",
"2001:ac8:25:3c::c011",
"2001:ac8:25:3c::c012",
"2001:ac8:25:3c::c013",
"2001:ac8:25:3c::c014",
"2001:ac8:25:3c::c015",
"2001:ac8:25:3c::c016",
"2001:ac8:25:3c::c017",
"2001:ac8:25:3c::c018",
"2001:ac8:25:3c::c019",
"2001:ac8:25:3c::c01a",
"2001:ac8:25:3c::c01b",
"2001:ac8:25:3c::c01c",
"2001:ac8:25:3c::c01d",
"2001:ac8:25:3c::c01e",
"2001:ac8:25:3c::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "fr-par-wg-103.blockerad.eu"
}
}
},
{
"hostname": "fr-par-wg-301",
"location": "fr-par",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "95.173.222.2",
"include_in_country": true,
"weight": 100,
"public_key": "gCYpOei4ZYsWJ3mOgCdQo6bnsRgdLNJR9SWEA69U7Gw=",
"ipv6_addr_in": "2a02:6ea0:1901:2::f001",
"shadowsocks_extra_addr_in": [
"95.173.222.5"
]
},
{
"hostname": "fr-par-wg-302",
"location": "fr-par",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "95.173.222.31",
"include_in_country": true,
"weight": 100,
"public_key": "CpbLl0WVeiW+YbJKNod5khzAI03D2hX2dhq2CCYc2Xc=",
"ipv6_addr_in": "2a02:6ea0:1901:3::f001",
"shadowsocks_extra_addr_in": [
"95.173.222.33"
]
},
{
"hostname": "gb-glw-wg-001",
"location": "gb-glw",
"active": true,
"owned": false,
"provider": "HostRoyale",
"stboot": true,
"ipv4_addr_in": "185.201.188.3",
"include_in_country": false,
"weight": 100,
"public_key": "xCPSxGj0QVKC637D8HpRsUUCaSfgAF4ephG/CjhQ2kU=",
"ipv6_addr_in": "2a06:3040:d:410::f001",
"features": {
"lwo": {}
}
},
{
"hostname": "gb-glw-wg-002",
"location": "gb-glw",
"active": true,
"owned": false,
"provider": "HostRoyale",
"stboot": true,
"ipv4_addr_in": "185.201.188.33",
"include_in_country": false,
"weight": 100,
"public_key": "tX+LKwiFvZhGtbuJq8e62+/vhogHNqdAdjHeoOlWqws=",
"ipv6_addr_in": "2a06:3040:d:410::f101"
},
{
"hostname": "gb-lon-wg-001",
"location": "gb-lon",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "141.98.252.130",
"include_in_country": true,
"weight": 100,
"public_key": "IJJe0TQtuQOyemL4IZn6oHEsMKSPqOuLfD5HoAWEPTY=",
"ipv6_addr_in": "2a03:1b20:7:f011::a01f",
"shadowsocks_extra_addr_in": [
"185.195.232.98",
"2a03:1b20:7:f011::b001",
"2a03:1b20:7:f011::b002",
"2a03:1b20:7:f011::b003",
"2a03:1b20:7:f011::b004",
"2a03:1b20:7:f011::b005",
"2a03:1b20:7:f011::b006",
"2a03:1b20:7:f011::b007",
"2a03:1b20:7:f011::b008",
"2a03:1b20:7:f011::b009",
"2a03:1b20:7:f011::b00a",
"2a03:1b20:7:f011::b00b",
"2a03:1b20:7:f011::b00c",
"2a03:1b20:7:f011::b00d",
"2a03:1b20:7:f011::b00e",
"2a03:1b20:7:f011::b00f",
"2a03:1b20:7:f011::b010",
"2a03:1b20:7:f011::b011",
"2a03:1b20:7:f011::b012",
"2a03:1b20:7:f011::b013",
"2a03:1b20:7:f011::b014",
"2a03:1b20:7:f011::b015",
"2a03:1b20:7:f011::b016",
"2a03:1b20:7:f011::b017",
"2a03:1b20:7:f011::b018",
"2a03:1b20:7:f011::b019",
"2a03:1b20:7:f011::b01a",
"2a03:1b20:7:f011::b01b",
"2a03:1b20:7:f011::b01c",
"2a03:1b20:7:f011::b01d",
"2a03:1b20:7:f011::b01e",
"2a03:1b20:7:f011::b01f"
],
"features": {
"quic": {
"addr_in": [
"185.195.232.99",
"185.195.232.95",
"185.195.232.96",
"185.195.232.97",
"2a03:1b20:7:f011::c001",
"2a03:1b20:7:f011::c002",
"2a03:1b20:7:f011::c003",
"2a03:1b20:7:f011::c004",
"2a03:1b20:7:f011::c005",
"2a03:1b20:7:f011::c006",
"2a03:1b20:7:f011::c007",
"2a03:1b20:7:f011::c008",
"2a03:1b20:7:f011::c009",
"2a03:1b20:7:f011::c00a",
"2a03:1b20:7:f011::c00b",
"2a03:1b20:7:f011::c00c",
"2a03:1b20:7:f011::c00d",
"2a03:1b20:7:f011::c00e",
"2a03:1b20:7:f011::c00f",
"2a03:1b20:7:f011::c010",
"2a03:1b20:7:f011::c011",
"2a03:1b20:7:f011::c012",
"2a03:1b20:7:f011::c013",
"2a03:1b20:7:f011::c014",
"2a03:1b20:7:f011::c015",
"2a03:1b20:7:f011::c016",
"2a03:1b20:7:f011::c017",
"2a03:1b20:7:f011::c018",
"2a03:1b20:7:f011::c019",
"2a03:1b20:7:f011::c01a",
"2a03:1b20:7:f011::c01b",
"2a03:1b20:7:f011::c01c",
"2a03:1b20:7:f011::c01d",
"2a03:1b20:7:f011::c01e",
"2a03:1b20:7:f011::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "gb-lon-wg-001.blockerad.eu"
}
}
},
{
"hostname": "gb-lon-wg-002",
"location": "gb-lon",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "141.98.252.222",
"include_in_country": true,
"weight": 1,
"public_key": "J57ba81Q8bigy9RXBXvl0DgABTrbl81nb37GuX50gnY=",
"ipv6_addr_in": "2a03:1b20:7:f011::a02f",
"shadowsocks_extra_addr_in": [
"2a03:1b20:7:f011::b101",
"2a03:1b20:7:f011::b102",
"2a03:1b20:7:f011::b103",
"2a03:1b20:7:f011::b104",
"2a03:1b20:7:f011::b105",
"2a03:1b20:7:f011::b106",
"2a03:1b20:7:f011::b107",
"2a03:1b20:7:f011::b108",
"2a03:1b20:7:f011::b109",
"2a03:1b20:7:f011::b10a",
"2a03:1b20:7:f011::b10b",
"2a03:1b20:7:f011::b10c",
"2a03:1b20:7:f011::b10d",
"2a03:1b20:7:f011::b10e",
"2a03:1b20:7:f011::b10f",
"2a03:1b20:7:f011::b110",
"2a03:1b20:7:f011::b111",
"2a03:1b20:7:f011::b112",
"2a03:1b20:7:f011::b113",
"2a03:1b20:7:f011::b114",
"2a03:1b20:7:f011::b115",
"2a03:1b20:7:f011::b116",
"2a03:1b20:7:f011::b117",
"2a03:1b20:7:f011::b118",
"2a03:1b20:7:f011::b119",
"2a03:1b20:7:f011::b11a",
"2a03:1b20:7:f011::b11b",
"2a03:1b20:7:f011::b11c",
"2a03:1b20:7:f011::b11d",
"2a03:1b20:7:f011::b11e",
"2a03:1b20:7:f011::b11f"
]
},
{
"hostname": "gb-lon-wg-003",
"location": "gb-lon",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "185.195.232.66",
"include_in_country": true,
"weight": 100,
"public_key": "VZwE8hrpNzg6SMwn9LtEqonXzSWd5dkFk62PrNWFW3Y=",
"ipv6_addr_in": "2a03:1b20:7:f011::a11f",
"shadowsocks_extra_addr_in": [
"2a03:1b20:7:f011::b201",
"2a03:1b20:7:f011::b202",
"2a03:1b20:7:f011::b203",
"2a03:1b20:7:f011::b204",
"2a03:1b20:7:f011::b205",
"2a03:1b20:7:f011::b206",
"2a03:1b20:7:f011::b207",
"2a03:1b20:7:f011::b208",
"2a03:1b20:7:f011::b209",
"2a03:1b20:7:f011::b20a",
"2a03:1b20:7:f011::b20b",
"2a03:1b20:7:f011::b20c",
"2a03:1b20:7:f011::b20d",
"2a03:1b20:7:f011::b20e",
"2a03:1b20:7:f011::b20f",
"2a03:1b20:7:f011::b210",
"2a03:1b20:7:f011::b211",
"2a03:1b20:7:f011::b212",
"2a03:1b20:7:f011::b213",
"2a03:1b20:7:f011::b214",
"2a03:1b20:7:f011::b215",
"2a03:1b20:7:f011::b216",
"2a03:1b20:7:f011::b217",
"2a03:1b20:7:f011::b218",
"2a03:1b20:7:f011::b219",
"2a03:1b20:7:f011::b21a",
"2a03:1b20:7:f011::b21b",
"2a03:1b20:7:f011::b21c",
"2a03:1b20:7:f011::b21d",
"2a03:1b20:7:f011::b21e",
"2a03:1b20:7:f011::b21f"
]
},
{
"hostname": "gb-lon-wg-004",
"location": "gb-lon",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "185.195.232.67",
"include_in_country": true,
"weight": 100,
"public_key": "PLpO9ikFX1garSFaeUpo7XVSMrILrTB8D9ZwQt6Zgwk=",
"ipv6_addr_in": "2a03:1b20:7:f011::a12f",
"shadowsocks_extra_addr_in": [
"2a03:1b20:7:f011::b301",
"2a03:1b20:7:f011::b302",
"2a03:1b20:7:f011::b303",
"2a03:1b20:7:f011::b304",
"2a03:1b20:7:f011::b305",
"2a03:1b20:7:f011::b306",
"2a03:1b20:7:f011::b307",
"2a03:1b20:7:f011::b308",
"2a03:1b20:7:f011::b309",
"2a03:1b20:7:f011::b30a",
"2a03:1b20:7:f011::b30b",
"2a03:1b20:7:f011::b30c",
"2a03:1b20:7:f011::b30d",
"2a03:1b20:7:f011::b30e",
"2a03:1b20:7:f011::b30f",
"2a03:1b20:7:f011::b310",
"2a03:1b20:7:f011::b311",
"2a03:1b20:7:f011::b312",
"2a03:1b20:7:f011::b313",
"2a03:1b20:7:f011::b314",
"2a03:1b20:7:f011::b315",
"2a03:1b20:7:f011::b316",
"2a03:1b20:7:f011::b317",
"2a03:1b20:7:f011::b318",
"2a03:1b20:7:f011::b319",
"2a03:1b20:7:f011::b31a",
"2a03:1b20:7:f011::b31b",
"2a03:1b20:7:f011::b31c",
"2a03:1b20:7:f011::b31d",
"2a03:1b20:7:f011::b31e",
"2a03:1b20:7:f011::b31f"
]
},
{
"hostname": "gb-lon-wg-005",
"location": "gb-lon",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "185.195.232.68",
"include_in_country": true,
"weight": 100,
"public_key": "bG6WulLmMK408n719B8nQJNuTRyRA3Qjm7bsm9d6v2M=",
"ipv6_addr_in": "2a03:1b20:7:f011::a13f",
"shadowsocks_extra_addr_in": [
"2a03:1b20:7:f011::b401",
"2a03:1b20:7:f011::b402",
"2a03:1b20:7:f011::b403",
"2a03:1b20:7:f011::b404",
"2a03:1b20:7:f011::b405",
"2a03:1b20:7:f011::b406",
"2a03:1b20:7:f011::b407",
"2a03:1b20:7:f011::b408",
"2a03:1b20:7:f011::b409",
"2a03:1b20:7:f011::b40a",
"2a03:1b20:7:f011::b40b",
"2a03:1b20:7:f011::b40c",
"2a03:1b20:7:f011::b40d",
"2a03:1b20:7:f011::b40e",
"2a03:1b20:7:f011::b40f",
"2a03:1b20:7:f011::b410",
"2a03:1b20:7:f011::b411",
"2a03:1b20:7:f011::b412",
"2a03:1b20:7:f011::b413",
"2a03:1b20:7:f011::b414",
"2a03:1b20:7:f011::b415",
"2a03:1b20:7:f011::b416",
"2a03:1b20:7:f011::b417",
"2a03:1b20:7:f011::b418",
"2a03:1b20:7:f011::b419",
"2a03:1b20:7:f011::b41a",
"2a03:1b20:7:f011::b41b",
"2a03:1b20:7:f011::b41c",
"2a03:1b20:7:f011::b41d",
"2a03:1b20:7:f011::b41e",
"2a03:1b20:7:f011::b41f"
]
},
{
"hostname": "gb-lon-wg-006",
"location": "gb-lon",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "185.195.232.69",
"include_in_country": true,
"weight": 100,
"public_key": "INRhM0h4T1hi9j28pcC+vRv47bp7DIsNKtagaFZFSBI=",
"ipv6_addr_in": "2a03:1b20:7:f011::a14f",
"shadowsocks_extra_addr_in": [
"2a03:1b20:7:f011::b501",
"2a03:1b20:7:f011::b502",
"2a03:1b20:7:f011::b503",
"2a03:1b20:7:f011::b504",
"2a03:1b20:7:f011::b505",
"2a03:1b20:7:f011::b506",
"2a03:1b20:7:f011::b507",
"2a03:1b20:7:f011::b508",
"2a03:1b20:7:f011::b509",
"2a03:1b20:7:f011::b50a",
"2a03:1b20:7:f011::b50b",
"2a03:1b20:7:f011::b50c",
"2a03:1b20:7:f011::b50d",
"2a03:1b20:7:f011::b50e",
"2a03:1b20:7:f011::b50f",
"2a03:1b20:7:f011::b510",
"2a03:1b20:7:f011::b511",
"2a03:1b20:7:f011::b512",
"2a03:1b20:7:f011::b513",
"2a03:1b20:7:f011::b514",
"2a03:1b20:7:f011::b515",
"2a03:1b20:7:f011::b516",
"2a03:1b20:7:f011::b517",
"2a03:1b20:7:f011::b518",
"2a03:1b20:7:f011::b519",
"2a03:1b20:7:f011::b51a",
"2a03:1b20:7:f011::b51b",
"2a03:1b20:7:f011::b51c",
"2a03:1b20:7:f011::b51d",
"2a03:1b20:7:f011::b51e",
"2a03:1b20:7:f011::b51f"
]
},
{
"hostname": "gb-lon-wg-007",
"location": "gb-lon",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "185.195.232.70",
"include_in_country": true,
"weight": 100,
"public_key": "MVqe9e9aDwfFuvEhEn4Wd/zWV3cmiCX9fZMWetz+23A=",
"ipv6_addr_in": "2a03:1b20:7:f011::a15f",
"shadowsocks_extra_addr_in": [
"2a03:1b20:7:f011::b601",
"2a03:1b20:7:f011::b602",
"2a03:1b20:7:f011::b603",
"2a03:1b20:7:f011::b604",
"2a03:1b20:7:f011::b605",
"2a03:1b20:7:f011::b606",
"2a03:1b20:7:f011::b607",
"2a03:1b20:7:f011::b608",
"2a03:1b20:7:f011::b609",
"2a03:1b20:7:f011::b60a",
"2a03:1b20:7:f011::b60b",
"2a03:1b20:7:f011::b60c",
"2a03:1b20:7:f011::b60d",
"2a03:1b20:7:f011::b60e",
"2a03:1b20:7:f011::b60f",
"2a03:1b20:7:f011::b610",
"2a03:1b20:7:f011::b611",
"2a03:1b20:7:f011::b612",
"2a03:1b20:7:f011::b613",
"2a03:1b20:7:f011::b614",
"2a03:1b20:7:f011::b615",
"2a03:1b20:7:f011::b616",
"2a03:1b20:7:f011::b617",
"2a03:1b20:7:f011::b618",
"2a03:1b20:7:f011::b619",
"2a03:1b20:7:f011::b61a",
"2a03:1b20:7:f011::b61b",
"2a03:1b20:7:f011::b61c",
"2a03:1b20:7:f011::b61d",
"2a03:1b20:7:f011::b61e",
"2a03:1b20:7:f011::b61f"
]
},
{
"hostname": "gb-lon-wg-008",
"location": "gb-lon",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "141.98.252.138",
"include_in_country": true,
"weight": 1,
"public_key": "uHkxYjfx6yzPHSdyqYqSEHsgFNFV8QCSV6aghuQK3AA=",
"ipv6_addr_in": "2a03:1b20:7:f011::f801",
"daita": true,
"shadowsocks_extra_addr_in": [
"2a03:1b20:7:f011::c801",
"2a03:1b20:7:f011::c802",
"2a03:1b20:7:f011::c803",
"2a03:1b20:7:f011::c804",
"2a03:1b20:7:f011::c805",
"2a03:1b20:7:f011::c806",
"2a03:1b20:7:f011::c807",
"2a03:1b20:7:f011::c808",
"2a03:1b20:7:f011::c809",
"2a03:1b20:7:f011::c80a",
"2a03:1b20:7:f011::c80b",
"2a03:1b20:7:f011::c80c",
"2a03:1b20:7:f011::c80d",
"2a03:1b20:7:f011::c80e",
"2a03:1b20:7:f011::c80f",
"2a03:1b20:7:f011::c810",
"2a03:1b20:7:f011::c811",
"2a03:1b20:7:f011::c812",
"2a03:1b20:7:f011::c813",
"2a03:1b20:7:f011::c814",
"2a03:1b20:7:f011::c815",
"2a03:1b20:7:f011::c816",
"2a03:1b20:7:f011::c817",
"2a03:1b20:7:f011::c818",
"2a03:1b20:7:f011::c819",
"2a03:1b20:7:f011::c81a",
"2a03:1b20:7:f011::c81b",
"2a03:1b20:7:f011::c81c",
"2a03:1b20:7:f011::c81d",
"2a03:1b20:7:f011::c81e",
"2a03:1b20:7:f011::c81f"
],
"features": {
"daita": {}
}
},
{
"hostname": "gb-lon-wg-201",
"location": "gb-lon",
"active": true,
"owned": false,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "185.248.85.3",
"include_in_country": true,
"weight": 100,
"public_key": "b71Y8V/vVwNRGkL4d1zvApDVL18u7m31dN+x+i5OJVs=",
"ipv6_addr_in": "2a0b:89c1:3::a33f"
},
{
"hostname": "gb-lon-wg-202",
"location": "gb-lon",
"active": true,
"owned": false,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "185.248.85.18",
"include_in_country": true,
"weight": 100,
"public_key": "+iQWuT3wb2DCy1u2eUKovhJTCB4aUdJUnpxGtONDIVE=",
"ipv6_addr_in": "2a0b:89c1:3::a34f"
},
{
"hostname": "gb-lon-wg-203",
"location": "gb-lon",
"active": true,
"owned": false,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "185.248.85.33",
"include_in_country": true,
"weight": 100,
"public_key": "G7XDQqevQOw1SVL7Iarn9PM+RvmI6H/CfkmahBYEG0g=",
"ipv6_addr_in": "2a0b:89c1:3::a35f"
},
{
"hostname": "gb-lon-wg-204",
"location": "gb-lon",
"active": true,
"owned": false,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "185.248.85.48",
"include_in_country": true,
"weight": 100,
"public_key": "tJVHqpfkV2Xgmd4YK60aoErSt6PmJKJjkggHNDfWwiU=",
"ipv6_addr_in": "2a0b:89c1:3::a36f",
"features": {
"lwo": {}
}
},
{
"hostname": "gb-lon-wg-305",
"location": "gb-lon",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.119.2",
"include_in_country": true,
"weight": 100,
"public_key": "QCmRXGF/4sefzm5bdfXEcN/fYQGrb+F6HbOzI/FK4hU=",
"ipv6_addr_in": "2a04:9dc0:18:70::f001",
"shadowsocks_extra_addr_in": [
"146.70.119.13",
"146.70.119.14",
"146.70.119.15",
"146.70.119.16",
"146.70.119.17",
"146.70.119.18",
"146.70.119.19",
"146.70.119.20",
"146.70.119.21",
"146.70.119.22",
"2a04:9dc0:18:70::b002",
"2a04:9dc0:18:70::b003",
"2a04:9dc0:18:70::b004",
"2a04:9dc0:18:70::b005",
"2a04:9dc0:18:70::b006",
"2a04:9dc0:18:70::b007",
"2a04:9dc0:18:70::b008",
"2a04:9dc0:18:70::b009",
"2a04:9dc0:18:70::b00a",
"2a04:9dc0:18:70::b00b",
"2a04:9dc0:18:70::b00c",
"2a04:9dc0:18:70::b00d",
"2a04:9dc0:18:70::b00e",
"2a04:9dc0:18:70::b00f",
"2a04:9dc0:18:70::b010",
"2a04:9dc0:18:70::b011",
"2a04:9dc0:18:70::b012",
"2a04:9dc0:18:70::b013",
"2a04:9dc0:18:70::b014",
"2a04:9dc0:18:70::b015",
"2a04:9dc0:18:70::b016",
"2a04:9dc0:18:70::b017",
"2a04:9dc0:18:70::b018",
"2a04:9dc0:18:70::b019",
"2a04:9dc0:18:70::b01a",
"2a04:9dc0:18:70::b01b",
"2a04:9dc0:18:70::b01c",
"2a04:9dc0:18:70::b01d",
"2a04:9dc0:18:70::b01e",
"2a04:9dc0:18:70::b01f"
],
"features": {
"quic": {
"addr_in": [
"146.70.119.23",
"146.70.119.24",
"146.70.119.25",
"146.70.119.26",
"146.70.119.27",
"146.70.119.28",
"146.70.119.29",
"146.70.119.30",
"146.70.119.31",
"146.70.119.32",
"2a04:9dc0:18:70::c002",
"2a04:9dc0:18:70::c003",
"2a04:9dc0:18:70::c004",
"2a04:9dc0:18:70::c005",
"2a04:9dc0:18:70::c006",
"2a04:9dc0:18:70::c007",
"2a04:9dc0:18:70::c008",
"2a04:9dc0:18:70::c009",
"2a04:9dc0:18:70::c00a",
"2a04:9dc0:18:70::c00b",
"2a04:9dc0:18:70::c00c",
"2a04:9dc0:18:70::c00d",
"2a04:9dc0:18:70::c00e",
"2a04:9dc0:18:70::c00f",
"2a04:9dc0:18:70::c010",
"2a04:9dc0:18:70::c011",
"2a04:9dc0:18:70::c012",
"2a04:9dc0:18:70::c013",
"2a04:9dc0:18:70::c014",
"2a04:9dc0:18:70::c015",
"2a04:9dc0:18:70::c016",
"2a04:9dc0:18:70::c017",
"2a04:9dc0:18:70::c018",
"2a04:9dc0:18:70::c019",
"2a04:9dc0:18:70::c01a",
"2a04:9dc0:18:70::c01b",
"2a04:9dc0:18:70::c01c",
"2a04:9dc0:18:70::c01d",
"2a04:9dc0:18:70::c01e",
"2a04:9dc0:18:70::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "gb-lon-wg-305.blockerad.eu"
}
}
},
{
"hostname": "gb-lon-wg-306",
"location": "gb-lon",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.119.130",
"include_in_country": true,
"weight": 100,
"public_key": "zTM3WRyxGSqh+ZMUBXDynlyOWYkSG/J/eTFb8boDAkw=",
"ipv6_addr_in": "2a04:9dc0:18:71::f001",
"shadowsocks_extra_addr_in": [
"146.70.119.151",
"146.70.119.152",
"146.70.119.153",
"146.70.119.154",
"146.70.119.155",
"146.70.119.156",
"146.70.119.157",
"146.70.119.158",
"146.70.119.159",
"146.70.119.160",
"146.70.119.161",
"146.70.119.162",
"146.70.119.163",
"146.70.119.164",
"146.70.119.165",
"146.70.119.166",
"146.70.119.167",
"146.70.119.168",
"146.70.119.169",
"146.70.119.170",
"2a04:9dc0:18:71::b002",
"2a04:9dc0:18:71::b003",
"2a04:9dc0:18:71::b004",
"2a04:9dc0:18:71::b005",
"2a04:9dc0:18:71::b006",
"2a04:9dc0:18:71::b007",
"2a04:9dc0:18:71::b008",
"2a04:9dc0:18:71::b009",
"2a04:9dc0:18:71::b00a",
"2a04:9dc0:18:71::b00b",
"2a04:9dc0:18:71::b00c",
"2a04:9dc0:18:71::b00d",
"2a04:9dc0:18:71::b00e",
"2a04:9dc0:18:71::b00f",
"2a04:9dc0:18:71::b010",
"2a04:9dc0:18:71::b011",
"2a04:9dc0:18:71::b012",
"2a04:9dc0:18:71::b013",
"2a04:9dc0:18:71::b014",
"2a04:9dc0:18:71::b015",
"2a04:9dc0:18:71::b016",
"2a04:9dc0:18:71::b017",
"2a04:9dc0:18:71::b018",
"2a04:9dc0:18:71::b019",
"2a04:9dc0:18:71::b01a",
"2a04:9dc0:18:71::b01b",
"2a04:9dc0:18:71::b01c",
"2a04:9dc0:18:71::b01d",
"2a04:9dc0:18:71::b01e",
"2a04:9dc0:18:71::b01f"
],
"features": {
"quic": {
"addr_in": [
"146.70.119.171",
"146.70.119.172",
"146.70.119.173",
"146.70.119.174",
"146.70.119.175",
"146.70.119.176",
"146.70.119.177",
"146.70.119.178",
"146.70.119.179",
"146.70.119.180",
"146.70.119.181",
"146.70.119.182",
"146.70.119.183",
"146.70.119.184",
"146.70.119.185",
"146.70.119.186",
"146.70.119.187",
"146.70.119.188",
"146.70.119.189",
"146.70.119.190",
"2a04:9dc0:18:71::c002",
"2a04:9dc0:18:71::c003",
"2a04:9dc0:18:71::c004",
"2a04:9dc0:18:71::c005",
"2a04:9dc0:18:71::c006",
"2a04:9dc0:18:71::c007",
"2a04:9dc0:18:71::c008",
"2a04:9dc0:18:71::c009",
"2a04:9dc0:18:71::c00a",
"2a04:9dc0:18:71::c00b",
"2a04:9dc0:18:71::c00c",
"2a04:9dc0:18:71::c00d",
"2a04:9dc0:18:71::c00e",
"2a04:9dc0:18:71::c00f",
"2a04:9dc0:18:71::c010",
"2a04:9dc0:18:71::c011",
"2a04:9dc0:18:71::c012",
"2a04:9dc0:18:71::c013",
"2a04:9dc0:18:71::c014",
"2a04:9dc0:18:71::c015",
"2a04:9dc0:18:71::c016",
"2a04:9dc0:18:71::c017",
"2a04:9dc0:18:71::c018",
"2a04:9dc0:18:71::c019",
"2a04:9dc0:18:71::c01a",
"2a04:9dc0:18:71::c01b",
"2a04:9dc0:18:71::c01c",
"2a04:9dc0:18:71::c01d",
"2a04:9dc0:18:71::c01e",
"2a04:9dc0:18:71::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "gb-lon-wg-306.blockerad.eu"
}
}
},
{
"hostname": "gb-lon-wg-308",
"location": "gb-lon",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "135.136.58.130",
"include_in_country": true,
"weight": 100,
"public_key": "Piwplz/ROMLZqL/GEeH3//jcMYQ5oatOeWcKZOi0Nyk=",
"ipv6_addr_in": "2a04:9dc0:18:73::f001",
"shadowsocks_extra_addr_in": [
"135.136.58.141",
"135.136.58.142",
"135.136.58.143",
"135.136.58.144",
"135.136.58.145",
"135.136.58.146",
"135.136.58.147",
"135.136.58.148",
"135.136.58.149",
"135.136.58.150",
"2a04:9dc0:18:73::b002",
"2a04:9dc0:18:73::b003",
"2a04:9dc0:18:73::b004",
"2a04:9dc0:18:73::b005",
"2a04:9dc0:18:73::b006",
"2a04:9dc0:18:73::b007",
"2a04:9dc0:18:73::b008",
"2a04:9dc0:18:73::b009",
"2a04:9dc0:18:73::b00a",
"2a04:9dc0:18:73::b00b",
"2a04:9dc0:18:73::b00c",
"2a04:9dc0:18:73::b00d",
"2a04:9dc0:18:73::b00e",
"2a04:9dc0:18:73::b00f",
"2a04:9dc0:18:73::b010",
"2a04:9dc0:18:73::b011",
"2a04:9dc0:18:73::b012",
"2a04:9dc0:18:73::b013",
"2a04:9dc0:18:73::b014",
"2a04:9dc0:18:73::b015",
"2a04:9dc0:18:73::b016",
"2a04:9dc0:18:73::b017",
"2a04:9dc0:18:73::b018",
"2a04:9dc0:18:73::b019",
"2a04:9dc0:18:73::b01a",
"2a04:9dc0:18:73::b01b",
"2a04:9dc0:18:73::b01c",
"2a04:9dc0:18:73::b01d",
"2a04:9dc0:18:73::b01e",
"2a04:9dc0:18:73::b01f"
],
"features": {
"quic": {
"addr_in": [
"135.136.58.151",
"135.136.58.152",
"135.136.58.153",
"135.136.58.154",
"135.136.58.155",
"135.136.58.156",
"135.136.58.157",
"135.136.58.158",
"135.136.58.159",
"135.136.58.160",
"2a04:9dc0:18:73::c002",
"2a04:9dc0:18:73::c003",
"2a04:9dc0:18:73::c004",
"2a04:9dc0:18:73::c005",
"2a04:9dc0:18:73::c006",
"2a04:9dc0:18:73::c007",
"2a04:9dc0:18:73::c008",
"2a04:9dc0:18:73::c009",
"2a04:9dc0:18:73::c00a",
"2a04:9dc0:18:73::c00b",
"2a04:9dc0:18:73::c00c",
"2a04:9dc0:18:73::c00d",
"2a04:9dc0:18:73::c00e",
"2a04:9dc0:18:73::c00f",
"2a04:9dc0:18:73::c010",
"2a04:9dc0:18:73::c011",
"2a04:9dc0:18:73::c012",
"2a04:9dc0:18:73::c013",
"2a04:9dc0:18:73::c014",
"2a04:9dc0:18:73::c015",
"2a04:9dc0:18:73::c016",
"2a04:9dc0:18:73::c017",
"2a04:9dc0:18:73::c018",
"2a04:9dc0:18:73::c019",
"2a04:9dc0:18:73::c01a",
"2a04:9dc0:18:73::c01b",
"2a04:9dc0:18:73::c01c",
"2a04:9dc0:18:73::c01d",
"2a04:9dc0:18:73::c01e",
"2a04:9dc0:18:73::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "gb-lon-wg-308.blockerad.eu"
}
}
},
{
"hostname": "gb-mnc-wg-001",
"location": "gb-mnc",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.132.2",
"include_in_country": false,
"weight": 200,
"public_key": "Q2khJLbTSFxmppPGHgq2HdxMQx7CczPZCgVpYZMoNnM=",
"ipv6_addr_in": "2001:ac8:8b:104::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"146.70.132.16",
"146.70.132.17",
"146.70.132.18",
"146.70.132.19",
"146.70.132.20",
"146.70.132.21",
"146.70.132.22",
"146.70.132.23",
"146.70.132.24",
"146.70.132.25",
"146.70.132.26",
"2001:ac8:8b:104::b001",
"2001:ac8:8b:104::b002",
"2001:ac8:8b:104::b003",
"2001:ac8:8b:104::b004",
"2001:ac8:8b:104::b005",
"2001:ac8:8b:104::b006",
"2001:ac8:8b:104::b007",
"2001:ac8:8b:104::b008",
"2001:ac8:8b:104::b009",
"2001:ac8:8b:104::b00a",
"2001:ac8:8b:104::b00b",
"2001:ac8:8b:104::b00c",
"2001:ac8:8b:104::b00d",
"2001:ac8:8b:104::b00e",
"2001:ac8:8b:104::b00f",
"2001:ac8:8b:104::b010",
"2001:ac8:8b:104::b011",
"2001:ac8:8b:104::b012",
"2001:ac8:8b:104::b013",
"2001:ac8:8b:104::b014",
"2001:ac8:8b:104::b015",
"2001:ac8:8b:104::b016",
"2001:ac8:8b:104::b017",
"2001:ac8:8b:104::b018",
"2001:ac8:8b:104::b019",
"2001:ac8:8b:104::b01a",
"2001:ac8:8b:104::b01b",
"2001:ac8:8b:104::b01c",
"2001:ac8:8b:104::b01d",
"2001:ac8:8b:104::b01e",
"2001:ac8:8b:104::b01f"
],
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"146.70.132.5",
"146.70.132.6",
"146.70.132.7",
"146.70.132.8",
"146.70.132.9",
"146.70.132.10",
"146.70.132.11",
"146.70.132.12",
"146.70.132.13",
"146.70.132.14",
"146.70.132.15",
"2001:ac8:8b:104::c001",
"2001:ac8:8b:104::c002",
"2001:ac8:8b:104::c003",
"2001:ac8:8b:104::c004",
"2001:ac8:8b:104::c005",
"2001:ac8:8b:104::c006",
"2001:ac8:8b:104::c007",
"2001:ac8:8b:104::c008",
"2001:ac8:8b:104::c009",
"2001:ac8:8b:104::c00a",
"2001:ac8:8b:104::c00b",
"2001:ac8:8b:104::c00c",
"2001:ac8:8b:104::c00d",
"2001:ac8:8b:104::c00e",
"2001:ac8:8b:104::c00f",
"2001:ac8:8b:104::c010",
"2001:ac8:8b:104::c011",
"2001:ac8:8b:104::c012",
"2001:ac8:8b:104::c013",
"2001:ac8:8b:104::c014",
"2001:ac8:8b:104::c015",
"2001:ac8:8b:104::c016",
"2001:ac8:8b:104::c017",
"2001:ac8:8b:104::c018",
"2001:ac8:8b:104::c019",
"2001:ac8:8b:104::c01a",
"2001:ac8:8b:104::c01b",
"2001:ac8:8b:104::c01c",
"2001:ac8:8b:104::c01d",
"2001:ac8:8b:104::c01e",
"2001:ac8:8b:104::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "gb-mnc-wg-001.blockerad.eu"
}
}
},
{
"hostname": "gb-mnc-wg-002",
"location": "gb-mnc",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "135.136.22.2",
"include_in_country": false,
"weight": 200,
"public_key": "1yWXDkKtU7NQU1349DS/nvGr0XjQgsZFhRt2P+fVtTg=",
"ipv6_addr_in": "2001:ac8:8b:105::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"135.136.22.16",
"135.136.22.17",
"135.136.22.18",
"135.136.22.19",
"135.136.22.20",
"135.136.22.21",
"135.136.22.22",
"135.136.22.23",
"135.136.22.24",
"135.136.22.25",
"135.136.22.26",
"2001:ac8:8b:105::b001",
"2001:ac8:8b:105::b002",
"2001:ac8:8b:105::b003",
"2001:ac8:8b:105::b004",
"2001:ac8:8b:105::b005",
"2001:ac8:8b:105::b006",
"2001:ac8:8b:105::b007",
"2001:ac8:8b:105::b008",
"2001:ac8:8b:105::b009",
"2001:ac8:8b:105::b00a",
"2001:ac8:8b:105::b00b",
"2001:ac8:8b:105::b00c",
"2001:ac8:8b:105::b00d",
"2001:ac8:8b:105::b00e",
"2001:ac8:8b:105::b00f",
"2001:ac8:8b:105::b010",
"2001:ac8:8b:105::b011",
"2001:ac8:8b:105::b012",
"2001:ac8:8b:105::b013",
"2001:ac8:8b:105::b014",
"2001:ac8:8b:105::b015",
"2001:ac8:8b:105::b016",
"2001:ac8:8b:105::b017",
"2001:ac8:8b:105::b018",
"2001:ac8:8b:105::b019",
"2001:ac8:8b:105::b01a",
"2001:ac8:8b:105::b01b",
"2001:ac8:8b:105::b01c",
"2001:ac8:8b:105::b01d",
"2001:ac8:8b:105::b01e",
"2001:ac8:8b:105::b01f"
],
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"135.136.22.5",
"135.136.22.6",
"135.136.22.7",
"135.136.22.8",
"135.136.22.9",
"135.136.22.10",
"135.136.22.11",
"135.136.22.12",
"135.136.22.13",
"135.136.22.14",
"135.136.22.15",
"2001:ac8:8b:105::c001",
"2001:ac8:8b:105::c002",
"2001:ac8:8b:105::c003",
"2001:ac8:8b:105::c004",
"2001:ac8:8b:105::c005",
"2001:ac8:8b:105::c006",
"2001:ac8:8b:105::c007",
"2001:ac8:8b:105::c008",
"2001:ac8:8b:105::c009",
"2001:ac8:8b:105::c00a",
"2001:ac8:8b:105::c00b",
"2001:ac8:8b:105::c00c",
"2001:ac8:8b:105::c00d",
"2001:ac8:8b:105::c00e",
"2001:ac8:8b:105::c00f",
"2001:ac8:8b:105::c010",
"2001:ac8:8b:105::c011",
"2001:ac8:8b:105::c012",
"2001:ac8:8b:105::c013",
"2001:ac8:8b:105::c014",
"2001:ac8:8b:105::c015",
"2001:ac8:8b:105::c016",
"2001:ac8:8b:105::c017",
"2001:ac8:8b:105::c018",
"2001:ac8:8b:105::c019",
"2001:ac8:8b:105::c01a",
"2001:ac8:8b:105::c01b",
"2001:ac8:8b:105::c01c",
"2001:ac8:8b:105::c01d",
"2001:ac8:8b:105::c01e",
"2001:ac8:8b:105::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "gb-mnc-wg-002.blockerad.eu"
}
}
},
{
"hostname": "gb-mnc-wg-003",
"location": "gb-mnc",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "135.136.22.130",
"include_in_country": true,
"weight": 100,
"public_key": "3pCAP2xIdWn3O83V9tzuF0W5fmLkhFO+od0VsU3Kiy0=",
"ipv6_addr_in": "2001:ac8:8b:106::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"135.136.22.144",
"135.136.22.145",
"135.136.22.146",
"135.136.22.147",
"135.136.22.148",
"135.136.22.149",
"135.136.22.150",
"135.136.22.151",
"135.136.22.152",
"135.136.22.153",
"135.136.22.154",
"2001:ac8:8b:106::b001",
"2001:ac8:8b:106::b002",
"2001:ac8:8b:106::b003",
"2001:ac8:8b:106::b004",
"2001:ac8:8b:106::b005",
"2001:ac8:8b:106::b006",
"2001:ac8:8b:106::b007",
"2001:ac8:8b:106::b008",
"2001:ac8:8b:106::b009",
"2001:ac8:8b:106::b00a",
"2001:ac8:8b:106::b00b",
"2001:ac8:8b:106::b00c",
"2001:ac8:8b:106::b00d",
"2001:ac8:8b:106::b00e",
"2001:ac8:8b:106::b00f",
"2001:ac8:8b:106::b010",
"2001:ac8:8b:106::b011",
"2001:ac8:8b:106::b012",
"2001:ac8:8b:106::b013",
"2001:ac8:8b:106::b014",
"2001:ac8:8b:106::b015",
"2001:ac8:8b:106::b016",
"2001:ac8:8b:106::b017",
"2001:ac8:8b:106::b018",
"2001:ac8:8b:106::b019",
"2001:ac8:8b:106::b01a",
"2001:ac8:8b:106::b01b",
"2001:ac8:8b:106::b01c",
"2001:ac8:8b:106::b01d",
"2001:ac8:8b:106::b01e",
"2001:ac8:8b:106::b01f"
],
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"135.136.22.133",
"135.136.22.134",
"135.136.22.135",
"135.136.22.136",
"135.136.22.137",
"135.136.22.138",
"135.136.22.139",
"135.136.22.140",
"135.136.22.141",
"135.136.22.142",
"135.136.22.143",
"2001:ac8:8b:106::c001",
"2001:ac8:8b:106::c002",
"2001:ac8:8b:106::c003",
"2001:ac8:8b:106::c004",
"2001:ac8:8b:106::c005",
"2001:ac8:8b:106::c006",
"2001:ac8:8b:106::c007",
"2001:ac8:8b:106::c008",
"2001:ac8:8b:106::c009",
"2001:ac8:8b:106::c00a",
"2001:ac8:8b:106::c00b",
"2001:ac8:8b:106::c00c",
"2001:ac8:8b:106::c00d",
"2001:ac8:8b:106::c00e",
"2001:ac8:8b:106::c00f",
"2001:ac8:8b:106::c010",
"2001:ac8:8b:106::c011",
"2001:ac8:8b:106::c012",
"2001:ac8:8b:106::c013",
"2001:ac8:8b:106::c014",
"2001:ac8:8b:106::c015",
"2001:ac8:8b:106::c016",
"2001:ac8:8b:106::c017",
"2001:ac8:8b:106::c018",
"2001:ac8:8b:106::c019",
"2001:ac8:8b:106::c01a",
"2001:ac8:8b:106::c01b",
"2001:ac8:8b:106::c01c",
"2001:ac8:8b:106::c01d",
"2001:ac8:8b:106::c01e",
"2001:ac8:8b:106::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "gb-mnc-wg-003.blockerad.eu"
}
}
},
{
"hostname": "gb-mnc-wg-004",
"location": "gb-mnc",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "135.136.21.2",
"include_in_country": true,
"weight": 100,
"public_key": "BvBubnaVVynalBjiHxHxbtBLLMBC+suHZdonTpBT4zg=",
"ipv6_addr_in": "2001:ac8:8b:107::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"135.136.21.13",
"135.136.21.14",
"135.136.21.15",
"135.136.21.16",
"135.136.21.17",
"135.136.21.18",
"135.136.21.19",
"135.136.21.20",
"135.136.21.21",
"135.136.21.22",
"2001:ac8:8b:107::b002",
"2001:ac8:8b:107::b003",
"2001:ac8:8b:107::b004",
"2001:ac8:8b:107::b005",
"2001:ac8:8b:107::b006",
"2001:ac8:8b:107::b007",
"2001:ac8:8b:107::b008",
"2001:ac8:8b:107::b009",
"2001:ac8:8b:107::b00a",
"2001:ac8:8b:107::b00b",
"2001:ac8:8b:107::b00c",
"2001:ac8:8b:107::b00d",
"2001:ac8:8b:107::b00e",
"2001:ac8:8b:107::b00f",
"2001:ac8:8b:107::b010",
"2001:ac8:8b:107::b011",
"2001:ac8:8b:107::b012",
"2001:ac8:8b:107::b013",
"2001:ac8:8b:107::b014",
"2001:ac8:8b:107::b015",
"2001:ac8:8b:107::b016",
"2001:ac8:8b:107::b017",
"2001:ac8:8b:107::b018",
"2001:ac8:8b:107::b019",
"2001:ac8:8b:107::b01a",
"2001:ac8:8b:107::b01b",
"2001:ac8:8b:107::b01c",
"2001:ac8:8b:107::b01d",
"2001:ac8:8b:107::b01e",
"2001:ac8:8b:107::b01f"
],
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"135.136.21.23",
"135.136.21.24",
"135.136.21.25",
"135.136.21.26",
"135.136.21.27",
"135.136.21.28",
"135.136.21.29",
"135.136.21.30",
"135.136.21.31",
"135.136.21.32",
"2001:ac8:8b:107::c002",
"2001:ac8:8b:107::c003",
"2001:ac8:8b:107::c004",
"2001:ac8:8b:107::c005",
"2001:ac8:8b:107::c006",
"2001:ac8:8b:107::c007",
"2001:ac8:8b:107::c008",
"2001:ac8:8b:107::c009",
"2001:ac8:8b:107::c00a",
"2001:ac8:8b:107::c00b",
"2001:ac8:8b:107::c00c",
"2001:ac8:8b:107::c00d",
"2001:ac8:8b:107::c00e",
"2001:ac8:8b:107::c00f",
"2001:ac8:8b:107::c010",
"2001:ac8:8b:107::c011",
"2001:ac8:8b:107::c012",
"2001:ac8:8b:107::c013",
"2001:ac8:8b:107::c014",
"2001:ac8:8b:107::c015",
"2001:ac8:8b:107::c016",
"2001:ac8:8b:107::c017",
"2001:ac8:8b:107::c018",
"2001:ac8:8b:107::c019",
"2001:ac8:8b:107::c01a",
"2001:ac8:8b:107::c01b",
"2001:ac8:8b:107::c01c",
"2001:ac8:8b:107::c01d",
"2001:ac8:8b:107::c01e",
"2001:ac8:8b:107::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "gb-mnc-wg-004.blockerad.eu"
}
}
},
{
"hostname": "gb-mnc-wg-201",
"location": "gb-mnc",
"active": true,
"owned": false,
"provider": "Veloxserv",
"stboot": true,
"ipv4_addr_in": "167.160.13.3",
"include_in_country": false,
"weight": 400,
"public_key": "x3APiw/mxJzdD+3WAPxTFnvOZHVotm6SGomHtMoR4Hg=",
"ipv6_addr_in": "2a03:ee40:3304::f001",
"shadowsocks_extra_addr_in": [
"167.160.13.14"
],
"features": {
"lwo": {}
}
},
{
"hostname": "gb-mnc-wg-202",
"location": "gb-mnc",
"active": true,
"owned": false,
"provider": "Veloxserv",
"stboot": true,
"ipv4_addr_in": "167.160.13.127",
"include_in_country": false,
"weight": 1,
"public_key": "OpQgffPufxbHQUbItRoezS2V+yAEBKZ10jfU82YIByI=",
"ipv6_addr_in": "2a03:ee40:3304::f101",
"shadowsocks_extra_addr_in": [
"167.160.13.139"
]
},
{
"hostname": "gr-ath-wg-101",
"location": "gr-ath",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "149.102.246.2",
"include_in_country": true,
"weight": 100,
"public_key": "li+thkAD7s6IZDgUoiKw4YSjM/U1q203PuthMzIJIU0=",
"ipv6_addr_in": "2a02:6ea0:f501:2::f001",
"features": {
"lwo": {}
}
},
{
"hostname": "gr-ath-wg-102",
"location": "gr-ath",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "149.102.246.15",
"include_in_country": true,
"weight": 100,
"public_key": "OL0gbjlNt1s26CDQjRP9wgMZbgYff7/xyUI8ypOn01s=",
"ipv6_addr_in": "2a02:6ea0:f501:3::f001",
"features": {
"lwo": {}
}
},
{
"hostname": "hk-hkg-wg-201",
"location": "hk-hkg",
"active": true,
"owned": false,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "103.125.233.18",
"include_in_country": true,
"weight": 100,
"public_key": "Oxh13dmwY6nNUa5rVHr7sLiFOj0fjzsaAUAUV87/nGs=",
"ipv6_addr_in": "2403:2c81:1000::a06f",
"shadowsocks_extra_addr_in": [
"103.125.233.3",
"103.125.233.4",
"103.125.233.5",
"103.125.233.6",
"103.125.233.7",
"103.125.233.8",
"2403:2c81:1000::b002",
"2403:2c81:1000::b003",
"2403:2c81:1000::b004",
"2403:2c81:1000::b005",
"2403:2c81:1000::b006",
"2403:2c81:1000::b007",
"2403:2c81:1000::b008",
"2403:2c81:1000::b009",
"2403:2c81:1000::b00a",
"2403:2c81:1000::b00b",
"2403:2c81:1000::b00c",
"2403:2c81:1000::b00d",
"2403:2c81:1000::b00e",
"2403:2c81:1000::b00f",
"2403:2c81:1000::b010",
"2403:2c81:1000::b011",
"2403:2c81:1000::b012",
"2403:2c81:1000::b013",
"2403:2c81:1000::b014",
"2403:2c81:1000::b015",
"2403:2c81:1000::b016",
"2403:2c81:1000::b017",
"2403:2c81:1000::b018",
"2403:2c81:1000::b019",
"2403:2c81:1000::b01a",
"2403:2c81:1000::b01b",
"2403:2c81:1000::b01c",
"2403:2c81:1000::b01d",
"2403:2c81:1000::b01e",
"2403:2c81:1000::b01f"
],
"features": {
"lwo": {}
}
},
{
"hostname": "hk-hkg-wg-202",
"location": "hk-hkg",
"active": false,
"owned": false,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "103.125.233.3",
"include_in_country": false,
"weight": 100,
"public_key": "zmhMPHfkgo+uQxP+l919Gw7cj5NTatg9nMU37eEUWis=",
"ipv6_addr_in": "2403:2c81:1000::a05f"
},
{
"hostname": "hk-hkg-wg-203",
"location": "hk-hkg",
"active": true,
"owned": false,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "103.125.233.33",
"include_in_country": true,
"weight": 100,
"public_key": "e3vqR6xVRps5ZlkL3/i6bHlrjeM/kNz+pWfSJ00UMQs=",
"ipv6_addr_in": "2403:2c81:1000::f301",
"shadowsocks_extra_addr_in": [
"103.125.233.35",
"103.125.233.36",
"103.125.233.37",
"2403:2c81:1000::b302",
"2403:2c81:1000::b303",
"2403:2c81:1000::b304",
"2403:2c81:1000::b305",
"2403:2c81:1000::b306",
"2403:2c81:1000::b307",
"2403:2c81:1000::b308",
"2403:2c81:1000::b309",
"2403:2c81:1000::b30a",
"2403:2c81:1000::b30b",
"2403:2c81:1000::b30c",
"2403:2c81:1000::b30d",
"2403:2c81:1000::b30e",
"2403:2c81:1000::b30f",
"2403:2c81:1000::b310",
"2403:2c81:1000::b311",
"2403:2c81:1000::b312",
"2403:2c81:1000::b313",
"2403:2c81:1000::b314",
"2403:2c81:1000::b315",
"2403:2c81:1000::b316",
"2403:2c81:1000::b317",
"2403:2c81:1000::b318",
"2403:2c81:1000::b319",
"2403:2c81:1000::b31a",
"2403:2c81:1000::b31b",
"2403:2c81:1000::b31c",
"2403:2c81:1000::b31d",
"2403:2c81:1000::b31e",
"2403:2c81:1000::b31f"
]
},
{
"hostname": "hk-hkg-wg-301",
"location": "hk-hkg",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.224.2",
"include_in_country": true,
"weight": 100,
"public_key": "qbvU06SBHXnqMnpb49rnE0yC4AOWQcWl2bEScu18dh8=",
"ipv6_addr_in": "2001:ac8:a:f::f001",
"features": {
"lwo": {},
"quic": {
"addr_in": [
"146.70.224.62"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "hk-hkg-wg-301.blockerad.eu"
}
}
},
{
"hostname": "hk-hkg-wg-302",
"location": "hk-hkg",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.224.66",
"include_in_country": true,
"weight": 100,
"public_key": "7FADgmd9KyAVs3eFJE/ob9tV3E6m/klONEEIOfCoPTU=",
"ipv6_addr_in": "2001:ac8:a:19::f001"
},
{
"hostname": "hk-hkg-wg-303",
"location": "hk-hkg",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.224.196",
"include_in_country": true,
"weight": 100,
"public_key": "RtTENHB7VBUiowxtdAzopcb2Fvd+OFneN73k13oPUEo=",
"ipv6_addr_in": "2001:ac8:a:1b::f001"
},
{
"hostname": "hr-zag-wg-001",
"location": "hr-zag",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "154.47.29.2",
"include_in_country": true,
"weight": 100,
"public_key": "PJvsgLogdAgZiVSxwTDyk9ri02mLZGuElklHShIjDGM=",
"ipv6_addr_in": "2a02:6ea0:f401:1::a01f"
},
{
"hostname": "hr-zag-wg-002",
"location": "hr-zag",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "154.47.29.15",
"include_in_country": true,
"weight": 100,
"public_key": "V0iDOyLSj870sjGGenDvAWqJudlPKDc212cQN85snEo=",
"ipv6_addr_in": "2a02:6ea0:f401:2::a01f"
},
{
"hostname": "hu-bud-wg-101",
"location": "hu-bud",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.196.194",
"include_in_country": true,
"weight": 100,
"public_key": "u+h0GmQJ8UBaMTi2BP9Ls6UUszcGC51y6vTmNr/y+AU=",
"ipv6_addr_in": "2001:ac8:26:55::f001"
},
{
"hostname": "hu-bud-wg-102",
"location": "hu-bud",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.196.130",
"include_in_country": true,
"weight": 100,
"public_key": "iEWLm2F4xV013ZETeZcT1dyUd5O+JnyndHso8RP8txw=",
"ipv6_addr_in": "2001:ac8:26:54::f001"
},
{
"hostname": "hu-bud-wg-201",
"location": "hu-bud",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "79.127.182.130",
"include_in_country": true,
"weight": 100,
"public_key": "RPhw+caiytSurUMQfZhEFlxGK83xcwWMNtXCkpTqJBI=",
"ipv6_addr_in": "2a02:6ea0:5700:1::f001",
"shadowsocks_extra_addr_in": [
"79.127.182.132"
],
"features": {
"lwo": {}
}
},
{
"hostname": "hu-bud-wg-202",
"location": "hu-bud",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "79.127.182.160",
"include_in_country": true,
"weight": 100,
"public_key": "xiC/w18znzSImAuzMYpP5NH+1T912cwZXo8M1V4Ruiw=",
"ipv6_addr_in": "2a02:6ea0:5700:2::f001",
"shadowsocks_extra_addr_in": [
"79.127.182.162"
],
"features": {
"lwo": {}
}
},
{
"hostname": "id-jpu-wg-001",
"location": "id-jpu",
"active": true,
"owned": false,
"provider": "Zenlayer",
"stboot": true,
"ipv4_addr_in": "129.227.46.130",
"include_in_country": true,
"weight": 100,
"public_key": "XYQvOrRqu8j521Hy/8+jGRDLZoSAssOvCectyKz350Y=",
"ipv6_addr_in": "2602:ffe4:c0d:801d::f001"
},
{
"hostname": "id-jpu-wg-002",
"location": "id-jpu",
"active": true,
"owned": false,
"provider": "Zenlayer",
"stboot": true,
"ipv4_addr_in": "129.227.46.162",
"include_in_country": true,
"weight": 100,
"public_key": "gWsH1w7lTYbsS+WxsE6w6vtXSAJoHM6PhDX5DFMYM1k=",
"ipv6_addr_in": "2602:ffe4:c0d:801e::f101",
"features": {
"lwo": {}
}
},
{
"hostname": "ie-dub-wg-101",
"location": "ie-dub",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.189.2",
"include_in_country": true,
"weight": 100,
"public_key": "2r0vPpM71ZXpseWXTXw3iwn2sjIHOTpw1V9sp03bLWw=",
"ipv6_addr_in": "2001:ac8:88:107::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"146.70.189.16",
"146.70.189.17",
"146.70.189.18",
"146.70.189.19",
"146.70.189.20",
"146.70.189.21",
"146.70.189.22",
"146.70.189.23",
"146.70.189.24",
"146.70.189.25",
"146.70.189.26",
"2001:ac8:88:107::b002",
"2001:ac8:88:107::b003",
"2001:ac8:88:107::b004",
"2001:ac8:88:107::b005",
"2001:ac8:88:107::b006",
"2001:ac8:88:107::b007",
"2001:ac8:88:107::b008",
"2001:ac8:88:107::b009",
"2001:ac8:88:107::b00a",
"2001:ac8:88:107::b00b",
"2001:ac8:88:107::b00c",
"2001:ac8:88:107::b00d",
"2001:ac8:88:107::b00e",
"2001:ac8:88:107::b00f",
"2001:ac8:88:107::b010",
"2001:ac8:88:107::b011",
"2001:ac8:88:107::b012",
"2001:ac8:88:107::b013",
"2001:ac8:88:107::b014",
"2001:ac8:88:107::b015",
"2001:ac8:88:107::b016",
"2001:ac8:88:107::b017",
"2001:ac8:88:107::b018",
"2001:ac8:88:107::b019",
"2001:ac8:88:107::b01a",
"2001:ac8:88:107::b01b",
"2001:ac8:88:107::b01c",
"2001:ac8:88:107::b01d",
"2001:ac8:88:107::b01e",
"2001:ac8:88:107::b01f"
],
"features": {
"daita": {},
"quic": {
"addr_in": [
"146.70.189.5",
"146.70.189.6",
"146.70.189.7",
"146.70.189.8",
"146.70.189.9",
"146.70.189.10",
"146.70.189.11",
"146.70.189.12",
"146.70.189.13",
"146.70.189.14",
"146.70.189.15",
"2001:ac8:88:107::c002",
"2001:ac8:88:107::c003",
"2001:ac8:88:107::c004",
"2001:ac8:88:107::c005",
"2001:ac8:88:107::c006",
"2001:ac8:88:107::c007",
"2001:ac8:88:107::c008",
"2001:ac8:88:107::c009",
"2001:ac8:88:107::c00a",
"2001:ac8:88:107::c00b",
"2001:ac8:88:107::c00c",
"2001:ac8:88:107::c00d",
"2001:ac8:88:107::c00e",
"2001:ac8:88:107::c00f",
"2001:ac8:88:107::c010",
"2001:ac8:88:107::c011",
"2001:ac8:88:107::c012",
"2001:ac8:88:107::c013",
"2001:ac8:88:107::c014",
"2001:ac8:88:107::c015",
"2001:ac8:88:107::c016",
"2001:ac8:88:107::c017",
"2001:ac8:88:107::c018",
"2001:ac8:88:107::c019",
"2001:ac8:88:107::c01a",
"2001:ac8:88:107::c01b",
"2001:ac8:88:107::c01c",
"2001:ac8:88:107::c01d",
"2001:ac8:88:107::c01e",
"2001:ac8:88:107::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "ie-dub-wg-101.blockerad.eu"
}
}
},
{
"hostname": "ie-dub-wg-102",
"location": "ie-dub",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.189.130",
"include_in_country": true,
"weight": 100,
"public_key": "2RSnfqTRb0BL/bPaKGj0OA/qopQaNG1qtzEH2Y8JyjE=",
"ipv6_addr_in": "2001:ac8:88:108::f001",
"shadowsocks_extra_addr_in": [
"146.70.189.144",
"146.70.189.145",
"146.70.189.146",
"146.70.189.147",
"146.70.189.148",
"146.70.189.149",
"146.70.189.150",
"146.70.189.151",
"146.70.189.152",
"146.70.189.153",
"146.70.189.154",
"2001:ac8:88:108::b002",
"2001:ac8:88:108::b003",
"2001:ac8:88:108::b004",
"2001:ac8:88:108::b005",
"2001:ac8:88:108::b006",
"2001:ac8:88:108::b007",
"2001:ac8:88:108::b008",
"2001:ac8:88:108::b009",
"2001:ac8:88:108::b00a",
"2001:ac8:88:108::b00b",
"2001:ac8:88:108::b00c",
"2001:ac8:88:108::b00d",
"2001:ac8:88:108::b00e",
"2001:ac8:88:108::b00f",
"2001:ac8:88:108::b010",
"2001:ac8:88:108::b011",
"2001:ac8:88:108::b012",
"2001:ac8:88:108::b013",
"2001:ac8:88:108::b014",
"2001:ac8:88:108::b015",
"2001:ac8:88:108::b016",
"2001:ac8:88:108::b017",
"2001:ac8:88:108::b018",
"2001:ac8:88:108::b019",
"2001:ac8:88:108::b01a",
"2001:ac8:88:108::b01b",
"2001:ac8:88:108::b01c",
"2001:ac8:88:108::b01d",
"2001:ac8:88:108::b01e",
"2001:ac8:88:108::b01f"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"146.70.189.133",
"146.70.189.134",
"146.70.189.135",
"146.70.189.136",
"146.70.189.137",
"146.70.189.138",
"146.70.189.139",
"146.70.189.140",
"146.70.189.141",
"146.70.189.142",
"146.70.189.143",
"2001:ac8:88:108::c002",
"2001:ac8:88:108::c003",
"2001:ac8:88:108::c004",
"2001:ac8:88:108::c005",
"2001:ac8:88:108::c006",
"2001:ac8:88:108::c007",
"2001:ac8:88:108::c008",
"2001:ac8:88:108::c009",
"2001:ac8:88:108::c00a",
"2001:ac8:88:108::c00b",
"2001:ac8:88:108::c00c",
"2001:ac8:88:108::c00d",
"2001:ac8:88:108::c00e",
"2001:ac8:88:108::c00f",
"2001:ac8:88:108::c010",
"2001:ac8:88:108::c011",
"2001:ac8:88:108::c012",
"2001:ac8:88:108::c013",
"2001:ac8:88:108::c014",
"2001:ac8:88:108::c015",
"2001:ac8:88:108::c016",
"2001:ac8:88:108::c017",
"2001:ac8:88:108::c018",
"2001:ac8:88:108::c019",
"2001:ac8:88:108::c01a",
"2001:ac8:88:108::c01b",
"2001:ac8:88:108::c01c",
"2001:ac8:88:108::c01d",
"2001:ac8:88:108::c01e",
"2001:ac8:88:108::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "ie-dub-wg-102.blockerad.eu"
}
}
},
{
"hostname": "ie-dub-wg-103",
"location": "ie-dub",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "130.195.213.130",
"include_in_country": true,
"weight": 100,
"public_key": "/Q7cQuVZo0IYckUncGSzRnQssR1DC5veZWaAnf/yDTI=",
"ipv6_addr_in": "2001:ac8:88:109::f001",
"shadowsocks_extra_addr_in": [
"130.195.213.144",
"130.195.213.145",
"130.195.213.146",
"130.195.213.147",
"130.195.213.148",
"130.195.213.149",
"130.195.213.150",
"130.195.213.151",
"130.195.213.152",
"130.195.213.153",
"130.195.213.154",
"2001:ac8:88:109::b002",
"2001:ac8:88:109::b003",
"2001:ac8:88:109::b004",
"2001:ac8:88:109::b005",
"2001:ac8:88:109::b006",
"2001:ac8:88:109::b007",
"2001:ac8:88:109::b008",
"2001:ac8:88:109::b009",
"2001:ac8:88:109::b00a",
"2001:ac8:88:109::b00b",
"2001:ac8:88:109::b00c",
"2001:ac8:88:109::b00d",
"2001:ac8:88:109::b00e",
"2001:ac8:88:109::b00f",
"2001:ac8:88:109::b010",
"2001:ac8:88:109::b011",
"2001:ac8:88:109::b012",
"2001:ac8:88:109::b013",
"2001:ac8:88:109::b014",
"2001:ac8:88:109::b015",
"2001:ac8:88:109::b016",
"2001:ac8:88:109::b017",
"2001:ac8:88:109::b018",
"2001:ac8:88:109::b019",
"2001:ac8:88:109::b01a",
"2001:ac8:88:109::b01b",
"2001:ac8:88:109::b01c",
"2001:ac8:88:109::b01d",
"2001:ac8:88:109::b01e",
"2001:ac8:88:109::b01f"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"130.195.213.133",
"130.195.213.134",
"130.195.213.135",
"130.195.213.136",
"130.195.213.137",
"130.195.213.138",
"130.195.213.139",
"130.195.213.140",
"130.195.213.141",
"130.195.213.142",
"130.195.213.143",
"2001:ac8:88:109::c002",
"2001:ac8:88:109::c003",
"2001:ac8:88:109::c004",
"2001:ac8:88:109::c005",
"2001:ac8:88:109::c006",
"2001:ac8:88:109::c007",
"2001:ac8:88:109::c008",
"2001:ac8:88:109::c009",
"2001:ac8:88:109::c00a",
"2001:ac8:88:109::c00b",
"2001:ac8:88:109::c00c",
"2001:ac8:88:109::c00d",
"2001:ac8:88:109::c00e",
"2001:ac8:88:109::c00f",
"2001:ac8:88:109::c010",
"2001:ac8:88:109::c011",
"2001:ac8:88:109::c012",
"2001:ac8:88:109::c013",
"2001:ac8:88:109::c014",
"2001:ac8:88:109::c015",
"2001:ac8:88:109::c016",
"2001:ac8:88:109::c017",
"2001:ac8:88:109::c018",
"2001:ac8:88:109::c019",
"2001:ac8:88:109::c01a",
"2001:ac8:88:109::c01b",
"2001:ac8:88:109::c01c",
"2001:ac8:88:109::c01d",
"2001:ac8:88:109::c01e",
"2001:ac8:88:109::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "ie-dub-wg-103.blockerad.eu"
}
}
},
{
"hostname": "il-tlv-wg-101",
"location": "il-tlv",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "169.150.227.197",
"include_in_country": true,
"weight": 100,
"public_key": "XOedjVJaT2IrEDJbzvtZeL4hP5uPRHzFxvD1cwVwUFo=",
"ipv6_addr_in": "2a02:6ea0:3b00:1::a01f"
},
{
"hostname": "il-tlv-wg-102",
"location": "il-tlv",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "169.150.227.210",
"include_in_country": true,
"weight": 100,
"public_key": "UNeML4rXjvOerAstTNf4gG5B+OfjVzjSQrWE6mrswD0=",
"ipv6_addr_in": "2a02:6ea0:3b00:2::a02f"
},
{
"hostname": "il-tlv-wg-103",
"location": "il-tlv",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "169.150.227.222",
"include_in_country": true,
"weight": 100,
"public_key": "11FJ/NY3jaAw1PSYG9w7bxsMxAzlI+1p8/juh1LJPT0=",
"ipv6_addr_in": "2a02:6ea0:3b00:3::a03f"
},
{
"hostname": "it-mil-wg-001",
"location": "it-mil",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "178.249.211.66",
"include_in_country": true,
"weight": 200,
"public_key": "Sa9fFFthvihGMO4cPExJ7ZaWSHNYoXmOqZMvJsaxOVk=",
"ipv6_addr_in": "2a02:6ea0:d509:1::a09f",
"features": {
"lwo": {}
}
},
{
"hostname": "it-mil-wg-002",
"location": "it-mil",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "178.249.211.79",
"include_in_country": true,
"weight": 200,
"public_key": "RJ7e37UEP6hfyLQM/lJ2K5wcZOJQFhm2VhFaBniH1kg=",
"ipv6_addr_in": "2a02:6ea0:d509:2::a10f",
"features": {
"lwo": {}
}
},
{
"hostname": "it-mil-wg-003",
"location": "it-mil",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "178.249.211.92",
"include_in_country": true,
"weight": 200,
"public_key": "WOyki5Gzoez07X7D3jAhG68hpoiYIWAx1yypVbkQaVY=",
"ipv6_addr_in": "2a02:6ea0:d509:3::a11f"
},
{
"hostname": "it-mil-wg-201",
"location": "it-mil",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.225.2",
"include_in_country": true,
"weight": 100,
"public_key": "XHwDoIVZGoVfUYbfcPiRp1LhaOCDc0A3QrS72i3ztBw=",
"ipv6_addr_in": "2001:ac8:24:17::f001"
},
{
"hostname": "it-mil-wg-202",
"location": "it-mil",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.225.66",
"include_in_country": true,
"weight": 100,
"public_key": "y5raL0QZx2CpOozrL+Knmjj7nnly3JKatFnxynjXpE0=",
"ipv6_addr_in": "2001:ac8:24:18::f001"
},
{
"hostname": "it-pmo-wg-001",
"location": "it-pmo",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "149.22.91.66",
"include_in_country": true,
"weight": 100,
"public_key": "cE6s9wV8jfAa84sgXWJ5C4d769m5Ki/XA3rxPdMWhVw=",
"ipv6_addr_in": "2a02:6ea0:4f00::f001"
},
{
"hostname": "it-pmo-wg-002",
"location": "it-pmo",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "149.22.91.79",
"include_in_country": true,
"weight": 100,
"public_key": "bGtOejMzRDKzFR1gNBAi185dkr/5RtN+QiC8EVl4kU4=",
"ipv6_addr_in": "2a02:6ea0:4f00::f101"
},
{
"hostname": "jp-osa-wg-001",
"location": "jp-osa",
"active": true,
"owned": false,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "194.114.136.3",
"include_in_country": true,
"weight": 0,
"public_key": "uhbuY1A7g0yNu0lRhLTi020kYeAx34ED30BA5DQRHFo=",
"ipv6_addr_in": "2403:fbc0:7000::f001",
"features": {
"lwo": {},
"quic": {
"addr_in": [
"194.114.136.33"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "jp-osa-wg-001.blockerad.eu"
}
}
},
{
"hostname": "jp-osa-wg-002",
"location": "jp-osa",
"active": true,
"owned": false,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "194.114.136.34",
"include_in_country": true,
"weight": 0,
"public_key": "wzGXxsYOraTCPZuRxfXVTNmoWsRkMFLqMqDxI4PutBg=",
"ipv6_addr_in": "2403:fbc0:7000::f101"
},
{
"hostname": "jp-osa-wg-003",
"location": "jp-osa",
"active": true,
"owned": false,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "194.114.136.65",
"include_in_country": true,
"weight": 0,
"public_key": "Pt18GnBffElW0sqnd6IDRr5r0B/NDezy6NicoPI+fG8=",
"ipv6_addr_in": "2403:fbc0:7000::f201"
},
{
"hostname": "jp-osa-wg-004",
"location": "jp-osa",
"active": true,
"owned": false,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "194.114.136.96",
"include_in_country": true,
"weight": 0,
"public_key": "JpDAtRuR39GLFKoQNiKvpzuJ65jOOLD7h85ekZ3reVc=",
"ipv6_addr_in": "2403:fbc0:7000::f301"
},
{
"hostname": "jp-osa-wg-101",
"location": "jp-osa",
"active": true,
"owned": true,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "194.127.166.2",
"include_in_country": true,
"weight": 100,
"public_key": "qdFG9butVjZdtGFeQHuNftvf6ZmISf2J+v167rcPDU4=",
"ipv6_addr_in": "2a07:d883:600:1::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"194.127.166.8",
"194.127.166.9",
"194.127.166.10",
"194.127.166.11",
"194.127.166.12",
"2a07:d883:600:1::b002",
"2a07:d883:600:1::b003",
"2a07:d883:600:1::b004",
"2a07:d883:600:1::b005",
"2a07:d883:600:1::b006",
"2a07:d883:600:1::b007",
"2a07:d883:600:1::b008",
"2a07:d883:600:1::b009",
"2a07:d883:600:1::b00a",
"2a07:d883:600:1::b00b",
"2a07:d883:600:1::b00c",
"2a07:d883:600:1::b00d",
"2a07:d883:600:1::b00e",
"2a07:d883:600:1::b00f",
"2a07:d883:600:1::b010",
"2a07:d883:600:1::b011",
"2a07:d883:600:1::b012",
"2a07:d883:600:1::b013",
"2a07:d883:600:1::b014",
"2a07:d883:600:1::b015",
"2a07:d883:600:1::b016",
"2a07:d883:600:1::b017",
"2a07:d883:600:1::b018",
"2a07:d883:600:1::b019",
"2a07:d883:600:1::b01a",
"2a07:d883:600:1::b01b",
"2a07:d883:600:1::b01c",
"2a07:d883:600:1::b01d",
"2a07:d883:600:1::b01e",
"2a07:d883:600:1::b01f"
],
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"194.127.166.13",
"194.127.166.14",
"194.127.166.15",
"194.127.166.16",
"194.127.166.17",
"2a07:d883:600:1::c002",
"2a07:d883:600:1::c003",
"2a07:d883:600:1::c004",
"2a07:d883:600:1::c005",
"2a07:d883:600:1::c006",
"2a07:d883:600:1::c007",
"2a07:d883:600:1::c008",
"2a07:d883:600:1::c009",
"2a07:d883:600:1::c00a",
"2a07:d883:600:1::c00b",
"2a07:d883:600:1::c00c",
"2a07:d883:600:1::c00d",
"2a07:d883:600:1::c00e",
"2a07:d883:600:1::c00f",
"2a07:d883:600:1::c010",
"2a07:d883:600:1::c011",
"2a07:d883:600:1::c012",
"2a07:d883:600:1::c013",
"2a07:d883:600:1::c014",
"2a07:d883:600:1::c015",
"2a07:d883:600:1::c016",
"2a07:d883:600:1::c017",
"2a07:d883:600:1::c018",
"2a07:d883:600:1::c019",
"2a07:d883:600:1::c01a",
"2a07:d883:600:1::c01b",
"2a07:d883:600:1::c01c",
"2a07:d883:600:1::c01d",
"2a07:d883:600:1::c01e",
"2a07:d883:600:1::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "jp-osa-wg-101.blockerad.eu"
}
}
},
{
"hostname": "jp-osa-wg-102",
"location": "jp-osa",
"active": true,
"owned": true,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "194.127.166.81",
"include_in_country": true,
"weight": 100,
"public_key": "4Gl6OMUtsLEDIrg23j/COdpKsCi7W9tzM4zvBPXOy18=",
"ipv6_addr_in": "2a07:d883:600:2::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"194.127.166.87",
"194.127.166.88",
"194.127.166.89",
"194.127.166.90",
"194.127.166.91",
"2a07:d883:600:2::b002",
"2a07:d883:600:2::b003",
"2a07:d883:600:2::b004",
"2a07:d883:600:2::b005",
"2a07:d883:600:2::b006",
"2a07:d883:600:2::b007",
"2a07:d883:600:2::b008",
"2a07:d883:600:2::b009",
"2a07:d883:600:2::b00a",
"2a07:d883:600:2::b00b",
"2a07:d883:600:2::b00c",
"2a07:d883:600:2::b00d",
"2a07:d883:600:2::b00e",
"2a07:d883:600:2::b00f",
"2a07:d883:600:2::b010",
"2a07:d883:600:2::b011",
"2a07:d883:600:2::b012",
"2a07:d883:600:2::b013",
"2a07:d883:600:2::b014",
"2a07:d883:600:2::b015",
"2a07:d883:600:2::b016",
"2a07:d883:600:2::b017",
"2a07:d883:600:2::b018",
"2a07:d883:600:2::b019",
"2a07:d883:600:2::b01a",
"2a07:d883:600:2::b01b",
"2a07:d883:600:2::b01c",
"2a07:d883:600:2::b01d",
"2a07:d883:600:2::b01e",
"2a07:d883:600:2::b01f"
],
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"194.127.166.92",
"194.127.166.93",
"194.127.166.94",
"194.127.166.95",
"194.127.166.96",
"2a07:d883:600:2::c002",
"2a07:d883:600:2::c003",
"2a07:d883:600:2::c004",
"2a07:d883:600:2::c005",
"2a07:d883:600:2::c006",
"2a07:d883:600:2::c007",
"2a07:d883:600:2::c008",
"2a07:d883:600:2::c009",
"2a07:d883:600:2::c00a",
"2a07:d883:600:2::c00b",
"2a07:d883:600:2::c00c",
"2a07:d883:600:2::c00d",
"2a07:d883:600:2::c00e",
"2a07:d883:600:2::c00f",
"2a07:d883:600:2::c010",
"2a07:d883:600:2::c011",
"2a07:d883:600:2::c012",
"2a07:d883:600:2::c013",
"2a07:d883:600:2::c014",
"2a07:d883:600:2::c015",
"2a07:d883:600:2::c016",
"2a07:d883:600:2::c017",
"2a07:d883:600:2::c018",
"2a07:d883:600:2::c019",
"2a07:d883:600:2::c01a",
"2a07:d883:600:2::c01b",
"2a07:d883:600:2::c01c",
"2a07:d883:600:2::c01d",
"2a07:d883:600:2::c01e",
"2a07:d883:600:2::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "jp-osa-wg-102.blockerad.eu"
}
}
},
{
"hostname": "jp-osa-wg-103",
"location": "jp-osa",
"active": true,
"owned": true,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "194.127.166.161",
"include_in_country": true,
"weight": 100,
"public_key": "B4LgHDQA8GQtqer7jAEjVDiTBLTBYk6vdOY/sM8DbGI=",
"ipv6_addr_in": "2a07:d883:600:3::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"194.127.166.167",
"194.127.166.168",
"194.127.166.169",
"194.127.166.170",
"194.127.166.171",
"2a07:d883:600:3::b002",
"2a07:d883:600:3::b003",
"2a07:d883:600:3::b004",
"2a07:d883:600:3::b005",
"2a07:d883:600:3::b006",
"2a07:d883:600:3::b007",
"2a07:d883:600:3::b008",
"2a07:d883:600:3::b009",
"2a07:d883:600:3::b00a",
"2a07:d883:600:3::b00b",
"2a07:d883:600:3::b00c",
"2a07:d883:600:3::b00d",
"2a07:d883:600:3::b00e",
"2a07:d883:600:3::b00f",
"2a07:d883:600:3::b010",
"2a07:d883:600:3::b011",
"2a07:d883:600:3::b012",
"2a07:d883:600:3::b013",
"2a07:d883:600:3::b014",
"2a07:d883:600:3::b015",
"2a07:d883:600:3::b016",
"2a07:d883:600:3::b017",
"2a07:d883:600:3::b018",
"2a07:d883:600:3::b019",
"2a07:d883:600:3::b01a",
"2a07:d883:600:3::b01b",
"2a07:d883:600:3::b01c",
"2a07:d883:600:3::b01d",
"2a07:d883:600:3::b01e",
"2a07:d883:600:3::b01f"
],
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"194.127.166.172",
"194.127.166.173",
"194.127.166.174",
"194.127.166.175",
"194.127.166.176",
"2a07:d883:600:3::c002",
"2a07:d883:600:3::c003",
"2a07:d883:600:3::c004",
"2a07:d883:600:3::c005",
"2a07:d883:600:3::c006",
"2a07:d883:600:3::c007",
"2a07:d883:600:3::c008",
"2a07:d883:600:3::c009",
"2a07:d883:600:3::c00a",
"2a07:d883:600:3::c00b",
"2a07:d883:600:3::c00c",
"2a07:d883:600:3::c00d",
"2a07:d883:600:3::c00e",
"2a07:d883:600:3::c00f",
"2a07:d883:600:3::c010",
"2a07:d883:600:3::c011",
"2a07:d883:600:3::c012",
"2a07:d883:600:3::c013",
"2a07:d883:600:3::c014",
"2a07:d883:600:3::c015",
"2a07:d883:600:3::c016",
"2a07:d883:600:3::c017",
"2a07:d883:600:3::c018",
"2a07:d883:600:3::c019",
"2a07:d883:600:3::c01a",
"2a07:d883:600:3::c01b",
"2a07:d883:600:3::c01c",
"2a07:d883:600:3::c01d",
"2a07:d883:600:3::c01e",
"2a07:d883:600:3::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "jp-osa-wg-103.blockerad.eu"
}
}
},
{
"hostname": "jp-tyo-wg-001",
"location": "jp-tyo",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "138.199.21.239",
"include_in_country": true,
"weight": 200,
"public_key": "AUo2zhQ0wCDy3/jmZgOe4QMncWWqrdME7BbY2UlkgyI=",
"ipv6_addr_in": "2a02:6ea0:d31c::a15f",
"daita": true,
"features": {
"daita": {}
}
},
{
"hostname": "jp-tyo-wg-002",
"location": "jp-tyo",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "138.199.21.226",
"include_in_country": true,
"weight": 200,
"public_key": "zdlqydCbeR7sG1y5L8sS65X1oOtRKvfVbAuFgqEGhi4=",
"ipv6_addr_in": "2a02:6ea0:d31b::a14f"
},
{
"hostname": "jp-tyo-wg-201",
"location": "jp-tyo",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.201.2",
"include_in_country": true,
"weight": 100,
"public_key": "5YlME8hOnWqvZ7iSampvPW5bG/dJ+PYpaBFV5kfp9UA=",
"ipv6_addr_in": "2001:ac8:40:13::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"146.70.201.13",
"146.70.201.14",
"146.70.201.15",
"146.70.201.16",
"146.70.201.17",
"146.70.201.18",
"146.70.201.19",
"146.70.201.20",
"146.70.201.21",
"146.70.201.22",
"2001:ac8:40:13::b002",
"2001:ac8:40:13::b003",
"2001:ac8:40:13::b004",
"2001:ac8:40:13::b005",
"2001:ac8:40:13::b006",
"2001:ac8:40:13::b007",
"2001:ac8:40:13::b008",
"2001:ac8:40:13::b009",
"2001:ac8:40:13::b00a",
"2001:ac8:40:13::b00b",
"2001:ac8:40:13::b00c",
"2001:ac8:40:13::b00d",
"2001:ac8:40:13::b00e",
"2001:ac8:40:13::b00f",
"2001:ac8:40:13::b010",
"2001:ac8:40:13::b011",
"2001:ac8:40:13::b012",
"2001:ac8:40:13::b013",
"2001:ac8:40:13::b014",
"2001:ac8:40:13::b015",
"2001:ac8:40:13::b016",
"2001:ac8:40:13::b017",
"2001:ac8:40:13::b018",
"2001:ac8:40:13::b019",
"2001:ac8:40:13::b01a",
"2001:ac8:40:13::b01b",
"2001:ac8:40:13::b01c",
"2001:ac8:40:13::b01d",
"2001:ac8:40:13::b01e",
"2001:ac8:40:13::b01f"
],
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"146.70.201.23",
"146.70.201.24",
"146.70.201.25",
"146.70.201.26",
"146.70.201.27",
"146.70.201.28",
"146.70.201.29",
"146.70.201.30",
"146.70.201.31",
"146.70.201.32",
"2001:ac8:40:13::c002",
"2001:ac8:40:13::c003",
"2001:ac8:40:13::c004",
"2001:ac8:40:13::c005",
"2001:ac8:40:13::c006",
"2001:ac8:40:13::c007",
"2001:ac8:40:13::c008",
"2001:ac8:40:13::c009",
"2001:ac8:40:13::c00a",
"2001:ac8:40:13::c00b",
"2001:ac8:40:13::c00c",
"2001:ac8:40:13::c00d",
"2001:ac8:40:13::c00e",
"2001:ac8:40:13::c00f",
"2001:ac8:40:13::c010",
"2001:ac8:40:13::c011",
"2001:ac8:40:13::c012",
"2001:ac8:40:13::c013",
"2001:ac8:40:13::c014",
"2001:ac8:40:13::c015",
"2001:ac8:40:13::c016",
"2001:ac8:40:13::c017",
"2001:ac8:40:13::c018",
"2001:ac8:40:13::c019",
"2001:ac8:40:13::c01a",
"2001:ac8:40:13::c01b",
"2001:ac8:40:13::c01c",
"2001:ac8:40:13::c01d",
"2001:ac8:40:13::c01e",
"2001:ac8:40:13::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "jp-tyo-wg-201.blockerad.eu"
}
}
},
{
"hostname": "jp-tyo-wg-202",
"location": "jp-tyo",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.201.130",
"include_in_country": true,
"weight": 100,
"public_key": "3NykAEXAdeaT0qFstBkJorW3PDsBRUHHbBUc6YoIzAs=",
"ipv6_addr_in": "2001:ac8:40:14::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"146.70.201.141",
"146.70.201.142",
"146.70.201.143",
"146.70.201.144",
"146.70.201.145",
"146.70.201.146",
"146.70.201.147",
"146.70.201.148",
"146.70.201.149",
"146.70.201.150",
"2001:ac8:40:14::b002",
"2001:ac8:40:14::b003",
"2001:ac8:40:14::b004",
"2001:ac8:40:14::b005",
"2001:ac8:40:14::b006",
"2001:ac8:40:14::b007",
"2001:ac8:40:14::b008",
"2001:ac8:40:14::b009",
"2001:ac8:40:14::b00a",
"2001:ac8:40:14::b00b",
"2001:ac8:40:14::b00c",
"2001:ac8:40:14::b00d",
"2001:ac8:40:14::b00e",
"2001:ac8:40:14::b00f",
"2001:ac8:40:14::b010",
"2001:ac8:40:14::b011",
"2001:ac8:40:14::b012",
"2001:ac8:40:14::b013",
"2001:ac8:40:14::b014",
"2001:ac8:40:14::b015",
"2001:ac8:40:14::b016",
"2001:ac8:40:14::b017",
"2001:ac8:40:14::b018",
"2001:ac8:40:14::b019",
"2001:ac8:40:14::b01a",
"2001:ac8:40:14::b01b",
"2001:ac8:40:14::b01c",
"2001:ac8:40:14::b01d",
"2001:ac8:40:14::b01e",
"2001:ac8:40:14::b01f"
],
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"146.70.201.151",
"146.70.201.152",
"146.70.201.153",
"146.70.201.154",
"146.70.201.155",
"146.70.201.156",
"146.70.201.157",
"146.70.201.158",
"146.70.201.159",
"146.70.201.160",
"2001:ac8:40:14::c002",
"2001:ac8:40:14::c003",
"2001:ac8:40:14::c004",
"2001:ac8:40:14::c005",
"2001:ac8:40:14::c006",
"2001:ac8:40:14::c007",
"2001:ac8:40:14::c008",
"2001:ac8:40:14::c009",
"2001:ac8:40:14::c00a",
"2001:ac8:40:14::c00b",
"2001:ac8:40:14::c00c",
"2001:ac8:40:14::c00d",
"2001:ac8:40:14::c00e",
"2001:ac8:40:14::c00f",
"2001:ac8:40:14::c010",
"2001:ac8:40:14::c011",
"2001:ac8:40:14::c012",
"2001:ac8:40:14::c013",
"2001:ac8:40:14::c014",
"2001:ac8:40:14::c015",
"2001:ac8:40:14::c016",
"2001:ac8:40:14::c017",
"2001:ac8:40:14::c018",
"2001:ac8:40:14::c019",
"2001:ac8:40:14::c01a",
"2001:ac8:40:14::c01b",
"2001:ac8:40:14::c01c",
"2001:ac8:40:14::c01d",
"2001:ac8:40:14::c01e",
"2001:ac8:40:14::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "jp-tyo-wg-202.blockerad.eu"
}
}
},
{
"hostname": "jp-tyo-wg-203",
"location": "jp-tyo",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "135.136.55.2",
"include_in_country": true,
"weight": 100,
"public_key": "nkNCONMj0uw6/PV/t8R1TX7q2+DKNSDIUCnxvc0fWjs=",
"ipv6_addr_in": "2001:ac8:40:1d::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"135.136.55.13",
"135.136.55.14",
"135.136.55.15",
"135.136.55.16",
"135.136.55.17",
"135.136.55.18",
"135.136.55.19",
"135.136.55.20",
"135.136.55.21",
"135.136.55.22",
"2001:ac8:40:1d::b002",
"2001:ac8:40:1d::b003",
"2001:ac8:40:1d::b004",
"2001:ac8:40:1d::b005",
"2001:ac8:40:1d::b006",
"2001:ac8:40:1d::b007",
"2001:ac8:40:1d::b008",
"2001:ac8:40:1d::b009",
"2001:ac8:40:1d::b00a",
"2001:ac8:40:1d::b00b",
"2001:ac8:40:1d::b00c",
"2001:ac8:40:1d::b00d",
"2001:ac8:40:1d::b00e",
"2001:ac8:40:1d::b00f",
"2001:ac8:40:1d::b010",
"2001:ac8:40:1d::b011",
"2001:ac8:40:1d::b012",
"2001:ac8:40:1d::b013",
"2001:ac8:40:1d::b014",
"2001:ac8:40:1d::b015",
"2001:ac8:40:1d::b016",
"2001:ac8:40:1d::b017",
"2001:ac8:40:1d::b018",
"2001:ac8:40:1d::b019",
"2001:ac8:40:1d::b01a",
"2001:ac8:40:1d::b01b",
"2001:ac8:40:1d::b01c",
"2001:ac8:40:1d::b01d",
"2001:ac8:40:1d::b01e",
"2001:ac8:40:1d::b01f"
],
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"135.136.55.23",
"135.136.55.24",
"135.136.55.25",
"135.136.55.26",
"135.136.55.27",
"135.136.55.28",
"135.136.55.29",
"135.136.55.30",
"135.136.55.31",
"135.136.55.32",
"2001:ac8:40:1d::c002",
"2001:ac8:40:1d::c003",
"2001:ac8:40:1d::c004",
"2001:ac8:40:1d::c005",
"2001:ac8:40:1d::c006",
"2001:ac8:40:1d::c007",
"2001:ac8:40:1d::c008",
"2001:ac8:40:1d::c009",
"2001:ac8:40:1d::c00a",
"2001:ac8:40:1d::c00b",
"2001:ac8:40:1d::c00c",
"2001:ac8:40:1d::c00d",
"2001:ac8:40:1d::c00e",
"2001:ac8:40:1d::c00f",
"2001:ac8:40:1d::c010",
"2001:ac8:40:1d::c011",
"2001:ac8:40:1d::c012",
"2001:ac8:40:1d::c013",
"2001:ac8:40:1d::c014",
"2001:ac8:40:1d::c015",
"2001:ac8:40:1d::c016",
"2001:ac8:40:1d::c017",
"2001:ac8:40:1d::c018",
"2001:ac8:40:1d::c019",
"2001:ac8:40:1d::c01a",
"2001:ac8:40:1d::c01b",
"2001:ac8:40:1d::c01c",
"2001:ac8:40:1d::c01d",
"2001:ac8:40:1d::c01e",
"2001:ac8:40:1d::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "jp-tyo-wg-203.blockerad.eu"
}
}
},
{
"hostname": "mx-qro-wg-001",
"location": "mx-qro",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "149.88.22.129",
"include_in_country": true,
"weight": 100,
"public_key": "yxyntWsANEwxeR0pOPNAcfWY7zEVICZe9G+GxortzEY=",
"ipv6_addr_in": "2a02:6ea0:f803::f001",
"daita": true,
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"149.88.22.141"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "mx-qro-wg-001.blockerad.eu"
}
}
},
{
"hostname": "mx-qro-wg-002",
"location": "mx-qro",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "149.88.22.142",
"include_in_country": true,
"weight": 100,
"public_key": "kGkalo3qvm8MynKdzwW7CGBYXkqRwGhHfYVssgKOWnU=",
"ipv6_addr_in": "2a02:6ea0:f803:1::f001",
"features": {
"lwo": {}
}
},
{
"hostname": "mx-qro-wg-003",
"location": "mx-qro",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "149.88.22.155",
"include_in_country": true,
"weight": 100,
"public_key": "hRamkTwXw0usPFDorPl2vf1qP8chczEBcqeV5bA1QDA=",
"ipv6_addr_in": "2a02:6ea0:f803:2::f001"
},
{
"hostname": "mx-qro-wg-004",
"location": "mx-qro",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "149.88.22.168",
"include_in_country": true,
"weight": 100,
"public_key": "Q3yqhnYHK/bFjrd6yqti8gSV1gzOwvnl5N5tXuUxMyk=",
"ipv6_addr_in": "2a02:6ea0:f803:3::f001"
},
{
"hostname": "my-kul-wg-001",
"location": "my-kul",
"active": true,
"owned": false,
"provider": "Zenlayer",
"stboot": true,
"ipv4_addr_in": "98.98.47.130",
"include_in_country": true,
"weight": 100,
"public_key": "RnwTFcAl6z4UfXio9ApLqlOjBcYvD0gWG0htl6fiCl4=",
"ipv6_addr_in": "2602:ffe4:c20:112::f001",
"shadowsocks_extra_addr_in": [
"98.98.47.132"
]
},
{
"hostname": "my-kul-wg-002",
"location": "my-kul",
"active": true,
"owned": false,
"provider": "Zenlayer",
"stboot": true,
"ipv4_addr_in": "162.128.129.98",
"include_in_country": true,
"weight": 100,
"public_key": "BVh+R5uifa9kn6fDNozd1OrnlGlV8qTr/IUIg0PDGl0=",
"ipv6_addr_in": "2602:ffe4:c20:112::f101",
"shadowsocks_extra_addr_in": [
"162.128.129.100"
],
"features": {
"lwo": {}
}
},
{
"hostname": "ng-los-wg-001",
"location": "ng-los",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "79.127.149.130",
"include_in_country": true,
"weight": 100,
"public_key": "nlpbIResE9vYypA9M/tKvfbUamsmCSawTqmq0cbVJjw=",
"ipv6_addr_in": "2a02:6ea0:5400:1::f001",
"shadowsocks_extra_addr_in": [
"79.127.149.132"
]
},
{
"hostname": "ng-los-wg-002",
"location": "ng-los",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "79.127.149.159",
"include_in_country": true,
"weight": 100,
"public_key": "Hel+ma9otIsWedjgK6Dp51t/WmUys+Q/hUqpvN7qBXg=",
"ipv6_addr_in": "2a02:6ea0:5400:2::f001",
"shadowsocks_extra_addr_in": [
"79.127.149.161"
]
},
{
"hostname": "nl-ams-wg-001",
"location": "nl-ams",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "193.32.249.66",
"include_in_country": true,
"weight": 50,
"public_key": "UrQiI9ISdPPzd4ARw1NHOPKKvKvxUhjwRjaI0JpJFgM=",
"ipv6_addr_in": "2a03:1b20:3:f011::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"2a03:1b20:3:f011::b002",
"2a03:1b20:3:f011::b003",
"2a03:1b20:3:f011::b004",
"2a03:1b20:3:f011::b005",
"2a03:1b20:3:f011::b006",
"2a03:1b20:3:f011::b007",
"2a03:1b20:3:f011::b008",
"2a03:1b20:3:f011::b009",
"2a03:1b20:3:f011::b00a",
"2a03:1b20:3:f011::b00b",
"2a03:1b20:3:f011::b00c",
"2a03:1b20:3:f011::b00d",
"2a03:1b20:3:f011::b00e",
"2a03:1b20:3:f011::b00f",
"2a03:1b20:3:f011::b010",
"2a03:1b20:3:f011::b011",
"2a03:1b20:3:f011::b012",
"2a03:1b20:3:f011::b013",
"2a03:1b20:3:f011::b014",
"2a03:1b20:3:f011::b015",
"2a03:1b20:3:f011::b016",
"2a03:1b20:3:f011::b017",
"2a03:1b20:3:f011::b018",
"2a03:1b20:3:f011::b019",
"2a03:1b20:3:f011::b01a",
"2a03:1b20:3:f011::b01b",
"2a03:1b20:3:f011::b01c",
"2a03:1b20:3:f011::b01d",
"2a03:1b20:3:f011::b01e",
"2a03:1b20:3:f011::b01f",
"141.11.20.22",
"141.11.20.23",
"141.11.20.24",
"141.11.20.25",
"141.11.20.26",
"141.11.20.27",
"141.11.20.28",
"141.11.20.29",
"141.11.20.30",
"141.11.20.31",
"141.11.20.32",
"141.11.20.33",
"141.11.20.34",
"141.11.20.35",
"141.11.20.36",
"141.11.20.37",
"141.11.20.38",
"141.11.20.39",
"141.11.20.40",
"141.11.20.41"
],
"features": {
"daita": {},
"lwo": {}
}
},
{
"hostname": "nl-ams-wg-002",
"location": "nl-ams",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "185.65.134.82",
"include_in_country": true,
"weight": 50,
"public_key": "DVui+5aifNFRIVDjH3v2y+dQ+uwI+HFZOd21ajbEpBo=",
"ipv6_addr_in": "2a03:1b20:3:f011::a02f",
"daita": true,
"shadowsocks_extra_addr_in": [
"2a03:1b20:3:f011::b102",
"2a03:1b20:3:f011::b103",
"2a03:1b20:3:f011::b104",
"2a03:1b20:3:f011::b105",
"2a03:1b20:3:f011::b106",
"2a03:1b20:3:f011::b107",
"2a03:1b20:3:f011::b108",
"2a03:1b20:3:f011::b109",
"2a03:1b20:3:f011::b10a",
"2a03:1b20:3:f011::b10b",
"2a03:1b20:3:f011::b10c",
"2a03:1b20:3:f011::b10d",
"2a03:1b20:3:f011::b10e",
"2a03:1b20:3:f011::b10f",
"2a03:1b20:3:f011::b110",
"2a03:1b20:3:f011::b111",
"2a03:1b20:3:f011::b112",
"2a03:1b20:3:f011::b113",
"2a03:1b20:3:f011::b114",
"2a03:1b20:3:f011::b115",
"2a03:1b20:3:f011::b116",
"2a03:1b20:3:f011::b117",
"2a03:1b20:3:f011::b118",
"2a03:1b20:3:f011::b119",
"2a03:1b20:3:f011::b11a",
"2a03:1b20:3:f011::b11b",
"2a03:1b20:3:f011::b11c",
"2a03:1b20:3:f011::b11d",
"2a03:1b20:3:f011::b11e",
"2a03:1b20:3:f011::b11f",
"141.11.20.82",
"141.11.20.83",
"141.11.20.84",
"141.11.20.85",
"141.11.20.86",
"141.11.20.87",
"141.11.20.88",
"141.11.20.89",
"141.11.20.90",
"141.11.20.91",
"141.11.20.92",
"141.11.20.93",
"141.11.20.94",
"141.11.20.95",
"141.11.20.96",
"141.11.20.97",
"141.11.20.98",
"141.11.20.99",
"141.11.20.100",
"141.11.20.101"
],
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"185.65.134.218",
"2a03:1b20:3:f011::c102",
"2a03:1b20:3:f011::c103",
"2a03:1b20:3:f011::c104",
"2a03:1b20:3:f011::c105",
"2a03:1b20:3:f011::c106",
"2a03:1b20:3:f011::c107",
"2a03:1b20:3:f011::c108",
"2a03:1b20:3:f011::c109",
"2a03:1b20:3:f011::c10a",
"2a03:1b20:3:f011::c10b",
"2a03:1b20:3:f011::c10c",
"2a03:1b20:3:f011::c10d",
"2a03:1b20:3:f011::c10e",
"2a03:1b20:3:f011::c10f",
"2a03:1b20:3:f011::c110",
"2a03:1b20:3:f011::c111",
"2a03:1b20:3:f011::c112",
"2a03:1b20:3:f011::c113",
"2a03:1b20:3:f011::c114",
"2a03:1b20:3:f011::c115",
"2a03:1b20:3:f011::c116",
"2a03:1b20:3:f011::c117",
"2a03:1b20:3:f011::c118",
"2a03:1b20:3:f011::c119",
"2a03:1b20:3:f011::c11a",
"2a03:1b20:3:f011::c11b",
"2a03:1b20:3:f011::c11c",
"2a03:1b20:3:f011::c11d",
"2a03:1b20:3:f011::c11e",
"2a03:1b20:3:f011::c11f",
"141.11.20.102",
"141.11.20.103",
"141.11.20.104",
"141.11.20.105",
"141.11.20.106",
"141.11.20.107",
"141.11.20.108",
"141.11.20.109",
"141.11.20.110",
"141.11.20.111",
"141.11.20.112",
"141.11.20.113",
"141.11.20.114",
"141.11.20.115",
"141.11.20.116",
"141.11.20.117",
"141.11.20.118",
"141.11.20.119",
"141.11.20.120",
"141.11.20.121"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "nl-ams-wg-002.blockerad.eu"
}
}
},
{
"hostname": "nl-ams-wg-003",
"location": "nl-ams",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "185.65.134.83",
"include_in_country": true,
"weight": 50,
"public_key": "if4HpJZbN7jft5E9R9wAoTcggIu6eZhgYDvqxnwrXic=",
"ipv6_addr_in": "2a03:1b20:3:f011::f201",
"shadowsocks_extra_addr_in": [
"2a03:1b20:3:f011::b202",
"2a03:1b20:3:f011::b203",
"2a03:1b20:3:f011::b204",
"2a03:1b20:3:f011::b205",
"2a03:1b20:3:f011::b206",
"2a03:1b20:3:f011::b207",
"2a03:1b20:3:f011::b208",
"2a03:1b20:3:f011::b209",
"2a03:1b20:3:f011::b20a",
"2a03:1b20:3:f011::b20b",
"2a03:1b20:3:f011::b20c",
"2a03:1b20:3:f011::b20d",
"2a03:1b20:3:f011::b20e",
"2a03:1b20:3:f011::b20f",
"2a03:1b20:3:f011::b210",
"2a03:1b20:3:f011::b211",
"2a03:1b20:3:f011::b212",
"2a03:1b20:3:f011::b213",
"2a03:1b20:3:f011::b214",
"2a03:1b20:3:f011::b215",
"2a03:1b20:3:f011::b216",
"2a03:1b20:3:f011::b217",
"2a03:1b20:3:f011::b218",
"2a03:1b20:3:f011::b219",
"2a03:1b20:3:f011::b21a",
"2a03:1b20:3:f011::b21b",
"2a03:1b20:3:f011::b21c",
"2a03:1b20:3:f011::b21d",
"2a03:1b20:3:f011::b21e",
"2a03:1b20:3:f011::b21f",
"141.11.20.142",
"141.11.20.143",
"141.11.20.144",
"141.11.20.145",
"141.11.20.146",
"141.11.20.147",
"141.11.20.148",
"141.11.20.149",
"141.11.20.150",
"141.11.20.151",
"141.11.20.152",
"141.11.20.153",
"141.11.20.154",
"141.11.20.155",
"141.11.20.156",
"141.11.20.157",
"141.11.20.158",
"141.11.20.159",
"141.11.20.160",
"141.11.20.161"
],
"features": {
"lwo": {}
}
},
{
"hostname": "nl-ams-wg-004",
"location": "nl-ams",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "193.32.249.69",
"include_in_country": true,
"weight": 50,
"public_key": "hnRyse6QxPPcZOoSwRsHUtK1W+APWXnIoaDTmH6JsHQ=",
"ipv6_addr_in": "2a03:1b20:3:f011::f301",
"shadowsocks_extra_addr_in": [
"2a03:1b20:3:f011::b302",
"2a03:1b20:3:f011::b303",
"2a03:1b20:3:f011::b304",
"2a03:1b20:3:f011::b305",
"2a03:1b20:3:f011::b306",
"2a03:1b20:3:f011::b307",
"2a03:1b20:3:f011::b308",
"2a03:1b20:3:f011::b309",
"2a03:1b20:3:f011::b30a",
"2a03:1b20:3:f011::b30b",
"2a03:1b20:3:f011::b30c",
"2a03:1b20:3:f011::b30d",
"2a03:1b20:3:f011::b30e",
"2a03:1b20:3:f011::b30f",
"2a03:1b20:3:f011::b310",
"2a03:1b20:3:f011::b311",
"2a03:1b20:3:f011::b312",
"2a03:1b20:3:f011::b313",
"2a03:1b20:3:f011::b314",
"2a03:1b20:3:f011::b315",
"2a03:1b20:3:f011::b316",
"2a03:1b20:3:f011::b317",
"2a03:1b20:3:f011::b318",
"2a03:1b20:3:f011::b319",
"2a03:1b20:3:f011::b31a",
"2a03:1b20:3:f011::b31b",
"2a03:1b20:3:f011::b31c",
"2a03:1b20:3:f011::b31d",
"2a03:1b20:3:f011::b31e",
"2a03:1b20:3:f011::b31f",
"141.11.20.202",
"141.11.20.203",
"141.11.20.204",
"141.11.20.205",
"141.11.20.206",
"141.11.20.207",
"141.11.20.208",
"141.11.20.209",
"141.11.20.210",
"141.11.20.211",
"141.11.20.212",
"141.11.20.213",
"141.11.20.214",
"141.11.20.215",
"141.11.20.216",
"141.11.20.217",
"141.11.20.218",
"141.11.20.219",
"141.11.20.220",
"141.11.20.221"
],
"features": {
"lwo": {}
}
},
{
"hostname": "nl-ams-wg-005",
"location": "nl-ams",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "193.32.249.70",
"include_in_country": true,
"weight": 50,
"public_key": "33BoONMGCm2vknq2eq72eozRsHmHQY6ZHEEZ4851TkY=",
"ipv6_addr_in": "2a03:1b20:3:f011::f401",
"shadowsocks_extra_addr_in": [
"2a03:1b20:3:f011::b402",
"2a03:1b20:3:f011::b403",
"2a03:1b20:3:f011::b404",
"2a03:1b20:3:f011::b405",
"2a03:1b20:3:f011::b406",
"2a03:1b20:3:f011::b407",
"2a03:1b20:3:f011::b408",
"2a03:1b20:3:f011::b409",
"2a03:1b20:3:f011::b40a",
"2a03:1b20:3:f011::b40b",
"2a03:1b20:3:f011::b40c",
"2a03:1b20:3:f011::b40d",
"2a03:1b20:3:f011::b40e",
"2a03:1b20:3:f011::b40f",
"2a03:1b20:3:f011::b410",
"2a03:1b20:3:f011::b411",
"2a03:1b20:3:f011::b412",
"2a03:1b20:3:f011::b413",
"2a03:1b20:3:f011::b414",
"2a03:1b20:3:f011::b415",
"2a03:1b20:3:f011::b416",
"2a03:1b20:3:f011::b417",
"2a03:1b20:3:f011::b418",
"2a03:1b20:3:f011::b419",
"2a03:1b20:3:f011::b41a",
"2a03:1b20:3:f011::b41b",
"2a03:1b20:3:f011::b41c",
"2a03:1b20:3:f011::b41d",
"2a03:1b20:3:f011::b41e",
"2a03:1b20:3:f011::b41f"
]
},
{
"hostname": "nl-ams-wg-006",
"location": "nl-ams",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "185.65.134.86",
"include_in_country": true,
"weight": 50,
"public_key": "xpZ3ZDEukbqKQvdHwaqKMUhsYhcYD3uLPUh1ACsVr1s=",
"ipv6_addr_in": "2a03:1b20:3:f011::f501",
"shadowsocks_extra_addr_in": [
"2a03:1b20:3:f011::b502",
"2a03:1b20:3:f011::b503",
"2a03:1b20:3:f011::b504",
"2a03:1b20:3:f011::b505",
"2a03:1b20:3:f011::b506",
"2a03:1b20:3:f011::b507",
"2a03:1b20:3:f011::b508",
"2a03:1b20:3:f011::b509",
"2a03:1b20:3:f011::b50a",
"2a03:1b20:3:f011::b50b",
"2a03:1b20:3:f011::b50c",
"2a03:1b20:3:f011::b50d",
"2a03:1b20:3:f011::b50e",
"2a03:1b20:3:f011::b50f",
"2a03:1b20:3:f011::b510",
"2a03:1b20:3:f011::b511",
"2a03:1b20:3:f011::b512",
"2a03:1b20:3:f011::b513",
"2a03:1b20:3:f011::b514",
"2a03:1b20:3:f011::b515",
"2a03:1b20:3:f011::b516",
"2a03:1b20:3:f011::b517",
"2a03:1b20:3:f011::b518",
"2a03:1b20:3:f011::b519",
"2a03:1b20:3:f011::b51a",
"2a03:1b20:3:f011::b51b",
"2a03:1b20:3:f011::b51c",
"2a03:1b20:3:f011::b51d",
"2a03:1b20:3:f011::b51e",
"2a03:1b20:3:f011::b51f"
]
},
{
"hostname": "nl-ams-wg-007",
"location": "nl-ams",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "185.65.134.76",
"include_in_country": true,
"weight": 50,
"public_key": "Os/BwxAIWehlypQ8QjrKVEK5PhY84b413+U3YWZJYXQ=",
"ipv6_addr_in": "2a03:1b20:3:f011::f701",
"shadowsocks_extra_addr_in": [
"2a03:1b20:3:f011::b702",
"2a03:1b20:3:f011::b703",
"2a03:1b20:3:f011::b704",
"2a03:1b20:3:f011::b705",
"2a03:1b20:3:f011::b706",
"2a03:1b20:3:f011::b707",
"2a03:1b20:3:f011::b708",
"2a03:1b20:3:f011::b709",
"2a03:1b20:3:f011::b70a",
"2a03:1b20:3:f011::b70b",
"2a03:1b20:3:f011::b70c",
"2a03:1b20:3:f011::b70d",
"2a03:1b20:3:f011::b70e",
"2a03:1b20:3:f011::b70f",
"2a03:1b20:3:f011::b710",
"2a03:1b20:3:f011::b711",
"2a03:1b20:3:f011::b712",
"2a03:1b20:3:f011::b713",
"2a03:1b20:3:f011::b714",
"2a03:1b20:3:f011::b715",
"2a03:1b20:3:f011::b716",
"2a03:1b20:3:f011::b717",
"2a03:1b20:3:f011::b718",
"2a03:1b20:3:f011::b719",
"2a03:1b20:3:f011::b71a",
"2a03:1b20:3:f011::b71b",
"2a03:1b20:3:f011::b71c",
"2a03:1b20:3:f011::b71d",
"2a03:1b20:3:f011::b71e",
"2a03:1b20:3:f011::b71f"
],
"features": {
"lwo": {}
}
},
{
"hostname": "nl-ams-wg-008",
"location": "nl-ams",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "193.32.249.73",
"include_in_country": true,
"weight": 50,
"public_key": "hf+klJbIyUoGUaFHgac9W+yriwb9uvSnafDfnmEW9Hc=",
"ipv6_addr_in": "2a03:1b20:3:f011::f801",
"shadowsocks_extra_addr_in": [
"193.32.249.209",
"2a03:1b20:3:f011::b802",
"2a03:1b20:3:f011::b803",
"2a03:1b20:3:f011::b804",
"2a03:1b20:3:f011::b805",
"2a03:1b20:3:f011::b806",
"2a03:1b20:3:f011::b807",
"2a03:1b20:3:f011::b808",
"2a03:1b20:3:f011::b809",
"2a03:1b20:3:f011::b80a",
"2a03:1b20:3:f011::b80b",
"2a03:1b20:3:f011::b80c",
"2a03:1b20:3:f011::b80d",
"2a03:1b20:3:f011::b80e",
"2a03:1b20:3:f011::b80f",
"2a03:1b20:3:f011::b810",
"2a03:1b20:3:f011::b811",
"2a03:1b20:3:f011::b812",
"2a03:1b20:3:f011::b813",
"2a03:1b20:3:f011::b814",
"2a03:1b20:3:f011::b815",
"2a03:1b20:3:f011::b816",
"2a03:1b20:3:f011::b817",
"2a03:1b20:3:f011::b818",
"2a03:1b20:3:f011::b819",
"2a03:1b20:3:f011::b81a",
"2a03:1b20:3:f011::b81b",
"2a03:1b20:3:f011::b81c",
"2a03:1b20:3:f011::b81d",
"2a03:1b20:3:f011::b81e",
"2a03:1b20:3:f011::b81f"
],
"features": {
"lwo": {}
}
},
{
"hostname": "nl-ams-wg-101",
"location": "nl-ams",
"active": true,
"owned": false,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "92.60.40.194",
"include_in_country": true,
"weight": 0,
"public_key": "m9w2Fr0rcN6R1a9HYrGnUTU176rTZIq2pcsovPd9sms=",
"ipv6_addr_in": "2a0c:59c0:18::a20f"
},
{
"hostname": "nl-ams-wg-102",
"location": "nl-ams",
"active": true,
"owned": false,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "92.60.40.209",
"include_in_country": true,
"weight": 0,
"public_key": "uUYbYGKoA6UBh1hfkAz5tAWFv4SmteYC9kWh7/K6Ah0=",
"ipv6_addr_in": "2a0c:59c0:18::a21f"
},
{
"hostname": "nl-ams-wg-103",
"location": "nl-ams",
"active": true,
"owned": false,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "92.60.40.224",
"include_in_country": true,
"weight": 0,
"public_key": "CE7mlfDJ4gpwLPB/CyPfIusITnGZwDI9v4IlVueGT24=",
"ipv6_addr_in": "2a0c:59c0:18::a22f",
"features": {
"lwo": {},
"quic": {
"addr_in": [
"92.60.40.237"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "nl-ams-wg-103.blockerad.eu"
}
}
},
{
"hostname": "nl-ams-wg-201",
"location": "nl-ams",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "169.150.196.2",
"include_in_country": true,
"weight": 100,
"public_key": "vt+yTcpxWvH8qiSncd1wSPV/78vt2aE2BBU8ZbG7x1Q=",
"ipv6_addr_in": "2a02:6ea0:c034:1::a30f",
"daita": true,
"features": {
"daita": {}
}
},
{
"hostname": "nl-ams-wg-202",
"location": "nl-ams",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "169.150.196.15",
"include_in_country": true,
"weight": 100,
"public_key": "BChJDLOwZu9Q1oH0UcrxcHP6xxHhyRbjrBUsE0e07Vk=",
"ipv6_addr_in": "2a02:6ea0:c034:2::a31f"
},
{
"hostname": "nl-ams-wg-203",
"location": "nl-ams",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "169.150.196.28",
"include_in_country": true,
"weight": 100,
"public_key": "M5z8TKjJYpIJ3FXoXy7k58IUaoVro2tWMKSgC5WIqR8=",
"ipv6_addr_in": "2a02:6ea0:c034:3::a32f"
},
{
"hostname": "nl-ams-wg-301",
"location": "nl-ams",
"active": true,
"owned": true,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "185.184.222.3",
"include_in_country": true,
"weight": 100,
"public_key": "bcCnX0Rtwat5a02t80k0aVJU5Q3z48dwuePiSXQ1kEY=",
"ipv6_addr_in": "2a07:d883:700:1::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"185.184.222.14",
"185.184.222.15",
"185.184.222.16",
"185.184.222.17",
"185.184.222.18",
"185.184.222.19",
"185.184.222.20",
"185.184.222.21",
"185.184.222.22",
"185.184.222.23",
"185.184.222.24",
"185.184.222.25",
"185.184.222.26",
"185.184.222.27",
"185.184.222.28",
"185.184.222.29",
"2a07:d883:700:1::b002",
"2a07:d883:700:1::b003",
"2a07:d883:700:1::b004",
"2a07:d883:700:1::b005",
"2a07:d883:700:1::b006",
"2a07:d883:700:1::b007",
"2a07:d883:700:1::b008",
"2a07:d883:700:1::b009",
"2a07:d883:700:1::b00a",
"2a07:d883:700:1::b00b",
"2a07:d883:700:1::b00c",
"2a07:d883:700:1::b00d",
"2a07:d883:700:1::b00e",
"2a07:d883:700:1::b00f",
"2a07:d883:700:1::b010",
"2a07:d883:700:1::b011",
"2a07:d883:700:1::b012",
"2a07:d883:700:1::b013",
"2a07:d883:700:1::b014",
"2a07:d883:700:1::b015",
"2a07:d883:700:1::b016",
"2a07:d883:700:1::b017",
"2a07:d883:700:1::b018",
"2a07:d883:700:1::b019",
"2a07:d883:700:1::b01a",
"2a07:d883:700:1::b01b",
"2a07:d883:700:1::b01c",
"2a07:d883:700:1::b01d",
"2a07:d883:700:1::b01e",
"2a07:d883:700:1::b01f"
],
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"185.184.222.30",
"185.184.222.31",
"185.184.222.32",
"185.184.222.33",
"185.184.222.34",
"185.184.222.35",
"185.184.222.36",
"185.184.222.37",
"185.184.222.38",
"185.184.222.39",
"185.184.222.40",
"185.184.222.41",
"185.184.222.42",
"185.184.222.43",
"185.184.222.44",
"2a07:d883:700:1::c002",
"2a07:d883:700:1::c003",
"2a07:d883:700:1::c004",
"2a07:d883:700:1::c005",
"2a07:d883:700:1::c006",
"2a07:d883:700:1::c007",
"2a07:d883:700:1::c008",
"2a07:d883:700:1::c009",
"2a07:d883:700:1::c00a",
"2a07:d883:700:1::c00b",
"2a07:d883:700:1::c00c",
"2a07:d883:700:1::c00d",
"2a07:d883:700:1::c00e",
"2a07:d883:700:1::c00f",
"2a07:d883:700:1::c010",
"2a07:d883:700:1::c011",
"2a07:d883:700:1::c012",
"2a07:d883:700:1::c013",
"2a07:d883:700:1::c014",
"2a07:d883:700:1::c015",
"2a07:d883:700:1::c016",
"2a07:d883:700:1::c017",
"2a07:d883:700:1::c018",
"2a07:d883:700:1::c019",
"2a07:d883:700:1::c01a",
"2a07:d883:700:1::c01b",
"2a07:d883:700:1::c01c",
"2a07:d883:700:1::c01d",
"2a07:d883:700:1::c01e",
"2a07:d883:700:1::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "nl-ams-wg-301.blockerad.eu"
}
}
},
{
"hostname": "nl-ams-wg-302",
"location": "nl-ams",
"active": true,
"owned": true,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "185.184.222.166",
"include_in_country": true,
"weight": 100,
"public_key": "P40jSYOl1qrMXtRBszMp5W7bHZMDM7zyxysqJcUGxWw=",
"ipv6_addr_in": "2a07:d883:700:2::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"185.184.222.178",
"185.184.222.179",
"185.184.222.180",
"185.184.222.181",
"185.184.222.182",
"185.184.222.183",
"185.184.222.184",
"185.184.222.185",
"185.184.222.186",
"185.184.222.187",
"185.184.222.188",
"185.184.222.189",
"185.184.222.190",
"185.184.222.191",
"185.184.222.192",
"2a07:d883:700:2::b002",
"2a07:d883:700:2::b003",
"2a07:d883:700:2::b004",
"2a07:d883:700:2::b005",
"2a07:d883:700:2::b006",
"2a07:d883:700:2::b007",
"2a07:d883:700:2::b008",
"2a07:d883:700:2::b009",
"2a07:d883:700:2::b00a",
"2a07:d883:700:2::b00b",
"2a07:d883:700:2::b00c",
"2a07:d883:700:2::b00d",
"2a07:d883:700:2::b00e",
"2a07:d883:700:2::b00f",
"2a07:d883:700:2::b010",
"2a07:d883:700:2::b011",
"2a07:d883:700:2::b012",
"2a07:d883:700:2::b013",
"2a07:d883:700:2::b014",
"2a07:d883:700:2::b015",
"2a07:d883:700:2::b016",
"2a07:d883:700:2::b017",
"2a07:d883:700:2::b018",
"2a07:d883:700:2::b019",
"2a07:d883:700:2::b01a",
"2a07:d883:700:2::b01b",
"2a07:d883:700:2::b01c",
"2a07:d883:700:2::b01d",
"2a07:d883:700:2::b01e",
"2a07:d883:700:2::b01f"
],
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"185.184.222.193",
"185.184.222.194",
"185.184.222.195",
"185.184.222.196",
"185.184.222.197",
"185.184.222.198",
"185.184.222.199",
"185.184.222.200",
"185.184.222.201",
"185.184.222.202",
"185.184.222.203",
"185.184.222.204",
"185.184.222.205",
"185.184.222.206",
"185.184.222.207",
"2a07:d883:700:2::c002",
"2a07:d883:700:2::c003",
"2a07:d883:700:2::c004",
"2a07:d883:700:2::c005",
"2a07:d883:700:2::c006",
"2a07:d883:700:2::c007",
"2a07:d883:700:2::c008",
"2a07:d883:700:2::c009",
"2a07:d883:700:2::c00a",
"2a07:d883:700:2::c00b",
"2a07:d883:700:2::c00c",
"2a07:d883:700:2::c00d",
"2a07:d883:700:2::c00e",
"2a07:d883:700:2::c00f",
"2a07:d883:700:2::c010",
"2a07:d883:700:2::c011",
"2a07:d883:700:2::c012",
"2a07:d883:700:2::c013",
"2a07:d883:700:2::c014",
"2a07:d883:700:2::c015",
"2a07:d883:700:2::c016",
"2a07:d883:700:2::c017",
"2a07:d883:700:2::c018",
"2a07:d883:700:2::c019",
"2a07:d883:700:2::c01a",
"2a07:d883:700:2::c01b",
"2a07:d883:700:2::c01c",
"2a07:d883:700:2::c01d",
"2a07:d883:700:2::c01e",
"2a07:d883:700:2::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "nl-ams-wg-302.blockerad.eu"
}
}
},
{
"hostname": "nl-ams-wg-303",
"location": "nl-ams",
"active": true,
"owned": true,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "185.184.222.209",
"include_in_country": true,
"weight": 100,
"public_key": "Ax99pLRK5ixjeBz50E2qB8aWRrj5mw0QEdS6ZThiA3o=",
"ipv6_addr_in": "2a07:d883:700:3::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"185.184.222.220",
"185.184.222.221",
"185.184.222.222",
"185.184.222.223",
"185.184.222.224",
"185.184.222.225",
"185.184.222.226",
"185.184.222.227",
"185.184.222.228",
"185.184.222.229",
"185.184.222.230",
"185.184.222.231",
"185.184.222.232",
"185.184.222.233",
"185.184.222.234",
"2a07:d883:700:3::b002",
"2a07:d883:700:3::b003",
"2a07:d883:700:3::b004",
"2a07:d883:700:3::b005",
"2a07:d883:700:3::b006",
"2a07:d883:700:3::b007",
"2a07:d883:700:3::b008",
"2a07:d883:700:3::b009",
"2a07:d883:700:3::b00a",
"2a07:d883:700:3::b00b",
"2a07:d883:700:3::b00c",
"2a07:d883:700:3::b00d",
"2a07:d883:700:3::b00e",
"2a07:d883:700:3::b00f",
"2a07:d883:700:3::b010",
"2a07:d883:700:3::b011",
"2a07:d883:700:3::b012",
"2a07:d883:700:3::b013",
"2a07:d883:700:3::b014",
"2a07:d883:700:3::b015",
"2a07:d883:700:3::b016",
"2a07:d883:700:3::b017",
"2a07:d883:700:3::b018",
"2a07:d883:700:3::b019",
"2a07:d883:700:3::b01a",
"2a07:d883:700:3::b01b",
"2a07:d883:700:3::b01c",
"2a07:d883:700:3::b01d",
"2a07:d883:700:3::b01e",
"2a07:d883:700:3::b01f"
],
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"185.184.222.235",
"185.184.222.236",
"185.184.222.237",
"185.184.222.238",
"185.184.222.239",
"185.184.222.240",
"185.184.222.241",
"185.184.222.242",
"185.184.222.243",
"185.184.222.244",
"185.184.222.245",
"185.184.222.246",
"185.184.222.247",
"185.184.222.248",
"185.184.222.249",
"185.184.222.250",
"2a07:d883:700:3::c002",
"2a07:d883:700:3::c003",
"2a07:d883:700:3::c004",
"2a07:d883:700:3::c005",
"2a07:d883:700:3::c006",
"2a07:d883:700:3::c007",
"2a07:d883:700:3::c008",
"2a07:d883:700:3::c009",
"2a07:d883:700:3::c00a",
"2a07:d883:700:3::c00b",
"2a07:d883:700:3::c00c",
"2a07:d883:700:3::c00d",
"2a07:d883:700:3::c00e",
"2a07:d883:700:3::c00f",
"2a07:d883:700:3::c010",
"2a07:d883:700:3::c011",
"2a07:d883:700:3::c012",
"2a07:d883:700:3::c013",
"2a07:d883:700:3::c014",
"2a07:d883:700:3::c015",
"2a07:d883:700:3::c016",
"2a07:d883:700:3::c017",
"2a07:d883:700:3::c018",
"2a07:d883:700:3::c019",
"2a07:d883:700:3::c01a",
"2a07:d883:700:3::c01b",
"2a07:d883:700:3::c01c",
"2a07:d883:700:3::c01d",
"2a07:d883:700:3::c01e",
"2a07:d883:700:3::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "nl-ams-wg-303.blockerad.eu"
}
}
},
{
"hostname": "no-osl-wg-001",
"location": "no-osl",
"active": true,
"owned": true,
"provider": "Blix",
"stboot": true,
"ipv4_addr_in": "176.125.235.71",
"include_in_country": true,
"weight": 100,
"public_key": "jOUZjMq2PWHDzQxu3jPXktYB7EKeFwBzGZx56cTXXQg=",
"ipv6_addr_in": "2a02:20c8:4124::a01f",
"daita": true,
"shadowsocks_extra_addr_in": [
"91.90.44.27",
"91.90.44.28",
"91.90.44.29",
"91.90.44.30",
"91.90.44.31",
"91.90.44.32",
"91.90.44.33",
"91.90.44.34",
"91.90.44.35",
"91.90.44.36",
"91.90.44.37",
"91.90.44.38",
"91.90.44.39",
"91.90.44.40",
"91.90.44.41",
"91.90.44.42",
"91.90.44.43",
"91.90.44.44",
"91.90.44.45",
"91.90.44.46",
"2a02:20c8:4124::b002",
"2a02:20c8:4124::b003",
"2a02:20c8:4124::b004",
"2a02:20c8:4124::b005",
"2a02:20c8:4124::b006",
"2a02:20c8:4124::b007",
"2a02:20c8:4124::b008",
"2a02:20c8:4124::b009",
"2a02:20c8:4124::b00a",
"2a02:20c8:4124::b00b",
"2a02:20c8:4124::b00c",
"2a02:20c8:4124::b00d",
"2a02:20c8:4124::b00e",
"2a02:20c8:4124::b00f",
"2a02:20c8:4124::b010",
"2a02:20c8:4124::b011",
"2a02:20c8:4124::b012",
"2a02:20c8:4124::b013",
"2a02:20c8:4124::b014",
"2a02:20c8:4124::b015",
"2a02:20c8:4124::b016",
"2a02:20c8:4124::b017",
"2a02:20c8:4124::b018",
"2a02:20c8:4124::b019",
"2a02:20c8:4124::b01a",
"2a02:20c8:4124::b01b",
"2a02:20c8:4124::b01c",
"2a02:20c8:4124::b01d",
"2a02:20c8:4124::b01e",
"2a02:20c8:4124::b01f"
],
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"91.90.44.47",
"91.90.44.48",
"91.90.44.49",
"91.90.44.50",
"91.90.44.51",
"91.90.44.52",
"91.90.44.53",
"91.90.44.54",
"91.90.44.55",
"91.90.44.56",
"91.90.44.57",
"91.90.44.58",
"91.90.44.59",
"91.90.44.60",
"91.90.44.61",
"91.90.44.62",
"2a02:20c8:4124::c002",
"2a02:20c8:4124::c003",
"2a02:20c8:4124::c004",
"2a02:20c8:4124::c005",
"2a02:20c8:4124::c006",
"2a02:20c8:4124::c007",
"2a02:20c8:4124::c008",
"2a02:20c8:4124::c009",
"2a02:20c8:4124::c00a",
"2a02:20c8:4124::c00b",
"2a02:20c8:4124::c00c",
"2a02:20c8:4124::c00d",
"2a02:20c8:4124::c00e",
"2a02:20c8:4124::c00f",
"2a02:20c8:4124::c010",
"2a02:20c8:4124::c011",
"2a02:20c8:4124::c012",
"2a02:20c8:4124::c013",
"2a02:20c8:4124::c014",
"2a02:20c8:4124::c015",
"2a02:20c8:4124::c016",
"2a02:20c8:4124::c017",
"2a02:20c8:4124::c018",
"2a02:20c8:4124::c019",
"2a02:20c8:4124::c01a",
"2a02:20c8:4124::c01b",
"2a02:20c8:4124::c01c",
"2a02:20c8:4124::c01d",
"2a02:20c8:4124::c01e",
"2a02:20c8:4124::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "no-osl-wg-001.blockerad.eu"
}
}
},
{
"hostname": "no-osl-wg-002",
"location": "no-osl",
"active": true,
"owned": true,
"provider": "Blix",
"stboot": true,
"ipv4_addr_in": "176.125.235.72",
"include_in_country": true,
"weight": 100,
"public_key": "IhhpKphSFWpwja1P4HBctZ367G3Q53EgdeFGZro29Tc=",
"ipv6_addr_in": "2a02:20c8:4124::a02f",
"daita": true,
"shadowsocks_extra_addr_in": [
"176.125.235.81",
"176.125.235.82",
"176.125.235.83",
"176.125.235.84",
"176.125.235.85",
"176.125.235.86",
"176.125.235.87",
"176.125.235.88",
"176.125.235.89",
"176.125.235.91",
"176.125.235.92",
"176.125.235.93",
"176.125.235.94",
"176.125.235.95",
"176.125.235.96",
"176.125.235.97",
"176.125.235.98",
"176.125.235.99",
"2a02:20c8:4124::b102",
"2a02:20c8:4124::b103",
"2a02:20c8:4124::b104",
"2a02:20c8:4124::b105",
"2a02:20c8:4124::b106",
"2a02:20c8:4124::b107",
"2a02:20c8:4124::b108",
"2a02:20c8:4124::b109",
"2a02:20c8:4124::b10a",
"2a02:20c8:4124::b10b",
"2a02:20c8:4124::b10c",
"2a02:20c8:4124::b10d",
"2a02:20c8:4124::b10e",
"2a02:20c8:4124::b10f",
"2a02:20c8:4124::b110",
"2a02:20c8:4124::b111",
"2a02:20c8:4124::b112",
"2a02:20c8:4124::b113",
"2a02:20c8:4124::b114",
"2a02:20c8:4124::b115",
"2a02:20c8:4124::b116",
"2a02:20c8:4124::b117",
"2a02:20c8:4124::b118",
"2a02:20c8:4124::b119",
"2a02:20c8:4124::b11a",
"2a02:20c8:4124::b11b",
"2a02:20c8:4124::b11c",
"2a02:20c8:4124::b11d",
"2a02:20c8:4124::b11e",
"2a02:20c8:4124::b11f"
],
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"176.125.235.101",
"176.125.235.102",
"176.125.235.103",
"176.125.235.104",
"176.125.235.105",
"176.125.235.106",
"176.125.235.107",
"176.125.235.108",
"176.125.235.109",
"176.125.235.110",
"176.125.235.111",
"176.125.235.112",
"176.125.235.113",
"176.125.235.114",
"176.125.235.115",
"176.125.235.116",
"176.125.235.117",
"176.125.235.118",
"176.125.235.119",
"176.125.235.120",
"176.125.235.121",
"176.125.235.122",
"176.125.235.123",
"176.125.235.124",
"176.125.235.125",
"2a02:20c8:4124::c102",
"2a02:20c8:4124::c103",
"2a02:20c8:4124::c104",
"2a02:20c8:4124::c105",
"2a02:20c8:4124::c106",
"2a02:20c8:4124::c107",
"2a02:20c8:4124::c108",
"2a02:20c8:4124::c109",
"2a02:20c8:4124::c10a",
"2a02:20c8:4124::c10b",
"2a02:20c8:4124::c10c",
"2a02:20c8:4124::c10d",
"2a02:20c8:4124::c10e",
"2a02:20c8:4124::c10f",
"2a02:20c8:4124::c110",
"2a02:20c8:4124::c111",
"2a02:20c8:4124::c112",
"2a02:20c8:4124::c113",
"2a02:20c8:4124::c114",
"2a02:20c8:4124::c115",
"2a02:20c8:4124::c116",
"2a02:20c8:4124::c117",
"2a02:20c8:4124::c118",
"2a02:20c8:4124::c119",
"2a02:20c8:4124::c11a",
"2a02:20c8:4124::c11b",
"2a02:20c8:4124::c11c",
"2a02:20c8:4124::c11d",
"2a02:20c8:4124::c11e",
"2a02:20c8:4124::c11f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "no-osl-wg-002.blockerad.eu"
}
}
},
{
"hostname": "no-osl-wg-003",
"location": "no-osl",
"active": true,
"owned": true,
"provider": "Blix",
"stboot": true,
"ipv4_addr_in": "176.125.235.73",
"include_in_country": true,
"weight": 100,
"public_key": "zOBWmQ3BEOZKsYKbj4dC2hQjxCbr3eKa6wGWyEDYbC4=",
"ipv6_addr_in": "2a02:20c8:4124::a03f",
"daita": true,
"shadowsocks_extra_addr_in": [
"178.255.149.150",
"178.255.149.151",
"178.255.149.152",
"178.255.149.153",
"178.255.149.154",
"178.255.149.155",
"178.255.149.156",
"178.255.149.157",
"178.255.149.158",
"178.255.149.159",
"178.255.149.160",
"178.255.149.161",
"178.255.149.162",
"178.255.149.163",
"178.255.149.164",
"178.255.149.165",
"178.255.149.166",
"178.255.149.167",
"178.255.149.168",
"178.255.149.169",
"2a02:20c8:4124::b202",
"2a02:20c8:4124::b203",
"2a02:20c8:4124::b204",
"2a02:20c8:4124::b205",
"2a02:20c8:4124::b206",
"2a02:20c8:4124::b207",
"2a02:20c8:4124::b208",
"2a02:20c8:4124::b209",
"2a02:20c8:4124::b20a",
"2a02:20c8:4124::b20b",
"2a02:20c8:4124::b20c",
"2a02:20c8:4124::b20d",
"2a02:20c8:4124::b20e",
"2a02:20c8:4124::b20f",
"2a02:20c8:4124::b210",
"2a02:20c8:4124::b211",
"2a02:20c8:4124::b212",
"2a02:20c8:4124::b213",
"2a02:20c8:4124::b214",
"2a02:20c8:4124::b215",
"2a02:20c8:4124::b216",
"2a02:20c8:4124::b217",
"2a02:20c8:4124::b218",
"2a02:20c8:4124::b219",
"2a02:20c8:4124::b21a",
"2a02:20c8:4124::b21b",
"2a02:20c8:4124::b21c",
"2a02:20c8:4124::b21d",
"2a02:20c8:4124::b21e",
"2a02:20c8:4124::b21f"
],
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"178.255.149.170",
"178.255.149.171",
"178.255.149.172",
"178.255.149.173",
"178.255.149.174",
"178.255.149.175",
"178.255.149.176",
"178.255.149.177",
"178.255.149.178",
"178.255.149.179",
"178.255.149.180",
"178.255.149.181",
"178.255.149.182",
"178.255.149.183",
"178.255.149.184",
"178.255.149.185",
"178.255.149.186",
"178.255.149.187",
"178.255.149.188",
"178.255.149.189",
"2a02:20c8:4124::c202",
"2a02:20c8:4124::c203",
"2a02:20c8:4124::c204",
"2a02:20c8:4124::c205",
"2a02:20c8:4124::c206",
"2a02:20c8:4124::c207",
"2a02:20c8:4124::c208",
"2a02:20c8:4124::c209",
"2a02:20c8:4124::c20a",
"2a02:20c8:4124::c20b",
"2a02:20c8:4124::c20c",
"2a02:20c8:4124::c20d",
"2a02:20c8:4124::c20e",
"2a02:20c8:4124::c20f",
"2a02:20c8:4124::c210",
"2a02:20c8:4124::c211",
"2a02:20c8:4124::c212",
"2a02:20c8:4124::c213",
"2a02:20c8:4124::c214",
"2a02:20c8:4124::c215",
"2a02:20c8:4124::c216",
"2a02:20c8:4124::c217",
"2a02:20c8:4124::c218",
"2a02:20c8:4124::c219",
"2a02:20c8:4124::c21a",
"2a02:20c8:4124::c21b",
"2a02:20c8:4124::c21c",
"2a02:20c8:4124::c21d",
"2a02:20c8:4124::c21e",
"2a02:20c8:4124::c21f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "no-osl-wg-003.blockerad.eu"
}
}
},
{
"hostname": "no-osl-wg-101",
"location": "no-osl",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "141.98.253.5",
"include_in_country": true,
"weight": 100,
"public_key": "QXR6DwdWn2urvyVNt5pFulLuhkyeuTp2STwGgEQ6Ehw=",
"ipv6_addr_in": "2a03:1b20:c:f011:1::f001",
"shadowsocks_extra_addr_in": [
"141.98.253.7",
"2a03:1b20:c:f011:1::b002",
"2a03:1b20:c:f011:1::b003",
"2a03:1b20:c:f011:1::b004",
"2a03:1b20:c:f011:1::b005",
"2a03:1b20:c:f011:1::b006",
"2a03:1b20:c:f011:1::b007",
"2a03:1b20:c:f011:1::b008",
"2a03:1b20:c:f011:1::b009",
"2a03:1b20:c:f011:1::b00a",
"2a03:1b20:c:f011:1::b00b",
"2a03:1b20:c:f011:1::b00c",
"2a03:1b20:c:f011:1::b00d",
"2a03:1b20:c:f011:1::b00e",
"2a03:1b20:c:f011:1::b00f",
"2a03:1b20:c:f011:1::b010",
"2a03:1b20:c:f011:1::b011",
"2a03:1b20:c:f011:1::b012",
"2a03:1b20:c:f011:1::b013",
"2a03:1b20:c:f011:1::b014",
"2a03:1b20:c:f011:1::b015",
"2a03:1b20:c:f011:1::b016",
"2a03:1b20:c:f011:1::b017",
"2a03:1b20:c:f011:1::b018",
"2a03:1b20:c:f011:1::b019",
"2a03:1b20:c:f011:1::b01a",
"2a03:1b20:c:f011:1::b01b",
"2a03:1b20:c:f011:1::b01c",
"2a03:1b20:c:f011:1::b01d",
"2a03:1b20:c:f011:1::b01e",
"2a03:1b20:c:f011:1::b01f"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"141.98.253.8",
"2a03:1b20:c:f011:1::c002",
"2a03:1b20:c:f011:1::c003",
"2a03:1b20:c:f011:1::c004",
"2a03:1b20:c:f011:1::c005",
"2a03:1b20:c:f011:1::c006",
"2a03:1b20:c:f011:1::c007",
"2a03:1b20:c:f011:1::c008",
"2a03:1b20:c:f011:1::c009",
"2a03:1b20:c:f011:1::c00a",
"2a03:1b20:c:f011:1::c00b",
"2a03:1b20:c:f011:1::c00c",
"2a03:1b20:c:f011:1::c00d",
"2a03:1b20:c:f011:1::c00e",
"2a03:1b20:c:f011:1::c00f",
"2a03:1b20:c:f011:1::c010",
"2a03:1b20:c:f011:1::c011",
"2a03:1b20:c:f011:1::c012",
"2a03:1b20:c:f011:1::c013",
"2a03:1b20:c:f011:1::c014",
"2a03:1b20:c:f011:1::c015",
"2a03:1b20:c:f011:1::c016",
"2a03:1b20:c:f011:1::c017",
"2a03:1b20:c:f011:1::c018",
"2a03:1b20:c:f011:1::c019",
"2a03:1b20:c:f011:1::c01a",
"2a03:1b20:c:f011:1::c01b",
"2a03:1b20:c:f011:1::c01c",
"2a03:1b20:c:f011:1::c01d",
"2a03:1b20:c:f011:1::c01e",
"2a03:1b20:c:f011:1::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "no-osl-wg-101.blockerad.eu"
}
}
},
{
"hostname": "no-osl-wg-102",
"location": "no-osl",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "141.98.253.85",
"include_in_country": true,
"weight": 100,
"public_key": "MlS7Fep/Lx6d0j2c+ZWPWECAC+OpGVRq/NV4AWvw+C8=",
"ipv6_addr_in": "2a03:1b20:c:f011:2::f001",
"shadowsocks_extra_addr_in": [
"141.98.253.87",
"2a03:1b20:c:f011:2::b002",
"2a03:1b20:c:f011:2::b003",
"2a03:1b20:c:f011:2::b004",
"2a03:1b20:c:f011:2::b005",
"2a03:1b20:c:f011:2::b006",
"2a03:1b20:c:f011:2::b007",
"2a03:1b20:c:f011:2::b008",
"2a03:1b20:c:f011:2::b009",
"2a03:1b20:c:f011:2::b00a",
"2a03:1b20:c:f011:2::b00b",
"2a03:1b20:c:f011:2::b00c",
"2a03:1b20:c:f011:2::b00d",
"2a03:1b20:c:f011:2::b00e",
"2a03:1b20:c:f011:2::b00f",
"2a03:1b20:c:f011:2::b010",
"2a03:1b20:c:f011:2::b011",
"2a03:1b20:c:f011:2::b012",
"2a03:1b20:c:f011:2::b013",
"2a03:1b20:c:f011:2::b014",
"2a03:1b20:c:f011:2::b015",
"2a03:1b20:c:f011:2::b016",
"2a03:1b20:c:f011:2::b017",
"2a03:1b20:c:f011:2::b018",
"2a03:1b20:c:f011:2::b019",
"2a03:1b20:c:f011:2::b01a",
"2a03:1b20:c:f011:2::b01b",
"2a03:1b20:c:f011:2::b01c",
"2a03:1b20:c:f011:2::b01d",
"2a03:1b20:c:f011:2::b01e",
"2a03:1b20:c:f011:2::b01f"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"141.98.253.88",
"2a03:1b20:c:f011:2::c002",
"2a03:1b20:c:f011:2::c003",
"2a03:1b20:c:f011:2::c004",
"2a03:1b20:c:f011:2::c005",
"2a03:1b20:c:f011:2::c006",
"2a03:1b20:c:f011:2::c007",
"2a03:1b20:c:f011:2::c008",
"2a03:1b20:c:f011:2::c009",
"2a03:1b20:c:f011:2::c00a",
"2a03:1b20:c:f011:2::c00b",
"2a03:1b20:c:f011:2::c00c",
"2a03:1b20:c:f011:2::c00d",
"2a03:1b20:c:f011:2::c00e",
"2a03:1b20:c:f011:2::c00f",
"2a03:1b20:c:f011:2::c010",
"2a03:1b20:c:f011:2::c011",
"2a03:1b20:c:f011:2::c012",
"2a03:1b20:c:f011:2::c013",
"2a03:1b20:c:f011:2::c014",
"2a03:1b20:c:f011:2::c015",
"2a03:1b20:c:f011:2::c016",
"2a03:1b20:c:f011:2::c017",
"2a03:1b20:c:f011:2::c018",
"2a03:1b20:c:f011:2::c019",
"2a03:1b20:c:f011:2::c01a",
"2a03:1b20:c:f011:2::c01b",
"2a03:1b20:c:f011:2::c01c",
"2a03:1b20:c:f011:2::c01d",
"2a03:1b20:c:f011:2::c01e",
"2a03:1b20:c:f011:2::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "no-osl-wg-102.blockerad.eu"
}
}
},
{
"hostname": "no-osl-wg-103",
"location": "no-osl",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "141.98.253.165",
"include_in_country": true,
"weight": 100,
"public_key": "7aoQqj/A9rVeZmuT6kCRPuQ4Pf0yy2T2RlTo7P8LYGE=",
"ipv6_addr_in": "2a03:1b20:c:f011:3::f001",
"shadowsocks_extra_addr_in": [
"141.98.253.167",
"2a03:1b20:c:f011:3::b002",
"2a03:1b20:c:f011:3::b003",
"2a03:1b20:c:f011:3::b004",
"2a03:1b20:c:f011:3::b005",
"2a03:1b20:c:f011:3::b006",
"2a03:1b20:c:f011:3::b007",
"2a03:1b20:c:f011:3::b008",
"2a03:1b20:c:f011:3::b009",
"2a03:1b20:c:f011:3::b00a",
"2a03:1b20:c:f011:3::b00b",
"2a03:1b20:c:f011:3::b00c",
"2a03:1b20:c:f011:3::b00d",
"2a03:1b20:c:f011:3::b00e",
"2a03:1b20:c:f011:3::b00f",
"2a03:1b20:c:f011:3::b010",
"2a03:1b20:c:f011:3::b011",
"2a03:1b20:c:f011:3::b012",
"2a03:1b20:c:f011:3::b013",
"2a03:1b20:c:f011:3::b014",
"2a03:1b20:c:f011:3::b015",
"2a03:1b20:c:f011:3::b016",
"2a03:1b20:c:f011:3::b017",
"2a03:1b20:c:f011:3::b018",
"2a03:1b20:c:f011:3::b019",
"2a03:1b20:c:f011:3::b01a",
"2a03:1b20:c:f011:3::b01b",
"2a03:1b20:c:f011:3::b01c",
"2a03:1b20:c:f011:3::b01d",
"2a03:1b20:c:f011:3::b01e",
"2a03:1b20:c:f011:3::b01f"
],
"features": {
"quic": {
"addr_in": [
"141.98.253.168",
"2a03:1b20:c:f011:3::c002",
"2a03:1b20:c:f011:3::c003",
"2a03:1b20:c:f011:3::c004",
"2a03:1b20:c:f011:3::c005",
"2a03:1b20:c:f011:3::c006",
"2a03:1b20:c:f011:3::c007",
"2a03:1b20:c:f011:3::c008",
"2a03:1b20:c:f011:3::c009",
"2a03:1b20:c:f011:3::c00a",
"2a03:1b20:c:f011:3::c00b",
"2a03:1b20:c:f011:3::c00c",
"2a03:1b20:c:f011:3::c00d",
"2a03:1b20:c:f011:3::c00e",
"2a03:1b20:c:f011:3::c00f",
"2a03:1b20:c:f011:3::c010",
"2a03:1b20:c:f011:3::c011",
"2a03:1b20:c:f011:3::c012",
"2a03:1b20:c:f011:3::c013",
"2a03:1b20:c:f011:3::c014",
"2a03:1b20:c:f011:3::c015",
"2a03:1b20:c:f011:3::c016",
"2a03:1b20:c:f011:3::c017",
"2a03:1b20:c:f011:3::c018",
"2a03:1b20:c:f011:3::c019",
"2a03:1b20:c:f011:3::c01a",
"2a03:1b20:c:f011:3::c01b",
"2a03:1b20:c:f011:3::c01c",
"2a03:1b20:c:f011:3::c01d",
"2a03:1b20:c:f011:3::c01e",
"2a03:1b20:c:f011:3::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "no-osl-wg-103.blockerad.eu"
}
}
},
{
"hostname": "no-svg-wg-001",
"location": "no-svg",
"active": true,
"owned": true,
"provider": "Blix",
"stboot": true,
"ipv4_addr_in": "194.127.199.2",
"include_in_country": true,
"weight": 300,
"public_key": "kduYoE/b1mA2Pjszx1CzE4Lktsdc2zsUU8Relul2m2U=",
"ipv6_addr_in": "2a02:20c8:4120::a01f",
"shadowsocks_extra_addr_in": [
"2a02:20c8:4120::b002",
"2a02:20c8:4120::b003",
"2a02:20c8:4120::b004",
"2a02:20c8:4120::b005",
"2a02:20c8:4120::b006",
"2a02:20c8:4120::b007",
"2a02:20c8:4120::b008",
"2a02:20c8:4120::b009",
"2a02:20c8:4120::b00a",
"2a02:20c8:4120::b00b",
"2a02:20c8:4120::b00c",
"2a02:20c8:4120::b00d",
"2a02:20c8:4120::b00e",
"2a02:20c8:4120::b00f",
"2a02:20c8:4120::b010",
"2a02:20c8:4120::b011",
"2a02:20c8:4120::b012",
"2a02:20c8:4120::b013",
"2a02:20c8:4120::b014",
"2a02:20c8:4120::b015",
"2a02:20c8:4120::b016",
"2a02:20c8:4120::b017",
"2a02:20c8:4120::b018",
"2a02:20c8:4120::b019",
"2a02:20c8:4120::b01a",
"2a02:20c8:4120::b01b",
"2a02:20c8:4120::b01c",
"2a02:20c8:4120::b01d",
"2a02:20c8:4120::b01e",
"2a02:20c8:4120::b01f"
]
},
{
"hostname": "no-svg-wg-002",
"location": "no-svg",
"active": true,
"owned": true,
"provider": "Blix",
"stboot": true,
"ipv4_addr_in": "194.127.199.31",
"include_in_country": true,
"weight": 300,
"public_key": "U9fbFesIIr2HotWdkfMpKyOEPk+RYtE2oYn3KoLmkj4=",
"ipv6_addr_in": "2a02:20c8:4120::a02f",
"shadowsocks_extra_addr_in": [
"2a02:20c8:4120::b102",
"2a02:20c8:4120::b103",
"2a02:20c8:4120::b104",
"2a02:20c8:4120::b105",
"2a02:20c8:4120::b106",
"2a02:20c8:4120::b107",
"2a02:20c8:4120::b108",
"2a02:20c8:4120::b109",
"2a02:20c8:4120::b10a",
"2a02:20c8:4120::b10b",
"2a02:20c8:4120::b10c",
"2a02:20c8:4120::b10d",
"2a02:20c8:4120::b10e",
"2a02:20c8:4120::b10f",
"2a02:20c8:4120::b110",
"2a02:20c8:4120::b111",
"2a02:20c8:4120::b112",
"2a02:20c8:4120::b113",
"2a02:20c8:4120::b114",
"2a02:20c8:4120::b115",
"2a02:20c8:4120::b116",
"2a02:20c8:4120::b117",
"2a02:20c8:4120::b118",
"2a02:20c8:4120::b119",
"2a02:20c8:4120::b11a",
"2a02:20c8:4120::b11b",
"2a02:20c8:4120::b11c",
"2a02:20c8:4120::b11d",
"2a02:20c8:4120::b11e",
"2a02:20c8:4120::b11f"
],
"features": {
"lwo": {}
}
},
{
"hostname": "no-svg-wg-003",
"location": "no-svg",
"active": true,
"owned": true,
"provider": "Blix",
"stboot": true,
"ipv4_addr_in": "194.127.199.62",
"include_in_country": true,
"weight": 300,
"public_key": "btc4mh3n9jVCW6yikw3cOPct0x3B5cDK+kKnvgCV0S0=",
"ipv6_addr_in": "2a02:20c8:4120::a03f",
"shadowsocks_extra_addr_in": [
"2a02:20c8:4120::b202",
"2a02:20c8:4120::b203",
"2a02:20c8:4120::b204",
"2a02:20c8:4120::b205",
"2a02:20c8:4120::b206",
"2a02:20c8:4120::b207",
"2a02:20c8:4120::b208",
"2a02:20c8:4120::b209",
"2a02:20c8:4120::b20a",
"2a02:20c8:4120::b20b",
"2a02:20c8:4120::b20c",
"2a02:20c8:4120::b20d",
"2a02:20c8:4120::b20e",
"2a02:20c8:4120::b20f",
"2a02:20c8:4120::b210",
"2a02:20c8:4120::b211",
"2a02:20c8:4120::b212",
"2a02:20c8:4120::b213",
"2a02:20c8:4120::b214",
"2a02:20c8:4120::b215",
"2a02:20c8:4120::b216",
"2a02:20c8:4120::b217",
"2a02:20c8:4120::b218",
"2a02:20c8:4120::b219",
"2a02:20c8:4120::b21a",
"2a02:20c8:4120::b21b",
"2a02:20c8:4120::b21c",
"2a02:20c8:4120::b21d",
"2a02:20c8:4120::b21e",
"2a02:20c8:4120::b21f"
]
},
{
"hostname": "no-svg-wg-004",
"location": "no-svg",
"active": true,
"owned": true,
"provider": "Blix",
"stboot": true,
"ipv4_addr_in": "194.127.199.93",
"include_in_country": true,
"weight": 300,
"public_key": "Fu98PLCZw/FTcQqyTy0vzaepkfxuSLAah7wnafGVO1g=",
"ipv6_addr_in": "2a02:20c8:4120::a04f",
"shadowsocks_extra_addr_in": [
"2a02:20c8:4120::b302",
"2a02:20c8:4120::b303",
"2a02:20c8:4120::b304",
"2a02:20c8:4120::b305",
"2a02:20c8:4120::b306",
"2a02:20c8:4120::b307",
"2a02:20c8:4120::b308",
"2a02:20c8:4120::b309",
"2a02:20c8:4120::b30a",
"2a02:20c8:4120::b30b",
"2a02:20c8:4120::b30c",
"2a02:20c8:4120::b30d",
"2a02:20c8:4120::b30e",
"2a02:20c8:4120::b30f",
"2a02:20c8:4120::b310",
"2a02:20c8:4120::b311",
"2a02:20c8:4120::b312",
"2a02:20c8:4120::b313",
"2a02:20c8:4120::b314",
"2a02:20c8:4120::b315",
"2a02:20c8:4120::b316",
"2a02:20c8:4120::b317",
"2a02:20c8:4120::b318",
"2a02:20c8:4120::b319",
"2a02:20c8:4120::b31a",
"2a02:20c8:4120::b31b",
"2a02:20c8:4120::b31c",
"2a02:20c8:4120::b31d",
"2a02:20c8:4120::b31e",
"2a02:20c8:4120::b31f"
],
"features": {
"lwo": {}
}
},
{
"hostname": "nz-akl-wg-301",
"location": "nz-akl",
"active": true,
"owned": false,
"provider": "hostuniversal",
"stboot": true,
"ipv4_addr_in": "103.75.11.50",
"include_in_country": true,
"weight": 100,
"public_key": "BOEOP01bcND1a0zvmOxRHPB/ObgjgPIzBJE5wbm7B0M=",
"ipv6_addr_in": "2404:f780:5:deb::f001"
},
{
"hostname": "nz-akl-wg-302",
"location": "nz-akl",
"active": true,
"owned": false,
"provider": "hostuniversal",
"stboot": true,
"ipv4_addr_in": "103.75.11.66",
"include_in_country": true,
"weight": 100,
"public_key": "80WGWgFP9q3eU16MuLJISB1fzAu2LM2heschmokVSVU=",
"ipv6_addr_in": "2404:f780:5:dec::c02f",
"features": {
"lwo": {}
}
},
{
"hostname": "nz-akl-wg-303",
"location": "nz-akl",
"active": true,
"owned": false,
"provider": "hostuniversal",
"stboot": true,
"ipv4_addr_in": "103.75.11.98",
"include_in_country": true,
"weight": 100,
"public_key": "1G7/wskBBlY77PXMV3sSAv4eCm5IPjxx99Wlfs58QSI=",
"ipv6_addr_in": "2404:f780:5:def::f201",
"features": {
"lwo": {}
}
},
{
"hostname": "pe-lim-wg-001",
"location": "pe-lim",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "95.173.223.130",
"include_in_country": true,
"weight": 100,
"public_key": "S4j4wshSstg9Au6ewFWr9vsZ8giovGPpKbKehXN8Nwc=",
"ipv6_addr_in": "2a02:6ea0:5500:1::f001",
"shadowsocks_extra_addr_in": [
"95.173.223.132"
]
},
{
"hostname": "pe-lim-wg-002",
"location": "pe-lim",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "95.173.223.159",
"include_in_country": true,
"weight": 100,
"public_key": "y7LsVrzYjeMLlTZmVUuuDkFvJp0kONC6+w+wP0gUIyo=",
"ipv6_addr_in": "2a02:6ea0:5500:2::f001",
"shadowsocks_extra_addr_in": [
"95.173.223.161"
]
},
{
"hostname": "ph-mnl-wg-001",
"location": "ph-mnl",
"active": true,
"owned": false,
"provider": "Zenlayer",
"stboot": true,
"ipv4_addr_in": "129.227.118.162",
"include_in_country": true,
"weight": 100,
"public_key": "hORxMf/YMmN2/8VWOnTCdgGzGfEyXUEQQ5EBfoCyFDM=",
"ipv6_addr_in": "2602:ffe4:c06:11e::f001",
"shadowsocks_extra_addr_in": [
"129.227.118.164"
]
},
{
"hostname": "ph-mnl-wg-002",
"location": "ph-mnl",
"active": true,
"owned": false,
"provider": "Zenlayer",
"stboot": true,
"ipv4_addr_in": "156.59.127.194",
"include_in_country": true,
"weight": 100,
"public_key": "TfNj4SJuIZzaXSxulpNzreDZXcX6GJJj+UYpqA2XMVE=",
"ipv6_addr_in": "2602:ffe4:c06:11e::f101",
"shadowsocks_extra_addr_in": [
"156.59.127.196"
]
},
{
"hostname": "pl-waw-wg-101",
"location": "pl-waw",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "45.134.212.66",
"include_in_country": true,
"weight": 100,
"public_key": "fO4beJGkKZxosCZz1qunktieuPyzPnEVKVQNhzanjnA=",
"ipv6_addr_in": "2a02:6ea0:ce08:1::f001"
},
{
"hostname": "pl-waw-wg-102",
"location": "pl-waw",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "45.134.212.79",
"include_in_country": true,
"weight": 100,
"public_key": "nJEWae9GebEY7yJONXQ1j4gbURV4QULjx388woAlbDs=",
"ipv6_addr_in": "2a02:6ea0:ce08:2::a06f",
"features": {
"lwo": {}
}
},
{
"hostname": "pl-waw-wg-103",
"location": "pl-waw",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "45.134.212.92",
"include_in_country": true,
"weight": 100,
"public_key": "07eUtSNhiJ9dQXBmUqFODj0OqhmbKQGbRikIq9f90jM=",
"ipv6_addr_in": "2a02:6ea0:ce08:3::a07f",
"features": {
"lwo": {}
}
},
{
"hostname": "pl-waw-wg-201",
"location": "pl-waw",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "45.128.38.226",
"include_in_country": true,
"weight": 100,
"public_key": "XwFAczY5LdogFwE9soDecXWqywSCDGuRyJhr/0psI00=",
"ipv6_addr_in": "2a0d:5600:13:67::a01f"
},
{
"hostname": "pl-waw-wg-202",
"location": "pl-waw",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.144.34",
"include_in_country": true,
"weight": 100,
"public_key": "nyfOkamv1ryTS62lsmyU96cqI0dtqek84DhyxWgAQGY=",
"ipv6_addr_in": "2a0d:5600:13:c47::a02f"
},
{
"hostname": "pt-lis-wg-201",
"location": "pt-lis",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "149.88.20.206",
"include_in_country": true,
"weight": 100,
"public_key": "JCAe7D/owe11Ii2rhpIKhGZvP/V1P1cVZwZAjpSRqmc=",
"ipv6_addr_in": "2a02:6ea0:fb01:1::f001",
"features": {
"lwo": {}
}
},
{
"hostname": "pt-lis-wg-202",
"location": "pt-lis",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "149.88.20.193",
"include_in_country": true,
"weight": 100,
"public_key": "5P4CQYQeSozk/3KQZh/kl7tUMFGgRB60Ttx6x2nh+F8=",
"ipv6_addr_in": "2a02:6ea0:fb01:2::f002",
"features": {
"lwo": {}
}
},
{
"hostname": "pt-lis-wg-301",
"location": "pt-lis",
"active": true,
"owned": false,
"provider": "HostRoyale",
"stboot": true,
"ipv4_addr_in": "185.92.210.195",
"include_in_country": true,
"weight": 100,
"public_key": "A2+7EIVBsq1jZlnx0AWb8xkoaTkkn8LRFwAl3Qb/xTc=",
"ipv6_addr_in": "2a06:3040:0:1410::f001"
},
{
"hostname": "pt-lis-wg-302",
"location": "pt-lis",
"active": true,
"owned": false,
"provider": "HostRoyale",
"stboot": true,
"ipv4_addr_in": "185.92.210.225",
"include_in_country": true,
"weight": 100,
"public_key": "4V8TnXninUL+vjZqXKUIFnBPOhjFEicdVHa5ZMZhSzc=",
"ipv6_addr_in": "2a06:3040:0:1410::f101",
"features": {
"lwo": {}
}
},
{
"hostname": "ro-buh-wg-001",
"location": "ro-buh",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.124.130",
"include_in_country": true,
"weight": 100,
"public_key": "xpKhRTf9JI269S2PujLbrJm1TwIe67HD5CLe+sP4tUU=",
"ipv6_addr_in": "2a04:9dc0:0:133::a01f"
},
{
"hostname": "ro-buh-wg-002",
"location": "ro-buh",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.124.194",
"include_in_country": true,
"weight": 100,
"public_key": "Ekc3+qU88FuMfkEMyLlgRqDYv+WHJvUsfOMI/C0ydE4=",
"ipv6_addr_in": "2a04:9dc0:0:135::f001"
},
{
"hostname": "rs-beg-wg-101",
"location": "rs-beg",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.193.2",
"include_in_country": true,
"weight": 100,
"public_key": "Orrce1127WpljZa+xKbF21zJkJ9wM1M3VJ5GJ/UsIDU=",
"ipv6_addr_in": "2001:ac8:7d:37::a01f"
},
{
"hostname": "rs-beg-wg-102",
"location": "rs-beg",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.193.66",
"include_in_country": true,
"weight": 100,
"public_key": "35lawt+YUx10ELTFhZhg4/xzXRmjxCl/j1O4RK5d60M=",
"ipv6_addr_in": "2001:ac8:7d:38::a02f"
},
{
"hostname": "se-got-wg-001",
"location": "se-got",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "185.213.154.66",
"include_in_country": true,
"weight": 1,
"public_key": "5JMPeO7gXIbR5CnUa/NPNK4L5GqUnreF0/Bozai4pl4=",
"ipv6_addr_in": "2a03:1b20:5:f011:31::a03f",
"shadowsocks_extra_addr_in": [
"185.213.154.238",
"2a03:1b20:5:f011:31::b002",
"2a03:1b20:5:f011:31::b003",
"2a03:1b20:5:f011:31::b004",
"2a03:1b20:5:f011:31::b005",
"2a03:1b20:5:f011:31::b006",
"2a03:1b20:5:f011:31::b007",
"2a03:1b20:5:f011:31::b008",
"2a03:1b20:5:f011:31::b009",
"2a03:1b20:5:f011:31::b00a",
"2a03:1b20:5:f011:31::b00b",
"2a03:1b20:5:f011:31::b00c",
"2a03:1b20:5:f011:31::b00d",
"2a03:1b20:5:f011:31::b00e",
"2a03:1b20:5:f011:31::b00f",
"2a03:1b20:5:f011:31::b010",
"2a03:1b20:5:f011:31::b011",
"2a03:1b20:5:f011:31::b012",
"2a03:1b20:5:f011:31::b013",
"2a03:1b20:5:f011:31::b014",
"2a03:1b20:5:f011:31::b015",
"2a03:1b20:5:f011:31::b016",
"2a03:1b20:5:f011:31::b017",
"2a03:1b20:5:f011:31::b018",
"2a03:1b20:5:f011:31::b019",
"2a03:1b20:5:f011:31::b01a",
"2a03:1b20:5:f011:31::b01b",
"2a03:1b20:5:f011:31::b01c",
"2a03:1b20:5:f011:31::b01d",
"2a03:1b20:5:f011:31::b01e",
"2a03:1b20:5:f011:31::b01f"
],
"features": {
"lwo": {}
}
},
{
"hostname": "se-got-wg-002",
"location": "se-got",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "185.213.154.67",
"include_in_country": true,
"weight": 1,
"public_key": "AtvE5KdPeQtOcE2QyXaPt9eQoBV3GBxzimQ2FIuGQ2U=",
"ipv6_addr_in": "2a03:1b20:5:f011::a05f",
"shadowsocks_extra_addr_in": [
"2a03:1b20:5:f011:31::b202",
"2a03:1b20:5:f011:31::b203",
"2a03:1b20:5:f011:31::b204",
"2a03:1b20:5:f011:31::b205",
"2a03:1b20:5:f011:31::b206",
"2a03:1b20:5:f011:31::b207",
"2a03:1b20:5:f011:31::b208",
"2a03:1b20:5:f011:31::b209",
"2a03:1b20:5:f011:31::b20a",
"2a03:1b20:5:f011:31::b20b",
"2a03:1b20:5:f011:31::b20c",
"2a03:1b20:5:f011:31::b20d",
"2a03:1b20:5:f011:31::b20e",
"2a03:1b20:5:f011:31::b20f",
"2a03:1b20:5:f011:31::b210",
"2a03:1b20:5:f011:31::b211",
"2a03:1b20:5:f011:31::b212",
"2a03:1b20:5:f011:31::b213",
"2a03:1b20:5:f011:31::b214",
"2a03:1b20:5:f011:31::b215",
"2a03:1b20:5:f011:31::b216",
"2a03:1b20:5:f011:31::b217",
"2a03:1b20:5:f011:31::b218",
"2a03:1b20:5:f011:31::b219",
"2a03:1b20:5:f011:31::b21a",
"2a03:1b20:5:f011:31::b21b",
"2a03:1b20:5:f011:31::b21c",
"2a03:1b20:5:f011:31::b21d",
"2a03:1b20:5:f011:31::b21e",
"2a03:1b20:5:f011:31::b21f"
],
"features": {
"lwo": {}
}
},
{
"hostname": "se-got-wg-003",
"location": "se-got",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "185.213.154.68",
"include_in_country": true,
"weight": 100,
"public_key": "BLNHNoGO88LjV/wDBa7CUUwUzPq/fO2UwcGLy56hKy4=",
"ipv6_addr_in": "2a03:1b20:5:f011::a09f",
"shadowsocks_extra_addr_in": [
"2a03:1b20:5:f011:3:b:0:1",
"2a03:1b20:5:f011:3:b:0:2",
"2a03:1b20:5:f011:3:b:0:3",
"2a03:1b20:5:f011:3:b:0:4",
"2a03:1b20:5:f011:3:b:0:5",
"2a03:1b20:5:f011:3:b:0:6",
"2a03:1b20:5:f011:3:b:0:7",
"2a03:1b20:5:f011:3:b:0:8",
"2a03:1b20:5:f011:3:b:0:9",
"2a03:1b20:5:f011:3:b:0:a",
"2a03:1b20:5:f011:3:b:0:b",
"2a03:1b20:5:f011:3:b:0:e",
"2a03:1b20:5:f011:3:b:0:d",
"2a03:1b20:5:f011:3:b:0:e",
"2a03:1b20:5:f011:3:b:0:f",
"2a03:1b20:5:f011:3:b:0:10",
"2a03:1b20:5:f011:3:b:0:11",
"2a03:1b20:5:f011:3:b:0:12",
"2a03:1b20:5:f011:3:b:0:13",
"2a03:1b20:5:f011:3:b:0:14",
"2a03:1b20:5:f011:3:b:0:15",
"2a03:1b20:5:f011:3:b:0:16",
"2a03:1b20:5:f011:3:b:0:17",
"2a03:1b20:5:f011:3:b:0:18",
"2a03:1b20:5:f011:3:b:0:19",
"2a03:1b20:5:f011:3:b:0:1a",
"2a03:1b20:5:f011:3:b:0:1b",
"2a03:1b20:5:f011:3:b:0:1c",
"2a03:1b20:5:f011:3:b:0:1d",
"2a03:1b20:5:f011:3:b:0:1e",
"2a03:1b20:5:f011:3:b:0:1f",
"2a03:1b20:5:f011:3:b:0:20",
"2a03:1b20:5:f011:3:b:0:21",
"2a03:1b20:5:f011:3:b:0:22",
"2a03:1b20:5:f011:3:b:0:23",
"2a03:1b20:5:f011:3:b:0:24",
"2a03:1b20:5:f011:3:b:0:25",
"2a03:1b20:5:f011:3:b:0:26",
"2a03:1b20:5:f011:3:b:0:27",
"2a03:1b20:5:f011:3:b:0:28",
"2a03:1b20:5:f011:3:b:0:29",
"2a03:1b20:5:f011:3:b:0:2a",
"2a03:1b20:5:f011:3:b:0:2b",
"2a03:1b20:5:f011:3:b:0:2c",
"2a03:1b20:5:f011:3:b:0:2d",
"2a03:1b20:5:f011:3:b:0:2e",
"2a03:1b20:5:f011:3:b:0:2f",
"2a03:1b20:5:f011:3:b:0:30",
"2a03:1b20:5:f011:3:b:0:31",
"2a03:1b20:5:f011:3:b:0:32",
"2a03:1b20:5:f011:3:b:0:33",
"2a03:1b20:5:f011:3:b:0:34",
"2a03:1b20:5:f011:3:b:0:35",
"2a03:1b20:5:f011:3:b:0:36",
"2a03:1b20:5:f011:3:b:0:37",
"2a03:1b20:5:f011:3:b:0:38",
"2a03:1b20:5:f011:3:b:0:39",
"2a03:1b20:5:f011:3:b:0:3a",
"2a03:1b20:5:f011:3:b:0:3b",
"2a03:1b20:5:f011:3:b:0:3c",
"2a03:1b20:5:f011:3:b:0:3d",
"2a03:1b20:5:f011:3:b:0:3e",
"2a03:1b20:5:f011:3:b:0:3f"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"2a03:1b20:5:f011:3:c:0:1",
"2a03:1b20:5:f011:3:c:0:2",
"2a03:1b20:5:f011:3:c:0:3",
"2a03:1b20:5:f011:3:c:0:4",
"2a03:1b20:5:f011:3:c:0:5",
"2a03:1b20:5:f011:3:c:0:6",
"2a03:1b20:5:f011:3:c:0:7",
"2a03:1b20:5:f011:3:c:0:8",
"2a03:1b20:5:f011:3:c:0:9",
"2a03:1b20:5:f011:3:c:0:a",
"2a03:1b20:5:f011:3:c:0:b",
"2a03:1b20:5:f011:3:c:0:e",
"2a03:1b20:5:f011:3:c:0:d",
"2a03:1b20:5:f011:3:c:0:e",
"2a03:1b20:5:f011:3:c:0:f",
"2a03:1b20:5:f011:3:c:0:10",
"2a03:1b20:5:f011:3:c:0:11",
"2a03:1b20:5:f011:3:c:0:12",
"2a03:1b20:5:f011:3:c:0:13",
"2a03:1b20:5:f011:3:c:0:14",
"2a03:1b20:5:f011:3:c:0:15",
"2a03:1b20:5:f011:3:c:0:16",
"2a03:1b20:5:f011:3:c:0:17",
"2a03:1b20:5:f011:3:c:0:18",
"2a03:1b20:5:f011:3:c:0:19",
"2a03:1b20:5:f011:3:c:0:1a",
"2a03:1b20:5:f011:3:c:0:1b",
"2a03:1b20:5:f011:3:c:0:1c",
"2a03:1b20:5:f011:3:c:0:1d",
"2a03:1b20:5:f011:3:c:0:1e",
"2a03:1b20:5:f011:3:c:0:1f",
"2a03:1b20:5:f011:3:c:0:20",
"2a03:1b20:5:f011:3:c:0:21",
"2a03:1b20:5:f011:3:c:0:22",
"2a03:1b20:5:f011:3:c:0:23",
"2a03:1b20:5:f011:3:c:0:24",
"2a03:1b20:5:f011:3:c:0:25",
"2a03:1b20:5:f011:3:c:0:26",
"2a03:1b20:5:f011:3:c:0:27",
"2a03:1b20:5:f011:3:c:0:28",
"2a03:1b20:5:f011:3:c:0:29",
"2a03:1b20:5:f011:3:c:0:2a",
"2a03:1b20:5:f011:3:c:0:2b",
"2a03:1b20:5:f011:3:c:0:2c",
"2a03:1b20:5:f011:3:c:0:2d",
"2a03:1b20:5:f011:3:c:0:2e",
"2a03:1b20:5:f011:3:c:0:2f",
"2a03:1b20:5:f011:3:c:0:30",
"2a03:1b20:5:f011:3:c:0:31",
"2a03:1b20:5:f011:3:c:0:32",
"2a03:1b20:5:f011:3:c:0:33",
"2a03:1b20:5:f011:3:c:0:34",
"2a03:1b20:5:f011:3:c:0:35",
"2a03:1b20:5:f011:3:c:0:36",
"2a03:1b20:5:f011:3:c:0:37",
"2a03:1b20:5:f011:3:c:0:38",
"2a03:1b20:5:f011:3:c:0:39",
"2a03:1b20:5:f011:3:c:0:3a",
"2a03:1b20:5:f011:3:c:0:3b",
"2a03:1b20:5:f011:3:c:0:3c",
"2a03:1b20:5:f011:3:c:0:3d",
"2a03:1b20:5:f011:3:c:0:3e",
"2a03:1b20:5:f011:3:c:0:3f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "se-got-wg-003.blockerad.eu"
}
}
},
{
"hostname": "se-got-wg-004",
"location": "se-got",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "185.213.154.69",
"include_in_country": true,
"weight": 100,
"public_key": "veGD6/aEY6sMfN3Ls7YWPmNgu3AheO7nQqsFT47YSws=",
"ipv6_addr_in": "2a03:1b20:5:f011::a10f",
"shadowsocks_extra_addr_in": [
"2a03:1b20:5:f011:31::b402",
"2a03:1b20:5:f011:31::b403",
"2a03:1b20:5:f011:31::b404",
"2a03:1b20:5:f011:31::b405",
"2a03:1b20:5:f011:31::b406",
"2a03:1b20:5:f011:31::b407",
"2a03:1b20:5:f011:31::b408",
"2a03:1b20:5:f011:31::b409",
"2a03:1b20:5:f011:31::b40a",
"2a03:1b20:5:f011:31::b40b",
"2a03:1b20:5:f011:31::b40c",
"2a03:1b20:5:f011:31::b40d",
"2a03:1b20:5:f011:31::b40e",
"2a03:1b20:5:f011:31::b40f",
"2a03:1b20:5:f011:31::b410",
"2a03:1b20:5:f011:31::b411",
"2a03:1b20:5:f011:31::b412",
"2a03:1b20:5:f011:31::b413",
"2a03:1b20:5:f011:31::b414",
"2a03:1b20:5:f011:31::b415",
"2a03:1b20:5:f011:31::b416",
"2a03:1b20:5:f011:31::b417",
"2a03:1b20:5:f011:31::b418",
"2a03:1b20:5:f011:31::b419",
"2a03:1b20:5:f011:31::b41a",
"2a03:1b20:5:f011:31::b41b",
"2a03:1b20:5:f011:31::b41c",
"2a03:1b20:5:f011:31::b41d",
"2a03:1b20:5:f011:31::b41e",
"2a03:1b20:5:f011:31::b41f"
],
"features": {
"lwo": {}
}
},
{
"hostname": "se-got-wg-005",
"location": "se-got",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "185.209.199.2",
"include_in_country": true,
"weight": 100,
"public_key": "x4h55uXoIIKUqKjjm6PzNiZlzLjxjuAIKzvgU9UjOGw=",
"ipv6_addr_in": "2a03:1b20:5:f011:5::f001",
"features": {
"lwo": {},
"quic": {
"addr_in": [
"185.209.199.6",
"2a03:1b20:5:f011:5::f00a"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "se-got-wg-005.blockerad.eu"
}
}
},
{
"hostname": "se-got-wg-006",
"location": "se-got",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "185.209.199.7",
"include_in_country": true,
"weight": 100,
"public_key": "dcSpHioI+TY37dbZcviFA/sxSUqmpECXRZIapwR8pVg=",
"ipv6_addr_in": "2a03:1b20:5:f011:6::f001",
"daita": true,
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"185.209.199.11",
"2a03:1b20:5:f011:6::f00a"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "se-got-wg-006.blockerad.eu"
}
}
},
{
"hostname": "se-got-wg-007",
"location": "se-got",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "185.209.199.12",
"include_in_country": true,
"weight": 100,
"public_key": "ywfkKYdoVAnjsSYW145ACtrw3DV8xTzFS1hlIO7QRD4=",
"ipv6_addr_in": "2a03:1b20:5:f011:7::f001",
"features": {
"lwo": {},
"quic": {
"addr_in": [
"185.209.199.16",
"2a03:1b20:5:f011:7::f00a"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "se-got-wg-007.blockerad.eu"
}
}
},
{
"hostname": "se-got-wg-008",
"location": "se-got",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "185.209.199.17",
"include_in_country": true,
"weight": 100,
"public_key": "Vh3Y2LsBG1yN4kDeebOr3J6dFooGJIBTftzVqlWhiD4=",
"ipv6_addr_in": "2a03:1b20:5:f011:8::f001",
"features": {
"lwo": {},
"quic": {
"addr_in": [
"185.209.199.21",
"2a03:1b20:5:f011:8::f00a"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "se-got-wg-008.blockerad.eu"
}
}
},
{
"hostname": "se-got-wg-101",
"location": "se-got",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "185.213.154.70",
"include_in_country": true,
"weight": 100,
"public_key": "B8UVAeNkAW4NiGHd1lpl933Drh4y7pMqpXJpH0SrGjQ=",
"ipv6_addr_in": "2a03:1b20:5:f011::aaaf",
"features": {
"lwo": {}
}
},
{
"hostname": "se-mma-wg-001",
"location": "se-mma",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "193.138.218.220",
"include_in_country": true,
"weight": 100,
"public_key": "Qn1QaXYTJJSmJSMw18CGdnFiVM0/Gj/15OdkxbXCSG0=",
"ipv6_addr_in": "2a03:1b20:1:f410::fa01",
"shadowsocks_extra_addr_in": [
"2a03:1b20:1:f410::ba02",
"2a03:1b20:1:f410::ba03",
"2a03:1b20:1:f410::ba04",
"2a03:1b20:1:f410::ba05",
"2a03:1b20:1:f410::ba06",
"2a03:1b20:1:f410::ba07",
"2a03:1b20:1:f410::ba08",
"2a03:1b20:1:f410::ba09",
"2a03:1b20:1:f410::ba0a",
"2a03:1b20:1:f410::ba0b",
"2a03:1b20:1:f410::ba0c",
"2a03:1b20:1:f410::ba0d",
"2a03:1b20:1:f410::ba0e",
"2a03:1b20:1:f410::ba0f",
"2a03:1b20:1:f410::ba10",
"2a03:1b20:1:f410::ba11",
"2a03:1b20:1:f410::ba12",
"2a03:1b20:1:f410::ba13",
"2a03:1b20:1:f410::ba14",
"2a03:1b20:1:f410::ba15",
"2a03:1b20:1:f410::ba16",
"2a03:1b20:1:f410::ba17",
"2a03:1b20:1:f410::ba18",
"2a03:1b20:1:f410::ba19",
"2a03:1b20:1:f410::ba1a",
"2a03:1b20:1:f410::ba1b",
"2a03:1b20:1:f410::ba1c",
"2a03:1b20:1:f410::ba1d",
"2a03:1b20:1:f410::ba1e",
"2a03:1b20:1:f410::ba1f"
]
},
{
"hostname": "se-mma-wg-002",
"location": "se-mma",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "193.138.218.80",
"include_in_country": true,
"weight": 100,
"public_key": "5y66WShsFXqM5K7/4CPEGCWfk7PQyNhVBT2ILjbGm2I=",
"ipv6_addr_in": "2a03:1b20:1:f410::a15f",
"shadowsocks_extra_addr_in": [
"2a03:1b20:1:f410::bb02",
"2a03:1b20:1:f410::bb03",
"2a03:1b20:1:f410::bb04",
"2a03:1b20:1:f410::bb05",
"2a03:1b20:1:f410::bb06",
"2a03:1b20:1:f410::bb07",
"2a03:1b20:1:f410::bb08",
"2a03:1b20:1:f410::bb09",
"2a03:1b20:1:f410::bb0a",
"2a03:1b20:1:f410::bb0b",
"2a03:1b20:1:f410::bb0c",
"2a03:1b20:1:f410::bb0d",
"2a03:1b20:1:f410::bb0e",
"2a03:1b20:1:f410::bb0f",
"2a03:1b20:1:f410::bb10",
"2a03:1b20:1:f410::bb11",
"2a03:1b20:1:f410::bb12",
"2a03:1b20:1:f410::bb13",
"2a03:1b20:1:f410::bb14",
"2a03:1b20:1:f410::bb15",
"2a03:1b20:1:f410::bb16",
"2a03:1b20:1:f410::bb17",
"2a03:1b20:1:f410::bb18",
"2a03:1b20:1:f410::bb19",
"2a03:1b20:1:f410::bb1a",
"2a03:1b20:1:f410::bb1b",
"2a03:1b20:1:f410::bb1c",
"2a03:1b20:1:f410::bb1d",
"2a03:1b20:1:f410::bb1e",
"2a03:1b20:1:f410::bb1f"
]
},
{
"hostname": "se-mma-wg-003",
"location": "se-mma",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "193.138.218.83",
"include_in_country": true,
"weight": 100,
"public_key": "fZFAcd8vqWOBpRqlXifsjzGf16gMTg2GuwKyZtkG6UU=",
"ipv6_addr_in": "2a03:1b20:1:f410::a18f",
"shadowsocks_extra_addr_in": [
"2a03:1b20:1:f410::bc02",
"2a03:1b20:1:f410::bc03",
"2a03:1b20:1:f410::bc04",
"2a03:1b20:1:f410::bc05",
"2a03:1b20:1:f410::bc06",
"2a03:1b20:1:f410::bc07",
"2a03:1b20:1:f410::bc08",
"2a03:1b20:1:f410::bc09",
"2a03:1b20:1:f410::bc0a",
"2a03:1b20:1:f410::bc0b",
"2a03:1b20:1:f410::bc0c",
"2a03:1b20:1:f410::bc0d",
"2a03:1b20:1:f410::bc0e",
"2a03:1b20:1:f410::bc0f",
"2a03:1b20:1:f410::bc10",
"2a03:1b20:1:f410::bc11",
"2a03:1b20:1:f410::bc12",
"2a03:1b20:1:f410::bc13",
"2a03:1b20:1:f410::bc14",
"2a03:1b20:1:f410::bc15",
"2a03:1b20:1:f410::bc16",
"2a03:1b20:1:f410::bc17",
"2a03:1b20:1:f410::bc18",
"2a03:1b20:1:f410::bc19",
"2a03:1b20:1:f410::bc1a",
"2a03:1b20:1:f410::bc1b",
"2a03:1b20:1:f410::bc1c",
"2a03:1b20:1:f410::bc1d",
"2a03:1b20:1:f410::bc1e",
"2a03:1b20:1:f410::bc1f"
]
},
{
"hostname": "se-mma-wg-004",
"location": "se-mma",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "193.138.218.130",
"include_in_country": false,
"weight": 100,
"public_key": "m4jnogFbACz7LByjo++8z5+1WV0BuR1T7E1OWA+n8h0=",
"ipv6_addr_in": "2a03:1b20:1:f410:40::a04f"
},
{
"hostname": "se-mma-wg-005",
"location": "se-mma",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "193.138.218.82",
"include_in_country": true,
"weight": 100,
"public_key": "qnJrQEf2JiDHMnMWFFxWz8I9NREockylVgYVE95s72s=",
"ipv6_addr_in": "2a03:1b20:1:f410::a17f",
"shadowsocks_extra_addr_in": [
"2a03:1b20:1:f410::be02",
"2a03:1b20:1:f410::be03",
"2a03:1b20:1:f410::be04",
"2a03:1b20:1:f410::be05",
"2a03:1b20:1:f410::be06",
"2a03:1b20:1:f410::be07",
"2a03:1b20:1:f410::be08",
"2a03:1b20:1:f410::be09",
"2a03:1b20:1:f410::be0a",
"2a03:1b20:1:f410::be0b",
"2a03:1b20:1:f410::be0c",
"2a03:1b20:1:f410::be0d",
"2a03:1b20:1:f410::be0e",
"2a03:1b20:1:f410::be0f",
"2a03:1b20:1:f410::be10",
"2a03:1b20:1:f410::be11",
"2a03:1b20:1:f410::be12",
"2a03:1b20:1:f410::be13",
"2a03:1b20:1:f410::be14",
"2a03:1b20:1:f410::be15",
"2a03:1b20:1:f410::be16",
"2a03:1b20:1:f410::be17",
"2a03:1b20:1:f410::be18",
"2a03:1b20:1:f410::be19",
"2a03:1b20:1:f410::be1a",
"2a03:1b20:1:f410::be1b",
"2a03:1b20:1:f410::be1c",
"2a03:1b20:1:f410::be1d",
"2a03:1b20:1:f410::be1e",
"2a03:1b20:1:f410::be1f"
],
"features": {
"lwo": {}
}
},
{
"hostname": "se-mma-wg-011",
"location": "se-mma",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "141.98.255.94",
"include_in_country": true,
"weight": 2,
"public_key": "vclzw8ytARhkEqw4cLUJPC3REvMZqWsO+7TYD/U2UVk=",
"ipv6_addr_in": "2a03:1b20:1:f410::f101",
"shadowsocks_extra_addr_in": [
"141.98.255.96"
],
"features": {
"lwo": {}
}
},
{
"hostname": "se-mma-wg-012",
"location": "se-mma",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "141.98.255.97",
"include_in_country": true,
"weight": 2,
"public_key": "aPcHJj3I1oISU8cwLz2Uyq4ctUOXdTpuS96aW89snUs=",
"ipv6_addr_in": "2a03:1b20:1:f410::f201",
"shadowsocks_extra_addr_in": [
"141.98.255.99"
],
"features": {
"lwo": {}
}
},
{
"hostname": "se-mma-wg-101",
"location": "se-mma",
"active": false,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "45.83.220.68",
"include_in_country": true,
"weight": 200,
"public_key": "7ncbaCb+9za3jnXlR95I6dJBkwL1ABB5i4ndFUesYxE=",
"ipv6_addr_in": "2a03:1b20:1:e011::a21f",
"shadowsocks_extra_addr_in": [
"2a03:1b20:1:e011::b002",
"2a03:1b20:1:e011::b003",
"2a03:1b20:1:e011::b004",
"2a03:1b20:1:e011::b005",
"2a03:1b20:1:e011::b006",
"2a03:1b20:1:e011::b007",
"2a03:1b20:1:e011::b008",
"2a03:1b20:1:e011::b009",
"2a03:1b20:1:e011::b00a",
"2a03:1b20:1:e011::b00b",
"2a03:1b20:1:e011::b00c",
"2a03:1b20:1:e011::b00d",
"2a03:1b20:1:e011::b00e",
"2a03:1b20:1:e011::b00f",
"2a03:1b20:1:e011::b010",
"2a03:1b20:1:e011::b011",
"2a03:1b20:1:e011::b012",
"2a03:1b20:1:e011::b013",
"2a03:1b20:1:e011::b014",
"2a03:1b20:1:e011::b015",
"2a03:1b20:1:e011::b016",
"2a03:1b20:1:e011::b017",
"2a03:1b20:1:e011::b018",
"2a03:1b20:1:e011::b019",
"2a03:1b20:1:e011::b01a",
"2a03:1b20:1:e011::b01b",
"2a03:1b20:1:e011::b01c",
"2a03:1b20:1:e011::b01d",
"2a03:1b20:1:e011::b01e",
"2a03:1b20:1:e011::b01f"
],
"features": {
"lwo": {}
}
},
{
"hostname": "se-mma-wg-102",
"location": "se-mma",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "45.83.220.69",
"include_in_country": true,
"weight": 200,
"public_key": "cwglRdgLQ4gMG36TIYlc5OIemLNrYs4UM1KTc8mnzxk=",
"ipv6_addr_in": "2a03:1b20:1:e011::a22f",
"shadowsocks_extra_addr_in": [
"2a03:1b20:1:e011::b202",
"2a03:1b20:1:e011::b203",
"2a03:1b20:1:e011::b204",
"2a03:1b20:1:e011::b205",
"2a03:1b20:1:e011::b206",
"2a03:1b20:1:e011::b207",
"2a03:1b20:1:e011::b208",
"2a03:1b20:1:e011::b209",
"2a03:1b20:1:e011::b20a",
"2a03:1b20:1:e011::b20b",
"2a03:1b20:1:e011::b20c",
"2a03:1b20:1:e011::b20d",
"2a03:1b20:1:e011::b20e",
"2a03:1b20:1:e011::b20f",
"2a03:1b20:1:e011::b210",
"2a03:1b20:1:e011::b211",
"2a03:1b20:1:e011::b212",
"2a03:1b20:1:e011::b213",
"2a03:1b20:1:e011::b214",
"2a03:1b20:1:e011::b215",
"2a03:1b20:1:e011::b216",
"2a03:1b20:1:e011::b217",
"2a03:1b20:1:e011::b218",
"2a03:1b20:1:e011::b219",
"2a03:1b20:1:e011::b21a",
"2a03:1b20:1:e011::b21b",
"2a03:1b20:1:e011::b21c",
"2a03:1b20:1:e011::b21d",
"2a03:1b20:1:e011::b21e",
"2a03:1b20:1:e011::b21f"
],
"features": {
"lwo": {}
}
},
{
"hostname": "se-mma-wg-103",
"location": "se-mma",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "45.83.220.70",
"include_in_country": true,
"weight": 100,
"public_key": "XscA5gebj51nmhAr6o+aUCnMHWGjbS1Gvvd0tuLRiFE=",
"ipv6_addr_in": "2a03:1b20:1:e011::a23f",
"shadowsocks_extra_addr_in": [
"2a03:1b20:1:e011::b302",
"2a03:1b20:1:e011::b303",
"2a03:1b20:1:e011::b304",
"2a03:1b20:1:e011::b305",
"2a03:1b20:1:e011::b306",
"2a03:1b20:1:e011::b307",
"2a03:1b20:1:e011::b308",
"2a03:1b20:1:e011::b309",
"2a03:1b20:1:e011::b30a",
"2a03:1b20:1:e011::b30b",
"2a03:1b20:1:e011::b30c",
"2a03:1b20:1:e011::b30d",
"2a03:1b20:1:e011::b30e",
"2a03:1b20:1:e011::b30f",
"2a03:1b20:1:e011::b310",
"2a03:1b20:1:e011::b311",
"2a03:1b20:1:e011::b312",
"2a03:1b20:1:e011::b313",
"2a03:1b20:1:e011::b314",
"2a03:1b20:1:e011::b315",
"2a03:1b20:1:e011::b316",
"2a03:1b20:1:e011::b317",
"2a03:1b20:1:e011::b318",
"2a03:1b20:1:e011::b319",
"2a03:1b20:1:e011::b31a",
"2a03:1b20:1:e011::b31b",
"2a03:1b20:1:e011::b31c",
"2a03:1b20:1:e011::b31d",
"2a03:1b20:1:e011::b31e",
"2a03:1b20:1:e011::b31f"
]
},
{
"hostname": "se-mma-wg-111",
"location": "se-mma",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "45.129.59.19",
"include_in_country": true,
"weight": 2,
"public_key": "vi0PPk0ZCDvDMCSQD0mctmPFFH7NiawLxJquyPIGwAY=",
"ipv6_addr_in": "2a03:1b20:1:e011::f701",
"daita": true,
"shadowsocks_extra_addr_in": [
"45.129.59.29",
"2a03:1b20:1:e011::b702",
"2a03:1b20:1:e011::b703",
"2a03:1b20:1:e011::b704",
"2a03:1b20:1:e011::b705",
"2a03:1b20:1:e011::b706",
"2a03:1b20:1:e011::b707",
"2a03:1b20:1:e011::b708",
"2a03:1b20:1:e011::b709",
"2a03:1b20:1:e011::b70a",
"2a03:1b20:1:e011::b70b",
"2a03:1b20:1:e011::b70c",
"2a03:1b20:1:e011::b70d",
"2a03:1b20:1:e011::b70e",
"2a03:1b20:1:e011::b70f",
"2a03:1b20:1:e011::b710",
"2a03:1b20:1:e011::b711",
"2a03:1b20:1:e011::b712",
"2a03:1b20:1:e011::b713",
"2a03:1b20:1:e011::b714",
"2a03:1b20:1:e011::b715",
"2a03:1b20:1:e011::b716",
"2a03:1b20:1:e011::b717",
"2a03:1b20:1:e011::b718",
"2a03:1b20:1:e011::b719",
"2a03:1b20:1:e011::b71a",
"2a03:1b20:1:e011::b71b",
"2a03:1b20:1:e011::b71c",
"2a03:1b20:1:e011::b71d",
"2a03:1b20:1:e011::b71e",
"2a03:1b20:1:e011::b71f"
],
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"45.129.59.25",
"2a03:1b20:1:e011::c702",
"2a03:1b20:1:e011::c703",
"2a03:1b20:1:e011::c704",
"2a03:1b20:1:e011::c705",
"2a03:1b20:1:e011::c706",
"2a03:1b20:1:e011::c707",
"2a03:1b20:1:e011::c708",
"2a03:1b20:1:e011::c709",
"2a03:1b20:1:e011::c70a",
"2a03:1b20:1:e011::c70b",
"2a03:1b20:1:e011::c70c",
"2a03:1b20:1:e011::c70d",
"2a03:1b20:1:e011::c70e",
"2a03:1b20:1:e011::c70f",
"2a03:1b20:1:e011::c710",
"2a03:1b20:1:e011::c711",
"2a03:1b20:1:e011::c712",
"2a03:1b20:1:e011::c713",
"2a03:1b20:1:e011::c714",
"2a03:1b20:1:e011::c715",
"2a03:1b20:1:e011::c716",
"2a03:1b20:1:e011::c717",
"2a03:1b20:1:e011::c718",
"2a03:1b20:1:e011::c719",
"2a03:1b20:1:e011::c71a",
"2a03:1b20:1:e011::c71b",
"2a03:1b20:1:e011::c71c",
"2a03:1b20:1:e011::c71d",
"2a03:1b20:1:e011::c71e",
"2a03:1b20:1:e011::c71f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "se-mma-wg-111.blockerad.eu"
}
}
},
{
"hostname": "se-mma-wg-112",
"location": "se-mma",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "45.129.59.129",
"include_in_country": true,
"weight": 2,
"public_key": "bysuFAwy+jwl5IePhY06/j7ByWDsAtU5pKPo44k4qEY=",
"ipv6_addr_in": "2a03:1b20:1:e011::f601",
"daita": true,
"shadowsocks_extra_addr_in": [
"45.129.59.139",
"2a03:1b20:1:e011::b602",
"2a03:1b20:1:e011::b603",
"2a03:1b20:1:e011::b604",
"2a03:1b20:1:e011::b605",
"2a03:1b20:1:e011::b606",
"2a03:1b20:1:e011::b607",
"2a03:1b20:1:e011::b608",
"2a03:1b20:1:e011::b609",
"2a03:1b20:1:e011::b60a",
"2a03:1b20:1:e011::b60b",
"2a03:1b20:1:e011::b60c",
"2a03:1b20:1:e011::b60d",
"2a03:1b20:1:e011::b60e",
"2a03:1b20:1:e011::b60f",
"2a03:1b20:1:e011::b610",
"2a03:1b20:1:e011::b611",
"2a03:1b20:1:e011::b612",
"2a03:1b20:1:e011::b613",
"2a03:1b20:1:e011::b614",
"2a03:1b20:1:e011::b615",
"2a03:1b20:1:e011::b616",
"2a03:1b20:1:e011::b617",
"2a03:1b20:1:e011::b618",
"2a03:1b20:1:e011::b619",
"2a03:1b20:1:e011::b61a",
"2a03:1b20:1:e011::b61b",
"2a03:1b20:1:e011::b61c",
"2a03:1b20:1:e011::b61d",
"2a03:1b20:1:e011::b61e",
"2a03:1b20:1:e011::b61f"
],
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"45.129.59.135",
"2a03:1b20:1:e011::c602",
"2a03:1b20:1:e011::c603",
"2a03:1b20:1:e011::c604",
"2a03:1b20:1:e011::c605",
"2a03:1b20:1:e011::c606",
"2a03:1b20:1:e011::c607",
"2a03:1b20:1:e011::c608",
"2a03:1b20:1:e011::c609",
"2a03:1b20:1:e011::c60a",
"2a03:1b20:1:e011::c60b",
"2a03:1b20:1:e011::c60c",
"2a03:1b20:1:e011::c60d",
"2a03:1b20:1:e011::c60e",
"2a03:1b20:1:e011::c60f",
"2a03:1b20:1:e011::c610",
"2a03:1b20:1:e011::c611",
"2a03:1b20:1:e011::c612",
"2a03:1b20:1:e011::c613",
"2a03:1b20:1:e011::c614",
"2a03:1b20:1:e011::c615",
"2a03:1b20:1:e011::c616",
"2a03:1b20:1:e011::c617",
"2a03:1b20:1:e011::c618",
"2a03:1b20:1:e011::c619",
"2a03:1b20:1:e011::c61a",
"2a03:1b20:1:e011::c61b",
"2a03:1b20:1:e011::c61c",
"2a03:1b20:1:e011::c61d",
"2a03:1b20:1:e011::c61e",
"2a03:1b20:1:e011::c61f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "se-mma-wg-112.blockerad.eu"
}
}
},
{
"hostname": "se-sto-wg-001",
"location": "se-sto",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "185.195.233.76",
"include_in_country": true,
"weight": 100,
"public_key": "MkP/Jytkg51/Y/EostONjIN6YaFRpsAYiNKMX27/CAY=",
"ipv6_addr_in": "2a03:1b20:4:f011::999f"
},
{
"hostname": "se-sto-wg-002",
"location": "se-sto",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "185.65.135.67",
"include_in_country": true,
"weight": 100,
"public_key": "q2ZZPfumPaRVl4DJfzNdQF/GHfe6BYAzQ2GZZHb6rmI=",
"ipv6_addr_in": "2a03:1b20:4:f011::a02f",
"shadowsocks_extra_addr_in": [
"2a03:1b20:4:f011::b102",
"2a03:1b20:4:f011::b103",
"2a03:1b20:4:f011::b104",
"2a03:1b20:4:f011::b105",
"2a03:1b20:4:f011::b106",
"2a03:1b20:4:f011::b107",
"2a03:1b20:4:f011::b108",
"2a03:1b20:4:f011::b109",
"2a03:1b20:4:f011::b10a",
"2a03:1b20:4:f011::b10b",
"2a03:1b20:4:f011::b10c",
"2a03:1b20:4:f011::b10d",
"2a03:1b20:4:f011::b10e",
"2a03:1b20:4:f011::b10f",
"2a03:1b20:4:f011::b110",
"2a03:1b20:4:f011::b111",
"2a03:1b20:4:f011::b112",
"2a03:1b20:4:f011::b113",
"2a03:1b20:4:f011::b114",
"2a03:1b20:4:f011::b115",
"2a03:1b20:4:f011::b116",
"2a03:1b20:4:f011::b117",
"2a03:1b20:4:f011::b118",
"2a03:1b20:4:f011::b119",
"2a03:1b20:4:f011::b11a",
"2a03:1b20:4:f011::b11b",
"2a03:1b20:4:f011::b11c",
"2a03:1b20:4:f011::b11d",
"2a03:1b20:4:f011::b11e",
"2a03:1b20:4:f011::b11f"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"2a03:1b20:4:f011::c102",
"2a03:1b20:4:f011::c103",
"2a03:1b20:4:f011::c104",
"2a03:1b20:4:f011::c105",
"2a03:1b20:4:f011::c106",
"2a03:1b20:4:f011::c107",
"2a03:1b20:4:f011::c108",
"2a03:1b20:4:f011::c109",
"2a03:1b20:4:f011::c10a",
"2a03:1b20:4:f011::c10b",
"2a03:1b20:4:f011::c10c",
"2a03:1b20:4:f011::c10d",
"2a03:1b20:4:f011::c10e",
"2a03:1b20:4:f011::c10f",
"2a03:1b20:4:f011::c110",
"2a03:1b20:4:f011::c111",
"2a03:1b20:4:f011::c112",
"2a03:1b20:4:f011::c113",
"2a03:1b20:4:f011::c114",
"2a03:1b20:4:f011::c115",
"2a03:1b20:4:f011::c116",
"2a03:1b20:4:f011::c117",
"2a03:1b20:4:f011::c118",
"2a03:1b20:4:f011::c119",
"2a03:1b20:4:f011::c11a",
"2a03:1b20:4:f011::c11b",
"2a03:1b20:4:f011::c11c",
"2a03:1b20:4:f011::c11d",
"2a03:1b20:4:f011::c11e",
"2a03:1b20:4:f011::c11f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "se-sto-wg-002.blockerad.eu"
}
}
},
{
"hostname": "se-sto-wg-003",
"location": "se-sto",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "185.65.135.68",
"include_in_country": true,
"weight": 100,
"public_key": "qZbwfoY4LHhDPzUROFbG+LqOjB0+Odwjg/Nv3kGolWc=",
"ipv6_addr_in": "2a03:1b20:4:f011::f201",
"features": {
"lwo": {}
}
},
{
"hostname": "se-sto-wg-007",
"location": "se-sto",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "185.65.135.70",
"include_in_country": true,
"weight": 100,
"public_key": "YD4k8xaiw2kcRhfLRf2UiRNcDmvvu5NV0xT4d5xOFzU=",
"ipv6_addr_in": "2a03:1b20:4:f011::b07f",
"shadowsocks_extra_addr_in": [
"2a03:1b20:4:f011::b602",
"2a03:1b20:4:f011::b603",
"2a03:1b20:4:f011::b604",
"2a03:1b20:4:f011::b605",
"2a03:1b20:4:f011::b606",
"2a03:1b20:4:f011::b607",
"2a03:1b20:4:f011::b608",
"2a03:1b20:4:f011::b609",
"2a03:1b20:4:f011::b60a",
"2a03:1b20:4:f011::b60b",
"2a03:1b20:4:f011::b60c",
"2a03:1b20:4:f011::b60d",
"2a03:1b20:4:f011::b60e",
"2a03:1b20:4:f011::b60f",
"2a03:1b20:4:f011::b610",
"2a03:1b20:4:f011::b611",
"2a03:1b20:4:f011::b612",
"2a03:1b20:4:f011::b613",
"2a03:1b20:4:f011::b614",
"2a03:1b20:4:f011::b615",
"2a03:1b20:4:f011::b616",
"2a03:1b20:4:f011::b617",
"2a03:1b20:4:f011::b618",
"2a03:1b20:4:f011::b619",
"2a03:1b20:4:f011::b61a",
"2a03:1b20:4:f011::b61b",
"2a03:1b20:4:f011::b61c",
"2a03:1b20:4:f011::b61d",
"2a03:1b20:4:f011::b61e",
"2a03:1b20:4:f011::b61f"
],
"features": {
"lwo": {}
}
},
{
"hostname": "se-sto-wg-008",
"location": "se-sto",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "185.65.135.71",
"include_in_country": true,
"weight": 100,
"public_key": "4nOXEaCDYBV//nsVXk7MrnHpxLV9MbGjt+IGQY//p3k=",
"ipv6_addr_in": "2a03:1b20:4:f011::f701"
},
{
"hostname": "se-sto-wg-009",
"location": "se-sto",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "185.195.233.69",
"include_in_country": false,
"weight": 1,
"public_key": "t1XlQD7rER0JUPrmh3R5IpxjUP9YOqodJAwfRorNxl4=",
"ipv6_addr_in": "2a03:1b20:4:f011::a09f",
"daita": true,
"shadowsocks_extra_addr_in": [
"2a03:1b20:4:f011::b802",
"2a03:1b20:4:f011::b803",
"2a03:1b20:4:f011::b804",
"2a03:1b20:4:f011::b805",
"2a03:1b20:4:f011::b806",
"2a03:1b20:4:f011::b807",
"2a03:1b20:4:f011::b808",
"2a03:1b20:4:f011::b809",
"2a03:1b20:4:f011::b80a",
"2a03:1b20:4:f011::b80b",
"2a03:1b20:4:f011::b80c",
"2a03:1b20:4:f011::b80d",
"2a03:1b20:4:f011::b80e",
"2a03:1b20:4:f011::b80f",
"2a03:1b20:4:f011::b810",
"2a03:1b20:4:f011::b811",
"2a03:1b20:4:f011::b812",
"2a03:1b20:4:f011::b813",
"2a03:1b20:4:f011::b814",
"2a03:1b20:4:f011::b815",
"2a03:1b20:4:f011::b816",
"2a03:1b20:4:f011::b817",
"2a03:1b20:4:f011::b818",
"2a03:1b20:4:f011::b819",
"2a03:1b20:4:f011::b81a",
"2a03:1b20:4:f011::b81b",
"2a03:1b20:4:f011::b81c",
"2a03:1b20:4:f011::b81d",
"2a03:1b20:4:f011::b81e",
"2a03:1b20:4:f011::b81f"
],
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"185.195.233.172",
"2a03:1b20:4:f011::c802",
"2a03:1b20:4:f011::c803",
"2a03:1b20:4:f011::c804",
"2a03:1b20:4:f011::c805",
"2a03:1b20:4:f011::c806",
"2a03:1b20:4:f011::c807",
"2a03:1b20:4:f011::c808",
"2a03:1b20:4:f011::c809",
"2a03:1b20:4:f011::c80a",
"2a03:1b20:4:f011::c80b",
"2a03:1b20:4:f011::c80c",
"2a03:1b20:4:f011::c80d",
"2a03:1b20:4:f011::c80e",
"2a03:1b20:4:f011::c80f",
"2a03:1b20:4:f011::c810",
"2a03:1b20:4:f011::c811",
"2a03:1b20:4:f011::c812",
"2a03:1b20:4:f011::c813",
"2a03:1b20:4:f011::c814",
"2a03:1b20:4:f011::c815",
"2a03:1b20:4:f011::c816",
"2a03:1b20:4:f011::c817",
"2a03:1b20:4:f011::c818",
"2a03:1b20:4:f011::c819",
"2a03:1b20:4:f011::c81a",
"2a03:1b20:4:f011::c81b",
"2a03:1b20:4:f011::c81c",
"2a03:1b20:4:f011::c81d",
"2a03:1b20:4:f011::c81e",
"2a03:1b20:4:f011::c81f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "se-sto-wg-009.blockerad.eu"
}
}
},
{
"hostname": "se-sto-wg-010",
"location": "se-sto",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "185.195.233.70",
"include_in_country": true,
"weight": 1,
"public_key": "pWhNidLbYca9j66c7iw/3kgtU+UyFRIgc75xy8riqzg=",
"ipv6_addr_in": "2a03:1b20:4:f011::a10f",
"shadowsocks_extra_addr_in": [
"2a03:1b20:4:f011::b902",
"2a03:1b20:4:f011::b903",
"2a03:1b20:4:f011::b904",
"2a03:1b20:4:f011::b905",
"2a03:1b20:4:f011::b906",
"2a03:1b20:4:f011::b907",
"2a03:1b20:4:f011::b908",
"2a03:1b20:4:f011::b909",
"2a03:1b20:4:f011::b90a",
"2a03:1b20:4:f011::b90b",
"2a03:1b20:4:f011::b90c",
"2a03:1b20:4:f011::b90d",
"2a03:1b20:4:f011::b90e",
"2a03:1b20:4:f011::b90f",
"2a03:1b20:4:f011::b910",
"2a03:1b20:4:f011::b911",
"2a03:1b20:4:f011::b912",
"2a03:1b20:4:f011::b913",
"2a03:1b20:4:f011::b914",
"2a03:1b20:4:f011::b915",
"2a03:1b20:4:f011::b916",
"2a03:1b20:4:f011::b917",
"2a03:1b20:4:f011::b918",
"2a03:1b20:4:f011::b919",
"2a03:1b20:4:f011::b91a",
"2a03:1b20:4:f011::b91b",
"2a03:1b20:4:f011::b91c",
"2a03:1b20:4:f011::b91d",
"2a03:1b20:4:f011::b91e",
"2a03:1b20:4:f011::b91f"
],
"features": {
"lwo": {}
}
},
{
"hostname": "se-sto-wg-011",
"location": "se-sto",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "185.195.233.71",
"include_in_country": true,
"weight": 100,
"public_key": "GqKpm8VwKJQLQEQ0PXbkRueY9hDqiMibr+EpW3n9syk=",
"ipv6_addr_in": "2a03:1b20:4:f011::a11f",
"shadowsocks_extra_addr_in": [
"2a03:1b20:4:f011::ba02",
"2a03:1b20:4:f011::ba03",
"2a03:1b20:4:f011::ba04",
"2a03:1b20:4:f011::ba05",
"2a03:1b20:4:f011::ba06",
"2a03:1b20:4:f011::ba07",
"2a03:1b20:4:f011::ba08",
"2a03:1b20:4:f011::ba09",
"2a03:1b20:4:f011::ba0a",
"2a03:1b20:4:f011::ba0b",
"2a03:1b20:4:f011::ba0c",
"2a03:1b20:4:f011::ba0d",
"2a03:1b20:4:f011::ba0e",
"2a03:1b20:4:f011::ba0f",
"2a03:1b20:4:f011::ba10",
"2a03:1b20:4:f011::ba11",
"2a03:1b20:4:f011::ba12",
"2a03:1b20:4:f011::ba13",
"2a03:1b20:4:f011::ba14",
"2a03:1b20:4:f011::ba15",
"2a03:1b20:4:f011::ba16",
"2a03:1b20:4:f011::ba17",
"2a03:1b20:4:f011::ba18",
"2a03:1b20:4:f011::ba19",
"2a03:1b20:4:f011::ba1a",
"2a03:1b20:4:f011::ba1b",
"2a03:1b20:4:f011::ba1c",
"2a03:1b20:4:f011::ba1d",
"2a03:1b20:4:f011::ba1e",
"2a03:1b20:4:f011::ba1f"
],
"features": {
"lwo": {}
}
},
{
"hostname": "se-sto-wg-012",
"location": "se-sto",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "185.195.233.66",
"include_in_country": true,
"weight": 100,
"public_key": "1493vtFUbIfSpQKRBki/1d0YgWIQwMV4AQAvGxjCNVM=",
"ipv6_addr_in": "2a03:1b20:4:f011::fb01",
"features": {
"lwo": {}
}
},
{
"hostname": "se-sto-wg-013",
"location": "se-sto",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "185.195.233.67",
"include_in_country": true,
"weight": 100,
"public_key": "u3pZZjXm0NHCNqPIhKlZ7Vy6CQm5G9YpfgvaywurTho=",
"ipv6_addr_in": "2a03:1b20:4:f011::fe01",
"features": {
"lwo": {}
}
},
{
"hostname": "se-sto-wg-014",
"location": "se-sto",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "185.195.233.68",
"include_in_country": true,
"weight": 100,
"public_key": "DYlwUsH63DLjEfKC9yq7P+FoQx99WdKvZGGhXoUZVgk=",
"ipv6_addr_in": "2a03:1b20:4:f011::fd01"
},
{
"hostname": "se-sto-wg-201",
"location": "se-sto",
"active": true,
"owned": true,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "89.37.63.10",
"include_in_country": true,
"weight": 300,
"public_key": "V5RUvv8xp3xYc9b/KoGjTL6EUEb2mTv+8egxuEvUAnc=",
"ipv6_addr_in": "2a02:6ea0:1508:1::f001",
"shadowsocks_extra_addr_in": [
"89.37.63.16"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"89.37.63.15",
"2a02:6ea0:1508:1::f009"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "se-sto-wg-201.blockerad.eu"
}
}
},
{
"hostname": "se-sto-wg-202",
"location": "se-sto",
"active": true,
"owned": true,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "89.37.63.66",
"include_in_country": true,
"weight": 300,
"public_key": "S4fVJ6wjUxrRQsDZwWvKVLtcNBJgoSshkqy3wXWG0UM=",
"ipv6_addr_in": "2a02:6ea0:1508:2::f001",
"shadowsocks_extra_addr_in": [
"89.37.63.72"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"89.37.63.71",
"2a02:6ea0:1508:2::f009"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "se-sto-wg-202.blockerad.eu"
}
}
},
{
"hostname": "se-sto-wg-203",
"location": "se-sto",
"active": true,
"owned": true,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "89.37.63.129",
"include_in_country": true,
"weight": 300,
"public_key": "mkBf9JhtMPHS3w0FfJOwSS5kfmUQ0RGSLXBdxUNlzTs=",
"ipv6_addr_in": "2a02:6ea0:1508:3::f001",
"shadowsocks_extra_addr_in": [
"89.37.63.135"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"89.37.63.134",
"2a02:6ea0:1508:3::f009"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "se-sto-wg-203.blockerad.eu"
}
}
},
{
"hostname": "se-sto-wg-204",
"location": "se-sto",
"active": true,
"owned": true,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "89.37.63.190",
"include_in_country": true,
"weight": 300,
"public_key": "cPhM7ShRWQmKiJtD9Wd1vDh0GwIlaMvFb/WPrP58FH8=",
"ipv6_addr_in": "2a02:6ea0:1508:4::f001",
"shadowsocks_extra_addr_in": [
"89.37.63.196"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"89.37.63.195",
"2a02:6ea0:1508:4::c101"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "se-sto-wg-204.blockerad.eu"
}
}
},
{
"hostname": "se-sto-wg-205",
"location": "se-sto",
"active": true,
"owned": true,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "170.62.100.10",
"include_in_country": true,
"weight": 300,
"public_key": "9V4G5BERZI4xHudcIf5wdDG77XZSY08lVEiXrAGXuEE=",
"ipv6_addr_in": "2a02:6ea0:1508:5::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"170.62.100.16"
],
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"170.62.100.15"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "se-sto-wg-205.blockerad.eu"
}
}
},
{
"hostname": "se-sto-wg-206",
"location": "se-sto",
"active": true,
"owned": true,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "170.62.100.66",
"include_in_country": true,
"weight": 300,
"public_key": "9KHMuwHqa1Mx2VrKX3cvqLN/ZPDjH5/z0q+IWbfrmW8=",
"ipv6_addr_in": "2a02:6ea0:1508:6::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"170.62.100.72"
],
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"170.62.100.71"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "se-sto-wg-206.blockerad.eu"
}
}
},
{
"hostname": "se-sto-wg-207",
"location": "se-sto",
"active": true,
"owned": true,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "170.62.100.129",
"include_in_country": true,
"weight": 300,
"public_key": "OatHF/w6fOg8w2415s8zPSXw6LtcYOm+90pqyJ5ZsVY=",
"ipv6_addr_in": "2a02:6ea0:1508:7::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"170.62.100.135"
],
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"170.62.100.134"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "se-sto-wg-207.blockerad.eu"
}
}
},
{
"hostname": "se-sto-wg-208",
"location": "se-sto",
"active": true,
"owned": true,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "170.62.100.170",
"include_in_country": true,
"weight": 300,
"public_key": "HozGhf1OfjFEASBzjmktB9AKkIgbC+OhSabZKwT6EHc=",
"ipv6_addr_in": "2a02:6ea0:1508:8::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"170.62.100.176"
],
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"170.62.100.175"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "se-sto-wg-208.blockerad.eu"
}
}
},
{
"hostname": "se-sto-wg-209",
"location": "se-sto",
"active": true,
"owned": true,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "170.62.100.211",
"include_in_country": true,
"weight": 300,
"public_key": "r3360zyxOKxUthx90sfRkLZBt1Q5alk45/H9Dkq5kFM=",
"ipv6_addr_in": "2a02:6ea0:1508:9::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"170.62.100.217"
],
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"170.62.100.216"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "se-sto-wg-209.blockerad.eu"
}
}
},
{
"hostname": "sg-sin-wg-001",
"location": "sg-sin",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "138.199.60.2",
"include_in_country": true,
"weight": 100,
"public_key": "sFHv/qzG7b6ds5pow+oAR3G5Wqp9eFbBD3BmEGBuUWU=",
"ipv6_addr_in": "2a02:6ea0:d13e:1::a09f",
"daita": true,
"features": {
"daita": {}
}
},
{
"hostname": "sg-sin-wg-002",
"location": "sg-sin",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "138.199.60.15",
"include_in_country": true,
"weight": 100,
"public_key": "WM5I4IFwQcVysM4fF4NXZtQXNrSkqVWkQxNPPygOiF0=",
"ipv6_addr_in": "2a02:6ea0:d13e:2::a10f",
"daita": true,
"features": {
"daita": {}
}
},
{
"hostname": "sg-sin-wg-003",
"location": "sg-sin",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "138.199.60.28",
"include_in_country": true,
"weight": 100,
"public_key": "3HtGdhEXUPKQIDRW49wCUoTK2ZXfq+QfzjfYoldNchg=",
"ipv6_addr_in": "2a02:6ea0:d13e:3::a11f",
"features": {
"lwo": {}
}
},
{
"hostname": "sg-sin-wg-101",
"location": "sg-sin",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.199.194",
"include_in_country": true,
"weight": 100,
"public_key": "KB6ZA1PAixd74c+mO0VBY4j7LaitK8B4L1APbFIQyQ0=",
"ipv6_addr_in": "2a0d:5600:d:44::a01f"
},
{
"hostname": "sg-sin-wg-102",
"location": "sg-sin",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.199.130",
"include_in_country": true,
"weight": 100,
"public_key": "qrhHOwk0ree+LFxW6htvGEfVFuhM2efQ/M+4p0sx/gA=",
"ipv6_addr_in": "2a0d:5600:d:43::a02f"
},
{
"hostname": "si-lju-wg-001",
"location": "si-lju",
"active": true,
"owned": false,
"provider": "HostRoyale",
"stboot": true,
"ipv4_addr_in": "93.115.0.3",
"include_in_country": true,
"weight": 100,
"public_key": "fXWKnogYH3IORGePtkyFg3r/56ZQGkF6hjdw2svhmw8=",
"ipv6_addr_in": "2a06:3040:7:210::f001"
},
{
"hostname": "si-lju-wg-002",
"location": "si-lju",
"active": true,
"owned": false,
"provider": "HostRoyale",
"stboot": true,
"ipv4_addr_in": "93.115.0.33",
"include_in_country": true,
"weight": 100,
"public_key": "HkPoWKRG/KV2C8afaaah9Jl5lYuvJo1loCaFadKDZVU=",
"ipv6_addr_in": "2a06:3040:7:210::f101"
},
{
"hostname": "sk-bts-wg-001",
"location": "sk-bts",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "138.199.34.129",
"include_in_country": true,
"weight": 100,
"public_key": "QEVIaIycN8p5twXCuZeQTEj9utozakw/MU8H6+/whls=",
"ipv6_addr_in": "2a02:6ea0:2901:1::f001"
},
{
"hostname": "sk-bts-wg-002",
"location": "sk-bts",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "138.199.34.143",
"include_in_country": true,
"weight": 100,
"public_key": "JeEuObwimNmoVtPn4kpMI1y1UM+IChGVBLtmP3CNNVQ=",
"ipv6_addr_in": "2a02:6ea0:2901::a02f"
},
{
"hostname": "th-bkk-wg-001",
"location": "th-bkk",
"active": true,
"owned": false,
"provider": "Zenlayer",
"stboot": true,
"ipv4_addr_in": "156.59.50.194",
"include_in_country": true,
"weight": 100,
"public_key": "zX6pm3TVJe7rjQ9GrFH1IY29vw/PJL6LGh3/ALxEyx4=",
"ipv6_addr_in": "2602:ffe4:c09:10a::f001",
"features": {
"lwo": {}
}
},
{
"hostname": "th-bkk-wg-002",
"location": "th-bkk",
"active": true,
"owned": false,
"provider": "Zenlayer",
"stboot": true,
"ipv4_addr_in": "156.59.50.226",
"include_in_country": true,
"weight": 100,
"public_key": "L8CCv3NWDaMyUh4dxO44LSy07ETWCcWBeeGFyQZIlyo=",
"ipv6_addr_in": "2602:ffe4:c09:109::f101"
},
{
"hostname": "tr-ist-wg-001",
"location": "tr-ist",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "149.102.229.129",
"include_in_country": true,
"weight": 100,
"public_key": "jPhK/ziQfJ1Z5GCPj+qR3A7YV2mIQSQtEPCRuG7TUW8=",
"ipv6_addr_in": "2a02:6ea0:e813::f001",
"shadowsocks_extra_addr_in": [
"149.102.229.131"
]
},
{
"hostname": "tr-ist-wg-002",
"location": "tr-ist",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "149.102.229.158",
"include_in_country": true,
"weight": 100,
"public_key": "TDHn9OvFYoHh9nwlYG7OCpPRvCjfODUOksSQPzhguTg=",
"ipv6_addr_in": "2a02:6ea0:e813:1::f001",
"shadowsocks_extra_addr_in": [
"149.102.229.160"
]
},
{
"hostname": "ua-iev-wg-001",
"location": "ua-iev",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "149.102.240.79",
"include_in_country": true,
"weight": 100,
"public_key": "PO2o3ewguPP24wLy8bbDqx1xuAnTOIVzdzVGVT0d8kU=",
"ipv6_addr_in": "2a02:6ea0:e109:2::a01f"
},
{
"hostname": "ua-iev-wg-002",
"location": "ua-iev",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "149.102.240.66",
"include_in_country": true,
"weight": 100,
"public_key": "HUj/J8Rxx7QVGh3kJsFgPZoqtm2BQIX03vKJSIyTOSo=",
"ipv6_addr_in": "2a02:6ea0:e109:1::a02f"
},
{
"hostname": "us-atl-wg-001",
"location": "us-atl",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "45.134.140.130",
"include_in_country": false,
"weight": 100,
"public_key": "nvyBkaEXHwyPBAm8spGB0TFzf2W5wPAl8EEuJ0t+bzs=",
"ipv6_addr_in": "2a02:6ea0:c122:1::b79f",
"features": {
"lwo": {},
"quic": {
"addr_in": [
"45.134.140.142"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-atl-wg-001.blockerad.eu"
}
}
},
{
"hostname": "us-atl-wg-002",
"location": "us-atl",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "45.134.140.143",
"include_in_country": false,
"weight": 100,
"public_key": "ECeGYeh8CfPJO3v56ucCDdl+PlKcj2bBszUGkT+hVWQ=",
"ipv6_addr_in": "2a02:6ea0:c122:2::b80f"
},
{
"hostname": "us-atl-wg-401",
"location": "us-atl",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.108.3",
"include_in_country": true,
"weight": 100,
"public_key": "49LoowbQpQfc/Yw+1DZ0A/Gien3wRnxwJzvo7Gz8Zhw=",
"ipv6_addr_in": "2607:9000:c00:31::f001",
"shadowsocks_extra_addr_in": [
"23.234.108.14"
]
},
{
"hostname": "us-atl-wg-402",
"location": "us-atl",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.108.127",
"include_in_country": true,
"weight": 100,
"public_key": "9CYtFK8cSKxzEiFYpiCuKgYnjMO5Jqri2iFiG2lDUlM=",
"ipv6_addr_in": "2607:9000:c00:32::f001",
"shadowsocks_extra_addr_in": [
"23.234.108.139"
],
"features": {
"lwo": {}
}
},
{
"hostname": "us-atl-wg-403",
"location": "us-atl",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.109.3",
"include_in_country": true,
"weight": 100,
"public_key": "a64LFZfr0htAq1mk5EvVPmQPi52oboISpVUHaYKGE1E=",
"ipv6_addr_in": "2607:9000:c00:33::f001",
"shadowsocks_extra_addr_in": [
"23.234.109.14"
]
},
{
"hostname": "us-atl-wg-404",
"location": "us-atl",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.109.127",
"include_in_country": true,
"weight": 100,
"public_key": "kYm0GM0/fD37iCZM3+60vAxRV1w/PUW+WQkYV14QZFo=",
"ipv6_addr_in": "2607:9000:c00:34::f001",
"shadowsocks_extra_addr_in": [
"23.234.109.139"
]
},
{
"hostname": "us-atl-wg-405",
"location": "us-atl",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.110.3",
"include_in_country": true,
"weight": 100,
"public_key": "643HR3VhN/WVydahUwuKL/e8jT8UNDHduBfDPMF/2E8=",
"ipv6_addr_in": "2607:9000:c00:35::f001",
"shadowsocks_extra_addr_in": [
"23.234.110.14"
]
},
{
"hostname": "us-atl-wg-406",
"location": "us-atl",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.110.127",
"include_in_country": true,
"weight": 100,
"public_key": "spmw1nZv6lgKC/T1KMSuLKyAfCifmrxCdXvVPNhQFCY=",
"ipv6_addr_in": "2607:9000:c00:36::f001",
"shadowsocks_extra_addr_in": [
"23.234.110.139"
],
"features": {
"lwo": {}
}
},
{
"hostname": "us-atl-wg-407",
"location": "us-atl",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.111.3",
"include_in_country": true,
"weight": 100,
"public_key": "e2UcVruvaIHcCXYjaHe6alKbZW/Qc9lbYzYh1AckWEU=",
"ipv6_addr_in": "2607:9000:c00:37::f001",
"shadowsocks_extra_addr_in": [
"23.234.111.14"
],
"features": {
"lwo": {}
}
},
{
"hostname": "us-atl-wg-408",
"location": "us-atl",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.111.127",
"include_in_country": true,
"weight": 100,
"public_key": "x3sKDqtdNIUhOjCiZCzMSZmoMps20J0JloSQMebYK2o=",
"ipv6_addr_in": "2607:9000:c00:38::f001",
"shadowsocks_extra_addr_in": [
"23.234.111.139"
],
"features": {
"lwo": {}
}
},
{
"hostname": "us-bos-wg-001",
"location": "us-bos",
"active": true,
"owned": false,
"provider": "HostRoyale",
"stboot": true,
"ipv4_addr_in": "43.225.189.131",
"include_in_country": true,
"weight": 100,
"public_key": "CsysTnZ0HvyYRjsKMPx60JIgy777JhD0h9WpbHbV83o=",
"ipv6_addr_in": "2a06:3040:12:610::a01f",
"shadowsocks_extra_addr_in": [
"2a06:3040:12:610::b002",
"2a06:3040:12:610::b003",
"2a06:3040:12:610::b004",
"2a06:3040:12:610::b005",
"2a06:3040:12:610::b006",
"2a06:3040:12:610::b007",
"2a06:3040:12:610::b008",
"2a06:3040:12:610::b009",
"2a06:3040:12:610::b00a",
"2a06:3040:12:610::b00b",
"2a06:3040:12:610::b00c",
"2a06:3040:12:610::b00d",
"2a06:3040:12:610::b00e",
"2a06:3040:12:610::b00f",
"2a06:3040:12:610::b010",
"2a06:3040:12:610::b011",
"2a06:3040:12:610::b012",
"2a06:3040:12:610::b013",
"2a06:3040:12:610::b014",
"2a06:3040:12:610::b015",
"2a06:3040:12:610::b016",
"2a06:3040:12:610::b017",
"2a06:3040:12:610::b018",
"2a06:3040:12:610::b019",
"2a06:3040:12:610::b01a",
"2a06:3040:12:610::b01b",
"2a06:3040:12:610::b01c",
"2a06:3040:12:610::b01d",
"2a06:3040:12:610::b01e",
"2a06:3040:12:610::b01f"
]
},
{
"hostname": "us-bos-wg-002",
"location": "us-bos",
"active": false,
"owned": false,
"provider": "HostRoyale",
"stboot": true,
"ipv4_addr_in": "43.225.189.162",
"include_in_country": true,
"weight": 100,
"public_key": "LLkA2XSBvfUeXgLdMKP+OTQeKhtGB03kKskJEwlzAE8=",
"ipv6_addr_in": "2a06:3040:12:610::a02f",
"shadowsocks_extra_addr_in": [
"2a06:3040:12:610::b102",
"2a06:3040:12:610::b103",
"2a06:3040:12:610::b104",
"2a06:3040:12:610::b105",
"2a06:3040:12:610::b106",
"2a06:3040:12:610::b107",
"2a06:3040:12:610::b108",
"2a06:3040:12:610::b109",
"2a06:3040:12:610::b10a",
"2a06:3040:12:610::b10b",
"2a06:3040:12:610::b10c",
"2a06:3040:12:610::b10d",
"2a06:3040:12:610::b10e",
"2a06:3040:12:610::b10f",
"2a06:3040:12:610::b110",
"2a06:3040:12:610::b111",
"2a06:3040:12:610::b112",
"2a06:3040:12:610::b113",
"2a06:3040:12:610::b114",
"2a06:3040:12:610::b115",
"2a06:3040:12:610::b116",
"2a06:3040:12:610::b117",
"2a06:3040:12:610::b118",
"2a06:3040:12:610::b119",
"2a06:3040:12:610::b11a",
"2a06:3040:12:610::b11b",
"2a06:3040:12:610::b11c",
"2a06:3040:12:610::b11d",
"2a06:3040:12:610::b11e",
"2a06:3040:12:610::b11f"
]
},
{
"hostname": "us-bos-wg-101",
"location": "us-bos",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "149.40.50.98",
"include_in_country": true,
"weight": 100,
"public_key": "oxJ2PIqrQOmS0uiyXvnxT64E1uZnjZDWPbP/+APToAE=",
"ipv6_addr_in": "2a02:6ea0:f901::a01f"
},
{
"hostname": "us-bos-wg-102",
"location": "us-bos",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "149.40.50.112",
"include_in_country": true,
"weight": 100,
"public_key": "wcmmadJObux2/62ES+QbIO21BkU7p2I0s6n4WNZZgW0=",
"ipv6_addr_in": "2a02:6ea0:f901:1::a02f",
"features": {
"lwo": {}
}
},
{
"hostname": "us-chi-wg-201",
"location": "us-chi",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "87.249.134.1",
"include_in_country": true,
"weight": 1,
"public_key": "+Xx2mJnoJ+JS11Z6g8mp6aUZV7p6DAN9ZTAzPaHakhM=",
"ipv6_addr_in": "2a02:6ea0:c61f::b63f",
"daita": true,
"features": {
"daita": {}
}
},
{
"hostname": "us-chi-wg-202",
"location": "us-chi",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "87.249.134.14",
"include_in_country": true,
"weight": 100,
"public_key": "rmN4IM0I0gF7V9503/xnQMOLsu9txl8GTqci9dgUO18=",
"ipv6_addr_in": "2a02:6ea0:c61f:1::b64f",
"features": {
"lwo": {}
}
},
{
"hostname": "us-chi-wg-203",
"location": "us-chi",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "87.249.134.27",
"include_in_country": true,
"weight": 100,
"public_key": "V0ilKm3bVqt0rmJ80sP0zSVK4m6O3nADi88IQAL5kjw=",
"ipv6_addr_in": "2a02:6ea0:c61f:2::f001",
"features": {
"lwo": {}
}
},
{
"hostname": "us-chi-wg-301",
"location": "us-chi",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "68.235.46.2",
"include_in_country": true,
"weight": 200,
"public_key": "g9Dlad9R9OcM9w1yu3gq9pQWARQBc3Muj4KfeRY1p20=",
"ipv6_addr_in": "2607:9000:0:101::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"68.235.46.4"
],
"features": {
"daita": {}
}
},
{
"hostname": "us-chi-wg-302",
"location": "us-chi",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "68.235.46.33",
"include_in_country": true,
"weight": 200,
"public_key": "rEVQ7I5Ckvg44uLaSg1l085FcQvFHfM01hMfHxyAQz0=",
"ipv6_addr_in": "2607:9000:0:102::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"68.235.46.35"
],
"features": {
"daita": {}
}
},
{
"hostname": "us-chi-wg-303",
"location": "us-chi",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "68.235.46.64",
"include_in_country": true,
"weight": 200,
"public_key": "DfmNHT84TTS6JcJJfZJwT7tZZVgKIKRJU/2AE5sJ6A4=",
"ipv6_addr_in": "2607:9000:0:103::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"68.235.46.66"
],
"features": {
"daita": {}
}
},
{
"hostname": "us-chi-wg-304",
"location": "us-chi",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "68.235.46.95",
"include_in_country": true,
"weight": 200,
"public_key": "Tr2rkoiqX7bERbeLMDw9CLiTaB0dp9/Fov/Ytz3C+xY=",
"ipv6_addr_in": "2607:9000:0:104::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"68.235.46.97"
],
"features": {
"daita": {}
}
},
{
"hostname": "us-chi-wg-305",
"location": "us-chi",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "68.235.46.126",
"include_in_country": true,
"weight": 200,
"public_key": "jx/3CJiJRozty6hUTs40M/Swhfcch0z3yElmS1VKoVg=",
"ipv6_addr_in": "2607:9000:0:105::f001",
"shadowsocks_extra_addr_in": [
"68.235.46.128"
]
},
{
"hostname": "us-chi-wg-306",
"location": "us-chi",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "68.235.46.157",
"include_in_country": true,
"weight": 200,
"public_key": "WlEbNkNAx/186YZH/UPE6YWkMyAMxRpMRP+IqWrq+TE=",
"ipv6_addr_in": "2607:9000:0:106::f001",
"shadowsocks_extra_addr_in": [
"68.235.46.159"
]
},
{
"hostname": "us-chi-wg-307",
"location": "us-chi",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "68.235.46.188",
"include_in_country": true,
"weight": 200,
"public_key": "U9UAYlVm8nXZjWPrF/vbb1P9oqSRmHo+IfK52yDYpGo=",
"ipv6_addr_in": "2607:9000:0:107::f001",
"shadowsocks_extra_addr_in": [
"68.235.46.190"
],
"features": {
"lwo": {}
}
},
{
"hostname": "us-chi-wg-308",
"location": "us-chi",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "68.235.46.209",
"include_in_country": true,
"weight": 200,
"public_key": "gJsL4BfGcf2QOLGY1Std2Mjg6V2t2w7T2FScANlkJ2I=",
"ipv6_addr_in": "2607:9000:0:108::f001",
"shadowsocks_extra_addr_in": [
"68.235.46.211"
],
"features": {
"lwo": {}
}
},
{
"hostname": "us-chi-wg-309",
"location": "us-chi",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "173.249.252.2",
"include_in_country": true,
"weight": 100,
"public_key": "HMvcz+L7tNQc6FRMkkRDV7BUPzBH8SW74gN7yarX+hk=",
"ipv6_addr_in": "2607:9000:100:41::f001",
"shadowsocks_extra_addr_in": [
"173.249.252.5",
"173.249.252.6",
"173.249.252.7",
"173.249.252.8",
"173.249.252.9",
"173.249.252.10",
"173.249.252.11",
"173.249.252.12",
"173.249.252.13",
"173.249.252.14",
"173.249.252.15",
"173.249.252.16",
"173.249.252.17",
"173.249.252.18",
"173.249.252.19",
"2607:9000:100:41::b002",
"2607:9000:100:41::b003",
"2607:9000:100:41::b004",
"2607:9000:100:41::b005",
"2607:9000:100:41::b006",
"2607:9000:100:41::b007",
"2607:9000:100:41::b008",
"2607:9000:100:41::b009",
"2607:9000:100:41::b00a",
"2607:9000:100:41::b00b",
"2607:9000:100:41::b00c",
"2607:9000:100:41::b00d",
"2607:9000:100:41::b00e",
"2607:9000:100:41::b00f",
"2607:9000:100:41::b010",
"2607:9000:100:41::b011",
"2607:9000:100:41::b012",
"2607:9000:100:41::b013",
"2607:9000:100:41::b014",
"2607:9000:100:41::b015",
"2607:9000:100:41::b016",
"2607:9000:100:41::b017",
"2607:9000:100:41::b018",
"2607:9000:100:41::b019",
"2607:9000:100:41::b01a",
"2607:9000:100:41::b01b",
"2607:9000:100:41::b01c",
"2607:9000:100:41::b01d",
"2607:9000:100:41::b01e",
"2607:9000:100:41::b01f"
],
"features": {
"quic": {
"addr_in": [
"173.249.252.20",
"173.249.252.21",
"173.249.252.22",
"173.249.252.23",
"173.249.252.24",
"173.249.252.25",
"173.249.252.26",
"173.249.252.27",
"173.249.252.28",
"173.249.252.29",
"173.249.252.30",
"173.249.252.31",
"173.249.252.32",
"173.249.252.33",
"173.249.252.34",
"2607:9000:100:41::c002",
"2607:9000:100:41::c003",
"2607:9000:100:41::c004",
"2607:9000:100:41::c005",
"2607:9000:100:41::c006",
"2607:9000:100:41::c007",
"2607:9000:100:41::c008",
"2607:9000:100:41::c009",
"2607:9000:100:41::c00a",
"2607:9000:100:41::c00b",
"2607:9000:100:41::c00c",
"2607:9000:100:41::c00d",
"2607:9000:100:41::c00e",
"2607:9000:100:41::c00f",
"2607:9000:100:41::c010",
"2607:9000:100:41::c011",
"2607:9000:100:41::c012",
"2607:9000:100:41::c013",
"2607:9000:100:41::c014",
"2607:9000:100:41::c015",
"2607:9000:100:41::c016",
"2607:9000:100:41::c017",
"2607:9000:100:41::c018",
"2607:9000:100:41::c019",
"2607:9000:100:41::c01a",
"2607:9000:100:41::c01b",
"2607:9000:100:41::c01c",
"2607:9000:100:41::c01d",
"2607:9000:100:41::c01e",
"2607:9000:100:41::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-chi-wg-309.blockerad.eu"
}
}
},
{
"hostname": "us-chi-wg-310",
"location": "us-chi",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "173.249.252.127",
"include_in_country": true,
"weight": 100,
"public_key": "bJLgTMbt7cx1lKyWzOwW3+Lqc0n6OOXu/iTerXZxawY=",
"ipv6_addr_in": "2607:9000:100:42::f001",
"shadowsocks_extra_addr_in": [
"173.249.252.130",
"173.249.252.131",
"173.249.252.132",
"173.249.252.133",
"173.249.252.134",
"173.249.252.135",
"173.249.252.136",
"173.249.252.137",
"173.249.252.138",
"173.249.252.139",
"173.249.252.140",
"173.249.252.141",
"173.249.252.142",
"173.249.252.143",
"173.249.252.144",
"2607:9000:100:42::b002",
"2607:9000:100:42::b003",
"2607:9000:100:42::b004",
"2607:9000:100:42::b005",
"2607:9000:100:42::b006",
"2607:9000:100:42::b007",
"2607:9000:100:42::b008",
"2607:9000:100:42::b009",
"2607:9000:100:42::b00a",
"2607:9000:100:42::b00b",
"2607:9000:100:42::b00c",
"2607:9000:100:42::b00d",
"2607:9000:100:42::b00e",
"2607:9000:100:42::b00f",
"2607:9000:100:42::b010",
"2607:9000:100:42::b011",
"2607:9000:100:42::b012",
"2607:9000:100:42::b013",
"2607:9000:100:42::b014",
"2607:9000:100:42::b015",
"2607:9000:100:42::b016",
"2607:9000:100:42::b017",
"2607:9000:100:42::b018",
"2607:9000:100:42::b019",
"2607:9000:100:42::b01a",
"2607:9000:100:42::b01b",
"2607:9000:100:42::b01c",
"2607:9000:100:42::b01d",
"2607:9000:100:42::b01e",
"2607:9000:100:42::b01f"
],
"features": {
"quic": {
"addr_in": [
"173.249.252.145",
"173.249.252.146",
"173.249.252.147",
"173.249.252.148",
"173.249.252.149",
"173.249.252.150",
"173.249.252.151",
"173.249.252.152",
"173.249.252.153",
"173.249.252.154",
"173.249.252.155",
"173.249.252.156",
"173.249.252.157",
"173.249.252.158",
"173.249.252.159",
"2607:9000:100:42::c002",
"2607:9000:100:42::c003",
"2607:9000:100:42::c004",
"2607:9000:100:42::c005",
"2607:9000:100:42::c006",
"2607:9000:100:42::c007",
"2607:9000:100:42::c008",
"2607:9000:100:42::c009",
"2607:9000:100:42::c00a",
"2607:9000:100:42::c00b",
"2607:9000:100:42::c00c",
"2607:9000:100:42::c00d",
"2607:9000:100:42::c00e",
"2607:9000:100:42::c00f",
"2607:9000:100:42::c010",
"2607:9000:100:42::c011",
"2607:9000:100:42::c012",
"2607:9000:100:42::c013",
"2607:9000:100:42::c014",
"2607:9000:100:42::c015",
"2607:9000:100:42::c016",
"2607:9000:100:42::c017",
"2607:9000:100:42::c018",
"2607:9000:100:42::c019",
"2607:9000:100:42::c01a",
"2607:9000:100:42::c01b",
"2607:9000:100:42::c01c",
"2607:9000:100:42::c01d",
"2607:9000:100:42::c01e",
"2607:9000:100:42::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-chi-wg-310.blockerad.eu"
}
}
},
{
"hostname": "us-chi-wg-311",
"location": "us-chi",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "173.249.253.2",
"include_in_country": true,
"weight": 100,
"public_key": "9oEgVktX3TUJI5XPWnvVHszj1Q44ix6VDN0CqS0eglc=",
"ipv6_addr_in": "2607:9000:100:43::f001",
"shadowsocks_extra_addr_in": [
"173.249.253.5",
"173.249.253.6",
"173.249.253.7",
"173.249.253.8",
"173.249.253.9",
"173.249.253.10",
"173.249.253.11",
"173.249.253.12",
"173.249.253.13",
"173.249.253.14",
"173.249.253.15",
"173.249.253.16",
"173.249.253.17",
"173.249.253.18",
"173.249.253.19",
"2607:9000:100:43::b002",
"2607:9000:100:43::b003",
"2607:9000:100:43::b004",
"2607:9000:100:43::b005",
"2607:9000:100:43::b006",
"2607:9000:100:43::b007",
"2607:9000:100:43::b008",
"2607:9000:100:43::b009",
"2607:9000:100:43::b00a",
"2607:9000:100:43::b00b",
"2607:9000:100:43::b00c",
"2607:9000:100:43::b00d",
"2607:9000:100:43::b00e",
"2607:9000:100:43::b00f",
"2607:9000:100:43::b010",
"2607:9000:100:43::b011",
"2607:9000:100:43::b012",
"2607:9000:100:43::b013",
"2607:9000:100:43::b014",
"2607:9000:100:43::b015",
"2607:9000:100:43::b016",
"2607:9000:100:43::b017",
"2607:9000:100:43::b018",
"2607:9000:100:43::b019",
"2607:9000:100:43::b01a",
"2607:9000:100:43::b01b",
"2607:9000:100:43::b01c",
"2607:9000:100:43::b01d",
"2607:9000:100:43::b01e",
"2607:9000:100:43::b01f"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"173.249.253.20",
"173.249.253.21",
"173.249.253.22",
"173.249.253.23",
"173.249.253.24",
"173.249.253.25",
"173.249.253.26",
"173.249.253.27",
"173.249.253.28",
"173.249.253.29",
"173.249.253.30",
"173.249.253.31",
"173.249.253.32",
"173.249.253.33",
"173.249.253.34",
"2607:9000:100:43::c002",
"2607:9000:100:43::c003",
"2607:9000:100:43::c004",
"2607:9000:100:43::c005",
"2607:9000:100:43::c006",
"2607:9000:100:43::c007",
"2607:9000:100:43::c008",
"2607:9000:100:43::c009",
"2607:9000:100:43::c00a",
"2607:9000:100:43::c00b",
"2607:9000:100:43::c00c",
"2607:9000:100:43::c00d",
"2607:9000:100:43::c00e",
"2607:9000:100:43::c00f",
"2607:9000:100:43::c010",
"2607:9000:100:43::c011",
"2607:9000:100:43::c012",
"2607:9000:100:43::c013",
"2607:9000:100:43::c014",
"2607:9000:100:43::c015",
"2607:9000:100:43::c016",
"2607:9000:100:43::c017",
"2607:9000:100:43::c018",
"2607:9000:100:43::c019",
"2607:9000:100:43::c01a",
"2607:9000:100:43::c01b",
"2607:9000:100:43::c01c",
"2607:9000:100:43::c01d",
"2607:9000:100:43::c01e",
"2607:9000:100:43::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-chi-wg-311.blockerad.eu"
}
}
},
{
"hostname": "us-chi-wg-312",
"location": "us-chi",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "173.249.253.127",
"include_in_country": true,
"weight": 100,
"public_key": "XzMA3EWGePHQ6ko5XImi4m3TphQqjq9++A8XPfre/0A=",
"ipv6_addr_in": "2607:9000:100:44::f001",
"shadowsocks_extra_addr_in": [
"173.249.253.130",
"173.249.253.131",
"173.249.253.132",
"173.249.253.133",
"173.249.253.134",
"173.249.253.135",
"173.249.253.136",
"173.249.253.137",
"173.249.253.138",
"173.249.253.139",
"173.249.253.140",
"173.249.253.141",
"173.249.253.142",
"173.249.253.143",
"173.249.253.144",
"2607:9000:100:44::b002",
"2607:9000:100:44::b003",
"2607:9000:100:44::b004",
"2607:9000:100:44::b005",
"2607:9000:100:44::b006",
"2607:9000:100:44::b007",
"2607:9000:100:44::b008",
"2607:9000:100:44::b009",
"2607:9000:100:44::b00a",
"2607:9000:100:44::b00b",
"2607:9000:100:44::b00c",
"2607:9000:100:44::b00d",
"2607:9000:100:44::b00e",
"2607:9000:100:44::b00f",
"2607:9000:100:44::b010",
"2607:9000:100:44::b011",
"2607:9000:100:44::b012",
"2607:9000:100:44::b013",
"2607:9000:100:44::b014",
"2607:9000:100:44::b015",
"2607:9000:100:44::b016",
"2607:9000:100:44::b017",
"2607:9000:100:44::b018",
"2607:9000:100:44::b019",
"2607:9000:100:44::b01a",
"2607:9000:100:44::b01b",
"2607:9000:100:44::b01c",
"2607:9000:100:44::b01d",
"2607:9000:100:44::b01e",
"2607:9000:100:44::b01f"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"173.249.253.145",
"173.249.253.146",
"173.249.253.147",
"173.249.253.148",
"173.249.253.149",
"173.249.253.150",
"173.249.253.151",
"173.249.253.152",
"173.249.253.153",
"173.249.253.154",
"173.249.253.155",
"173.249.253.156",
"173.249.253.157",
"173.249.253.158",
"173.249.253.159",
"2607:9000:100:44::c002",
"2607:9000:100:44::c003",
"2607:9000:100:44::c004",
"2607:9000:100:44::c005",
"2607:9000:100:44::c006",
"2607:9000:100:44::c007",
"2607:9000:100:44::c008",
"2607:9000:100:44::c009",
"2607:9000:100:44::c00a",
"2607:9000:100:44::c00b",
"2607:9000:100:44::c00c",
"2607:9000:100:44::c00d",
"2607:9000:100:44::c00e",
"2607:9000:100:44::c00f",
"2607:9000:100:44::c010",
"2607:9000:100:44::c011",
"2607:9000:100:44::c012",
"2607:9000:100:44::c013",
"2607:9000:100:44::c014",
"2607:9000:100:44::c015",
"2607:9000:100:44::c016",
"2607:9000:100:44::c017",
"2607:9000:100:44::c018",
"2607:9000:100:44::c019",
"2607:9000:100:44::c01a",
"2607:9000:100:44::c01b",
"2607:9000:100:44::c01c",
"2607:9000:100:44::c01d",
"2607:9000:100:44::c01e",
"2607:9000:100:44::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-chi-wg-312.blockerad.eu"
}
}
},
{
"hostname": "us-chi-wg-313",
"location": "us-chi",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "173.249.254.2",
"include_in_country": true,
"weight": 100,
"public_key": "/xG21lmyVnh9eSbTP2iYWCM4SIw1QCkKyFKGBkoJlXM=",
"ipv6_addr_in": "2607:9000:100:45::f001",
"shadowsocks_extra_addr_in": [
"173.249.254.5",
"173.249.254.6",
"173.249.254.7",
"173.249.254.8",
"173.249.254.9",
"173.249.254.10",
"173.249.254.11",
"173.249.254.12",
"173.249.254.13",
"173.249.254.14",
"173.249.254.15",
"173.249.254.16",
"173.249.254.17",
"173.249.254.18",
"173.249.254.19",
"2607:9000:100:45::b002",
"2607:9000:100:45::b003",
"2607:9000:100:45::b004",
"2607:9000:100:45::b005",
"2607:9000:100:45::b006",
"2607:9000:100:45::b007",
"2607:9000:100:45::b008",
"2607:9000:100:45::b009",
"2607:9000:100:45::b00a",
"2607:9000:100:45::b00b",
"2607:9000:100:45::b00c",
"2607:9000:100:45::b00d",
"2607:9000:100:45::b00e",
"2607:9000:100:45::b00f",
"2607:9000:100:45::b010",
"2607:9000:100:45::b011",
"2607:9000:100:45::b012",
"2607:9000:100:45::b013",
"2607:9000:100:45::b014",
"2607:9000:100:45::b015",
"2607:9000:100:45::b016",
"2607:9000:100:45::b017",
"2607:9000:100:45::b018",
"2607:9000:100:45::b019",
"2607:9000:100:45::b01a",
"2607:9000:100:45::b01b",
"2607:9000:100:45::b01c",
"2607:9000:100:45::b01d",
"2607:9000:100:45::b01e",
"2607:9000:100:45::b01f"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"173.249.254.20",
"173.249.254.21",
"173.249.254.22",
"173.249.254.23",
"173.249.254.24",
"173.249.254.25",
"173.249.254.26",
"173.249.254.27",
"173.249.254.28",
"173.249.254.29",
"173.249.254.30",
"173.249.254.31",
"173.249.254.32",
"173.249.254.33",
"173.249.254.34",
"2607:9000:100:45::c002",
"2607:9000:100:45::c003",
"2607:9000:100:45::c004",
"2607:9000:100:45::c005",
"2607:9000:100:45::c006",
"2607:9000:100:45::c007",
"2607:9000:100:45::c008",
"2607:9000:100:45::c009",
"2607:9000:100:45::c00a",
"2607:9000:100:45::c00b",
"2607:9000:100:45::c00c",
"2607:9000:100:45::c00d",
"2607:9000:100:45::c00e",
"2607:9000:100:45::c00f",
"2607:9000:100:45::c010",
"2607:9000:100:45::c011",
"2607:9000:100:45::c012",
"2607:9000:100:45::c013",
"2607:9000:100:45::c014",
"2607:9000:100:45::c015",
"2607:9000:100:45::c016",
"2607:9000:100:45::c017",
"2607:9000:100:45::c018",
"2607:9000:100:45::c019",
"2607:9000:100:45::c01a",
"2607:9000:100:45::c01b",
"2607:9000:100:45::c01c",
"2607:9000:100:45::c01d",
"2607:9000:100:45::c01e",
"2607:9000:100:45::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-chi-wg-313.blockerad.eu"
}
}
},
{
"hostname": "us-chi-wg-314",
"location": "us-chi",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "173.249.254.127",
"include_in_country": true,
"weight": 100,
"public_key": "2UyKDI5jY9Nlys5aiOUh8piEfF0wFBZsk7WToNQ8HTk=",
"ipv6_addr_in": "2607:9000:100:46::f001",
"shadowsocks_extra_addr_in": [
"173.249.254.130",
"173.249.254.131",
"173.249.254.132",
"173.249.254.133",
"173.249.254.134",
"173.249.254.135",
"173.249.254.136",
"173.249.254.137",
"173.249.254.138",
"173.249.254.139",
"173.249.254.140",
"173.249.254.141",
"173.249.254.142",
"173.249.254.143",
"173.249.254.144",
"2607:9000:100:46::b002",
"2607:9000:100:46::b003",
"2607:9000:100:46::b004",
"2607:9000:100:46::b005",
"2607:9000:100:46::b006",
"2607:9000:100:46::b007",
"2607:9000:100:46::b008",
"2607:9000:100:46::b009",
"2607:9000:100:46::b00a",
"2607:9000:100:46::b00b",
"2607:9000:100:46::b00c",
"2607:9000:100:46::b00d",
"2607:9000:100:46::b00e",
"2607:9000:100:46::b00f",
"2607:9000:100:46::b010",
"2607:9000:100:46::b011",
"2607:9000:100:46::b012",
"2607:9000:100:46::b013",
"2607:9000:100:46::b014",
"2607:9000:100:46::b015",
"2607:9000:100:46::b016",
"2607:9000:100:46::b017",
"2607:9000:100:46::b018",
"2607:9000:100:46::b019",
"2607:9000:100:46::b01a",
"2607:9000:100:46::b01b",
"2607:9000:100:46::b01c",
"2607:9000:100:46::b01d",
"2607:9000:100:46::b01e",
"2607:9000:100:46::b01f"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"173.249.254.145",
"173.249.254.146",
"173.249.254.147",
"173.249.254.148",
"173.249.254.149",
"173.249.254.150",
"173.249.254.151",
"173.249.254.152",
"173.249.254.153",
"173.249.254.154",
"173.249.254.155",
"173.249.254.156",
"173.249.254.157",
"173.249.254.158",
"173.249.254.159",
"2607:9000:100:46::c002",
"2607:9000:100:46::c003",
"2607:9000:100:46::c004",
"2607:9000:100:46::c005",
"2607:9000:100:46::c006",
"2607:9000:100:46::c007",
"2607:9000:100:46::c008",
"2607:9000:100:46::c009",
"2607:9000:100:46::c00a",
"2607:9000:100:46::c00b",
"2607:9000:100:46::c00c",
"2607:9000:100:46::c00d",
"2607:9000:100:46::c00e",
"2607:9000:100:46::c00f",
"2607:9000:100:46::c010",
"2607:9000:100:46::c011",
"2607:9000:100:46::c012",
"2607:9000:100:46::c013",
"2607:9000:100:46::c014",
"2607:9000:100:46::c015",
"2607:9000:100:46::c016",
"2607:9000:100:46::c017",
"2607:9000:100:46::c018",
"2607:9000:100:46::c019",
"2607:9000:100:46::c01a",
"2607:9000:100:46::c01b",
"2607:9000:100:46::c01c",
"2607:9000:100:46::c01d",
"2607:9000:100:46::c01e",
"2607:9000:100:46::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-chi-wg-314.blockerad.eu"
}
}
},
{
"hostname": "us-chi-wg-315",
"location": "us-chi",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "173.249.255.2",
"include_in_country": true,
"weight": 100,
"public_key": "q8TC/ILZWlaydPdkJLkL/pWB8qrK0dWkKtZMGqEElh8=",
"ipv6_addr_in": "2607:9000:100:47::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"173.249.255.5",
"173.249.255.6",
"173.249.255.7",
"173.249.255.8",
"173.249.255.9",
"173.249.255.10",
"173.249.255.11",
"173.249.255.12",
"173.249.255.13",
"173.249.255.14",
"173.249.255.15",
"173.249.255.16",
"173.249.255.17",
"173.249.255.18",
"173.249.255.19",
"2607:9000:100:47::b002",
"2607:9000:100:47::b003",
"2607:9000:100:47::b004",
"2607:9000:100:47::b005",
"2607:9000:100:47::b006",
"2607:9000:100:47::b007",
"2607:9000:100:47::b008",
"2607:9000:100:47::b009",
"2607:9000:100:47::b00a",
"2607:9000:100:47::b00b",
"2607:9000:100:47::b00c",
"2607:9000:100:47::b00d",
"2607:9000:100:47::b00e",
"2607:9000:100:47::b00f",
"2607:9000:100:47::b010",
"2607:9000:100:47::b011",
"2607:9000:100:47::b012",
"2607:9000:100:47::b013",
"2607:9000:100:47::b014",
"2607:9000:100:47::b015",
"2607:9000:100:47::b016",
"2607:9000:100:47::b017",
"2607:9000:100:47::b018",
"2607:9000:100:47::b019",
"2607:9000:100:47::b01a",
"2607:9000:100:47::b01b",
"2607:9000:100:47::b01c",
"2607:9000:100:47::b01d",
"2607:9000:100:47::b01e",
"2607:9000:100:47::b01f"
],
"features": {
"daita": {},
"quic": {
"addr_in": [
"173.249.255.20",
"173.249.255.21",
"173.249.255.22",
"173.249.255.23",
"173.249.255.24",
"173.249.255.25",
"173.249.255.26",
"173.249.255.27",
"173.249.255.28",
"173.249.255.29",
"173.249.255.30",
"173.249.255.31",
"173.249.255.32",
"173.249.255.33",
"173.249.255.34",
"2607:9000:100:47::c002",
"2607:9000:100:47::c003",
"2607:9000:100:47::c004",
"2607:9000:100:47::c005",
"2607:9000:100:47::c006",
"2607:9000:100:47::c007",
"2607:9000:100:47::c008",
"2607:9000:100:47::c009",
"2607:9000:100:47::c00a",
"2607:9000:100:47::c00b",
"2607:9000:100:47::c00c",
"2607:9000:100:47::c00d",
"2607:9000:100:47::c00e",
"2607:9000:100:47::c00f",
"2607:9000:100:47::c010",
"2607:9000:100:47::c011",
"2607:9000:100:47::c012",
"2607:9000:100:47::c013",
"2607:9000:100:47::c014",
"2607:9000:100:47::c015",
"2607:9000:100:47::c016",
"2607:9000:100:47::c017",
"2607:9000:100:47::c018",
"2607:9000:100:47::c019",
"2607:9000:100:47::c01a",
"2607:9000:100:47::c01b",
"2607:9000:100:47::c01c",
"2607:9000:100:47::c01d",
"2607:9000:100:47::c01e",
"2607:9000:100:47::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-chi-wg-315.blockerad.eu"
}
}
},
{
"hostname": "us-chi-wg-316",
"location": "us-chi",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "173.249.255.127",
"include_in_country": true,
"weight": 100,
"public_key": "5oGrphw1JoWMIeJUHytMdOKvyxx5P4l7OyP/uTYDmyg=",
"ipv6_addr_in": "2607:9000:100:48::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"173.249.255.130",
"173.249.255.131",
"173.249.255.132",
"173.249.255.133",
"173.249.255.134",
"173.249.255.135",
"173.249.255.136",
"173.249.255.137",
"173.249.255.138",
"173.249.255.139",
"173.249.255.140",
"173.249.255.141",
"173.249.255.142",
"173.249.255.143",
"173.249.255.144",
"2607:9000:100:48::b002",
"2607:9000:100:48::b003",
"2607:9000:100:48::b004",
"2607:9000:100:48::b005",
"2607:9000:100:48::b006",
"2607:9000:100:48::b007",
"2607:9000:100:48::b008",
"2607:9000:100:48::b009",
"2607:9000:100:48::b00a",
"2607:9000:100:48::b00b",
"2607:9000:100:48::b00c",
"2607:9000:100:48::b00d",
"2607:9000:100:48::b00e",
"2607:9000:100:48::b00f",
"2607:9000:100:48::b010",
"2607:9000:100:48::b011",
"2607:9000:100:48::b012",
"2607:9000:100:48::b013",
"2607:9000:100:48::b014",
"2607:9000:100:48::b015",
"2607:9000:100:48::b016",
"2607:9000:100:48::b017",
"2607:9000:100:48::b018",
"2607:9000:100:48::b019",
"2607:9000:100:48::b01a",
"2607:9000:100:48::b01b",
"2607:9000:100:48::b01c",
"2607:9000:100:48::b01d",
"2607:9000:100:48::b01e",
"2607:9000:100:48::b01f"
],
"features": {
"daita": {},
"quic": {
"addr_in": [
"173.249.255.145",
"173.249.255.146",
"173.249.255.147",
"173.249.255.148",
"173.249.255.149",
"173.249.255.150",
"173.249.255.151",
"173.249.255.152",
"173.249.255.153",
"173.249.255.154",
"173.249.255.155",
"173.249.255.156",
"173.249.255.157",
"173.249.255.158",
"173.249.255.159",
"2607:9000:100:48::c002",
"2607:9000:100:48::c003",
"2607:9000:100:48::c004",
"2607:9000:100:48::c005",
"2607:9000:100:48::c006",
"2607:9000:100:48::c007",
"2607:9000:100:48::c008",
"2607:9000:100:48::c009",
"2607:9000:100:48::c00a",
"2607:9000:100:48::c00b",
"2607:9000:100:48::c00c",
"2607:9000:100:48::c00d",
"2607:9000:100:48::c00e",
"2607:9000:100:48::c00f",
"2607:9000:100:48::c010",
"2607:9000:100:48::c011",
"2607:9000:100:48::c012",
"2607:9000:100:48::c013",
"2607:9000:100:48::c014",
"2607:9000:100:48::c015",
"2607:9000:100:48::c016",
"2607:9000:100:48::c017",
"2607:9000:100:48::c018",
"2607:9000:100:48::c019",
"2607:9000:100:48::c01a",
"2607:9000:100:48::c01b",
"2607:9000:100:48::c01c",
"2607:9000:100:48::c01d",
"2607:9000:100:48::c01e",
"2607:9000:100:48::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-chi-wg-316.blockerad.eu"
}
}
},
{
"hostname": "us-dal-wg-001",
"location": "us-dal",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.211.66",
"include_in_country": true,
"weight": 100,
"public_key": "EAzbWMQXxJGsd8j2brhYerGB3t5cPOXqdIDFspDGSng=",
"ipv6_addr_in": "2001:ac8:9a:76::1f",
"features": {
"lwo": {},
"quic": {
"addr_in": [
"146.70.211.126"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-dal-wg-001.blockerad.eu"
}
}
},
{
"hostname": "us-dal-wg-002",
"location": "us-dal",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.211.2",
"include_in_country": true,
"weight": 100,
"public_key": "OYG1hxzz3kUGpVeGjx9DcCYreMO3S6tZN17iHUK+zDE=",
"ipv6_addr_in": "2001:ac8:9a:75::2f"
},
{
"hostname": "us-dal-wg-003",
"location": "us-dal",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.211.130",
"include_in_country": true,
"weight": 100,
"public_key": "jn/i/ekJOkkRUdMj2I4ViUKd3d/LAdTQ+ICKmBy1tkM=",
"ipv6_addr_in": "2001:ac8:9a:78::3f"
},
{
"hostname": "us-dal-wg-401",
"location": "us-dal",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "37.19.200.156",
"include_in_country": true,
"weight": 100,
"public_key": "xZsnCxFN7pOvx6YlTbi92copdsY5xgekTCp//VUMyhE=",
"ipv6_addr_in": "2a02:6ea0:d20c:3::b72f"
},
{
"hostname": "us-dal-wg-402",
"location": "us-dal",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "37.19.200.143",
"include_in_country": true,
"weight": 100,
"public_key": "sPQEji8BhxuM/Za0Q0/9aWYxyACtQF0qRpzaBLumEzo=",
"ipv6_addr_in": "2a02:6ea0:d20c:2::b71f"
},
{
"hostname": "us-dal-wg-403",
"location": "us-dal",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "37.19.200.130",
"include_in_country": true,
"weight": 100,
"public_key": "4s9JIhxC/D02tosXYYcgrD+pHI+C7oTAFsXzVisKjRs=",
"ipv6_addr_in": "2a02:6ea0:d20c:1::f001"
},
{
"hostname": "us-dal-wg-601",
"location": "us-dal",
"active": true,
"owned": false,
"provider": "HostRoyale",
"stboot": true,
"ipv4_addr_in": "103.102.246.3",
"include_in_country": true,
"weight": 100,
"public_key": "353XrBhmW0VisDN/ztYLb7WwnxQUTnL9Ys5FBPUHHVw=",
"ipv6_addr_in": "2a01:4740:2::f001",
"shadowsocks_extra_addr_in": [
"103.102.246.14"
]
},
{
"hostname": "us-dal-wg-602",
"location": "us-dal",
"active": false,
"owned": false,
"provider": "HostRoyale",
"stboot": true,
"ipv4_addr_in": "103.102.246.127",
"include_in_country": true,
"weight": 100,
"public_key": "Vm9kQsUFIGgNeb+NBrY0KZpW51dC84cAQWMY9eMa8Ho=",
"ipv6_addr_in": "2a01:4740:2::f101",
"shadowsocks_extra_addr_in": [
"103.102.246.139"
]
},
{
"hostname": "us-dal-wg-603",
"location": "us-dal",
"active": true,
"owned": false,
"provider": "HostRoyale",
"stboot": true,
"ipv4_addr_in": "103.102.247.3",
"include_in_country": true,
"weight": 100,
"public_key": "Y5SK28yMGjcZVByWZkMb24KdmbmY07mDnwLN6817yEE=",
"ipv6_addr_in": "2a01:4740:2::f201",
"shadowsocks_extra_addr_in": [
"103.102.247.14"
]
},
{
"hostname": "us-dal-wg-604",
"location": "us-dal",
"active": true,
"owned": false,
"provider": "HostRoyale",
"stboot": true,
"ipv4_addr_in": "103.102.247.127",
"include_in_country": true,
"weight": 100,
"public_key": "7Wyh9lX1nIkKfIpwUywcSUVF8pOxP0c04EehfEeIWg4=",
"ipv6_addr_in": "2a01:4740:2::f301",
"shadowsocks_extra_addr_in": [
"103.102.247.139"
]
},
{
"hostname": "us-dal-wg-701",
"location": "us-dal",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.104.2",
"include_in_country": true,
"weight": 100,
"public_key": "pl4AW+ZGaOknJlgTbACqwihOe+A3GC5aALB74RLTFF8=",
"ipv6_addr_in": "2607:9000:b00:31::f001",
"shadowsocks_extra_addr_in": [
"23.234.104.5",
"23.234.104.6",
"23.234.104.7",
"23.234.104.8",
"23.234.104.9",
"23.234.104.10",
"23.234.104.11",
"23.234.104.12",
"23.234.104.13",
"23.234.104.14",
"23.234.104.15",
"23.234.104.16",
"23.234.104.17",
"23.234.104.18",
"23.234.104.19",
"2607:9000:b00:31::b002",
"2607:9000:b00:31::b003",
"2607:9000:b00:31::b004",
"2607:9000:b00:31::b005",
"2607:9000:b00:31::b006",
"2607:9000:b00:31::b007",
"2607:9000:b00:31::b008",
"2607:9000:b00:31::b009",
"2607:9000:b00:31::b00a",
"2607:9000:b00:31::b00b",
"2607:9000:b00:31::b00c",
"2607:9000:b00:31::b00d",
"2607:9000:b00:31::b00e",
"2607:9000:b00:31::b00f",
"2607:9000:b00:31::b010",
"2607:9000:b00:31::b011",
"2607:9000:b00:31::b012",
"2607:9000:b00:31::b013",
"2607:9000:b00:31::b014",
"2607:9000:b00:31::b015",
"2607:9000:b00:31::b016",
"2607:9000:b00:31::b017",
"2607:9000:b00:31::b018",
"2607:9000:b00:31::b019",
"2607:9000:b00:31::b01a",
"2607:9000:b00:31::b01b",
"2607:9000:b00:31::b01c",
"2607:9000:b00:31::b01d",
"2607:9000:b00:31::b01e",
"2607:9000:b00:31::b01f"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"23.234.104.20",
"23.234.104.21",
"23.234.104.22",
"23.234.104.23",
"23.234.104.24",
"23.234.104.25",
"23.234.104.26",
"23.234.104.27",
"23.234.104.28",
"23.234.104.29",
"23.234.104.30",
"23.234.104.31",
"23.234.104.32",
"23.234.104.33",
"23.234.104.34",
"2607:9000:b00:31::c002",
"2607:9000:b00:31::c003",
"2607:9000:b00:31::c004",
"2607:9000:b00:31::c005",
"2607:9000:b00:31::c006",
"2607:9000:b00:31::c007",
"2607:9000:b00:31::c008",
"2607:9000:b00:31::c009",
"2607:9000:b00:31::c00a",
"2607:9000:b00:31::c00b",
"2607:9000:b00:31::c00c",
"2607:9000:b00:31::c00d",
"2607:9000:b00:31::c00e",
"2607:9000:b00:31::c00f",
"2607:9000:b00:31::c010",
"2607:9000:b00:31::c011",
"2607:9000:b00:31::c012",
"2607:9000:b00:31::c013",
"2607:9000:b00:31::c014",
"2607:9000:b00:31::c015",
"2607:9000:b00:31::c016",
"2607:9000:b00:31::c017",
"2607:9000:b00:31::c018",
"2607:9000:b00:31::c019",
"2607:9000:b00:31::c01a",
"2607:9000:b00:31::c01b",
"2607:9000:b00:31::c01c",
"2607:9000:b00:31::c01d",
"2607:9000:b00:31::c01e",
"2607:9000:b00:31::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-dal-wg-701.blockerad.eu"
}
}
},
{
"hostname": "us-dal-wg-702",
"location": "us-dal",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.104.127",
"include_in_country": true,
"weight": 100,
"public_key": "UNyJnd4U9T7P+v1/NZzIBPMl83+maIY+J9NWTP0bskc=",
"ipv6_addr_in": "2607:9000:b00:32::f001",
"shadowsocks_extra_addr_in": [
"23.234.104.130",
"23.234.104.131",
"23.234.104.132",
"23.234.104.133",
"23.234.104.134",
"23.234.104.135",
"23.234.104.136",
"23.234.104.137",
"23.234.104.138",
"23.234.104.139",
"23.234.104.140",
"23.234.104.141",
"23.234.104.142",
"23.234.104.143",
"23.234.104.144",
"2607:9000:b00:31::b002",
"2607:9000:b00:31::b003",
"2607:9000:b00:31::b004",
"2607:9000:b00:31::b005",
"2607:9000:b00:31::b006",
"2607:9000:b00:31::b007",
"2607:9000:b00:31::b008",
"2607:9000:b00:31::b009",
"2607:9000:b00:31::b00a",
"2607:9000:b00:31::b00b",
"2607:9000:b00:31::b00c",
"2607:9000:b00:31::b00d",
"2607:9000:b00:31::b00e",
"2607:9000:b00:31::b00f",
"2607:9000:b00:31::b010",
"2607:9000:b00:31::b011",
"2607:9000:b00:31::b012",
"2607:9000:b00:31::b013",
"2607:9000:b00:31::b014",
"2607:9000:b00:31::b015",
"2607:9000:b00:31::b016",
"2607:9000:b00:31::b017",
"2607:9000:b00:31::b018",
"2607:9000:b00:31::b019",
"2607:9000:b00:31::b01a",
"2607:9000:b00:31::b01b",
"2607:9000:b00:31::b01c",
"2607:9000:b00:31::b01d",
"2607:9000:b00:31::b01e",
"2607:9000:b00:31::b01f"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"23.234.104.145",
"23.234.104.146",
"23.234.104.147",
"23.234.104.148",
"23.234.104.149",
"23.234.104.150",
"23.234.104.151",
"23.234.104.152",
"23.234.104.153",
"23.234.104.154",
"23.234.104.155",
"23.234.104.156",
"23.234.104.157",
"23.234.104.158",
"23.234.104.159",
"2607:9000:b00:31::c002",
"2607:9000:b00:31::c003",
"2607:9000:b00:31::c004",
"2607:9000:b00:31::c005",
"2607:9000:b00:31::c006",
"2607:9000:b00:31::c007",
"2607:9000:b00:31::c008",
"2607:9000:b00:31::c009",
"2607:9000:b00:31::c00a",
"2607:9000:b00:31::c00b",
"2607:9000:b00:31::c00c",
"2607:9000:b00:31::c00d",
"2607:9000:b00:31::c00e",
"2607:9000:b00:31::c00f",
"2607:9000:b00:31::c010",
"2607:9000:b00:31::c011",
"2607:9000:b00:31::c012",
"2607:9000:b00:31::c013",
"2607:9000:b00:31::c014",
"2607:9000:b00:31::c015",
"2607:9000:b00:31::c016",
"2607:9000:b00:31::c017",
"2607:9000:b00:31::c018",
"2607:9000:b00:31::c019",
"2607:9000:b00:31::c01a",
"2607:9000:b00:31::c01b",
"2607:9000:b00:31::c01c",
"2607:9000:b00:31::c01d",
"2607:9000:b00:31::c01e",
"2607:9000:b00:31::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-dal-wg-702.blockerad.eu"
}
}
},
{
"hostname": "us-dal-wg-703",
"location": "us-dal",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.105.2",
"include_in_country": true,
"weight": 100,
"public_key": "A+PTuYy2zuYfHcKs9VZU7bgXSC0/PNndLuUD6xxgaRQ=",
"ipv6_addr_in": "2607:9000:b00:33::f001",
"shadowsocks_extra_addr_in": [
"23.234.105.5",
"23.234.105.6",
"23.234.105.7",
"23.234.105.8",
"23.234.105.9",
"23.234.105.10",
"23.234.105.11",
"23.234.105.12",
"23.234.105.13",
"23.234.105.14",
"23.234.105.15",
"23.234.105.16",
"23.234.105.17",
"23.234.105.18",
"23.234.105.19",
"2607:9000:b00:33::b002",
"2607:9000:b00:33::b003",
"2607:9000:b00:33::b004",
"2607:9000:b00:33::b005",
"2607:9000:b00:33::b006",
"2607:9000:b00:33::b007",
"2607:9000:b00:33::b008",
"2607:9000:b00:33::b009",
"2607:9000:b00:33::b00a",
"2607:9000:b00:33::b00b",
"2607:9000:b00:33::b00c",
"2607:9000:b00:33::b00d",
"2607:9000:b00:33::b00e",
"2607:9000:b00:33::b00f",
"2607:9000:b00:33::b010",
"2607:9000:b00:33::b011",
"2607:9000:b00:33::b012",
"2607:9000:b00:33::b013",
"2607:9000:b00:33::b014",
"2607:9000:b00:33::b015",
"2607:9000:b00:33::b016",
"2607:9000:b00:33::b017",
"2607:9000:b00:33::b018",
"2607:9000:b00:33::b019",
"2607:9000:b00:33::b01a",
"2607:9000:b00:33::b01b",
"2607:9000:b00:33::b01c",
"2607:9000:b00:33::b01d",
"2607:9000:b00:33::b01e",
"2607:9000:b00:33::b01f"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"23.234.105.20",
"23.234.105.21",
"23.234.105.22",
"23.234.105.23",
"23.234.105.24",
"23.234.105.25",
"23.234.105.26",
"23.234.105.27",
"23.234.105.28",
"23.234.105.29",
"23.234.105.30",
"23.234.105.31",
"23.234.105.32",
"23.234.105.33",
"23.234.105.34",
"2607:9000:b00:33::c002",
"2607:9000:b00:33::c003",
"2607:9000:b00:33::c004",
"2607:9000:b00:33::c005",
"2607:9000:b00:33::c006",
"2607:9000:b00:33::c007",
"2607:9000:b00:33::c008",
"2607:9000:b00:33::c009",
"2607:9000:b00:33::c00a",
"2607:9000:b00:33::c00b",
"2607:9000:b00:33::c00c",
"2607:9000:b00:33::c00d",
"2607:9000:b00:33::c00e",
"2607:9000:b00:33::c00f",
"2607:9000:b00:33::c010",
"2607:9000:b00:33::c011",
"2607:9000:b00:33::c012",
"2607:9000:b00:33::c013",
"2607:9000:b00:33::c014",
"2607:9000:b00:33::c015",
"2607:9000:b00:33::c016",
"2607:9000:b00:33::c017",
"2607:9000:b00:33::c018",
"2607:9000:b00:33::c019",
"2607:9000:b00:33::c01a",
"2607:9000:b00:33::c01b",
"2607:9000:b00:33::c01c",
"2607:9000:b00:33::c01d",
"2607:9000:b00:33::c01e",
"2607:9000:b00:33::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-dal-wg-703.blockerad.eu"
}
}
},
{
"hostname": "us-dal-wg-704",
"location": "us-dal",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.105.127",
"include_in_country": true,
"weight": 100,
"public_key": "DlDMRNqq5oppRQaCWz8XKAccxtjCW2jSjBWGdY77BQw=",
"ipv6_addr_in": "2607:9000:b00:34::f001",
"shadowsocks_extra_addr_in": [
"23.234.105.130",
"23.234.105.131",
"23.234.105.132",
"23.234.105.133",
"23.234.105.134",
"23.234.105.135",
"23.234.105.136",
"23.234.105.137",
"23.234.105.138",
"23.234.105.139",
"23.234.105.140",
"23.234.105.141",
"23.234.105.142",
"23.234.105.143",
"23.234.105.144",
"2607:9000:b00:34::b002",
"2607:9000:b00:34::b003",
"2607:9000:b00:34::b004",
"2607:9000:b00:34::b005",
"2607:9000:b00:34::b006",
"2607:9000:b00:34::b007",
"2607:9000:b00:34::b008",
"2607:9000:b00:34::b009",
"2607:9000:b00:34::b00a",
"2607:9000:b00:34::b00b",
"2607:9000:b00:34::b00c",
"2607:9000:b00:34::b00d",
"2607:9000:b00:34::b00e",
"2607:9000:b00:34::b00f",
"2607:9000:b00:34::b010",
"2607:9000:b00:34::b011",
"2607:9000:b00:34::b012",
"2607:9000:b00:34::b013",
"2607:9000:b00:34::b014",
"2607:9000:b00:34::b015",
"2607:9000:b00:34::b016",
"2607:9000:b00:34::b017",
"2607:9000:b00:34::b018",
"2607:9000:b00:34::b019",
"2607:9000:b00:34::b01a",
"2607:9000:b00:34::b01b",
"2607:9000:b00:34::b01c",
"2607:9000:b00:34::b01d",
"2607:9000:b00:34::b01e",
"2607:9000:b00:34::b01f"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"23.234.105.145",
"23.234.105.146",
"23.234.105.147",
"23.234.105.148",
"23.234.105.149",
"23.234.105.150",
"23.234.105.151",
"23.234.105.152",
"23.234.105.153",
"23.234.105.154",
"23.234.105.155",
"23.234.105.156",
"23.234.105.157",
"23.234.105.158",
"23.234.105.159",
"2607:9000:b00:34::c002",
"2607:9000:b00:34::c003",
"2607:9000:b00:34::c004",
"2607:9000:b00:34::c005",
"2607:9000:b00:34::c006",
"2607:9000:b00:34::c007",
"2607:9000:b00:34::c008",
"2607:9000:b00:34::c009",
"2607:9000:b00:34::c00a",
"2607:9000:b00:34::c00b",
"2607:9000:b00:34::c00c",
"2607:9000:b00:34::c00d",
"2607:9000:b00:34::c00e",
"2607:9000:b00:34::c00f",
"2607:9000:b00:34::c010",
"2607:9000:b00:34::c011",
"2607:9000:b00:34::c012",
"2607:9000:b00:34::c013",
"2607:9000:b00:34::c014",
"2607:9000:b00:34::c015",
"2607:9000:b00:34::c016",
"2607:9000:b00:34::c017",
"2607:9000:b00:34::c018",
"2607:9000:b00:34::c019",
"2607:9000:b00:34::c01a",
"2607:9000:b00:34::c01b",
"2607:9000:b00:34::c01c",
"2607:9000:b00:34::c01d",
"2607:9000:b00:34::c01e",
"2607:9000:b00:34::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-dal-wg-704.blockerad.eu"
}
}
},
{
"hostname": "us-dal-wg-705",
"location": "us-dal",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.106.2",
"include_in_country": true,
"weight": 100,
"public_key": "vaI2uM3xjXYxvtWMkAwRwuWMI/vlJNxsfwTAILvUNHM=",
"ipv6_addr_in": "2607:9000:b00:35::f001",
"shadowsocks_extra_addr_in": [
"23.234.106.5",
"23.234.106.6",
"23.234.106.7",
"23.234.106.8",
"23.234.106.9",
"23.234.106.10",
"23.234.106.11",
"23.234.106.12",
"23.234.106.13",
"23.234.106.14",
"23.234.106.15",
"23.234.106.16",
"23.234.106.17",
"23.234.106.18",
"23.234.106.19",
"2607:9000:b00:35::b002",
"2607:9000:b00:35::b003",
"2607:9000:b00:35::b004",
"2607:9000:b00:35::b005",
"2607:9000:b00:35::b006",
"2607:9000:b00:35::b007",
"2607:9000:b00:35::b008",
"2607:9000:b00:35::b009",
"2607:9000:b00:35::b00a",
"2607:9000:b00:35::b00b",
"2607:9000:b00:35::b00c",
"2607:9000:b00:35::b00d",
"2607:9000:b00:35::b00e",
"2607:9000:b00:35::b00f",
"2607:9000:b00:35::b010",
"2607:9000:b00:35::b011",
"2607:9000:b00:35::b012",
"2607:9000:b00:35::b013",
"2607:9000:b00:35::b014",
"2607:9000:b00:35::b015",
"2607:9000:b00:35::b016",
"2607:9000:b00:35::b017",
"2607:9000:b00:35::b018",
"2607:9000:b00:35::b019",
"2607:9000:b00:35::b01a",
"2607:9000:b00:35::b01b",
"2607:9000:b00:35::b01c",
"2607:9000:b00:35::b01d",
"2607:9000:b00:35::b01e",
"2607:9000:b00:35::b01f"
],
"features": {
"quic": {
"addr_in": [
"23.234.106.20",
"23.234.106.21",
"23.234.106.22",
"23.234.106.23",
"23.234.106.24",
"23.234.106.25",
"23.234.106.26",
"23.234.106.27",
"23.234.106.28",
"23.234.106.29",
"23.234.106.30",
"23.234.106.31",
"23.234.106.32",
"23.234.106.33",
"23.234.106.34",
"2607:9000:b00:35::c002",
"2607:9000:b00:35::c003",
"2607:9000:b00:35::c004",
"2607:9000:b00:35::c005",
"2607:9000:b00:35::c006",
"2607:9000:b00:35::c007",
"2607:9000:b00:35::c008",
"2607:9000:b00:35::c009",
"2607:9000:b00:35::c00a",
"2607:9000:b00:35::c00b",
"2607:9000:b00:35::c00c",
"2607:9000:b00:35::c00d",
"2607:9000:b00:35::c00e",
"2607:9000:b00:35::c00f",
"2607:9000:b00:35::c010",
"2607:9000:b00:35::c011",
"2607:9000:b00:35::c012",
"2607:9000:b00:35::c013",
"2607:9000:b00:35::c014",
"2607:9000:b00:35::c015",
"2607:9000:b00:35::c016",
"2607:9000:b00:35::c017",
"2607:9000:b00:35::c018",
"2607:9000:b00:35::c019",
"2607:9000:b00:35::c01a",
"2607:9000:b00:35::c01b",
"2607:9000:b00:35::c01c",
"2607:9000:b00:35::c01d",
"2607:9000:b00:35::c01e",
"2607:9000:b00:35::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-dal-wg-705.blockerad.eu"
}
}
},
{
"hostname": "us-dal-wg-706",
"location": "us-dal",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.106.127",
"include_in_country": true,
"weight": 100,
"public_key": "vO4TIJsyvNnSH+m9iwoM1BLJokFa80YsCpMjnC8FMzc=",
"ipv6_addr_in": "2607:9000:b00:36::f001",
"shadowsocks_extra_addr_in": [
"23.234.106.130",
"23.234.106.131",
"23.234.106.132",
"23.234.106.133",
"23.234.106.134",
"23.234.106.135",
"23.234.106.136",
"23.234.106.137",
"23.234.106.138",
"23.234.106.139",
"23.234.106.140",
"23.234.106.141",
"23.234.106.142",
"23.234.106.143",
"23.234.106.144",
"2607:9000:b00:36::b002",
"2607:9000:b00:36::b003",
"2607:9000:b00:36::b004",
"2607:9000:b00:36::b005",
"2607:9000:b00:36::b006",
"2607:9000:b00:36::b007",
"2607:9000:b00:36::b008",
"2607:9000:b00:36::b009",
"2607:9000:b00:36::b00a",
"2607:9000:b00:36::b00b",
"2607:9000:b00:36::b00c",
"2607:9000:b00:36::b00d",
"2607:9000:b00:36::b00e",
"2607:9000:b00:36::b00f",
"2607:9000:b00:36::b010",
"2607:9000:b00:36::b011",
"2607:9000:b00:36::b012",
"2607:9000:b00:36::b013",
"2607:9000:b00:36::b014",
"2607:9000:b00:36::b015",
"2607:9000:b00:36::b016",
"2607:9000:b00:36::b017",
"2607:9000:b00:36::b018",
"2607:9000:b00:36::b019",
"2607:9000:b00:36::b01a",
"2607:9000:b00:36::b01b",
"2607:9000:b00:36::b01c",
"2607:9000:b00:36::b01d",
"2607:9000:b00:36::b01e",
"2607:9000:b00:36::b01f"
],
"features": {
"quic": {
"addr_in": [
"23.234.106.145",
"23.234.106.146",
"23.234.106.147",
"23.234.106.148",
"23.234.106.149",
"23.234.106.150",
"23.234.106.151",
"23.234.106.152",
"23.234.106.153",
"23.234.106.154",
"23.234.106.155",
"23.234.106.156",
"23.234.106.157",
"23.234.106.158",
"23.234.106.159",
"2607:9000:b00:36::c002",
"2607:9000:b00:36::c003",
"2607:9000:b00:36::c004",
"2607:9000:b00:36::c005",
"2607:9000:b00:36::c006",
"2607:9000:b00:36::c007",
"2607:9000:b00:36::c008",
"2607:9000:b00:36::c009",
"2607:9000:b00:36::c00a",
"2607:9000:b00:36::c00b",
"2607:9000:b00:36::c00c",
"2607:9000:b00:36::c00d",
"2607:9000:b00:36::c00e",
"2607:9000:b00:36::c00f",
"2607:9000:b00:36::c010",
"2607:9000:b00:36::c011",
"2607:9000:b00:36::c012",
"2607:9000:b00:36::c013",
"2607:9000:b00:36::c014",
"2607:9000:b00:36::c015",
"2607:9000:b00:36::c016",
"2607:9000:b00:36::c017",
"2607:9000:b00:36::c018",
"2607:9000:b00:36::c019",
"2607:9000:b00:36::c01a",
"2607:9000:b00:36::c01b",
"2607:9000:b00:36::c01c",
"2607:9000:b00:36::c01d",
"2607:9000:b00:36::c01e",
"2607:9000:b00:36::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-dal-wg-706.blockerad.eu"
}
}
},
{
"hostname": "us-dal-wg-707",
"location": "us-dal",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.107.2",
"include_in_country": true,
"weight": 100,
"public_key": "MnFc+hUAUSIID/PykPuUPoYlMbRBbFkGK1nIlHSeJEs=",
"ipv6_addr_in": "2607:9000:b00:37::f001",
"shadowsocks_extra_addr_in": [
"23.234.107.5",
"23.234.107.6",
"23.234.107.7",
"23.234.107.8",
"23.234.107.9",
"23.234.107.10",
"23.234.107.11",
"23.234.107.12",
"23.234.107.13",
"23.234.107.14",
"23.234.107.15",
"23.234.107.16",
"23.234.107.17",
"23.234.107.18",
"23.234.107.19",
"2607:9000:b00:37::b002",
"2607:9000:b00:37::b003",
"2607:9000:b00:37::b004",
"2607:9000:b00:37::b005",
"2607:9000:b00:37::b006",
"2607:9000:b00:37::b007",
"2607:9000:b00:37::b008",
"2607:9000:b00:37::b009",
"2607:9000:b00:37::b00a",
"2607:9000:b00:37::b00b",
"2607:9000:b00:37::b00c",
"2607:9000:b00:37::b00d",
"2607:9000:b00:37::b00e",
"2607:9000:b00:37::b00f",
"2607:9000:b00:37::b010",
"2607:9000:b00:37::b011",
"2607:9000:b00:37::b012",
"2607:9000:b00:37::b013",
"2607:9000:b00:37::b014",
"2607:9000:b00:37::b015",
"2607:9000:b00:37::b016",
"2607:9000:b00:37::b017",
"2607:9000:b00:37::b018",
"2607:9000:b00:37::b019",
"2607:9000:b00:37::b01a",
"2607:9000:b00:37::b01b",
"2607:9000:b00:37::b01c",
"2607:9000:b00:37::b01d",
"2607:9000:b00:37::b01e",
"2607:9000:b00:37::b01f"
],
"features": {
"quic": {
"addr_in": [
"23.234.107.20",
"23.234.107.21",
"23.234.107.22",
"23.234.107.23",
"23.234.107.24",
"23.234.107.25",
"23.234.107.26",
"23.234.107.27",
"23.234.107.28",
"23.234.107.29",
"23.234.107.30",
"23.234.107.31",
"23.234.107.32",
"23.234.107.33",
"23.234.107.34",
"2607:9000:b00:37::c002",
"2607:9000:b00:37::c003",
"2607:9000:b00:37::c004",
"2607:9000:b00:37::c005",
"2607:9000:b00:37::c006",
"2607:9000:b00:37::c007",
"2607:9000:b00:37::c008",
"2607:9000:b00:37::c009",
"2607:9000:b00:37::c00a",
"2607:9000:b00:37::c00b",
"2607:9000:b00:37::c00c",
"2607:9000:b00:37::c00d",
"2607:9000:b00:37::c00e",
"2607:9000:b00:37::c00f",
"2607:9000:b00:37::c010",
"2607:9000:b00:37::c011",
"2607:9000:b00:37::c012",
"2607:9000:b00:37::c013",
"2607:9000:b00:37::c014",
"2607:9000:b00:37::c015",
"2607:9000:b00:37::c016",
"2607:9000:b00:37::c017",
"2607:9000:b00:37::c018",
"2607:9000:b00:37::c019",
"2607:9000:b00:37::c01a",
"2607:9000:b00:37::c01b",
"2607:9000:b00:37::c01c",
"2607:9000:b00:37::c01d",
"2607:9000:b00:37::c01e",
"2607:9000:b00:37::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-dal-wg-707.blockerad.eu"
}
}
},
{
"hostname": "us-dal-wg-708",
"location": "us-dal",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.107.127",
"include_in_country": true,
"weight": 100,
"public_key": "I8b0Y+odQGMzuMQi+P2fbZF+FiR3rmyZsAc1SIGzNUo=",
"ipv6_addr_in": "2607:9000:b00:38::f001",
"shadowsocks_extra_addr_in": [
"23.234.107.130",
"23.234.107.131",
"23.234.107.132",
"23.234.107.133",
"23.234.107.134",
"23.234.107.135",
"23.234.107.136",
"23.234.107.137",
"23.234.107.138",
"23.234.107.139",
"23.234.107.140",
"23.234.107.141",
"23.234.107.142",
"23.234.107.143",
"23.234.107.144",
"2607:9000:b00:38::b002",
"2607:9000:b00:38::b003",
"2607:9000:b00:38::b004",
"2607:9000:b00:38::b005",
"2607:9000:b00:38::b006",
"2607:9000:b00:38::b007",
"2607:9000:b00:38::b008",
"2607:9000:b00:38::b009",
"2607:9000:b00:38::b00a",
"2607:9000:b00:38::b00b",
"2607:9000:b00:38::b00c",
"2607:9000:b00:38::b00d",
"2607:9000:b00:38::b00e",
"2607:9000:b00:38::b00f",
"2607:9000:b00:38::b010",
"2607:9000:b00:38::b011",
"2607:9000:b00:38::b012",
"2607:9000:b00:38::b013",
"2607:9000:b00:38::b014",
"2607:9000:b00:38::b015",
"2607:9000:b00:38::b016",
"2607:9000:b00:38::b017",
"2607:9000:b00:38::b018",
"2607:9000:b00:38::b019",
"2607:9000:b00:38::b01a",
"2607:9000:b00:38::b01b",
"2607:9000:b00:38::b01c",
"2607:9000:b00:38::b01d",
"2607:9000:b00:38::b01e",
"2607:9000:b00:38::b01f"
],
"features": {
"quic": {
"addr_in": [
"23.234.107.145",
"23.234.107.146",
"23.234.107.147",
"23.234.107.148",
"23.234.107.149",
"23.234.107.150",
"23.234.107.151",
"23.234.107.152",
"23.234.107.153",
"23.234.107.154",
"23.234.107.155",
"23.234.107.156",
"23.234.107.157",
"23.234.107.158",
"23.234.107.159",
"2607:9000:b00:38::c002",
"2607:9000:b00:38::c003",
"2607:9000:b00:38::c004",
"2607:9000:b00:38::c005",
"2607:9000:b00:38::c006",
"2607:9000:b00:38::c007",
"2607:9000:b00:38::c008",
"2607:9000:b00:38::c009",
"2607:9000:b00:38::c00a",
"2607:9000:b00:38::c00b",
"2607:9000:b00:38::c00c",
"2607:9000:b00:38::c00d",
"2607:9000:b00:38::c00e",
"2607:9000:b00:38::c00f",
"2607:9000:b00:38::c010",
"2607:9000:b00:38::c011",
"2607:9000:b00:38::c012",
"2607:9000:b00:38::c013",
"2607:9000:b00:38::c014",
"2607:9000:b00:38::c015",
"2607:9000:b00:38::c016",
"2607:9000:b00:38::c017",
"2607:9000:b00:38::c018",
"2607:9000:b00:38::c019",
"2607:9000:b00:38::c01a",
"2607:9000:b00:38::c01b",
"2607:9000:b00:38::c01c",
"2607:9000:b00:38::c01d",
"2607:9000:b00:38::c01e",
"2607:9000:b00:38::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-dal-wg-708.blockerad.eu"
}
}
},
{
"hostname": "us-den-wg-101",
"location": "us-den",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "37.19.210.1",
"include_in_country": true,
"weight": 100,
"public_key": "74U+9EQrMwVOafgXuSp8eaKG0+p4zjSsDe3J7+ojhx0=",
"ipv6_addr_in": "2a02:6ea0:d70a::b57f"
},
{
"hostname": "us-den-wg-102",
"location": "us-den",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "37.19.210.14",
"include_in_country": true,
"weight": 100,
"public_key": "T44stCRbQXFCBCcpdDbZPlNHp2eZEi91ooyk0JDC21E=",
"ipv6_addr_in": "2a02:6ea0:d70a:1::b58f"
},
{
"hostname": "us-den-wg-103",
"location": "us-den",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "37.19.210.27",
"include_in_country": true,
"weight": 100,
"public_key": "Az+PGHQ0xFElmRBv+PKZuRnEzKPrPtUpRD3vpxb4si4=",
"ipv6_addr_in": "2a02:6ea0:d70a:2::b59f"
},
{
"hostname": "us-den-wg-201",
"location": "us-den",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.68.2",
"include_in_country": true,
"weight": 0,
"public_key": "MsF1hhYtyCsvPt4B8f48biVcVYd692STflhcbKwTGAw=",
"ipv6_addr_in": "2607:9000:2000:41::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"23.234.68.13"
],
"features": {
"daita": {}
}
},
{
"hostname": "us-den-wg-202",
"location": "us-den",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.68.127",
"include_in_country": true,
"weight": 0,
"public_key": "YP20qT+/cY/sbBhlXo6fWZlfVhRU+emQlZ1am+vUNnw=",
"ipv6_addr_in": "2607:9000:2000:42::f001",
"shadowsocks_extra_addr_in": [
"23.234.68.138"
],
"features": {
"lwo": {}
}
},
{
"hostname": "us-den-wg-203",
"location": "us-den",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.69.2",
"include_in_country": true,
"weight": 0,
"public_key": "D8TSWEfmRIm1qMS0RgO8uireFMMZCMi+XxhIJ2jPBEU=",
"ipv6_addr_in": "2607:9000:2000:43::f001",
"shadowsocks_extra_addr_in": [
"23.234.69.13"
],
"features": {
"lwo": {}
}
},
{
"hostname": "us-den-wg-204",
"location": "us-den",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.69.127",
"include_in_country": true,
"weight": 0,
"public_key": "DZcEpwNSf+6BoDcHknHBVPwAA0ZJjz7DgQ+llATpAzg=",
"ipv6_addr_in": "2607:9000:2000:44::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"23.234.69.138"
],
"features": {
"daita": {}
}
},
{
"hostname": "us-den-wg-205",
"location": "us-den",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.70.2",
"include_in_country": true,
"weight": 0,
"public_key": "0LQQJLKBZD0Wf0s0nwFfyMW0MMEKoxNPZ14ZbxkogiY=",
"ipv6_addr_in": "2607:9000:2000:45::f001",
"shadowsocks_extra_addr_in": [
"23.234.70.13"
]
},
{
"hostname": "us-den-wg-206",
"location": "us-den",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.70.127",
"include_in_country": true,
"weight": 0,
"public_key": "Y4waCBM7GE9iOT+xl9PcZ2mNKGiawEOBv8UkH84CaAo=",
"ipv6_addr_in": "2607:9000:2000:46::f001",
"shadowsocks_extra_addr_in": [
"23.234.70.138"
]
},
{
"hostname": "us-den-wg-207",
"location": "us-den",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.71.2",
"include_in_country": true,
"weight": 0,
"public_key": "nUnmeY34CDLjW4Q3TAbJQ168jVXmkY4MVAp28rmpzEc=",
"ipv6_addr_in": "2607:9000:2000:47::f001",
"shadowsocks_extra_addr_in": [
"23.234.71.13"
]
},
{
"hostname": "us-den-wg-208",
"location": "us-den",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.71.127",
"include_in_country": true,
"weight": 0,
"public_key": "Fo6J7nLUeSnNPenB1NiPoivVod3m4fN4OE5yjafxYXY=",
"ipv6_addr_in": "2607:9000:2000:48::f001",
"shadowsocks_extra_addr_in": [
"23.234.71.138"
]
},
{
"hostname": "us-det-wg-001",
"location": "us-det",
"active": true,
"owned": false,
"provider": "HostRoyale",
"stboot": true,
"ipv4_addr_in": "185.141.119.131",
"include_in_country": true,
"weight": 100,
"public_key": "+USmlxhnLmlNkDnBbu+rXwjUwa383e0ilYEqPkEkNHA=",
"ipv6_addr_in": "2a06:3040:11:610::f001",
"features": {
"lwo": {}
}
},
{
"hostname": "us-det-wg-002",
"location": "us-det",
"active": true,
"owned": false,
"provider": "HostRoyale",
"stboot": true,
"ipv4_addr_in": "185.141.119.161",
"include_in_country": true,
"weight": 100,
"public_key": "cYqP1UqhOYuaj47e4jAbgL55h52L+ALjtML26OtBvFU=",
"ipv6_addr_in": "2a06:3040:11:610::f101",
"features": {
"lwo": {}
}
},
{
"hostname": "us-hou-wg-001",
"location": "us-hou",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "37.19.221.130",
"include_in_country": true,
"weight": 200,
"public_key": "NKscQ4mm24nsYWfpL85Cve+BKIExR0JaysldUtVSlzg=",
"ipv6_addr_in": "2a02:6ea0:e001::f001"
},
{
"hostname": "us-hou-wg-002",
"location": "us-hou",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "37.19.221.143",
"include_in_country": true,
"weight": 200,
"public_key": "tzSfoiq9ZbCcE5I0Xz9kCrsWksDn0wgvaz9TiHYTmnU=",
"ipv6_addr_in": "2a02:6ea0:e001:1::f001"
},
{
"hostname": "us-hou-wg-003",
"location": "us-hou",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "37.19.221.156",
"include_in_country": true,
"weight": 200,
"public_key": "fNSu30TCgbADxNKACx+5qWY6XGJOga4COmTZZE0k0R4=",
"ipv6_addr_in": "2a02:6ea0:e001:2::b55f"
},
{
"hostname": "us-hou-wg-004",
"location": "us-hou",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "37.19.221.169",
"include_in_country": true,
"weight": 200,
"public_key": "NkZMYUEcHykPkAFdm3dE8l2U9P2mt58Dw6j6BWhzaCc=",
"ipv6_addr_in": "2a02:6ea0:e001:3::b56f"
},
{
"hostname": "us-lax-wg-001",
"location": "us-lax",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.72.2",
"include_in_country": true,
"weight": 100,
"public_key": "zqsfGglzJPY657WMRxf/S4omG7+ZkSDIpDq+ggbc9yo=",
"ipv6_addr_in": "2607:9000:300:31::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"23.234.72.5",
"23.234.72.6",
"23.234.72.7",
"23.234.72.8",
"23.234.72.9",
"23.234.72.10",
"23.234.72.11",
"23.234.72.12",
"23.234.72.13",
"23.234.72.14",
"23.234.72.15",
"23.234.72.16",
"23.234.72.17",
"23.234.72.18",
"23.234.72.19",
"2607:9000:300:31::b002",
"2607:9000:300:31::b003",
"2607:9000:300:31::b004",
"2607:9000:300:31::b005",
"2607:9000:300:31::b006",
"2607:9000:300:31::b007",
"2607:9000:300:31::b008",
"2607:9000:300:31::b009",
"2607:9000:300:31::b00a",
"2607:9000:300:31::b00b",
"2607:9000:300:31::b00c",
"2607:9000:300:31::b00d",
"2607:9000:300:31::b00e",
"2607:9000:300:31::b00f",
"2607:9000:300:31::b010",
"2607:9000:300:31::b011",
"2607:9000:300:31::b012",
"2607:9000:300:31::b013",
"2607:9000:300:31::b014",
"2607:9000:300:31::b015",
"2607:9000:300:31::b016",
"2607:9000:300:31::b017",
"2607:9000:300:31::b018",
"2607:9000:300:31::b019",
"2607:9000:300:31::b01a",
"2607:9000:300:31::b01b",
"2607:9000:300:31::b01c",
"2607:9000:300:31::b01d",
"2607:9000:300:31::b01e",
"2607:9000:300:31::b01f"
],
"features": {
"daita": {},
"quic": {
"addr_in": [
"23.234.72.20",
"23.234.72.21",
"23.234.72.22",
"23.234.72.23",
"23.234.72.24",
"23.234.72.25",
"23.234.72.26",
"23.234.72.27",
"23.234.72.28",
"23.234.72.29",
"23.234.72.30",
"23.234.72.31",
"23.234.72.32",
"23.234.72.33",
"23.234.72.34",
"2607:9000:300:31::c002",
"2607:9000:300:31::c003",
"2607:9000:300:31::c004",
"2607:9000:300:31::c005",
"2607:9000:300:31::c006",
"2607:9000:300:31::c007",
"2607:9000:300:31::c008",
"2607:9000:300:31::c009",
"2607:9000:300:31::c00a",
"2607:9000:300:31::c00b",
"2607:9000:300:31::c00c",
"2607:9000:300:31::c00d",
"2607:9000:300:31::c00e",
"2607:9000:300:31::c00f",
"2607:9000:300:31::c010",
"2607:9000:300:31::c011",
"2607:9000:300:31::c012",
"2607:9000:300:31::c013",
"2607:9000:300:31::c014",
"2607:9000:300:31::c015",
"2607:9000:300:31::c016",
"2607:9000:300:31::c017",
"2607:9000:300:31::c018",
"2607:9000:300:31::c019",
"2607:9000:300:31::c01a",
"2607:9000:300:31::c01b",
"2607:9000:300:31::c01c",
"2607:9000:300:31::c01d",
"2607:9000:300:31::c01e",
"2607:9000:300:31::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-lax-wg-001.blockerad.eu"
}
}
},
{
"hostname": "us-lax-wg-002",
"location": "us-lax",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.72.127",
"include_in_country": true,
"weight": 100,
"public_key": "sgcr0zSYzfspx4lD38bl3Nb9X7gtJiFLAVE2rqaDjxE=",
"ipv6_addr_in": "2607:9000:300:32::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"23.234.72.130",
"23.234.72.131",
"23.234.72.132",
"23.234.72.133",
"23.234.72.134",
"23.234.72.135",
"23.234.72.136",
"23.234.72.137",
"23.234.72.138",
"23.234.72.139",
"23.234.72.140",
"23.234.72.141",
"23.234.72.142",
"23.234.72.143",
"23.234.72.144",
"2607:9000:300:32::b002",
"2607:9000:300:32::b003",
"2607:9000:300:32::b004",
"2607:9000:300:32::b005",
"2607:9000:300:32::b006",
"2607:9000:300:32::b007",
"2607:9000:300:32::b008",
"2607:9000:300:32::b009",
"2607:9000:300:32::b00a",
"2607:9000:300:32::b00b",
"2607:9000:300:32::b00c",
"2607:9000:300:32::b00d",
"2607:9000:300:32::b00e",
"2607:9000:300:32::b00f",
"2607:9000:300:32::b010",
"2607:9000:300:32::b011",
"2607:9000:300:32::b012",
"2607:9000:300:32::b013",
"2607:9000:300:32::b014",
"2607:9000:300:32::b015",
"2607:9000:300:32::b016",
"2607:9000:300:32::b017",
"2607:9000:300:32::b018",
"2607:9000:300:32::b019",
"2607:9000:300:32::b01a",
"2607:9000:300:32::b01b",
"2607:9000:300:32::b01c",
"2607:9000:300:32::b01d",
"2607:9000:300:32::b01e",
"2607:9000:300:32::b01f"
],
"features": {
"daita": {},
"quic": {
"addr_in": [
"23.234.72.145",
"23.234.72.146",
"23.234.72.147",
"23.234.72.148",
"23.234.72.149",
"23.234.72.150",
"23.234.72.151",
"23.234.72.152",
"23.234.72.153",
"23.234.72.154",
"23.234.72.155",
"23.234.72.156",
"23.234.72.157",
"23.234.72.158",
"23.234.72.159",
"2607:9000:300:32::c002",
"2607:9000:300:32::c003",
"2607:9000:300:32::c004",
"2607:9000:300:32::c005",
"2607:9000:300:32::c006",
"2607:9000:300:32::c007",
"2607:9000:300:32::c008",
"2607:9000:300:32::c009",
"2607:9000:300:32::c00a",
"2607:9000:300:32::c00b",
"2607:9000:300:32::c00c",
"2607:9000:300:32::c00d",
"2607:9000:300:32::c00e",
"2607:9000:300:32::c00f",
"2607:9000:300:32::c010",
"2607:9000:300:32::c011",
"2607:9000:300:32::c012",
"2607:9000:300:32::c013",
"2607:9000:300:32::c014",
"2607:9000:300:32::c015",
"2607:9000:300:32::c016",
"2607:9000:300:32::c017",
"2607:9000:300:32::c018",
"2607:9000:300:32::c019",
"2607:9000:300:32::c01a",
"2607:9000:300:32::c01b",
"2607:9000:300:32::c01c",
"2607:9000:300:32::c01d",
"2607:9000:300:32::c01e",
"2607:9000:300:32::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-lax-wg-002.blockerad.eu"
}
}
},
{
"hostname": "us-lax-wg-003",
"location": "us-lax",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.73.2",
"include_in_country": true,
"weight": 100,
"public_key": "kZkubkNYgzXKAWuF70RA/XGhOxorA4C3Ph3v4t+LThM=",
"ipv6_addr_in": "2607:9000:300:33::f001",
"shadowsocks_extra_addr_in": [
"23.234.73.5",
"23.234.73.6",
"23.234.73.7",
"23.234.73.8",
"23.234.73.9",
"23.234.73.10",
"23.234.73.11",
"23.234.73.12",
"23.234.73.13",
"23.234.73.14",
"23.234.73.15",
"23.234.73.16",
"23.234.73.17",
"23.234.73.18",
"23.234.73.19",
"2607:9000:300:33::b002",
"2607:9000:300:33::b003",
"2607:9000:300:33::b004",
"2607:9000:300:33::b005",
"2607:9000:300:33::b006",
"2607:9000:300:33::b007",
"2607:9000:300:33::b008",
"2607:9000:300:33::b009",
"2607:9000:300:33::b00a",
"2607:9000:300:33::b00b",
"2607:9000:300:33::b00c",
"2607:9000:300:33::b00d",
"2607:9000:300:33::b00e",
"2607:9000:300:33::b00f",
"2607:9000:300:33::b010",
"2607:9000:300:33::b011",
"2607:9000:300:33::b012",
"2607:9000:300:33::b013",
"2607:9000:300:33::b014",
"2607:9000:300:33::b015",
"2607:9000:300:33::b016",
"2607:9000:300:33::b017",
"2607:9000:300:33::b018",
"2607:9000:300:33::b019",
"2607:9000:300:33::b01a",
"2607:9000:300:33::b01b",
"2607:9000:300:33::b01c",
"2607:9000:300:33::b01d",
"2607:9000:300:33::b01e",
"2607:9000:300:33::b01f"
],
"features": {
"quic": {
"addr_in": [
"23.234.73.20",
"23.234.73.21",
"23.234.73.22",
"23.234.73.23",
"23.234.73.24",
"23.234.73.25",
"23.234.73.26",
"23.234.73.27",
"23.234.73.28",
"23.234.73.29",
"23.234.73.30",
"23.234.73.31",
"23.234.73.32",
"23.234.73.33",
"23.234.73.34",
"2607:9000:300:33::c002",
"2607:9000:300:33::c003",
"2607:9000:300:33::c004",
"2607:9000:300:33::c005",
"2607:9000:300:33::c006",
"2607:9000:300:33::c007",
"2607:9000:300:33::c008",
"2607:9000:300:33::c009",
"2607:9000:300:33::c00a",
"2607:9000:300:33::c00b",
"2607:9000:300:33::c00c",
"2607:9000:300:33::c00d",
"2607:9000:300:33::c00e",
"2607:9000:300:33::c00f",
"2607:9000:300:33::c010",
"2607:9000:300:33::c011",
"2607:9000:300:33::c012",
"2607:9000:300:33::c013",
"2607:9000:300:33::c014",
"2607:9000:300:33::c015",
"2607:9000:300:33::c016",
"2607:9000:300:33::c017",
"2607:9000:300:33::c018",
"2607:9000:300:33::c019",
"2607:9000:300:33::c01a",
"2607:9000:300:33::c01b",
"2607:9000:300:33::c01c",
"2607:9000:300:33::c01d",
"2607:9000:300:33::c01e",
"2607:9000:300:33::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-lax-wg-003.blockerad.eu"
}
}
},
{
"hostname": "us-lax-wg-004",
"location": "us-lax",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.73.127",
"include_in_country": true,
"weight": 100,
"public_key": "5E2RphAlOuRZjhDLr5ZfRscrWJST3IkMsxEtbrJsEno=",
"ipv6_addr_in": "2607:9000:300:34::f001",
"shadowsocks_extra_addr_in": [
"23.234.73.130",
"23.234.73.131",
"23.234.73.132",
"23.234.73.133",
"23.234.73.134",
"23.234.73.135",
"23.234.73.136",
"23.234.73.137",
"23.234.73.138",
"23.234.73.139",
"23.234.73.140",
"23.234.73.141",
"23.234.73.142",
"23.234.73.143",
"23.234.73.144",
"2607:9000:300:34::b002",
"2607:9000:300:34::b003",
"2607:9000:300:34::b004",
"2607:9000:300:34::b005",
"2607:9000:300:34::b006",
"2607:9000:300:34::b007",
"2607:9000:300:34::b008",
"2607:9000:300:34::b009",
"2607:9000:300:34::b00a",
"2607:9000:300:34::b00b",
"2607:9000:300:34::b00c",
"2607:9000:300:34::b00d",
"2607:9000:300:34::b00e",
"2607:9000:300:34::b00f",
"2607:9000:300:34::b010",
"2607:9000:300:34::b011",
"2607:9000:300:34::b012",
"2607:9000:300:34::b013",
"2607:9000:300:34::b014",
"2607:9000:300:34::b015",
"2607:9000:300:34::b016",
"2607:9000:300:34::b017",
"2607:9000:300:34::b018",
"2607:9000:300:34::b019",
"2607:9000:300:34::b01a",
"2607:9000:300:34::b01b",
"2607:9000:300:34::b01c",
"2607:9000:300:34::b01d",
"2607:9000:300:34::b01e",
"2607:9000:300:34::b01f"
],
"features": {
"quic": {
"addr_in": [
"23.234.73.145",
"23.234.73.146",
"23.234.73.147",
"23.234.73.148",
"23.234.73.149",
"23.234.73.150",
"23.234.73.151",
"23.234.73.152",
"23.234.73.153",
"23.234.73.154",
"23.234.73.155",
"23.234.73.156",
"23.234.73.157",
"23.234.73.158",
"23.234.73.159",
"2607:9000:300:34::c002",
"2607:9000:300:34::c003",
"2607:9000:300:34::c004",
"2607:9000:300:34::c005",
"2607:9000:300:34::c006",
"2607:9000:300:34::c007",
"2607:9000:300:34::c008",
"2607:9000:300:34::c009",
"2607:9000:300:34::c00a",
"2607:9000:300:34::c00b",
"2607:9000:300:34::c00c",
"2607:9000:300:34::c00d",
"2607:9000:300:34::c00e",
"2607:9000:300:34::c00f",
"2607:9000:300:34::c010",
"2607:9000:300:34::c011",
"2607:9000:300:34::c012",
"2607:9000:300:34::c013",
"2607:9000:300:34::c014",
"2607:9000:300:34::c015",
"2607:9000:300:34::c016",
"2607:9000:300:34::c017",
"2607:9000:300:34::c018",
"2607:9000:300:34::c019",
"2607:9000:300:34::c01a",
"2607:9000:300:34::c01b",
"2607:9000:300:34::c01c",
"2607:9000:300:34::c01d",
"2607:9000:300:34::c01e",
"2607:9000:300:34::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-lax-wg-004.blockerad.eu"
}
}
},
{
"hostname": "us-lax-wg-005",
"location": "us-lax",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.74.2",
"include_in_country": true,
"weight": 100,
"public_key": "U3GkeSnBuP8WmQ90Nw99Q6+lrTbgIsCD2VLpVOkRQhI=",
"ipv6_addr_in": "2607:9000:300:35::f001",
"shadowsocks_extra_addr_in": [
"23.234.74.5",
"23.234.74.6",
"23.234.74.7",
"23.234.74.8",
"23.234.74.9",
"23.234.74.10",
"23.234.74.11",
"23.234.74.12",
"23.234.74.13",
"23.234.74.14",
"23.234.74.15",
"23.234.74.16",
"23.234.74.17",
"23.234.74.18",
"23.234.74.19",
"2607:9000:300:35::b002",
"2607:9000:300:35::b003",
"2607:9000:300:35::b004",
"2607:9000:300:35::b005",
"2607:9000:300:35::b006",
"2607:9000:300:35::b007",
"2607:9000:300:35::b008",
"2607:9000:300:35::b009",
"2607:9000:300:35::b00a",
"2607:9000:300:35::b00b",
"2607:9000:300:35::b00c",
"2607:9000:300:35::b00d",
"2607:9000:300:35::b00e",
"2607:9000:300:35::b00f",
"2607:9000:300:35::b010",
"2607:9000:300:35::b011",
"2607:9000:300:35::b012",
"2607:9000:300:35::b013",
"2607:9000:300:35::b014",
"2607:9000:300:35::b015",
"2607:9000:300:35::b016",
"2607:9000:300:35::b017",
"2607:9000:300:35::b018",
"2607:9000:300:35::b019",
"2607:9000:300:35::b01a",
"2607:9000:300:35::b01b",
"2607:9000:300:35::b01c",
"2607:9000:300:35::b01d",
"2607:9000:300:35::b01e",
"2607:9000:300:35::b01f"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"23.234.74.20",
"23.234.74.21",
"23.234.74.22",
"23.234.74.23",
"23.234.74.24",
"23.234.74.25",
"23.234.74.26",
"23.234.74.27",
"23.234.74.28",
"23.234.74.29",
"23.234.74.30",
"23.234.74.31",
"23.234.74.32",
"23.234.74.33",
"23.234.74.34",
"2607:9000:300:35::c002",
"2607:9000:300:35::c003",
"2607:9000:300:35::c004",
"2607:9000:300:35::c005",
"2607:9000:300:35::c006",
"2607:9000:300:35::c007",
"2607:9000:300:35::c008",
"2607:9000:300:35::c009",
"2607:9000:300:35::c00a",
"2607:9000:300:35::c00b",
"2607:9000:300:35::c00c",
"2607:9000:300:35::c00d",
"2607:9000:300:35::c00e",
"2607:9000:300:35::c00f",
"2607:9000:300:35::c010",
"2607:9000:300:35::c011",
"2607:9000:300:35::c012",
"2607:9000:300:35::c013",
"2607:9000:300:35::c014",
"2607:9000:300:35::c015",
"2607:9000:300:35::c016",
"2607:9000:300:35::c017",
"2607:9000:300:35::c018",
"2607:9000:300:35::c019",
"2607:9000:300:35::c01a",
"2607:9000:300:35::c01b",
"2607:9000:300:35::c01c",
"2607:9000:300:35::c01d",
"2607:9000:300:35::c01e",
"2607:9000:300:35::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-lax-wg-005.blockerad.eu"
}
}
},
{
"hostname": "us-lax-wg-006",
"location": "us-lax",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.74.127",
"include_in_country": true,
"weight": 100,
"public_key": "I8vdSZuJhYHhbidl21oXgiNtnHla9gjgZdm8G5UNKGU=",
"ipv6_addr_in": "2607:9000:300:36::f001",
"shadowsocks_extra_addr_in": [
"23.234.74.130",
"23.234.74.131",
"23.234.74.132",
"23.234.74.133",
"23.234.74.134",
"23.234.74.135",
"23.234.74.136",
"23.234.74.137",
"23.234.74.138",
"23.234.74.139",
"23.234.74.140",
"23.234.74.141",
"23.234.74.142",
"23.234.74.143",
"23.234.74.144",
"2607:9000:300:36::b002",
"2607:9000:300:36::b003",
"2607:9000:300:36::b004",
"2607:9000:300:36::b005",
"2607:9000:300:36::b006",
"2607:9000:300:36::b007",
"2607:9000:300:36::b008",
"2607:9000:300:36::b009",
"2607:9000:300:36::b00a",
"2607:9000:300:36::b00b",
"2607:9000:300:36::b00c",
"2607:9000:300:36::b00d",
"2607:9000:300:36::b00e",
"2607:9000:300:36::b00f",
"2607:9000:300:36::b010",
"2607:9000:300:36::b011",
"2607:9000:300:36::b012",
"2607:9000:300:36::b013",
"2607:9000:300:36::b014",
"2607:9000:300:36::b015",
"2607:9000:300:36::b016",
"2607:9000:300:36::b017",
"2607:9000:300:36::b018",
"2607:9000:300:36::b019",
"2607:9000:300:36::b01a",
"2607:9000:300:36::b01b",
"2607:9000:300:36::b01c",
"2607:9000:300:36::b01d",
"2607:9000:300:36::b01e",
"2607:9000:300:36::b01f"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"23.234.74.145",
"23.234.74.146",
"23.234.74.147",
"23.234.74.148",
"23.234.74.149",
"23.234.74.150",
"23.234.74.151",
"23.234.74.152",
"23.234.74.153",
"23.234.74.154",
"23.234.74.155",
"23.234.74.156",
"23.234.74.157",
"23.234.74.158",
"23.234.74.159",
"2607:9000:300:36::c002",
"2607:9000:300:36::c003",
"2607:9000:300:36::c004",
"2607:9000:300:36::c005",
"2607:9000:300:36::c006",
"2607:9000:300:36::c007",
"2607:9000:300:36::c008",
"2607:9000:300:36::c009",
"2607:9000:300:36::c00a",
"2607:9000:300:36::c00b",
"2607:9000:300:36::c00c",
"2607:9000:300:36::c00d",
"2607:9000:300:36::c00e",
"2607:9000:300:36::c00f",
"2607:9000:300:36::c010",
"2607:9000:300:36::c011",
"2607:9000:300:36::c012",
"2607:9000:300:36::c013",
"2607:9000:300:36::c014",
"2607:9000:300:36::c015",
"2607:9000:300:36::c016",
"2607:9000:300:36::c017",
"2607:9000:300:36::c018",
"2607:9000:300:36::c019",
"2607:9000:300:36::c01a",
"2607:9000:300:36::c01b",
"2607:9000:300:36::c01c",
"2607:9000:300:36::c01d",
"2607:9000:300:36::c01e",
"2607:9000:300:36::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-lax-wg-006.blockerad.eu"
}
}
},
{
"hostname": "us-lax-wg-007",
"location": "us-lax",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.75.2",
"include_in_country": true,
"weight": 100,
"public_key": "7O2meGDMGbd6HXpRQi7ZiuF5l4JQAoV7BejdNgiLZFQ=",
"ipv6_addr_in": "2607:9000:300:37::f001",
"shadowsocks_extra_addr_in": [
"23.234.75.5",
"23.234.75.6",
"23.234.75.7",
"23.234.75.8",
"23.234.75.9",
"23.234.75.10",
"23.234.75.11",
"23.234.75.12",
"23.234.75.13",
"23.234.75.14",
"23.234.75.15",
"23.234.75.16",
"23.234.75.17",
"23.234.75.18",
"23.234.75.19",
"2607:9000:300:37::b002",
"2607:9000:300:37::b003",
"2607:9000:300:37::b004",
"2607:9000:300:37::b005",
"2607:9000:300:37::b006",
"2607:9000:300:37::b007",
"2607:9000:300:37::b008",
"2607:9000:300:37::b009",
"2607:9000:300:37::b00a",
"2607:9000:300:37::b00b",
"2607:9000:300:37::b00c",
"2607:9000:300:37::b00d",
"2607:9000:300:37::b00e",
"2607:9000:300:37::b00f",
"2607:9000:300:37::b010",
"2607:9000:300:37::b011",
"2607:9000:300:37::b012",
"2607:9000:300:37::b013",
"2607:9000:300:37::b014",
"2607:9000:300:37::b015",
"2607:9000:300:37::b016",
"2607:9000:300:37::b017",
"2607:9000:300:37::b018",
"2607:9000:300:37::b019",
"2607:9000:300:37::b01a",
"2607:9000:300:37::b01b",
"2607:9000:300:37::b01c",
"2607:9000:300:37::b01d",
"2607:9000:300:37::b01e",
"2607:9000:300:37::b01f"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"23.234.75.20",
"23.234.75.21",
"23.234.75.22",
"23.234.75.23",
"23.234.75.24",
"23.234.75.25",
"23.234.75.26",
"23.234.75.27",
"23.234.75.28",
"23.234.75.29",
"23.234.75.30",
"23.234.75.31",
"23.234.75.32",
"23.234.75.33",
"23.234.75.34",
"2607:9000:300:37::c002",
"2607:9000:300:37::c003",
"2607:9000:300:37::c004",
"2607:9000:300:37::c005",
"2607:9000:300:37::c006",
"2607:9000:300:37::c007",
"2607:9000:300:37::c008",
"2607:9000:300:37::c009",
"2607:9000:300:37::c00a",
"2607:9000:300:37::c00b",
"2607:9000:300:37::c00c",
"2607:9000:300:37::c00d",
"2607:9000:300:37::c00e",
"2607:9000:300:37::c00f",
"2607:9000:300:37::c010",
"2607:9000:300:37::c011",
"2607:9000:300:37::c012",
"2607:9000:300:37::c013",
"2607:9000:300:37::c014",
"2607:9000:300:37::c015",
"2607:9000:300:37::c016",
"2607:9000:300:37::c017",
"2607:9000:300:37::c018",
"2607:9000:300:37::c019",
"2607:9000:300:37::c01a",
"2607:9000:300:37::c01b",
"2607:9000:300:37::c01c",
"2607:9000:300:37::c01d",
"2607:9000:300:37::c01e",
"2607:9000:300:37::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-lax-wg-007.blockerad.eu"
}
}
},
{
"hostname": "us-lax-wg-008",
"location": "us-lax",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.75.127",
"include_in_country": true,
"weight": 100,
"public_key": "8qtzkafLNGJkfgtuYc8bPeKN0apyyZrZ3Pq4tCkqIxc=",
"ipv6_addr_in": "2607:9000:300:38::f001",
"shadowsocks_extra_addr_in": [
"23.234.75.130",
"23.234.75.131",
"23.234.75.132",
"23.234.75.133",
"23.234.75.134",
"23.234.75.135",
"23.234.75.136",
"23.234.75.137",
"23.234.75.138",
"23.234.75.139",
"23.234.75.140",
"23.234.75.141",
"23.234.75.142",
"23.234.75.143",
"23.234.75.144",
"2607:9000:300:38::b002",
"2607:9000:300:38::b003",
"2607:9000:300:38::b004",
"2607:9000:300:38::b005",
"2607:9000:300:38::b006",
"2607:9000:300:38::b007",
"2607:9000:300:38::b008",
"2607:9000:300:38::b009",
"2607:9000:300:38::b00a",
"2607:9000:300:38::b00b",
"2607:9000:300:38::b00c",
"2607:9000:300:38::b00d",
"2607:9000:300:38::b00e",
"2607:9000:300:38::b00f",
"2607:9000:300:38::b010",
"2607:9000:300:38::b011",
"2607:9000:300:38::b012",
"2607:9000:300:38::b013",
"2607:9000:300:38::b014",
"2607:9000:300:38::b015",
"2607:9000:300:38::b016",
"2607:9000:300:38::b017",
"2607:9000:300:38::b018",
"2607:9000:300:38::b019",
"2607:9000:300:38::b01a",
"2607:9000:300:38::b01b",
"2607:9000:300:38::b01c",
"2607:9000:300:38::b01d",
"2607:9000:300:38::b01e",
"2607:9000:300:38::b01f"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"23.234.75.145",
"23.234.75.146",
"23.234.75.147",
"23.234.75.148",
"23.234.75.149",
"23.234.75.150",
"23.234.75.151",
"23.234.75.152",
"23.234.75.153",
"23.234.75.154",
"23.234.75.155",
"23.234.75.156",
"23.234.75.157",
"23.234.75.158",
"23.234.75.159",
"2607:9000:300:38::c002",
"2607:9000:300:38::c003",
"2607:9000:300:38::c004",
"2607:9000:300:38::c005",
"2607:9000:300:38::c006",
"2607:9000:300:38::c007",
"2607:9000:300:38::c008",
"2607:9000:300:38::c009",
"2607:9000:300:38::c00a",
"2607:9000:300:38::c00b",
"2607:9000:300:38::c00c",
"2607:9000:300:38::c00d",
"2607:9000:300:38::c00e",
"2607:9000:300:38::c00f",
"2607:9000:300:38::c010",
"2607:9000:300:38::c011",
"2607:9000:300:38::c012"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-lax-wg-008.blockerad.eu"
}
}
},
{
"hostname": "us-lax-wg-201",
"location": "us-lax",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "169.150.203.2",
"include_in_country": false,
"weight": 100,
"public_key": "xWobY7DWTL+vL1yD4NWwbQ3V4e8qz10Yz+EFdkIjq0Y=",
"ipv6_addr_in": "2a02:6ea0:c859:1::a01f"
},
{
"hostname": "us-lax-wg-202",
"location": "us-lax",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "169.150.203.15",
"include_in_country": false,
"weight": 100,
"public_key": "SDnciTlujuy2APFTkhzfq5X+LDi+lhfU38wI2HBCxxs=",
"ipv6_addr_in": "2a02:6ea0:c859:2::a02f"
},
{
"hostname": "us-lax-wg-203",
"location": "us-lax",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "169.150.203.28",
"include_in_country": true,
"weight": 1,
"public_key": "W6/Yamxmfx3geWTwwtBbJe/J8UdEzOfa6M+cEpNPIwg=",
"ipv6_addr_in": "2a02:6ea0:c859:3::a03f",
"daita": true,
"features": {
"daita": {},
"lwo": {}
}
},
{
"hostname": "us-lax-wg-402",
"location": "us-lax",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.173.66",
"include_in_country": false,
"weight": 100,
"public_key": "EKZXvHlSDeqAjfC/m9aQR0oXfQ6Idgffa9L0DH5yaCo=",
"ipv6_addr_in": "2a0d:5600:8:6::d2f",
"features": {
"lwo": {}
}
},
{
"hostname": "us-lax-wg-403",
"location": "us-lax",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.173.130",
"include_in_country": false,
"weight": 100,
"public_key": "mBqaWs6pti93U+1feyj6LRzzveNmeklancn3XuKoPWI=",
"ipv6_addr_in": "2a0d:5600:8:d::d3f",
"features": {
"lwo": {}
}
},
{
"hostname": "us-lax-wg-404",
"location": "us-lax",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.173.194",
"include_in_country": false,
"weight": 100,
"public_key": "YGl+lj1tk08U9x9Z73zowUW3rk8i0nPmYkxGzNdE4VM=",
"ipv6_addr_in": "2a0d:5600:8:2f::f001",
"features": {
"lwo": {}
}
},
{
"hostname": "us-lax-wg-405",
"location": "us-lax",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.172.2",
"include_in_country": false,
"weight": 100,
"public_key": "Pe86fNGUd+AIeaabsn7Hk4clQf1kJvxOXPykfVGjeho=",
"ipv6_addr_in": "2a0d:5600:8:37::f001"
},
{
"hostname": "us-lax-wg-406",
"location": "us-lax",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.174.2",
"include_in_country": false,
"weight": 1,
"public_key": "K3KF3TCWbYcHF5XHL2zaifvQGHrPWoCjFYxDaJO71GA=",
"ipv6_addr_in": "2a0d:5600:8:3b::f001",
"features": {
"lwo": {},
"quic": {
"addr_in": [
"146.70.174.62"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-lax-wg-406.blockerad.eu"
}
}
},
{
"hostname": "us-lax-wg-407",
"location": "us-lax",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.172.66",
"include_in_country": true,
"weight": 100,
"public_key": "1nGkBr+oLwK5lQcVt9vF6rGM5R3ra5bmYTGJfGIh0lk=",
"ipv6_addr_in": "2a0d:5600:8:38::f001"
},
{
"hostname": "us-lax-wg-408",
"location": "us-lax",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.172.130",
"include_in_country": true,
"weight": 100,
"public_key": "9L5cW9VuUJUS2gH6H7ln2JeCI66fMnnjLiD5UymAtlo=",
"ipv6_addr_in": "2a0d:5600:8:39::f001"
},
{
"hostname": "us-lax-wg-409",
"location": "us-lax",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.172.194",
"include_in_country": true,
"weight": 100,
"public_key": "V+LTWA5DxEVITAXqHexqBzeZo95b8r+3WR8g1FsbPQ4=",
"ipv6_addr_in": "2a0d:5600:8:3a::f001"
},
{
"hostname": "us-lax-wg-601",
"location": "us-lax",
"active": true,
"owned": false,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "23.162.40.3",
"include_in_country": true,
"weight": 100,
"public_key": "oA6/33kBggrBOJ7z+uo5gZW6L1w2zYcCILKXXax8knY=",
"ipv6_addr_in": "2602:fa19::f001",
"shadowsocks_extra_addr_in": [
"23.162.40.14"
]
},
{
"hostname": "us-lax-wg-602",
"location": "us-lax",
"active": true,
"owned": false,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "23.162.40.127",
"include_in_country": true,
"weight": 100,
"public_key": "oLu1H6C8YaoWtmaPzAFboFX8r102Wb1uma9spVPqAX8=",
"ipv6_addr_in": "2602:fa19::f101",
"shadowsocks_extra_addr_in": [
"23.162.40.139"
]
},
{
"hostname": "us-lax-wg-603",
"location": "us-lax",
"active": true,
"owned": false,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "23.159.216.3",
"include_in_country": true,
"weight": 100,
"public_key": "qeojNB247YQbT0/ysFyZDjs9RJ6Y4bFaKCLu6PjeMxA=",
"ipv6_addr_in": "2602:fa47::f001",
"shadowsocks_extra_addr_in": [
"23.159.216.14"
]
},
{
"hostname": "us-lax-wg-604",
"location": "us-lax",
"active": true,
"owned": false,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "23.159.216.127",
"include_in_country": true,
"weight": 100,
"public_key": "GKl6nhOl96/1AJtVCdEZpOO6F0BS5/TMkrjdH2fb93A=",
"ipv6_addr_in": "2602:fa47::f101",
"shadowsocks_extra_addr_in": [
"23.159.216.139"
]
},
{
"hostname": "us-lax-wg-605",
"location": "us-lax",
"active": true,
"owned": false,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "23.160.24.3",
"include_in_country": true,
"weight": 100,
"public_key": "DbZksYqiYPGxOEF7iIaAiyN4+hZc+8HcuMMqpLW3XmA=",
"ipv6_addr_in": "2602:fa45::f001",
"shadowsocks_extra_addr_in": [
"23.160.24.14"
]
},
{
"hostname": "us-lax-wg-606",
"location": "us-lax",
"active": true,
"owned": false,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "23.160.24.127",
"include_in_country": true,
"weight": 100,
"public_key": "AW1YO/vYtXJioBmD8BhSGpz1DQNIQeU+jOu+3F7KBDY=",
"ipv6_addr_in": "2602:fa45::f101",
"shadowsocks_extra_addr_in": [
"23.160.24.139"
]
},
{
"hostname": "us-lax-wg-607",
"location": "us-lax",
"active": true,
"owned": false,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "23.168.216.3",
"include_in_country": true,
"weight": 100,
"public_key": "ItEcyDXwTXtq6bQubbO6lY0K/oh0dfk26AV+muU+Ah4=",
"ipv6_addr_in": "2602:f99d::f001",
"shadowsocks_extra_addr_in": [
"23.168.216.14"
]
},
{
"hostname": "us-lax-wg-608",
"location": "us-lax",
"active": true,
"owned": false,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "23.168.216.127",
"include_in_country": true,
"weight": 100,
"public_key": "ikLR1TUKk+PTWFnydqwZ9m0HaD1dPaMNI9DwZTvzYBs=",
"ipv6_addr_in": "2602:f99d::f101",
"shadowsocks_extra_addr_in": [
"23.168.216.139"
]
},
{
"hostname": "us-lax-wg-701",
"location": "us-lax",
"active": true,
"owned": false,
"provider": "HostRoyale",
"stboot": true,
"ipv4_addr_in": "103.251.26.3",
"include_in_country": true,
"weight": 100,
"public_key": "EM/33kdl9RiNOF5jvwtp/nfchPAD/sq7MJleg1bZikU=",
"ipv6_addr_in": "2a01:4740:3::f001",
"shadowsocks_extra_addr_in": [
"103.251.26.14"
]
},
{
"hostname": "us-lax-wg-702",
"location": "us-lax",
"active": true,
"owned": false,
"provider": "HostRoyale",
"stboot": true,
"ipv4_addr_in": "103.251.26.127",
"include_in_country": true,
"weight": 100,
"public_key": "ddv7vosBlf396nOa79nWn6qXQu2LzezGXfNUDO3hAXQ=",
"ipv6_addr_in": "2a01:4740:3::f101",
"shadowsocks_extra_addr_in": [
"103.251.26.139"
]
},
{
"hostname": "us-lax-wg-703",
"location": "us-lax",
"active": true,
"owned": false,
"provider": "HostRoyale",
"stboot": true,
"ipv4_addr_in": "103.251.27.3",
"include_in_country": true,
"weight": 100,
"public_key": "/FWUNK2WlEQbmwYaXuTzUmtshvIYvJnKWVnuqgzlfXw=",
"ipv6_addr_in": "2a01:4740:3::f201",
"shadowsocks_extra_addr_in": [
"103.251.27.14"
]
},
{
"hostname": "us-lax-wg-704",
"location": "us-lax",
"active": true,
"owned": false,
"provider": "HostRoyale",
"stboot": true,
"ipv4_addr_in": "103.251.27.127",
"include_in_country": true,
"weight": 100,
"public_key": "KPjr8jrGP3dVI+GbMq2LNc9eREW6EhGHndoSWHqakxE=",
"ipv6_addr_in": "2a01:4740:3::f301",
"shadowsocks_extra_addr_in": [
"103.251.27.139"
]
},
{
"hostname": "us-mia-wg-001",
"location": "us-mia",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "45.134.142.219",
"include_in_country": true,
"weight": 100,
"public_key": "FVEKAMJqaJU2AwWn5Mg9TK9IAfJc4XDUmSzEeC/VXGs=",
"ipv6_addr_in": "2a02:6ea0:cc1f:2::b62f",
"features": {
"lwo": {}
}
},
{
"hostname": "us-mia-wg-002",
"location": "us-mia",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "45.134.142.206",
"include_in_country": true,
"weight": 200,
"public_key": "H5t7PsMDnUAHrR8D2Jt3Mh6N6w43WmCzrOHShlEU+zw=",
"ipv6_addr_in": "2a02:6ea0:cc1f:1::b61f",
"features": {
"lwo": {}
}
},
{
"hostname": "us-mia-wg-003",
"location": "us-mia",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "45.134.142.193",
"include_in_country": true,
"weight": 200,
"public_key": "N/3F0QvCuiWWzCwaJmnPZO53LZrKn6sr7rItecrQSQY=",
"ipv6_addr_in": "2a02:6ea0:cc1f::f001",
"features": {
"lwo": {}
}
},
{
"hostname": "us-mia-wg-101",
"location": "us-mia",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.187.2",
"include_in_country": true,
"weight": 100,
"public_key": "Mn0lrr3cYuJQyIqWGSWv99MwJAS+VqlYmODpOpY3e0U=",
"ipv6_addr_in": "2001:ac8:40:11::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"146.70.187.13",
"146.70.187.14",
"146.70.187.15",
"146.70.187.16",
"146.70.187.17",
"146.70.187.18",
"146.70.187.19",
"146.70.187.20",
"146.70.187.21",
"146.70.187.22",
"2001:ac8:40:11::b002",
"2001:ac8:40:11::b003",
"2001:ac8:40:11::b004",
"2001:ac8:40:11::b005",
"2001:ac8:40:11::b006",
"2001:ac8:40:11::b007",
"2001:ac8:40:11::b008",
"2001:ac8:40:11::b009",
"2001:ac8:40:11::b00a",
"2001:ac8:40:11::b00b",
"2001:ac8:40:11::b00c",
"2001:ac8:40:11::b00d",
"2001:ac8:40:11::b00e",
"2001:ac8:40:11::b00f",
"2001:ac8:40:11::b010",
"2001:ac8:40:11::b011",
"2001:ac8:40:11::b012",
"2001:ac8:40:11::b013",
"2001:ac8:40:11::b014",
"2001:ac8:40:11::b015",
"2001:ac8:40:11::b016",
"2001:ac8:40:11::b017",
"2001:ac8:40:11::b018",
"2001:ac8:40:11::b019",
"2001:ac8:40:11::b01a",
"2001:ac8:40:11::b01b",
"2001:ac8:40:11::b01c",
"2001:ac8:40:11::b01d",
"2001:ac8:40:11::b01e",
"2001:ac8:40:11::b01f"
],
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"146.70.187.23",
"146.70.187.24",
"146.70.187.25",
"146.70.187.26",
"146.70.187.27",
"146.70.187.28",
"146.70.187.29",
"146.70.187.30",
"146.70.187.31",
"146.70.187.32",
"2001:ac8:40:11::c002",
"2001:ac8:40:11::c003",
"2001:ac8:40:11::c004",
"2001:ac8:40:11::c005",
"2001:ac8:40:11::c006",
"2001:ac8:40:11::c007",
"2001:ac8:40:11::c008",
"2001:ac8:40:11::c009",
"2001:ac8:40:11::c00a",
"2001:ac8:40:11::c00b",
"2001:ac8:40:11::c00c",
"2001:ac8:40:11::c00d",
"2001:ac8:40:11::c00e",
"2001:ac8:40:11::c00f",
"2001:ac8:40:11::c010",
"2001:ac8:40:11::c011",
"2001:ac8:40:11::c012",
"2001:ac8:40:11::c013",
"2001:ac8:40:11::c014",
"2001:ac8:40:11::c015",
"2001:ac8:40:11::c016",
"2001:ac8:40:11::c017",
"2001:ac8:40:11::c018",
"2001:ac8:40:11::c019",
"2001:ac8:40:11::c01a",
"2001:ac8:40:11::c01b",
"2001:ac8:40:11::c01c",
"2001:ac8:40:11::c01d",
"2001:ac8:40:11::c01e",
"2001:ac8:40:11::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-mia-wg-101.blockerad.eu"
}
}
},
{
"hostname": "us-mia-wg-102",
"location": "us-mia",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.187.130",
"include_in_country": true,
"weight": 100,
"public_key": "4X0whnzbu8PkdJd9znks3vXx4JyI0asFf/241XjPdks=",
"ipv6_addr_in": "2a0d:5600:6:105::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"146.70.187.141",
"146.70.187.142",
"146.70.187.143",
"146.70.187.144",
"146.70.187.145",
"146.70.187.146",
"146.70.187.147",
"146.70.187.148",
"146.70.187.149",
"146.70.187.150",
"2a0d:5600:6:105::b002",
"2a0d:5600:6:105::b003",
"2a0d:5600:6:105::b004",
"2a0d:5600:6:105::b005",
"2a0d:5600:6:105::b006",
"2a0d:5600:6:105::b007",
"2a0d:5600:6:105::b008",
"2a0d:5600:6:105::b009",
"2a0d:5600:6:105::b00a",
"2a0d:5600:6:105::b00b",
"2a0d:5600:6:105::b00c",
"2a0d:5600:6:105::b00d",
"2a0d:5600:6:105::b00e",
"2a0d:5600:6:105::b00f",
"2a0d:5600:6:105::b010",
"2a0d:5600:6:105::b011",
"2a0d:5600:6:105::b012",
"2a0d:5600:6:105::b013",
"2a0d:5600:6:105::b014",
"2a0d:5600:6:105::b015",
"2a0d:5600:6:105::b016",
"2a0d:5600:6:105::b017",
"2a0d:5600:6:105::b018",
"2a0d:5600:6:105::b019",
"2a0d:5600:6:105::b01a",
"2a0d:5600:6:105::b01b",
"2a0d:5600:6:105::b01c",
"2a0d:5600:6:105::b01d",
"2a0d:5600:6:105::b01e",
"2a0d:5600:6:105::b01f"
],
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"146.70.187.151",
"146.70.187.152",
"146.70.187.153",
"146.70.187.154",
"146.70.187.155",
"146.70.187.156",
"146.70.187.157",
"146.70.187.158",
"146.70.187.159",
"146.70.187.160",
"2a0d:5600:6:105::c002",
"2a0d:5600:6:105::c003",
"2a0d:5600:6:105::c004",
"2a0d:5600:6:105::c005",
"2a0d:5600:6:105::c006",
"2a0d:5600:6:105::c007",
"2a0d:5600:6:105::c008",
"2a0d:5600:6:105::c009",
"2a0d:5600:6:105::c00a",
"2a0d:5600:6:105::c00b",
"2a0d:5600:6:105::c00c",
"2a0d:5600:6:105::c00d",
"2a0d:5600:6:105::c00e",
"2a0d:5600:6:105::c00f",
"2a0d:5600:6:105::c010",
"2a0d:5600:6:105::c011",
"2a0d:5600:6:105::c012",
"2a0d:5600:6:105::c013",
"2a0d:5600:6:105::c014",
"2a0d:5600:6:105::c015",
"2a0d:5600:6:105::c016",
"2a0d:5600:6:105::c017",
"2a0d:5600:6:105::c018",
"2a0d:5600:6:105::c019",
"2a0d:5600:6:105::c01a",
"2a0d:5600:6:105::c01b",
"2a0d:5600:6:105::c01c",
"2a0d:5600:6:105::c01d",
"2a0d:5600:6:105::c01e",
"2a0d:5600:6:105::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-mia-wg-102.blockerad.eu"
}
}
},
{
"hostname": "us-mia-wg-103",
"location": "us-mia",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "135.136.36.2",
"include_in_country": true,
"weight": 100,
"public_key": "AvtyY8vuNyROYZQYnBCk5UTsfxb8J43Ztm9cjuHMBUg=",
"ipv6_addr_in": "2a0d:5600:6:106::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"135.136.36.13",
"135.136.36.14",
"135.136.36.15",
"135.136.36.16",
"135.136.36.17",
"135.136.36.18",
"135.136.36.19",
"135.136.36.20",
"135.136.36.21",
"135.136.36.22",
"2a0d:5600:6:106::b002",
"2a0d:5600:6:106::b003",
"2a0d:5600:6:106::b004",
"2a0d:5600:6:106::b005",
"2a0d:5600:6:106::b006",
"2a0d:5600:6:106::b007",
"2a0d:5600:6:106::b008",
"2a0d:5600:6:106::b009",
"2a0d:5600:6:106::b00a",
"2a0d:5600:6:106::b00b",
"2a0d:5600:6:106::b00c",
"2a0d:5600:6:106::b00d",
"2a0d:5600:6:106::b00e",
"2a0d:5600:6:106::b00f",
"2a0d:5600:6:106::b010",
"2a0d:5600:6:106::b011",
"2a0d:5600:6:106::b012",
"2a0d:5600:6:106::b013",
"2a0d:5600:6:106::b014",
"2a0d:5600:6:106::b015",
"2a0d:5600:6:106::b016",
"2a0d:5600:6:106::b017",
"2a0d:5600:6:106::b018",
"2a0d:5600:6:106::b019",
"2a0d:5600:6:106::b01a",
"2a0d:5600:6:106::b01b",
"2a0d:5600:6:106::b01c",
"2a0d:5600:6:106::b01d",
"2a0d:5600:6:106::b01e",
"2a0d:5600:6:106::b01f"
],
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"135.136.36.23",
"135.136.36.24",
"135.136.36.25",
"135.136.36.26",
"135.136.36.27",
"135.136.36.28",
"135.136.36.29",
"135.136.36.30",
"135.136.36.31",
"135.136.36.32",
"2a0d:5600:6:106::c002",
"2a0d:5600:6:106::c003",
"2a0d:5600:6:106::c004",
"2a0d:5600:6:106::c005",
"2a0d:5600:6:106::c006",
"2a0d:5600:6:106::c007",
"2a0d:5600:6:106::c008",
"2a0d:5600:6:106::c009",
"2a0d:5600:6:106::c00a",
"2a0d:5600:6:106::c00b",
"2a0d:5600:6:106::c00c",
"2a0d:5600:6:106::c00d",
"2a0d:5600:6:106::c00e",
"2a0d:5600:6:106::c00f",
"2a0d:5600:6:106::c010",
"2a0d:5600:6:106::c011",
"2a0d:5600:6:106::c012",
"2a0d:5600:6:106::c013",
"2a0d:5600:6:106::c014",
"2a0d:5600:6:106::c015",
"2a0d:5600:6:106::c016",
"2a0d:5600:6:106::c017",
"2a0d:5600:6:106::c018",
"2a0d:5600:6:106::c019",
"2a0d:5600:6:106::c01a",
"2a0d:5600:6:106::c01b",
"2a0d:5600:6:106::c01c",
"2a0d:5600:6:106::c01d",
"2a0d:5600:6:106::c01e",
"2a0d:5600:6:106::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-mia-wg-103.blockerad.eu"
}
}
},
{
"hostname": "us-mkc-wg-001",
"location": "us-mkc",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.116.3",
"include_in_country": true,
"weight": 100,
"public_key": "0EwMQYJ2uo6xu0C3lOEfsxMdc4NpFOURVc0JPJqkhlI=",
"ipv6_addr_in": "2607:9000:e00:2::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"23.234.116.14"
],
"features": {
"daita": {}
}
},
{
"hostname": "us-mkc-wg-002",
"location": "us-mkc",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.116.127",
"include_in_country": true,
"weight": 100,
"public_key": "XeYfktwZerrhrXzVVEd9FQUw5MaUwv2gZmkTJWK8wSU=",
"ipv6_addr_in": "2607:9000:e00:3::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"23.234.116.139"
],
"features": {
"daita": {}
}
},
{
"hostname": "us-mkc-wg-003",
"location": "us-mkc",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.117.3",
"include_in_country": true,
"weight": 100,
"public_key": "FOPZvXEnM1XWHH+WY17JX25N4EwJz6SSmqmAxP5y7CA=",
"ipv6_addr_in": "2607:9000:e00:4::f001",
"shadowsocks_extra_addr_in": [
"23.234.117.14"
]
},
{
"hostname": "us-mkc-wg-004",
"location": "us-mkc",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.117.127",
"include_in_country": true,
"weight": 100,
"public_key": "8ueNKHj+2nbTpnnv4MpxY98VrhtIKSMMwh0R9HF6iyE=",
"ipv6_addr_in": "2607:9000:e00:5::f001",
"shadowsocks_extra_addr_in": [
"23.234.117.139"
]
},
{
"hostname": "us-mkc-wg-005",
"location": "us-mkc",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.118.3",
"include_in_country": true,
"weight": 100,
"public_key": "KHbQz9XJVVj5M/sK3azWfgNyybdLNOjXahnHIzYYqXY=",
"ipv6_addr_in": "2607:9000:e00:6::f001",
"shadowsocks_extra_addr_in": [
"23.234.118.14"
]
},
{
"hostname": "us-mkc-wg-006",
"location": "us-mkc",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.118.127",
"include_in_country": true,
"weight": 100,
"public_key": "bQWDsoitERBoPnP0AXI/jCUhk4AX8cMFbhCW93wn3HM=",
"ipv6_addr_in": "2607:9000:e00:7::f001",
"shadowsocks_extra_addr_in": [
"23.234.118.139"
]
},
{
"hostname": "us-mkc-wg-007",
"location": "us-mkc",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.119.3",
"include_in_country": true,
"weight": 100,
"public_key": "e7BOh4K+tNWSnwUMWKI7yDCiskyamqXtpLjcg00KTn8=",
"ipv6_addr_in": "2607:9000:e00:8::f001",
"shadowsocks_extra_addr_in": [
"23.234.119.14"
]
},
{
"hostname": "us-mkc-wg-008",
"location": "us-mkc",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.119.127",
"include_in_country": true,
"weight": 100,
"public_key": "9PByPs4okeg0lWhPYkW7tuyw1XKy5+BKhgVuQbxSOk4=",
"ipv6_addr_in": "2607:9000:e00:9::f001",
"shadowsocks_extra_addr_in": [
"23.234.119.139"
]
},
{
"hostname": "us-mkc-wg-101",
"location": "us-mkc",
"active": true,
"owned": false,
"provider": "hostuniversal",
"stboot": true,
"ipv4_addr_in": "155.2.191.3",
"include_in_country": true,
"weight": 100,
"public_key": "Nk6dTIVRHBQzIZ6CUrJH7l4dItXEz3XOSBwmI933WUo=",
"ipv6_addr_in": "2602:fed2:7e0a::f001",
"shadowsocks_extra_addr_in": [
"155.2.191.14"
]
},
{
"hostname": "us-mkc-wg-102",
"location": "us-mkc",
"active": true,
"owned": false,
"provider": "hostuniversal",
"stboot": true,
"ipv4_addr_in": "155.2.191.53",
"include_in_country": true,
"weight": 100,
"public_key": "ie5ag1xd2x/P3fxodzB21vPbLEmqhtfqKcUs1OR0BDs=",
"ipv6_addr_in": "2602:fed2:7e0a::f101",
"shadowsocks_extra_addr_in": [
"155.2.191.64"
]
},
{
"hostname": "us-mkc-wg-103",
"location": "us-mkc",
"active": true,
"owned": false,
"provider": "hostuniversal",
"stboot": true,
"ipv4_addr_in": "155.2.191.103",
"include_in_country": true,
"weight": 100,
"public_key": "5dpXegNTyOFwWswBaJxViEwrXSAgC+Je9KokpT1sdjU=",
"ipv6_addr_in": "2602:fed2:7e0a::f201",
"shadowsocks_extra_addr_in": [
"155.2.191.114"
]
},
{
"hostname": "us-mkc-wg-104",
"location": "us-mkc",
"active": true,
"owned": false,
"provider": "hostuniversal",
"stboot": true,
"ipv4_addr_in": "155.2.191.153",
"include_in_country": true,
"weight": 100,
"public_key": "wugRpkJNlfAV2lE3p1UXsTfZtO8JYWEdA9ZMLFeF3G4=",
"ipv6_addr_in": "2602:fed2:7e0a::f301",
"shadowsocks_extra_addr_in": [
"155.2.191.164"
]
},
{
"hostname": "us-mkc-wg-105",
"location": "us-mkc",
"active": true,
"owned": false,
"provider": "hostuniversal",
"stboot": true,
"ipv4_addr_in": "155.2.191.203",
"include_in_country": true,
"weight": 100,
"public_key": "9w1yXK8tpAKZ2au6JHcu+L7TytOYmmZo9q7qfCwa1U8=",
"ipv6_addr_in": "2602:fed2:7e0a::f401",
"shadowsocks_extra_addr_in": [
"155.2.191.214"
]
},
{
"hostname": "us-nyc-wg-301",
"location": "us-nyc",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "143.244.47.65",
"include_in_country": true,
"weight": 100,
"public_key": "IzqkjVCdJYC1AShILfzebchTlKCqVCt/SMEXolaS3Uc=",
"ipv6_addr_in": "2a02:6ea0:c43f::f001"
},
{
"hostname": "us-nyc-wg-302",
"location": "us-nyc",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "143.244.47.78",
"include_in_country": true,
"weight": 100,
"public_key": "gH/fZJwc9iLv9fazk09J/DUWT2X7/LFXijRS15e2n34=",
"ipv6_addr_in": "2a02:6ea0:c43f:1::f001"
},
{
"hostname": "us-nyc-wg-303",
"location": "us-nyc",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "143.244.47.91",
"include_in_country": true,
"weight": 1,
"public_key": "KRO+RzrFV92Ah+qpHgAMKZH2jtjRlmJ4ayl0gletY3c=",
"ipv6_addr_in": "2a02:6ea0:c43f:2::b52f",
"features": {
"lwo": {},
"quic": {
"addr_in": [
"143.244.47.103"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-nyc-wg-303.blockerad.eu"
}
}
},
{
"hostname": "us-nyc-wg-501",
"location": "us-nyc",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.165.2",
"include_in_country": true,
"weight": 1,
"public_key": "FMNXnFgDHNTrT9o49U8bb3Z8J90LZzVJPpRzKtJM9W8=",
"ipv6_addr_in": "2a0d:5600:24:2b6::f001"
},
{
"hostname": "us-nyc-wg-502",
"location": "us-nyc",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.165.130",
"include_in_country": true,
"weight": 100,
"public_key": "cmUR4g9aIFDa5Xnp4B6Zjyp20jwgTTMgBdhcdvDV0FM=",
"ipv6_addr_in": "2a0d:5600:24:2b8::f001"
},
{
"hostname": "us-nyc-wg-503",
"location": "us-nyc",
"active": false,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.165.194",
"include_in_country": true,
"weight": 100,
"public_key": "czE6NJ8CccA5jnJkKoZGDpMXFqSudeVTzxU5scLP/H8=",
"ipv6_addr_in": "2a0d:5600:24:2b9::f001"
},
{
"hostname": "us-nyc-wg-504",
"location": "us-nyc",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.166.130",
"include_in_country": true,
"weight": 100,
"public_key": "MVa5yuoYnjXJtSCeBsyvaemuaK4KFN1p78+37Nvm2m0=",
"ipv6_addr_in": "2a0d:5600:24:2c2::f001"
},
{
"hostname": "us-nyc-wg-505",
"location": "us-nyc",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.166.194",
"include_in_country": true,
"weight": 100,
"public_key": "jrjogHbVDuPxyloBldvtB51TmebNJo+4rW2JFrN33iM=",
"ipv6_addr_in": "2a0d:5600:24:2c3::f001"
},
{
"hostname": "us-nyc-wg-506",
"location": "us-nyc",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.165.66",
"include_in_country": true,
"weight": 100,
"public_key": "IjdtI6sz8ZjU5tlK3eW4HAPp+GRvHErDtqxBcr8JvTM=",
"ipv6_addr_in": "2a0d:5600:24:2b7::f001"
},
{
"hostname": "us-nyc-wg-601",
"location": "us-nyc",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.185.2",
"include_in_country": true,
"weight": 1,
"public_key": "OKyEPafS1lnUTWqtVeWElkTzcmkvLi9dncBHbSyFrH8=",
"ipv6_addr_in": "2a0d:5600:24:136a::f001",
"features": {
"quic": {
"addr_in": [
"146.70.185.62"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-nyc-wg-601.blockerad.eu"
}
}
},
{
"hostname": "us-nyc-wg-602",
"location": "us-nyc",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.168.130",
"include_in_country": true,
"weight": 100,
"public_key": "4Lg7yQlukAMp6EX+2Ap+q4O+QIV/OEZyybtFJmN9umw=",
"ipv6_addr_in": "2a0d:5600:24:1378::f001"
},
{
"hostname": "us-nyc-wg-603",
"location": "us-nyc",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.168.66",
"include_in_country": true,
"weight": 100,
"public_key": "s3N8Xeh6khECbgRYPk9pp5slw2uE0deOxa9rSJ6bzwE=",
"ipv6_addr_in": "2a0d:5600:24:1377::f001"
},
{
"hostname": "us-nyc-wg-604",
"location": "us-nyc",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.171.66",
"include_in_country": true,
"weight": 100,
"public_key": "FIcFPDjxfF24xBrv+W7Bcqb2wADSWd+HAWPKYo6xZEk=",
"ipv6_addr_in": "2a0d:5600:24:1372::f001"
},
{
"hostname": "us-nyc-wg-605",
"location": "us-nyc",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.171.130",
"include_in_country": true,
"weight": 100,
"public_key": "78nFhfPEjrfOxBkUf2ylM7w6upYBEcHXm93sr8CMTE4=",
"ipv6_addr_in": "2a0d:5600:24:1374::f001"
},
{
"hostname": "us-nyc-wg-606",
"location": "us-nyc",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.168.194",
"include_in_country": true,
"weight": 100,
"public_key": "a8+VB6Cgah7Q5mWY860VfgU/h3Zf+pMpMdHB22e1uTQ=",
"ipv6_addr_in": "2a0d:5600:24:1379::f001"
},
{
"hostname": "us-nyc-wg-701",
"location": "us-nyc",
"active": false,
"owned": false,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "23.162.8.3",
"include_in_country": true,
"weight": 1,
"public_key": "S3X2pCfD9X6c29fd4C6b86mEO0b01mc/WUCDN5OgyjM=",
"ipv6_addr_in": "2602:fa1f:1::f001",
"shadowsocks_extra_addr_in": [
"23.162.8.9"
]
},
{
"hostname": "us-nyc-wg-702",
"location": "us-nyc",
"active": true,
"owned": false,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "23.162.8.67",
"include_in_country": true,
"weight": 100,
"public_key": "O81+YN0WHF4wuWRejhPG62PGK9bv/8BQTa6Ni3fomWM=",
"ipv6_addr_in": "2602:fa1f:1::f033",
"shadowsocks_extra_addr_in": [
"23.162.8.73"
]
},
{
"hostname": "us-nyc-wg-703",
"location": "us-nyc",
"active": false,
"owned": false,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "23.162.8.130",
"include_in_country": true,
"weight": 1,
"public_key": "Ycm86cSu1NKGpC+vZA6htq6YE9BUFk9wweE2/RySA1g=",
"ipv6_addr_in": "2602:fa1f:1:3::f001",
"shadowsocks_extra_addr_in": [
"23.162.8.136"
]
},
{
"hostname": "us-nyc-wg-801",
"location": "us-nyc",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.100.3",
"include_in_country": true,
"weight": 100,
"public_key": "3XVRp858LSMwQ6pA2Zo5LFGf4nIjLnuTkbXTJiNPcmo=",
"ipv6_addr_in": "2607:9000:a000:31::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"23.234.100.14"
],
"features": {
"daita": {},
"quic": {
"addr_in": [
"23.234.100.13"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-nyc-wg-801.blockerad.eu"
}
}
},
{
"hostname": "us-nyc-wg-802",
"location": "us-nyc",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.100.127",
"include_in_country": true,
"weight": 100,
"public_key": "SG1mcVhXNEZDZkir3GGLA7DCltIfPr71rPW6nFzW1Rc=",
"ipv6_addr_in": "2607:9000:a000:32::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"23.234.100.139"
],
"features": {
"daita": {},
"quic": {
"addr_in": [
"23.234.100.138"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-nyc-wg-802.blockerad.eu"
}
}
},
{
"hostname": "us-nyc-wg-803",
"location": "us-nyc",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.101.3",
"include_in_country": true,
"weight": 100,
"public_key": "X1ZCLofMRmOnoJiNUTokpTazaRrdtbdH8+yAFvyCMnM=",
"ipv6_addr_in": "2607:9000:a000:33::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"23.234.101.14"
],
"features": {
"daita": {},
"quic": {
"addr_in": [
"23.234.101.13"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-nyc-wg-803.blockerad.eu"
}
}
},
{
"hostname": "us-nyc-wg-804",
"location": "us-nyc",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.101.127",
"include_in_country": true,
"weight": 100,
"public_key": "uNKXjnTzZE0najF3fo5HiDBkg/fCF+anDkVuBNTCfhs=",
"ipv6_addr_in": "2607:9000:a000:34::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"23.234.101.139"
],
"features": {
"daita": {},
"quic": {
"addr_in": [
"23.234.101.138"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-nyc-wg-804.blockerad.eu"
}
}
},
{
"hostname": "us-nyc-wg-805",
"location": "us-nyc",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.102.3",
"include_in_country": true,
"weight": 100,
"public_key": "i97V7R9Fk5IrrbYw+k7H35i8frXOHvbES13AAoRHrWY=",
"ipv6_addr_in": "2607:9000:a000:35::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"23.234.102.14"
],
"features": {
"daita": {},
"quic": {
"addr_in": [
"23.234.102.13"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-nyc-wg-805.blockerad.eu"
}
}
},
{
"hostname": "us-nyc-wg-806",
"location": "us-nyc",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.102.127",
"include_in_country": true,
"weight": 100,
"public_key": "TJxsTwqSLYLKHFJLf7Uo87GiqVXnpYFaNbiiP9qwfBE=",
"ipv6_addr_in": "2607:9000:a000:36::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"23.234.102.139"
],
"features": {
"daita": {},
"quic": {
"addr_in": [
"23.234.102.138"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-nyc-wg-806.blockerad.eu"
}
}
},
{
"hostname": "us-nyc-wg-807",
"location": "us-nyc",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.103.3",
"include_in_country": true,
"weight": 100,
"public_key": "THimhBHKHZ2KeoTRURvpNIVir4nlaxx5NSYwqNuF1wk=",
"ipv6_addr_in": "2607:9000:a000:37::f001",
"shadowsocks_extra_addr_in": [
"23.234.103.14"
],
"features": {
"quic": {
"addr_in": [
"23.234.103.13"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-nyc-wg-807.blockerad.eu"
}
}
},
{
"hostname": "us-nyc-wg-808",
"location": "us-nyc",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.103.127",
"include_in_country": true,
"weight": 100,
"public_key": "tI+Ddqg8MZ3nqXLuvA5Kzryih//XLId7IM4IEgROiFk=",
"ipv6_addr_in": "2607:9000:a000:38::f001",
"shadowsocks_extra_addr_in": [
"23.234.103.139"
],
"features": {
"quic": {
"addr_in": [
"23.234.103.138"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-nyc-wg-808.blockerad.eu"
}
}
},
{
"hostname": "us-phx-wg-201",
"location": "us-phx",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.88.3",
"include_in_country": true,
"weight": 100,
"public_key": "8mie5kslgD63v3pZkbFmwGdj3dg5mu8Wm2Ji5kntfXA=",
"ipv6_addr_in": "2607:9000:700:41::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"23.234.88.14"
],
"features": {
"daita": {}
}
},
{
"hostname": "us-phx-wg-202",
"location": "us-phx",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.88.127",
"include_in_country": true,
"weight": 100,
"public_key": "I8eCMCSsFlb78N8VNaFqSJKM4Z2+3iVdlG6CvJkYEiA=",
"ipv6_addr_in": "2607:9000:700:42::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"23.234.88.139"
],
"features": {
"daita": {}
}
},
{
"hostname": "us-phx-wg-203",
"location": "us-phx",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.89.3",
"include_in_country": true,
"weight": 100,
"public_key": "nSeEIx++JuzqxNqLPOm2BVCXwPpR72Q3QLflDUK8tTA=",
"ipv6_addr_in": "2607:9000:700:43::f001",
"shadowsocks_extra_addr_in": [
"23.234.89.14"
]
},
{
"hostname": "us-phx-wg-204",
"location": "us-phx",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.89.127",
"include_in_country": true,
"weight": 100,
"public_key": "0is4/9V/KIBWwfeuDVDlBmPa134UuV5gaFGUqI1emXY=",
"ipv6_addr_in": "2607:9000:700:44::f001",
"shadowsocks_extra_addr_in": [
"23.234.89.139"
]
},
{
"hostname": "us-phx-wg-205",
"location": "us-phx",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.90.3",
"include_in_country": true,
"weight": 100,
"public_key": "sZMMs5XaQN+p0HXCK15zYV1jo7IJN7agm1Ftm7JDnnk=",
"ipv6_addr_in": "2607:9000:700:45::f001",
"shadowsocks_extra_addr_in": [
"23.234.90.14"
]
},
{
"hostname": "us-phx-wg-206",
"location": "us-phx",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.90.127",
"include_in_country": true,
"weight": 100,
"public_key": "fdA7Lc9cpwb1oPy4Oa/A8sPm+RaDpW5yrdgjykde4jM=",
"ipv6_addr_in": "2607:9000:700:46::f001",
"shadowsocks_extra_addr_in": [
"23.234.90.139"
]
},
{
"hostname": "us-phx-wg-207",
"location": "us-phx",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.91.3",
"include_in_country": true,
"weight": 100,
"public_key": "G5tIt92dwuvvln9nlsi/cI3Au47U94mOMgSdODRMIxs=",
"ipv6_addr_in": "2607:9000:700:47::f001",
"shadowsocks_extra_addr_in": [
"23.234.91.14"
]
},
{
"hostname": "us-phx-wg-208",
"location": "us-phx",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.91.127",
"include_in_country": true,
"weight": 100,
"public_key": "4nHL/Y9efuazXJB0cx6ktdBb0L0gkITWzCFCswfCh04=",
"ipv6_addr_in": "2607:9000:700:48::f001",
"shadowsocks_extra_addr_in": [
"23.234.91.139"
]
},
{
"hostname": "us-qas-wg-101",
"location": "us-qas",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "185.156.46.130",
"include_in_country": true,
"weight": 100,
"public_key": "JEuuPzZE8uE53OFhd3YFiZuwwANLqwmdXWMHPUbBwnk=",
"ipv6_addr_in": "2a02:6ea0:e206:1::a01f"
},
{
"hostname": "us-qas-wg-102",
"location": "us-qas",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "185.156.46.143",
"include_in_country": true,
"weight": 100,
"public_key": "5hlEb3AjTzVIJyYWCYvJvbgA4p25Ltfp2cYnys90LQ0=",
"ipv6_addr_in": "2a02:6ea0:e206:2::a02f"
},
{
"hostname": "us-qas-wg-103",
"location": "us-qas",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "185.156.46.156",
"include_in_country": true,
"weight": 100,
"public_key": "oD9IFZsA5sync37K/sekVXaww76MwA3IvDRpR/irZWQ=",
"ipv6_addr_in": "2a02:6ea0:e206:3::a03f"
},
{
"hostname": "us-qas-wg-201",
"location": "us-qas",
"active": true,
"owned": false,
"provider": "HostRoyale",
"stboot": true,
"ipv4_addr_in": "103.81.230.3",
"include_in_country": true,
"weight": 100,
"public_key": "no0QE15NRHLECYe/B976IH9mLn22QecYBbcYl3LZhD0=",
"ipv6_addr_in": "2a01:4740:1::f001",
"shadowsocks_extra_addr_in": [
"103.81.230.14"
]
},
{
"hostname": "us-qas-wg-202",
"location": "us-qas",
"active": false,
"owned": false,
"provider": "HostRoyale",
"stboot": true,
"ipv4_addr_in": "103.81.230.127",
"include_in_country": true,
"weight": 100,
"public_key": "eUTgjAPvpLba9wwMcC0HNcLwC2Q42QYCKZuFPy34+Ug=",
"ipv6_addr_in": "2a01:4740:1::f101",
"shadowsocks_extra_addr_in": [
"103.81.230.139"
]
},
{
"hostname": "us-qas-wg-203",
"location": "us-qas",
"active": true,
"owned": false,
"provider": "HostRoyale",
"stboot": true,
"ipv4_addr_in": "103.81.231.3",
"include_in_country": true,
"weight": 100,
"public_key": "tI5F6pIZMEf0aJUTG/I2ZvYkkJDJpOxVakObTLLmBAI=",
"ipv6_addr_in": "2a01:4740:1::f201",
"shadowsocks_extra_addr_in": [
"103.81.231.14"
],
"features": {
"lwo": {}
}
},
{
"hostname": "us-qas-wg-204",
"location": "us-qas",
"active": true,
"owned": false,
"provider": "HostRoyale",
"stboot": true,
"ipv4_addr_in": "103.81.231.127",
"include_in_country": true,
"weight": 100,
"public_key": "2bvhh22EcdV3MIuIJze47gD2KmXpplYrNbCjNff2ID8=",
"ipv6_addr_in": "2a01:4740:1::f301",
"shadowsocks_extra_addr_in": [
"103.81.231.139"
],
"features": {
"lwo": {}
}
},
{
"hostname": "us-qas-wg-301",
"location": "us-qas",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.96.2",
"include_in_country": true,
"weight": 100,
"public_key": "WUF0hoTY+kiklSDjMt2Z9kuebB6L/xTm5LcdNbwnslk=",
"ipv6_addr_in": "2607:9000:900:31::f001",
"shadowsocks_extra_addr_in": [
"23.234.96.5",
"23.234.96.6",
"23.234.96.7",
"23.234.96.8",
"23.234.96.9",
"23.234.96.10",
"23.234.96.11",
"23.234.96.12",
"23.234.96.13",
"23.234.96.14",
"23.234.96.15",
"23.234.96.16",
"23.234.96.17",
"23.234.96.18",
"23.234.96.19",
"2607:9000:900:31::b002",
"2607:9000:900:31::b003",
"2607:9000:900:31::b004",
"2607:9000:900:31::b005",
"2607:9000:900:31::b006",
"2607:9000:900:31::b007",
"2607:9000:900:31::b008",
"2607:9000:900:31::b009",
"2607:9000:900:31::b00a",
"2607:9000:900:31::b00b",
"2607:9000:900:31::b00c",
"2607:9000:900:31::b00d",
"2607:9000:900:31::b00e",
"2607:9000:900:31::b00f",
"2607:9000:900:31::b010",
"2607:9000:900:31::b011",
"2607:9000:900:31::b012",
"2607:9000:900:31::b013",
"2607:9000:900:31::b014",
"2607:9000:900:31::b015",
"2607:9000:900:31::b016",
"2607:9000:900:31::b017",
"2607:9000:900:31::b018",
"2607:9000:900:31::b019",
"2607:9000:900:31::b01a",
"2607:9000:900:31::b01b",
"2607:9000:900:31::b01c",
"2607:9000:900:31::b01d",
"2607:9000:900:31::b01e",
"2607:9000:900:31::b01f"
],
"features": {
"quic": {
"addr_in": [
"23.234.96.20",
"23.234.96.21",
"23.234.96.22",
"23.234.96.23",
"23.234.96.24",
"23.234.96.25",
"23.234.96.26",
"23.234.96.27",
"23.234.96.28",
"23.234.96.29",
"23.234.96.30",
"23.234.96.31",
"23.234.96.32",
"23.234.96.33",
"23.234.96.34",
"2607:9000:900:31::c002",
"2607:9000:900:31::c003",
"2607:9000:900:31::c004",
"2607:9000:900:31::c005",
"2607:9000:900:31::c006",
"2607:9000:900:31::c007",
"2607:9000:900:31::c008",
"2607:9000:900:31::c009",
"2607:9000:900:31::c00a",
"2607:9000:900:31::c00b",
"2607:9000:900:31::c00c",
"2607:9000:900:31::c00d",
"2607:9000:900:31::c00e",
"2607:9000:900:31::c00f",
"2607:9000:900:31::c010",
"2607:9000:900:31::c011",
"2607:9000:900:31::c012",
"2607:9000:900:31::c013",
"2607:9000:900:31::c014",
"2607:9000:900:31::c015",
"2607:9000:900:31::c016",
"2607:9000:900:31::c017",
"2607:9000:900:31::c018",
"2607:9000:900:31::c019",
"2607:9000:900:31::c01a",
"2607:9000:900:31::c01b",
"2607:9000:900:31::c01c",
"2607:9000:900:31::c01d",
"2607:9000:900:31::c01e",
"2607:9000:900:31::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-qas-wg-301.blockerad.eu"
}
}
},
{
"hostname": "us-qas-wg-302",
"location": "us-qas",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.96.127",
"include_in_country": true,
"weight": 100,
"public_key": "vwIDgSCPbEzumzi/XveunLso8yzLdOP4OdZCHFYsbkg=",
"ipv6_addr_in": "2607:9000:900:32::f001",
"shadowsocks_extra_addr_in": [
"23.234.96.130",
"23.234.96.131",
"23.234.96.132",
"23.234.96.133",
"23.234.96.134",
"23.234.96.135",
"23.234.96.136",
"23.234.96.137",
"23.234.96.138",
"23.234.96.139",
"23.234.96.140",
"23.234.96.141",
"23.234.96.142",
"23.234.96.143",
"23.234.96.144",
"2607:9000:900:32::b002",
"2607:9000:900:32::b003",
"2607:9000:900:32::b004",
"2607:9000:900:32::b005",
"2607:9000:900:32::b006",
"2607:9000:900:32::b007",
"2607:9000:900:32::b008",
"2607:9000:900:32::b009",
"2607:9000:900:32::b00a",
"2607:9000:900:32::b00b",
"2607:9000:900:32::b00c",
"2607:9000:900:32::b00d",
"2607:9000:900:32::b00e",
"2607:9000:900:32::b00f",
"2607:9000:900:32::b010",
"2607:9000:900:32::b011",
"2607:9000:900:32::b012",
"2607:9000:900:32::b013",
"2607:9000:900:32::b014",
"2607:9000:900:32::b015",
"2607:9000:900:32::b016",
"2607:9000:900:32::b017",
"2607:9000:900:32::b018",
"2607:9000:900:32::b019",
"2607:9000:900:32::b01a",
"2607:9000:900:32::b01b",
"2607:9000:900:32::b01c",
"2607:9000:900:32::b01d",
"2607:9000:900:32::b01e",
"2607:9000:900:32::b01f"
],
"features": {
"quic": {
"addr_in": [
"23.234.96.145",
"23.234.96.146",
"23.234.96.147",
"23.234.96.148",
"23.234.96.149",
"23.234.96.150",
"23.234.96.151",
"23.234.96.152",
"23.234.96.153",
"23.234.96.154",
"23.234.96.155",
"23.234.96.156",
"23.234.96.157",
"23.234.96.158",
"23.234.96.159",
"2607:9000:900:32::c002",
"2607:9000:900:32::c003",
"2607:9000:900:32::c004",
"2607:9000:900:32::c005",
"2607:9000:900:32::c006",
"2607:9000:900:32::c007",
"2607:9000:900:32::c008",
"2607:9000:900:32::c009",
"2607:9000:900:32::c00a",
"2607:9000:900:32::c00b",
"2607:9000:900:32::c00c",
"2607:9000:900:32::c00d",
"2607:9000:900:32::c00e",
"2607:9000:900:32::c00f",
"2607:9000:900:32::c010",
"2607:9000:900:32::c011",
"2607:9000:900:32::c012",
"2607:9000:900:32::c013",
"2607:9000:900:32::c014",
"2607:9000:900:32::c015",
"2607:9000:900:32::c016",
"2607:9000:900:32::c017",
"2607:9000:900:32::c018",
"2607:9000:900:32::c019",
"2607:9000:900:32::c01a",
"2607:9000:900:32::c01b",
"2607:9000:900:32::c01c",
"2607:9000:900:32::c01d",
"2607:9000:900:32::c01e",
"2607:9000:900:32::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-qas-wg-302.blockerad.eu"
}
}
},
{
"hostname": "us-qas-wg-303",
"location": "us-qas",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.97.2",
"include_in_country": true,
"weight": 100,
"public_key": "eym7onKZRi6uTtIA7SCxON/1q6zln3o5mYeYlasMeR8=",
"ipv6_addr_in": "2607:9000:900:33::f001",
"shadowsocks_extra_addr_in": [
"23.234.97.5",
"23.234.97.6",
"23.234.97.7",
"23.234.97.8",
"23.234.97.9",
"23.234.97.10",
"23.234.97.11",
"23.234.97.12",
"23.234.97.13",
"23.234.97.14",
"23.234.97.15",
"23.234.97.16",
"23.234.97.17",
"23.234.97.18",
"23.234.97.19",
"2607:9000:900:33::b002",
"2607:9000:900:33::b003",
"2607:9000:900:33::b004",
"2607:9000:900:33::b005",
"2607:9000:900:33::b006",
"2607:9000:900:33::b007",
"2607:9000:900:33::b008",
"2607:9000:900:33::b009",
"2607:9000:900:33::b00a",
"2607:9000:900:33::b00b",
"2607:9000:900:33::b00c",
"2607:9000:900:33::b00d",
"2607:9000:900:33::b00e",
"2607:9000:900:33::b00f",
"2607:9000:900:33::b010",
"2607:9000:900:33::b011",
"2607:9000:900:33::b012",
"2607:9000:900:33::b013",
"2607:9000:900:33::b014",
"2607:9000:900:33::b015",
"2607:9000:900:33::b016",
"2607:9000:900:33::b017",
"2607:9000:900:33::b018",
"2607:9000:900:33::b019",
"2607:9000:900:33::b01a",
"2607:9000:900:33::b01b",
"2607:9000:900:33::b01c",
"2607:9000:900:33::b01d",
"2607:9000:900:33::b01e",
"2607:9000:900:33::b01f"
],
"features": {
"quic": {
"addr_in": [
"23.234.97.20",
"23.234.97.21",
"23.234.97.22",
"23.234.97.23",
"23.234.97.24",
"23.234.97.25",
"23.234.97.26",
"23.234.97.27",
"23.234.97.28",
"23.234.97.29",
"23.234.97.30",
"23.234.97.31",
"23.234.97.32",
"23.234.97.33",
"23.234.97.34",
"2607:9000:900:33::c002",
"2607:9000:900:33::c003",
"2607:9000:900:33::c004",
"2607:9000:900:33::c005",
"2607:9000:900:33::c006",
"2607:9000:900:33::c007",
"2607:9000:900:33::c008",
"2607:9000:900:33::c009",
"2607:9000:900:33::c00a",
"2607:9000:900:33::c00b",
"2607:9000:900:33::c00c",
"2607:9000:900:33::c00d",
"2607:9000:900:33::c00e",
"2607:9000:900:33::c00f",
"2607:9000:900:33::c010",
"2607:9000:900:33::c011",
"2607:9000:900:33::c012",
"2607:9000:900:33::c013",
"2607:9000:900:33::c014",
"2607:9000:900:33::c015",
"2607:9000:900:33::c016",
"2607:9000:900:33::c017",
"2607:9000:900:33::c018",
"2607:9000:900:33::c019",
"2607:9000:900:33::c01a",
"2607:9000:900:33::c01b",
"2607:9000:900:33::c01c",
"2607:9000:900:33::c01d",
"2607:9000:900:33::c01e",
"2607:9000:900:33::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-qas-wg-303.blockerad.eu"
}
}
},
{
"hostname": "us-qas-wg-304",
"location": "us-qas",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.97.127",
"include_in_country": true,
"weight": 100,
"public_key": "D3xigYvUQnLnKBVNQ7KpaWpuIbGxHHB1mb/+nSf3QXI=",
"ipv6_addr_in": "2607:9000:900:34::f001",
"shadowsocks_extra_addr_in": [
"23.234.97.130",
"23.234.97.131",
"23.234.97.132",
"23.234.97.133",
"23.234.97.134",
"23.234.97.135",
"23.234.97.136",
"23.234.97.137",
"23.234.97.138",
"23.234.97.139",
"23.234.97.140",
"23.234.97.141",
"23.234.97.142",
"23.234.97.143",
"23.234.97.144",
"2607:9000:900:34::b002",
"2607:9000:900:34::b003",
"2607:9000:900:34::b004",
"2607:9000:900:34::b005",
"2607:9000:900:34::b006",
"2607:9000:900:34::b007",
"2607:9000:900:34::b008",
"2607:9000:900:34::b009",
"2607:9000:900:34::b00a",
"2607:9000:900:34::b00b",
"2607:9000:900:34::b00c",
"2607:9000:900:34::b00d",
"2607:9000:900:34::b00e",
"2607:9000:900:34::b00f",
"2607:9000:900:34::b010",
"2607:9000:900:34::b011",
"2607:9000:900:34::b012",
"2607:9000:900:34::b013",
"2607:9000:900:34::b014",
"2607:9000:900:34::b015",
"2607:9000:900:34::b016",
"2607:9000:900:34::b017",
"2607:9000:900:34::b018",
"2607:9000:900:34::b019",
"2607:9000:900:34::b01a",
"2607:9000:900:34::b01b",
"2607:9000:900:34::b01c",
"2607:9000:900:34::b01d",
"2607:9000:900:34::b01e",
"2607:9000:900:34::b01f"
],
"features": {
"quic": {
"addr_in": [
"23.234.97.145",
"23.234.97.146",
"23.234.97.147",
"23.234.97.148",
"23.234.97.149",
"23.234.97.150",
"23.234.97.151",
"23.234.97.152",
"23.234.97.153",
"23.234.97.154",
"23.234.97.155",
"23.234.97.156",
"23.234.97.157",
"23.234.97.158",
"23.234.97.159",
"2607:9000:900:34::c002",
"2607:9000:900:34::c003",
"2607:9000:900:34::c004",
"2607:9000:900:34::c005",
"2607:9000:900:34::c006",
"2607:9000:900:34::c007",
"2607:9000:900:34::c008",
"2607:9000:900:34::c009",
"2607:9000:900:34::c00a",
"2607:9000:900:34::c00b",
"2607:9000:900:34::c00c",
"2607:9000:900:34::c00d",
"2607:9000:900:34::c00e",
"2607:9000:900:34::c00f",
"2607:9000:900:34::c010",
"2607:9000:900:34::c011",
"2607:9000:900:34::c012",
"2607:9000:900:34::c013",
"2607:9000:900:34::c014",
"2607:9000:900:34::c015",
"2607:9000:900:34::c016",
"2607:9000:900:34::c017",
"2607:9000:900:34::c018",
"2607:9000:900:34::c019",
"2607:9000:900:34::c01a",
"2607:9000:900:34::c01b",
"2607:9000:900:34::c01c",
"2607:9000:900:34::c01d",
"2607:9000:900:34::c01e",
"2607:9000:900:34::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-qas-wg-304.blockerad.eu"
}
}
},
{
"hostname": "us-qas-wg-305",
"location": "us-qas",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.98.2",
"include_in_country": true,
"weight": 100,
"public_key": "hOuBVCXBzSA2eDx1cuAozt1B7Cg9M9IGCS6tedZHEkE=",
"ipv6_addr_in": "2607:9000:900:35::f001",
"shadowsocks_extra_addr_in": [
"23.234.98.5",
"23.234.98.6",
"23.234.98.7",
"23.234.98.8",
"23.234.98.9",
"23.234.98.10",
"23.234.98.11",
"23.234.98.12",
"23.234.98.13",
"23.234.98.14",
"23.234.98.15",
"23.234.98.16",
"23.234.98.17",
"23.234.98.18",
"23.234.98.19",
"2607:9000:900:35::b002",
"2607:9000:900:35::b003",
"2607:9000:900:35::b004",
"2607:9000:900:35::b005",
"2607:9000:900:35::b006",
"2607:9000:900:35::b007",
"2607:9000:900:35::b008",
"2607:9000:900:35::b009",
"2607:9000:900:35::b00a",
"2607:9000:900:35::b00b",
"2607:9000:900:35::b00c",
"2607:9000:900:35::b00d",
"2607:9000:900:35::b00e",
"2607:9000:900:35::b00f",
"2607:9000:900:35::b010",
"2607:9000:900:35::b011",
"2607:9000:900:35::b012",
"2607:9000:900:35::b013",
"2607:9000:900:35::b014",
"2607:9000:900:35::b015",
"2607:9000:900:35::b016",
"2607:9000:900:35::b017",
"2607:9000:900:35::b018",
"2607:9000:900:35::b019",
"2607:9000:900:35::b01a",
"2607:9000:900:35::b01b",
"2607:9000:900:35::b01c",
"2607:9000:900:35::b01d",
"2607:9000:900:35::b01e",
"2607:9000:900:35::b01f"
],
"features": {
"quic": {
"addr_in": [
"23.234.98.20",
"23.234.98.21",
"23.234.98.22",
"23.234.98.23",
"23.234.98.24",
"23.234.98.25",
"23.234.98.26",
"23.234.98.27",
"23.234.98.28",
"23.234.98.29",
"23.234.98.30",
"23.234.98.31",
"23.234.98.32",
"23.234.98.33",
"23.234.98.34",
"2607:9000:900:35::c002",
"2607:9000:900:35::c003",
"2607:9000:900:35::c004",
"2607:9000:900:35::c005",
"2607:9000:900:35::c006",
"2607:9000:900:35::c007",
"2607:9000:900:35::c008",
"2607:9000:900:35::c009",
"2607:9000:900:35::c00a",
"2607:9000:900:35::c00b",
"2607:9000:900:35::c00c",
"2607:9000:900:35::c00d",
"2607:9000:900:35::c00e",
"2607:9000:900:35::c00f",
"2607:9000:900:35::c010",
"2607:9000:900:35::c011",
"2607:9000:900:35::c012",
"2607:9000:900:35::c013",
"2607:9000:900:35::c014",
"2607:9000:900:35::c015",
"2607:9000:900:35::c016",
"2607:9000:900:35::c017",
"2607:9000:900:35::c018",
"2607:9000:900:35::c019",
"2607:9000:900:35::c01a",
"2607:9000:900:35::c01b",
"2607:9000:900:35::c01c",
"2607:9000:900:35::c01d",
"2607:9000:900:35::c01e",
"2607:9000:900:35::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-qas-wg-305.blockerad.eu"
}
}
},
{
"hostname": "us-qas-wg-306",
"location": "us-qas",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.98.127",
"include_in_country": true,
"weight": 100,
"public_key": "5J/CzkztJt5djDo/UiHA0jQwMOr5b7SfeY77TWmcVF0=",
"ipv6_addr_in": "2607:9000:900:36::f001",
"shadowsocks_extra_addr_in": [
"23.234.98.130",
"23.234.98.131",
"23.234.98.132",
"23.234.98.133",
"23.234.98.134",
"23.234.98.135",
"23.234.98.136",
"23.234.98.137",
"23.234.98.138",
"23.234.98.139",
"23.234.98.140",
"23.234.98.141",
"23.234.98.142",
"23.234.98.143",
"23.234.98.144",
"2607:9000:900:36::b002",
"2607:9000:900:36::b003",
"2607:9000:900:36::b004",
"2607:9000:900:36::b005",
"2607:9000:900:36::b006",
"2607:9000:900:36::b007",
"2607:9000:900:36::b008",
"2607:9000:900:36::b009",
"2607:9000:900:36::b00a",
"2607:9000:900:36::b00b",
"2607:9000:900:36::b00c",
"2607:9000:900:36::b00d",
"2607:9000:900:36::b00e",
"2607:9000:900:36::b00f",
"2607:9000:900:36::b010",
"2607:9000:900:36::b011",
"2607:9000:900:36::b012",
"2607:9000:900:36::b013",
"2607:9000:900:36::b014",
"2607:9000:900:36::b015",
"2607:9000:900:36::b016",
"2607:9000:900:36::b017",
"2607:9000:900:36::b018",
"2607:9000:900:36::b019",
"2607:9000:900:36::b01a",
"2607:9000:900:36::b01b",
"2607:9000:900:36::b01c",
"2607:9000:900:36::b01d",
"2607:9000:900:36::b01e",
"2607:9000:900:36::b01f"
],
"features": {
"quic": {
"addr_in": [
"23.234.98.145",
"23.234.98.146",
"23.234.98.147",
"23.234.98.148",
"23.234.98.149",
"23.234.98.150",
"23.234.98.151",
"23.234.98.152",
"23.234.98.153",
"23.234.98.154",
"23.234.98.155",
"23.234.98.156",
"23.234.98.157",
"23.234.98.158",
"23.234.98.159",
"2607:9000:900:36::c002",
"2607:9000:900:36::c003",
"2607:9000:900:36::c004",
"2607:9000:900:36::c005",
"2607:9000:900:36::c006",
"2607:9000:900:36::c007",
"2607:9000:900:36::c008",
"2607:9000:900:36::c009",
"2607:9000:900:36::c00a",
"2607:9000:900:36::c00b",
"2607:9000:900:36::c00c",
"2607:9000:900:36::c00d",
"2607:9000:900:36::c00e",
"2607:9000:900:36::c00f",
"2607:9000:900:36::c010",
"2607:9000:900:36::c011",
"2607:9000:900:36::c012",
"2607:9000:900:36::c013",
"2607:9000:900:36::c014",
"2607:9000:900:36::c015",
"2607:9000:900:36::c016",
"2607:9000:900:36::c017",
"2607:9000:900:36::c018",
"2607:9000:900:36::c019",
"2607:9000:900:36::c01a",
"2607:9000:900:36::c01b",
"2607:9000:900:36::c01c",
"2607:9000:900:36::c01d",
"2607:9000:900:36::c01e",
"2607:9000:900:36::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-qas-wg-306.blockerad.eu"
}
}
},
{
"hostname": "us-qas-wg-307",
"location": "us-qas",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.99.2",
"include_in_country": true,
"weight": 100,
"public_key": "aVmjjHrEAPxxg3l/19K+WSXjH4bKBpfaKkDI+6+umkc=",
"ipv6_addr_in": "2607:9000:900:37::f001",
"shadowsocks_extra_addr_in": [
"23.234.99.5",
"23.234.99.6",
"23.234.99.7",
"23.234.99.8",
"23.234.99.9",
"23.234.99.10",
"23.234.99.11",
"23.234.99.12",
"23.234.99.13",
"23.234.99.14",
"23.234.99.15",
"23.234.99.16",
"23.234.99.17",
"23.234.99.18",
"23.234.99.19",
"2607:9000:900:37::b002",
"2607:9000:900:37::b003",
"2607:9000:900:37::b004",
"2607:9000:900:37::b005",
"2607:9000:900:37::b006",
"2607:9000:900:37::b007",
"2607:9000:900:37::b008",
"2607:9000:900:37::b009",
"2607:9000:900:37::b00a",
"2607:9000:900:37::b00b",
"2607:9000:900:37::b00c",
"2607:9000:900:37::b00d",
"2607:9000:900:37::b00e",
"2607:9000:900:37::b00f",
"2607:9000:900:37::b010",
"2607:9000:900:37::b011",
"2607:9000:900:37::b012",
"2607:9000:900:37::b013",
"2607:9000:900:37::b014",
"2607:9000:900:37::b015",
"2607:9000:900:37::b016",
"2607:9000:900:37::b017",
"2607:9000:900:37::b018",
"2607:9000:900:37::b019",
"2607:9000:900:37::b01a",
"2607:9000:900:37::b01b",
"2607:9000:900:37::b01c",
"2607:9000:900:37::b01d",
"2607:9000:900:37::b01e",
"2607:9000:900:37::b01f"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"23.234.99.20",
"23.234.99.21",
"23.234.99.22",
"23.234.99.23",
"23.234.99.24",
"23.234.99.25",
"23.234.99.26",
"23.234.99.27",
"23.234.99.28",
"23.234.99.29",
"23.234.99.30",
"23.234.99.31",
"23.234.99.32",
"23.234.99.33",
"23.234.99.34",
"2607:9000:900:37::c002",
"2607:9000:900:37::c003",
"2607:9000:900:37::c004",
"2607:9000:900:37::c005",
"2607:9000:900:37::c006",
"2607:9000:900:37::c007",
"2607:9000:900:37::c008",
"2607:9000:900:37::c009",
"2607:9000:900:37::c00a",
"2607:9000:900:37::c00b",
"2607:9000:900:37::c00c",
"2607:9000:900:37::c00d",
"2607:9000:900:37::c00e",
"2607:9000:900:37::c00f",
"2607:9000:900:37::c010",
"2607:9000:900:37::c011",
"2607:9000:900:37::c012",
"2607:9000:900:37::c013",
"2607:9000:900:37::c014",
"2607:9000:900:37::c015",
"2607:9000:900:37::c016",
"2607:9000:900:37::c017",
"2607:9000:900:37::c018",
"2607:9000:900:37::c019",
"2607:9000:900:37::c01a",
"2607:9000:900:37::c01b",
"2607:9000:900:37::c01c",
"2607:9000:900:37::c01d",
"2607:9000:900:37::c01e",
"2607:9000:900:37::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-qas-wg-307.blockerad.eu"
}
}
},
{
"hostname": "us-qas-wg-308",
"location": "us-qas",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.99.127",
"include_in_country": true,
"weight": 100,
"public_key": "lXSNRlfRVmeljwu0y7m4+M2OhveCbaMRewTbssgHDyY=",
"ipv6_addr_in": "2607:9000:900:38::f001",
"shadowsocks_extra_addr_in": [
"23.234.99.130",
"23.234.99.131",
"23.234.99.132",
"23.234.99.133",
"23.234.99.134",
"23.234.99.135",
"23.234.99.136",
"23.234.99.137",
"23.234.99.138",
"23.234.99.139",
"23.234.99.140",
"23.234.99.141",
"23.234.99.142",
"23.234.99.143",
"23.234.99.144",
"2607:9000:900:38::b002",
"2607:9000:900:38::b003",
"2607:9000:900:38::b004",
"2607:9000:900:38::b005",
"2607:9000:900:38::b006",
"2607:9000:900:38::b007",
"2607:9000:900:38::b008",
"2607:9000:900:38::b009",
"2607:9000:900:38::b00a",
"2607:9000:900:38::b00b",
"2607:9000:900:38::b00c",
"2607:9000:900:38::b00d",
"2607:9000:900:38::b00e",
"2607:9000:900:38::b00f",
"2607:9000:900:38::b010",
"2607:9000:900:38::b011",
"2607:9000:900:38::b012",
"2607:9000:900:38::b013",
"2607:9000:900:38::b014",
"2607:9000:900:38::b015",
"2607:9000:900:38::b016",
"2607:9000:900:38::b017",
"2607:9000:900:38::b018",
"2607:9000:900:38::b019",
"2607:9000:900:38::b01a",
"2607:9000:900:38::b01b",
"2607:9000:900:38::b01c",
"2607:9000:900:38::b01d",
"2607:9000:900:38::b01e",
"2607:9000:900:38::b01f"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"23.234.99.145",
"23.234.99.146",
"23.234.99.147",
"23.234.99.148",
"23.234.99.149",
"23.234.99.150",
"23.234.99.151",
"23.234.99.152",
"23.234.99.153",
"23.234.99.154",
"23.234.99.155",
"23.234.99.156",
"23.234.99.157",
"23.234.99.158",
"23.234.99.159",
"2607:9000:900:38::c002",
"2607:9000:900:38::c003",
"2607:9000:900:38::c004",
"2607:9000:900:38::c005",
"2607:9000:900:38::c006",
"2607:9000:900:38::c007",
"2607:9000:900:38::c008",
"2607:9000:900:38::c009",
"2607:9000:900:38::c00a",
"2607:9000:900:38::c00b",
"2607:9000:900:38::c00c",
"2607:9000:900:38::c00d",
"2607:9000:900:38::c00e",
"2607:9000:900:38::c00f",
"2607:9000:900:38::c010",
"2607:9000:900:38::c011",
"2607:9000:900:38::c012",
"2607:9000:900:38::c013",
"2607:9000:900:38::c014",
"2607:9000:900:38::c015",
"2607:9000:900:38::c016",
"2607:9000:900:38::c017",
"2607:9000:900:38::c018",
"2607:9000:900:38::c019",
"2607:9000:900:38::c01a",
"2607:9000:900:38::c01b",
"2607:9000:900:38::c01c",
"2607:9000:900:38::c01d",
"2607:9000:900:38::c01e",
"2607:9000:900:38::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-qas-wg-308.blockerad.eu"
}
}
},
{
"hostname": "us-rag-wg-201",
"location": "us-rag",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.76.2",
"include_in_country": true,
"weight": 100,
"public_key": "MuKjekVqBwpSizHLNwVRl4b8bwi6aTCBOshPiOOWrEQ=",
"ipv6_addr_in": "2607:9000:4000:31::f001",
"shadowsocks_extra_addr_in": [
"23.234.76.13"
],
"features": {
"lwo": {}
}
},
{
"hostname": "us-rag-wg-202",
"location": "us-rag",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.76.127",
"include_in_country": true,
"weight": 100,
"public_key": "T2diUJ97txooCDntCrB6Q29Qe0fm/hMdZDzdc9uOUgQ=",
"ipv6_addr_in": "2607:9000:4000:32::f001",
"shadowsocks_extra_addr_in": [
"23.234.76.138"
],
"features": {
"lwo": {}
}
},
{
"hostname": "us-rag-wg-203",
"location": "us-rag",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.77.2",
"include_in_country": true,
"weight": 100,
"public_key": "4BioSTLTYH1qL/oYGY/z5IZ049I7oSzs5IKoFZzrgn0=",
"ipv6_addr_in": "2607:9000:4000:33::f001",
"shadowsocks_extra_addr_in": [
"23.234.77.13"
],
"features": {
"lwo": {}
}
},
{
"hostname": "us-rag-wg-204",
"location": "us-rag",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.77.127",
"include_in_country": true,
"weight": 100,
"public_key": "Tk5lPM5K5qrXPWDktHH+AvcxC+UxhGSX6aILsPi33zU=",
"ipv6_addr_in": "2607:9000:4000:34::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"23.234.77.138"
],
"features": {
"daita": {}
}
},
{
"hostname": "us-rag-wg-205",
"location": "us-rag",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.78.2",
"include_in_country": true,
"weight": 100,
"public_key": "z7vhWZ1oY+UkE7PoXF/QtofOhTNGnNfoP20al/cniyc=",
"ipv6_addr_in": "2607:9000:4000:35::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"23.234.78.13"
],
"features": {
"daita": {}
}
},
{
"hostname": "us-rag-wg-206",
"location": "us-rag",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.78.127",
"include_in_country": true,
"weight": 100,
"public_key": "ekRrcTqihriWz4TldL2deIEbHlqwytL3pu1WV+v7zjw=",
"ipv6_addr_in": "2607:9000:4000:36::f001",
"shadowsocks_extra_addr_in": [
"23.234.78.138"
],
"features": {
"lwo": {}
}
},
{
"hostname": "us-rag-wg-207",
"location": "us-rag",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.79.2",
"include_in_country": true,
"weight": 100,
"public_key": "Y16tMAXHpCEExSZJ8AL5LfskKqPqIrZWeLFbSLE/piE=",
"ipv6_addr_in": "2607:9000:4000:37::f001",
"shadowsocks_extra_addr_in": [
"23.234.79.13"
],
"features": {
"lwo": {}
}
},
{
"hostname": "us-rag-wg-208",
"location": "us-rag",
"active": false,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.79.127",
"include_in_country": true,
"weight": 100,
"public_key": "lCyIXwxSGEBSpUah0kYSyuaZuDJJB0Cwia7gv4r7XTA=",
"ipv6_addr_in": "2607:9000:4000:38::f001",
"shadowsocks_extra_addr_in": [
"23.234.79.138"
]
},
{
"hostname": "us-sea-wg-001",
"location": "us-sea",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "138.199.43.91",
"include_in_country": true,
"weight": 100,
"public_key": "bZQF7VRDRK/JUJ8L6EFzF/zRw2tsqMRk6FesGtTgsC0=",
"ipv6_addr_in": "2a02:6ea0:d80b:3::b75f"
},
{
"hostname": "us-sea-wg-002",
"location": "us-sea",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "138.199.43.78",
"include_in_country": true,
"weight": 100,
"public_key": "Xt80FGN9eLy1vX3F29huj6oW2MnQt7ne3DMBpo525Qw=",
"ipv6_addr_in": "2a02:6ea0:d80b:2::f001"
},
{
"hostname": "us-sea-wg-003",
"location": "us-sea",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "138.199.43.65",
"include_in_country": true,
"weight": 100,
"public_key": "4ke8ZSsroiI6Sp23OBbMAU6yQmdF3xU2N8CyzQXE/Qw=",
"ipv6_addr_in": "2a02:6ea0:d80b:1::b73f"
},
{
"hostname": "us-sea-wg-401",
"location": "us-sea",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.80.2",
"include_in_country": true,
"weight": 100,
"public_key": "wRvkGNE3N2UklxKajU06gbBJ3Bg7KmhZsU7a5HIFBw8=",
"ipv6_addr_in": "2607:9000:5000:31::f001",
"shadowsocks_extra_addr_in": [
"23.234.80.13"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"23.234.80.12"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-sea-wg-401.blockerad.eu"
}
}
},
{
"hostname": "us-sea-wg-402",
"location": "us-sea",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.80.127",
"include_in_country": true,
"weight": 100,
"public_key": "NBnpCxDrc0tdX91KUm5cEmQv7BSMOZqd7dS/d7piQl0=",
"ipv6_addr_in": "2607:9000:5000:32::f001",
"shadowsocks_extra_addr_in": [
"23.234.80.138"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"23.234.80.137"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-sea-wg-402.blockerad.eu"
}
}
},
{
"hostname": "us-sea-wg-403",
"location": "us-sea",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.81.2",
"include_in_country": true,
"weight": 100,
"public_key": "cJ8317JqMtNDvxvd/8z29lWurK/3sb5nFZuOY5mw3ys=",
"ipv6_addr_in": "2607:9000:5000:33::f001",
"shadowsocks_extra_addr_in": [
"23.234.81.13"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"23.234.81.12"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-sea-wg-403.blockerad.eu"
}
}
},
{
"hostname": "us-sea-wg-404",
"location": "us-sea",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.81.127",
"include_in_country": true,
"weight": 100,
"public_key": "G6+A375GVmuFCAtvwgx3SWCWhrMvdQ+cboXQ8zp2ang=",
"ipv6_addr_in": "2607:9000:5000:34::f001",
"shadowsocks_extra_addr_in": [
"23.234.81.138"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"23.234.81.137"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-sea-wg-404.blockerad.eu"
}
}
},
{
"hostname": "us-sea-wg-405",
"location": "us-sea",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.82.2",
"include_in_country": true,
"weight": 100,
"public_key": "X+efE4ntYuAEHBHU32SBMq/U0lAFEKeX5/nl3CKtrVM=",
"ipv6_addr_in": "2607:9000:5000:35::f001",
"shadowsocks_extra_addr_in": [
"23.234.82.13"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"23.234.82.12"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-sea-wg-405.blockerad.eu"
}
}
},
{
"hostname": "us-sea-wg-406",
"location": "us-sea",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.82.127",
"include_in_country": true,
"weight": 100,
"public_key": "kT695K8pTGd+I6Q4a4URU2AdXN2VAtHyi7kNSRjUEiw=",
"ipv6_addr_in": "2607:9000:5000:36::f001",
"shadowsocks_extra_addr_in": [
"23.234.82.138"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"23.234.82.137"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-sea-wg-406.blockerad.eu"
}
}
},
{
"hostname": "us-sea-wg-407",
"location": "us-sea",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.83.2",
"include_in_country": true,
"weight": 100,
"public_key": "HrhtkMqLmKtpAHiUIw7uLHwt48mDlhyLOt4+1kpNj3Y=",
"ipv6_addr_in": "2607:9000:5000:37::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"23.234.83.13"
],
"features": {
"daita": {},
"quic": {
"addr_in": [
"23.234.83.12"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-sea-wg-407.blockerad.eu"
}
}
},
{
"hostname": "us-sea-wg-408",
"location": "us-sea",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.83.127",
"include_in_country": true,
"weight": 100,
"public_key": "tfhYXF12+7tB6bEOhqZ7eMODDv08fDMnQSBTmlau9VI=",
"ipv6_addr_in": "2607:9000:5000:38::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"23.234.83.138"
],
"features": {
"daita": {},
"quic": {
"addr_in": [
"23.234.83.137"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-sea-wg-408.blockerad.eu"
}
}
},
{
"hostname": "us-sfo-wg-001",
"location": "us-sfo",
"active": true,
"owned": false,
"provider": "HostRoyale",
"stboot": true,
"ipv4_addr_in": "45.153.102.3",
"include_in_country": true,
"weight": 100,
"public_key": "mf/nsPsUZZvssmD8IqZBYda/PoPyD3mZFKEf0NkyynY=",
"ipv6_addr_in": "2a06:3040:9:610::f101",
"shadowsocks_extra_addr_in": [
"45.153.102.24",
"45.153.102.25",
"45.153.102.26",
"45.153.102.27",
"45.153.102.28",
"45.153.102.29",
"45.153.102.30",
"45.153.102.31",
"45.153.102.32",
"45.153.102.33",
"45.153.102.34",
"45.153.102.35",
"45.153.102.36",
"45.153.102.37",
"45.153.102.38",
"45.153.102.39",
"45.153.102.40",
"45.153.102.41",
"45.153.102.42",
"45.153.102.43",
"2a06:3040:9:610::b102",
"2a06:3040:9:610::b103",
"2a06:3040:9:610::b104",
"2a06:3040:9:610::b105",
"2a06:3040:9:610::b106",
"2a06:3040:9:610::b107",
"2a06:3040:9:610::b108",
"2a06:3040:9:610::b109",
"2a06:3040:9:610::b10a",
"2a06:3040:9:610::b10b",
"2a06:3040:9:610::b10c",
"2a06:3040:9:610::b10d",
"2a06:3040:9:610::b10e",
"2a06:3040:9:610::b10f",
"2a06:3040:9:610::b110",
"2a06:3040:9:610::b111",
"2a06:3040:9:610::b112",
"2a06:3040:9:610::b113",
"2a06:3040:9:610::b114",
"2a06:3040:9:610::b115",
"2a06:3040:9:610::b116",
"2a06:3040:9:610::b117",
"2a06:3040:9:610::b118",
"2a06:3040:9:610::b119",
"2a06:3040:9:610::b11a",
"2a06:3040:9:610::b11b",
"2a06:3040:9:610::b11c",
"2a06:3040:9:610::b11d",
"2a06:3040:9:610::b11e",
"2a06:3040:9:610::b11f"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"45.153.102.44",
"45.153.102.45",
"45.153.102.46",
"45.153.102.47",
"45.153.102.48",
"45.153.102.49",
"45.153.102.50",
"45.153.102.51",
"45.153.102.52",
"45.153.102.53",
"45.153.102.54",
"45.153.102.55",
"45.153.102.56",
"45.153.102.57",
"45.153.102.58",
"45.153.102.59",
"45.153.102.60",
"45.153.102.61",
"45.153.102.62",
"45.153.102.63",
"2a06:3040:9:610::c102",
"2a06:3040:9:610::c103",
"2a06:3040:9:610::c104",
"2a06:3040:9:610::c105",
"2a06:3040:9:610::c106",
"2a06:3040:9:610::c107",
"2a06:3040:9:610::c108",
"2a06:3040:9:610::c109",
"2a06:3040:9:610::c10a",
"2a06:3040:9:610::c10b",
"2a06:3040:9:610::c10c",
"2a06:3040:9:610::c10d",
"2a06:3040:9:610::c10e",
"2a06:3040:9:610::c10f",
"2a06:3040:9:610::c110",
"2a06:3040:9:610::c111",
"2a06:3040:9:610::c112",
"2a06:3040:9:610::c113",
"2a06:3040:9:610::c114",
"2a06:3040:9:610::c115",
"2a06:3040:9:610::c116",
"2a06:3040:9:610::c117",
"2a06:3040:9:610::c118",
"2a06:3040:9:610::c119",
"2a06:3040:9:610::c11a",
"2a06:3040:9:610::c11b",
"2a06:3040:9:610::c11c",
"2a06:3040:9:610::c11d",
"2a06:3040:9:610::c11e",
"2a06:3040:9:610::c11f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-sfo-wg-001.blockerad.eu"
}
}
},
{
"hostname": "us-sfo-wg-002",
"location": "us-sfo",
"active": true,
"owned": false,
"provider": "HostRoyale",
"stboot": true,
"ipv4_addr_in": "194.126.179.3",
"include_in_country": true,
"weight": 100,
"public_key": "sXWVQ/6I6Yj9fiA3yLqpLhnoq6qAVxkwRP7KirMRb3M=",
"ipv6_addr_in": "2a06:3040:9:610::f201",
"shadowsocks_extra_addr_in": [
"2a06:3040:9:610::c202",
"2a06:3040:9:610::c203",
"2a06:3040:9:610::c204",
"2a06:3040:9:610::c205",
"2a06:3040:9:610::c206",
"2a06:3040:9:610::c207",
"2a06:3040:9:610::c208",
"2a06:3040:9:610::c209",
"2a06:3040:9:610::c20a",
"2a06:3040:9:610::c20b",
"2a06:3040:9:610::c20c",
"2a06:3040:9:610::c20d",
"2a06:3040:9:610::c20e",
"2a06:3040:9:610::c20f",
"2a06:3040:9:610::c210",
"2a06:3040:9:610::c211",
"2a06:3040:9:610::c212",
"2a06:3040:9:610::c213",
"2a06:3040:9:610::c214",
"2a06:3040:9:610::c215",
"2a06:3040:9:610::c216",
"2a06:3040:9:610::c217",
"2a06:3040:9:610::c218",
"2a06:3040:9:610::c219",
"2a06:3040:9:610::c21a",
"2a06:3040:9:610::c21b",
"2a06:3040:9:610::c21c",
"2a06:3040:9:610::c21d",
"2a06:3040:9:610::c21e",
"2a06:3040:9:610::c21f",
"194.126.179.24",
"194.126.179.25",
"194.126.179.26",
"194.126.179.27",
"194.126.179.28",
"194.126.179.29",
"194.126.179.30",
"194.126.179.31",
"194.126.179.32",
"194.126.179.33",
"194.126.179.34",
"194.126.179.35",
"194.126.179.36",
"194.126.179.37",
"194.126.179.38",
"194.126.179.39",
"194.126.179.40",
"194.126.179.41",
"194.126.179.42",
"194.126.179.43"
],
"features": {
"lwo": {},
"quic": {
"addr_in": [
"2a06:3040:9:610::b202",
"2a06:3040:9:610::b203",
"2a06:3040:9:610::b204",
"2a06:3040:9:610::b205",
"2a06:3040:9:610::b206",
"2a06:3040:9:610::b207",
"2a06:3040:9:610::b208",
"2a06:3040:9:610::b209",
"2a06:3040:9:610::b20a",
"2a06:3040:9:610::b20b",
"2a06:3040:9:610::b20c",
"2a06:3040:9:610::b20d",
"2a06:3040:9:610::b20e",
"2a06:3040:9:610::b20f",
"2a06:3040:9:610::b210",
"2a06:3040:9:610::b211",
"2a06:3040:9:610::b212",
"2a06:3040:9:610::b213",
"2a06:3040:9:610::b214",
"2a06:3040:9:610::b215",
"2a06:3040:9:610::b216",
"2a06:3040:9:610::b217",
"2a06:3040:9:610::b218",
"2a06:3040:9:610::b219",
"2a06:3040:9:610::b21a",
"2a06:3040:9:610::b21b",
"2a06:3040:9:610::b21c",
"2a06:3040:9:610::b21d",
"2a06:3040:9:610::b21e",
"2a06:3040:9:610::b21f",
"194.126.179.44",
"194.126.179.45",
"194.126.179.46",
"194.126.179.47",
"194.126.179.48",
"194.126.179.49",
"194.126.179.50",
"194.126.179.51",
"194.126.179.52",
"194.126.179.53",
"194.126.179.54",
"194.126.179.55",
"194.126.179.56",
"194.126.179.57",
"194.126.179.58",
"194.126.179.59",
"194.126.179.60",
"194.126.179.61",
"194.126.179.62",
"194.126.179.63"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-sfo-wg-002.blockerad.eu"
}
}
},
{
"hostname": "us-sjc-wg-001",
"location": "us-sjc",
"active": true,
"owned": true,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "23.144.160.67",
"include_in_country": true,
"weight": 100,
"public_key": "FGcXuLkvErFPiTPAjtJusTtbCoFkJOK8SXHwWOeNYUM=",
"ipv6_addr_in": "2604:e8c0:6::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"23.144.160.72",
"23.144.160.73",
"23.144.160.74",
"23.144.160.75",
"23.144.160.76",
"23.144.160.77",
"2604:e8c0:6::b002",
"2604:e8c0:6::b003",
"2604:e8c0:6::b004",
"2604:e8c0:6::b005",
"2604:e8c0:6::b006",
"2604:e8c0:6::b007",
"2604:e8c0:6::b008",
"2604:e8c0:6::b009",
"2604:e8c0:6::b00a",
"2604:e8c0:6::b00b",
"2604:e8c0:6::b00c",
"2604:e8c0:6::b00d",
"2604:e8c0:6::b00e",
"2604:e8c0:6::b00f",
"2604:e8c0:6::b010",
"2604:e8c0:6::b011",
"2604:e8c0:6::b012",
"2604:e8c0:6::b013",
"2604:e8c0:6::b014",
"2604:e8c0:6::b015",
"2604:e8c0:6::b016",
"2604:e8c0:6::b017",
"2604:e8c0:6::b018",
"2604:e8c0:6::b019",
"2604:e8c0:6::b01a",
"2604:e8c0:6::b01b",
"2604:e8c0:6::b01c",
"2604:e8c0:6::b01d",
"2604:e8c0:6::b01e",
"2604:e8c0:6::b01f"
],
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"23.144.160.78",
"23.144.160.79",
"23.144.160.80",
"23.144.160.81",
"23.144.160.82",
"23.144.160.83",
"23.144.160.84",
"23.144.160.85",
"2604:e8c0:6::c002",
"2604:e8c0:6::c003",
"2604:e8c0:6::c004",
"2604:e8c0:6::c005",
"2604:e8c0:6::c006",
"2604:e8c0:6::c007",
"2604:e8c0:6::c008",
"2604:e8c0:6::c009",
"2604:e8c0:6::c00a",
"2604:e8c0:6::c00b",
"2604:e8c0:6::c00c",
"2604:e8c0:6::c00d",
"2604:e8c0:6::c00e",
"2604:e8c0:6::c00f",
"2604:e8c0:6::c010",
"2604:e8c0:6::c011",
"2604:e8c0:6::c012",
"2604:e8c0:6::c013",
"2604:e8c0:6::c014",
"2604:e8c0:6::c015",
"2604:e8c0:6::c016",
"2604:e8c0:6::c017",
"2604:e8c0:6::c018",
"2604:e8c0:6::c019",
"2604:e8c0:6::c01a",
"2604:e8c0:6::c01b",
"2604:e8c0:6::c01c",
"2604:e8c0:6::c01d",
"2604:e8c0:6::c01e",
"2604:e8c0:6::c01f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-sjc-wg-001.blockerad.eu"
}
}
},
{
"hostname": "us-sjc-wg-002",
"location": "us-sjc",
"active": true,
"owned": true,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "23.144.160.86",
"include_in_country": true,
"weight": 100,
"public_key": "A/FGRjSdq2is0cFCBixLy5Htx5SYFXsVVs28Lv1wsCs=",
"ipv6_addr_in": "2604:e8c0:6::f101",
"daita": true,
"shadowsocks_extra_addr_in": [
"23.144.160.91",
"23.144.160.92",
"23.144.160.93",
"23.144.160.94",
"23.144.160.95",
"23.144.160.96",
"2604:e8c0:6::b102",
"2604:e8c0:6::b103",
"2604:e8c0:6::b104",
"2604:e8c0:6::b105",
"2604:e8c0:6::b106",
"2604:e8c0:6::b107",
"2604:e8c0:6::b108",
"2604:e8c0:6::b109",
"2604:e8c0:6::b10a",
"2604:e8c0:6::b10b",
"2604:e8c0:6::b10c",
"2604:e8c0:6::b10d",
"2604:e8c0:6::b10e",
"2604:e8c0:6::b10f",
"2604:e8c0:6::b110",
"2604:e8c0:6::b111",
"2604:e8c0:6::b112",
"2604:e8c0:6::b113",
"2604:e8c0:6::b114",
"2604:e8c0:6::b115",
"2604:e8c0:6::b116",
"2604:e8c0:6::b117",
"2604:e8c0:6::b118",
"2604:e8c0:6::b119",
"2604:e8c0:6::b11a",
"2604:e8c0:6::b11b",
"2604:e8c0:6::b11c",
"2604:e8c0:6::b11d",
"2604:e8c0:6::b11e",
"2604:e8c0:6::b11f"
],
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"23.144.160.97",
"23.144.160.98",
"23.144.160.99",
"23.144.160.100",
"23.144.160.101",
"23.144.160.102",
"23.144.160.103",
"23.144.160.104",
"23.144.160.105",
"2604:e8c0:6::c102",
"2604:e8c0:6::c103",
"2604:e8c0:6::c104",
"2604:e8c0:6::c105",
"2604:e8c0:6::c106",
"2604:e8c0:6::c107",
"2604:e8c0:6::c108",
"2604:e8c0:6::c109",
"2604:e8c0:6::c10a",
"2604:e8c0:6::c10b",
"2604:e8c0:6::c10c",
"2604:e8c0:6::c10d",
"2604:e8c0:6::c10e",
"2604:e8c0:6::c10f",
"2604:e8c0:6::c110",
"2604:e8c0:6::c111",
"2604:e8c0:6::c112",
"2604:e8c0:6::c113",
"2604:e8c0:6::c114",
"2604:e8c0:6::c115",
"2604:e8c0:6::c116",
"2604:e8c0:6::c117",
"2604:e8c0:6::c118",
"2604:e8c0:6::c119",
"2604:e8c0:6::c11a",
"2604:e8c0:6::c11b",
"2604:e8c0:6::c11c",
"2604:e8c0:6::c11d",
"2604:e8c0:6::c11e",
"2604:e8c0:6::c11f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-sjc-wg-002.blockerad.eu"
}
}
},
{
"hostname": "us-sjc-wg-003",
"location": "us-sjc",
"active": true,
"owned": true,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "23.144.160.106",
"include_in_country": true,
"weight": 100,
"public_key": "PHvr2i7PvHljrPvbMpSQikfksXJNA/tseNeplNv1Wn8=",
"ipv6_addr_in": "2604:e8c0:6::f201",
"daita": true,
"shadowsocks_extra_addr_in": [
"23.144.160.112",
"23.144.160.113",
"23.144.160.114",
"23.144.160.115",
"23.144.160.116",
"23.144.160.117",
"2604:e8c0:6::b202",
"2604:e8c0:6::b203",
"2604:e8c0:6::b204",
"2604:e8c0:6::b205",
"2604:e8c0:6::b206",
"2604:e8c0:6::b207",
"2604:e8c0:6::b208",
"2604:e8c0:6::b209",
"2604:e8c0:6::b20a",
"2604:e8c0:6::b20b",
"2604:e8c0:6::b20c",
"2604:e8c0:6::b20d",
"2604:e8c0:6::b20e",
"2604:e8c0:6::b20f",
"2604:e8c0:6::b210",
"2604:e8c0:6::b211",
"2604:e8c0:6::b212",
"2604:e8c0:6::b213",
"2604:e8c0:6::b214",
"2604:e8c0:6::b215",
"2604:e8c0:6::b216",
"2604:e8c0:6::b217",
"2604:e8c0:6::b218",
"2604:e8c0:6::b219",
"2604:e8c0:6::b21a",
"2604:e8c0:6::b21b",
"2604:e8c0:6::b21c",
"2604:e8c0:6::b21d",
"2604:e8c0:6::b21e",
"2604:e8c0:6::b21f"
],
"features": {
"daita": {},
"lwo": {},
"quic": {
"addr_in": [
"23.144.160.117",
"23.144.160.118",
"23.144.160.119",
"23.144.160.120",
"23.144.160.121",
"23.144.160.122",
"23.144.160.123",
"23.144.160.124",
"23.144.160.125",
"23.144.160.126",
"2604:e8c0:6::c202",
"2604:e8c0:6::c203",
"2604:e8c0:6::c204",
"2604:e8c0:6::c205",
"2604:e8c0:6::c206",
"2604:e8c0:6::c207",
"2604:e8c0:6::c208",
"2604:e8c0:6::c209",
"2604:e8c0:6::c20a",
"2604:e8c0:6::c20b",
"2604:e8c0:6::c20c",
"2604:e8c0:6::c20d",
"2604:e8c0:6::c20e",
"2604:e8c0:6::c20f",
"2604:e8c0:6::c210",
"2604:e8c0:6::c211",
"2604:e8c0:6::c212",
"2604:e8c0:6::c213",
"2604:e8c0:6::c214",
"2604:e8c0:6::c215",
"2604:e8c0:6::c216",
"2604:e8c0:6::c217",
"2604:e8c0:6::c218",
"2604:e8c0:6::c219",
"2604:e8c0:6::c21a",
"2604:e8c0:6::c21b",
"2604:e8c0:6::c21c",
"2604:e8c0:6::c21d",
"2604:e8c0:6::c21e",
"2604:e8c0:6::c21f"
],
"token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
"domain": "us-sjc-wg-003.blockerad.eu"
}
}
},
{
"hostname": "us-sjc-wg-302",
"location": "us-sjc",
"active": true,
"owned": false,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "142.147.89.210",
"include_in_country": true,
"weight": 0,
"public_key": "8wVb4HUgmpQEa5a1Q8Ff1hTDTJVaHts487bksJVugEo=",
"ipv6_addr_in": "2604:e8c0:7::f001"
},
{
"hostname": "us-sjc-wg-303",
"location": "us-sjc",
"active": true,
"owned": false,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "142.147.89.225",
"include_in_country": true,
"weight": 0,
"public_key": "2ZQTRk/3jT+ccfG3G/QoJV3NFC4CFHQwGBCSokOvBnA=",
"ipv6_addr_in": "2604:e8c0:7::b68f"
},
{
"hostname": "us-sjc-wg-401",
"location": "us-sjc",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "79.127.217.34",
"include_in_country": true,
"weight": 100,
"public_key": "2q0LGwWvnV2qbNEAgOOHh4tvol5vGeQXJZDAbazCSBY=",
"ipv6_addr_in": "2a02:6ea0:e611::f001"
},
{
"hostname": "us-sjc-wg-402",
"location": "us-sjc",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "79.127.217.47",
"include_in_country": true,
"weight": 100,
"public_key": "+UZsgTzYTdG3LvqpL+V9ZkwEMiFcls32YlpuI0cqDQ4=",
"ipv6_addr_in": "2a02:6ea0:e611:1::f001"
},
{
"hostname": "us-sjc-wg-501",
"location": "us-sjc",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.92.3",
"include_in_country": true,
"weight": 100,
"public_key": "wbK8/hP/ZMr972OtanZxugSqUVt/sM/G9rnTiQ5YbSw=",
"ipv6_addr_in": "2607:9000:800:31::f001",
"shadowsocks_extra_addr_in": [
"23.234.92.14"
],
"features": {
"lwo": {}
}
},
{
"hostname": "us-sjc-wg-502",
"location": "us-sjc",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.92.127",
"include_in_country": true,
"weight": 100,
"public_key": "dCHtOy+ieOOMzgpZPr557dXygpmlj9RRNCAvUQvXj3I=",
"ipv6_addr_in": "2607:9000:800:32::f001",
"shadowsocks_extra_addr_in": [
"23.234.92.139"
],
"features": {
"lwo": {}
}
},
{
"hostname": "us-sjc-wg-503",
"location": "us-sjc",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.93.3",
"include_in_country": true,
"weight": 100,
"public_key": "HqWGqZbCgLxYLGHQG7P3jHYWQgc5p6ImqaxgqA97WCY=",
"ipv6_addr_in": "2607:9000:800:33::f001",
"shadowsocks_extra_addr_in": [
"23.234.93.14"
],
"features": {
"lwo": {}
}
},
{
"hostname": "us-sjc-wg-504",
"location": "us-sjc",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.93.127",
"include_in_country": true,
"weight": 100,
"public_key": "hQ/UqXflXztKM2T39HmQRPpPjWP8I2r9FMqnqFWy53M=",
"ipv6_addr_in": "2607:9000:800:34::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"23.234.93.139"
],
"features": {
"daita": {}
}
},
{
"hostname": "us-sjc-wg-505",
"location": "us-sjc",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.94.3",
"include_in_country": true,
"weight": 100,
"public_key": "v0CXmb+wIy1P+IbFA/1nYTB3KoDzFyW5k7n8vXoTxiY=",
"ipv6_addr_in": "2607:9000:800:35::f001",
"daita": true,
"shadowsocks_extra_addr_in": [
"23.234.94.14"
],
"features": {
"daita": {}
}
},
{
"hostname": "us-sjc-wg-506",
"location": "us-sjc",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.94.127",
"include_in_country": true,
"weight": 100,
"public_key": "sjWKL/W2+21cyjEBjtMd4TQQlWTsLTUN4skYOF7YgnU=",
"ipv6_addr_in": "2607:9000:800:36::f001",
"shadowsocks_extra_addr_in": [
"23.234.94.139"
]
},
{
"hostname": "us-sjc-wg-507",
"location": "us-sjc",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.95.3",
"include_in_country": true,
"weight": 100,
"public_key": "IKhrTUlWJXlcH30jNV82mlWlj6NEre3PZffJ7MoT0zc=",
"ipv6_addr_in": "2607:9000:800:37::f001",
"shadowsocks_extra_addr_in": [
"23.234.95.14"
]
},
{
"hostname": "us-sjc-wg-508",
"location": "us-sjc",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.95.127",
"include_in_country": true,
"weight": 100,
"public_key": "rIqRJ1o3UxvuwXj9B7VDquiTZ8BtQdab4wsb4F1L7l8=",
"ipv6_addr_in": "2607:9000:800:38::f001",
"shadowsocks_extra_addr_in": [
"23.234.95.139"
]
},
{
"hostname": "us-slc-wg-301",
"location": "us-slc",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.112.3",
"include_in_country": true,
"weight": 100,
"public_key": "tA/k8ouzYiVmgCRCF7TWibVzv5xRp3cgv9TJX66poGE=",
"ipv6_addr_in": "2607:9000:d00:2::f001",
"shadowsocks_extra_addr_in": [
"23.234.112.14"
]
},
{
"hostname": "us-slc-wg-302",
"location": "us-slc",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.112.127",
"include_in_country": true,
"weight": 100,
"public_key": "6hF/LLVCkxlW+mH6wFob5ZiDZNu2DqfEj82w8wzVnHY=",
"ipv6_addr_in": "2607:9000:d00:3::f001",
"shadowsocks_extra_addr_in": [
"23.234.112.139"
],
"features": {
"lwo": {}
}
},
{
"hostname": "us-slc-wg-303",
"location": "us-slc",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.113.3",
"include_in_country": true,
"weight": 100,
"public_key": "Taa3TPPNUUcD3upveDHqpi9uaNHbeXzh6kX+sQUcM0s=",
"ipv6_addr_in": "2607:9000:d00:4::f001",
"shadowsocks_extra_addr_in": [
"23.234.113.14"
],
"features": {
"lwo": {}
}
},
{
"hostname": "us-slc-wg-304",
"location": "us-slc",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.113.127",
"include_in_country": true,
"weight": 100,
"public_key": "+ru/ZmhgTYWNLyn3ZWuC57PMOU64yMfuWPZ5ow0XY3A=",
"ipv6_addr_in": "2607:9000:d00:5::f001",
"shadowsocks_extra_addr_in": [
"23.234.113.139"
],
"features": {
"lwo": {}
}
},
{
"hostname": "us-slc-wg-305",
"location": "us-slc",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.114.3",
"include_in_country": true,
"weight": 100,
"public_key": "QkiwUWRNNtI+8YSK0SPCq6KeKPSohpX/8FbFZkx+uHg=",
"ipv6_addr_in": "2607:9000:d00:6::f001",
"shadowsocks_extra_addr_in": [
"23.234.114.14"
]
},
{
"hostname": "us-slc-wg-306",
"location": "us-slc",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.114.127",
"include_in_country": true,
"weight": 100,
"public_key": "Gv4GZOT46WQsTOAH4mYlauwFRxtpCX08BI0bzot5Piw=",
"ipv6_addr_in": "2607:9000:d00:7::f001",
"shadowsocks_extra_addr_in": [
"23.234.114.139"
]
},
{
"hostname": "us-slc-wg-307",
"location": "us-slc",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.115.3",
"include_in_country": true,
"weight": 100,
"public_key": "6pJrsejyhJLRotKdS+RCZez28/WqlOw6qEs1BbjQVSI=",
"ipv6_addr_in": "2607:9000:d00:8::f001",
"shadowsocks_extra_addr_in": [
"23.234.115.14"
]
},
{
"hostname": "us-slc-wg-308",
"location": "us-slc",
"active": true,
"owned": false,
"provider": "Tzulo",
"stboot": true,
"ipv4_addr_in": "23.234.115.127",
"include_in_country": true,
"weight": 100,
"public_key": "f7xT56F8RP9XDXW7UCxBcjgP+SAGyH+y2OZ4fieR4X8=",
"ipv6_addr_in": "2607:9000:d00:9::f001",
"shadowsocks_extra_addr_in": [
"23.234.115.139"
]
},
{
"hostname": "us-txc-wg-001",
"location": "us-txc",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "79.127.222.194",
"include_in_country": true,
"weight": 100,
"public_key": "+OCONjBoN5RytiPy000VOzhZsiu1tSzecmc1hl/q8hI=",
"ipv6_addr_in": "2a02:6ea0:fe00:1::f001"
},
{
"hostname": "us-txc-wg-002",
"location": "us-txc",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "79.127.222.207",
"include_in_country": true,
"weight": 100,
"public_key": "mjv8qVNwhVKO0ePAI97CRil188uwdR/VR6ihcNY/hio=",
"ipv6_addr_in": "2a02:6ea0:fe00:2::f001"
},
{
"hostname": "us-uyk-wg-201",
"location": "us-uyk",
"active": true,
"owned": false,
"provider": "HostRoyale",
"stboot": true,
"ipv4_addr_in": "104.36.50.3",
"include_in_country": true,
"weight": 100,
"public_key": "utm9eFUk8tH0j/dwKLJvlb6BRSfm3GZbomxr52ZDGn0=",
"ipv6_addr_in": "2a06:3040:22:620::f001",
"shadowsocks_extra_addr_in": [
"104.36.50.5"
]
},
{
"hostname": "us-uyk-wg-202",
"location": "us-uyk",
"active": true,
"owned": false,
"provider": "HostRoyale",
"stboot": true,
"ipv4_addr_in": "104.36.50.33",
"include_in_country": true,
"weight": 100,
"public_key": "8Rh2Qc+vXTREhJb/RfCcpXS13U9xSqy4Pnw4+Wwt7iE=",
"ipv6_addr_in": "2a06:3040:22:620::f101",
"shadowsocks_extra_addr_in": [
"104.36.50.35"
]
},
{
"hostname": "us-was-wg-001",
"location": "us-was",
"active": true,
"owned": false,
"provider": "Zenlayer",
"stboot": true,
"ipv4_addr_in": "185.213.193.3",
"include_in_country": true,
"weight": 100,
"public_key": "qD3AH8vI8MhEVc9+0+2O8zV0Gx9FfKdy7ri3Bnpzo10=",
"ipv6_addr_in": "2604:980:1002:11::f001",
"shadowsocks_extra_addr_in": [
"185.213.193.14"
],
"features": {
"lwo": {}
}
},
{
"hostname": "us-was-wg-002",
"location": "us-was",
"active": true,
"owned": false,
"provider": "Zenlayer",
"stboot": true,
"ipv4_addr_in": "185.213.193.127",
"include_in_country": true,
"weight": 100,
"public_key": "2AvJGG4MJfnJMRSR6kcha9FZMMkhJM/AtktI5DSESSI=",
"ipv6_addr_in": "2604:980:1002:11::f101",
"shadowsocks_extra_addr_in": [
"185.213.193.139"
],
"features": {
"lwo": {}
}
},
{
"hostname": "za-jnb-wg-001",
"location": "za-jnb",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "154.47.30.130",
"include_in_country": true,
"weight": 100,
"public_key": "5dOGXJ9JK/Bul0q57jsuvjNnc15gRpSO1rMbxkf4J2M=",
"ipv6_addr_in": "2a02:6ea0:f206::f001"
},
{
"hostname": "za-jnb-wg-002",
"location": "za-jnb",
"active": true,
"owned": false,
"provider": "DataPacket",
"stboot": true,
"ipv4_addr_in": "154.47.30.143",
"include_in_country": true,
"weight": 100,
"public_key": "lTq6+yUYfYsXwBpj/u3LnYqpLhW8ZJXQQ19N/ybP2B8=",
"ipv6_addr_in": "2a02:6ea0:f207::f001"
}
],
"port_ranges": [
[
53,
53
],
[
123,
123
],
[
4000,
33433
],
[
33565,
51820
],
[
52001,
60000
]
],
"shadowsocks_port_ranges": [
[
51900,
51949
]
],
"ipv4_gateway": "10.64.0.1",
"ipv6_gateway": "fc00:bbbb:bbbb:bb01::1"
},
"bridge": {
"relays": [
{
"hostname": "au-syd-br-001",
"location": "au-syd",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.141.154",
"include_in_country": true,
"weight": 100
},
{
"hostname": "ca-mtr-br-001",
"location": "ca-mtr",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "217.138.213.18",
"include_in_country": true,
"weight": 100
},
{
"hostname": "ch-zrh-br-001",
"location": "ch-zrh",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "193.32.127.117",
"include_in_country": true,
"weight": 1
},
{
"hostname": "cz-prg-br-101",
"location": "cz-prg",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "217.138.199.106",
"include_in_country": true,
"weight": 100
},
{
"hostname": "fi-hel-br-101",
"location": "fi-hel",
"active": true,
"owned": true,
"provider": "Blix",
"stboot": true,
"ipv4_addr_in": "193.138.7.132",
"include_in_country": true,
"weight": 100
},
{
"hostname": "gb-lon-br-001",
"location": "gb-lon",
"active": true,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "141.98.252.66",
"include_in_country": true,
"weight": 100
},
{
"hostname": "hk-hkg-br-201",
"location": "hk-hkg",
"active": false,
"owned": false,
"provider": "xtom",
"stboot": true,
"ipv4_addr_in": "103.125.233.210",
"include_in_country": true,
"weight": 100
},
{
"hostname": "jp-tyo-br-201",
"location": "jp-tyo",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "185.242.4.34",
"include_in_country": true,
"weight": 100
},
{
"hostname": "nl-ams-br-001",
"location": "nl-ams",
"active": false,
"owned": true,
"provider": "31173",
"stboot": true,
"ipv4_addr_in": "185.65.134.116",
"include_in_country": true,
"weight": 100
},
{
"hostname": "sg-sin-br-101",
"location": "sg-sin",
"active": false,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "146.70.192.38",
"include_in_country": true,
"weight": 100
},
{
"hostname": "us-lax-br-401",
"location": "us-lax",
"active": false,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "62.133.44.202",
"include_in_country": false,
"weight": 100
},
{
"hostname": "us-nyc-br-501",
"location": "us-nyc",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "212.103.48.226",
"include_in_country": true,
"weight": 100
},
{
"hostname": "us-nyc-br-601",
"location": "us-nyc",
"active": true,
"owned": false,
"provider": "M247",
"stboot": true,
"ipv4_addr_in": "38.132.121.146",
"include_in_country": true,
"weight": 100
}
],
"shadowsocks": [
{
"protocol": "tcp",
"port": 443,
"cipher": "aes-256-gcm",
"password": "mullvad"
},
{
"protocol": "udp",
"port": 1234,
"cipher": "aes-256-cfb",
"password": "mullvad"
},
{
"protocol": "udp",
"port": 1236,
"cipher": "aes-256-gcm",
"password": "mullvad"
}
]
}
}
5.7 - Pgp
Simeonwarren
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBGm/rtIBEADFDMFRtPbif4sMCPMf7de0jiDLCm7fok4Y4jZPwRMGw7pNc6jC
N6coa+9ZarYDv1luSzPDjU+cTh3J6A5nsfBM4zjB5FZXLRnH1Fe8Kw4n9ROlXBg6
8ixm+uRzdgMKWY3+w4Fx9FE36jet5Kx0mAuKk3v+1gT6K6jBstpyVT8RTgWmfMAO
tPUEXHJ6di80hPTicORMyGFVOBjb1eXnNlc4NgML5hJTkSTR9OyYKiWA1PglMfvW
ZDKKU03uuCsia8FrJGeF3m5oP99ntQqlj7rRh2jFNeJ67b5+/z16NpzddwYufVPS
TdgZ0H93iiWDhACVf7hi/83otXVt/2ltv753bsGwuBn0ga5SZFUMalnNOaaJsXLA
0mHRIoZSl3SjM6dv+m7Y3QnMkWCXGdvg8GhQiEVUBN7h9CpXvbcfNDEQshVLDihY
T623TLPzvkWF5AxSKU6SokgOkEVUhRAYNnn8NXhgVgMSmxXRL8VU72b1sJ3YcM2J
qLP363SOCZkTPTJUQZF1sUTpvpQJuxC6bpg0r5ecKtWHFHtQIw4fOnQgTPcmFhiw
hSao1Ed2Te4pz1g+B4JsWajbIxS9CO/08LIrDTEih6bgNWZH7+XPzPgkOXdXs9Fy
qQlZznbyOBx2ombKPo8HV2VxCPnjvbwHrO0d6xMeYQBdzYqY7wEvEksQswARAQAB
tClzaW1lb253YXJyZW4gPHNpbWVvbndhcnJlbkBhbHdhbGRlbmQuY29tPokCTAQT
AQoANhYhBOD5L3UneLIiAYU7Dgn0JC/sMMPRBQJpv67SAhsBBAsJCAcEFQoJCAUW
AgMBAAIeBQIXgAAKCRAJ9CQv7DDD0V9bD/0SbKwC+XFeN54tUx0S8Fw3PVn4+UyM
CMzt8P+xHA4wa7kQYqWpdSOxYPqeWpHUmGcdIL+Re22eoLbYjKVD58dGyFKfqXvi
fWYubvdhOSIHbjSiW/hqa6ycVO4FvA51iRmFRLCj6EriFVwfMsNdxCl7/fare0vR
JiIG1VwgAbb7/CnQxsjkuGz2Shee/OhR17lLyHEl8azQhi/HUD47jCZinDw97feW
nyboZyfFJbK3EdzYCrKiuyxp2XqkCez/4DyjgDpmp1m5gOieJasHYodJ3++Q3bDE
eikNDHiRemi59kCcCNWsgJCtvRk1AyWKM0D6Rs0hHbeDtg4OJcu7MsvNEgYx7xXP
hGoYEYek52T2utWPAx9SiO/Cibo5aIEM5sRZe4iUjIEysaluBf3YLGGdD4gdUVEw
Ehn9J+Nc1F6mWnZvlYOGEeh1h0c8AQIwRAGX8YZiAf1p/ScoQ1mjJe27hxZMMVnB
osQ3iGNnMyuiL763lY6lBYmO+Ogvfx9uSAKzZuRQwSwe/A7bOiDux+7fnI1CtPRk
VYf6hNeB55aGmF8LJ/qzKApXefnhxPa2El8KDYKnM10o1yvaHtFXY5PtR9hzgNXA
pflTzw6Xy3Susz0OOkuNimLE6ubYv9gl2UKALuQEW6otVnMQNzSy/HKfKXYPfR+c
d5K8B8AB4TjJRbkCDQRpv86yARAA67SYuAteECrZ8dU2L41UOI5f7nx8j0ycAr1N
tpc+aeNkkwHH/NQnOtHXLy9Binx9Mwh5kjcQw7IgR+dYxqCXgsYHZvLWjcEPyhp8
3aTA2Ek8LlXWmPindOVu2O8DBw0Y7SAVknSEQZd7Hwg7ShbpDszhfKr37ekIvUn4
dVfRJ4Qbwm+Wl131sXzNC2nTWMaSN3HKLSPf2lX4LV65MPYHtRpcx3Sf4QrQyA++
AkOnDRjw4hbzsWqOFRcN+z5m5G7/1qhWp9coLq2bAptgIUDi7YSm6yKkv8AaMugs
RvrtVFZnBCuKEEg3LXW6mR5wJTCNxIUQxfoTIWE8ZQEK2LEMiWBtTbOzdXGOs0BM
zC3lPRUHoNUOTfIVwkrtfuh31D9J1v52S2PhMKbKtc2jlJADG0NWDu+mWwITxEep
36A6ibLRtsZVL1+MSkISjTyTwC7cRON0wEdtj2szftLJ9c/AroE/wPaNq2PFv9Wu
w8I0wBTBwDpZ3vWioXHD12+Wo9zZmKL8QHBogM4GKZhTvMyQUOzrd6bi77VsAKiw
KteVV22sBUJzEvmTduOAY+B35ThHinmx50EFIbewDaUx15hGggAZhNKQNbqSIofb
0CgucCqPHsMntYv/71JMVoQX2o3DyrS9+lq3j2YiRRQzrh56DHh2W234m1sgLzU6
RgamLGcAEQEAAYkEcgQYAQoAJhYhBOD5L3UneLIiAYU7Dgn0JC/sMMPRBQJpv86y
AhsCBQkB4TOAAkAJEAn0JC/sMMPRwXQgBBkBCgAdFiEEFuxvv2wIGF1W5BG5192I
qwwHN/IFAmm/zrIACgkQ192IqwwHN/KsmA//a926zNLxaKwWkxXW79DAvVXOpHPg
psm0ZQNCG6wB6ArJKuuF+HtpYWWahoGHVRToWJPpeHpwtoBKJ7tjWzuaByZdQINH
6u5TR3k4pDy5lWAmu97s6nlyITqPgPZDyF+mtMUoKoVe3WnNO3jF5jus0C2yf6x7
47X7JmiQYKPfwmVFWk6cr0bmlLL3pCWORocgdAllqoI8Xk537Zx38gTbb/9pPGa1
UEnq5xSQX6VKPHw2ar684QuG02QCzGnovxT2sFHgEwJtHydwnt+WwzLg3NaJXny0
zhLEH0J80958nJtkjV4KUBFOWn1Rks83j6ElUGmI5qApfy943F8dW3192tU/JK+C
Ja4vg2skwV2pfIRQp2MabU3O+sUH9b/6Yl1pjgy6pVWbwBrdHwFDoU9jXVZxMsiS
HzageHVjy0MQ24G4doHn8TEWxCjOT4rmeMvmxm9mKlzZ5K+EfqMZDosXc8NGKIVm
s6KqFJ6AcKVPK7oKEYSDFA1SoAkY19z8pUv3Utib4F7CZvhlHVDUXJ12YeALR8db
BdZAptuLaqfos8+bAy8FxavlezIr1Kdlo2u+EKV2ytQtur4PHnoFrwm7zUqpbqkK
AP/ziYyejgUyGoqLo1xOtJORWHjum8DCZkYkZbdKCJdm3GOIgSbvLcRmE4cQZpCE
JBar+mo7dkTTgGZtLw//WkZWoZdoRLscvKvFAUWdfE5RqSNP1uzsEL10wJx2Qtv4
jux+PWM3WzSsAL/EfaX0ip8XU+xhb4BjtlvdVWcAum6dB18TMQZCVpAtWZiPEHNr
SQ6BndE4t/grnLHSRGOKmZO2QHUasZiwALMiaTKpou3l31B/+dxRvYbJaqF8h47I
P/GJaWCENoO3NwhYkrWfRpctJO8nR87airqkFxdjsFyH8KJWpEzDouDgk8lmhHYe
QEwjy29DKtu+ASoIXOUDuQOn+bT7sVLh8Rlbwj9z5qrnXwZfBTTABrUhIA/ogGv5
wD4kOQ0RbjYoMwGSUAMuQZ+zhCUPRh5lKG12PhrB2mJ0X7X9diCJ0Tvqp2uSm5Wt
vH2KUyItPCB60cPa/ZAuUoD3/wdDWxTbE3XkczidRPqFb1KjCOoDiFJTOHq2FdqH
s/Zz3vMslHHBs5TwFhxrNC0/XKLTv3gOr8lU72yzPakCXdGyiLOviAcl6TgGabgU
MWLtYeOqpy8NjwcDTv1PimLzDUuhoLWfeGm9TAviDVjhAl8clIzKfWczYhTt83xE
W0FlbwXN6N388iL3+Hxwn9Q62yFAkftSm19JD6H7rrTMQIsxUHq9IdOQ1H19AyEO
87wmnJ3PGSqL1cRIic/PSE4RkZIFuDbVAJtmzvDG9E/WSafGNwbDPK7aBbMFgjS5
Ag0Eab/OsgEQAMZM+4+gJmnSM4KOKei3dyqjjYhoOltgPe0UVAbMBh5RclbZ2EIh
GqKn2HlX8OYx4IFVvuqZSPzm4MF8CoWDZbXsjgUAfk+TltR14kzyuM0wzD1HrzoH
zxYzATDH9/ciNUfJJNcW6Vfe5tNEKsjUU3UGXJ3r8Q6WsOM/YMXYH5Gw39AHPgyV
xRlY6+CTNQQIaXR2SJFJQhiOiaO6PaFIzMidrheC71n0O64q44iTEtRwIqgCbENs
3WKLFN0z3Hz5e1Os6mz6+M7Sav1XwXyM6ysAtC3Utg8j/8w4ZPH+lJO3N96GIU8H
jRjYjLedH13f7r6scRhB6Mlfp1qPK8ehYZfS+nzAmLNnsD3taw2N0pCfB5mvSRPB
EE3EDBRd8A5IMPAZTTEo9gLSlfr0ANeo23znuxYYkIZ2jWhG7TWODuGrhWHjjdDy
en5CA5ZasrpIBk5ITiNDSUrWhQwH7hfLhAaCbdt+KeKqoFfVbmZbQ7dKEbW8P1ZB
s2NKSZGqCyya2POVp+Ws7jbLoPLgUCDOyPOIz+G7o4kCnx8nBINIWKHFA4bl8U9H
jrWIW8HhX9TeH6f+ZkwVLgRfKgUvYpDPjwvgRQnyBQTeO72LM1wA7spuvKbCN0k+
cbkWxlGeoNqEYpZAlDciZN+feh7FgIgrPeuzjEkNy9rJRji8If+75ShvABEBAAGJ
AjwEGAEKACYWIQTg+S91J3iyIgGFOw4J9CQv7DDD0QUCab/OsgIbDAUJAeEzgAAK
CRAJ9CQv7DDD0a1lD/9k39CGrOXtRqTmoH1QknLGuiIeqGBPZrnN6WSh5XF3hwLV
3j97ES3VPbwd10YWAaFw7v+kMKwAaTSVaOK9Z9s5CpKwBKZo8tlAvLVHtAAFP0FJ
KK0zTIcXSdNjMLVhBo9Rj1BcovsVBLXdhMCsxt9q19V+OeVwBV3c+1KOUhl3J015
Z1qb+xh8+SZHK9AHSYQMQebyRcH4VtJgPHx3SWNiVHMI5NbPiUO1SVZXcn8P2oyu
fthY+OKeCd8y51+ubfur2O43CTGDCYWAzkWh2Xrhy3n1NHVGPAsL4+7gqblotpu2
9ULcn1Tft1AW9wRWM3syeK1TXNmPX0M/0MXtoUIpmwE6LEDTu88K7LKLu6QJt8tu
0ZmyJ2Rc2koD6/L5o2mtYRF/5feQzWGs2S9NI3CMsO7RKz4t2kJf0hftAVaUN82R
gpKAWUtsVBNnUW8tOfNEq91ql46cUTC86FXRakD0NEEw2oEBxCHuFYfVwwOQXHgt
G62NzRM4dHHBMxg6J40lFq3WJ5P2bw+sOcZLsvex4OIByZZmujJEEDnYgf+p8z/F
JEL2jiLXb61BevMVixG3y7/vYSf0OCc6xvU5DXNlG1Q+Z0xE5jKSp1L3mldF3MWR
8mQC6Rg+RHQxxABmNrofeuu2umJSaB8z+0kdgeV93/AiXnX80PY3aCkbca3MGLgz
BGm/zsoWCSsGAQQB2kcPAQEHQNe+6zNbs5HKrdZnHgeik/y7v5QYQr1cLYqfdCQ4
9GbMiQI8BBgBCgAmFiEE4PkvdSd4siIBhTsOCfQkL+www9EFAmm/zsoCGyAFCQHh
M4AACgkQCfQkL+www9FTmRAAkO36Rc9FIpWLQqMp8/KkuEtOx4UTcD1HLdHtT9dB
gdVr+OgP0dRMwT7l7rKSgX7ueWhhDdPB0gIkI2tasO7qzuFHUf8ywDxrMVWk+AJf
A+2cdrP6RANGs15clFdKfqR/r9Zn0rxDRAJKnVMirqQt1ilCHXqaavvXDOsphPgT
reoApVVv2sJbQYuL9TQnVtzfcS4cQnRPGoIqBUP98IlAhA4wK26rY9btRj5Dt6Fg
clKGu1EPCsRBWNeK/ykAfoKwJqNdnJDTUok4yEgHHZA6EcReuZlTu5RaaoQh61IC
69hSQhMO0ZXuyQKVmmSx1LAzgcPeIUaLZzUtyKqA1GEnmB32K6QmHd1nHOatZDNs
o1IIkD2EMy4JjUu3mzDKi2rPpn977jD16XrxFGGkfOhyeYayLl+vO4gVXWmWpv1F
LrYrDjbzinD1SaBYOFFl7ar+BunJcmGOQO/StJWzDHQRmFi5yiM/nxTeK5DUSJwy
baWT0G8xYedvmOwL4s0+3OT3NwA958pvluCzAQyAYcGlnEotGVBxK7sADasHtJPQ
pIVvxkUxj0SDljpk8sdJY5K4r0uWOIy9AkZbxxxu4USw7fD+gSo7wYzH06Bsdj6x
ZyvmmmEa/V0b7e3k/AghvhqTPkZT3RFs44cGmK9SHKIBBHLMt6LEEqk1LmywtuK4
9+8=
=9DMa
-----END PGP PUBLIC KEY BLOCK-----
Detached signature created using the old key
-----BEGIN PGP SIGNATURE-----
iHUEABYKAB0WIQQzN2BQvnncpX2uEp/3LMCDXvUIegUCab/V6AAKCRD3LMCDXvUI
euylAP9F9HHcjEg2ABQaZ3pbtOxGqqgZkAxna1zo76XWsDqWGQEAq4eJamdvVnyy
+YTOnHXfG6GswSyaavue0DlxHhx2cQ8=
=LJwp
-----END PGP SIGNATURE-----
Old
-----BEGIN PGP PUBLIC KEY BLOCK-----
mDMEaA4PTxYJKwYBBAHaRw8BAQdAqQlRlsv3N0tK9onuKxG7RIt5AGtXyI1k35cM
WZa2jA60UnNpbWVvbndhcnJlbiAoc2ltZW9ud2FycmVuLWxhcHRvcDAxLXZtLWRl
dikgPHNpbWVvbndhcnJlbi1naXQtcHpld3FAYWx3YWxkZW5kLmNvbT6ImQQTFgoA
QRYhBDM3YFC+edylfa4Sn/cswINe9Qh6BQJoDg9PAhsDBQkB4TOABQsJCAcCAiIC
BhUKCQgLAgQWAgMBAh4HAheAAAoJEPcswINe9Qh6ofgBANcxQFFPu0SsDHzwzPoo
EETvNUIy+MOKlFWHowx+o/EEAP4iEWXFg+9ujKIn52G7Vi+MR4KT9I0gOnKKYv03
teGZCrg4BGgOD08SCisGAQQBl1UBBQEBB0BojOTJPJWTlFUdWcjnPYU1dT2B0lE6
sl3EJEY+r9PzewMBCAeIfgQYFgoAJhYhBDM3YFC+edylfa4Sn/cswINe9Qh6BQJo
Dg9PAhsMBQkB4TOAAAoJEPcswINe9Qh6dzQA+wanGg8efVClaSu9TBqqTtiIltAH
gQ8/G/6Wo1xY9DvlAP0SzZXlF5o2d0tqAuQ1MdEoXb+3TL7M6R4vxkjLvfeRDA==
=mJFu
-----END PGP PUBLIC KEY BLOCK-----
Openbao
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBGZx4nABEACnQllkFhq8bMuf9cgEqtpuJ133TWogetAW21nQUL7mKaPrrSdC
S63wR5hCTiSLpoBFSNACUTYINviIDcmseq54peOivGBQvw5ywZAznPDX7DqrrOP/
Cr6YYfIdK3bVA8filgio/NgRRaUXY0aUkUceKJhF1sjRWJoJR5nkZ6ltaHwgiW2P
mGb7stRPcn0Qa3gikbv/BTCxqKg7frQLsswcsb7lVJ/1d8xODLBQnwOFCCUwnTUV
7UL/6L7QV/hl0sBLSdmFDVVHnPAlCo46BL2LfaFRcJC123Uw4xJWaL+eN7x+hFZX
meVdDIgGWUilZM3Vau0au7i8eMwi5ezczrU/bHm7q+KnCi0KivUykDmngK4FQdC2
YkZo3mYTEnFdlfp7e4KHFB+2Yc2AgziwRbxDEuPTRTcIKfr7nlqiPEAbJSqmwQlt
u5dHYeqz6ZaeOZ3S+PqVDgznhZw1PVx0qDI5gdJY/WqlwvgjOaG9s3LwMezWvLub
P2JhpgpcXpNh1R+ShwHCawjGeJxL7GS5X0qYoarAaRdJKKsPt1dBFSyuLhwfuGL0
CaXqma5WklZDyMnAqdEufFE2bVhYZZPm7E/4O+AvNIZAeMthn1QaQnwH4pQP8H0r
jODxp+Sr0X6hmx07GDlzkvTaD7DjibqMyad5tBij4AdMYX0vTyLupVIXkwARAQAB
tCJPcGVuQmFvIDxvcGVuYmFvQGxpc3RzLmxmZWRnZS5vcmc+iQJXBBMBCABBFiEE
ZtFf3YcochnI4VR40gDNcChT5tAFAmZx4nACGwEFCThkCQAFCwkIBwICIgIGFQoJ
CAsCBBYCAwECHgcCF4AACgkQ0gDNcChT5tASvw//Wx21z9DAKHuHn597UB/O9wXz
OkhHedFEq89z6+oJj7lvpnwvK5kRqnqiajerZVcbJCeq2o55qK5Q+YQFIMzJungt
zbT1d2QM99QWHq2oJD6YB1y0eUvYe+h8kLh1ljPPflLngrZJH+OtqavaIV3TS874
o6taePVyIuGRyKrQWBaYnSra7WYoeHgLqVx3KVdIwowWI48wDfBsfs5quOzJMkdg
kbxOFgb3rMtPwW72yQGN0I7xLNZQkSchgFjuX6Ue2Q8QOCkkVn1qmf1aSgavGvpW
EcGeMGvdZlzVR451/B5NKvVWFsoT3filUQzJeAN2TiNj09wr8JyIrOxf6j0vnrwD
ClrMVdtT5yDf+ZkPBya2igISPmhuKc2jezroXu7FEqzKcXsJQSV6DWhzb0RDZ00S
2pBDDs4jNGm/svwbwfz7DaBz6PnfTIZfN0ytBcGZ8OfWHksb73GvR94UIm/B8FgQ
9911xfaj/rZOd1NoL8DEw1s4KY/QRJZgKLcBh5L/AU1yZR5dUsqg88LtDCgohnug
jMVwJFsqiAF/nsfClU/pLwNCb5MP0u9rWKt+88DLc1hVUoKJn2sb6OhQeBpcZB+v
ZKcg8OM4QsY4LRWOzi5DtA6YnBYL01C0pLal6RNAnprtKaxlaoEJLlO43rJdnDSM
llN8DKC2PndsTqVofj25Ag0EZnHjqQEQAMyuoe8era7DvgkzY0lmKiILVFs9TroV
dFMaN+oGdphpn/uwrU+/gEzGemm23pkJuRpY1joS9NRyxAObIcLQulL7dcsyiRTl
m8fz6eSUlgVHrysGuArGolJRLy/BOgN0YMq5YB5N6dbzECUu7I13GmumLyxeVkTV
Pjvob91xqHJ/8JBmTmU+VQ4/SciBfvCPUHCKUA5iP5b3YLjN7zNzZ2ZmUs4AxqWS
lVrI1HZi/K1sLqCmzjIjG3Pc3JiK4Ox87JZWsv0ZGUJwgCdgthLe/fyaUuvZtfv0
Y/4e+IO7YnrekWGy3sHqSO8npdlPpwzlTlmOqHx2VpG5DlUCDy8qh4o8ya/u5YEq
Osd1Z04PsRLzB6Rl/D/lWsaztDp2Ec2U/Bv3R+bswPlIuPe3got1Q1768GQadSz6
PoxzDXBfS+Qk3do6kCsm7AUGlmH/M0SByA7kYt/mpkPrsCaF7TWUcR6p0j/VsAI7
Lk0ipYxYly8SRKARyAR811D+QFxmhLcQNTLdhxSAKKZS4n3qp3xuGQ5qfItsAFwR
+8qH19iOpLhWm/3Rgolt19G+gVUkyZEB4c0OrwAEcgHZrIgmtnELnKoAn7LJsZh6
n3heef5gmRPPF66dqXKYZTA3TrZjKJXE0C0B+3V/qaV6SNkfWhf5WGwqJ7Ot64pJ
vr53uj6PRaflABEBAAGJBHIEGAEIACYWIQRm0V/dhyhyGcjhVHjSAM1wKFPm0AUC
ZnHjqQIbAgUJOGQJAAJACRDSAM1wKFPm0MF0IAQZAQgAHRYhBOYX3NQGXCr8Cyz3
p7qLwIwPaR+UBQJmceOpAAoJELqLwIwPaR+UQx4P/0icW/kHRw/7xN24pJP2CnmL
Rga6M2H8hV4jwc2AuFuVsi/QsZKosHtFnISitl+w3crhjb/dA5ugfeQmuZpyaem0
OIk0nJLzBEdyRBTdR4b6MvraaU63KIYN6QPdHZtmFSd99MRCh6wz+S+H+K7yIDRJ
Ok4dZ2oGzQReLymsK1Ebpxl4KOlh0fT2Jz98i2enpz3AvPBJJEh6yf3/6cqb4jOa
37RVU2fuTaYVv6WwekoqkLnec0pDPuz8LUSx9yOsmXff/g+ONge8vK/EngQu5gxw
pbmF39Ki2rlFAS6yMo4SU7C+UMcx4fa4Ysa0ZByx0iy7hhRG6XhjTWEP8TZx3tGC
JCQ4/eAjpjFPQFXeOcjJcAtVb1bQCr5f+xNdMYedIaP4RbFLfhuKaMiTzrwm1Vcc
EwV4e93oPGjYwMW72XXQUgpbDiRITYYuZ3D8h2Gu3IM1ptMlCZ9cKXfkl4TKDoyx
ZtHDGMpKlXqjgYWRweeq2ZYf5y+rL9Me0/rh4JcYUInTn/XXgw/OyP9dSJjbClJ1
JCrLYBbZwofdSj0IgOA8riMzsKZBlSzS9TMfZ+QjuMSea7tYPgYNh5IwS6g8obNR
MkAZbwc0i9wSe3nohVcI7yEYilvkd4XaO/59KUrrR3piBvcotHx1QZ4M9w7BQx3r
a3e/4l2OHp7qP002DjRe0d4QAKV7971qxuAiTBkppf+KQo2Yla0xJbQUNwEHWHfM
YrUXvpPrHmID5jCR4+RoVvoxD2QGlj7mRhfv6m+J0WiE1k/4YEFxL+a4IupcLETT
n+p4bRdkVcV2a5ujrHxLU9sPtEXPGQhMjDH43FRJWNiJDIXWTBgaE2QVLpWT5ebe
qmxYBxDmexwJkiWjtBE2BO3NBxAVAw5iIvwxaSQ5pwHKQb1QeNeNVwcXOHz3t/t5
/n0pct/RD8N6hyae0fgJwjnauqsmf05nkI0xX8gdm9zaTSEFEaL3oLrRDQ+K62my
BL8DGTF9FFKV3n7lIiAhWG6OelWc4OmOnqExMb7KAZbsOzpN0Xq+S9+sFOlBhMJj
hi4pzT6ScnFglK4rQsX0dOS8oHToCXOxtzFj2WFUOnm7qtyQGKf+rpBnThvro+ep
VY3L+BDLGAMhHZsk+UAtN9a8kVGVlXrDKeFd18JMlGtxqCNVC6PGm7TEVQJ9GU2d
M19dmvNlRud4Jy4yaKp8KtJ175xPFtF4K8REiQN1XH7GIp70UWOifxSrkuYHf6ac
/2gUPx/f77XNOhECfEzR3qJi5/AgucxM4F69iaHQUVBTjiyocmQwN/eD+VrvlC4e
c4/joxuECGIF5ElE9A6d7zKkEXl18m1eZQ15tvkFyTr3TWy/b/khRTQgW33OQPpK
p3K7uQINBGZx5RgBEAC3Qits8vR4XzyHbTc9nBcquyuy8I6uYaaixEegMZRGfM62
RmgZjyGTDGF1vwmgQb0wha35b9DD33qnDb/Ea/yhUCY43nyDdvWzjIzhPTRRTn+O
5vI48PlGGzm6VHiUrO+Ds8cGbTqalzW/04ARLEHu+1U27B8+6vi9Pd+63MJl06rZ
r6F9F6lmG3XCqtXpGUv1NTI0vuOosElny546S99IqcA1TG68XozsW3mNv3R6EQb2
YEUlh3cANvWsNGDK5gH/l7Z+PsZvJW3z2bqWkD6dU5HmEE03KnNSAbs7H1Jvt6y6
kJjTo1QwTmapEf6VZ/YJigVC4YiOmdKeqr8rIWiW6dFH7YEXOjzDlWubJw+qNz1N
oN/wJtEPG0AF4QC14G3qGi0Gzw5mcZXzC+9zXJnrdNRae2PRxpSzHfSjS8vHXwNV
oE2G5zzsnfjF5MV5e4H07mBSZ0/NZiWnkN735CaFVgXSh7MSpm8q1L4H4NL0aMFr
c91HvZo7wiNMp/vDv3Tw1Mx+H9+E2djWfazfRP6SMXuEYSH1h7EAcDWWhEdIhZcC
OIoLuL/esuaK6PUxvUxDeR7M0HiyarLwUbsCSmOz2QbuMqtFmIIPNJO/ohmNC8et
9WvDAMOGkSZ3wHfyFL5yD1sLeN2FE/B1M0F/9eLttmDaOBjY7NtRCB2zzZ8FLwAR
AQABiQI8BBgBCAAmFiEEZtFf3YcochnI4VR40gDNcChT5tAFAmZx5RgCGwwFCThk
CQAACgkQ0gDNcChT5tCXIA/+PQ4WN9+pdeo7kgVjtyOz3XqQOoo+Cg01jIEmSS0r
iN/QK7iwWlxnHrhGdSjIvjM+Frx0dNGJJGaat4AVCkfo5v33SfTvn/5luS4rQiVu
TDOOIvv5d1cs8NO9kzwNBk8zMzUMad0XDiayeNGy30PUock5Qiv+oFZJ1OjiSfJ0
DNhhcEUogDvUXaeMXY9DBxAq1SDQZZSh5M+xspuPAfw3oz17Ix07DVijqTY8FStA
GANGzqtty4lfYKJuraYOnI83hQYQSO+OT01okldrUZE5WegMhrwi9prIleHjyOdF
2z6goRSH6jraYCpIXbyzLn91nYGm6Os8p0Bgvv6aFicNXKJ7XOLAh7UcCvKVrfrn
nGIywFbOAxp/lEKAZrPQ8HYjMCbOYqntw1+4BbcgART9y9OY7xNFGxRn3kdxGD/0
ue65RfY1IikPtZDNHGTYft2N3pI802VvlK4gizRSg9OJ4Tvs2x0sSxD9/P4wlwga
B6hw4NTXUre2bFUezE2gvHAnzKf6kN/59hmsQBB0QGOo9Bdt+c/17yT/TImGaf2E
XGyohhRqHw0vTn8GgnQtPQoip9cnDzU5c/MpS28A4yGxG46fIpMRIJ7bX1k/V0Az
Fd9lHWrRp+XQLjT/Y28NrFKHgOWKZZfTC+K5zax2sEezDFIMSpCmBy3rLjLl2JbY
f3S5Ag0EZnHlvgEQANi0HuC3XJiEQhlD+qciZW9fPSqsgPL0wX+x9qICBLuueWQk
5wZ+Oo476/VVy4Q6bGU/lpyDN2tiv/CQ/vejFsau90qMMsf1QlAVwNC/QFrUhDnZ
vjPjajORZuSad22efnRa8+PLTk0Iow/aqQefv0esINl6Ial7fEuBP0BG+BzU0c7+
zKHjAcqVwqtzyn0my/PqBlsXLJthwjqCiBMBLwf8BwkCsYEdOysHpsEZJUF4mQKs
Cm6QRSZylyyHnFvAk4RiVdVXZDx8HyIiKQw22H+kUYR6y6977Gi9dV2zOzwIgY43
RBBTCmiGpkbeIE6gtL1P5W8VMGwhdWVRCKK+6sB+Txlwo2iCUchuBbsVI5QoDKn4
JvzTEVMBGNH3hkIKg2atrZJ+vOaQk5ZVdmpbcPZ7rx88zFnKS2XwRrwgO82HUSNR
RLqUzf3bioNNxFGmtwcwTafT0feeFPFCs6TZWcaPtb32qYUdcoU+ZFXMNGk0k++Q
rqfbMvlVD5mn2VuCG3pzmk5oxg8OfqyaUv2Rr2DgMEm2mjtDR/SSRA9g37FMihe/
i7bRXI6JeCDQe9k9kpygvOb6lxRwScS8b5Po2YOLUd9TW+bHmaPXTnkEjfOk/Z8w
2I7nrUz44/aL7XVf2pyzKKgoTlzM52mNvYH+WKF/0g2nz2kYsZqF61VXC+RLABEB
AAGJAjMEGAEIACcWIQRm0V/dhyhyGcjhVHjSAM1wKFPm0AUCZnHlvgMbIAQFCThk
CQAAAOqDEACBwdvGyhm2vO4ZsnLmfq88OR0HCa2SsdB66XBF4e9EN0d4fNQkqQz0
6xq4Z4Pr3dIu41yrlKJhtK3wWbs4mpqGpUU4SXmlAJrh5G3QBzhoQNJwRSxBUu1H
7wYWZDfNzALQyHzfn8KUt9j9F5J7T80Uk9yT5ni27N5oTZBFoLZvf1441qdOPvkm
2XZiNS3/y57+N8J6x8Uk4ruE8/2c4Br008MXlX5ELmpbAW7yVFi6C+TvoM5QJgBs
cz6wz7bz6ZLtZmAeRZACx8teNr5sl64lKdZ74fVibPxQ2zYJLs/MCJ8H3hcjLAk7
RGfuZMKTmiacTihTTxtrQH7l6kB5oTYLkEZ5anP+Rl1m4PtHj/L7td/Af1iBBfdm
7MM3utNxRmQUC0lYw/058riksFWLQfHvgb/yICXG2TN0Q+75MHbnXknsi+8amw0z
Rb50sYi2GBa5NII+gj+2jXtakz2RlWhN0+XuTtBMHKNLpe1qh64tLrVjHGivAZwi
wIUySjVgdn9TKStReSyaDLUuYWnd3g2bKlBRjA0AIixnkEGxgajk5moaLpTHmXv4
qsIrrWjvFS0QOmuChHODqPKVR6T681HbElUkhDOBnMgRMyWxRc6WWV06IUrXZOdD
HJyC+hbV9j8H8Hwvq1RKzHeMaofejSqTJxBR8wExXC12PN7uon0DCA==
=coUG
-----END PGP PUBLIC KEY BLOCK-----
5.8 - ssh
Links
- CA generation: https://developer.hashicorp.com/vault/docs/secrets/ssh/signed-ssh-certificates
- OpenPGP ssh key: https://github.com/drduh/YubiKey-Guide/tree/master
ca_clients
CA for SSH clients
Source: ../../infra/vault/tf/output
Update: automatically
ca_servers
CA for SSH servers
Source: ../../infra/vault/tf/output
Update: automatically
simeonwarren
Source ./simeonwarren@alwaldend.com-2026-03-22-openpgp.pub
Update: manual export from the yubikey
5.9 - Ssl
5.9.1 - Alwaldend.com
Links
- Generation: https://arminreiter.com/2022/01/create-your-own-certificate-authority-ca-using-openssl/
- Vault: https://developer.hashicorp.com/vault/tutorials/pki/pki-engine-external-ca
Root CA
Source: ./root_ca.crt
Update: manually
Intermediate CA1
Source: ./ica1.crt
Update: manually
Client certificate CA
Source: ../../../infra/vault/tf/output
Update: automatically
Server certificate CA
Source: ../../../infra/vault/tf/output
Update: automatically
6 - Third party
This tree contains vendored and externally sourced code. All tracked content follows the repository’s public-source policy and retains its upstream license and provenance requirements.
Requirements
- Bazel targets MUST use repository-internal visibility unless an owning toolchain contract requires otherwise.
- Third-party content MUST NOT be represented or published as first-party source or artifacts.
- Third-party content MAY be used in builds.
- An explicit repackaging or mirroring target MAY publish an upstream artifact under its owner and license policy.
Publish vendored helm
This is a state-changing operator example. An agent needs explicit publication
authority and must invoke the target through bazel_agent.
bazel_agent bazel run //third_party:publish_helm.io_goharbor_helm_harbor
6.1 -
OpenSpec
The pinned OpenSpec CLI wrapper lives at //tools/openspec. Its generated
openspec-* agent skills are materialized from the pinned upstream release
archive declared in third_party/org_fissionai_openspec/; the resulting
.agents/skills/openspec-* entries are written as regular files by
//.agents:write_skills and verified by //.agents:write_skills_test.
6.2 -
OpenSpec
Upstream OpenSpec release archive pinned by tag. //third_party/openspec
materializes the skills/openspec-* instructions from this archive into the
consuming repository.
6.5 - com_github_bazelbuild_bazel_protobuf
6.7 - com_github_georgewfraser_java_language_server
6.8 - com_nanovms_ops
Links
- Site: https://ops.city/
- Nanovms site: https://nanovms.com/
6.11 - dev_sanaei_3xui
Links
- Site: https://docs.sanaei.dev/
- Releases: https://github.com/MHSanaei/3x-ui/releases
6.13 - Gradle
Pinned Gradle 8.13 binary distribution from the primary publisher.
Links
- Source code: https://github.com/gradle/gradle/tree/v8.13.0
6.14 - Images
Deploy ISO to Proxmox
bazel run //third_party/images:deploy_proxmox
Deploy ISO to Yandex Cloud
bazel run //third_party/images:deploy_yc
6.14.1 - Tf
6.19 - io_goharbor_harbor_cli
Links
- Site: https://goharbor.io/
- Releases: https://github.com/goharbor/harbor-cli/releases
6.21 - io_goharbor_offline_installer
Links
- Site: https://goharbor.io/
- Releases: https://github.com/goharbor/harbor/releases
6.25 - Lego ACME client
This package supplies the Linux x86-64 build of Lego 5.4.1, licensed under MIT. Its archive checksum matches both the publisher’s release checksum file and GitHub release asset metadata. The binary is packaged by the XCP-ng Ansible workflow; no package manager or lifecycle download runs on the host.
The binary_toolchain.json file owns the immutable version and integrity pin.
6.26 - net_zlib_zlib
Links
- Site: https://zlib.net/
- Module: https://registry.bazel.build/modules/zlib
6.27 - OpenHands canvas UI compatibility module
tools/canvas_ui_tool.py from OpenHands/OpenHands at tag v1.18.0
(commit 9120ff6cbbe23640f0e475661e5a9c9729cdbf1f). The OpenHands Agent
Canvas launchers import it into the agent server through
--import-modules canvas_ui_tool.
It is required because the automation preset builds its agent with a
finish_tool_response_schema, which registers the SDK’s builtin FinishTool
only inside the preset’s own process while advertising it to the agent server as
openhands.sdk.tool.builtins.finish. That SDK module does not self-register, so
every automation-dispatched remote conversation fails to resolve FinishTool
unless the compatibility module registers it in the agent server process first.
The module also keeps persisted pre-client_tools conversations resolvable.
It is vendored rather than copied so the upstream revision, license, and
provenance stay with the third-party tree.
Upstream license: MIT, see LICENSE.
6.33 - org_kernel_headers
Links
- Site: https://www.kernel.org/
- Header install: https://www.kernel.org/doc/Documentation/kbuild/headers_install.txt
- Reference: https://github.com/DanielEliad/rules_linux_kernel_headers/tree/main
Generate the config
zcat /proc/config.gz >third_party/org_kernel_headers/config.txt
6.34 - org_nmap_nmap
Links
- Site: https://nmap.org/
- Build: https://nmap.org/book/inst-source.html
6.38 - sh_helm_helm
Links
- Site: https://helm.sh/
- Releases: https://github.com/helm/helm/releases
6.39 - Terraform dependencies
include.MODULE.bazel owns the repository’s Terraform provider versions,
immutable release URLs, and SHA256 integrity. Consumers select the generated
provider labels through the public
rules_terraform rules. One version is
selected per provider source; the rule module’s resolution boundary can support
an explicit override policy later.
The pins were verified against the publishers’ release checksums listed by the Terraform registry protocol. Provider downloads use Bazel’s verified downloader. Terraform installs only from the selected runfiles mirror and writes provider locks in runtime workspaces.
The offline fixture in test/ checks installation with the declared Local
provider, failure without it, and isolation from inherited registry/cache settings.
Updating a pin also requires checking consuming Terraform constraints and these
provider integration tests.
6.41 - Xen Orchestra OIDC plugin
This package supplies Xen Orchestra’s AGPL-3.0-or-later auth-oidc 0.4.0
from upstream commit 4bc614ffd1417d3e0563522aeb4a195fa494c57c, including
OIDC group synchronization and the single-group claim fix. It can be installed
independently of the XO server; the Ansible deployment verifies its runtime
before restarting XO.
The plugin is plain CommonJS. Its complete runtime dependency set is
passport-openidconnect 0.1.2 (MIT), passport-strategy 1.0.0 (MIT), and
oauth 0.10.2 (MIT). The npm archives retain upstream license files and use
integrity values from the appliance revision’s
upstream lockfile.
Bazel fetches and verifies all inputs before deployment; Ansible extracts them
without a package-manager resolution or lifecycle script.
7 - Users
This tree contains user-specific code and infrastructure. Tracked source follows the repository’s public-source policy. Personal information and secrets must not be tracked or disclosed. Non-secret, non-personal operational facts remain public even when they describe generated or live state.
Requirements
- Bazel targets MUST use repository-internal visibility.
- User artifacts MUST NOT be published.
- User targets MUST NOT be dependencies of production build targets.
7.1 - simeonwarren
Generate a client cert
bazel run //users/simeonwarren:gen_client_cert -- --host phone1 --ttl "180d" --output_dir "${PWD}/certs"
Run opencode
bazel run //users/simeonwarren:opencode -- "${PWD}"
Apply terraform
bazel run //users/simeonwarren/tf:tf.apply
Prepare opencode
ln -s "${PWD}/users/simeonwarren/opencode.json" ~/.config/opencode/opencode.json
ln -s "${PWD}/users/simeonwarren/tui.json" ~/.config/opencode/tui.json
7.1.1 - Ansible
7.1.2 - Host Bot
Host Bot runs Traefik with mTLS in front of T3 Code. The host firewall blocks direct external access to T3 Code and accepts new connections only on SSH, HTTP, and HTTPS ports.
The DNS Terraform package uses the dedicated
src_users_simeonwarren_host_bot AppRole through dns_al. Ansible retains
its existing al configuration and user_simeonwarren authentication.
T3 Code controls permissions per thread. Its Auto mode maps to Codex
Auto-review. The managed Codex requirements allow read-only and host-bot
permissions with on-request approvals, so threads cannot select Full
access or disable approvals. The requirements file only allowlists the
host-bot profile; it must not define the profile because T3 Code supplies a
per-thread config layer with the same name, and Codex rejects profiles defined
by both requirements and config. The normal and isolated provider configs
define host-bot with workspace writes, public command-network access, and
write access to the Bazel cache and Bazelisk directories while keeping local
network binding and loopback connections available for Bazel servers. Other
private network targets remain blocked. T3 Code must select that profile for
the thread. Hosted web search is not restricted by this role.
The deployment installs pinned Bazelisk as ~/.local/bin/bazel, provisions
the repository’s bazel_agent runner in the same directory, and pre-seeds its
content-addressed mcp_cordis and repo_delivery runtimes when the canonical
repository checkout is present. New Codex worktrees can then start Cordis and
run delivery operations without first loading their own Bazel graph.
Two SATA SSDs, selected by their stable ATA IDs, back the sata_ssd volume
group. Its striped bazel_cache logical volume is mounted persistently at
/var/cache/bazel. Every Bazel workspace uses its disk_cache directory and
the managed user bazelrc points its output-user root at the same filesystem.
Automatic garbage collection caps the action disk cache at 700 GiB, leaving
room within the 1-TiB filesystem for output bases and install state; the
volume group retains about 900 GiB for later growth or another logical volume.
Because the volume is striped, either SSD failing invalidates the disposable
cache.
The managed user bazelrc limits each Bazel invocation to eight concurrent jobs and budgets half of the host CPUs for local actions. These scheduling limits apply to builds and tests; they do not impose a combined CPU cap across independent Bazel processes or Codex sessions.
Executable repository tools use /var/cache/bazel/tool_cache. Unlike the
disposable action and output caches, this directory is private to the host-bot
account. Cache entries are keyed by declared source, build configuration,
platform, and dependency pins, and are installed atomically after a Bazel
build on the first miss.
The arXiv MCP server is pinned to version 0.7.2 and runs locally over stdio.
Its downloaded papers and search data live under
/srv/misc/arxiv-mcp-server/papers on a reusable 100-GiB misc logical
volume in the existing sata_ssd volume group. The volume is mounted for
reconstructible non-executable application data. Data with durability or
different reliability requirements belongs on a separate volume.
The managed Codex configuration allows up to 20 concurrent subagents per session. The root agent is accounted for separately.
Node.js and npm are provisioned through the development VM role’s mutable or
OSTree package backend. Open Computer Use 0.3.3 is then installed without npm
lifecycle scripts under the managed user’s ~/.local prefix. Its skill is
then installed for the whole host under /etc/codex/skills from the matching
immutable upstream revision. The deployment configures its stdio MCP server in
the normal Codex config and the isolated OpenRouter and Abliteration homes.
The MCP can inspect and control the logged-in desktop session, so agents must treat its actions as real user input and obtain approval before
externally visible or destructive actions.
OpenRouter is available through its isolated Codex home. Its
configuration reads its API key from the desktop keyring entry selected by
service=openrouter and application=codex; the key is not stored in the
configuration. Repository work uses the repo-owned $codex-migration skill, while
the user-level Codex instructions require isolated migration testing and
intentional host changes to be mirrored into this role. Existing sessions are
not redirected because provider-bound encrypted reasoning history cannot
safely migrate in place.
T3 Code can use OpenRouter as a separate Codex provider by setting its
CODEX_HOME path to /var/home/simeonwarrenbot/.codex-openrouter. That
isolated home defaults to ~deepseek/deepseek-v4-flash-latest and shares no
conversation state with the ChatGPT-backed Codex provider. Start a new thread
when selecting it.
The OpenRouter no-tools home at ~/.codex-openrouter-no-tools mirrors the
OpenRouter provider with every tool surface disabled. It reuses the same
keyring lookup and model, sets web_search = "disabled", turns off the shell,
unified-exec, image, multi-agent, computer-use, browser, app, plugin, and goal
features, and disables the request_user_input tool and the MCP servers.
Codex then advertises no tools at all, so the model can only reply with text.
This matters beyond tidiness: OpenRouter rejects a request that carries any
tools when its routed endpoint supports none, so a single leftover tool fails
the turn.
T3 Code launches the Codex app server with
-c mcp_servers.t3-code.url=..., so its own MCP server would otherwise
reintroduce the MCP resource tools. The no-tools config therefore declares
[mcp_servers.t3-code] with enabled = false, which still wins over that
launch-time override.
Select it in T3 Code with CODEX_HOME path set to
/var/home/simeonwarrenbot/.codex-openrouter-no-tools and start a new thread.
The Abliteration and standard OpenRouter homes keep their tools.
Abliteration uses a separate home with
CODEX_HOME="$HOME/.codex-abliteration" codex, using the endpoint and model from its
Codex integration guide.
It retrieves its API token at runtime with secret-tool, selecting
service=abliteration and application=codex. Save the token from an
interactive terminal in the same user’s desktop keyring:
secret-tool store --label='Abliteration API token for Codex' service abliteration application codex
Enter the token at the hidden prompt. The configuration contains only the
lookup command. Provider response and tool-call validation require a saved
token. Both providers keep their configuration and conversation state outside
the main Codex home; provider profiles in the main home are removed. For
T3 Code, set its CODEX_HOME path to
/var/home/simeonwarrenbot/.codex-abliteration and start a new thread.
T3_MCP_BEARER_TOKEN authenticates the Codex app-server’s loopback MCP
connection to T3 Code at /mcp. Codex excludes it from model-spawned commands
so those subprocesses do not inherit the credential.
Deployment
bazel run //users/simeonwarren/host_bot/ansible
7.1.2.1 -
owned-dns Specification
Purpose
Define Host Bot DNS management through the owner’s tf root,
including canonical declarations, scoped credentials, and offline source checks
before adopting live records.
Requirements
Requirement: Owner-local DNS configuration
The tf root SHALL consume this owner’s canonical dnsconfig.json through
the shared DNS Terraform module, preserving declared record identities and views.
DNS resources SHALL default to disabled until the shared migration adopts them
and SHALL retain enabled ownership after authorized adoption into the owner’s
state. Reconciliation of adopted records with unchanged declarations SHALL
propose no record additions, changes, replacements, or deletions.
Scenario: Inspect the preparatory configuration
- WHEN the checked-in root is evaluated with default inputs before authorized adoption
- THEN it reads this owner’s declaration and disables managed DNS records
- AND the package contains the module and declaration inputs
Scenario: Inspect adopted source defaults
- WHEN the adopted host root is evaluated with its checked-in source defaults
- THEN record ownership is enabled for the owner’s declared records and views
- AND the package retains the canonical declaration and shared module inputs
Scenario: Reconcile existing DNS records
- WHEN the host root plans against its adopted state and unchanged declarations
- THEN it proposes no record additions, changes, replacements, or deletions
- AND records outside this owner’s declarations remain unchanged
Requirement: Scoped DNS execution and offline checks
The DNS wrapper SHALL select src_users_simeonwarren_host_bot through the repository AL flow and keep
secret values in injected variables. DNS injection SHALL select the root’s existing
Terraform stage label. Real DNS credentials and Vault policy grants SHALL be
prerequisites for operational Terraform calls. RouterOS DNS credentials SHALL be isolated
from unrelated RouterOS resources. The package SHALL expose a format test that
does not authenticate to Vault or contact DNS providers.
Scenario: Validate the Terraform source
- WHEN the package format test executes
- THEN it checks the packaged Terraform configuration without live credentials
- AND existing non-DNS authentication and backend paths remain unchanged
Scenario: Prepare an operational Terraform invocation
- WHEN the wrapper selects its Terraform stage labels
- THEN it selects DNS credential injection through the owner AppRole
- AND disabled DNS resources do not imply offline provider configuration
7.1.2.2 -
DNS Terraform
This root packages the owner’s canonical DNS declarations
through the shared DNS module and keeps state in the DNS AppRole’s Vault HTTP
backend. It uses the dedicated dns_al configuration; Ansible retains its
separate al configuration and user_simeonwarren authority.
The root contains DNS resources only. dns_enabled defaults to true after
verified adoption. Keep it enabled to retain records; disabling it would
propose deletion.
The DNS migration procedure owns
credential provisioning, reconciliation, and recovery. The adoption record
contains import and verification evidence. Use the normal explicit
//users/simeonwarren/host_bot/tf:tf wrappers for DNS operations and the
//users/simeonwarren/host_bot/tf:tf_tests.fmt_test target for offline source
validation.
Operational Terraform calls require the DNS AppRole policy grants and credential fields described by the migration procedure. Provider configuration and authentication require real credentials and live access.