WebHost: Refactor `tracker.py`, removal of dead code, and tweaks to layouts of some tracker pages. (#2438)
This commit is contained in:
parent
185a519248
commit
790f192ded
|
@ -27,8 +27,10 @@ from .models import Command, GameDataPackage, Room, db
|
|||
class CustomClientMessageProcessor(ClientMessageProcessor):
|
||||
ctx: WebHostContext
|
||||
|
||||
def _cmd_video(self, platform, user):
|
||||
"""Set a link for your name in the WebHostLib tracker pointing to a video stream"""
|
||||
def _cmd_video(self, platform: str, user: str):
|
||||
"""Set a link for your name in the WebHostLib tracker pointing to a video stream.
|
||||
Currently, only YouTube and Twitch platforms are supported.
|
||||
"""
|
||||
if platform.lower().startswith("t"): # twitch
|
||||
self.ctx.video[self.client.team, self.client.slot] = "Twitch", user
|
||||
self.ctx.save()
|
||||
|
|
|
@ -4,13 +4,20 @@ const adjustTableHeight = () => {
|
|||
return;
|
||||
const upperDistance = tablesContainer.getBoundingClientRect().top;
|
||||
|
||||
const containerHeight = window.innerHeight - upperDistance;
|
||||
tablesContainer.style.maxHeight = `calc(${containerHeight}px - 1rem)`;
|
||||
|
||||
const tableWrappers = document.getElementsByClassName('table-wrapper');
|
||||
for(let i=0; i < tableWrappers.length; i++){
|
||||
const maxHeight = (window.innerHeight - upperDistance) / 2;
|
||||
tableWrappers[i].style.maxHeight = `calc(${maxHeight}px - 1rem)`;
|
||||
for (let i = 0; i < tableWrappers.length; i++) {
|
||||
// Ensure we are starting from maximum size prior to calculation.
|
||||
tableWrappers[i].style.height = null;
|
||||
tableWrappers[i].style.maxHeight = null;
|
||||
|
||||
// Set as a reasonable height, but still allows the user to resize element if they desire.
|
||||
const currentHeight = tableWrappers[i].offsetHeight;
|
||||
const maxHeight = (window.innerHeight - upperDistance) / Math.min(tableWrappers.length, 4);
|
||||
if (currentHeight > maxHeight) {
|
||||
tableWrappers[i].style.height = `calc(${maxHeight}px - 1rem)`;
|
||||
}
|
||||
|
||||
tableWrappers[i].style.maxHeight = `${currentHeight}px`;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -7,138 +7,55 @@
|
|||
width: calc(100% - 1rem);
|
||||
}
|
||||
|
||||
#tracker-wrapper a{
|
||||
#tracker-wrapper a {
|
||||
color: #234ae4;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.table-wrapper{
|
||||
overflow-y: auto;
|
||||
overflow-x: auto;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
#tracker-header-bar{
|
||||
#tracker-header-bar {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
align-content: center;
|
||||
line-height: 20px;
|
||||
gap: 0.5rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
#tracker-header-bar .info{
|
||||
#tracker-header-bar .info {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
#search{
|
||||
border: 1px solid #000000;
|
||||
border-radius: 3px;
|
||||
padding: 3px;
|
||||
width: 200px;
|
||||
margin-bottom: 0.5rem;
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
#multi-stream-link{
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
div.dataTables_wrapper.no-footer .dataTables_scrollBody{
|
||||
border: none;
|
||||
}
|
||||
|
||||
table.dataTable{
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
table.dataTable thead{
|
||||
font-family: LexendDeca-Regular, sans-serif;
|
||||
}
|
||||
|
||||
table.dataTable tbody, table.dataTable tfoot{
|
||||
background-color: #dce2bd;
|
||||
font-family: LexendDeca-Light, sans-serif;
|
||||
}
|
||||
|
||||
table.dataTable tbody tr:hover, table.dataTable tfoot tr:hover{
|
||||
background-color: #e2eabb;
|
||||
}
|
||||
|
||||
table.dataTable tbody td, table.dataTable tfoot td{
|
||||
padding: 4px 6px;
|
||||
}
|
||||
|
||||
table.dataTable, table.dataTable.no-footer{
|
||||
border-left: 1px solid #bba967;
|
||||
width: calc(100% - 2px) !important;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
table.dataTable thead th{
|
||||
position: -webkit-sticky;
|
||||
position: sticky;
|
||||
background-color: #b0a77d;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
table.dataTable thead th.upper-row{
|
||||
position: -webkit-sticky;
|
||||
position: sticky;
|
||||
background-color: #b0a77d;
|
||||
height: 36px;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
table.dataTable thead th.lower-row{
|
||||
position: -webkit-sticky;
|
||||
position: sticky;
|
||||
background-color: #b0a77d;
|
||||
height: 22px;
|
||||
top: 46px;
|
||||
}
|
||||
|
||||
table.dataTable tbody td, table.dataTable tfoot td{
|
||||
border: 1px solid #bba967;
|
||||
}
|
||||
|
||||
table.dataTable tfoot td{
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.dataTables_scrollBody{
|
||||
background-color: inherit !important;
|
||||
}
|
||||
|
||||
table.dataTable .center-column{
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
img.alttp-sprite {
|
||||
height: auto;
|
||||
max-height: 32px;
|
||||
min-height: 14px;
|
||||
}
|
||||
|
||||
.item-acquired{
|
||||
background-color: #d3c97d;
|
||||
padding: 2px;
|
||||
flex-grow: 1;
|
||||
align-self: center;
|
||||
text-align: justify;
|
||||
}
|
||||
|
||||
#tracker-navigation {
|
||||
display: inline-flex;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin: 0 0.5rem 0.5rem 0.5rem;
|
||||
user-select: none;
|
||||
height: 2rem;
|
||||
}
|
||||
|
||||
.tracker-navigation-bar {
|
||||
display: flex;
|
||||
background-color: #b0a77d;
|
||||
margin: 0.5rem;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.tracker-navigation-button {
|
||||
display: block;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin: 4px;
|
||||
padding-left: 12px;
|
||||
padding-right: 12px;
|
||||
border-radius: 4px;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
color: #000;
|
||||
color: black !important;
|
||||
font-weight: lighter;
|
||||
}
|
||||
|
||||
|
@ -150,6 +67,100 @@ img.alttp-sprite {
|
|||
background-color: rgb(220, 226, 189);
|
||||
}
|
||||
|
||||
.table-wrapper {
|
||||
overflow-y: auto;
|
||||
overflow-x: auto;
|
||||
margin-bottom: 1rem;
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
#search {
|
||||
border: 1px solid #000000;
|
||||
border-radius: 3px;
|
||||
padding: 3px;
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
div.dataTables_wrapper.no-footer .dataTables_scrollBody {
|
||||
border: none;
|
||||
}
|
||||
|
||||
table.dataTable {
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
table.dataTable thead {
|
||||
font-family: LexendDeca-Regular, sans-serif;
|
||||
}
|
||||
|
||||
table.dataTable tbody, table.dataTable tfoot {
|
||||
background-color: #dce2bd;
|
||||
font-family: LexendDeca-Light, sans-serif;
|
||||
}
|
||||
|
||||
table.dataTable tbody tr:hover, table.dataTable tfoot tr:hover {
|
||||
background-color: #e2eabb;
|
||||
}
|
||||
|
||||
table.dataTable tbody td, table.dataTable tfoot td {
|
||||
padding: 4px 6px;
|
||||
}
|
||||
|
||||
table.dataTable, table.dataTable.no-footer {
|
||||
border-left: 1px solid #bba967;
|
||||
width: calc(100% - 2px) !important;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
table.dataTable thead th {
|
||||
position: -webkit-sticky;
|
||||
position: sticky;
|
||||
background-color: #b0a77d;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
table.dataTable thead th.upper-row {
|
||||
position: -webkit-sticky;
|
||||
position: sticky;
|
||||
background-color: #b0a77d;
|
||||
height: 36px;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
table.dataTable thead th.lower-row {
|
||||
position: -webkit-sticky;
|
||||
position: sticky;
|
||||
background-color: #b0a77d;
|
||||
height: 22px;
|
||||
top: 46px;
|
||||
}
|
||||
|
||||
table.dataTable tbody td, table.dataTable tfoot td {
|
||||
border: 1px solid #bba967;
|
||||
}
|
||||
|
||||
table.dataTable tfoot td {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.dataTables_scrollBody {
|
||||
background-color: inherit !important;
|
||||
}
|
||||
|
||||
table.dataTable .center-column {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
img.icon-sprite {
|
||||
height: auto;
|
||||
max-height: 32px;
|
||||
min-height: 14px;
|
||||
}
|
||||
|
||||
.item-acquired {
|
||||
background-color: #d3c97d;
|
||||
}
|
||||
|
||||
@media all and (max-width: 1700px) {
|
||||
table.dataTable thead th.upper-row{
|
||||
position: -webkit-sticky;
|
||||
|
@ -159,7 +170,7 @@ img.alttp-sprite {
|
|||
top: 0;
|
||||
}
|
||||
|
||||
table.dataTable thead th.lower-row{
|
||||
table.dataTable thead th.lower-row {
|
||||
position: -webkit-sticky;
|
||||
position: sticky;
|
||||
background-color: #b0a77d;
|
||||
|
@ -167,11 +178,11 @@ img.alttp-sprite {
|
|||
top: 37px;
|
||||
}
|
||||
|
||||
table.dataTable, table.dataTable.no-footer{
|
||||
table.dataTable, table.dataTable.no-footer {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
img.alttp-sprite {
|
||||
img.icon-sprite {
|
||||
height: auto;
|
||||
max-height: 24px;
|
||||
min-height: 10px;
|
||||
|
@ -187,7 +198,7 @@ img.alttp-sprite {
|
|||
top: 0;
|
||||
}
|
||||
|
||||
table.dataTable thead th.lower-row{
|
||||
table.dataTable thead th.lower-row {
|
||||
position: -webkit-sticky;
|
||||
position: sticky;
|
||||
background-color: #b0a77d;
|
||||
|
@ -195,11 +206,11 @@ img.alttp-sprite {
|
|||
top: 32px;
|
||||
}
|
||||
|
||||
table.dataTable, table.dataTable.no-footer{
|
||||
table.dataTable, table.dataTable.no-footer {
|
||||
font-size: 0.6rem;
|
||||
}
|
||||
|
||||
img.alttp-sprite {
|
||||
img.icon-sprite {
|
||||
height: auto;
|
||||
max-height: 20px;
|
||||
min-height: 10px;
|
||||
|
|
|
@ -1,36 +1,57 @@
|
|||
{% extends 'tablepage.html' %}
|
||||
{% extends "tablepage.html" %}
|
||||
{% block head %}
|
||||
{{ super() }}
|
||||
<title>{{ player_name }}'s Tracker</title>
|
||||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename="styles/tracker.css") }}"/>
|
||||
<script type="application/ecmascript" src="{{ url_for('static', filename="assets/jquery.scrollsync.js") }}"></script>
|
||||
<script type="application/ecmascript" src="{{ url_for('static', filename="assets/trackerCommon.js") }}"></script>
|
||||
<link rel="stylesheet" type="text/css" href="{{ url_for("static", filename="styles/tracker.css") }}"/>
|
||||
<script type="application/ecmascript" src="{{ url_for("static", filename="assets/jquery.scrollsync.js") }}"></script>
|
||||
<script type="application/ecmascript" src="{{ url_for("static", filename="assets/trackerCommon.js") }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
{% include 'header/dirtHeader.html' %}
|
||||
<div id="tracker-wrapper" data-tracker="{{ room.tracker|suuid }}/{{ team }}/{{ player }}" data-second="{{ saving_second }}">
|
||||
<div id="tracker-header-bar">
|
||||
<input placeholder="Search" id="search"/>
|
||||
<span class="info">This tracker will automatically update itself periodically.</span>
|
||||
{% include "header/dirtHeader.html" %}
|
||||
|
||||
<div id="tracker-navigation">
|
||||
<div class="tracker-navigation-bar">
|
||||
<a
|
||||
class="tracker-navigation-button"
|
||||
href="{{ url_for("get_multiworld_tracker", tracker=room.tracker) }}"
|
||||
>
|
||||
🡸 Return to Multiworld Tracker
|
||||
</a>
|
||||
{% if game_specific_tracker %}
|
||||
<a
|
||||
class="tracker-navigation-button"
|
||||
href="{{ url_for("get_player_tracker", tracker=room.tracker, tracked_team=team, tracked_player=player) }}"
|
||||
>
|
||||
Game-Specific Tracker
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="tracker-wrapper" data-tracker="{{ room.tracker | suuid }}/{{ team }}/{{ player }}" data-second="{{ saving_second }}">
|
||||
<div id="tracker-header-bar">
|
||||
<input placeholder="Search" id="search" />
|
||||
<div class="info">This tracker will automatically update itself periodically.</div>
|
||||
</div>
|
||||
<div id="tables-container">
|
||||
<div class="table-wrapper">
|
||||
<table id="received-table" class="table non-unique-item-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Item</th>
|
||||
<th>Amount</th>
|
||||
<th>Order Received</th>
|
||||
<th>Last Order Received</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
{% for id, count in inventory.items() %}
|
||||
<tr>
|
||||
<td>{{ id | item_name }}</td>
|
||||
<td>{{ count }}</td>
|
||||
<td>{{received_items[id]}}</td>
|
||||
</tr>
|
||||
{% for id, count in inventory.items() if count > 0 %}
|
||||
<tr>
|
||||
<td>{{ item_id_to_name[game][id] }}</td>
|
||||
<td>{{ count }}</td>
|
||||
<td>{{ received_items[id] }}</td>
|
||||
</tr>
|
||||
{%- endfor -%}
|
||||
|
||||
</tbody>
|
||||
|
@ -39,24 +60,62 @@
|
|||
<div class="table-wrapper">
|
||||
<table id="locations-table" class="table non-unique-item-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Location</th>
|
||||
<th>Checked</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Location</th>
|
||||
<th class="center-column">Checked</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for name in checked_locations %}
|
||||
|
||||
{%- for location in locations -%}
|
||||
<tr>
|
||||
<td>{{ name | location_name}}</td>
|
||||
<td>✔</td>
|
||||
<td>{{ location_id_to_name[game][location] }}</td>
|
||||
<td class="center-column">
|
||||
{% if location in checked_locations %}✔{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{%- endfor -%}
|
||||
{% for name in not_checked_locations %}
|
||||
{%- endfor -%}
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="table-wrapper">
|
||||
<table id="hints-table" class="table non-unique-item-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>{{ name | location_name}}</td>
|
||||
<td></td>
|
||||
<th>Finder</th>
|
||||
<th>Receiver</th>
|
||||
<th>Item</th>
|
||||
<th>Location</th>
|
||||
<th>Game</th>
|
||||
<th>Entrance</th>
|
||||
<th class="center-column">Found</th>
|
||||
</tr>
|
||||
{%- endfor -%}
|
||||
</thead>
|
||||
<tbody>
|
||||
{%- for hint in hints -%}
|
||||
<tr>
|
||||
<td>
|
||||
{% if hint.finding_player == player %}
|
||||
<b>{{ player_names_with_alias[(team, hint.finding_player)] }}</b>
|
||||
{% else %}
|
||||
{{ player_names_with_alias[(team, hint.finding_player)] }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if hint.receiving_player == player %}
|
||||
<b>{{ player_names_with_alias[(team, hint.receiving_player)] }}</b>
|
||||
{% else %}
|
||||
{{ player_names_with_alias[(team, hint.receiving_player)] }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ item_id_to_name[games[(team, hint.receiving_player)]][hint.item] }}</td>
|
||||
<td>{{ location_id_to_name[games[(team, hint.finding_player)]][hint.location] }}</td>
|
||||
<td>{{ games[(team, hint.finding_player)] }}</td>
|
||||
<td>{% if hint.entrance %}{{ hint.entrance }}{% else %}Vanilla{% endif %}</td>
|
||||
<td class="center-column">{% if hint.found %}✔{% endif %}</td>
|
||||
</tr>
|
||||
{%- endfor -%}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
{% for team, hints in hints.items() %}
|
||||
<div class="table-wrapper">
|
||||
<table id="hints-table" class="table non-unique-item-table" data-order='[[5, "asc"], [0, "asc"]]'>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Finder</th>
|
||||
<th>Receiver</th>
|
||||
<th>Item</th>
|
||||
<th>Location</th>
|
||||
<th>Entrance</th>
|
||||
<th>Found</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{%- for hint in hints -%}
|
||||
<tr>
|
||||
<td>{{ long_player_names[team, hint.finding_player] }}</td>
|
||||
<td>{{ long_player_names[team, hint.receiving_player] }}</td>
|
||||
<td>{{ hint.item|item_name }}</td>
|
||||
<td>{{ hint.location|location_name }}</td>
|
||||
<td>{% if hint.entrance %}{{ hint.entrance }}{% else %}Vanilla{% endif %}</td>
|
||||
<td>{% if hint.found %}✔{% endif %}</td>
|
||||
</tr>
|
||||
{%- endfor -%}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endfor %}
|
|
@ -1,171 +0,0 @@
|
|||
{% extends 'tablepage.html' %}
|
||||
{% block head %}
|
||||
{{ super() }}
|
||||
<title>ALttP Multiworld Tracker</title>
|
||||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename="styles/tracker.css") }}"/>
|
||||
<script type="application/ecmascript" src="{{ url_for('static', filename="assets/jquery.scrollsync.js") }}"></script>
|
||||
<script type="application/ecmascript" src="{{ url_for('static', filename="assets/lttpMultiTracker.js") }}"></script>
|
||||
<script type="application/ecmascript" src="{{ url_for('static', filename="assets/trackerCommon.js") }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
{% include 'header/dirtHeader.html' %}
|
||||
{% include 'multiTrackerNavigation.html' %}
|
||||
<div id="tracker-wrapper" data-tracker="{{ room.tracker|suuid }}">
|
||||
<div id="tracker-header-bar">
|
||||
<input placeholder="Search" id="search"/>
|
||||
<span{% if not video %} hidden{% endif %} id="multi-stream-link">
|
||||
<a target="_blank" href="https://multistream.me/
|
||||
{%- for platform, link in video.values()|unique(False, 1)-%}
|
||||
{%- if platform == "Twitch" -%}t{%- else -%}yt{%- endif -%}:{{- link -}}/
|
||||
{%- endfor -%}">
|
||||
Multistream
|
||||
</a>
|
||||
</span>
|
||||
<span class="info">Clicking on a slot's number will bring up a slot-specific auto-tracker. This tracker will automatically update itself periodically.</span>
|
||||
</div>
|
||||
<div id="tables-container">
|
||||
{% for team, players in inventory.items() %}
|
||||
<div class="table-wrapper">
|
||||
<table id="inventory-table" class="table unique-item-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Name</th>
|
||||
{%- for name in tracking_names -%}
|
||||
{%- if name in icons -%}
|
||||
<th class="center-column">
|
||||
<img class="alttp-sprite" src="{{ icons[name] }}" alt="{{ name|e }}">
|
||||
</th>
|
||||
{%- else -%}
|
||||
<th class="center-column">{{ name|e }}</th>
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{%- for player, items in players.items() -%}
|
||||
<tr>
|
||||
<td><a href="{{ url_for("get_player_tracker", tracker=room.tracker,
|
||||
tracked_team=team, tracked_player=player)}}">{{ loop.index }}</a></td>
|
||||
{%- if (team, loop.index) in video -%}
|
||||
{%- if video[(team, loop.index)][0] == "Twitch" -%}
|
||||
<td>
|
||||
<a target="_blank" href="https://www.twitch.tv/{{ video[(team, loop.index)][1] }}">
|
||||
{{ player_names[(team, loop.index)] }}
|
||||
▶️</a></td>
|
||||
{%- elif video[(team, loop.index)][0] == "Youtube" -%}
|
||||
<td>
|
||||
<a target="_blank" href="youtube.com/c/{{ video[(team, loop.index)][1] }}/live">
|
||||
{{ player_names[(team, loop.index)] }}
|
||||
▶️</a></td>
|
||||
{%- endif -%}
|
||||
{%- else -%}
|
||||
<td>{{ player_names[(team, loop.index)] }}</td>
|
||||
{%- endif -%}
|
||||
{%- for id in tracking_ids -%}
|
||||
{%- if items[id] -%}
|
||||
<td class="center-column item-acquired">
|
||||
{% if id in multi_items %}{{ items[id] }}{% else %}✔️{% endif %}</td>
|
||||
{%- else -%}
|
||||
<td></td>
|
||||
{%- endif -%}
|
||||
{% endfor %}
|
||||
</tr>
|
||||
{%- endfor -%}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
{% for team, players in checks_done.items() %}
|
||||
<div class="table-wrapper">
|
||||
<table id="checks-table" class="table non-unique-item-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th rowspan="2">#</th>
|
||||
<th rowspan="2">Name</th>
|
||||
{% for area in ordered_areas %}
|
||||
{% set colspan = 1 %}
|
||||
{% if area in key_locations %}
|
||||
{% set colspan = colspan + 1 %}
|
||||
{% endif %}
|
||||
{% if area in big_key_locations %}
|
||||
{% set colspan = colspan + 1 %}
|
||||
{% endif %}
|
||||
{% if area in icons %}
|
||||
<th colspan="{{ colspan }}" class="center-column upper-row">
|
||||
<img class="alttp-sprite" src="{{ icons[area] }}" alt="{{ area }}"></th>
|
||||
{%- else -%}
|
||||
<th colspan="{{ colspan }}" class="center-column">{{ area }}</th>
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
<th rowspan="2" class="center-column">%</th>
|
||||
<th rowspan="2" class="center-column hours">Last<br>Activity</th>
|
||||
</tr>
|
||||
<tr>
|
||||
{% for area in ordered_areas %}
|
||||
<th class="center-column lower-row fraction">
|
||||
<img class="alttp-sprite" src="{{ icons["Chest"] }}" alt="Checks">
|
||||
</th>
|
||||
{% if area in key_locations %}
|
||||
<th class="center-column lower-row number">
|
||||
<img class="alttp-sprite" src="{{ icons["Small Key"] }}" alt="Small Key">
|
||||
</th>
|
||||
{% endif %}
|
||||
{% if area in big_key_locations %}
|
||||
<th class="center-column lower-row number">
|
||||
<img class="alttp-sprite" src="{{ icons["Big Key"] }}" alt="Big Key">
|
||||
</th>
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{%- for player, checks in players.items() -%}
|
||||
<tr>
|
||||
<td><a href="{{ url_for("get_player_tracker", tracker=room.tracker,
|
||||
tracked_team=team, tracked_player=player)}}">{{ loop.index }}</a></td>
|
||||
<td>{{ player_names[(team, loop.index)]|e }}</td>
|
||||
{%- for area in ordered_areas -%}
|
||||
{% if player in checks_in_area and area in checks_in_area[player] %}
|
||||
{%- set checks_done = checks[area] -%}
|
||||
{%- set checks_total = checks_in_area[player][area] -%}
|
||||
{%- if checks_done == checks_total -%}
|
||||
<td class="item-acquired center-column">
|
||||
{{ checks_done }}/{{ checks_total }}</td>
|
||||
{%- else -%}
|
||||
<td class="center-column">{{ checks_done }}/{{ checks_total }}</td>
|
||||
{%- endif -%}
|
||||
{%- if area in key_locations -%}
|
||||
<td class="center-column">{{ inventory[team][player][small_key_ids[area]] }}</td>
|
||||
{%- endif -%}
|
||||
{%- if area in big_key_locations -%}
|
||||
<td class="center-column">{% if inventory[team][player][big_key_ids[area]] %}✔️{% endif %}</td>
|
||||
{%- endif -%}
|
||||
{% else %}
|
||||
<td class="center-column"></td>
|
||||
{%- if area in key_locations -%}
|
||||
<td class="center-column"></td>
|
||||
{%- endif -%}
|
||||
{%- if area in big_key_locations -%}
|
||||
<td class="center-column"></td>
|
||||
{%- endif -%}
|
||||
{% endif %}
|
||||
{%- endfor -%}
|
||||
<td class="center-column">{{ "{0:.2f}".format(percent_total_checks_done[team][player]) }}</td>
|
||||
{%- if activity_timers[(team, player)] -%}
|
||||
<td class="center-column">{{ activity_timers[(team, player)].total_seconds() }}</td>
|
||||
{%- else -%}
|
||||
<td class="center-column">None</td>
|
||||
{%- endif -%}
|
||||
</tr>
|
||||
{%- endfor -%}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% include "hintTable.html" with context %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -1,92 +0,0 @@
|
|||
{% extends 'tablepage.html' %}
|
||||
{% block head %}
|
||||
{{ super() }}
|
||||
<title>Multiworld Tracker</title>
|
||||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename="styles/tracker.css") }}"/>
|
||||
<script type="application/ecmascript" src="{{ url_for('static', filename="assets/trackerCommon.js") }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
{% include 'header/dirtHeader.html' %}
|
||||
{% include 'multiTrackerNavigation.html' %}
|
||||
<div id="tracker-wrapper" data-tracker="{{ room.tracker|suuid }}">
|
||||
<div id="tracker-header-bar">
|
||||
<input placeholder="Search" id="search"/>
|
||||
<span{% if not video %} hidden{% endif %} id="multi-stream-link">
|
||||
<a target="_blank" href="https://multistream.me/
|
||||
{%- for platform, link in video.values()|unique(False, 1)-%}
|
||||
{%- if platform == "Twitch" -%}t{%- else -%}yt{%- endif -%}:{{- link -}}/
|
||||
{%- endfor -%}">
|
||||
Multistream
|
||||
</a>
|
||||
</span>
|
||||
<span class="info">Clicking on a slot's number will bring up a slot-specific auto-tracker. This tracker will automatically update itself periodically.</span>
|
||||
</div>
|
||||
<div id="tables-container">
|
||||
{% for team, players in checks_done.items() %}
|
||||
<div class="table-wrapper">
|
||||
<table id="checks-table" class="table non-unique-item-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Name</th>
|
||||
<th>Game</th>
|
||||
<th>Status</th>
|
||||
{% block custom_table_headers %}
|
||||
{# implement this block in game-specific multi trackers #}
|
||||
{% endblock %}
|
||||
<th class="center-column">Checks</th>
|
||||
<th class="center-column">%</th>
|
||||
<th class="center-column hours last-activity">Last<br>Activity</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{%- for player, checks in players.items() -%}
|
||||
<tr>
|
||||
<td><a href="{{ url_for("get_player_tracker", tracker=room.tracker,
|
||||
tracked_team=team, tracked_player=player)}}">{{ loop.index }}</a></td>
|
||||
<td>{{ player_names[(team, loop.index)]|e }}</td>
|
||||
<td>{{ games[player] }}</td>
|
||||
<td>{{ {0: "Disconnected", 5: "Connected", 10: "Ready", 20: "Playing",
|
||||
30: "Goal Completed"}.get(states[team, player], "Unknown State") }}</td>
|
||||
{% block custom_table_row scoped %}
|
||||
{# implement this block in game-specific multi trackers #}
|
||||
{% endblock %}
|
||||
<td class="center-column" data-sort="{{ checks["Total"] }}">
|
||||
{{ checks["Total"] }}/{{ locations[player] | length }}
|
||||
</td>
|
||||
<td class="center-column">{{ "{0:.2f}".format(percent_total_checks_done[team][player]) }}</td>
|
||||
{%- if activity_timers[team, player] -%}
|
||||
<td class="center-column">{{ activity_timers[team, player].total_seconds() }}</td>
|
||||
{%- else -%}
|
||||
<td class="center-column">None</td>
|
||||
{%- endif -%}
|
||||
</tr>
|
||||
{%- endfor -%}
|
||||
</tbody>
|
||||
{% if not self.custom_table_headers() | trim %}
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>Total</td>
|
||||
<td>All Games</td>
|
||||
<td>{{ completed_worlds }}/{{ players|length }} Complete</td>
|
||||
<td class="center-column">{{ players.values()|sum(attribute='Total') }}/{{ total_locations[team] }}</td>
|
||||
<td class="center-column">
|
||||
{% if total_locations[team] == 0 %}
|
||||
100
|
||||
{% else %}
|
||||
{{ "{0:.2f}".format(players.values()|sum(attribute='Total') / total_locations[team] * 100) }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="center-column last-activity"></td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
{% endif %}
|
||||
</table>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% include "hintTable.html" with context %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -1,9 +0,0 @@
|
|||
{%- if enabled_multiworld_trackers|length > 1 -%}
|
||||
<div id="tracker-navigation">
|
||||
{% for enabled_tracker in enabled_multiworld_trackers %}
|
||||
{% set tracker_url = url_for(enabled_tracker.endpoint, tracker=room.tracker) %}
|
||||
<a class="tracker-navigation-button{% if enabled_tracker.current %} selected{% endif %}"
|
||||
href="{{ tracker_url }}">{{ enabled_tracker.name }}</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{%- endif -%}
|
|
@ -0,0 +1,144 @@
|
|||
{% extends "tablepage.html" %}
|
||||
{% block head %}
|
||||
{{ super() }}
|
||||
<title>Multiworld Tracker</title>
|
||||
<link rel="stylesheet" type="text/css" href="{{ url_for("static", filename="styles/tracker.css") }}" />
|
||||
<script type="application/ecmascript" src="{{ url_for("static", filename="assets/trackerCommon.js") }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
{% include "header/dirtHeader.html" %}
|
||||
{% include "multitrackerNavigation.html" %}
|
||||
|
||||
<div id="tracker-wrapper" data-tracker="{{ room.tracker | suuid }}">
|
||||
<div id="tracker-header-bar">
|
||||
<input placeholder="Search" id="search" />
|
||||
|
||||
<div
|
||||
id="multi-stream-link"
|
||||
class="tracker-navigation-bar"
|
||||
{% if not videos %}style="display: none"{% endif %}
|
||||
>
|
||||
|
||||
<a
|
||||
class="tracker-navigation-button"
|
||||
href="https://multistream.me/
|
||||
{%- for platform, link in videos.values() | unique(False, 1) -%}
|
||||
{%- if platform == "Twitch" -%}t{%- else -%}yt{%- endif -%}:{{- link -}}/
|
||||
{%- endfor -%}"
|
||||
target="_blank"
|
||||
>
|
||||
► Multistream
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="info">
|
||||
Clicking on a slot's number will bring up the slot-specific tracker.
|
||||
This tracker will automatically update itself periodically.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="tables-container">
|
||||
{%- for team, players in room_players.items() -%}
|
||||
<div class="table-wrapper">
|
||||
<table id="checks-table" class="table non-unique-item-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Name</th>
|
||||
{% if current_tracker == "Generic" %}<th>Game</th>{% endif %}
|
||||
<th>Status</th>
|
||||
{% block custom_table_headers %}
|
||||
{# Implement this block in game-specific multi-trackers. #}
|
||||
{% endblock %}
|
||||
<th class="center-column">Checks</th>
|
||||
<th class="center-column">%</th>
|
||||
<th class="center-column hours last-activity">Last<br>Activity</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{%- for player in players -%}
|
||||
{%- if current_tracker == "Generic" or games[(team, player)] == current_tracker -%}
|
||||
<tr>
|
||||
<td>
|
||||
<a href="{{ url_for("get_player_tracker", tracker=room.tracker, tracked_team=team, tracked_player=player) }}">
|
||||
{{ player }}
|
||||
</a>
|
||||
</td>
|
||||
<td>{{ player_names_with_alias[(team, player)] | e }}</td>
|
||||
{%- if current_tracker == "Generic" -%}
|
||||
<td>{{ games[(team, player)] }}</td>
|
||||
{%- endif -%}
|
||||
<td>
|
||||
{{
|
||||
{
|
||||
0: "Disconnected",
|
||||
5: "Connected",
|
||||
10: "Ready",
|
||||
20: "Playing",
|
||||
30: "Goal Completed"
|
||||
}.get(states[(team, player)], "Unknown State")
|
||||
}}
|
||||
</td>
|
||||
|
||||
{% block custom_table_row scoped %}
|
||||
{# Implement this block in game-specific multi-trackers. #}
|
||||
{% endblock %}
|
||||
|
||||
{% set location_count = locations[(team, player)] | length %}
|
||||
<td class="center-column" data-sort="{{ locations_complete[(team, player)] }}">
|
||||
{{ locations_complete[(team, player)] }}/{{ location_count }}
|
||||
</td>
|
||||
|
||||
<td class="center-column">
|
||||
{%- if locations[(team, player)] | length > 0 -%}
|
||||
{% set percentage_of_completion = locations_complete[(team, player)] / location_count * 100 %}
|
||||
{{ "{0:.2f}".format(percentage_of_completion) }}
|
||||
{%- else -%}
|
||||
100.00
|
||||
{%- endif -%}
|
||||
</td>
|
||||
|
||||
{%- if activity_timers[(team, player)] -%}
|
||||
<td class="center-column">{{ activity_timers[(team, player)].total_seconds() }}</td>
|
||||
{%- else -%}
|
||||
<td class="center-column">None</td>
|
||||
{%- endif -%}
|
||||
</tr>
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
</tbody>
|
||||
|
||||
{%- if not self.custom_table_headers() | trim -%}
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="2" style="text-align: right">Total</td>
|
||||
<td>All Games</td>
|
||||
<td>{{ completed_worlds[team] }}/{{ players | length }} Complete</td>
|
||||
<td class="center-column">
|
||||
{{ total_team_locations_complete[team] }}/{{ total_team_locations[team] }}
|
||||
</td>
|
||||
<td class="center-column">
|
||||
{%- if total_team_locations[team] == 0 -%}
|
||||
100
|
||||
{%- else -%}
|
||||
{{ "{0:.2f}".format(total_team_locations_complete[team] / total_team_locations[team] * 100) }}
|
||||
{%- endif -%}
|
||||
</td>
|
||||
<td class="center-column last-activity"></td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
{%- endif -%}
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{%- endfor -%}
|
||||
|
||||
{% block custom_tables %}
|
||||
{# Implement this block to create custom tables in game-specific multi-trackers. #}
|
||||
{% endblock %}
|
||||
|
||||
{% include "multitrackerHintTable.html" with context %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -0,0 +1,37 @@
|
|||
{% for team, hints in hints.items() %}
|
||||
<div class="table-wrapper">
|
||||
<table id="hints-table" class="table non-unique-item-table" data-order='[[5, "asc"], [0, "asc"]]'>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Finder</th>
|
||||
<th>Receiver</th>
|
||||
<th>Item</th>
|
||||
<th>Location</th>
|
||||
<th>Game</th>
|
||||
<th>Entrance</th>
|
||||
<th class="center-column">Found</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{%- for hint in hints -%}
|
||||
{%-
|
||||
if current_tracker == "Generic" or (
|
||||
games[(team, hint.finding_player)] == current_tracker or
|
||||
games[(team, hint.receiving_player)] == current_tracker
|
||||
)
|
||||
-%}
|
||||
<tr>
|
||||
<td>{{ player_names_with_alias[(team, hint.finding_player)] }}</td>
|
||||
<td>{{ player_names_with_alias[(team, hint.receiving_player)] }}</td>
|
||||
<td>{{ item_id_to_name[games[(team, hint.receiving_player)]][hint.item] }}</td>
|
||||
<td>{{ location_id_to_name[games[(team, hint.finding_player)]][hint.location] }}</td>
|
||||
<td>{{ games[(team, hint.finding_player)] }}</td>
|
||||
<td>{% if hint.entrance %}{{ hint.entrance }}{% else %}Vanilla{% endif %}</td>
|
||||
<td class="center-column">{% if hint.found %}✔{% endif %}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{%- endfor -%}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endfor %}
|
|
@ -0,0 +1,16 @@
|
|||
{% if enabled_trackers | length > 1 %}
|
||||
<div id="tracker-navigation">
|
||||
{# Multitracker game navigation. #}
|
||||
<div class="tracker-navigation-bar">
|
||||
{%- for game_tracker in enabled_trackers -%}
|
||||
{%- set tracker_url = url_for("get_multiworld_tracker", tracker=room.tracker, game=game_tracker) -%}
|
||||
<a
|
||||
class="tracker-navigation-button{% if current_tracker == game_tracker %} selected{% endif %}"
|
||||
href="{{ tracker_url }}"
|
||||
>
|
||||
{{ game_tracker }}
|
||||
</a>
|
||||
{%- endfor -%}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
|
@ -0,0 +1,205 @@
|
|||
{% extends "multitracker.html" %}
|
||||
{% block head %}
|
||||
{{ super() }}
|
||||
<script type="application/ecmascript" src="{{ url_for("static", filename="assets/jquery.scrollsync.js") }}"></script>
|
||||
<script type="application/ecmascript" src="{{ url_for("static", filename="assets/lttpMultiTracker.js") }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
{# List all tracker-relevant icons. Format: (Name, Image URL) #}
|
||||
{%- set icons = {
|
||||
"Blue Shield": "https://www.zeldadungeon.net/wiki/images/8/85/Fighters-Shield.png",
|
||||
"Red Shield": "https://www.zeldadungeon.net/wiki/images/5/55/Fire-Shield.png",
|
||||
"Mirror Shield": "https://www.zeldadungeon.net/wiki/images/8/84/Mirror-Shield.png",
|
||||
"Fighter Sword": "https://oyster.ignimgs.com/mediawiki/apis.ign.com/the-legend-of-zelda-a-link-to-the-past/4/40/SFighterSword.png?width=1920",
|
||||
"Master Sword": "https://oyster.ignimgs.com/mediawiki/apis.ign.com/the-legend-of-zelda-a-link-to-the-past/6/65/SMasterSword.png?width=1920",
|
||||
"Tempered Sword": "https://oyster.ignimgs.com/mediawiki/apis.ign.com/the-legend-of-zelda-a-link-to-the-past/9/92/STemperedSword.png?width=1920",
|
||||
"Golden Sword": "https://oyster.ignimgs.com/mediawiki/apis.ign.com/the-legend-of-zelda-a-link-to-the-past/2/28/SGoldenSword.png?width=1920",
|
||||
"Bow": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/b/bc/ALttP_Bow_%26_Arrows_Sprite.png?version=5f85a70e6366bf473544ef93b274f74c",
|
||||
"Silver Bow": "https://oyster.ignimgs.com/mediawiki/apis.ign.com/the-legend-of-zelda-a-link-to-the-past/6/65/Bow.png?width=1920",
|
||||
"Green Mail": "https://oyster.ignimgs.com/mediawiki/apis.ign.com/the-legend-of-zelda-a-link-to-the-past/c/c9/SGreenTunic.png?width=1920",
|
||||
"Blue Mail": "https://oyster.ignimgs.com/mediawiki/apis.ign.com/the-legend-of-zelda-a-link-to-the-past/9/98/SBlueTunic.png?width=1920",
|
||||
"Red Mail": "https://oyster.ignimgs.com/mediawiki/apis.ign.com/the-legend-of-zelda-a-link-to-the-past/7/74/SRedTunic.png?width=1920",
|
||||
"Power Glove": "https://oyster.ignimgs.com/mediawiki/apis.ign.com/the-legend-of-zelda-a-link-to-the-past/f/f5/SPowerGlove.png?width=1920",
|
||||
"Titan Mitts": "https://oyster.ignimgs.com/mediawiki/apis.ign.com/the-legend-of-zelda-a-link-to-the-past/c/c1/STitanMitt.png?width=1920",
|
||||
"Progressive Sword": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/c/cc/ALttP_Master_Sword_Sprite.png?version=55869db2a20e157cd3b5c8f556097725",
|
||||
"Pegasus Boots": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/e/ed/ALttP_Pegasus_Shoes_Sprite.png?version=405f42f97240c9dcd2b71ffc4bebc7f9",
|
||||
"Progressive Glove": "https://oyster.ignimgs.com/mediawiki/apis.ign.com/the-legend-of-zelda-a-link-to-the-past/c/c1/STitanMitt.png?width=1920",
|
||||
"Flippers": "https://oyster.ignimgs.com/mediawiki/apis.ign.com/the-legend-of-zelda-a-link-to-the-past/4/4c/ZoraFlippers.png?width=1920",
|
||||
"Moon Pearl": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/6/63/ALttP_Moon_Pearl_Sprite.png?version=d601542d5abcc3e006ee163254bea77e",
|
||||
"Progressive Bow": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/b/bc/ALttP_Bow_%26_Arrows_Sprite.png?version=cfb7648b3714cccc80e2b17b2adf00ed",
|
||||
"Blue Boomerang": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/c/c3/ALttP_Boomerang_Sprite.png?version=96127d163759395eb510b81a556d500e",
|
||||
"Red Boomerang": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/b/b9/ALttP_Magical_Boomerang_Sprite.png?version=47cddce7a07bc3e4c2c10727b491f400",
|
||||
"Hookshot": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/2/24/Hookshot.png?version=c90bc8e07a52e8090377bd6ef854c18b",
|
||||
"Mushroom": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/3/35/ALttP_Mushroom_Sprite.png?version=1f1acb30d71bd96b60a3491e54bbfe59",
|
||||
"Magic Powder": "https://www.zeldadungeon.net/wiki/images/thumb/6/62/MagicPowder-ALttP-Sprite.png/86px-MagicPowder-ALttP-Sprite.png",
|
||||
"Fire Rod": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/d/d6/FireRod.png?version=6eabc9f24d25697e2c4cd43ddc8207c0",
|
||||
"Ice Rod": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/d/d7/ALttP_Ice_Rod_Sprite.png?version=1f944148223d91cfc6a615c92286c3bc",
|
||||
"Bombos": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/8/8c/ALttP_Bombos_Medallion_Sprite.png?version=f4d6aba47fb69375e090178f0fc33b26",
|
||||
"Ether": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/3/3c/Ether.png?version=34027651a5565fcc5a83189178ab17b5",
|
||||
"Quake": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/5/56/ALttP_Quake_Medallion_Sprite.png?version=efd64d451b1831bd59f7b7d6b61b5879",
|
||||
"Lamp": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/6/63/ALttP_Lantern_Sprite.png?version=e76eaa1ec509c9a5efb2916698d5a4ce",
|
||||
"Hammer": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/d/d1/ALttP_Hammer_Sprite.png?version=e0adec227193818dcaedf587eba34500",
|
||||
"Shovel": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/c/c4/ALttP_Shovel_Sprite.png?version=e73d1ce0115c2c70eaca15b014bd6f05",
|
||||
"Flute": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/d/db/Flute.png?version=ec4982b31c56da2c0c010905c5c60390",
|
||||
"Bug Catching Net": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/5/54/Bug-CatchingNet.png?version=4d40e0ee015b687ff75b333b968d8be6",
|
||||
"Book of Mudora": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/2/22/ALttP_Book_of_Mudora_Sprite.png?version=11e4632bba54f6b9bf921df06ac93744",
|
||||
"Bottle": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/e/ef/ALttP_Magic_Bottle_Sprite.png?version=fd98ab04db775270cbe79fce0235777b",
|
||||
"Cane of Somaria": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/e/e1/ALttP_Cane_of_Somaria_Sprite.png?version=8cc1900dfd887890badffc903bb87943",
|
||||
"Cane of Byrna": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/b/bc/ALttP_Cane_of_Byrna_Sprite.png?version=758b607c8cbe2cf1900d42a0b3d0fb54",
|
||||
"Cape": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/1/1c/ALttP_Magic_Cape_Sprite.png?version=6b77f0d609aab0c751307fc124736832",
|
||||
"Magic Mirror": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/e/e5/ALttP_Magic_Mirror_Sprite.png?version=e035dbc9cbe2a3bd44aa6d047762b0cc",
|
||||
"Triforce": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/4/4e/TriforceALttPTitle.png?version=dc398e1293177581c16303e4f9d12a48",
|
||||
"Triforce Piece": "https://www.zeldadungeon.net/wiki/images/thumb/5/54/Triforce_Fragment_-_BS_Zelda.png/62px-Triforce_Fragment_-_BS_Zelda.png",
|
||||
"Small Key": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/f/f1/ALttP_Small_Key_Sprite.png?version=4f35d92842f0de39d969181eea03774e",
|
||||
"Big Key": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/3/33/ALttP_Big_Key_Sprite.png?version=136dfa418ba76c8b4e270f466fc12f4d",
|
||||
"Chest": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/7/73/ALttP_Treasure_Chest_Sprite.png?version=5f530ecd98dcb22251e146e8049c0dda",
|
||||
"Light World": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/e/e7/ALttP_Soldier_Green_Sprite.png?version=d650d417934cd707a47e496489c268a6",
|
||||
"Dark World": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/9/94/ALttP_Moblin_Sprite.png?version=ebf50e33f4657c377d1606bcc0886ddc",
|
||||
"Hyrule Castle": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/d/d3/ALttP_Ball_and_Chain_Trooper_Sprite.png?version=1768a87c06d29cc8e7ddd80b9fa516be",
|
||||
"Agahnims Tower": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/1/1e/ALttP_Agahnim_Sprite.png?version=365956e61b0c2191eae4eddbe591dab5",
|
||||
"Desert Palace": "https://www.zeldadungeon.net/wiki/images/2/25/Lanmola-ALTTP-Sprite.png",
|
||||
"Eastern Palace": "https://www.zeldadungeon.net/wiki/images/d/dc/RedArmosKnight.png",
|
||||
"Tower of Hera": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/3/3c/ALttP_Moldorm_Sprite.png?version=c588257bdc2543468e008a6b30f262a7",
|
||||
"Palace of Darkness": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/e/ed/ALttP_Helmasaur_King_Sprite.png?version=ab8a4a1cfd91d4fc43466c56cba30022",
|
||||
"Swamp Palace": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/7/73/ALttP_Arrghus_Sprite.png?version=b098be3122e53f751b74f4a5ef9184b5",
|
||||
"Skull Woods": "https://alttp-wiki.net/images/6/6a/Mothula.png",
|
||||
"Thieves Town": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/8/86/ALttP_Blind_the_Thief_Sprite.png?version=3833021bfcd112be54e7390679047222",
|
||||
"Ice Palace": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/3/33/ALttP_Kholdstare_Sprite.png?version=e5a1b0e8b2298e550d85f90bf97045c0",
|
||||
"Misery Mire": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/8/85/ALttP_Vitreous_Sprite.png?version=92b2e9cb0aa63f831760f08041d8d8d8",
|
||||
"Turtle Rock": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/9/91/ALttP_Trinexx_Sprite.png?version=0cc867d513952aa03edd155597a0c0be",
|
||||
"Ganons Tower": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/b/b9/ALttP_Ganon_Sprite.png?version=956f51f054954dfff53c1a9d4f929c74",
|
||||
} -%}
|
||||
|
||||
{%- block custom_table_headers %}
|
||||
{#- macro that creates a table header with display name and image -#}
|
||||
{%- macro make_header(name, img_src) %}
|
||||
<th class="center-column">
|
||||
<img height="24" src="{{ img_src }}" title="{{ name }}" alt="{{ name }}" />
|
||||
</th>
|
||||
{% endmacro -%}
|
||||
|
||||
{#- call the macro to build the table header -#}
|
||||
{%- for name in tracking_names %}
|
||||
{%- if name in icons -%}
|
||||
<th class="center-column">
|
||||
<img class="icon-sprite" src="{{ icons[name] }}" alt="{{ name | e }}" title="{{ name | e }}" />
|
||||
</th>
|
||||
{%- endif %}
|
||||
{% endfor -%}
|
||||
{% endblock %}
|
||||
|
||||
{# build each row of custom entries #}
|
||||
{% block custom_table_row scoped %}
|
||||
{%- for id in tracking_ids -%}
|
||||
{# {{ checks }}#}
|
||||
{%- if inventories[(team, player)][id] -%}
|
||||
<td class="center-column item-acquired">
|
||||
{% if id in multi_items %}{{ inventories[(team, player)][id] }}{% else %}✔️{% endif %}
|
||||
</td>
|
||||
{%- else -%}
|
||||
<td></td>
|
||||
{%- endif -%}
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
|
||||
{% block custom_tables %}
|
||||
|
||||
{% for team, _ in total_team_locations.items() %}
|
||||
<div class="table-wrapper">
|
||||
<table id="area-table" class="table non-unique-item-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th rowspan="2">#</th>
|
||||
<th rowspan="2">Name</th>
|
||||
{% for area in ordered_areas %}
|
||||
{% set colspan = 1 %}
|
||||
{% if area in key_locations %}
|
||||
{% set colspan = colspan + 1 %}
|
||||
{% endif %}
|
||||
{% if area in big_key_locations %}
|
||||
{% set colspan = colspan + 1 %}
|
||||
{% endif %}
|
||||
{% if area in icons %}
|
||||
<th colspan="{{ colspan }}" class="center-column upper-row">
|
||||
<img class="icon-sprite" src="{{ icons[area] }}" alt="{{ area }}" title="{{ area }}"></th>
|
||||
{%- else -%}
|
||||
<th colspan="{{ colspan }}" class="center-column">{{ area }}</th>
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
<th rowspan="2" class="center-column">%</th>
|
||||
<th rowspan="2" class="center-column hours">Last<br>Activity</th>
|
||||
</tr>
|
||||
<tr>
|
||||
{% for area in ordered_areas %}
|
||||
<th class="center-column lower-row fraction">
|
||||
<img class="icon-sprite" src="{{ icons["Chest"] }}" alt="Checks" title="Checks Complete">
|
||||
</th>
|
||||
{% if area in key_locations %}
|
||||
<th class="center-column lower-row number">
|
||||
<img class="icon-sprite" src="{{ icons["Small Key"] }}" alt="Small Key" title="Small Keys">
|
||||
</th>
|
||||
{% endif %}
|
||||
{% if area in big_key_locations %}
|
||||
<th class="center-column lower-row number">
|
||||
<img class="icon-sprite" src="{{ icons["Big Key"] }}" alt="Big Key" title="Big Keys">
|
||||
</th>
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{%- for (checks_team, player), area_checks in checks_done.items() if games[(team, player)] == current_tracker and team == checks_team -%}
|
||||
<tr>
|
||||
<td><a href="{{ url_for("get_player_tracker", tracker=room.tracker,
|
||||
tracked_team=team, tracked_player=player)}}">{{ player }}</a></td>
|
||||
<td>{{ player_names_with_alias[(team, player)] | e }}</td>
|
||||
{%- for area in ordered_areas -%}
|
||||
{% if (team, player) in checks_in_area and area in checks_in_area[(team, player)] %}
|
||||
{%- set checks_done = area_checks[area] -%}
|
||||
{%- set checks_total = checks_in_area[(team, player)][area] -%}
|
||||
{%- if checks_done == checks_total -%}
|
||||
<td class="item-acquired center-column">
|
||||
{{ checks_done }}/{{ checks_total }}</td>
|
||||
{%- else -%}
|
||||
<td class="center-column">{{ checks_done }}/{{ checks_total }}</td>
|
||||
{%- endif -%}
|
||||
{%- if area in key_locations -%}
|
||||
<td class="center-column">{{ inventories[(team, player)][small_key_ids[area]] }}</td>
|
||||
{%- endif -%}
|
||||
{%- if area in big_key_locations -%}
|
||||
<td class="center-column">{% if inventories[(team, player)][big_key_ids[area]] %}✔️{% endif %}</td>
|
||||
{%- endif -%}
|
||||
{% else %}
|
||||
<td class="center-column"></td>
|
||||
{%- if area in key_locations -%}
|
||||
<td class="center-column"></td>
|
||||
{%- endif -%}
|
||||
{%- if area in big_key_locations -%}
|
||||
<td class="center-column"></td>
|
||||
{%- endif -%}
|
||||
{% endif %}
|
||||
{%- endfor -%}
|
||||
|
||||
<td class="center-column">
|
||||
{% set location_count = locations[(team, player)] | length %}
|
||||
{%- if locations[(team, player)] | length > 0 -%}
|
||||
{% set percentage_of_completion = locations_complete[(team, player)] / location_count * 100 %}
|
||||
{{ "{0:.2f}".format(percentage_of_completion) }}
|
||||
{%- else -%}
|
||||
100.00
|
||||
{%- endif -%}
|
||||
</td>
|
||||
|
||||
{%- if activity_timers[(team, player)] -%}
|
||||
<td class="center-column">{{ activity_timers[(team, player)].total_seconds() }}</td>
|
||||
{%- else -%}
|
||||
<td class="center-column">None</td>
|
||||
{%- endif -%}
|
||||
</tr>
|
||||
{%- endfor -%}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
{% endblock %}
|
|
@ -1,4 +1,4 @@
|
|||
{% extends "multiTracker.html" %}
|
||||
{% extends "multitracker.html" %}
|
||||
{# establish the to be tracked data. Display Name, factorio/AP internal name, display image #}
|
||||
{%- set science_packs = [
|
||||
("Logistic Science Pack", "logistic-science-pack",
|
||||
|
@ -14,12 +14,12 @@
|
|||
("Space Science Pack", "space-science-pack",
|
||||
"https://wiki.factorio.com/images/thumb/Space_science_pack.png/32px-Space_science_pack.png"),
|
||||
] -%}
|
||||
|
||||
{%- block custom_table_headers %}
|
||||
{#- macro that creates a table header with display name and image -#}
|
||||
{%- macro make_header(name, img_src) %}
|
||||
<th class="center-column">
|
||||
<img src="{{ img_src}}"
|
||||
alt="{{ name }}">
|
||||
<img class="icon-sprite" src="{{ img_src }}" alt="{{ name }}" title="{{ name }}" />
|
||||
</th>
|
||||
{% endmacro -%}
|
||||
{#- call the macro to build the table header -#}
|
||||
|
@ -27,16 +27,15 @@
|
|||
{{ make_header(name, img_src) }}
|
||||
{% endfor -%}
|
||||
{% endblock %}
|
||||
|
||||
{% block custom_table_row scoped %}
|
||||
{% if games[player] == "Factorio" %}
|
||||
{%- set player_inventory = named_inventory[team][player] -%}
|
||||
{%- set player_inventory = inventories[(team, player)] -%}
|
||||
{%- set prog_science = player_inventory["progressive-science-pack"] -%}
|
||||
{%- for name, internal_name, img_src in science_packs %}
|
||||
<td class="center-column">{% if player_inventory[internal_name] or prog_science > loop.index0 %}✔{% endif %}</td>
|
||||
{% if player_inventory[internal_name] or prog_science > loop.index0 %}
|
||||
<td class="center-column item-acquired">✔️</td>
|
||||
{% else %}
|
||||
<td class="center-column"></td>
|
||||
{% endif %}
|
||||
{% endfor -%}
|
||||
{% else %}
|
||||
{%- for _ in science_packs %}
|
||||
<td class="center-column">❌</td>
|
||||
{% endfor -%}
|
||||
{% endif %}
|
||||
{% endblock%}
|
|
@ -0,0 +1,154 @@
|
|||
{%- set icons = {
|
||||
"Blue Shield": "https://www.zeldadungeon.net/wiki/images/8/85/Fighters-Shield.png",
|
||||
"Red Shield": "https://www.zeldadungeon.net/wiki/images/5/55/Fire-Shield.png",
|
||||
"Mirror Shield": "https://www.zeldadungeon.net/wiki/images/8/84/Mirror-Shield.png",
|
||||
"Fighter Sword": "https://oyster.ignimgs.com/mediawiki/apis.ign.com/the-legend-of-zelda-a-link-to-the-past/4/40/SFighterSword.png?width=1920",
|
||||
"Master Sword": "https://oyster.ignimgs.com/mediawiki/apis.ign.com/the-legend-of-zelda-a-link-to-the-past/6/65/SMasterSword.png?width=1920",
|
||||
"Tempered Sword": "https://oyster.ignimgs.com/mediawiki/apis.ign.com/the-legend-of-zelda-a-link-to-the-past/9/92/STemperedSword.png?width=1920",
|
||||
"Golden Sword": "https://oyster.ignimgs.com/mediawiki/apis.ign.com/the-legend-of-zelda-a-link-to-the-past/2/28/SGoldenSword.png?width=1920",
|
||||
"Bow": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/b/bc/ALttP_Bow_%26_Arrows_Sprite.png?version=5f85a70e6366bf473544ef93b274f74c",
|
||||
"Silver Bow": "https://oyster.ignimgs.com/mediawiki/apis.ign.com/the-legend-of-zelda-a-link-to-the-past/6/65/Bow.png?width=1920",
|
||||
"Green Mail": "https://oyster.ignimgs.com/mediawiki/apis.ign.com/the-legend-of-zelda-a-link-to-the-past/c/c9/SGreenTunic.png?width=1920",
|
||||
"Blue Mail": "https://oyster.ignimgs.com/mediawiki/apis.ign.com/the-legend-of-zelda-a-link-to-the-past/9/98/SBlueTunic.png?width=1920",
|
||||
"Red Mail": "https://oyster.ignimgs.com/mediawiki/apis.ign.com/the-legend-of-zelda-a-link-to-the-past/7/74/SRedTunic.png?width=1920",
|
||||
"Power Glove": "https://oyster.ignimgs.com/mediawiki/apis.ign.com/the-legend-of-zelda-a-link-to-the-past/f/f5/SPowerGlove.png?width=1920",
|
||||
"Titan Mitts": "https://oyster.ignimgs.com/mediawiki/apis.ign.com/the-legend-of-zelda-a-link-to-the-past/c/c1/STitanMitt.png?width=1920",
|
||||
"Progressive Sword": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/c/cc/ALttP_Master_Sword_Sprite.png?version=55869db2a20e157cd3b5c8f556097725",
|
||||
"Pegasus Boots": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/e/ed/ALttP_Pegasus_Shoes_Sprite.png?version=405f42f97240c9dcd2b71ffc4bebc7f9",
|
||||
"Progressive Glove": "https://oyster.ignimgs.com/mediawiki/apis.ign.com/the-legend-of-zelda-a-link-to-the-past/c/c1/STitanMitt.png?width=1920",
|
||||
"Flippers": "https://oyster.ignimgs.com/mediawiki/apis.ign.com/the-legend-of-zelda-a-link-to-the-past/4/4c/ZoraFlippers.png?width=1920",
|
||||
"Moon Pearl": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/6/63/ALttP_Moon_Pearl_Sprite.png?version=d601542d5abcc3e006ee163254bea77e",
|
||||
"Progressive Bow": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/b/bc/ALttP_Bow_%26_Arrows_Sprite.png?version=cfb7648b3714cccc80e2b17b2adf00ed",
|
||||
"Blue Boomerang": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/c/c3/ALttP_Boomerang_Sprite.png?version=96127d163759395eb510b81a556d500e",
|
||||
"Red Boomerang": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/b/b9/ALttP_Magical_Boomerang_Sprite.png?version=47cddce7a07bc3e4c2c10727b491f400",
|
||||
"Hookshot": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/2/24/Hookshot.png?version=c90bc8e07a52e8090377bd6ef854c18b",
|
||||
"Mushroom": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/3/35/ALttP_Mushroom_Sprite.png?version=1f1acb30d71bd96b60a3491e54bbfe59",
|
||||
"Magic Powder": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/e/e5/ALttP_Magic_Powder_Sprite.png?version=c24e38effbd4f80496d35830ce8ff4ec",
|
||||
"Fire Rod": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/d/d6/FireRod.png?version=6eabc9f24d25697e2c4cd43ddc8207c0",
|
||||
"Ice Rod": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/d/d7/ALttP_Ice_Rod_Sprite.png?version=1f944148223d91cfc6a615c92286c3bc",
|
||||
"Bombos": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/8/8c/ALttP_Bombos_Medallion_Sprite.png?version=f4d6aba47fb69375e090178f0fc33b26",
|
||||
"Ether": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/3/3c/Ether.png?version=34027651a5565fcc5a83189178ab17b5",
|
||||
"Quake": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/5/56/ALttP_Quake_Medallion_Sprite.png?version=efd64d451b1831bd59f7b7d6b61b5879",
|
||||
"Lamp": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/6/63/ALttP_Lantern_Sprite.png?version=e76eaa1ec509c9a5efb2916698d5a4ce",
|
||||
"Hammer": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/d/d1/ALttP_Hammer_Sprite.png?version=e0adec227193818dcaedf587eba34500",
|
||||
"Shovel": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/c/c4/ALttP_Shovel_Sprite.png?version=e73d1ce0115c2c70eaca15b014bd6f05",
|
||||
"Flute": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/d/db/Flute.png?version=ec4982b31c56da2c0c010905c5c60390",
|
||||
"Bug Catching Net": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/5/54/Bug-CatchingNet.png?version=4d40e0ee015b687ff75b333b968d8be6",
|
||||
"Book of Mudora": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/2/22/ALttP_Book_of_Mudora_Sprite.png?version=11e4632bba54f6b9bf921df06ac93744",
|
||||
"Bottle": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/e/ef/ALttP_Magic_Bottle_Sprite.png?version=fd98ab04db775270cbe79fce0235777b",
|
||||
"Cane of Somaria": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/e/e1/ALttP_Cane_of_Somaria_Sprite.png?version=8cc1900dfd887890badffc903bb87943",
|
||||
"Cane of Byrna": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/b/bc/ALttP_Cane_of_Byrna_Sprite.png?version=758b607c8cbe2cf1900d42a0b3d0fb54",
|
||||
"Cape": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/1/1c/ALttP_Magic_Cape_Sprite.png?version=6b77f0d609aab0c751307fc124736832",
|
||||
"Magic Mirror": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/e/e5/ALttP_Magic_Mirror_Sprite.png?version=e035dbc9cbe2a3bd44aa6d047762b0cc",
|
||||
"Triforce": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/4/4e/TriforceALttPTitle.png?version=dc398e1293177581c16303e4f9d12a48",
|
||||
"Triforce Piece": "https://www.zeldadungeon.net/wiki/images/thumb/5/54/Triforce_Fragment_-_BS_Zelda.png/62px-Triforce_Fragment_-_BS_Zelda.png",
|
||||
"Small Key": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/f/f1/ALttP_Small_Key_Sprite.png?version=4f35d92842f0de39d969181eea03774e",
|
||||
"Big Key": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/3/33/ALttP_Big_Key_Sprite.png?version=136dfa418ba76c8b4e270f466fc12f4d",
|
||||
"Chest": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/7/73/ALttP_Treasure_Chest_Sprite.png?version=5f530ecd98dcb22251e146e8049c0dda",
|
||||
"Light World": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/e/e7/ALttP_Soldier_Green_Sprite.png?version=d650d417934cd707a47e496489c268a6",
|
||||
"Dark World": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/9/94/ALttP_Moblin_Sprite.png?version=ebf50e33f4657c377d1606bcc0886ddc",
|
||||
"Hyrule Castle": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/d/d3/ALttP_Ball_and_Chain_Trooper_Sprite.png?version=1768a87c06d29cc8e7ddd80b9fa516be",
|
||||
"Agahnims Tower": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/1/1e/ALttP_Agahnim_Sprite.png?version=365956e61b0c2191eae4eddbe591dab5",
|
||||
"Desert Palace": "https://www.zeldadungeon.net/wiki/images/2/25/Lanmola-ALTTP-Sprite.png",
|
||||
"Eastern Palace": "https://www.zeldadungeon.net/wiki/images/d/dc/RedArmosKnight.png",
|
||||
"Tower of Hera": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/3/3c/ALttP_Moldorm_Sprite.png?version=c588257bdc2543468e008a6b30f262a7",
|
||||
"Palace of Darkness": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/e/ed/ALttP_Helmasaur_King_Sprite.png?version=ab8a4a1cfd91d4fc43466c56cba30022",
|
||||
"Swamp Palace": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/7/73/ALttP_Arrghus_Sprite.png?version=b098be3122e53f751b74f4a5ef9184b5",
|
||||
"Skull Woods": "https://alttp-wiki.net/images/6/6a/Mothula.png",
|
||||
"Thieves Town": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/8/86/ALttP_Blind_the_Thief_Sprite.png?version=3833021bfcd112be54e7390679047222",
|
||||
"Ice Palace": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/3/33/ALttP_Kholdstare_Sprite.png?version=e5a1b0e8b2298e550d85f90bf97045c0",
|
||||
"Misery Mire": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/8/85/ALttP_Vitreous_Sprite.png?version=92b2e9cb0aa63f831760f08041d8d8d8",
|
||||
"Turtle Rock": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/9/91/ALttP_Trinexx_Sprite.png?version=0cc867d513952aa03edd155597a0c0be",
|
||||
"Ganons Tower": "https://gamepedia.cursecdn.com/zelda_gamepedia_en/b/b9/ALttP_Ganon_Sprite.png?version=956f51f054954dfff53c1a9d4f929c74",
|
||||
} -%}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>{{ player_name }}'s Tracker</title>
|
||||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename="styles/lttp-tracker.css") }}"/>
|
||||
<script type="application/ecmascript" src="{{ url_for('static', filename="assets/lttp-tracker.js") }}"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
{# TODO: Replace this with a proper wrapper for each tracker when developing TrackerAPI. #}
|
||||
<div style="margin-bottom: 0.5rem">
|
||||
<a href="{{ url_for("get_generic_game_tracker", tracker=room.tracker, tracked_team=team, tracked_player=player) }}">Switch To Generic Tracker</a>
|
||||
</div>
|
||||
|
||||
<div id="player-tracker-wrapper" data-tracker="{{ room.tracker|suuid }}">
|
||||
<table id="inventory-table">
|
||||
<tr>
|
||||
<td><img src="{{ icons[bow_icon] }}" class="{{ 'acquired' if bow_acquired }}" /></td>
|
||||
<td><img src="{{ icons["Blue Boomerang"] }}" class="{{ 'acquired' if 'Blue Boomerang' in acquired_items }}" /></td>
|
||||
<td><img src="{{ icons["Red Boomerang"] }}" class="{{ 'acquired' if 'Red Boomerang' in acquired_items }}" /></td>
|
||||
<td><img src="{{ icons["Hookshot"] }}" class="{{ 'acquired' if 'Hookshot' in acquired_items }}" /></td>
|
||||
<td><img src="{{ icons["Magic Powder"] }}" class="powder-fix {{ 'acquired' if 'Magic Powder' in acquired_items }}" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="{{ icons["Fire Rod"] }}" class="{{ 'acquired' if "Fire Rod" in acquired_items }}" /></td>
|
||||
<td><img src="{{ icons["Ice Rod"] }}" class="{{ 'acquired' if "Ice Rod" in acquired_items }}" /></td>
|
||||
<td><img src="{{ icons["Bombos"] }}" class="{{ 'acquired' if "Bombos" in acquired_items }}" /></td>
|
||||
<td><img src="{{ icons["Ether"] }}" class="{{ 'acquired' if "Ether" in acquired_items }}" /></td>
|
||||
<td><img src="{{ icons["Quake"] }}" class="{{ 'acquired' if "Quake" in acquired_items }}" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="{{ icons["Lamp"] }}" class="{{ 'acquired' if "Lamp" in acquired_items }}" /></td>
|
||||
<td><img src="{{ icons["Hammer"] }}" class="{{ 'acquired' if "Hammer" in acquired_items }}" /></td>
|
||||
<td><img src="{{ icons["Flute"] }}" class="{{ 'acquired' if "Flute" in acquired_items }}" /></td>
|
||||
<td><img src="{{ icons["Bug Catching Net"] }}" class="{{ 'acquired' if "Bug Catching Net" in acquired_items }}" /></td>
|
||||
<td><img src="{{ icons["Book of Mudora"] }}" class="{{ 'acquired' if "Book of Mudora" in acquired_items }}" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="{{ icons["Bottle"] }}" class="{{ 'acquired' if "Bottle" in acquired_items }}" /></td>
|
||||
<td><img src="{{ icons["Cane of Somaria"] }}" class="{{ 'acquired' if "Cane of Somaria" in acquired_items }}" /></td>
|
||||
<td><img src="{{ icons["Cane of Byrna"] }}" class="{{ 'acquired' if "Cane of Byrna" in acquired_items }}" /></td>
|
||||
<td><img src="{{ icons["Cape"] }}" class="{{ 'acquired' if "Cape" in acquired_items }}" /></td>
|
||||
<td><img src="{{ icons["Magic Mirror"] }}" class="{{ 'acquired' if "Magic Mirror" in acquired_items }}" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="{{ icons["Pegasus Boots"] }}" class="{{ 'acquired' if "Pegasus Boots" in acquired_items }}" /></td>
|
||||
<td><img src="{{ icons[glove_icon] }}" class="{{ 'acquired' if glove_acquired }}" /></td>
|
||||
<td><img src="{{ icons["Flippers"] }}" class="{{ 'acquired' if "Flippers" in acquired_items }}" /></td>
|
||||
<td><img src="{{ icons["Moon Pearl"] }}" class="{{ 'acquired' if "Moon Pearl" in acquired_items }}" /></td>
|
||||
<td><img src="{{ icons["Mushroom"] }}" class="{{ 'acquired' if "Mushroom" in acquired_items }}" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="{{ icons[sword_icon] }}" class="{{ 'acquired' if sword_acquired }}" /></td>
|
||||
<td><img src="{{ icons[shield_icon] }}" class="{{ 'acquired' if shield_acquired }}" /></td>
|
||||
<td><img src="{{ icons[mail_icon] }}" class="acquired" /></td>
|
||||
<td><img src="{{ icons["Shovel"] }}" class="{{ 'acquired' if "Shovel" in acquired_items }}" /></td>
|
||||
<td><img src="{{ icons["Triforce"] }}" class="{{ 'acquired' if "Triforce" in acquired_items }}" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
<table id="location-table">
|
||||
<tr>
|
||||
<th></th>
|
||||
<th class="counter"><img src="{{ icons["Chest"] }}" /></th>
|
||||
{% if key_locations and "Universal" not in key_locations %}
|
||||
<th class="counter"><img src="{{ icons["Small Key"] }}" /></th>
|
||||
{% endif %}
|
||||
{% if big_key_locations %}
|
||||
<th><img src="{{ icons["Big Key"] }}" /></th>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% for area in sp_areas %}
|
||||
<tr>
|
||||
<td>{{ area }}</td>
|
||||
<td class="counter">{{ checks_done[area] }} / {{ checks_in_area[area] }}</td>
|
||||
{% if key_locations and "Universal" not in key_locations %}
|
||||
<td class="counter">
|
||||
{{ inventory[small_key_ids[area]] if area in key_locations else '—' }}
|
||||
</td>
|
||||
{% endif %}
|
||||
{% if big_key_locations %}
|
||||
<td>
|
||||
{{ '✔' if area in big_key_locations and inventory[big_key_ids[area]] else ('—' if area not in big_key_locations else '') }}
|
||||
</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -7,6 +7,11 @@
|
|||
</head>
|
||||
|
||||
<body>
|
||||
{# TODO: Replace this with a proper wrapper for each tracker when developing TrackerAPI. #}
|
||||
<div style="margin-bottom: 0.5rem">
|
||||
<a href="{{ url_for("get_generic_game_tracker", tracker=room.tracker, tracked_team=team, tracked_player=player) }}">Switch To Generic Tracker</a>
|
||||
</div>
|
||||
|
||||
<div id="player-tracker-wrapper" data-tracker="{{ room.tracker|suuid }}">
|
||||
<table id="inventory-table">
|
||||
<tr class="column-headers">
|
|
@ -8,13 +8,18 @@
|
|||
</head>
|
||||
|
||||
<body>
|
||||
{# TODO: Replace this with a proper wrapper for each tracker when developing TrackerAPI. #}
|
||||
<div style="margin-bottom: 0.5rem">
|
||||
<a href="{{ url_for("get_generic_game_tracker", tracker=room.tracker, tracked_team=team, tracked_player=player) }}">Switch To Generic Tracker</a>
|
||||
</div>
|
||||
|
||||
<div id="player-tracker-wrapper" data-tracker="{{ room.tracker|suuid }}">
|
||||
<table id="inventory-table">
|
||||
<tr>
|
||||
<td><img src="{{ tools_url }}" class="{{ 'acquired' }}" title="Progressive Tools" /></td>
|
||||
<td><img src="{{ weapons_url }}" class="{{ 'acquired' }}" title="Progressive Weapons" /></td>
|
||||
<td><img src="{{ armor_url }}" class="{{ 'acquired' }}" title="Progressive Armor" /></td>
|
||||
<td><img src="{{ resource_crafting_url }}" class="{{ 'acquired' if 'Progressive Resource Crafting' in acquired_items }}"
|
||||
<td><img src="{{ resource_crafting_url }}" class="{{ 'acquired' if 'Progressive Resource Crafting' in acquired_items }}"
|
||||
title="Progressive Resource Crafting" /></td>
|
||||
<td><img src="{{ icons['Brewing Stand'] }}" class="{{ 'acquired' if 'Brewing' in acquired_items }}" title="Brewing" /></td>
|
||||
<td>
|
|
@ -0,0 +1,185 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>{{ player_name }}'s Tracker</title>
|
||||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='styles/ootTracker.css') }}"/>
|
||||
<script type="application/ecmascript" src="{{ url_for('static', filename='assets/ootTracker.js') }}"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
{# TODO: Replace this with a proper wrapper for each tracker when developing TrackerAPI. #}
|
||||
<div style="margin-bottom: 0.5rem">
|
||||
<a href="{{ url_for("get_generic_game_tracker", tracker=room.tracker, tracked_team=team, tracked_player=player) }}">Switch To Generic Tracker</a>
|
||||
</div>
|
||||
|
||||
<div id="player-tracker-wrapper" data-tracker="{{ room.tracker|suuid }}">
|
||||
<table id="inventory-table">
|
||||
<tr>
|
||||
<td><img src="{{ ocarina_url }}" class="{{ 'acquired' if 'Ocarina' in acquired_items }}" title="Ocarina" /></td>
|
||||
<td><img src="{{ icons['Bombs'] }}" class="{{ 'acquired' if 'Bomb Bag' in acquired_items }}" title="Bombs" /></td>
|
||||
<td><img src="{{ icons['Bow'] }}" class="{{ 'acquired' if 'Bow' in acquired_items }}" title="Fairy Bow" /></td>
|
||||
<td><img src="{{ icons['Fire Arrows'] }}" class="{{ 'acquired' if 'Fire Arrows' in acquired_items }}" title="Fire Arrows" /></td>
|
||||
<td><img src="{{ icons['Kokiri Sword'] }}" class="{{ 'acquired' if 'Kokiri Sword' in acquired_items }}" title="Kokiri Sword" /></td>
|
||||
<td><img src="{{ icons['Biggoron Sword'] }}" class="{{ 'acquired' if 'Biggoron Sword' in acquired_items }}" title="Biggoron's Sword" /></td>
|
||||
<td><img src="{{ icons['Mirror Shield'] }}" class="{{ 'acquired' if 'Mirror Shield' in acquired_items }}" title="Mirror Shield" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="{{ icons['Slingshot'] }}" class="{{ 'acquired' if 'Slingshot' in acquired_items }}" title="Slingshot" /></td>
|
||||
<td><img src="{{ icons['Bombchus'] }}" class="{{ 'acquired' if has_bombchus }}" title="Bombchus" /></td>
|
||||
<td>
|
||||
<div class="counted-item">
|
||||
<img src="{{ hookshot_url }}" class="{{ 'acquired' if 'Progressive Hookshot' in acquired_items }}" title="Progressive Hookshot" />
|
||||
<div class="item-count">{{ hookshot_length }}</div>
|
||||
</div>
|
||||
</td>
|
||||
<td><img src="{{ icons['Ice Arrows'] }}" class="{{ 'acquired' if 'Ice Arrows' in acquired_items }}" title="Ice Arrows" /></td>
|
||||
<td><img src="{{ strength_upgrade_url }}" class="{{ 'acquired' if 'Progressive Strength Upgrade' in acquired_items }}" title="Progressive Strength Upgrade" /></td>
|
||||
<td><img src="{{ icons['Goron Tunic'] }}" class="{{ 'acquired' if 'Goron Tunic' in acquired_items }}" title="Goron Tunic" /></td>
|
||||
<td><img src="{{ icons['Zora Tunic'] }}" class="{{ 'acquired' if 'Zora Tunic' in acquired_items }}" title="Zora Tunic" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="{{ icons['Boomerang'] }}" class="{{ 'acquired' if 'Boomerang' in acquired_items }}" title="Boomerang" /></td>
|
||||
<td><img src="{{ icons['Lens of Truth'] }}" class="{{ 'acquired' if 'Lens of Truth' in acquired_items }}" title="Lens of Truth" /></td>
|
||||
<td><img src="{{ icons['Megaton Hammer'] }}" class="{{ 'acquired' if 'Megaton Hammer' in acquired_items }}" title="Megaton Hammer" /></td>
|
||||
<td><img src="{{ icons['Light Arrows'] }}" class="{{ 'acquired' if 'Light Arrows' in acquired_items }}" title="Light Arrows" /></td>
|
||||
<td><img src="{{ scale_url }}" class="{{ 'acquired' if 'Progressive Scale' in acquired_items }}" title="Progressive Scale" /></td>
|
||||
<td><img src="{{ icons['Iron Boots'] }}" class="{{ 'acquired' if 'Iron Boots' in acquired_items }}" title="Iron Boots" /></td>
|
||||
<td><img src="{{ icons['Hover Boots'] }}" class="{{ 'acquired' if 'Hover Boots' in acquired_items }}" title="Hover Boots" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="counted-item">
|
||||
<img src="{{ bottle_url }}" class="{{ 'acquired' if bottle_count > 0 }}" title="Bottles" />
|
||||
<div class="item-count">{{ bottle_count if bottle_count > 0 else '' }}</div>
|
||||
</div>
|
||||
</td>
|
||||
<td><img src="{{ icons['Dins Fire'] }}" class="{{ 'acquired' if 'Dins Fire' in acquired_items }}" title="Din's Fire" /></td>
|
||||
<td><img src="{{ icons['Farores Wind'] }}" class="{{ 'acquired' if 'Farores Wind' in acquired_items }}" title="Farore's Wind" /></td>
|
||||
<td><img src="{{ icons['Nayrus Love'] }}" class="{{ 'acquired' if 'Nayrus Love' in acquired_items }}" title="Nayru's Love" /></td>
|
||||
<td>
|
||||
<div class="counted-item">
|
||||
<img src="{{ wallet_url }}" class="{{ 'acquired' if 'Progressive Wallet' in acquired_items }}" title="Progressive Wallet" />
|
||||
<div class="item-count">{{ wallet_size }}</div>
|
||||
</div>
|
||||
</td>
|
||||
<td><img src="{{ magic_meter_url }}" class="{{ 'acquired' if 'Magic Meter' in acquired_items }}" title="Magic Meter" /></td>
|
||||
<td><img src="{{ icons['Gerudo Membership Card'] }}" class="{{ 'acquired' if 'Gerudo Membership Card' in acquired_items }}" title="Gerudo Membership Card" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="counted-item">
|
||||
<img src="{{ icons['Zeldas Lullaby'] }}" class="{{ 'acquired' if 'Zeldas Lullaby' in acquired_items }}" title="Zelda's Lullaby" id="lullaby"/>
|
||||
<div class="item-count">Zelda</div>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="counted-item">
|
||||
<img src="{{ icons['Eponas Song'] }}" class="{{ 'acquired' if 'Eponas Song' in acquired_items }}" title="Epona's Song" id="epona" />
|
||||
<div class="item-count">Epona</div>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="counted-item">
|
||||
<img src="{{ icons['Sarias Song'] }}" class="{{ 'acquired' if 'Sarias Song' in acquired_items }}" title="Saria's Song" id="saria"/>
|
||||
<div class="item-count">Saria</div>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="counted-item">
|
||||
<img src="{{ icons['Suns Song'] }}" class="{{ 'acquired' if 'Suns Song' in acquired_items }}" title="Sun's Song" id="sun"/>
|
||||
<div class="item-count">Sun</div>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="counted-item">
|
||||
<img src="{{ icons['Song of Time'] }}" class="{{ 'acquired' if 'Song of Time' in acquired_items }}" title="Song of Time" id="time"/>
|
||||
<div class="item-count">Time</div>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="counted-item">
|
||||
<img src="{{ icons['Song of Storms'] }}" class="{{ 'acquired' if 'Song of Storms' in acquired_items }}" title="Song of Storms" />
|
||||
<div class="item-count">Storms</div>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="counted-item">
|
||||
<img src="{{ icons['Gold Skulltula Token'] }}" class="{{ 'acquired' if token_count > 0 }}" title="Gold Skulltula Tokens" />
|
||||
<div class="item-count">{{ token_count }}</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="counted-item">
|
||||
<img src="{{ icons['Minuet of Forest'] }}" class="{{ 'acquired' if 'Minuet of Forest' in acquired_items }}" title="Minuet of Forest" />
|
||||
<div class="item-count">Min</div>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="counted-item">
|
||||
<img src="{{ icons['Bolero of Fire'] }}" class="{{ 'acquired' if 'Bolero of Fire' in acquired_items }}" title="Bolero of Fire" />
|
||||
<div class="item-count">Bol</div>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="counted-item">
|
||||
<img src="{{ icons['Serenade of Water'] }}" class="{{ 'acquired' if 'Serenade of Water' in acquired_items }}" title="Serenade of Water" />
|
||||
<div class="item-count">Ser</div>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="counted-item">
|
||||
<img src="{{ icons['Requiem of Spirit'] }}" class="{{ 'acquired' if 'Requiem of Spirit' in acquired_items }}" title="Requiem of Spirit" />
|
||||
<div class="item-count">Req</div>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="counted-item">
|
||||
<img src="{{ icons['Nocturne of Shadow'] }}" class="{{ 'acquired' if 'Nocturne of Shadow' in acquired_items }}" title="Nocturne of Shadow" />
|
||||
<div class="item-count">Noc</div>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="counted-item">
|
||||
<img src="{{ icons['Prelude of Light'] }}" class="{{ 'acquired' if 'Prelude of Light' in acquired_items }}" title="Prelude of Light" />
|
||||
<div class="item-count">Pre</div>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="counted-item">
|
||||
<img src="{{ icons['Triforce'] if game_finished else icons['Triforce Piece'] }}" class="{{ 'acquired' if game_finished or piece_count > 0 }}" title="{{ 'Triforce' if game_finished else 'Triforce Pieces' }}" id=triforce />
|
||||
<div class="item-count">{{ piece_count if piece_count > 0 else '' }}</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table id="location-table">
|
||||
<tr>
|
||||
<td></td>
|
||||
<td><img src="{{ icons['Small Key'] }}" title="Small Keys" /></td>
|
||||
<td><img src="{{ icons['Boss Key'] }}" title="Boss Key" /></td>
|
||||
<td class="right-align">Items</td>
|
||||
</tr>
|
||||
{% for area in checks_done %}
|
||||
<tr class="location-category" id="{{area}}-header">
|
||||
<td>{{ area }} {{'▼' if area != 'Total'}}</td>
|
||||
<td class="smallkeys">{{ small_key_counts.get(area, '-') }}</td>
|
||||
<td class="bosskeys">{{ boss_key_counts.get(area, '-') }}</td>
|
||||
<td class="counter">{{ checks_done[area] }} / {{ checks_in_area[area] }}</td>
|
||||
</tr>
|
||||
<tbody class="locations hide" id="{{area}}">
|
||||
{% for location in location_info[area] %}
|
||||
<tr>
|
||||
<td class="location-name">{{ location }}</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td class="counter">{{ '✔' if location_info[area][location] else '' }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -8,6 +8,11 @@
|
|||
</head>
|
||||
|
||||
<body>
|
||||
{# TODO: Replace this with a proper wrapper for each tracker when developing TrackerAPI. #}
|
||||
<div style="margin-bottom: 0.5rem">
|
||||
<a href="{{ url_for("get_generic_game_tracker", tracker=room.tracker, tracked_team=team, tracked_player=player) }}">Switch To Generic Tracker</a>
|
||||
</div>
|
||||
|
||||
<div id="player-tracker-wrapper" data-tracker="{{ room.tracker|suuid }}">
|
||||
<table id="inventory-table">
|
||||
<tr>
|
|
@ -7,6 +7,11 @@
|
|||
</head>
|
||||
|
||||
<body>
|
||||
{# TODO: Replace this with a proper wrapper for each tracker when developing TrackerAPI. #}
|
||||
<div style="margin-bottom: 0.5rem">
|
||||
<a href="{{ url_for("get_generic_game_tracker", tracker=room.tracker, tracked_team=team, tracked_player=player) }}">Switch To Generic Tracker</a>
|
||||
</div>
|
||||
|
||||
<div id="player-tracker-wrapper" data-tracker="{{ room.tracker|suuid }}">
|
||||
<table id="inventory-table">
|
||||
<tr>
|
|
@ -7,6 +7,11 @@
|
|||
</head>
|
||||
|
||||
<body>
|
||||
{# TODO: Replace this with a proper wrapper for each tracker when developing TrackerAPI. #}
|
||||
<div style="margin-bottom: 0.5rem">
|
||||
<a href="{{ url_for("get_generic_game_tracker", tracker=room.tracker, tracked_team=team, tracked_player=player) }}">Switch To Generic Tracker</a>
|
||||
</div>
|
||||
|
||||
<div id="player-tracker-wrapper" data-tracker="{{ room.tracker|suuid }}">
|
||||
<div id="inventory-table">
|
||||
<div class="table-row">
|
||||
|
@ -51,16 +56,16 @@
|
|||
<div class="C4"><img src="{{ icons['Security Keycard D'] }}" class="{{ 'acquired' if 'Security Keycard D' in acquired_items }}" title="Security Keycard D" /></div>
|
||||
{% if 'DownloadableItems' in options %}
|
||||
<div class="C5"><img src="{{ icons['Library Keycard V'] }}" class="{{ 'acquired' if 'Library Keycard V' in acquired_items }}" title="Library Keycard V" /></div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="table-row">
|
||||
{% if 'DownloadableItems' in options %}
|
||||
<div class="C1"><img src="{{ icons['Tablet'] }}" class="{{ 'acquired' if 'Tablet' in acquired_items }}" title="Tablet" /></div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<div class="C2"><img src="{{ icons['Elevator Keycard'] }}" class="{{ 'acquired' if 'Elevator Keycard' in acquired_items }}" title="Elevator Keycard" /></div>
|
||||
{% if 'EyeSpy' in options %}
|
||||
<div class="C3"><img src="{{ icons['Oculus Ring'] }}" class="{{ 'acquired' if 'Oculus Ring' in acquired_items }}" title="Oculus Ring" /></div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<div class="C4"><img src="{{ icons['Water Mask'] }}" class="{{ 'acquired' if 'Water Mask' in acquired_items }}" title="Water Mask" /></div>
|
||||
<div class="C5"><img src="{{ icons['Gas Mask'] }}" class="{{ 'acquired' if 'Gas Mask' in acquired_items }}" title="Gas Mask" /></div>
|
||||
</div>
|
File diff suppressed because it is too large
Load Diff
|
@ -1,43 +1,40 @@
|
|||
import importlib
|
||||
import os
|
||||
import sys
|
||||
import typing
|
||||
import warnings
|
||||
import zipimport
|
||||
from typing import Dict, List, NamedTuple, TypedDict
|
||||
|
||||
from Utils import user_path, local_path
|
||||
from Utils import local_path, user_path
|
||||
|
||||
local_folder = os.path.dirname(__file__)
|
||||
user_folder = user_path("worlds") if user_path() != local_path() else None
|
||||
|
||||
__all__ = (
|
||||
"lookup_any_item_id_to_name",
|
||||
"lookup_any_location_id_to_name",
|
||||
__all__ = {
|
||||
"network_data_package",
|
||||
"AutoWorldRegister",
|
||||
"world_sources",
|
||||
"local_folder",
|
||||
"user_folder",
|
||||
)
|
||||
"GamesPackage",
|
||||
"DataPackage",
|
||||
}
|
||||
|
||||
|
||||
class GamesData(typing.TypedDict):
|
||||
item_name_groups: typing.Dict[str, typing.List[str]]
|
||||
item_name_to_id: typing.Dict[str, int]
|
||||
location_name_groups: typing.Dict[str, typing.List[str]]
|
||||
location_name_to_id: typing.Dict[str, int]
|
||||
version: int
|
||||
|
||||
|
||||
class GamesPackage(GamesData, total=False):
|
||||
class GamesPackage(TypedDict, total=False):
|
||||
item_name_groups: Dict[str, List[str]]
|
||||
item_name_to_id: Dict[str, int]
|
||||
location_name_groups: Dict[str, List[str]]
|
||||
location_name_to_id: Dict[str, int]
|
||||
checksum: str
|
||||
version: int # TODO: Remove support after per game data packages API change.
|
||||
|
||||
|
||||
class DataPackage(typing.TypedDict):
|
||||
games: typing.Dict[str, GamesPackage]
|
||||
class DataPackage(TypedDict):
|
||||
games: Dict[str, GamesPackage]
|
||||
|
||||
|
||||
class WorldSource(typing.NamedTuple):
|
||||
class WorldSource(NamedTuple):
|
||||
path: str # typically relative path from this module
|
||||
is_zip: bool = False
|
||||
relative: bool = True # relative to regular world import folder
|
||||
|
@ -88,7 +85,7 @@ class WorldSource(typing.NamedTuple):
|
|||
|
||||
|
||||
# find potential world containers, currently folders and zip-importable .apworld's
|
||||
world_sources: typing.List[WorldSource] = []
|
||||
world_sources: List[WorldSource] = []
|
||||
for folder in (folder for folder in (user_folder, local_folder) if folder):
|
||||
relative = folder == local_folder
|
||||
for entry in os.scandir(folder):
|
||||
|
@ -105,25 +102,9 @@ world_sources.sort()
|
|||
for world_source in world_sources:
|
||||
world_source.load()
|
||||
|
||||
lookup_any_item_id_to_name = {}
|
||||
lookup_any_location_id_to_name = {}
|
||||
games: typing.Dict[str, GamesPackage] = {}
|
||||
|
||||
from .AutoWorld import AutoWorldRegister # noqa: E402
|
||||
|
||||
# Build the data package for each game.
|
||||
for world_name, world in AutoWorldRegister.world_types.items():
|
||||
games[world_name] = world.get_data_package_data()
|
||||
lookup_any_item_id_to_name.update(world.item_id_to_name)
|
||||
lookup_any_location_id_to_name.update(world.location_id_to_name)
|
||||
from .AutoWorld import AutoWorldRegister
|
||||
|
||||
network_data_package: DataPackage = {
|
||||
"games": games,
|
||||
"games": {world_name: world.get_data_package_data() for world_name, world in AutoWorldRegister.world_types.items()},
|
||||
}
|
||||
|
||||
# Set entire datapackage to version 0 if any of them are set to 0
|
||||
if any(not world.data_version for world in AutoWorldRegister.world_types.values()):
|
||||
import logging
|
||||
|
||||
logging.warning(f"Datapackage is in custom mode. Custom Worlds: "
|
||||
f"{[world for world in AutoWorldRegister.world_types.values() if not world.data_version]}")
|
||||
|
|
Loading…
Reference in New Issue