Skip to content

Commit

Permalink
Merge pull request #77 from jeremyckahn/lstebner/achievement-i-am-rich
Browse files Browse the repository at this point in the history
Lstebner/achievement i am rich
  • Loading branch information
lstebner committed May 31, 2021
2 parents 3b34ab1 + 72f2301 commit 6bed24f
Show file tree
Hide file tree
Showing 7 changed files with 177 additions and 5 deletions.
6 changes: 5 additions & 1 deletion src/components/Item/Item.js
Expand Up @@ -21,6 +21,7 @@ import {
getFinalCropItemFromSeedItem,
getItemCurrentValue,
getResaleValue,
getSalePriceMultiplier,
moneyString,
integerString,
} from '../../utils'
Expand Down Expand Up @@ -145,6 +146,9 @@ export const Item = ({

const avatar = <img {...{ src: items[id] }} alt={name} />

const sellPrice =
adjustedValue * getSalePriceMultiplier(completedAchievements)

return (
<Card
{...{
Expand Down Expand Up @@ -221,7 +225,7 @@ export const Item = ({
<span>
Sell price:{' '}
<AnimatedNumber
{...{ number: adjustedValue, formatter: moneyString }}
{...{ number: sellPrice, formatter: moneyString }}
/>
</span>
</Tooltip>
Expand Down
2 changes: 2 additions & 0 deletions src/constants.js
Expand Up @@ -110,6 +110,8 @@ export const DAILY_FINANCIAL_HISTORY_RECORD_LENGTH = 7

export const RECIPE_INGREDIENT_VALUE_MULTIPLIER = 1.25

export const I_AM_RICH_BONUSES = [0.05, 0.1, 0.25]

export const PERSISTED_STATE_KEYS = [
'completedAchievements',
'cowBreedingPen',
Expand Down
36 changes: 35 additions & 1 deletion src/data/achievements.js
Expand Up @@ -7,9 +7,10 @@ import {
integerString,
memoize,
moneyTotal,
percentageString,
} from '../utils'
import { cropLifeStage, standardCowColors } from '../enums'
import { COW_FEED_ITEM_ID } from '../constants'
import { COW_FEED_ITEM_ID, I_AM_RICH_BONUSES } from '../constants'
import { addItemToInventory } from '../reducers'

import { itemsMap } from './maps'
Expand Down Expand Up @@ -241,6 +242,39 @@ const achievements = [
inventoryLimit: state.inventoryLimit + reward,
}),
}))(),

((goal = 500000) => ({
id: 'i-am-rich-1',
name: 'I am Rich!',
description: `Earn ${dollarString(goal)}.`,
rewardDescription: `All sales receive a ${percentageString(
I_AM_RICH_BONUSES[0]
)} bonus`,
condition: state => state.revenue >= goal,
reward: state => state,
}))(),

((goal = 1000000) => ({
id: 'i-am-rich-2',
name: 'Millionaire',
description: `Earn ${dollarString(goal)}.`,
rewardDescription: `All sales receive a ${percentageString(
I_AM_RICH_BONUSES[1]
)} bonus`,
condition: state => state.revenue >= goal,
reward: state => state,
}))(),

((goal = 1000000000) => ({
id: 'i-am-rich-3',
name: 'Billionaire',
description: `Earn ${dollarString(goal)}.`,
rewardDescription: `All sales receive a ${percentageString(
I_AM_RICH_BONUSES[2]
)} bonus`,
condition: state => state.revenue >= goal,
reward: state => state,
}))(),
]

export default achievements
Expand Down
44 changes: 44 additions & 0 deletions src/data/achievements.test.js
Expand Up @@ -43,3 +43,47 @@ describe('harvest-crop', () => {
})
})
})

const iAmRichVariants = [
['i-am-rich-1', 500000, 'Earn $500,000.', 'All sales receive a 5% bonus'],
['i-am-rich-2', 1000000, 'Earn $1,000,000.', 'All sales receive a 10% bonus'],
[
'i-am-rich-3',
1000000000,
'Earn $1,000,000,000.',
'All sales receive a 25% bonus',
],
]

describe.each(iAmRichVariants)(
'I am Rich variants',
(id, goal, description, rewardDescription) => {
describe(id, () => {
test('has the expected description', () => {
expect(achievementsMap[id].description).toEqual(description)
})

test('has the expected rewardDescription', () => {
expect(achievementsMap[id].rewardDescription).toEqual(rewardDescription)
})

test(`is achieved when revenue is greater than or equal to ${goal}`, () => {
const achievement = achievementsMap[id]
const state = {
revenue: goal,
}

expect(achievement.condition(state)).toEqual(true)
})

test(`is not achieved when revenue is less than ${goal}`, () => {
const achievement = achievementsMap[id]
const state = {
revenue: goal - 1,
}

expect(achievement.condition(state)).toEqual(false)
})
})
}
)
13 changes: 10 additions & 3 deletions src/reducers.js
Expand Up @@ -41,6 +41,7 @@ import {
getRandomUnlockedCrop,
getRangeCoords,
getResaleValue,
getSalePriceMultiplier,
getSeedItemIdFromFinalStageCropItemId,
inventorySpaceRemaining,
isItemAFarmProduct,
Expand Down Expand Up @@ -1120,7 +1121,12 @@ export const sellItem = (state, { id }, howMany = 1) => {
}

const item = itemsMap[id]
const { itemsSold, money: initialMoney, valueAdjustments } = state
const {
completedAchievements,
itemsSold,
money: initialMoney,
valueAdjustments,
} = state
const oldLevel = levelAchieved(farmProductsSold(itemsSold))
let { loanBalance } = state

Expand All @@ -1129,15 +1135,16 @@ export const sellItem = (state, { id }, howMany = 1) => {
: getAdjustedItemValue(valueAdjustments, id)
const saleIsGarnished = isItemAFarmProduct(item)
let saleValue = 0

for (let i = 0; i < howMany; i++) {
const loanGarnishment = saleIsGarnished
? Math.min(
loanBalance,
castToMoney(adjustedItemValue * LOAN_GARNISHMENT_RATE)
)
: 0
const garnishedProfit = adjustedItemValue - loanGarnishment
const garnishedProfit =
adjustedItemValue * getSalePriceMultiplier(completedAchievements) -
loanGarnishment
loanBalance = moneyTotal(loanBalance, -loanGarnishment)
saleValue = moneyTotal(saleValue, garnishedProfit)
}
Expand Down
25 changes: 25 additions & 0 deletions src/utils.js
Expand Up @@ -48,6 +48,7 @@ import {
COW_WEIGHT_MULTIPLIER_MINIMUM,
DAILY_FINANCIAL_HISTORY_RECORD_LENGTH,
HUGGING_MACHINE_ITEM_ID,
I_AM_RICH_BONUSES,
INITIAL_FIELD_HEIGHT,
INITIAL_FIELD_WIDTH,
INITIAL_SPRINKLER_RANGE,
Expand Down Expand Up @@ -192,6 +193,12 @@ export const dollarString = number => formatNumber(number, '$0,0')
*/
export const integerString = number => formatNumber(number, '0,0')

/**
* @param {number} number A float
* @returns {string} the float converted to a full number with a % added
*/
export const percentageString = number => `${Math.round(number * 100)}%`

/**
* @param {string} itemId
* @returns {number}
Expand Down Expand Up @@ -989,3 +996,21 @@ export const getCostOfNextStorageExpansion = currentInventoryLimit => {
* @returns {Promise}
*/
export const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))

/**
* @param {object} completedAchievements from game state
* @returns {number} multiplier to be used for sales price adjustments based on completedAchievements
*/
export const getSalePriceMultiplier = (completedAchievements = {}) => {
let salePriceMultiplier = 1

if (completedAchievements['i-am-rich-3']) {
salePriceMultiplier += I_AM_RICH_BONUSES[2]
} else if (completedAchievements['i-am-rich-2']) {
salePriceMultiplier += I_AM_RICH_BONUSES[1]
} else if (completedAchievements['i-am-rich-1']) {
salePriceMultiplier += I_AM_RICH_BONUSES[0]
}

return salePriceMultiplier
}
56 changes: 56 additions & 0 deletions src/utils.test.js
Expand Up @@ -24,12 +24,14 @@ import {
getPlotImage,
getPriceEventForCrop,
getRangeCoords,
getSalePriceMultiplier,
integerString,
isItemAFarmProduct,
levelAchieved,
maxYieldOfRecipe,
moneyString,
moneyTotal,
percentageString,
} from './utils'
import fruitNames from './data/fruit-names'
import { testCrop } from './test-utils'
Expand All @@ -55,6 +57,7 @@ import {
COW_STARTING_WEIGHT_VARIANCE,
COW_WEIGHT_MULTIPLIER_MAXIMUM,
COW_WEIGHT_MULTIPLIER_MINIMUM,
I_AM_RICH_BONUSES,
MALE_COW_WEIGHT_MULTIPLIER,
} from './constants'

Expand Down Expand Up @@ -909,3 +912,56 @@ describe('computeMarketPositions', () => {
})
})
})

const percentageStringTests = [
[0.5, '50%'],
[0.05, '5%'],
[1, '100%'],
[10, '1000%'],
[-0.3, '-30%'],
]

describe.each(percentageStringTests)(
'percentageString',
(percent, expectedString) => {
test(`it converts ${percent} to a ${expectedString}`, () => {
expect(percentageString(percent)).toEqual(expectedString)
})
}
)

describe('getSalePriceMultiplier', () => {
test('it returns 1 when there are no completedAchievements', () => {
expect(getSalePriceMultiplier({})).toEqual(1)
})

test('it returns 1 when there are no relevant completedAchievements', () => {
const completedAchievements = {
irrelevant: true,
'also-irrelevant': true,
}

expect(getSalePriceMultiplier(completedAchievements)).toEqual(1)
})

const iAmRichAchievements = [
['i-am-rich-1', 1 + I_AM_RICH_BONUSES[0]],
['i-am-rich-2', 1 + I_AM_RICH_BONUSES[1]],
['i-am-rich-3', 1 + I_AM_RICH_BONUSES[2]],
]

describe.each(iAmRichAchievements)(
'with I am Rich achievements completed',
(achievementId, expectedMultiplier) => {
test(`${achievementId} returns ${expectedMultiplier}`, () => {
const completedAchievements = {
[achievementId]: true,
}

expect(getSalePriceMultiplier(completedAchievements)).toEqual(
expectedMultiplier
)
})
}
)
})

0 comments on commit 6bed24f

Please sign in to comment.