<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="en">
	<head th:replace="layout.html :: head(title='Caches')">
		<title>Caches - OpenRS2 Archive</title>
		<link rel="stylesheet" href="/webjars/bootstrap/css/bootstrap.min.css" />
		<link rel="stylesheet" href="/static/css/openrs2.css" />
		<script src="/webjars/jquery/jquery.min.js" defer></script>
		<script src="/webjars/bootstrap/js/bootstrap.bundle.min.js" defer></script>
	</head>
	<body>
		<nav th:replace="layout.html :: nav(active='caches')"></nav>
		<main class="container">
			<h1>Caches</h1>
			<div class="table-responsive">
				<table class="table table-striped table-bordered table-hover" data-toggle="table" data-filter-control="true" data-sticky-header="true" data-custom-sort="customSort">
					<thead class="table-dark">
						<tr>
							<th data-field="game" data-filter-control="select">Game</th>
							<th data-field="environment" data-filter-control="select">Env</th>
							<th data-field="language" data-filter-control="select">Lang</th>
							<th data-field="builds" data-filter-control="input" data-sortable="true">Build(s)</th>
							<th data-field="timestamp" data-sortable="true">Timestamp</th>
							<th data-field="sources" data-filter-control="input">Source(s)</th>
							<th>Archives</th>
							<th>Groups</th>
							<th>Keys<sup><a href="#empty-locs">1</a></sup></th>
							<th>Size<sup><a href="#size">2</a></sup></th>
							<th>Links</th>
						</tr>
					</thead>
					<tbody>
						<!--/*@thymesVar id="caches" type="java.util.List<org.openrs2.archive.cache.CacheExporter.Cache>"*/-->
						<tr th:each="cache : ${caches}">
							<td th:text="${cache.game}">runescape</td>
							<td th:text="${cache.environment}">live</td>
							<td th:text="${cache.language}">en</td>
							<td class="text-end">
								<span th:each="build, it : ${cache.builds}" th:remove="tag">
									<span th:text="${build}">550</span>
									<br th:remove="${it.last}? 'all' : 'none'" />
								</span>
							</td>
							<td>
								<span th:if="${cache.timestamp}" th:remove="tag">
									<span th:text="${#temporals.format(cache.timestamp, 'yyyy-MM-dd')}"></span>
									<br />
									<span th:text="${#temporals.format(cache.timestamp, 'HH:mm:ss')}"></span>
								</span>
							</td>
							<td th:text="${#strings.setJoin(cache.sources, ', ')}"></td>
							<td th:classappend="${cache.stats}? (${cache.stats.allIndexesValid}? 'table-success' : 'table-danger')"
							    class="text-end">
								<span
									th:text="${cache.stats}? ${cache.stats.validIndexes} + '&nbsp;/&nbsp;' + ${cache.stats.indexes} : 'Calculating...'"></span>
								<br />
								<span
									th:text="${cache.stats}? '(' + ${#numbers.formatPercent(cache.stats.validIndexesFraction, 1, 2)} + ')'"></span>
							</td>
							<td th:classappend="${cache.stats}? (${cache.stats.allGroupsValid}? 'table-success' : 'table-warning')"
							    class="text-end">
								<span
									th:text="${cache.stats}? ${#numbers.formatInteger(cache.stats.validGroups, 1, 'COMMA')} + '&nbsp;/&nbsp;' + ${#numbers.formatInteger(cache.stats.groups, 1, 'COMMA')} : 'Calculating...'"></span>
								<br />
								<span
									th:text="${cache.stats}? '(' + ${#numbers.formatPercent(cache.stats.validGroupsFraction, 1, 2)} + ')'"></span>
							</td>
							<td th:classappend="${cache.stats}? (${cache.stats.allKeysValid}? 'table-success' : 'table-warning')"
							    class="text-end">
								<span
									th:text="${cache.stats}? ${#numbers.formatInteger(cache.stats.validKeys, 1, 'COMMA')} + '&nbsp;/&nbsp;' + ${#numbers.formatInteger(cache.stats.keys, 1, 'COMMA')} : 'Calculating...'"></span>
								<br />
								<span
									th:text="${cache.stats}? '(' + ${#numbers.formatPercent(cache.stats.validKeysFraction, 1, 2)} + ')'"></span>
							</td>
							<!--/*@thymesVar id="#byteunits" type="org.openrs2.archive.web.ByteUnits"*/-->
							<td th:text="${cache.stats}? ${#byteunits.format(cache.stats.size)} : 'Calculating...'"
							    class="text-end">Calculating...
							</td>
							<td>
								<div class="btn-group">
									<div class="btn-group">
										<button type="button"
										        class="btn btn-primary btn-sm dropdown-toggle"
										        data-bs-toggle="dropdown">
											Download
										</button>
										<ul class="dropdown-menu">
											<li th:if="${cache.stats != null and cache.stats.diskStoreValid}"><a
												th:href="${'/caches/' + cache.scope + '/' + cache.id + '/disk.zip'}"
												class="dropdown-item">Cache (.dat2/.idx)</a></li>
											<li><a th:href="${'/caches/' + cache.scope + '/' + cache.id + '/flat-file.tar.gz'}"
											       class="dropdown-item">Cache (Flat file)</a></li>
											<li>
												<hr class="dropdown-divider" />
											</li>
											<li><a th:href="${'/caches/' + cache.scope + '/' + cache.id + '/keys.json'}"
											       class="dropdown-item">Keys (JSON)</a></li>
											<li><a th:href="${'/caches/' + cache.scope + '/' + cache.id + '/keys.zip'}"
											       class="dropdown-item">Keys (Text)</a></li>
											<li>
												<hr class="dropdown-divider" />
											</li>
											<li><a th:href="${'/caches/' + cache.scope + '/' + cache.id + '/map.png'}"
											       class="dropdown-item">Map</a></li>
										</ul>
									</div>
									<a th:href="${'/caches/' + cache.scope + '/' + cache.id}"
									   class="btn btn-secondary btn-sm">More</a>
								</div>
							</td>
						</tr>
					</tbody>
				</table>
			</div>
			<p>
				The total size of all caches in the archive is
				<strong th:text="${#byteunits.format(totalSize)}">0 B</strong>.
			</p>
			<p>
				<sup id="empty-locs">1</sup> Map squares in the middle of the
				sea are unreachable by normal players, making it impossible to
				obtain the keys for their loc groups. However, the loc groups
				for these map squares are empty. As XTEA does not hide the
				length of the compressed data, this service infers which
				encrypted loc groups are empty and includes them in the number
				of valid keys, regardless of whether the key is known or not.
				After downloading a cache from this service, a cache editor may
				be used to replace the empty encrypted loc groups with
				unencrypted replacements.
			</p>
			<p>
				<sup id="size">2</sup> Sizes are estimated based on the total
				compressed length of all groups in the cache. The native
				<code>.dat2</code>/<code>.idx</code> format has some overhead
				above this, but the <code>.zip</code> file generated by the
				archiving service will reduce the overhead, so the estimated
				size will roughly match the size of the <code>.zip</code> file.
			</p>
		</main>
	</body>
</html>
