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.

230 lines
8.7 KiB

  1. {% extends "base.html" %}
  2. {% set active_page = "shares_calc" %}
  3. {% block title %}Spoil Shares Calculator{% endblock %}
  4. {% block content %}
  5. <div class="uk-flex uk-flex-center uk-margin-bottom uk-margin-top">
  6. <h1 class="uk-text-center"><strong>Legends of Palisma</strong>Spoil Shares Calculator</h1>
  7. </div>
  8. <div class="uk-grid-divider" uk-grid>
  9. <div class="uk-width-1-3">
  10. <h3>Session Info</h3>
  11. <form class="uk-form-horizontal uk-margin-large" autocomplete=off>
  12. <div class="uk-margin">
  13. <label class="uk-form-label" for="player_count">Number of players</label>
  14. <div class="uk-form-controls">
  15. <select name="player_count" id="player_count" class="uk-select">
  16. <option value="1">1</option>
  17. <option value="2">2</option>
  18. <option value="3">3</option>
  19. <option value="4">4</option>
  20. <option value="5">5</option>
  21. <option value="6">6</option>
  22. <option value="7">7</option>
  23. <option value="8">8</option>
  24. </select>
  25. </div>
  26. </div>
  27. <div class="uk-margin">
  28. <label class="uk-form-label" for="hench_count">Number of henchmen</label>
  29. <div class="uk-form-controls">
  30. <input class="uk-input" id="hench_count" name="hench_count" type="number" value="0">
  31. </div>
  32. </div>
  33. <div class="uk-margin">
  34. <label class="uk-form-label" for="gp_recovered">GP value recovered</label>
  35. <div class="uk-form-controls">
  36. <input class="uk-input" id="gp_recovered" name="gp_recovered" type="number" value="0">
  37. </div>
  38. </div>
  39. <div class="uk-margin">
  40. <label class="uk-form-label" for="xp_earned">XP earned from monsters</label>
  41. <div class="uk-form-controls">
  42. <input class="uk-input" id="xp_earned" name="xp_earned" type="number" value="0">
  43. </div>
  44. </div>
  45. <button type="button" id="share_calc_button" class="uk-button uk-button-primary">Calculate</button>
  46. </form>
  47. </div>
  48. <div class="uk-width-1-3">
  49. <h4>Henchmen XP Shares</h4>
  50. <table id="hench_shares" class="uk-table">
  51. <thead>
  52. <tr>
  53. <th>Bonus XP Rate</th>
  54. <th>Share Per-Henchman</th>
  55. </tr>
  56. </thead>
  57. <tbody></tbody>
  58. </table>
  59. </div>
  60. <div class="uk-width-1-3">
  61. <h4>Player XP Shares</h4>
  62. <table id="player_shares" class="uk-table">
  63. <thead>
  64. <tr>
  65. <th>Bonus XP Rate</th>
  66. <th>Share Per-Player</th>
  67. </tr>
  68. </thead>
  69. <tbody></tbody>
  70. </table>
  71. <h4>Player GP Share</h4>
  72. <span id="pc_gp_share"></span>
  73. <div id="share_button_container" class="uk-margin-large-top uk-hidden">
  74. <button type="button" class="uk-button uk-button-secondary uk-button-small" id="export_button" title="Will copy a chat message to be pasted into Roll20.">Share</button>
  75. <button type="button" class="uk-button uk-button-default uk-button-small" id="clear_button">Reset</button>
  76. </div>
  77. </div>
  78. </div>
  79. <textarea id="export-data" class="uk-textarea uk-hidden"></textarea>
  80. {% endblock %}
  81. {% block head %}
  82. <style>
  83. </style>
  84. {% endblock %}
  85. {% block scripts %}
  86. <script type="text/javascript">
  87. var lastCalculatedShares = null;
  88. window.addEventListener('DOMContentLoaded', () => {
  89. var calc = document.querySelector('button#share_calc_button');
  90. calc.addEventListener("click", calculateShares);
  91. var share = document.querySelector('button#export_button');
  92. share.addEventListener("click", clipboardShare);
  93. var clear = document.querySelector('button#clear_button');
  94. clear.addEventListener("click", resetPage);
  95. });
  96. function calculateShares() {
  97. document.querySelector('div#share_button_container').classList.remove('uk-hidden');
  98. var player_shares = document.querySelector('table#player_shares > tbody');
  99. var hench_shares = document.querySelector('table#hench_shares > tbody');
  100. var pc_gp_share = document.querySelector('span#pc_gp_share');
  101. player_shares.innerHTML = '';
  102. hench_shares.innerHTML = '';
  103. pc_gp_share.innerText = '';
  104. var player_count = parseInt(document.querySelector('select#player_count').value);
  105. var hench_count = parseInt(document.querySelector('input#hench_count').value);
  106. var gp = parseInt(document.querySelector('input#gp_recovered').value);
  107. var xp = parseInt(document.querySelector('input#xp_earned').value);
  108. lastCalculatedShares = {pc: player_count, hc: hench_count, gp: gp, xp: xp};
  109. let total_xp = gp + xp;
  110. let pc_base_xp_share = total_xp / (player_count + hench_count / 2.0);
  111. for(let i = 0; i < 5; i ++) {
  112. // Build player rows
  113. const row = document.createElement("tr");
  114. const c1 = document.createElement("td");
  115. const c2 = document.createElement("td");
  116. c1.appendChild(document.createTextNode(`@ ${5 * i}%`));
  117. c2.appendChild(document.createTextNode(`${Math.floor(pc_base_xp_share * (1 + 0.05 * i))} xp`));
  118. row.appendChild(c1);
  119. row.appendChild(c2);
  120. player_shares.appendChild(row);
  121. // Build hench rows
  122. const hrow = document.createElement("tr");
  123. const hc1 = document.createElement("td");
  124. const hc2 = document.createElement("td");
  125. hc1.appendChild(document.createTextNode(`@ ${5 * i}%`));
  126. hc2.appendChild(document.createTextNode(`${Math.floor(pc_base_xp_share * (1 + 0.05 * i) / 2.0)} xp`));
  127. hrow.appendChild(hc1);
  128. hrow.appendChild(hc2);
  129. hench_shares.appendChild(hrow);
  130. }
  131. var pc_gp_share = document.querySelector('span#pc_gp_share');
  132. let gpshare = Math.floor(gp / (player_count + hench_count / 6.0))
  133. pc_gp_share.appendChild(document.createTextNode(`${gpshare} gold per player.`));
  134. }
  135. function clipboardShare() {
  136. if(!lastCalculatedShares) {
  137. return;
  138. }
  139. var btn = document.querySelector('button#export_button');
  140. btn.classList.remove('uk-animation-shake');
  141. var lcs = lastCalculatedShares;
  142. var [player_count, hench_count, gp, xp] = [lcs.pc, lcs.hc, lcs.gp, lcs.xp];
  143. let total_xp = gp + xp;
  144. let pc_base_xp_share = total_xp / (player_count + hench_count / 2.0);
  145. var [ps, hs] = [{}, {}];
  146. for(let i = 0; i < 5; i ++) {
  147. // Build player rows
  148. ps[`@ ${5 * i}%`] = `${Math.floor(pc_base_xp_share * (1 + 0.05 * i))} xp`;
  149. // Build hench rows
  150. hs[`@ ${5 * i}%`] = `${Math.floor(pc_base_xp_share * (1 + 0.05 * i) / 2.0)} xp`;
  151. }
  152. let gpshare = Math.floor(gp / (player_count + hench_count / 6.0))
  153. {% raw %}
  154. let response = '&{template:acks}{{name=Spoil Shares}}';
  155. response += `{{**Player Gold Share** = [[${gpshare}]]}}`;
  156. response += '{{**Player XP Share**=\n'
  157. for(const [k, v] of Object.entries(ps)) {
  158. response += `${k} bonus: *${v}*\n`;
  159. }
  160. response += '}}';
  161. response += '{{**Henchmen XP Share**=\n'
  162. for(const [k, v] of Object.entries(hs)) {
  163. response += `${k} bonus: *${v}*\n`;
  164. }
  165. response += `}}{{desc=${player_count} players, ${hench_count} henchmen sharing ${gp} gold XP and ${xp} monster XP.}}`;
  166. {% endraw %}
  167. let export_data = document.querySelector('#export-data');
  168. export_data.value = response;
  169. export_data.classList.remove('uk-hidden');
  170. export_data.select();
  171. document.execCommand("copy");
  172. export_data.classList.add('uk-hidden');
  173. btn.classList.add('uk-animation-shake');
  174. }
  175. function resetPage() {
  176. document.querySelector('div#share_button_container').classList.add('uk-hidden');
  177. document.querySelector('table#player_shares > tbody').innerHTML = '';
  178. document.querySelector('table#hench_shares > tbody').innerHTML = '';
  179. document.querySelector('span#pc_gp_share').innerText = '';
  180. document.querySelector('select#player_count').value = 1;
  181. document.querySelector('input#hench_count').value = 0;
  182. document.querySelector('input#gp_recovered').value = 0;
  183. document.querySelector('input#xp_earned').value = 0;
  184. }
  185. </script>
  186. {% endblock %}