/* global log -- eslint */
/**
* @file This file contains functions related to the handling of passcode redeeming in Ingress.
* @module redeeming
*/
/**
* Provides a scale factor for short names of various Ingress items used in passcode rewards.
*
* @constant
* @name REDEEM_SHORT_NAMES
* @type {Object}
*/
window.REDEEM_SHORT_NAMES = {
'portal shield': 'S',
'force amp': 'FA',
'link amp': 'LA',
heatsink: 'H',
multihack: 'M',
turret: 'T',
'unusual object': 'U',
resonator: 'R',
'xmp burster': 'X',
'power cube': 'C',
media: 'M',
'ultra strike': 'US',
};
/**
* HTTP status codes and corresponding messages returned by the redemption API.
*
* @constant
* @name REDEEM_STATUSES
* @type {Object}
*/
window.REDEEM_STATUSES = {
429: 'You have been rate-limited by the server. Wait a bit and try again.',
500: 'Internal server error',
};
/**
* Handles the response from the passcode redeeming API.
*
* @function handleRedeemResponse
* @param {Object} data - The data returned by the API.
* @param {string} textStatus - The status of the response.
* @param {jqXHR} jqXHR - The jQuery wrapped XMLHttpRequest object.
*/
window.handleRedeemResponse = function (data, textStatus, jqXHR) {
var passcode = jqXHR.passcode;
if (data.error) {
log.error('Error redeeming passcode "' + passcode + '": ' + data.error);
window.dialog({
title: 'Error: ' + passcode,
html: '<strong>' + data.error + '</strong>',
});
return;
}
if (!data.rewards) {
log.error('Error redeeming passcode "' + passcode + '": ', data);
window.dialog({
title: 'Error: ' + passcode,
html: '<strong>An unexpected error occured</strong>',
});
return;
}
if (data.playerData) {
window.PLAYER = data.playerData;
window.setupPlayerStat();
}
var format = 'long';
try {
format = localStorage['iitc-passcode-format'];
} catch {
/* empty */
}
var formatHandlers = {
short: window.formatPasscodeShort,
long: window.formatPasscodeLong,
};
if (!formatHandlers[format]) format = 'long';
var html = formatHandlers[format](data.rewards);
var buttons = {};
Object.keys(formatHandlers).forEach(function (label) {
if (label === format) return;
buttons[label.toUpperCase()] = function () {
$(this).dialog('close');
localStorage['iitc-passcode-format'] = label;
window.handleRedeemResponse(data, textStatus, jqXHR);
};
});
// Display it
window.dialog({
title: 'Passcode: ' + passcode,
html: html,
buttons: buttons,
});
};
/**
* Formats passcode reward data into a long, detailed html string.
*
* @function formatPasscodeLong
* @param {Object} data - The reward data.
* @returns {string} Formatted string representing the detailed rewards.
*/
window.formatPasscodeLong = function (data) {
var html = '<p><strong>Passcode confirmed. Acquired items:</strong></p><ul class="redeemReward">';
if (data.other) {
data.other.forEach(function (item) {
html += '<li>' + window.escapeHtmlSpecialChars(item) + '</li>';
});
}
if (0 < data.xm) html += '<li>' + window.escapeHtmlSpecialChars(data.xm) + ' XM</li>';
if (0 < data.ap) html += '<li>' + window.escapeHtmlSpecialChars(data.ap) + ' AP</li>';
if (data.inventory) {
data.inventory.forEach(function (type) {
type.awards.forEach(function (item) {
html += '<li>' + item.count + 'x ';
var l = item.level;
if (0 < l) {
l = parseInt(l);
html += '<span class="itemlevel" style="color:' + window.COLORS_LVL[l] + '">L' + l + '</span> ';
}
html += window.escapeHtmlSpecialChars(type.name) + '</li>';
});
});
}
html += '</ul>';
return html;
};
/**
* Formats passcode reward data into a short, concise html string.
*
* @function formatPasscodeShort
* @param {Object} data - The reward data.
* @returns {string} Formatted string representing the concise rewards.
*/
window.formatPasscodeShort = function (data) {
let awards = [];
if (data.other) {
awards = data.other.map(window.escapeHtmlSpecialChars);
}
if (0 < data.xm) awards.push(window.escapeHtmlSpecialChars(data.xm) + ' XM');
if (0 < data.ap) awards.push(window.escapeHtmlSpecialChars(data.ap) + ' AP');
if (data.inventory) {
data.inventory.forEach(function (type) {
type.awards.forEach(function (item) {
var str = '';
if (item.count > 1) str += item.count + ' ';
if (window.REDEEM_SHORT_NAMES[type.name.toLowerCase()]) {
var shortName = window.REDEEM_SHORT_NAMES[type.name.toLowerCase()];
let l = item.level;
if (0 < l) {
l = parseInt(l);
str += '<span class="itemlevel" style="color:' + window.COLORS_LVL[l] + '">' + shortName + l + '</span>';
} else {
str += shortName;
}
} else {
// no short name known
let l = item.level;
if (0 < l) {
l = parseInt(l);
str += '<span class="itemlevel" style="color:' + window.COLORS_LVL[l] + '">L' + l + '</span> ';
}
str += type.name;
}
awards.push(str);
});
});
}
return '<p class="redeemReward">' + awards.join(', ') + '</p>';
};
/**
* Sets up the redeem functionality, binding to UI elements.
*
* @function setupRedeem
*/
window.setupRedeem = function () {
$('#redeem').keypress(function (e) {
if ((e.keyCode ? e.keyCode : e.which) !== 13) return;
var passcode = $(this).val();
passcode = passcode.replace(/[^\x20-\x7E]+/g, ''); // removes non-printable characters
if (!passcode) return;
var jqXHR = window.postAjax('redeemReward', { passcode: passcode }, window.handleRedeemResponse, function (response) {
var extra = '';
if (response.status) {
extra = (window.REDEEM_STATUSES[response.status] || 'The server indicated an error.') + ' (HTTP ' + response.status + ')';
} else {
extra = 'No status code was returned.';
}
window.dialog({
title: 'Request failed: ' + passcode,
html: '<strong>The HTTP request failed.</strong> ' + extra,
});
});
jqXHR.passcode = passcode;
});
};