Giter VIP home page Giter VIP logo

warframe-drop-data's Introduction

warframe-drop-data

Supported by the Warframe Community Developers Discord

Warframe drop data in an easier to parse format.

NOTE: This data is parsed from Digital Extremes official drop data website, no data mining was involved.

Web UI & URL

screenshot

There is an experimental searchable web ui available at http://drops.warframestat.us

"API Endpoints"

You can access the data via normal HTTP requests, which makes it usable like an API without really being one.

/data/all.json

All data from the website in one single file.

Data structure:

{
  "blueprintLocations": [ { ... } ],
  "cetusBountyRewards": [ { ... } ],
  "enemyBlueprintTables": [ { ... } ],
  "enemyModTables": [ { ... } ],
  "keyRewards": [ { ... } ],
  "missionRewards": { "Earth": { ... } },
  "modLocations": [ { ... } ],
  "relics": [ { ... } ],
  "sortieRewards": [ { ... } ],
  "transientRewards": [ { ... } ],
  "solarisBountyRewards" : [ { ... } ],
  "zarimanRewards": [ { ... } ],
  "syndicates": [ { ... }],
}

/data/info.json

The metadata of the current build. Updates when Digital Extremes' website is updated.

Legend:

  • Hash: An MD5 hash generated from the drop data page.
  • Timestamp: The timestamp at which the build was generated by us.
  • Modified: The timestamp at which the drop data page was last modified by DE.

Data structure:

{
  "hash": "d47a826e5c3a8dc7a37fe6f468f41a57",
  "timestamp": 1524933993968,
  "modified": 1524690737000
}

/data/missionRewards.json

All mission rewards, like what drops where and in which rotation. (Source)

Data structure:

"missionRewards": {
  "Sedna": {
    "Hydron": {
      "gameMode": "Defense",
      "isEvent": false,
      "rewards": {
        "A": [
          {
            "_id": "c0400ac7082c2f3d811e47ca9b7a8ae8",
            "itemName": "Vitality",
            "chance": 11.11,
            "rarity": "Uncommon"
          },
          { ... }
        ],
        "B": [ ... ]
      }
    },
    "Bere": { ... }
  },
  "Earth": { ... }
}

/data/missionRewards/$PLANET_NAME/$PLACE.json

Drop data for a specific location. Example: /data/missionRewards/Eris/Xini.json.

Data structure:

"Hydron": {
  "gameMode": "Defense",
  "isEvent": false,
  "rewards": {
    "A": [
      {
        "_id": "c0400ac7082c2f3d811e47ca9b7a8ae8",
        "itemName": "Vitality",
        "chance": 11.11,
        "rarity": "Uncommon"
      },
      { ... }
    ],
    "B": [ ... ]
  }
}

/data/relics.json

All relics, what they contain, rarity etc. (Source)

Data structure:

"relics": [
  {
    "_id": "4e4d817f8c2d887316c6d8add253403e",
    "tier": "Axi",
    "relicName": "A1",
    "state": "Intact",
    "rewards": [
      {
        "_id": "6733cc5298452209aa29dd72027c7df1",
        "itemName": "Akstiletto Prime Barrel",
        "chance": 11,
        "rarity": "Uncommon"
      },
      { ... }
    ]
  },
  { ... }
]

/data/relics/$TIER/$RELIC_NAME.json

Data for a specific relic. Example: /data/relics/Axi/R1.json.

Data structure:

{
  "_id": "4e4d817f8c2d887316c6d8add253403e",
  "tier": "Axi",
  "relicName": "A1",
  "state": "Intact",
  "rewards": {
    "Intact": [
      {
        "_id": "6733cc5298452209aa29dd72027c7df1",
        "itemName": "Akstiletto Prime Barrel",
        "chance": 11,
        "rarity": "Uncommon"
      },
      { ... }
    ],
    "Exceptional": [ ... ]
  }
}

/data/transientRewards.json

Rewards not tied to a specific location, like mods dropped by Nightmare Mode missions. (Source)

Data structure:

"transientRewards": [
  {
    "_id": "b3c734177040ffb494609a27d87d4841",
    "objectiveName": "Derelict Vault",
    "rewards": [
      {
        "_id": "24a4a903a7846a300d6b04e914e52e1b",
        "itemName": "Anemic Agility",
        "chance": 4.17,
        "rarity": "Rare"
      },
      { ... }
    ]
  },
  { ... }
]

/data/sortieRewards.json

Sortie rewards. (Source)

Data structure:

"sortieRewards": [
  {
    "_id": "b3c734177040ffb494609a27d87d4841",
    "itemName": "4000 Endo",
    "chance": 12.1,
    "rarity": "Uncommon"
  },
  { ... }
]

/data/modLocations.json

Mod drops sorted by mod. (Source)

Data structure:

"modLocations": [
  {
    "_id": "b3c734177040ffb494609a27d87d4841",
    "modName": "Accelerated Deflection",
    "enemies": [
      {
        "_id": "68cfde6d20b38ba62b412b48c440a7a0",
        "enemyName": "Arcane Boiler",
        "enemyModDropChance": 3,
        "chance": 7.37,
        "rarity": "Rare"
      },
      { ... }
    ]
  },
  { ... }
]

/data/enemyModTables.json

Mod drops sorted by enemy. (Source)

Data structure:

"modLocations": [
  {
    "_id": "2757006e018c952e40a6e3cf74048420",
    "enemyName": "002-Er",
    "enemyModDropChance": "10.00",
    "mods": [
      {
        "_id": "74ab77f66f97e146b6cef713a370e105",
        "modName": "Flux Overdrive",
        "chance": 12.5,
        "rarity": "Uncommon"
      },
      { ... }
    ]
  },
  { ... }
]

/data/enemyBlueprintTables.json

Blueprints and part drops sorted by enemy. (Source)

Data structure:

"enemyBlueprintTables": [
  {
    "_id": "6ba71181fe67be210250c59fdf06ecb8",
    "enemyName": "Arid Heavy Gunner",
    "enemyItemDropChance": "1.00",
    "items": [
      {
        "_id": "9568cc883b465bc94c14e0d206506b2d",
        "itemName": "Gorgon Blueprint",
        "chance": 100,
        "rarity": "Common"
      },
      { ... }
    ]
  },
  { ... }
]

/data/blueprintLocations.json

Blueprints and part drops sorted by item. (Source)

Data structure:

"blueprintLocations": [
  {
    "_id": "2d200b684ad2bac2184a5edc3a9655cb",
    "itemName": "Ash Chassis Blueprint",
    "enemies": [
      {
        "_id": "02ca12683663224f017f209954cb876a",
        "enemyName": "Grineer Manic",
        "enemyItemDropChance": 33,
        "chance": 38.72,
        "rarity": "Common"
      },
      { ... }
    ]
  },
  { ... }
]

/data/cetusBountyRewards.json

Drop data for Cetus bounty missions. (Source)

Data structure:

"cetusBountyRewards": [
  {
    "_id": "0b9c958b277561c57f47390f5db201ef",
    "bountyLevel": "Level 10 - 30 Bounty",
    "rewards": {
      "A": [
        {
          "_id": "2d220168d8505314316354e586fe4c7e",
          "stage": "Stage 1",
          "itemName": "100 Endo",
          "chance": 25,
          "rarity": "Uncommon"
        },
        { ... }
      ],
      "B": [ ... ]
    }
  },
  { ... }
]

/data/zarimanRewards.json

Drop data for Zariman bounty missions. (Source)

Data structure:

"zarimanRewards": [
  {
    "_id": "255771097c27769a3a76bfa38c9fba49",
    "bountyLevel": "Level 50 - 55 Zariman Bounty",
      "rewards": {
        { ... }
        "C": [
          {
            "_id": "d5ccc328b76d91df416cc361d2209c1f",
            "itemName": "15,000 Credits",
            "rarity": "Uncommon",
            "chance": 17.39,
            "stage": "Final stage"
          },
        { ... }
      ],
    }
  },
  { ... }
]

/data/syndicates.json

Drop data for syndicate vendors. Generated by data from the Warframe Wikia.

Data structure:

{
  "syndicates": {
    "Steel Meridian": [
      {
        "_id": "d765637f1f1ae09add1b5265f5d29ea1",
        "item": "Steel Meridian Sigil",
        "chance": 100,
        "rarity": "Common",
        "place": "Steel Meridian, Brave",
        "standing": 1000
      },
      { ... }
    ],
    { ... }
  },
}

/data/miscItems.json

Miscellanous enemy item drops. (Source)

Data structure:

"miscItems": [
  {
    "_id": "abce816f002a752c88308d5f6658427c",
    "enemyName": "Akkalak Turret",
    "enemyItemDropChance": "70.00",
    "items": [
      {
        "_id": "a3ab4147ff1f344ae81bc8fd301a4ba5",
        "itemName": "Circuits",
        "chance": 68.02,
        "rarity": "Common"
      },
      { ... }
    ]
  },
  { ... }
]

/data/builds/builds.json

A list of available builds and their timestamps.

Data structure:

[
  {
    "hash": "d47a826e5c3a8dc7a37fe6f468f41a57",
    "timestamp": 1524933993968,
    "modified": 1524690737000
  },
  { ... }
]

/data/builds/{hash}.json

The all.json file of the given hash. Other files, such as missionRewards.json are not available for previous builds.

Data structure:

{
  "blueprintLocations": [ { ... } ],
  "cetusBountyRewards": [ { ... } ],
  "enemyBlueprintTables": [ { ... } ],
  "enemyModTables": [ { ... } ],
  "keyRewards": [ { ... } ],
  "miscItems": [ { ... } ],
  "missionRewards": { "Earth": { ... } },
  "modLocations": [ { ... } ],
  "relics": [ { ... } ],
  "sortieRewards": [ { ... } ],
  "transientRewards": [ { ... } ]
}

For Developers

Dependencies

Usage

You can run the build script with npm run build.

Once built, serve the Web UI with npm run serve:dev.

Syndicate drop data

Syndicate drop data is scraped from the wiki and not from the drops site as the rest of the data.

The syndicate data needs to be scraped from different pages, one for each syndicate which could also contain multiple sections containing the drop data. To make this possible a declarative configuration has been created within lib/syndicates.js where you can define all of this in the following format:

/**
 * @typedef {Object} SyndicateMapperResult
 * @property {_id} _id Unique hash of the item
 * @property {string} item The name of the item
 * @property {number} chance The dropchance of the item
 * @property {string} rarity The rarity of the item
 * @property {string} place The location where the item drops
 */
/**
 * @typedef {function} SyndicateMapper
 * @param {module:cheerio/CheerioAPI} $ cheerio interface
 * @param {string} element Current element
 * @param {string} syndicate Name of the Syndicate
 * @param {string} [section] Section title - potentially empty
 * @returns {SyndicateMapperResult}
 */
/**
 * @typedef {Object} SyndicateSection
 * @property {string} [title] Indicates the name of the specific vendor
 * @property {string} selector jQuery selector used to find the elements you want to map
 * @property {SyndicateMapper} [mapper] Used to map these elements. If not provided, a default mapped is used 
 */
/**
 * @typedef {Object} SyndicateConfig
 * @property {string} name Name of the Syndicate (should match the wiki)
 * @property {string} url The wiki url of the syndicate
 * @property {SyndicateSection[]} sections These will be parsed and mapped into json data
 */

/** @type {Array<SyndicateConfig>} */
const SYNDICATES = [
  {
    name: 'Steel Meridian',
    url: 'https://warframe.fandom.com/wiki/Steel_Meridian',
    sections: [
      { selector: '#mw-customcollapsible-SteelMeridian > div > div' },
    ],
  },
  {
    name: 'Entrati',
    url: 'https://warframe.fandom.com/wiki/Entrati',
    sections: [
      { title: 'Father', selector: '#mw-customcollapsible-Father > div > div' },
      { title: 'Daughter', selector: '#mw-customcollapsible-Daughter > div > div' },
      { title: 'Son', selector: '#mw-customcollapsible-Son > div > div' },
      { title: 'Otak', selector: '.flex-container:eq(3) > div' },
      { title: 'Grandmother', selector: '#mw-customcollapsible-Grandmother #gallery-1 > div', mapper: galleryMapper },
    ],
  },
  { ... }
];

Mappers

A mapper is a function that maps a singular element (found by the selector) to a json object. The mapper receives the following arguments: the cheerio object, the current element, name of the syndicate, section title (can be empty). The return type should at least contain the following information:

/**
 * @typedef {Object} SyndicateMapperResult
 * @property {_id} _id Unique hash of the item
 * @property {string} item The name of the item
 * @property {number} chance The dropchance of the item
 * @property {string} rarity The rarity of the item
 * @property {string} place The location where the item drops
 */

Any additional properties will be added into the final result but won't show up in the slim json file.

Disclaimer

This list represents data and drops from the PC version of the Free-to-play game Warframe. That's right - Warframe is free! Which means our drop system is designed to maintain a balance. Our free players can earn the game's content, and our paying players who support us (and keep the game running) usually get first dibs on the content by using Platinum (which can be traded to free players)! As far as we can tell... we are the first developers to openly post something quite like this. Let's hope it works out for us and we set a trend.

This is automatically generated from our internal data but this data comes with no guarantees -- do not expect it to be comprehensive for how complex the game is. This list will be maintained by an automated process which will be published with Updates (not all Hotfixes). We update often and new game systems may or may not be covered here. This list can be discussed here. Know a free-to-play game that provides official drop rates in a different way? We'd love to know.

License

MIT

warframe-drop-data's People

Contributors

atomicptr avatar ayayem avatar ds-exe avatar kaptard avatar nwessing avatar oohshiny avatar senexis avatar snowyleopard avatar tobitenno avatar tpolito avatar wfcd-bot-boi 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

warframe-drop-data's Issues

Searches require <b> tag when including mission type

Summary (short):
Searching for the mission type (because rotation is after type, and people want to search specific rotations) requires the bold (<b>) tag wrapping the mission type.


If issue, Reproduction:
Steps to reproduce the behavior:

  1. Attempt to search for Ganymede (Disruption), Rotation C
  2. Fail to get results
  3. Search for Ganymede (<b>Disruption</b>), Rotation C
    4 Search succeeds

Mockups, screenshots, evidence:


Additional context
Nothin, just is very odd. We should probably search a minified place that doesn't include those html strings

relic locations

Warframe Drops Site Feature Request


Summary (short):

essentially the same as modLocations just for relics.


dunno what else to write about it, seems pretty clear :P

Should we change the format?

DE changed their structure recently which changed certain keys, for instance modLocations is now modByDrop and enemyModTable is modByAvatar. They also removed misc items and replaced it with resources as described in #43.

Question is, should we keep the data as is (using old terminology) or change it, which would probably break everything that is connected to this data set.

@TobiTenno

incomplete information (parsing error)

Warframe Drops Site Issue


Summary (short):
Bullet Dance only appears once, but it really drop in 3 different places:

Void/Stribog (Caches), Rotation C Rare 3.67%
Void/Marduk (Caches), Rotation C Rare 4.42%
Plains of Eidolon Incursions, Rotation B Rare 1.01%

It seems that when you add the data to the array in missionRewards, it is used as the "Void/Marduk" key, but there are two types, cache and sabotage, and only one is stored, the same thing happens with Stribog.

I do not know if this happens in other cases

If issue, Reproduction:
Steps to reproduce the behavior:

  1. check json

Search drop location as well

Would be kinda useful if you want to know what drops form a certain "something" :P

Pulling from my head, using a bit rusty js knowledge (not really want to go through the whole fork/PR mess):
In search:

   fill(window._data.filter(entry => entry.key.contains(searchValue)))

At the end of formatData:

   let searchData = [];

   for(let newData_ of newData) {
      newData_.key = `$(newData_.place): $(newData_.item)`;
      searchData.push(newData_);
   }
   return searchData;

Some drop data missing for RJ

Data incomplete. Some RJ drops not shown which are present in DE's data.


Search for 'carmine' in site.
Arc Silver/Erato/Lu-Yan shows for Veil nebula.
Ctrl-F 'carmine' on DE's pages.
Calabash/Numina/Arc Silver/Erato/Lu-Yan shows for Veil nebula.


image
image

Generate a single drop item array at generate time.

Warframe Drops Site Feature Request


Summary (short):
Generate a single array with all of the items.


Detailed requirements of the feature

As a developer, it would hasten my workflow to not have to combine all drop items into a single array.
As a user, it would hasten my pageload to never have to generate, only fetch, a json object to use.
As a developer, it would ease my adoption of new data in the site if all of it was available from an always updated single-source, akin to All.json, but in a single array instead of in separate objects.


Mockups:

This should be as simple as adding a new file, let's call it all.slim.json, and exporting the output from the existing formatData function in index.html to this file when called with the existing All.json generated object.


Additional context
Instead of generating a new _wfdata object when there's a new hash, just always use a newly generated all.slim.json each time, which would be a single processed version of what is normally created when there's a new hash on the user's client.

Request all drop locations for a specific item (API)

Warframe Drops API Feature Request


Summary (short):
Be able to get data about drop location for a specific item


Detailed requirements of the feature

As a user, I'd should be able to search for a location.
I should be able to request data/locations/{itemName}.json to find all the enemies/missions/events this item/mod/blueprint drops on.


Mockups:

It should look like that:
mockup


Additional context
I was making a little .NET wrapper for this data, and it would be much easier for me if I could just lookup like that.

Question: How to know which items are vaulted?

Hey there,

thanks for the great work you put in this project. This makes life a lot easier for a lot of data analysts :)

I was looking at your API's and data files and somehow was not able to find out if you distinguish between an item which is vaulted or not. E.g. the Axi S4 relict is vaulted right now, but I can't seem to find the information in your data.

What am I missing?

Drop website displays wrong drop chance

The website displays the wrong drop chance for "Intact Sentient Core" as you can see here:

image

It says "12.xx%" but inside of the all.json file it says "4x%":

image

This might affect more items.

Add "Arbitrations"

They're already on the list:

image

Kinda curious, I thought they didn't drop the update yet ๐Ÿค”

Add bounty rewards for Deimos/Necralisk

The drop table seems to now include the current bounties. I could implement the logic for the parsing (it's the same like the ones for cetus and fortuna) but I'm not sure what the naming convention of the current modules is.

Deimos Bounty Rewards

Relic Parsing Fails for relics numbered above 9

Now that the Neo S10 Relic has been released, the regular expression used to parse relics, in utils.js:parseRelic() is no longer correct.

The regex being used is: /([A-z]*)\s([A-Z][0-9])\sRelic\s\(([A-z]*)\)/i
It can be corrected using: /([A-z]*)\s([A-Z][0-9]+)\sRelic\s\(([A-z]*)\)/i

Add Sigils

Warframe Drops Site Feature Request


Summary (short):
Right now we're missing the sigils section, adding it would be great.


Detailed requirements of the feature

As a developer, being able to provide data on where to get specific sigils would be allow users to have a fuller idea of where they come from.


Mockups:
โŒ


Additional context
Nah. thanks to semlar for pointing it out.

Out of Date Documentation

Warframe Drops API Issue


Summary (short):
/data/all.json endpoint documentation is out of date.

  • miscItems is documented but not returned.
  • solarisBountyRewards is not documented but returned.

Just noticed these for now but there are probably more out of date entries, will update if I discover any.


If issue, Reproduction:
Steps to reproduce the behavior:

  1. Hit the endpoint

Search from drop location not working?

Warframe Drops Site Issue


Summary (short):
For example, searching for "assassination" "general sargas ruk" "mars" didn't show results for me. I noticed the functionality was added on April 21st according to issue #5 so something might have messed it up from then?


If issue, Reproduction:
Steps to reproduce the behavior:
Search for location keywords in the search box.


Mockups, screenshots, evidence:
assassination:
assassination
general sargas ruk
generalsargasruk
mars
mars


Let us sort by the different columns.

As of now it seems to be locked to sorting by # chance. It would be a lot more convenient if we could sort the different columns up/down.

Thanks!

Add additional search methods: exact, regex

Warframe Drops Site Feature Request


Summary (short):
Provide the option to search by exact string

Provide the option to search using regex


Detailed requirements of the feature

As a user, I should be able to indicate that I wish to search for a drop using an exact search string.
As a user, those search results should match the search string entirely.

As a user, I should be able to search for a drop using a regex.
As a user, those search results should match the regex.


Mockups:

Paint, photoshop mockups, sketchup, whatever you're envisioning.

A tickbox to indicate whether or not "Exact match" is desired
If this tickbox is selected, then searching for "Bite" should match "Bite" only, and not Frostbite. Searching for "Rush" should match "Rush" only, and not "Blood Rush", or "Gladiator Rush"

A tickbox to indicate whether or not "regex match" is desired
If this tickbox is selected, then searching for "^bite$" should match "Bite" only, and not Frostbite. Similarly, searching for "^(gladiator )?rush$" would match "Rush", "Gladiator Rush" but not "Blood Rush"


Additional context
Add any other context about the request here.

Move build process to Travis

Right now the script is running once per hour on my private server, but I think this should run on a Travis CI cron job instead, mostly because it's easier to determine why and when builds fail (Also the script can then be run on command, which would be useful when a new patch drops).

We'd probably have to move the entire page to a new branch and make it build into gh-pages.

Neo Z4 Relic contains drop data for all Requiem Relics

Warframe Drops Site Issue


Drop data for the Neo Z4 Relic contains all the drops for the new Requiem Relics introduced with the Old Blood update.


If issue, Reproduction:
Steps to reproduce the behavior:
n/a


Mockups, screenshots, evidence:

Search for Kuva on the site, or look in the raw drop data for Neo Z4.


Additional context
n/a

Atlas parts do not show up in web search

Warframe Drops Site Issue


Summary (short):
Searching for atlas parts do not show the appropriate data. results list is empty. Parts do show up in
data/all.json


If issue, Reproduction:
Steps to reproduce the behavior:

  1. Go to https://drops.warframestat.us/
  2. Input Atlas (or atlas)
  3. See no results found

Mockups, screenshots, evidence:
image

Dropdata outdated

Warframe Drops Site Issue


Summary (short):
Database was last parsed on June 24th

db

Cheers

Publish to NPM?

Warframe Drops Site Feature Request


Summary (short):
Publish the package to NPM?


Detailed requirements of the feature

As a developer, I'd should be able to install the package from npm.


Mockups:


Additional context
This project has awesome efforts, and I've got couple ideas that will depend on it, but since we always seek automation, so having this repo as NPM package will be awesome, I could do that, but I believe that the same owners of this repo should own it.

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.