fix(api): Armoire actually works randomly

This commit is contained in:
Blade Barringer 2016-09-23 23:18:40 -05:00
parent 4d5b6992be
commit 4df1601718
2 changed files with 55 additions and 88 deletions

View file

@ -1,24 +1,17 @@
/* eslint-disable camelcase */
import sinon from 'sinon'; // eslint-disable-line no-shadow
import {
generateUser,
} from '../../helpers/common.helper';
import count from '../../../website/common/script/count';
import buyArmoire from '../../../website/common/script/ops/buyArmoire';
import shared from '../../../website/common/script';
import content from '../../../website/common/script/content/index';
import {
NotAuthorized,
} from '../../../website/common/script/libs/errors';
import i18n from '../../../website/common/script/i18n';
describe('shared.ops.buyArmoire', () => {
let user;
let YIELD_EQUIPMENT = 0.5;
let YIELD_FOOD = 0.7;
let YIELD_EXP = 0.9;
function getFullArmoire () {
let fullArmoire = {};
_(content.gearTypes).each((type) => {
@ -29,39 +22,36 @@ describe('shared.ops.buyArmoire', () => {
}).value();
}).value();
return fullArmoire;
}
describe('shared.ops.buyArmoire', () => {
let user;
let YIELD_EQUIPMENT = 0.5;
let YIELD_FOOD = 0.7;
let YIELD_EXP = 0.9;
beforeEach(() => {
user = generateUser({
items: {
gear: {
owned: {
weapon_warrior_0: true,
},
equipped: {
weapon_warrior_0: true,
},
},
},
stats: { gp: 200 },
});
user.items.gear.owned = {
weapon_warrior_0: true,
};
user.achievements.ultimateGearSets = { rogue: true };
user.flags.armoireOpened = true;
user.stats.exp = 0;
user.items.food = {};
sinon.stub(shared.fns, 'randomVal');
sinon.stub(shared.fns, 'predictableRandom');
sandbox.stub(Math, 'random');
});
afterEach(() => {
shared.fns.randomVal.restore();
shared.fns.predictableRandom.restore();
Math.random.restore();
});
context('failure conditions', () => {
it('does not open if user does not have enough gold', (done) => {
shared.fns.predictableRandom.returns(YIELD_EQUIPMENT);
user.stats.gp = 50;
try {
@ -71,13 +61,6 @@ describe('shared.ops.buyArmoire', () => {
expect(err.message).to.equal(i18n.t('messageNotEnoughGold'));
expect(user.items.gear.owned).to.eql({
weapon_warrior_0: true,
eyewear_special_blackTopFrame: true,
eyewear_special_blueTopFrame: true,
eyewear_special_greenTopFrame: true,
eyewear_special_pinkTopFrame: true,
eyewear_special_redTopFrame: true,
eyewear_special_whiteTopFrame: true,
eyewear_special_yellowTopFrame: true,
});
expect(user.items.food).to.be.empty;
expect(user.stats.exp).to.eql(0);
@ -86,7 +69,6 @@ describe('shared.ops.buyArmoire', () => {
});
it('does not open without Ultimate Gear achievement', (done) => {
shared.fns.predictableRandom.returns(YIELD_EQUIPMENT);
user.achievements.ultimateGearSets = {healer: false, wizard: false, rogue: false, warrior: false};
try {
@ -96,13 +78,6 @@ describe('shared.ops.buyArmoire', () => {
expect(err.message).to.equal(i18n.t('cannotBuyItem'));
expect(user.items.gear.owned).to.eql({
weapon_warrior_0: true,
eyewear_special_blackTopFrame: true,
eyewear_special_blueTopFrame: true,
eyewear_special_greenTopFrame: true,
eyewear_special_pinkTopFrame: true,
eyewear_special_redTopFrame: true,
eyewear_special_whiteTopFrame: true,
eyewear_special_yellowTopFrame: true,
});
expect(user.items.food).to.be.empty;
expect(user.stats.exp).to.eql(0);
@ -112,93 +87,83 @@ describe('shared.ops.buyArmoire', () => {
});
context('non-gear awards', () => {
// Skipped because can't stub predictableRandom correctly
xit('gives Experience', () => {
shared.fns.predictableRandom.returns(YIELD_EXP);
it('gives Experience', () => {
let previousExp = user.stats.exp;
Math.random.returns(YIELD_EXP);
buyArmoire(user);
expect(user.items.gear.owned).to.eql({weapon_warrior_0: true});
expect(user.items.food).to.be.empty;
expect(user.stats.exp).to.eql(46);
expect(user.stats.gp).to.eql(100);
expect(user.stats.exp).to.be.greaterThan(previousExp);
expect(user.stats.gp).to.equal(100);
});
// Skipped because can't stub predictableRandom correctly
xit('gives food', () => {
let honey = content.food.Honey;
it('gives food', () => {
let previousExp = user.stats.exp;
shared.fns.randomVal.returns(honey);
shared.fns.predictableRandom.returns(YIELD_FOOD);
Math.random.returns(YIELD_FOOD);
buyArmoire(user);
expect(user.items.gear.owned).to.eql({weapon_warrior_0: true});
expect(user.items.food).to.eql({Honey: 1});
expect(user.stats.exp).to.eql(0);
expect(user.stats.gp).to.eql(100);
expect(user.items.food).to.not.be.empty;
expect(user.stats.exp).to.equal(previousExp);
expect(user.stats.gp).to.equal(100);
});
// Skipped because can't stub predictableRandom correctly
xit('does not give equipment if all equipment has been found', () => {
shared.fns.predictableRandom.returns(YIELD_EQUIPMENT);
user.items.gear.owned = fullArmoire;
it('does not give equipment if all equipment has been found', () => {
Math.random.returns(YIELD_EQUIPMENT);
user.items.gear.owned = getFullArmoire();
user.stats.gp = 150;
buyArmoire(user);
expect(user.items.gear.owned).to.eql(fullArmoire);
expect(user.items.gear.owned).to.eql(getFullArmoire());
let armoireCount = count.remainingGearInSet(user.items.gear.owned, 'armoire');
expect(armoireCount).to.eql(0);
expect(user.stats.exp).to.eql(30);
expect(user.stats.gp).to.eql(50);
expect(user.stats.gp).to.equal(50);
});
});
context('gear awards', () => {
beforeEach(() => {
let shield = content.gear.tree.shield.armoire.gladiatorShield;
shared.fns.randomVal.returns(shield);
});
// Skipped because can't stub predictableRandom correctly
xit('always drops equipment the first time', () => {
it('always drops equipment the first time', () => {
delete user.flags.armoireOpened;
shared.fns.predictableRandom.returns(YIELD_EXP);
Math.random.returns(YIELD_EXP);
expect(_.size(user.items.gear.owned)).to.equal(1);
buyArmoire(user);
expect(user.items.gear.owned).to.eql({
weapon_warrior_0: true,
shield_armoire_gladiatorShield: true,
});
expect(_.size(user.items.gear.owned)).to.equal(2);
let armoireCount = count.remainingGearInSet(user.items.gear.owned, 'armoire');
expect(armoireCount).to.eql(_.size(fullArmoire) - 1);
expect(armoireCount).to.eql(_.size(getFullArmoire()) - 1);
expect(user.items.food).to.be.empty;
expect(user.stats.exp).to.eql(0);
expect(user.stats.gp).to.eql(100);
expect(user.stats.exp).to.equal(0);
expect(user.stats.gp).to.equal(100);
});
// Skipped because can't stub predictableRandom correctly
xit('gives more equipment', () => {
shared.fns.predictableRandom.returns(YIELD_EQUIPMENT);
it('gives more equipment', () => {
Math.random.returns(YIELD_EQUIPMENT);
user.items.gear.owned = {
weapon_warrior_0: true,
head_armoire_hornedIronHelm: true,
};
user.stats.gp = 200;
expect(_.size(user.items.gear.owned)).to.equal(2);
buyArmoire(user);
expect(user.items.gear.owned).to.eql({weapon_warrior_0: true, shield_armoire_gladiatorShield: true, head_armoire_hornedIronHelm: true});
expect(_.size(user.items.gear.owned)).to.equal(3);
let armoireCount = count.remainingGearInSet(user.items.gear.owned, 'armoire');
expect(armoireCount).to.eql(_.size(fullArmoire) - 2);
expect(armoireCount).to.eql(_.size(getFullArmoire()) - 2);
expect(user.stats.gp).to.eql(100);
});
});

View file

@ -6,9 +6,11 @@ import splitWhitespace from '../libs/splitWhitespace';
import {
NotAuthorized,
} from '../libs/errors';
import predictableRandom from '../fns/predictableRandom';
import randomVal from '../fns/randomVal';
const YIELD_EQUIPMENT_THRESHOLD = 0.6;
const YIELD_FOOD_THRESHOLD = 0.8;
module.exports = function buyArmoire (user, req = {}, analytics) {
let item = content.armoire;
@ -21,17 +23,16 @@ module.exports = function buyArmoire (user, req = {}, analytics) {
}
let armoireResp;
let armoireResult;
let eligibleEquipment;
let drop;
let message;
armoireResult = predictableRandom(user, user.stats.gp);
eligibleEquipment = _.filter(content.gear.flat, (eligible) => {
let armoireResult = Math.random();
let eligibleEquipment = _.filter(content.gear.flat, (eligible) => {
return eligible.klass === 'armoire' && !user.items.gear.owned[eligible.key];
});
let armoireHasEquipment = !_.isEmpty(eligibleEquipment);
if (!_.isEmpty(eligibleEquipment) && (armoireResult < 0.6 || !user.flags.armoireOpened)) {
if (armoireHasEquipment && (armoireResult < YIELD_EQUIPMENT_THRESHOLD || !user.flags.armoireOpened)) {
eligibleEquipment.sort();
drop = randomVal(user, eligibleEquipment);
@ -55,10 +56,11 @@ module.exports = function buyArmoire (user, req = {}, analytics) {
dropKey: drop.key,
dropText: drop.text(req.language),
};
} else if ((!_.isEmpty(eligibleEquipment) && armoireResult < 0.8) || armoireResult < 0.5) { // eslint-disable-line no-extra-parens
} else if ((armoireHasEquipment && armoireResult < YIELD_FOOD_THRESHOLD) || armoireResult < 0.5) { // eslint-disable-line no-extra-parens
drop = randomVal(user, _.where(content.food, {
canDrop: true,
}));
user.items.food[drop.key] = user.items.food[drop.key] || 0;
user.items.food[drop.key] += 1;
@ -74,7 +76,7 @@ module.exports = function buyArmoire (user, req = {}, analytics) {
dropText: drop.text(req.language),
};
} else {
let armoireExp = Math.floor(predictableRandom(user, user.stats.exp) * 40 + 10);
let armoireExp = Math.floor(Math.random() * 40 + 10);
user.stats.exp += armoireExp;
message = i18n.t('armoireExp', req.language);
armoireResp = {