You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

347 lines
15 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. <!doctype html>
  2. <html>
  3. <head>
  4. <title>Orna Tools - atr0phy.net</title>
  5. <meta charset="utf-8">
  6. <meta name="viewport" contents="width=device-width, initial-scale=1">
  7. <!-- <link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}"> -->
  8. <!-- UIkit CSS -->
  9. <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/uikit@3.2.4/dist/css/uikit.min.css" />
  10. <!-- UIkit JS -->
  11. <script src="https://cdn.jsdelivr.net/npm/uikit@3.2.4/dist/js/uikit.min.js"></script>
  12. <script src="https://cdn.jsdelivr.net/npm/uikit@3.2.4/dist/js/uikit-icons.min.js"></script>
  13. <script src="https://cdn.jsdelivr.net/combine/npm/tablesort@5.2.0,npm/tablesort@5.2.0/src/sorts/tablesort.number.min.js"></script>
  14. </head>
  15. <body>
  16. <nav class="uk-navbar-container" uk-navbar>
  17. <div class="uk-navbar-center">
  18. <a href="" class="uk-navbar-item uk-logo">Orna Tools - Equipment Combinations</a>
  19. </div>
  20. </nav>
  21. <div class="uk-container">
  22. <div id="help-container" class="uk-padding-large uk-text-center uk-text-muted uk-margin-large-left uk-margin-large-right">
  23. <div>Use the three tabs to input your options for each equipment slot (head/chest/leg). Click the calculate button to populate a table with possible combinations. Click on the column headers to sort results. Use the green + to input additional items.</div>
  24. </div>
  25. <div id="equipment-container" class="uk-padding-large">
  26. <ul class="uk-flex-center" uk-tab>
  27. <li class="uk-active"><a href="">Head</a></li>
  28. <li><a href="">Chest</a></li>
  29. <li><a href="">Leg</a></li>
  30. </ul>
  31. <ul class="uk-switcher">
  32. {% for slot in ["Head", "Chest", "Leg"] %}
  33. <li>
  34. <div class="uk-padding-large uk-padding-remove-vertical">
  35. <table id="{{ slot | lower }}-table" class="uk-table">
  36. <caption>{{ slot }} Gear</caption>
  37. <thead>
  38. <tr>
  39. <th class="uk-table-shrink"></th>
  40. <th class="uk-table-expand">Item Name</th>
  41. <th class="uk-table-shrink">Defense</th>
  42. <th class="uk-table-shrink">Resistance</th>
  43. <th class="uk-table-shring"></th>
  44. </tr>
  45. </thead>
  46. <tbody>
  47. <tr>
  48. <td>1</td>
  49. <td><input type="text" class="uk-input"/></td>
  50. <td><input type="text" class="uk-input"/></td>
  51. <td><input type="text" class="uk-input"/></td>
  52. <td><a class="uk-icon-button del-row-button" uk-icon="icon:minus-circle;ratio:1"></a></td>
  53. </tr>
  54. </tbody>
  55. </table>
  56. <div class="uk-text-center">
  57. <a id="{{ slot | lower }}-button" class="uk-icon-button add-row-button" uk-icon="icon:plus-circle;ratio:2"></a>
  58. </div>
  59. </div>
  60. </li>
  61. {% endfor %}
  62. </ul>
  63. </div>
  64. <div class="uk-text-center uk-margin-bottom">
  65. <button id="clear-button" class="uk-button uk-button-danger">Clear</button>
  66. <button id="calculate-button" class="uk-button uk-button-primary">Calculate</button>
  67. </div>
  68. <div id="results-panel" class="uk-section uk-overflow-auto" hidden>
  69. <hr class="uk-divider-icon" />
  70. <table id="results-table" class="uk-table uk-table-divider uk-table-striped uk-table-hover">
  71. <thead>
  72. <th data-sort-default>Total</th>
  73. <th>Defense</th>
  74. <th>Resistance</th>
  75. <th class="uk-table-expand" data-sort-method='none'>Head</th>
  76. <th class="uk-table-expand" data-sort-method='none'>Chest</th>
  77. <th class="uk-table-expand" data-sort-method='none'>Legs</th>
  78. </thead>
  79. <tbody></tbody>
  80. </table>
  81. </div>
  82. <!-- Footer -->
  83. <footer class="uk-text-center uk-margin-large-top uk-margin-small-bottom">
  84. &copy; <script>document.write(new Date().getFullYear());</script> by <a href="http://binaryatrocity.name">binaryatrocity</a>
  85. &nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;
  86. Created for the <span class="uk-text-success">Legends of Palisma</span> Kingdom
  87. &nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;
  88. <a href="http://playorna.com">OrnaRPG</a>
  89. </footer>
  90. </div>
  91. </body>
  92. <script>
  93. // Support adding rows to the equipment tables
  94. function addEquipmentTableRow() {
  95. let input_element = document.createElement("input");
  96. input_element.className="uk-input";
  97. input_element.type = "text";
  98. // Create the delete button
  99. let delete_button = document.createElement("a");
  100. delete_button.className="uk-icon-button del-row-button";
  101. delete_button.setAttribute("uk-icon", "icon:minus-circle;ratio:1");
  102. delete_button.addEventListener("click", deleteEquipmentTableRow, false);
  103. let tbody = this.parentElement.previousElementSibling.children[2];
  104. let new_row = tbody.insertRow(-1);
  105. // Append all of the child cells needed
  106. new_row.insertCell(0).appendChild(delete_button);
  107. new_row.insertCell(0).appendChild(input_element.cloneNode());
  108. new_row.insertCell(0).appendChild(input_element.cloneNode());
  109. new_row.insertCell(0).appendChild(input_element.cloneNode());
  110. new_row.insertCell(0).appendChild(document.createTextNode(tbody.children.length))
  111. }
  112. // Support deleting rows from the equipment table
  113. function deleteEquipmentTableRow() {
  114. this.parentElement.parentElement.remove();
  115. }
  116. // Process results and display table
  117. function processEquipmentResults(results) {
  118. var results_tbody = document.querySelector("table#results-table > tbody");
  119. for(result of results) {
  120. let new_row = results_tbody.insertRow(-1);
  121. // Append all of the child cells
  122. new_row.insertCell(0).appendChild(document.createTextNode(result['eq'][2]));
  123. new_row.insertCell(0).appendChild(document.createTextNode(result['eq'][1]));
  124. new_row.insertCell(0).appendChild(document.createTextNode(result['eq'][0]));
  125. new_row.insertCell(0).appendChild(document.createTextNode(result['res']));
  126. new_row.insertCell(0).appendChild(document.createTextNode(result['def']));
  127. new_row.insertCell(0).appendChild(document.createTextNode(result['def'] + result['res']));
  128. }
  129. table_sort.refresh();
  130. document.querySelector("div#results-panel").hidden = false;
  131. results_tbody.scrollIntoView();
  132. }
  133. // Send data to backend
  134. function calculateEquipment() {
  135. let data = gatherEquipmentData();
  136. // Store data in localStorage
  137. localStorage.setItem('eq_data', JSON.stringify(data));
  138. // Clear out existing table rows
  139. for(let row of document.querySelectorAll("table#results-table > tbody > tr")) {
  140. row.remove();
  141. }
  142. fetch('/results', {
  143. method: 'POST',
  144. headers: { 'Content-Type': 'application/json' },
  145. body: JSON.stringify(data)
  146. }).then((response) => response.json()).then((data) => {
  147. processEquipmentResults(data);
  148. }).catch((error) => {
  149. console.log(error);
  150. alert("There was a problem...");
  151. });
  152. }
  153. function gatherEquipmentData() {
  154. var eq_head = [], eq_chest = [], eq_legs = [];
  155. // Gather head gear
  156. for(let row of document.querySelectorAll("table#head-table > tbody > tr")) {
  157. eq_head.push([
  158. row.children[1].firstChild.value,
  159. parseInt(row.children[2].firstChild.value) || 0,
  160. parseInt(row.children[3].firstChild.value) || 0
  161. ]);
  162. }
  163. // Gather chest gear
  164. for(let row of document.querySelectorAll("table#chest-table > tbody > tr")) {
  165. eq_chest.push([
  166. row.children[1].firstChild.value,
  167. parseInt(row.children[2].firstChild.value) || 0,
  168. parseInt(row.children[3].firstChild.value) || 0
  169. ]);
  170. }
  171. // Gather leg gear
  172. for(let row of document.querySelectorAll("table#leg-table > tbody > tr")) {
  173. eq_legs.push([
  174. row.children[1].firstChild.value,
  175. parseInt(row.children[2].firstChild.value) || 0,
  176. parseInt(row.children[3].firstChild.value) || 0
  177. ]);
  178. }
  179. let data = {
  180. "head": eq_head,
  181. "chest": eq_chest,
  182. "legs": eq_legs
  183. };
  184. return data;
  185. }
  186. function clearExistingData() {
  187. localStorage.clear();
  188. // Clear out existing table rows
  189. for(let row of document.querySelectorAll("table > tbody > tr")) {
  190. row.remove();
  191. }
  192. }
  193. function loadExistingData() {
  194. var data = localStorage.getItem('eq_data');
  195. function appendToTable(eq, table_id) {
  196. let input_element = document.createElement("input");
  197. input_element.className="uk-input";
  198. input_element.type = "text";
  199. // Create the delete button
  200. let delete_button = document.createElement("a");
  201. delete_button.className="uk-icon-button del-row-button";
  202. delete_button.setAttribute("uk-icon", "icon:minus-circle;ratio:1");
  203. delete_button.addEventListener("click", deleteEquipmentTableRow, false);
  204. let query = "table#" + table_id + " > tbody";
  205. let tbody = document.querySelector(query);
  206. let new_row = tbody.insertRow(-1);
  207. // Append all of the child cells needed
  208. new_row.insertCell(0).appendChild(delete_button);
  209. input_element.value = eq[2];
  210. new_row.insertCell(0).appendChild(input_element.cloneNode());
  211. input_element.value = eq[1];
  212. new_row.insertCell(0).appendChild(input_element.cloneNode());
  213. input_element.value = eq[0];
  214. new_row.insertCell(0).appendChild(input_element.cloneNode());
  215. new_row.insertCell(0).appendChild(document.createTextNode(tbody.children.length))
  216. }
  217. if(data) {
  218. data = JSON.parse(data);
  219. // Remove existing rows from all tables
  220. clearExistingData();
  221. // Populate new rows in all eq tables
  222. for(let hg of data['head']) {
  223. appendToTable(hg, "head-table");
  224. }
  225. for(let cg of data['chest']) {
  226. appendToTable(cg, "chest-table");
  227. }
  228. for(let lg of data['legs']) {
  229. appendToTable(lg, "leg-table");
  230. }
  231. }
  232. }
  233. function confirmDataCleanse() {
  234. if(confirm("Are you sure you want to clear all existing data?")) {
  235. clearExistingData();
  236. }
  237. }
  238. // Add event listeners to our table buttons
  239. const add_row_buttons = document.querySelectorAll("a.add-row-button");
  240. for(let button of add_row_buttons) {
  241. button.addEventListener("click", addEquipmentTableRow, false);
  242. }
  243. const del_row_buttons = document.querySelectorAll("a.del-row-button");
  244. for(let button of del_row_buttons) {
  245. button.addEventListener("click", deleteEquipmentTableRow, false);
  246. }
  247. // Add event listener to Calculate button, call backend
  248. document.querySelector("#calculate-button").addEventListener("click", calculateEquipment, false);
  249. document.querySelector("#clear-button").addEventListener("click", confirmDataCleanse, false);
  250. // Enable sorting for our results table
  251. var table_sort = new Tablesort(document.querySelector("table#results-table"), {descending: true});
  252. // Load any existing data from LocalStorage
  253. loadExistingData();
  254. </script>
  255. <style type="text/css">
  256. table:not(#results-table) > tbody > tr > td:first-child {
  257. color: #999;
  258. }
  259. div > a.add-row-button {
  260. color: #32d296;
  261. }
  262. table a.del-row-button {
  263. color: #f0506e;
  264. }
  265. table#results-table > tbody > tr > td:first-child {
  266. font-weight: bold;
  267. color: #6c9f12;
  268. }
  269. /* Result Table from Tablesort.css */
  270. th:not(.no-sort) {
  271. cursor: pointer;
  272. }
  273. th[role=columnheader]:not(.no-sort):after {
  274. content: '';
  275. float: right;
  276. margin-top: 7px;
  277. border-width: 0 4px 4px;
  278. border-style: solid;
  279. border-color: #404040 transparent;
  280. visibility: hidden;
  281. opacity: 0;
  282. -ms-user-select: none;
  283. -webkit-user-select: none;
  284. -moz-user-select: none;
  285. user-select: none;
  286. }
  287. th[aria-sort=ascending]:not(.no-sort):after {
  288. border-bottom: none;
  289. border-width: 4px 4px 0;
  290. }
  291. th[aria-sort]:not(.no-sort):after {
  292. visibility: visible;
  293. opacity: 0.4;
  294. }
  295. th[role=columnheader]:not(.no-sort):hover:after {
  296. visibility: visible;
  297. opacity: 1;
  298. }
  299. </style>
  300. </html>