1. 1 : /* global log -- eslint */
  2. 2 :
  3. 3 : /**
  4. 4 : * @file This file contains functions related to the handling of passcode redeeming in Ingress.
  5. 5 : * @module redeeming
  6. 6 : */
  7. 7 :
  8. 8 : /**
  9. 9 : * Provides a scale factor for short names of various Ingress items used in passcode rewards.
  10. 10 : *
  11. 11 : * @constant
  12. 12 : * @name REDEEM_SHORT_NAMES
  13. 13 : * @type {Object}
  14. 14 : */
  15. 15 : window.REDEEM_SHORT_NAMES = {
  16. 16 : 'portal shield': 'S',
  17. 17 : 'force amp': 'FA',
  18. 18 : 'link amp': 'LA',
  19. 19 : heatsink: 'H',
  20. 20 : multihack: 'M',
  21. 21 : turret: 'T',
  22. 22 : 'unusual object': 'U',
  23. 23 : resonator: 'R',
  24. 24 : 'xmp burster': 'X',
  25. 25 : 'power cube': 'C',
  26. 26 : media: 'M',
  27. 27 : 'ultra strike': 'US',
  28. 28 : };
  29. 29 :
  30. 30 : /**
  31. 31 : * HTTP status codes and corresponding messages returned by the redemption API.
  32. 32 : *
  33. 33 : * @constant
  34. 34 : * @name REDEEM_STATUSES
  35. 35 : * @type {Object}
  36. 36 : */
  37. 37 : window.REDEEM_STATUSES = {
  38. 38 : 429: 'You have been rate-limited by the server. Wait a bit and try again.',
  39. 39 : 500: 'Internal server error',
  40. 40 : };
  41. 41 :
  42. 42 : /**
  43. 43 : * Handles the response from the passcode redeeming API.
  44. 44 : *
  45. 45 : * @function handleRedeemResponse
  46. 46 : * @param {Object} data - The data returned by the API.
  47. 47 : * @param {string} textStatus - The status of the response.
  48. 48 : * @param {jqXHR} jqXHR - The jQuery wrapped XMLHttpRequest object.
  49. 49 : */
  50. 50 : window.handleRedeemResponse = function (data, textStatus, jqXHR) {
  51. 51 : var passcode = jqXHR.passcode;
  52. 52 :
  53. 53 : if (data.error) {
  54. 54 : log.error('Error redeeming passcode "' + passcode + '": ' + data.error);
  55. 55 : window.dialog({
  56. 56 : title: 'Error: ' + passcode,
  57. 57 : html: '<strong>' + data.error + '</strong>',
  58. 58 : });
  59. 59 : return;
  60. 60 : }
  61. 61 : if (!data.rewards) {
  62. 62 : log.error('Error redeeming passcode "' + passcode + '": ', data);
  63. 63 : window.dialog({
  64. 64 : title: 'Error: ' + passcode,
  65. 65 : html: '<strong>An unexpected error occured</strong>',
  66. 66 : });
  67. 67 : return;
  68. 68 : }
  69. 69 :
  70. 70 : if (data.playerData) {
  71. 71 : window.PLAYER = data.playerData;
  72. 72 : window.setupPlayerStat();
  73. 73 : }
  74. 74 :
  75. 75 : var format = 'long';
  76. 76 : try {
  77. 77 : format = localStorage['iitc-passcode-format'];
  78. 78 : } catch {
  79. 79 : /* empty */
  80. 80 : }
  81. 81 :
  82. 82 : var formatHandlers = {
  83. 83 : short: window.formatPasscodeShort,
  84. 84 : long: window.formatPasscodeLong,
  85. 85 : };
  86. 86 : if (!formatHandlers[format]) format = 'long';
  87. 87 :
  88. 88 : var html = formatHandlers[format](data.rewards);
  89. 89 :
  90. 90 : var buttons = {};
  91. 91 : Object.keys(formatHandlers).forEach(function (label) {
  92. 92 : if (label === format) return;
  93. 93 :
  94. 94 : buttons[label.toUpperCase()] = function () {
  95. 95 : $(this).dialog('close');
  96. 96 : localStorage['iitc-passcode-format'] = label;
  97. 97 : window.handleRedeemResponse(data, textStatus, jqXHR);
  98. 98 : };
  99. 99 : });
  100. 100 :
  101. 101 : // Display it
  102. 102 : window.dialog({
  103. 103 : title: 'Passcode: ' + passcode,
  104. 104 : html: html,
  105. 105 : buttons: buttons,
  106. 106 : });
  107. 107 : };
  108. 108 :
  109. 109 : /**
  110. 110 : * Formats passcode reward data into a long, detailed html string.
  111. 111 : *
  112. 112 : * @function formatPasscodeLong
  113. 113 : * @param {Object} data - The reward data.
  114. 114 : * @returns {string} Formatted string representing the detailed rewards.
  115. 115 : */
  116. 116 : window.formatPasscodeLong = function (data) {
  117. 117 : var html = '<p><strong>Passcode confirmed. Acquired items:</strong></p><ul class="redeemReward">';
  118. 118 :
  119. 119 : if (data.other) {
  120. 120 : data.other.forEach(function (item) {
  121. 121 : html += '<li>' + window.escapeHtmlSpecialChars(item) + '</li>';
  122. 122 : });
  123. 123 : }
  124. 124 :
  125. 125 : if (0 < data.xm) html += '<li>' + window.escapeHtmlSpecialChars(data.xm) + ' XM</li>';
  126. 126 : if (0 < data.ap) html += '<li>' + window.escapeHtmlSpecialChars(data.ap) + ' AP</li>';
  127. 127 :
  128. 128 : if (data.inventory) {
  129. 129 : data.inventory.forEach(function (type) {
  130. 130 : type.awards.forEach(function (item) {
  131. 131 : html += '<li>' + item.count + 'x ';
  132. 132 :
  133. 133 : var l = item.level;
  134. 134 : if (0 < l) {
  135. 135 : l = parseInt(l);
  136. 136 : html += '<span class="itemlevel" style="color:' + window.COLORS_LVL[l] + '">L' + l + '</span> ';
  137. 137 : }
  138. 138 :
  139. 139 : html += window.escapeHtmlSpecialChars(type.name) + '</li>';
  140. 140 : });
  141. 141 : });
  142. 142 : }
  143. 143 :
  144. 144 : html += '</ul>';
  145. 145 : return html;
  146. 146 : };
  147. 147 :
  148. 148 : /**
  149. 149 : * Formats passcode reward data into a short, concise html string.
  150. 150 : *
  151. 151 : * @function formatPasscodeShort
  152. 152 : * @param {Object} data - The reward data.
  153. 153 : * @returns {string} Formatted string representing the concise rewards.
  154. 154 : */
  155. 155 : window.formatPasscodeShort = function (data) {
  156. 156 : let awards = [];
  157. 157 : if (data.other) {
  158. 158 : awards = data.other.map(window.escapeHtmlSpecialChars);
  159. 159 : }
  160. 160 :
  161. 161 : if (0 < data.xm) awards.push(window.escapeHtmlSpecialChars(data.xm) + ' XM');
  162. 162 : if (0 < data.ap) awards.push(window.escapeHtmlSpecialChars(data.ap) + ' AP');
  163. 163 :
  164. 164 : if (data.inventory) {
  165. 165 : data.inventory.forEach(function (type) {
  166. 166 : type.awards.forEach(function (item) {
  167. 167 : var str = '';
  168. 168 : if (item.count > 1) str += item.count + '&nbsp;';
  169. 169 :
  170. 170 : if (window.REDEEM_SHORT_NAMES[type.name.toLowerCase()]) {
  171. 171 : var shortName = window.REDEEM_SHORT_NAMES[type.name.toLowerCase()];
  172. 172 :
  173. 173 : let l = item.level;
  174. 174 : if (0 < l) {
  175. 175 : l = parseInt(l);
  176. 176 : str += '<span class="itemlevel" style="color:' + window.COLORS_LVL[l] + '">' + shortName + l + '</span>';
  177. 177 : } else {
  178. 178 : str += shortName;
  179. 179 : }
  180. 180 : } else {
  181. 181 : // no short name known
  182. 182 : let l = item.level;
  183. 183 : if (0 < l) {
  184. 184 : l = parseInt(l);
  185. 185 : str += '<span class="itemlevel" style="color:' + window.COLORS_LVL[l] + '">L' + l + '</span> ';
  186. 186 : }
  187. 187 : str += type.name;
  188. 188 : }
  189. 189 :
  190. 190 : awards.push(str);
  191. 191 : });
  192. 192 : });
  193. 193 : }
  194. 194 :
  195. 195 : return '<p class="redeemReward">' + awards.join(', ') + '</p>';
  196. 196 : };
  197. 197 :
  198. 198 : /**
  199. 199 : * Sets up the redeem functionality, binding to UI elements.
  200. 200 : *
  201. 201 : * @function setupRedeem
  202. 202 : */
  203. 203 : window.setupRedeem = function () {
  204. 204 : $('#redeem').keypress(function (e) {
  205. 205 : if ((e.keyCode ? e.keyCode : e.which) !== 13) return;
  206. 206 :
  207. 207 : var passcode = $(this).val();
  208. 208 : passcode = passcode.replace(/[^\x20-\x7E]+/g, ''); // removes non-printable characters
  209. 209 : if (!passcode) return;
  210. 210 :
  211. 211 : var jqXHR = window.postAjax('redeemReward', { passcode: passcode }, window.handleRedeemResponse, function (response) {
  212. 212 : var extra = '';
  213. 213 : if (response.status) {
  214. 214 : extra = (window.REDEEM_STATUSES[response.status] || 'The server indicated an error.') + ' (HTTP ' + response.status + ')';
  215. 215 : } else {
  216. 216 : extra = 'No status code was returned.';
  217. 217 : }
  218. 218 : window.dialog({
  219. 219 : title: 'Request failed: ' + passcode,
  220. 220 : html: '<strong>The HTTP request failed.</strong> ' + extra,
  221. 221 : });
  222. 222 : });
  223. 223 : jqXHR.passcode = passcode;
  224. 224 : });
  225. 225 : };