Giter Club home page Giter Club logo

pokebot-gen3's People

Contributors

30-something-programmer avatar 40cakes avatar dlsantana avatar dukmos avatar flitpix avatar hanzi avatar jaytheidiot avatar m-atthieu avatar mechandtech avatar melanx avatar mowlawner avatar mythicwebsite avatar nopothegamer avatar pekempy avatar renatatostada avatar spilare avatar terasol avatar thisisatest1900 avatar u2ezneko avatar unixtreme avatar vitorsilverio avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

pokebot-gen3's Issues

Gift Pokémon modes

Gift Pokémon Modes

Create bot modes for unique static/gift Pokémon:
List of in-game event Pokémon (Emerald)

Wynaut

The old woman by the sand baths in Lavaridge Town will give the player a Wynaut Egg.

Castform

The staff of the Weather Institute will give the player a Castform for saving the facility from Team Aqua.

Fossil Pokémon

The player may choose between the Root and Claw Fossils in the Mirage Tower, while the other fossil will be available to them in the Desert Underpass after entering the Hall of Fame. The fossils can be revived into Lileep and Anorith at the Devon Corporation headquarters in Rustboro City.

Beldum

After the player has entered the Hall of Fame, Steven will leave a Beldum as a gift for them in his cottage in Mossdeep City.

Sudowoodo

Sudowoodo is located in the southeast section of the Battle Frontier. Much like in Generation II games, NPCs will talk about it as a tree. However, when the player uses the Wailmer Pail on it, it will spring to life.

Functionality

Required

  • Wynaut
  • Castform
  • Fossil Pokémon
  • Beldum
  • Sudowoodo

Optional

  • Any cheats/memhacks to make the modes faster (toggleable)

Notes

This issue has been raised to track the work/progress for this new feature/functionality.

Please keep your PR in draft until it is ready to be reviewed and tested. Referencing this issue in your PR description will allow for collaboration among many, and also just lets us know you're working on it, potentially saving someone else from wasting their time working on the same thing separately.

Don't be afraid to use this issue or visit the Discord channel #development-chat🛠 to ask for help or discuss ideas related to this issue.

Lati@s mode (Eon Duo)

Lati@s Mode

Latias & Latios in Emerald, Ruby, and Sapphire.

Once the player defeats the Elite Four and becomes Champion, they will return home. Upon going downstairs a cutscene begins and the player can choose either Red for Latias or Blue for Latios. At this point, the respective Pokémon becomes a Roaming Pokémon.

These cannot be soft-reset in the standard way, as the PID of the roamer is set during the TV Cutscene upon choosing RED or BLUE, immediately after the TV cutscene ends

After the cutscene, if the player has Lati@s registered as SEEN in their Pokédex, they can check the Area the roamer is currently in. Travelling to a route will make it move, so some pathing manipulation will be needed. If it is not shiny, a reset will then be needed to return to the TV broadcast.

Note - Roamers will attempt to flee instantly in battle. Arena trap doesn't work due to flying. Sleep also doesn't work. It may need a lead pokemon to outspeed with Mean Look

Prerequisites

Path finding/navigation rework

Functionality

Required

  • Latios (roaming)
  • Latias (roaming)
  • Latios (Southern Isle, static, run and reset)
  • Latias (Souther Isle, static, run and reset)
  • Cheat mode for roaming to SR at house until the roamer has a shiny PID, and then begin the tracking/hunting

Notes

Please keep your PR in draft until it is ready to be reviewed and tested. Referencing this issue in your PR description will allow for collaboration among many, and also just lets us know you're working on it, potentially saving someone else from wasting their time working on the same thing separately.

Don't be afraid to use this issue or visit the Discord channel #development-chat🛠 to ask for help or discuss ideas related to this issue.

Feebas mode

Feebas Mode

Feebas - The fishing spots Feebas is found in are randomly generated, in Ruby, Sapphire, and Emerald they randomly change whenever the trend in Dewford Town changes.

Create a mode to automatically find a tile with Feebas and continue to fish on the spot once found.

A threshold for users to define how many times the bot should search each tile for with most efficient option set by default, at 50% encounter rate on the correct tile, chance of finding Feebas if correct tile:

  • 1 encounter - 50%
  • 2 encounters - 75%
  • 3 encounters - 87.5%
  • 4 encounters - 93.75%
  • 5 encounters - 96.875% etc.

Functionality

Required

  • Automatically search and find Feebas tile, continue to fish on the tile once found
  • Configurable search threshold
  • If no Feebas encounter in last x (configurable?) encounters, the tile has moved, so start searching for a fresh tile

Optional

  • Cheat options to instantly find a tile

Notes

This issue has been raised to track the work/progress for this new feature/functionality.

Please keep your PR in draft until it is ready to be reviewed and tested. Referencing this issue in your PR description will allow for collaboration among many, and also just lets us know you're working on it, potentially saving someone else from wasting their time working on the same thing separately.

Don't be afraid to use this issue or visit the Discord channel #development-chat🛠 to ask for help or discuss ideas related to this issue.

Mode - Sky Pillar Solver

A mode is pretty much required to be able to get through Sky Pillar.

Ideally, it should be able to navigate from Sky Pillar bottom entrance to the top where Rayquaza is.

Minimum Requirements

  • Should be able to bypass the difficult cycling parts which require turns at high speeds

Ideal requirements

  • Navigate Sky Pillar from entrance to Rayquaza without any user input

image

Automatically installing packages can have catastrophic effects in user's python environments.

After recent changes, pokebot automatically installs requirements on run.
This is problematic for users that do not know this is going to happen, or that do not know how to use virtual environments.
People often clone repos off the internet and let them pollute their python installs causing conflicts with each other.

This is highly discouraged, especially on Linux systems where many system utilities rely on the base Python install even for some desktop environment features. But it will also conflict with anyone using the myriad of AI "tools" online that also do this by default, since pokebot installs numpy/pandas versions that will definitely conflict with a lot of them.

Proposed Solutions from least to most preferred:

  • On first run, create a venv for pokebot, or activate an existing one, and ensure pokebot is always running in a venv.
  • Do not install any packages, validate packages are present or not and provide instructions to install them with a disclaimer. Perhaps offer installing them with a confirmation prompt.
  • Move to the requirements.txt industry standard, in fact this should probably be done regardless of whatever is decided. Specific OS requirements can be handled by having two additional files like requirements-win.txt and requirements-linux.txt
  • Create a windows-only executable build for end user releases with all requirements pre-installed, users just double click and go, these "prod" releases can use AppData to store profile information.

New profile pop up window too small

Sorry in advance is this is stupid, I'm completely illiterate with this kind of stuff.

When starting pokebot.py and being promted to create a new profile, the pop up window that shows up is too small and I'm not able to proceed. I have no way to make it increase in size or maximize it.

image

Implement Auto-Catch

Implement the automatic catching of Shiny Pokemon when encountered, ideally using status moves to improve chances, and potentially damaging the opponent too if calculations can be done based on stats known to guarantee it will not KO

Features

Required

  • Auto-catch using the highest available Poké ball (excluding Master)

Optional

  • Use Spore / other status moves to improve catch rates
  • Potentially use damaging moves if you can calculate it will NOT ever have a chance of KO to reduce health to improve catching rate
  • Allow user defined priority list of Poké balls to use

Dark mode UI

Dark Mode UI

Obviously very low priority, but would be nice to add a dark mode theme for the UI (tkinter), such as Sun-Valley-ttk-theme.

Functionality

Required

  • Dark mode by default

Optional

  • Light/dark mode toggle
  • Multiple theme options

Notes

This issue has been raised to track the work/progress for this new feature/functionality.

Please keep your PR in draft until it is ready to be reviewed and tested. Referencing this issue in your PR description will allow for collaboration among many, and also just lets us know you're working on it, potentially saving someone else from wasting their time working on the same thing separately.

Don't be afraid to use this issue or visit the Discord channel #development-chat🛠 to ask for help or discuss ideas related to this issue.

Auto battling and pickup

Auto Battling and Pickup

PR #4 / #63 are currently open for this, just raising this while a refactor effort is required + track discussions/ideas on the topic of auto-battling. Any help to refactor this PR to work with the new main/generator mode loop would be highly appreciated.

This PR also contains a lot of important battle menu, start and party menu navigation which will be extremely useful for any other features that require menuing.

Functionality

  • Auto battling methods (use strongest moves available)
  • Learn new moves (learn best, stop bot, cancel)
  • Handle evolutions (prevent/allow)
  • Replace lead battler
  • Pickup item farming
  • Start menu navigation
  • Party menu navigation
  • Battle menu navigation

Notes

This issue has been raised to track the work/progress for this new feature/functionality.

Please keep your PR in draft until it is ready to be reviewed and tested. Referencing this issue in your PR description will allow for collaboration among many, and also just lets us know you're working on it, potentially saving someone else from wasting their time working on the same thing separately.

Don't be afraid to use this issue or visit the Discord channel #development-chat🛠 to ask for help or discuss ideas related to this issue.

new_move: learn_best

I think this don't work well. For now evolved 2 mons and when learn new move the bot goes manual despite having the learn_best instead of stop. So far, both times I had to learn a new move, that has happened to me. As I see new moves I will say if it continues to go manual or if it replaces some with the new one.

Edit: From what I've been able to observe, it only happens when it learns a move by evolving. If you try to learn by leveling up, it does replace an old one.

Dump shinies/party/PC to .pk3 files

Dump shinies/party/PC to .pk3 files

Add an option to dump shiny encounters or custom catch filtered Pokémon to raw byte .pk3 files to be imported into PKHeX or shared in #pkhexchange💱.

Some users have requested being able to save state on each shiny and just continue running the bot while auto-catch is still in the works, I think this feature is probably a lot better to use while utilising the catch block list + allows for dumping/backing up party and PC Pokémon.

PKHeX .pk3 naming convention:
<dex_num> <shiny ★> - <mon_name> - <pid>.pk3 (0273 ★ - SEEDOT - C88CF14B19C6.pk3)

Functionality

Required

  • Dump shiny encounters
  • Dump custom catch filtered Pokémon
  • Follow the same naming convention as PKHeX

Notes

This issue has been raised to track the work/progress for this new feature/functionality.

Please keep your PR in draft until it is ready to be reviewed and tested. Referencing this issue in your PR description will allow for collaboration among many, and also just lets us know you're working on it, potentially saving someone else from wasting their time working on the same thing separately.

Don't be afraid to use this issue or visit the Discord channel #development-chat🛠 to ask for help or discuss ideas related to this issue.

Deoxys Formes not exporting

In Gen 3 Pokemon games, Deoxys will change forme once caught on birth island, depending on the game - Attack Forme [FireRed]/Defense Forme [LeafGreen]/Speed Forme [Emerald].

When the bot exports a found shiny Deoxys, it doesn't seem to take this game variance into account, and instead always seems to just export Deoxys of the same forme despite the game it was found on.

This can be gotten around by catching the Deoxys, exporting that out, then resetting the event flags, redoing the stone bit and going again, but it would be smashing if it was at all possible for the bot to take it into account when exporting initially :)

Sweet Scent mode

Sweet Scent Mode

Sweet Scent causes wild Pokémon to appear when used as a field move, provided the player is standing in an area where wild Pokémon would normally appear. Sweet Scent will cause a wild encounter even if Repel is in effect.

Sweet Scent is probably slower than spinning due to menuing + animation, but this mode will be useful if RNG manipulation is ever added to the bot.

Prerequisites

Start + party menuing (WIP in #4 / #63 )

Functionality

Required

  • Start menu > Party > Find Sweet Scent Pokémon > Use Sweet Scent > Repeat

Notes

This issue has been raised to track the work/progress for this new feature/functionality.

Please keep your PR in draft until it is ready to be reviewed and tested. Referencing this issue in your PR description will allow for collaboration among many, and also just lets us know you're working on it, potentially saving someone else from wasting their time working on the same thing separately.

Don't be afraid to use this issue or visit the Discord channel #development-chat🛠 to ask for help or discuss ideas related to this issue.

Lugia and Ho-Oh mode

Lugia and Ho-Oh Mode

Lugia and Ho-Oh - In Pokémon FireRed, LeafGreen, and Emerald, if the player has a MysticTicket, they can take a ferry to Navel Rock. Here, the player can catch Lugia in its depths, and Ho-Oh at its peak.

These legendaries can simply be run from and they will respawn when the map is reloaded, this would be desirable over soft resets due to scuffed RNG in gen 3 games.

These should be exempt from auto-catch to allow players to weaken and catch manually.

Prerequisites

Path finding/navigation rework

Functionality

Required

  • Lugia
  • Ho-Oh

Notes

This issue has been raised to track the work/progress for this new feature/functionality.

Please keep your PR in draft until it is ready to be reviewed and tested. Referencing this issue in your PR description will allow for collaboration among many, and also just lets us know you're working on it, potentially saving someone else from wasting their time working on the same thing separately.

Don't be afraid to use this issue or visit the Discord channel #development-chat🛠 to ask for help or discuss ideas related to this issue.

Regis in Emerald

You can just run from them and enter to encounter, it will be much better than soft reseting

Fix Pickup mode for Ruby / Sapphire

Pickup is working on Emerald, FR, and LG, but is broken on R/S according to user reports in the discord. Will need looking into

Tasks

  • Fix and test pickup in Ruby
  • Fix and test pickup in Sapphire
  • Ensure the fix still works in Emerald

Super-ancient Legendary Pokémon mode

Super-Ancient Legendary Pokémon Mode

Super-ancient Pokémon:

These legendaries can simply be run from and they will respawn when the map is reloaded, this would be desirable over soft resets due to scuffed RNG in gen 3 games.

These should be exempt from auto-catch to allow players to weaken and catch manually.

Prerequisites

Path finding/navigation rework

Functionality

Required

  • Groudon
  • Kyogre
  • Rayquaza

Notes

This issue has been raised to track the work/progress for this new feature/functionality.

Please keep your PR in draft until it is ready to be reviewed and tested. Referencing this issue in your PR description will allow for collaboration among many, and also just lets us know you're working on it, potentially saving someone else from wasting their time working on the same thing separately.

Don't be afraid to use this issue or visit the Discord channel #development-chat🛠 to ask for help or discuss ideas related to this issue.

Mew Mode

Mew Mode

Mew - Found on Faraway Island

Create a mode to automatically follow a dedicated path and encounter Mew. If not shiny, leave and re-enter.
Best candidate is to add to existing Static Run Away with custom path

Functionality

Required

  • Automatically path to Mew and encounter
  • Leave map if not shiny and re-enter

Notes

This issue has been raised to track the work/progress for this new feature/functionality.

Please keep your PR in draft until it is ready to be reviewed and tested. Referencing this issue in your PR description will allow for collaboration among many, and also just lets us know you're working on it, potentially saving someone else from wasting their time working on the same thing separately.

Don't be afraid to use this issue or visit the Discord channel #development-chat🛠 to ask for help or discuss ideas related to this issue.

Loading save state freezes bot

See Discord for more information

From Johnnie:

currently loading a savestate new or old will freeze the bot , you can make new ones just cant load them , but when the game crashes it still makes the profile ss1 state so reloading the bot will load you from when you loaded the savestate so there is a work around you just need to reload the bot after loading a savestate

Fishing mode broken

Some weird behaviour with Fishing Mode where the Registered Item is becoming Master Ball or None upon battle start. This is when fishing in Safari Zone. When fishing outside, it's also doing the same thing.

This means you get prompted to pick a rod every time a battle starts.

I also noticed the items returned from the bag don't always include all 3 rods even when all 3 exists.

Definitely some weird behaviour with the fishing mode due to either get_player() / get_item_bag().quantity_of()

Peek_2024-02-12_20-03.mp4

image

Starters mode has a large delay when selecting the starter

I ran the bot for about 4500 encounters but the time the bot took to select the starter has increased reset by reset, seemingly a frame per reset. This is very noticable at 1x speeds but after some time it also is noticable even at unbound speeds.

2023-10-24.08-22-01.mp4

Config rework

Config Rework

Config is currently handled fairly primitively, as a dict that is imported wherever needed, should be converted to class/object. Also happy to discuss potentially better schema validation methods, but the current ones seem to work okay.

All files are loaded once at launch (except for catch_block.yml which is reloaded on every shiny encounter) and never again, which means users need to restart the bot for config changes to take effect - potentially look at polling files on an interval for changes with os.stat(filename).st_mtime?

config["general"]["bot_mode"] -> config.general.bot_mode

Allowing config to be overridden programatically or via CLI args for the bot session should enable easier automated bot tests (this should not overwrite the .yml config files).

python .\pokebot.py --config.general.bot_mode="spin"

Functionality

Required

  • Convert config dict to class/object
  • Override config with CLI args

Optional

  • Reload config on file change without requiring a bot restart
  • Config editor in the GUI

Notes

This issue has been raised to track the work/progress for this new feature/functionality.

Please keep your PR in draft until it is ready to be reviewed and tested. Referencing this issue in your PR description will allow for collaboration among many, and also just lets us know you're working on it, potentially saving someone else from wasting their time working on the same thing separately.

Don't be afraid to use this issue or visit the Discord channel #development-chat🛠 to ask for help or discuss ideas related to this issue.

Add hotkey to stepping mode

Just quickly jotting down this idea before crashing out for the night 😴

  • Add a hotkey, Space key (?) to step frames instead of requiring to left click this step-arrow
  • Run at 10-15fps (slow-mo) if key is held down to get to the desired frame a bit faster instead of spamming Space?

image

Starters Mode - GUI for Johto & Kanto starters

On the Wiki it states to pick your starter from the GUI Selection Menu - This is not implemented for Johto starters or Kanto starters.

See https://github.com/40Cakes/pokebot-gen3/blob/main/modules/modes/starters.py

For consistency with Hoenn starters, a GUI should be implemented for each Johto/Kanto starters, along with the random option, and walking to ensure the player is in front of the relevant Pokeball.

Features

  • GUI For Kanto Starters (FRLG)
  • GUI for Johto Starters (RSE)
  • Unown option for both of the above

FRLG Roamer Mode - raise BotModeError

The mode should raise BotModeError in cases:

  • Sapphire has already been handed in to Celio
    • if Roamer (data in Misc tab of debug mode) is not empty
  • No Sapphire in bag & Sapphire not handed in to Celio

Currently if either of these are met it just changes to manual without a context message

Day care mode

Day Care Mode

The player can leave their Pokémon at Pokémon Day Care, where they gain experience over time. At Pokémon Day Care centers that can raise two Pokémon at once, if the player leaves a compatible pair of Pokémon, they will produce a Pokémon Egg in a process known as Pokémon breeding.

Functionality

Required

  • Check parent Pokémon compatibility - stop if incompatible
  • Warn if the user doesn't have flame body or any egg boosting abilities
  • Check if egg is ready to be received, grab as soon as possible
  • Automatically use a mach bike if registered, to accumulate steps as fast as possible
  • Enter the Day Care and release any hatched eggs at the PC (deposit shinies/custom catch filter Pokémon)
  • Use the most efficient method of hatching/releasing - I think it's more efficient to release at the PC as they hatch instead of batch releasing

Optional

  • Cheat mode to check egg PID/shininess before hatching
  • Fast cheat mode to soft reset for eggs

Potentially Helpful Information/Data

class DaycareTab(DebugTab):
daycare.py

Notes

This issue has been raised to track the work/progress for this new feature/functionality.

Please keep your PR in draft until it is ready to be reviewed and tested. Referencing this issue in your PR description will allow for collaboration among many, and also just lets us know you're working on it, potentially saving someone else from wasting their time working on the same thing separately.

Don't be afraid to use this issue or visit the Discord channel #development-chat🛠 to ask for help or discuss ideas related to this issue.

Kecleon Self Destruct method

Kecleon Mode

There are eight set encounters with Kecleon accessible via the Devon Scope throughout Route 119 and Route 120. See self-KO method .

Create a mode that will self destruct on Kecleon to fail encounter without the static Kecleon moving
Preview video of the mode: https://youtu.be/lRCmVqgYLqM?t=136
This is faster than Soft Resetting, and running away would cause the static Kecleon to disappear.
As it's a 1% encounter usually, having this method makes the hunt significantly quicker.

Functionality

Required

  • Leave pokecenter and path back to the static Kecleon shown in the video above
  • Enter battle with Kecleon, self destruct and white out

Optional

  • Allow the bot to detect based on flags which static Kecleon are still remaining and path to the closest one to the poke center

Notes

This issue has been raised to track the work/progress for this new feature/functionality.

Please keep your PR in draft until it is ready to be reviewed and tested. Referencing this issue in your PR description will allow for collaboration among many, and also just lets us know you're working on it, potentially saving someone else from wasting their time working on the same thing separately.

Don't be afraid to use this issue or visit the Discord channel #development-chat🛠 to ask for help or discuss ideas related to this issue.

Lati@s bot gets stuck pathing

ripname brought to my attention that the lati@s bot was getting stuck in the tree , I tested it and confirmed stuck in the same spot

py_1YJzoFTnlN.mp4

Rock Smash mode

Rock Smash Mode

Rock Smash can be used to break breakable rocks to clear a path. Occasionally, breaking a rock will cause a wild Pokémon to be encountered.

https://bulbapedia.bulbagarden.net/wiki/Breakable_rock#Generation_III

image

Prerequisites

  • Start + party menuing (WIP in #4 / #63 )
  • Map navigation/path finding work

Functionality

Required

  • Detect which map trainer is on, navigate to and face smashable rocks
  • Start menu > Party > Find Rock Smash Pokémon > Use Rock Smash > Repeat
  • Leave map to respawn smashed rocks

Optional

  • Option to soft reset
  • Cheat mode if soft resetting

Notes

This issue has been raised to track the work/progress for this new feature/functionality.

Please keep your PR in draft until it is ready to be reviewed and tested. Referencing this issue in your PR description will allow for collaboration among many, and also just lets us know you're working on it, potentially saving someone else from wasting their time working on the same thing separately.

Don't be afraid to use this issue or visit the Discord channel #development-chat🛠 to ask for help or discuss ideas related to this issue.

bot is logging other trainers pokemon and making pkm files

im not sure if this is intended , but I dont think it would be , when in manual and you encounter a trainer the pokemon has 0's in all stats and that is logged then the custom catch filter is called and a pk3 file and a save state is made as well I already killed the 1st mon it was a tentacool and you can see the save state was made as well as the pk3
image

Battle - Switching Pokemon error in Ruby

when the bot goes to switch pokemon in ruby (all I testes so far ) the bot goes to manual and does not switch the pokemon , all mons are high levels battle.yml is set up to rotate and yml is in my profile
image

Pickup

How do I make the bot to farm items with pickup?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.