Skip to content

Instantly share code, notes, and snippets.

@juliarose
Last active May 2, 2017 12:09
Show Gist options
  • Save juliarose/4ed4b5bfa606b53c00ed876ad3400e02 to your computer and use it in GitHub Desktop.
Save juliarose/4ed4b5bfa606b53c00ed876ad3400e02 to your computer and use it in GitHub Desktop.
/*
For use on backpack.tf inventory pages only.
Used for converting any type of value (string, jQuery object, number)
to an easy to use interface for working with prices.
Usage:
Instance:
1. new Price('1 key'); // value = 1, currency = 'keys'
2. new Price($item); // convert jQuery item which has data-p_bptf attribute
3. new Price(5, 6, 'keys'); // 5-6 keys
4. new Price({ value: 2, value_high: 3, currency: metal }) // 2-3 ref
Instance Getters:
average:
Description:
Produces an average of value and value_high.
Usage:
new Price(3,4).avereage // 3.5
Instance Methods:
getRefinedValue:
Description:
Gets the value in refined. Bases conversion on average
by default. Pass a parameter to use a different value.
Returns 0 if no number can be converted.
Usage:
1. price.getRefinedValue();
2. price.getRefinedValue(price.value);
parseJQuery:
Description:
Parses jQuery item object for assigning values.
Usage:
price.parseJQuery($item);
parseUSD:
Description:
Parses USD value.
Usage:
price.parseUSD('$12.44');
parseString:
Description:
Parses a price string for assigning values.
Usage:
price.parseString('2-3 ref');
Class Methods:
setup:
Description:
Call when document is ready to set core attributes.
Usage:
$(document).ready(function() {
Price.setup(); // get key price
});
stringToRefinedPrice:
Description:
Converts a string to a value in refined metal.
Usage:
Price.stringToRefinedPrice('1 key, 5 ref'); // 25 (when keys are 20 refined)
stringToCurrencies:
Description:
Converts a string to an object of currencies.
Usage:
Price.stringToCurrencies('1 key, 5 ref'); // { keys: 1, metal: 5 }
modifyBonusValue:
Description:
Modifies value gained from paint or strange parts. This method
accepts a 2nd parameter to modify seperate values for each type
of bonus (paint, or strangePart)
Usage:
1. Price.modifyBonusValue($item, { paint: 0.5, strangePart: 0 }); // 50% added value from paints, 0% from strange parts
2. Price.modifyBonusValue($item); // values from bonuses
roundRefinedValue:
Description:
Rounds a refined value to the nearest 1/36 in two decimals.
Usage:
Price.roundRefinedValue(3.3333); // 3.33
Class Properites:
keyPrice:
The price of keys in refined metal.
instanceAttributes:
Array of attributes used by price instance.
RefinedCurrencyValue:
Value in refined metal of each currency.
CurrencyName:
Global name for currency string e.g. 'ref' = 'metal'
*/
// p1 and p2 are optional
var Price = function(o, p1, p2) {
var self = this;
switch (typeof o) {
case 'string':
this.parseString(o);
break;
case 'object':
if (o instanceof jQuery) {
this.parseJQuery(o, p1, p2);
} else {
// basic price object
// { value: 1, value_high: 2, currency: 'metal' }
for (var k, i = 0; i < Price.instanceAttributes.length; i++) {
k = Price.instanceAttributes[i];
if (o[k] !== undefined) {
this[k] = o[k]; // attach properties
}
}
}
break;
case 'number':
this.value = o;
this.value_high = !isNaN(p1) && p1;
this.currency = Price.CurrencyName[p2 || p1] || 'metal'; // presumed metal if no currency
break;
}
this.__defineGetter__('average', function() {
if (self.value_high && self.value) {
return (self.value + self.value_high) / 2;
} else {
return self.value || 0;
}
});
}
Price.prototype.parseJQuery = function($item, scm) {
if ($item.data('p_bptf')) {
this.parseString($item.data('p_bptf'));
} else if ($item.data('p_scm_all') && scm) { // p1 must be set to use scm price as value
this.parseString($item.data('p_scm_all')); // the scm value is only the base scm value, and does not included value for additions
}
if ($item.data('p_bptf_all')) {
this.parseUSD($item.data('p_bptf_all'));
}
// if there is no value that could be found, but there is a price...
if (!this.value && $item.data('price')) {
this.value = $item.data('price');
this.currency = 'metal';
}
}
Price.prototype.parseString = function(string) {
var match = string.match(/^([\d\.]*)[\––]?([\d\.]*)? (\w*)/); // "1-1.2 keys"
if (match) {
this.value = parseFloat(match[1]);
this.currency = Price.CurrencyName[match[3] || match[2]]; // if it's not in the 3rd group, it's in the 2nd
// if there are 3 match groups, there is a range
if (match[3]) {
this.value_high = parseFloat(match[2]);
}
}
}
Price.prototype.parseUSD = function(string) {
var match = string.match(/\$(\d{1,}\.\d{2})/); // 290.00 ref, $33.35
if (match) {
this.usd = parseFloat(match[1]);
}
}
Price.prototype.getRefinedValue = function(value) {
var currencyValue = Price.RefinedCurrencyValue[this.currency];
if (currencyValue) {
return (value || this.average) * currencyValue;
} else {
return 0;
}
}
Price.RefinedCurrencyValue = {
'metal': 1,
'keys': 1
};
Price.CurrencyName = {
'keys': 'keys',
'key': 'keys',
'ref': 'metal',
'$': 'usd'
};
// get the value of keys in metal
Price.getKeyPrice = function() {
// get key price only if a key price doesn't already exist, or the force value is truthy
// this process is slow (for larger inventories) and mostly only needs to be called once (should take 1-100ms)
if (Price.keyPrice) {
return;
}
var rawValue = Session.rawCurrency.value;
Price.RefinedCurrencyValue['usd'] = 1 / rawValue; // set value of usd
// find items priced in keys
// then sort items by price (the higher the price, the more accurate key value we can get)
jQuery('.item[data-p_bptf*="keys"]').sort(function(a,b) {
var ax = parseFloat($(a).attr('data-price')) || 0;
var bx = parseFloat($(b).attr('data-price')) || 0;
var val = 0;
if (ax > bx) {
return -1;
} else if (ax < bx) {
return 1;
}
return 0;
}).each(function() {
// loop through items until we find an item priced in keys
var price = new Price(jQuery(this));
if (price.currency === 'keys' && price.value && price.usd) {
// to get the value of keys in metal...
// value of items is 2 keys, or $4.32
// keys = 2
// usd = 4.32
// 4.32 / 2 = 2.16 (the value of 1 key)
// 2.16 / 0.12 (rawValue) = 18 (refined metal)
Price.setKeyPrice((price.usd / price.average) / rawValue);
return false; // we found what we're looking for, break the loop
}
});
if (!Price.keyPrice) {
// set value using the value of a key, if no items in inventory are priced in keys
var key = $('.item[data-name="Mann Co. Supply Crate Key"]:first');
var price = key && key.length && new Price(key);
if (price && price.value) {
Price.setKeyPrice(price.average);
}
}
}
Price.setKeyPrice = function(value) {
Price.keyPrice = value;
Price.RefinedCurrencyValue['keys'] = value;
console.log('key price is: ' + value);
}
Price.instanceAttributes = ['value', 'value_high', 'usd', 'currency'];
// convert a string to a value in refined metal
// when keys are 20 refined, 1 key, 5 ref -> 25
Price.stringToRefinedPrice = function(string) {
var currencies = Price.stringToCurrencies(string), value = 0, k;
for (k in currencies) {
if (Price.RefinedCurrencyValue[k]) {
value += Price.RefinedCurrencyValue[k] * currencies[k]; // multiply amount of currency by value of currency in metal
}
}
return Price.roundRefinedValue(value);
}
// round down to nearest 1/36 of a ref
Price.roundRefinedValue = function(value) {
return value && Math.floor(Math.round(value * 36) / 36 * 100) / 100;
}
// modify an item's bonus values
// values is an object:
// { strangePart: 0.2, paint: 0.5 }
// to value strange parts as 20% value and paint as 50% value
Price.modifyBonusValue = function($item, multipliers) {
var bonusValue = 0;
var rawBonusValue = 0;
var baseValue = 0;
var isUnusual = $item.data('quality') == 5;
// does not apply to unusuals
if (multipliers && !isUnusual) {
var basePrice = $item.data('price') && new Price($item, true);
baseValue = (basePrice && basePrice.getRefinedValue()) || 0; // modify based on price attribute
var bonusValues = {
strangePart: [
$item.data('part_price_1'),
$item.data('part_price_2'),
$item.data('part_price_3')
],
paint: [
$item.data('paint_price')
]
};
for (var k in bonusValues) {
// loop through values
for (var i = 0; i < bonusValues[k].length; i++) {
if (bonusValues[k][i]) {
var bonusPrice = new Price(bonusValues[k][i]);
var bonusPriceRefinedValue = bonusPrice.getRefinedValue();
bonusValue += bonusPriceRefinedValue * (multipliers[k] || 0); // create price from attribute and multiply its average by multiplier
rawBonusValue += bonusPriceRefinedValue;
}
}
}
} else {
baseValue = new Price($item).getRefinedValue();
}
return baseValue + bonusValue;
}
Price.hasBonuses = function($item) {
var bonusValues = {
strangePart: [
$item.data('part_price_1'),
$item.data('part_price_2'),
$item.data('part_price_3')
],
paint: [
$item.data('paint_price')
]
};
for (var k in bonusValues) {
for (var i = 0; i < bonusValues[k].length; i++) {
if (bonusValues[k][i]) {
return true;
}
}
}
return false;
}
// convert string of currencies to object of currencies
// 5 keys, 5 ref -> { keys: 5, metal: 5 }
Price.stringToCurrencies = function(string) {
var vals = string.split(', '), i, currency, match, reg = /([\d\.]*) (\w*)/; // currency name, amount
var currencies = {};
for (i = 0; i < vals.length; i++) {
match = vals[i].match(reg);
currency = match && Price.CurrencyName[match[2]];
if (currency) {
currencies[currency] = parseFloat(match[1]);
}
}
return currencies;
}
Price.setup = function() {
Price.getKeyPrice(); // get key price
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment