rarity-extended / rarityextended Goto Github PK
View Code? Open in Web Editor NEWAn On-Chain Adventure
Home Page: https://rarityextended.com/
License: GNU General Public License v3.0
An On-Chain Adventure
Home Page: https://rarityextended.com/
License: GNU General Public License v3.0
Allow NFTs to transfer Rat skins
call this "Trade with Party"
They will need to input their other character ID somehow
If my account already has a summoner, then I create another summoner, it triggers an error: execution reverted: ERC721: approved query for nonexistent token
.
Steps to reproduce the behavior: create a new summoner from the tavern.
Understanding which attributes to use.
Add a ? beside ATTRIBUTES with a popup that give the text descriptions found on this GSheet.
https://docs.google.com/document/d/1rMRn9xvO5GSawv3sdFyO7JMv0i0d0Ra1D6Cf7zTAepQ/edit?usp=sharing
Also, once a character starts to add a number to assigning attributes (as in image below) we can change the color of ones that this class should focus on. Also see the above do for color code.
We do not have any feedback on the UI after some blockchain action (except for the tavern)
I would like to put app-wide loader (toast) on the app to notify user's about the update
NA
Add some reorder in the readme to test autoclose
A clear and concise description of what the bug is.
Steps to reproduce the behavior:
Cannot harvest soft wood.
Try to harvest soft wood.
A clear and concise description of what the bug is.
If you refresh the home page https://rarityextended.com/ several times, you'll notice it does not show the existing summoner, instead, the page shows the UI for creating a summoner.
This is due to the api requests sent to the ftmscan.com did not include a valid API key.
This caused the ftmscan to return an error message instead of the real data:
And the UI logic updateRarities
always assumed the data is there.
Steps to reproduce the behavior: Refresh https://rarityextended.com/ a few times quickly.
Please register an account on ftmscan to get an API key and embed the API key when deploying the web app.
wallet connection does not work and has not been functioning for weeks.
Connect to metamask
Every time i connect my wallet I get this error now.
inpage.js:1 Uncaught (in promise) TypeError: Cannot create property 'jsonrpc' on string 'eth_accounts'
at l._rpcRequest (inpage.js:1)
at l.sendAsync (inpage.js:1)
at _app-104b918b42085d03539a.js:1
at l (main-6d848910cff452bf7614.js:1)
at Generator._invoke (main-6d848910cff452bf7614.js:1)
at Generator.next (main-6d848910cff452bf7614.js:1)
at r (_app-104b918b42085d03539a.js:1)
at s (_app-104b918b42085d03539a.js:1)
at _app-104b918b42085d03539a.js:1
at new Promise (<anonymous>)
I've checked the zap contract, and you can zap in 0 FTM. We shouldn't allow that
Right now we are using preliminary characters. We need to adapt the current ones using this spec: https://hackmd.io/Fc6J7u65QPyhfm4XW9x4Ig?view
Text for claiming gold is: WOULD YOU LIKE TO CLAIM YOUR 1000 GOLDS ?
Change it to this: WOULD YOU LIKE TO CLAIM YOUR GOLD (1000 COINS)?
Because of the lack of ressources, the items images were using a 8 bit version when the standard one was not available. Now that more standard are available, we should use them.
GENERIC ARMORS
GAUNTLET
and GLOVES
BOOTS
(the Forest)List of item is available here: https://rarityextended.com/codex/items
Contact me to get the ressources
This is already the light mode
Once clicked it will sitch to dark and the message is correct
Open https://rarityextended.com/ on private mode.
Users should be able to claim gold everyday. We should add this option and display the claimableBalance
We should add this in the tavern, for user to be able to claim that
Add some news to tavern.
I also think the tavern should be the landing page
THE SKILLBOOKS WENT OUT!
OUR SAGE, ANDRE, HAS SENT OUT EVERYONES SKILLBOOKS. YOU WILL FIND THEM IN YOUR INVENTORY. OPEN THEM UP, STUDY YOUR ATTRIBUTES. MAKE SOME CHOICES. DO YOU WANT TO BE WELL-ROUNDED? PUT POINTS IN SKILLS THAT YOU HAVE WEAK ATTRIBUTES IN. WANT TO BECOME A SUPER FOCUSED HERO. PUT POINTS IN SKILLS THAT YOU HAVE STRONG ATTRIBUTES IN. EACH CLASS SKILL LEVEL COSTS 1 POINT. EACH CROSS CLASS SKILL LEVEL COSTS 2 POINT. CAREFUL! THEY ARE IMMUTABLE
JANET THE GUILD MASTER OPENS SHOP!
JANET HAS OPENED UP A GUILD HOUSE. THIS IS A GREAT PLACE TO COMMAND YOUR HEROES TO GO ON ADVENTURES AND TO COLLECT YOUR GOLD PAYMENTS.
Add any other context or screenshots about the feature request here.
OH YOU HEARD ABOUT THE FOREST ? THIS MAN OVER THERE HAS SOME INFO ABOUT A TREASURE OR SOMETHING LIKE THAT. YOU SHOULD TALK TO HIM.
Change to
OH HAVE YOU HEARD ABOUT THE FOREST ? THE AUSTRIAN STAYING IN FACU"S TAVERN HAS SOME INFO ABOUT A TREASURE OR SOMETHING LIKE THAT. YOU SHOULD TALK TO HIM. WOULD YOU LIKE TO HEAD TO THE FOREST?
Change to
YES. THE BIG UGLY RAT. FACU THE TAVERN KEEPER NEEDS SOME HELP WITH THIS. REPULSIVE STUFF. IF YOU CAN DODGE AND HIT HARD, YOU SHOULD GO.
When a new player connects, and has no adventurers, it offers nothing to him/her
Here are a couple of the trans ids:
0xbd8f5e852419f7b8a53b47c02600c723b5dedc53d9b433a35148294adfd16444
0xbaee4121675514f171b4c58d8f2da297e203736521cb976655d4f111e6073688
2 others worked so I'm not sure what is going on.
Since the release of OpenMic I spotted some gas outs:
https://ftmscan.com/address/0x29d51e8736fcc8c2662aa1b2cf46753d5918606f
I re-created the latest fail from this tx:
https://ftmscan.com/tx/0xc166a329fda3254345a287709fc089423e160ed3fc0f1d0968a908e911c08054
const summoner = BigNumber.from(2_831_651)
const user = '0x1ab7f9e5bcc70bc6f2529a0aacd0230c4c90a157'
await hre.network.provider.request({
method: "hardhat_impersonateAccount",
params: [user],
})
const provider = await ethers.getDefaultProvider()
const signer = await ethers.getSigner(user)
let openmic = new ethers.Contract('0x29d51E8736FCC8C2662aA1B2cf46753d5918606F', [{"inputs":[{"internalType":"address","name":"_rarity","type":"address"},{"internalType":"address","name":"_attributes","type":"address"},{"internalType":"address","name":"_skills","type":"address"},{"internalType":"address","name":"_codex_base_random","type":"address"},{"internalType":"address","name":"_forest","type":"address"},{"internalType":"address","name":"_openmicV1","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"owner","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"approved","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"owner","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"operator","type":"uint256"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"summoner","type":"uint256"},{"indexed":false,"internalType":"int256","name":"check","type":"int256"},{"indexed":false,"internalType":"bool","name":"success","type":"bool"},{"indexed":false,"internalType":"bool","name":"crit","type":"bool"}],"name":"Perform","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"summoner","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"PrizeAwarded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"from","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"to","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"uint256","name":"from","type":"uint256"},{"internalType":"uint256","name":"to","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"attributes","outputs":[{"internalType":"contract IAttributes","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"owner","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"closeV1Remint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"difficultyClass","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"doorPrizes","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"forest","outputs":[{"internalType":"contract IForest","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDoorPrizes","outputs":[{"internalType":"string[]","name":"","type":"string[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"summoner","type":"uint256"}],"name":"getPerformance","outputs":[{"components":[{"internalType":"uint256","name":"blockTime","type":"uint256"},{"internalType":"bool","name":"success","type":"bool"}],"internalType":"struct Performance","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getPrize","outputs":[{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bool","name":"rare","type":"bool"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"string","name":"name","type":"string"}],"internalType":"struct PrizeView","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"summoner","type":"uint256"}],"name":"getPrizes","outputs":[{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bool","name":"rare","type":"bool"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"string","name":"name","type":"string"}],"internalType":"struct PrizeView[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRarePrizes","outputs":[{"internalType":"string[]","name":"","type":"string[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"intermission","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"owner","type":"uint256"},{"internalType":"uint256","name":"operator","type":"uint256"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"summoner","type":"uint256"}],"name":"odds","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"openmicV1","outputs":[{"internalType":"contract IOpenMicV1","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"summoner","type":"uint256"}],"name":"perform","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"perform_skill","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"random","outputs":[{"internalType":"contract ICodexBaseRandom","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"rarePrizes","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rarity","outputs":[{"internalType":"contract IRarity","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"fromTokenId","type":"uint256"},{"internalType":"uint256","name":"toTokenId","type":"uint256"}],"name":"remintV1Prizes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rm","outputs":[{"internalType":"contract IRarity","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"from","type":"uint256"},{"internalType":"uint256","name":"operator","type":"uint256"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"skills","outputs":[{"internalType":"contract ISkills","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"summoner","type":"uint256"}],"name":"timeToNextPerformance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenCounter","outputs":[{"internalType":"uint256","name":"_value","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"owner","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"operator","type":"uint256"},{"internalType":"uint256","name":"from","type":"uint256"},{"internalType":"uint256","name":"to","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"v1RemintOpen","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}], provider)
openmic = await openmic.connect(signer)
const performance = await (await openmic.perform(summoner)).wait()
const { check, success, crit } = performance.events[0].args
const prizes = await openmic.getPrizes(summoner)
console.log('check, success, crit', check.toString(), success, crit)
console.log('performance.gasUsed', performance.gasUsed.toString())
for(let i = 0; i < prizes.length; i++) {
const prize = prizes[i]
console.log('prize', prize.tokenId.toString(), prize.name)
}
Gas used comes out to 354_096
, but the frontend currently sets 325_000 as the limit. I tested the other failed txs and got the same result, 354_096. Wondering why these particular perform calls cost so much more than what I see in testing.
Each character has an HP score that is dependent on their class and Con mod (CM) (not 18, rather +4)
it can query by READ () 15. Health_by_class_and_level
https://ftmscan.com/address/0x2a0f1cb17680161cf255348ddfdee94ea8ca196a#readContract
Barb 12
Bard 6
Cleric 8
Druid 8
Figher 10
Monk 8
Paladin 10
Ranger 8
Rogue 6
Sorcerer 4
Wizard 4
So a Barb with a CON of 16 would have 12 + 3 = 15 HP
this needs to be displayed under XP bar on Adventurers page..
this will also be useful to display in any "go in a dungeon" page in the future
add more adventures,
add it to the tavern..
SPECS
4-7Day locking, to find treasure
Treasure is relative to character level (I think)
Req, level 5 to enter
we could have.
There is a dark looking man sitting at a table in the corner. His face is hidden under a full faced mask.
Do you want to approach him?
{add a CHARISMA filter here?}
He speaks of a Dark Forest to the North about a week's travel, there and back, with danger but treasure. He is willing to guide you there, but was hurt too much to enter the forest with you. He doesn't want anything in return for helping you, just that you vanquish the beast that has crippled him.
Do you accept his offer?
We can use this beast.
since Major bought this pack already.
https://elthen.itch.io/monster-sprite-pack
I found this
https://ftmscan.com/address/0xb37d3d79ea86B0334d9322c695339D577A3D57be#writeContract
It seems to be a vault like contract for characters that has some cool features. This will need some auditing/testing to see if it's not a rug..
https://github.com/TheAustrian1998/theRarityForest/blob/master/contracts/theRarityForest.sol#L86
That's the creator if anyone know him.
it would be nice to implement some community content.
Simple Typo.
I HAVE A FRIEND, THE WIFE OF THE UNCLE OF ONE OF MY COUSIN (ON MY MOTHER'S SIDE), THAT HAS REALLY GOOD PLAN. THE CURRENT APY IS 3.68%. DO YOU WANT TO APE-IN
Change to
I HAVE A FRIEND, THE WIFE OF THE UNCLE OF ONE OF MY COUSINS (ON MY MOTHER'S SIDE), THAT HAS A REALLY GOOD PLAN. THE CURRENT APY IS 3.68%. DO YOU WANT TO APE-IN
https://rarity-git-feature-dungeon1-tbouder.vercel.app/tavern?tab=ftm-vault
Some actions have a redirect as callback. Sometime (blockchain call) theses actions can take a lot of time and the user can change page in the meantime. In this case, the router.push should be disabled.
Loot the skin rat and change the page. Once the skin rat is claimed, you will be redirected to another page.
I am trying to do the tavern quest with my lvl6 bard. I can enter the quest page, but then cannot proceed and start singing. Nothing happens when clicking on the button. I retried with open dev console and noticed that the page loads without errors but after having clicked the button multiple error popup (see screenshot).
https://i.imgur.com/tcodILl.png
Steps to reproduce the behavior:
Go to https://rarityextended.com/adventures/openmic#action and try to start the quest by click the "stage and sing" button.
Because of the windowInFocus hook, the data about the adventurer are refetcher everytime a metamask popup is closed. We should add a minimum delay between two fetchs (~5/10s)
Click to execute an action and execute it/close the metamask popup. The yellow loading on top should trigger.
WHen I send a character down into the cellar to fight a rat, but he finds nothing, he remains as an option to go down again.
Same issue when he gets KO'd (this is not so much of an issue, as they can level up, deploy stat points, and try agian)
on
https://rarityextended.com/tavern?tab=the-cellar
I don't know.. there will need to be info stored,, seemingly.
Add any other context or screenshots about the feature request here.
Going in an adventure.
This needs to read. "Going on an adventure."
Transasction succesfull
Successful has only 1 L
In the news.. change to
FAUC WAS SURPRISED TO LEARN THAT THE TAVERN'S CELLAR WAS HOME TO THE LARGEST AND UGLIEST RAT EVER RECORDED ! THE LEGENDS SAY THAT IT CAN DEFEAT AN ADVENTURER IN A FEW BITES! WORST OF ALL, THE TREASURE IS NOT EVEN GREAT! FACU IS LOOKING FOR A LITTLE HELP!
MAYBE YOU NEVER NOTICED IT, BUT AFTER 4 DAYS SPENT HANGING OUT IN THIS GLOOMY INN, THIS IS THE FIRST TIME I SEE FACU, THE TAVERN KEEPER, MOVING! WHEN HE WINKED, I THOUGHT I WAS GOING CRAZY, OR PERHAPS THE MEAD WAS GOING TO MY HEAD, BUT NO, HE IS MOVING ! DOES IT MEAN THAT WE WILL ALL MOVE ONE DAY TOO?
OH, THERE IS AN HERO OVER THERE LOOKING FOR SOME ADVENTURE
Steps to reproduce the behavior:
WHen you talk to Lara and chose a quest.. let's add in people there.
Add a pic of quest giver and a speech bubble. In this case its Facu. (put him on the X in the image) If so we need to change the text to 1st person.. so this instead
"I BE FACU, THE TAVERNβS OWNER, ME HEARD SOME SCURRYING ABOUT DOWN IN DA CELLAR. I WENT DOWN TO CHECK IT AND FOUND SWARMS OF HUNGRY RATS. IN ME EARLIER DAYS, FACU THE COMMITTER WOULD HAVE SQUASHED THOSE PESTS, BUT THESE DAYS I BE WEAK AND FRAIL. "
DO YOU WANT TO HELP HIM OUT? ANYTHING YOU FIND YOU GET TO KEEP.
We had some report about the UX of the actions like the forest where it was not easy to find out which adventurer were ready for the forest/ready to dig/in the forest. Suggestion was made to use previous UI, displaying all the adventurer at once.
N/A
Please add status wallet to the list of wallet providers so I can connect to the dapp via Status Wallet
Integrate Status Wallet if it is not too hard, pls. Thanks!
Each class gets one appearance, but there is no way to personalize your look, reducing the feeling of ownership of one's summoners.
I suggest to integrate the rarity-skin open standard, managed by this contract : https://ftmscan.com/address/0xd1447fe5e70d58204946d61224643738ba54f5cc#code
It allows players to choose any NFT and assign them as avatars for their summoner. When no skin is assigned to a summoner, the current, default appearance is displayed. When the RaritySkinManager contract signals that a NFT is assigned to a summoner, the relevant image is fetched using ERC721's tokenURI() method.
I'm the developer of this standard, if you signal that you are interested, I offer to develop the solution and submit it to you through merge request.
Add character
Add Text
ELLO THERE. I AM JANET, I'LL HELP YOU COORDINATE YOUR PARTY OF HEROES. FREE OF CHARGE! THE TOWN PAYS ME. WHAT ARE YOUR COMMANDS.
SEND EVERYONE ON ADVENTURES ONE BY ONE (2)
CLAIM GOLD FOR ALL HEROES(1)
Nice to have: when I have only 1 point left, I still see the arrow to learn a skill that costs 2
Remove the arrow from skills that cost 2 points when I don't have enough, like what we do when all points are spent.
Add any other context or screenshots about the feature request here.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.