From e7e7426da133d3b1fbd6e97b5fb039e0f0ae68e5 Mon Sep 17 00:00:00 2001 From: Hamcha Date: Fri, 22 Nov 2019 11:47:27 +0100 Subject: [PATCH] More work on cube html --- cmd/cube-dev.ts | 90 +++++++++++++++++++++++++++++++++++++++++----- lib/utils.ts | 38 ++++++++++++++++++++ templates/cube.ejs | 77 +++++++++++++++++++++++++++++++-------- 3 files changed, 182 insertions(+), 23 deletions(-) diff --git a/cmd/cube-dev.ts b/cmd/cube-dev.ts index 911bade..3865e58 100644 --- a/cmd/cube-dev.ts +++ b/cmd/cube-dev.ts @@ -2,11 +2,23 @@ import * as ejs from "ejs"; import { existsSync } from "fs"; import { createServer } from "http"; -import { Article, asyncLoadJSON, CardItem, leanArticle, leanCard, MCMDB, onlyUnique } from "../lib"; +import { + Article, + asyncLoadJSON, + CardItem, + dictMap, + filterDict, + leanArticle, + leanCard, + MCMDB, + onlyUnique, + spanBy, +} from "../lib"; const colorNames = { CL: "Colorless", MC: "Multicolor", + L: "Land", W: "White", U: "Blue", B: "Black", @@ -35,13 +47,14 @@ const colorNames = { }; const columns: Record boolean> = { - W: c => colorid(c.colorIdentity) == "W", - U: c => colorid(c.colorIdentity) == "U", - B: c => colorid(c.colorIdentity) == "B", - R: c => colorid(c.colorIdentity) == "R", - G: c => colorid(c.colorIdentity) == "G", - MC: c => c.colorIdentity.length > 0, - CL: c => colorid(c.colorIdentity) == "CL" + W: c => c.types[0] != "Land" && colorid(c.colorIdentity) == "W", + U: c => c.types[0] != "Land" && colorid(c.colorIdentity) == "U", + B: c => c.types[0] != "Land" && colorid(c.colorIdentity) == "B", + R: c => c.types[0] != "Land" && colorid(c.colorIdentity) == "R", + G: c => c.types[0] != "Land" && colorid(c.colorIdentity) == "G", + MC: c => c.types[0] != "Land" && c.colorIdentity.length > 1, + CL: c => c.types[0] != "Land" && colorid(c.colorIdentity) == "CL", + L: c => c.types[0] == "Land" }; function wubrg(a: string, b: string) { @@ -58,6 +71,53 @@ function colorid(colors: string[]): string { return colors.sort(wubrg).join(""); } +function prettyColor(color: string) { + if (color in colorNames) { + return colorNames[color]; + } + return color; +} + +const allTypes = [ + "Creature", + "Planeswalker", + "Instant", + "Sorcery", + "Artifact", + "Enchantment" +]; +function typeSort(a: string, b: string): number { + const indexA = allTypes.indexOf(a); + const indexB = allTypes.indexOf(b); + return indexA - indexB; +} + +function abcSort(a: string, b: string): number { + if (a > b) { + return 1; + } + if (b > a) { + return -1; + } + return 0; +} + +// This would be properly typed but as of currently TS does not allow circular references for types +function deepSum(dict: any): number { + if (Array.isArray(dict)) { + return dict.length; + } + let total = 0; + for (let key in dict) { + if (Array.isArray(dict[key])) { + total += dict[key].length; + } else { + total += deepSum(dict[key]); + } + } + return total; +} + async function run() { if (process.argv.length < 3) { console.error("Usage: yarn fetch "); @@ -96,15 +156,27 @@ async function run() { ) .filter(onlyUnique); + // Filter by colors and cmc (nested) + let colorcards = filterDict(valid, columns); + let cmccards = dictMap(colorcards, (cards, col) => + dictMap( + spanBy(cards, c => + col == "MC" || col == "L" ? colorid(c.colorIdentity) : c.types[0] + ), + typed => spanBy(typed, c => c.convertedManaCost) + ) + ); const server = createServer(async (req, res) => { const template = await ejs.renderFile("templates/cube.ejs", { user: uid, cards: valid, + cmccards, columns, - utils: { wubrg, colorNames, colorid } + utils: { wubrg, prettyColor, colorid, deepSum, typeSort, abcSort } }); res.end(template); }); + server.on("clientError", (err, socket) => { socket.end("HTTP/1.1 400 Bad Request\r\n\r\n"); }); diff --git a/lib/utils.ts b/lib/utils.ts index c6d30b8..0290b57 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -61,3 +61,41 @@ export function leanArticle(article: Article): LeanArticle { export function onlyUnique(value: CardItem, index: number, self: CardItem[]) { return self.findIndex(c => c.name == value.name) == index; } + +export function filterDict( + arr: T[], + list: Record boolean> +): Record { + let out: Record = Object.create(null); + for (const key in list) { + out[key] = arr.filter(list[key]); + } + return out; +} + +export function spanBy( + arr: T[], + spanFn: (i: T) => K +): Record { + let out: Record = Object.create(null); + arr.forEach(item => { + let key = spanFn(item); + if (key in out) { + out[key].push(item); + } else { + out[key] = [item]; + } + }); + return out; +} + +export function dictMap( + dict: Record, + mapFn: (i: A, k: K) => B +): Record { + let out: Record = Object.create(null); + for (let key in dict) { + out[key] = mapFn(dict[key], key); + } + return out; +} diff --git a/templates/cube.ejs b/templates/cube.ejs index 972306b..c8bdecc 100644 --- a/templates/cube.ejs +++ b/templates/cube.ejs @@ -10,7 +10,7 @@ main { background: white; - max-width: 920px; + max-width: 1220px; margin: 0 auto; padding: 20pt; } @@ -33,58 +33,107 @@ .color-section { flex: 1; + margin: 5px; } .color-section header { text-align: center; } - .color-W header { + .color-W header.color-header { background-color: #fff6eb; } - .color-U header { + .color-U header.color-header { background-color: #49b0fd; } - .color-B header { + .color-B header.color-header { background-color: #666; color: white; } - .color-R header { + .color-R header.color-header { background-color: #ff6868; } - .color-G header { + .color-G header.color-header { background-color: #78ce59; } - .color-MC header { + .color-MC header.color-header { background: linear-gradient(to left, #f3ff6b, #ffb019); } - .color-CL header { + .color-CL header.color-header { background-color: #d2d2d2; } + + .color-L header.color-header { + background-color: #eeb445; + } + + .type-section { + border: 1px solid #aaa; + border-radius: 5px; + font-size: 10pt; + margin: 5px 0; + } + + .type-section header.type-header { + font-size: 12pt; + font-weight: bold; + border-bottom: 1px solid #ccc; + padding: 5px; + } + + ul { + margin: 0; + padding: 0; + list-style-type: none; + border-bottom: 1px solid #ccc; + } + + ul li { + padding: 5px; + } + + ul:last-child { + border-bottom: none; + }
-

Junk rare cube

+

Junk rare cube (<%=cards.length%> cards)

Using cards from <%= user %>

- <% for (const column in columns) { %> -
-
-

<%=utils.colorNames[column]%>

+ <% Object.entries(cmccards).forEach(([color, colorcards]) => { %> +
+
+

<%=utils.prettyColor(color)%> (<%=utils.deepSum(colorcards)%>)

+ <% Object.entries(colorcards).sort((a, b) => color == "MC" || color == "L" ? utils.abcSort(a[0], b[0]) : utils.typeSort(a[0], b[0])).forEach(([type, typecards]) => { %> +
+
<%= color == "MC" || color == "L" ? utils.prettyColor(type) : type %> + (<%=utils.deepSum(typecards)%>)
+
+ <% Object.entries(typecards).forEach(([cmc, finalcards]) => { %> +
    + <% finalcards.forEach(card => { %> +
  • <%= card.name %>
  • + <% }); %> +
+ <% }); %> +
+
+ <% }); %>
- <% } %> + <% }); %>