Files
two-stands-cg/table.html
T
2026-08-02 12:57:50 +03:00

429 lines
14 KiB
HTML

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=1920, initial-scale=1">
<title>Vadim vs Nikita — Transfer Opinions</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
<style>
@font-face { font-family: 'ONY One'; src: local('ONY One Regular'), url('file:///home/itten/.local/share/fonts/ONYOne-Regular.otf') format('opentype'); font-weight: 400; }
@font-face { font-family: 'ONY One'; src: local('ONY One Medium'), url('file:///home/itten/.local/share/fonts/ONYOne-Medium.otf') format('opentype'); font-weight: 500; }
@font-face { font-family: 'ONY One'; src: local('ONY One Bold'), url('file:///home/itten/.local/share/fonts/ONYOne-Bold.otf') format('opentype'); font-weight: 700; }
:root {
--bg: #222524;
--upvote: #91FF55;
--downvote: #F8F700;
--neutral: #919292;
--white: #FFFFFF;
--black: #000000;
--row-alt: #2A2D2C;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
html, body {
width: 1920px;
height: 1080px;
background: var(--bg);
overflow: hidden;
font-family: 'ONY One', 'Arial Narrow', sans-serif;
-webkit-font-smoothing: antialiased;
}
.frame {
position: relative;
width: 1920px;
height: 1080px;
background: var(--bg);
display: flex;
align-items: center;
justify-content: center;
}
/* ==================================================================
Table container — max 1730x880, centered in frame
================================================================== */
.table-wrapper {
width: 1730px;
max-height: 880px;
position: relative;
overflow: hidden;
background: var(--bg);
}
/* Header row */
.table-header {
display: grid;
grid-template-columns: 1fr 2px 1fr 2px 1fr;
align-items: center;
border-bottom: 3px solid var(--white);
padding-bottom: 16px;
margin-bottom: 8px;
}
.header-cell {
font-size: 42px;
font-weight: 700;
text-transform: uppercase;
text-align: center;
color: var(--white);
letter-spacing: 2px;
}
.header-center {
font-size: 24px;
font-weight: 500;
color: var(--neutral);
text-align: center;
}
.header-divider {
height: 36px;
border-left: 2px solid rgba(255, 255, 255, 0.1);
justify-self: center;
}
/* ==================================================================
Pages — up to 3 pages with smooth slide transition
================================================================== */
.pages-track {
display: flex;
width: 300%;
transition: transform 0.7s cubic-bezier(0.45, 0, 0.15, 1);
}
.pages-track.page-2 { transform: translateX(-33.333%); }
.pages-track.page-3 { transform: translateX(-66.666%); }
.page {
width: 33.333%;
flex-shrink: 0;
}
/* ==================================================================
Table rows
================================================================== */
.table-rows {
display: flex;
flex-direction: column;
}
.table-row {
display: grid;
grid-template-columns: 1fr 2px 1fr 2px 1fr;
align-items: center;
height: 78px;
transition: background 0.2s;
}
.table-row:nth-child(even) {
background: var(--row-alt);
}
.row-player {
font-size: 32px;
font-weight: 500;
color: var(--white);
text-align: center;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
padding: 0 20px;
display: flex;
align-items: center;
justify-content: center;
gap: 12px;
}
.row-logo {
width: 36px;
height: 36px;
object-fit: contain;
flex-shrink: 0;
}
.row-divider {
height: 36px;
border-left: 2px solid rgba(255, 255, 255, 0.1);
justify-self: center;
}
/* Opinion cells */
.opinion {
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
height: 100%;
}
.opinion-icon {
font-size: 42px;
}
/* Upvote */
.opinion.upvote {
color: var(--upvote);
}
/* Downvote */
.opinion.downvote {
color: var(--downvote);
}
/* Neutral */
.opinion.neutral {
color: var(--neutral);
}
/* ==================================================================
Paging indicator + counter
================================================================== */
.paging-bar {
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
display: flex;
gap: 10px;
align-items: center;
}
.page-dot {
width: 12px;
height: 12px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.2);
transition: background 0.3s;
}
.page-dot.active {
background: var(--white);
}
.page-counter {
font-size: 16px;
color: var(--neutral);
margin-left: 12px;
}
/* ==================================================================
Operator hint (dev)
================================================================== */
.op-hint {
position: absolute;
top: 10px;
right: 20px;
font-size: 14px;
color: var(--neutral);
opacity: 0.3;
pointer-events: none;
}
</style>
</head>
<body>
<div class="frame">
<div class="table-wrapper" id="tableWrapper">
<!-- Header -->
<div class="table-header">
<div class="header-cell">ВАДИМ</div>
<div class="header-divider"></div>
<div class="header-center">VS</div>
<div class="header-divider"></div>
<div class="header-cell">НИКИТА</div>
</div>
<!-- Pages -->
<div class="pages-track" id="pagesTrack">
<div class="page" id="page1">
<div class="table-rows" id="rows1"></div>
</div>
<div class="page" id="page2">
<div class="table-rows" id="rows2"></div>
</div>
<div class="page" id="page3">
<div class="table-rows" id="rows3"></div>
</div>
</div>
</div>
<div class="op-hint">Enter next page &nbsp; R reset</div>
</div>
<script>
/**
* Opinions data — EDIT MANUALLY.
*
* Each entry uses the player name from the CSV.
* opinion values: "upvote" | "downvote" | "neutral"
*
* If a player is not listed here, both default to "neutral".
*/
var OPINIONS = {
// ── Page 1 ──────────────────────────────────────────────
"Морган Роджерс": { vadim: "upvote", nikita: "downvote" },
"Эллиот Андерсон": { vadim: "upvote", nikita: "upvote" },
"Сандро Тонали": { vadim: "neutral", nikita: "upvote" },
"Матеус Фернандес": { vadim: "downvote", nikita: "neutral" },
"Энтони Гордон": { vadim: "upvote", nikita: "upvote" },
"Гонсало Рамуш": { vadim: "downvote", nikita: "downvote" },
"Самервилл": { vadim: "neutral", nikita: "downvote" },
"Жереми Жаке": { vadim: "upvote", nikita: "neutral" },
"Ван Хекке": { vadim: "upvote", nikita: "downvote" },
"Йохан Манзамби": { vadim: "neutral", nikita: "upvote" },
"Лука Вушкович": { vadim: "downvote", nikita: "downvote" },
"Марко Палестра": { vadim: "upvote", nikita: "upvote" },
"Андре Сантос": { vadim: "neutral", nikita: "neutral" },
"Марк Кукурелья": { vadim: "upvote", nikita: "downvote" },
// ── Page 2 ──────────────────────────────────────────────
"Натаниэль Браун": { vadim: "downvote", nikita: "neutral" },
"Исмаэль Сайбари": { vadim: "upvote", nikita: "upvote" },
"Ибрагим Конате": { vadim: "upvote", nikita: "upvote" },
"Опенда": { vadim: "downvote", nikita: "downvote" },
"Тилеманс": { vadim: "neutral", nikita: "upvote" },
"Христос Цолис": { vadim: "upvote", nikita: "neutral" },
"Кан Ли": { vadim: "downvote", nikita: "downvote" },
"Карим Адейеми": { vadim: "upvote", nikita: "upvote" },
"Гарначо": { vadim: "upvote", nikita: "downvote" },
"Александар Станкович": { vadim: "neutral", nikita: "upvote" },
"Думфрис": { vadim: "upvote", nikita: "upvote" },
"Гримальдо": { vadim: "downvote", nikita: "neutral" },
"Бернардо Силва": { vadim: "upvote", nikita: "upvote" },
"Оскар Мингеза": { vadim: "neutral", nikita: "downvote" },
"Аканжи": { vadim: "upvote", nikita: "neutral" },
"Альваро Мората": { vadim: "downvote", nikita: "downvote" },
};
// ── Icons ────────────────────────────────────────────────
var ICONS = {
upvote: '<i class="fa-solid fa-thumbs-up opinion-icon"></i>',
downvote: '<i class="fa-solid fa-thumbs-down opinion-icon"></i>',
neutral: '<i class="fa-solid fa-minus opinion-icon"></i>',
};
// ── Config ───────────────────────────────────────────────
var ROWS_PER_PAGE = 10;
var CSV_URL = "assets/transfers-list.csv";
var players = [];
var currentPage = 1;
var totalPages = 1;
// ── Parse CSV (simple parser, handles quoted fields) ─────
function parseCSV(text) {
var lines = text.trim().split(/\r?\n/);
var header = lines[0].split(",").map(function (h) {
return h.trim();
});
var playerIdx = header.indexOf("Player");
if (playerIdx === -1) playerIdx = 0;
var clubIdx = header.indexOf("Club");
if (clubIdx === -1) clubIdx = 1;
var logoIdx = header.indexOf("Logo");
if (logoIdx === -1) logoIdx = 4;
var result = [];
for (var i = 1; i < lines.length; i++) {
var line = lines[i].trim();
if (!line) continue;
// simple parse: split by comma but respect quotes
var fields = [];
var cur = "";
var inQ = false;
for (var j = 0; j < line.length; j++) {
var ch = line[j];
if (ch === '"') { inQ = !inQ; }
else if (ch === ',' && !inQ) { fields.push(cur.trim()); cur = ""; }
else { cur += ch; }
}
fields.push(cur.trim());
if (fields[playerIdx]) result.push({
name: fields[playerIdx],
club: fields[clubIdx] || "",
logo: fields[logoIdx] || "",
});
}
return result;
}
// ── Build row HTML ───────────────────────────────────────
function opinionCell(who, player) {
var op = "neutral";
var entry = OPINIONS[player.name];
if (entry && entry[who]) op = entry[who];
return '<div class="opinion ' + op + '">' + ICONS[op] + '</div>';
}
function buildRow(player) {
var label = player.name;
if (player.logo) label = '<img class="row-logo" src="clubs-logo/' + player.logo + '" alt="">' + label;
return '<div class="table-row">' +
opinionCell("vadim", player) +
'<div class="row-divider"></div>' +
'<div class="row-player">' + label + '</div>' +
'<div class="row-divider"></div>' +
opinionCell("nikita", player) +
'</div>';
}
// ── Render ───────────────────────────────────────────────
function render() {
var pages = [
document.getElementById("rows1"),
document.getElementById("rows2"),
document.getElementById("rows3"),
];
var count = 0;
for (var p = 0; p < 3; p++) {
var slice = players.slice(p * ROWS_PER_PAGE, (p + 1) * ROWS_PER_PAGE);
if (slice.length > 0) {
pages[p].innerHTML = slice.map(buildRow).join("");
count = p + 1;
} else {
pages[p].innerHTML = "";
}
}
totalPages = count;
updateCounter();
}
function updateCounter() {
console.log("Page " + currentPage + " / " + totalPages);
}
function goToPage(n) {
if (totalPages > 1 && n > totalPages) n = 1;
if (n < 1 || n > totalPages) return;
currentPage = n;
var track = document.getElementById("pagesTrack");
track.classList.toggle("page-2", currentPage === 2);
track.classList.toggle("page-3", currentPage === 3);
updateCounter();
}
// ── Keys ─────────────────────────────────────────────────
document.addEventListener("keydown", function (e) {
switch (e.key) {
case "Enter": e.preventDefault(); goToPage(currentPage + 1); break;
case "r": case "R": goToPage(1); break;
}
});
// ── Init ────────────────────────────────────────────────
fetch(CSV_URL)
.then(function (r) { return r.text(); })
.then(function (text) {
players = parseCSV(text);
render();
console.log("Table loaded: " + players.length + " players, " + totalPages + " pages");
})
.catch(function (e) {
console.error("Failed to load CSV", e);
});
</script>
</body>
</html>