user.eta 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. <% layout('main.eta') %>
  2. <%
  3. const division_to_class = {
  4. 'Unranked': 'unranked',
  5. 'Cardboard': 'cardboard',
  6. 'Wood': 'wood',
  7. 'Wood+': 'wood',
  8. 'Wood++': 'wood',
  9. 'Bronze': 'bronze',
  10. 'Bronze+': 'bronze',
  11. 'Bronze++': 'bronze',
  12. 'Silver': 'silver',
  13. 'Silver+': 'silver',
  14. 'Silver++': 'silver',
  15. 'Gold': 'gold',
  16. 'Gold+': 'gold',
  17. 'Gold++': 'gold',
  18. 'Platinum': 'platinum',
  19. 'Platinum+': 'platinum',
  20. 'Platinum++': 'platinum',
  21. 'Diamond': 'diamond',
  22. 'Diamond+': 'diamond',
  23. 'Diamond++': 'diamond',
  24. 'Legendary': 'legendary',
  25. 'The One': 'the-one',
  26. };
  27. function gen_chart(elos) {
  28. if(elos.length == 0) elos.push(1500);
  29. if(elos.length == 1) elos.push(elos[0]);
  30. let min = elos.reduce((acc, val) => Math.min(acc, val));
  31. let max = elos.reduce((acc, val) => Math.max(acc, val));
  32. let norm = elos.map(x => Math.round((x - min) / (max - min) * 150));
  33. let imod = (640 / elos.length);
  34. let d = 'M 0 ' + (175 - norm[0]) + ' S';
  35. for(let i = 1; i < norm.length; i++) {
  36. d += ` ${Math.round(i * imod)} ${175 - norm[i]}`;
  37. }
  38. return `
  39. <svg viewBox="0 0 600 200">
  40. <defs>
  41. <linearGradient id="gradient" gradientTransform="rotate(90)">
  42. <stop offset="5%" stop-color="yellow" />
  43. <stop offset="95%" stop-color="orange" />
  44. </linearGradient>
  45. </defs>
  46. <path fill="none" stroke="url('#gradient')" d="${d}" stroke-width="4" />
  47. </svg>`;
  48. }
  49. let rankup_percent = (it.rank.elo - it.rank.rankup?.floor_elo) / (it.rank.rankup?.ceil_elo - it.rank.rankup?.floor_elo);
  50. rankup_percent = Math.round(rankup_percent * 100);
  51. %>
  52. <div class="flex flex-wrap gap-6 justify-center">
  53. <div class="w-80">
  54. <div class="flex">
  55. <img class="block h-24 rounded-full" src="https://s.ppy.sh/a/<%= it.user.user_id %>" />
  56. <div class="ml-6 mt-3">
  57. <h1><%= it.user.username %></h1>
  58. <h3 class="text-lg"><%~ it.flag + ' ' + it.country_name %></h3>
  59. </div>
  60. </div>
  61. <% if(it.rank.is_ranked) { %>
  62. <div class="text-center mt-4">
  63. <span class="text-xl <%= division_to_class[it.rank.text] %>"><%= it.rank.text %></span>
  64. <% if(it.rank.rankup.floor_name != 'The One') { %>
  65. <div class="progress bg-gray-300" style="width:100%">
  66. <div class="bar bg-orange-600" style="width: <%= rankup_percent %>%; height: 20px"></div>
  67. </div>
  68. <%= Math.ceil(it.rank.rankup.ceil_elo - it.rank.elo) + ' elo to ' + it.rank.rankup.ceil_name %>
  69. <% } %>
  70. </div>
  71. <div class="p-2">
  72. <%~ gen_chart(it.elo_evolution) %>
  73. </div>
  74. <% } %>
  75. <div class="mt-4">
  76. <ul>
  77. <li><span class="text-lg">Rank #<%= it.rank.rank_nb %></span></li>
  78. <li><span class="text-lg"><%= it.rank.fancy_elo + ' ' %>elo</span></li>
  79. <li><span class="text-lg"><%= it.rank.total_scores + ' ' %>games played</span></li>
  80. <% if(it.rank.s2_division) { %><li><span class="text-lg">Season 2: <span class="<%= division_to_class[it.rank.s2_division] %>"><%= it.rank.s2_division %></span></span></li><% } %>
  81. <% if(it.rank.s1_division) { %><li><span class="text-lg">Season 1: <span class="<%= division_to_class[it.rank.s1_division] %>"><%= it.rank.s1_division %></span></span></li><% } %>
  82. <li><span class="text-lg"><a target="_blank" href="https://osu.ppy.sh/users/<%= it.user.user_id %>">osu! profile</a></span></li>
  83. </ul>
  84. </div>
  85. </div>
  86. <div class="max-w-5xl">
  87. <h2 class="text-center">Match History</h2>
  88. <table class="match-history block my-4">
  89. <thead class="flex flex-col">
  90. <tr class="inline-flex justify-between">
  91. <td class="map grow w-40 p-1.5 text-center font-bold">Map</td>
  92. <td class="w-40 p-1.5 text-center font-bold">Placement</td>
  93. <td class="w-40 p-1.5 text-center font-bold">Elo change</td>
  94. <td class="w-40 p-1.5 text-center font-bold">Time</td>
  95. </tr>
  96. </thead>
  97. <tbody class="flex flex-col map-list">
  98. <% it.matches.matches.forEach((match) => {
  99. let match_elo = Math.round(match.elo_diff);
  100. if(match_elo > 0) match_elo = '+' + match_elo;
  101. %>
  102. <tr class="inline-flex justify-between">
  103. <td class="map grow">
  104. <a href="https://osu.ppy.sh/beatmapsets/<%= match.map.set_id %>#<%= it.osu_ruleset %>/<%= match.map.map_id %>"><%= match.map.name %></a>
  105. </td>
  106. <td><%= match.placement %>/<%= match.nb_players %></td>
  107. <td class="<%= match.elo_diff >= 0 ? 'text-green-500' : 'text-red-500' %>"><%= match_elo %></td>
  108. <td data-tms="<%= match.tms %>"><%= match.time %></td>
  109. </tr>
  110. <% }) %>
  111. </tbody>
  112. </table>
  113. <%~
  114. include('pagination.eta', {
  115. page_num: it.matches.page,
  116. max_pages: it.matches.max_pages,
  117. url_formatter: (num) => `/u/${it.user.user_id}/page-${num}/`
  118. })
  119. %>
  120. </div>
  121. </div>