As this is your first Challenge, let’s take a look at how they are constructed. Each Challenge consists of the following parts:
commandName(argument1, argument2) -> returnValueIt is highly recommended to read through all Tasks carefully before you start designing your solution. Some might be tricky!
Remember that you can use whatever programming language you like to solve the tasks. How you structure your code is completely up to you. If you are used to other tutorials that might sound scary, but really it’s exciting!
Good luck!
The Wallet is very common feature among video games. If you have any sort of money that can be gained and spend, you want some implementation of a wallet.
The wallet concerns itself with gaining and spending various currencies. Users can gain money to increase the balance for a certain currency, and spend money to decrease the balance. They can not overspend, as the balance cannot go below 0.
gainCurrency(currencyId, amount)Add the amount to the balance of the specified currencyId.
spendCurrency(currencyId, amount) -> successRemove the amount from the balance of the specified currencyId if we have it.
Return whether the spending succeeded.
getBalance(currencyId) -> balanceRetrieve the amount of currencyId currently stored.
Each task describes a use-case of the wallet, and provides some example behaviour. Test-driven development
Make sure your implementation supports the example, but try to think beyond it as well. Are there special cases which are not covered?
The essence of the wallet. Gaining and spending various currencies.
getBalance('coins') -> 0
getBalance('diamonds') -> 0 gainCurrency('coins', 4)
getBalance('coins') -> 4 Gaining multiple times should add up.
gainCurrency('coins', 4)
gainCurrency('coins', 6)
getBalance('coins') -> 10 gainCurrency('coins', 4)
gainCurrency('diamonds', 6)
getBalance('coins') -> 4
getBalance('diamonds') -> 4 gainCurrency('coins', 10)
spendCurrency('coins', 6) -> true
getBalance('coins') -> 4 gainCurrency('coins', 5)
spendCurrency('coins', 3) -> true
getBalance('coins') -> 2
spendCurrency('coins', 3) -> false
getBalance('coins') -> 2 gainCurrencies([('coins', 1), ('diamonds', 2)])
getBalance('coins') -> 1
getBalance('diamonds') -> 2 gainCurrency('coins', 5)
gainCurrency('diamonds', 5)
spendCurrencies([('coins', 4), ('diamonds', 3)])
getBalance('coins') -> 1
getBalance('diamonds') -> 2 This Task is trickier than it seems, consider what should happen in the following scenario
gainCurrency('coins', 5)
gainCurrency('diamonds', 1)
spendCurrencies([('coins', 4), ('diamonds', 2)])
getBalance('coins') -> ?
getBalance('diamonds') -> ? Or even this one
gainCurrency('coins', 5)
spendCurrencies([('coins', 2), ('coins', 4)])
getBalance('coins') -> ? While it is nice to believe that once you’ve implemented everything, your wallet works perfectly, the reality is often different. happy path
You might not be the only developer working on a project, and you don’t want your colleagues to break your stuff.
Let’s try to get one step ahead of the “but obviously you shouldn’t do that” discussion!
Negative amount ? Ridiculous!
gainCurrency('coins', -1)
getBalance('coins') -> 0 spendCurrency('coins', -1)
getBalance('coins') -> 0 With our base logic in place, the wallet is technically functional. But some operations, such as checking whether we can afford something, can be a hassle to perform. We want to improve our wallet such that it becomes easier to use. utility methods
gainCurrency('money', 3
canAfford('money', 2) -> true
canAfford('money', 4) -> false Create a way to “connect” a function to run when a balance changes callback
We want to display information about our wallet in a way that is useful to the user.
If we have 37975227936943673922808 coins, we might want to display it as 3.80+22 instead.
Create a way to format the balances in your preferred way when outputting them.
In a multiplayer game, we might be dealing with multiple wallets too.
walletA: gainCurrency('money', 5)
walletB: gainCurrency('money', 5)
transaction('money', 3, walletA, walletB)
walletA: getBalance('money') -> 2
walletB: getBalance('money') -> 8 walletA: gainCurrency('money', 1)
walletB: gainCurrency('money', 2)
walletB: gainCurrency('diamonds', 3)
walletAB: merge(walletA, walletB)
walletAB: getBalance('money') -> 3
walletAB: getBalance('diamonds') -> 3 Bonus tasks are more free-form, and can require you to make big changes to your implementation
gainCurrency('coins', 5)
gainCurrency('diamonds', 10)
save() -> { coins: 5, diamonds: 10 } load({ coins: 5, diamonds: 10 })
getBalance('coins') -> 5
getBalance('diamonds') -> 10 Imagine there is a special currency called copper.
When you have 100 copper, it should turn into 1 silver.
And when you have 100 silver, it should turn into 1 gold.
What would be a clever way to implement this without having to change your wallet at all?