Start work on cube page
This commit is contained in:
parent
429cd927c4
commit
f5c94268be
9 changed files with 340 additions and 10 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -3,3 +3,4 @@ node_modules
|
||||||
AllPrintings.json
|
AllPrintings.json
|
||||||
mcmCards.json
|
mcmCards.json
|
||||||
*-cards.json
|
*-cards.json
|
||||||
|
*-cube.html
|
114
cmd/cube-dev.ts
Normal file
114
cmd/cube-dev.ts
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
import * as ejs from "ejs";
|
||||||
|
import { existsSync } from "fs";
|
||||||
|
import { createServer } from "http";
|
||||||
|
|
||||||
|
import { Article, asyncLoadJSON, CardItem, leanArticle, leanCard, MCMDB, onlyUnique } from "../lib";
|
||||||
|
|
||||||
|
const colorNames = {
|
||||||
|
CL: "Colorless",
|
||||||
|
MC: "Multicolor",
|
||||||
|
W: "White",
|
||||||
|
U: "Blue",
|
||||||
|
B: "Black",
|
||||||
|
R: "Red",
|
||||||
|
G: "Green",
|
||||||
|
WU: "Azorius",
|
||||||
|
UB: "Dimir",
|
||||||
|
BR: "Rakdos",
|
||||||
|
RG: "Gruul",
|
||||||
|
WG: "Selesnya",
|
||||||
|
WB: "Orzhov",
|
||||||
|
UR: "Izzet",
|
||||||
|
BG: "Golgari",
|
||||||
|
WR: "Boros",
|
||||||
|
UG: "Simic",
|
||||||
|
WUG: "Bant",
|
||||||
|
WUB: "Esper",
|
||||||
|
UBR: "Grixis",
|
||||||
|
BRG: "Jund",
|
||||||
|
WRG: "Naya",
|
||||||
|
WBG: "Abzan",
|
||||||
|
WUR: "Jeskai",
|
||||||
|
UBG: "Sultai",
|
||||||
|
WBR: "Mardu",
|
||||||
|
URG: "Temur"
|
||||||
|
};
|
||||||
|
|
||||||
|
const columns: Record<string, (c: CardItem) => 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"
|
||||||
|
};
|
||||||
|
|
||||||
|
function wubrg(a: string, b: string) {
|
||||||
|
const order = ["W", "U", "B", "R", "G"];
|
||||||
|
const indexA = order.indexOf(a);
|
||||||
|
const indexB = order.indexOf(b);
|
||||||
|
return indexA - indexB;
|
||||||
|
}
|
||||||
|
|
||||||
|
function colorid(colors: string[]): string {
|
||||||
|
if (colors.length < 1) {
|
||||||
|
return "CL";
|
||||||
|
}
|
||||||
|
return colors.sort(wubrg).join("");
|
||||||
|
}
|
||||||
|
|
||||||
|
async function run() {
|
||||||
|
if (process.argv.length < 3) {
|
||||||
|
console.error("Usage: yarn fetch <uid>");
|
||||||
|
process.exit(1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const uid = process.argv[2];
|
||||||
|
const uidCards = `${uid}-cards.json`;
|
||||||
|
if (!existsSync("mcmCards.json")) {
|
||||||
|
console.error("Card db is missing! Run 'yarn convert-db' first.");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
if (!existsSync(uidCards)) {
|
||||||
|
console.error(`Could not find ${uidCards}! Run 'yarn fetch ${uid}' first.`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
let db = await asyncLoadJSON<MCMDB>("mcmCards.json");
|
||||||
|
let articles = await asyncLoadJSON<Article[]>(`${uid}-cards.json`);
|
||||||
|
|
||||||
|
let cards: CardItem[] = articles
|
||||||
|
.filter(art => art.idProduct in db)
|
||||||
|
.map(art => {
|
||||||
|
const card = db[art.idProduct];
|
||||||
|
return {
|
||||||
|
...leanArticle(art),
|
||||||
|
...leanCard(card)
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
let valid = cards
|
||||||
|
.filter(
|
||||||
|
c =>
|
||||||
|
(c.language == "Italian" || c.language == "English") &&
|
||||||
|
c.price <= 0.1 &&
|
||||||
|
(c.rarity == "rare" || c.rarity == "mythic")
|
||||||
|
)
|
||||||
|
.filter(onlyUnique);
|
||||||
|
|
||||||
|
const server = createServer(async (req, res) => {
|
||||||
|
const template = await ejs.renderFile("templates/cube.ejs", {
|
||||||
|
user: uid,
|
||||||
|
cards: valid,
|
||||||
|
columns,
|
||||||
|
utils: { wubrg, colorNames, colorid }
|
||||||
|
});
|
||||||
|
res.end(template);
|
||||||
|
});
|
||||||
|
server.on("clientError", (err, socket) => {
|
||||||
|
socket.end("HTTP/1.1 400 Bad Request\r\n\r\n");
|
||||||
|
});
|
||||||
|
server.listen(8000);
|
||||||
|
}
|
||||||
|
|
||||||
|
run();
|
101
cmd/cube.ts
101
cmd/cube.ts
|
@ -0,0 +1,101 @@
|
||||||
|
import * as ejs from "ejs";
|
||||||
|
import { existsSync, writeFile } from "fs";
|
||||||
|
|
||||||
|
import { Article, asyncLoadJSON, CardItem, leanArticle, leanCard, MCMDB, onlyUnique } from "../lib";
|
||||||
|
|
||||||
|
const colorNames = {
|
||||||
|
CL: "Colorless",
|
||||||
|
W: "White",
|
||||||
|
U: "Blue",
|
||||||
|
B: "Black",
|
||||||
|
R: "Red",
|
||||||
|
G: "Green",
|
||||||
|
WU: "Azorius",
|
||||||
|
UB: "Dimir",
|
||||||
|
BR: "Rakdos",
|
||||||
|
RG: "Gruul",
|
||||||
|
WG: "Selesnya",
|
||||||
|
WB: "Orzhov",
|
||||||
|
UR: "Izzet",
|
||||||
|
BG: "Golgari",
|
||||||
|
WR: "Boros",
|
||||||
|
UG: "Simic",
|
||||||
|
WUG: "Bant",
|
||||||
|
WUB: "Esper",
|
||||||
|
UBR: "Grixis",
|
||||||
|
BRG: "Jund",
|
||||||
|
WRG: "Naya",
|
||||||
|
WBG: "Abzan",
|
||||||
|
WUR: "Jeskai",
|
||||||
|
UBG: "Sultai",
|
||||||
|
WBR: "Mardu",
|
||||||
|
URG: "Temur"
|
||||||
|
};
|
||||||
|
|
||||||
|
function wubrg(a: string, b: string) {
|
||||||
|
const order = ["W", "U", "B", "R", "G"];
|
||||||
|
const indexA = order.indexOf(a);
|
||||||
|
const indexB = order.indexOf(b);
|
||||||
|
return indexA - indexB;
|
||||||
|
}
|
||||||
|
|
||||||
|
function colorid(colors: string[]): string {
|
||||||
|
if (colors.length < 1) {
|
||||||
|
return "CL";
|
||||||
|
}
|
||||||
|
return colors.sort(wubrg).join("");
|
||||||
|
}
|
||||||
|
|
||||||
|
async function run() {
|
||||||
|
if (process.argv.length < 3) {
|
||||||
|
console.error("Usage: yarn fetch <uid>");
|
||||||
|
process.exit(1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const uid = process.argv[2];
|
||||||
|
const uidCards = `${uid}-cards.json`;
|
||||||
|
if (!existsSync("mcmCards.json")) {
|
||||||
|
console.error("Card db is missing! Run 'yarn convert-db' first.");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
if (!existsSync(uidCards)) {
|
||||||
|
console.error(`Could not find ${uidCards}! Run 'yarn fetch ${uid}' first.`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
let db = await asyncLoadJSON<MCMDB>("mcmCards.json");
|
||||||
|
let articles = await asyncLoadJSON<Article[]>(`${uid}-cards.json`);
|
||||||
|
|
||||||
|
let cards: CardItem[] = articles
|
||||||
|
.filter(art => art.idProduct in db)
|
||||||
|
.map(art => {
|
||||||
|
const card = db[art.idProduct];
|
||||||
|
return {
|
||||||
|
...leanArticle(art),
|
||||||
|
...leanCard(card)
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
let valid = cards
|
||||||
|
.filter(
|
||||||
|
c =>
|
||||||
|
(c.language == "Italian" || c.language == "English") &&
|
||||||
|
c.price <= 0.1 &&
|
||||||
|
(c.rarity == "rare" || c.rarity == "mythic")
|
||||||
|
)
|
||||||
|
.filter(onlyUnique);
|
||||||
|
|
||||||
|
const template = await ejs.renderFile("templates/cube.ejs", {
|
||||||
|
user: uid,
|
||||||
|
cards: valid,
|
||||||
|
utils: { wubrg, colorNames, colorid }
|
||||||
|
});
|
||||||
|
let cubeFile = `${uid}-cube.html`;
|
||||||
|
writeFile(cubeFile, template, {}, err => {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
console.log(`Wrote cube data to ${cubeFile}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
run();
|
|
@ -1,6 +1,6 @@
|
||||||
import { existsSync } from "fs";
|
import { existsSync } from "fs";
|
||||||
|
|
||||||
import { Article, asyncLoadJSON, asyncSaveJSON, leanArticle, leanCard, MCMDB } from "../lib";
|
import { Article, asyncLoadJSON, asyncSaveJSON, leanArticle, leanCard, MCMDB, onlyUnique } from "../lib";
|
||||||
|
|
||||||
async function run() {
|
async function run() {
|
||||||
if (process.argv.length < 3) {
|
if (process.argv.length < 3) {
|
||||||
|
@ -31,12 +31,14 @@ async function run() {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
let valid = cards.filter(
|
let valid = cards
|
||||||
|
.filter(
|
||||||
c =>
|
c =>
|
||||||
(c.language == "Italian" || c.language == "English") &&
|
(c.language == "Italian" || c.language == "English") &&
|
||||||
c.price <= 0.1 &&
|
c.price <= 0.1 &&
|
||||||
(c.rarity == "rare" || c.rarity == "mythic")
|
(c.rarity == "rare" || c.rarity == "mythic")
|
||||||
);
|
)
|
||||||
|
.filter(onlyUnique);
|
||||||
let netprice = valid.reduce((a, c) => (a += c.price), 0);
|
let netprice = valid.reduce((a, c) => (a += c.price), 0);
|
||||||
console.log(
|
console.log(
|
||||||
`Found ${
|
`Found ${
|
||||||
|
|
|
@ -131,3 +131,5 @@ export interface LeanArticle {
|
||||||
count: number;
|
count: number;
|
||||||
condition: string;
|
condition: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type CardItem = LeanMCMCard & LeanArticle;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { readFile, writeFile } from "fs";
|
import { readFile, writeFile } from "fs";
|
||||||
|
|
||||||
import { Article, LeanArticle, LeanMCMCard, MCMCard } from "./types";
|
import { Article, CardItem, LeanArticle, LeanMCMCard, MCMCard } from "./types";
|
||||||
|
|
||||||
export async function asyncLoadJSON<T>(filename: string): Promise<T> {
|
export async function asyncLoadJSON<T>(filename: string): Promise<T> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
@ -57,3 +57,7 @@ export function leanArticle(article: Article): LeanArticle {
|
||||||
condition: article.condition
|
condition: article.condition
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function onlyUnique(value: CardItem, index: number, self: CardItem[]) {
|
||||||
|
return self.findIndex(c => c.name == value.name) == index;
|
||||||
|
}
|
||||||
|
|
|
@ -8,11 +8,15 @@
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"fetch": "ts-node cmd/fetch.ts",
|
"fetch": "ts-node cmd/fetch.ts",
|
||||||
"init-db": "ts-node cmd/convert.ts",
|
"init-db": "ts-node cmd/convert.ts",
|
||||||
"find": "ts-node cmd/find.ts"
|
"find": "ts-node cmd/find.ts",
|
||||||
|
"cube": "ts-node cmd/cube.ts",
|
||||||
|
"cube-watch": "ts-node cmd/cube-dev.ts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@types/ejs": "^2.6.3",
|
||||||
"@types/node": "^12.12.11",
|
"@types/node": "^12.12.11",
|
||||||
"csv-parser": "^2.3.2",
|
"csv-parser": "^2.3.2",
|
||||||
|
"ejs": "^2.7.4",
|
||||||
"request": "^2.88.0",
|
"request": "^2.88.0",
|
||||||
"ts-node": "^8.5.2",
|
"ts-node": "^8.5.2",
|
||||||
"typescript": "^3.7.2"
|
"typescript": "^3.7.2"
|
||||||
|
|
92
templates/cube.ejs
Normal file
92
templates/cube.ejs
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>Junk rare cube</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
background: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
background: white;
|
||||||
|
max-width: 920px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 20pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3 {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.columns {
|
||||||
|
padding: 20pt 0;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-section {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-section header {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-W header {
|
||||||
|
background-color: #fff6eb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-U header {
|
||||||
|
background-color: #49b0fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-B header {
|
||||||
|
background-color: #666;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-R header {
|
||||||
|
background-color: #ff6868;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-G header {
|
||||||
|
background-color: #78ce59;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-MC header {
|
||||||
|
background: linear-gradient(to left, #f3ff6b, #ffb019);
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-CL header {
|
||||||
|
background-color: #d2d2d2;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<main>
|
||||||
|
<header>
|
||||||
|
<h1>Junk rare cube</h1>
|
||||||
|
<h2>Using cards from <a href="https://www.cardmarket.com/en/Magic/Users/<%=user%>"><b><%= user %></b></a>
|
||||||
|
</h2>
|
||||||
|
</header>
|
||||||
|
<section class="columns">
|
||||||
|
<% for (const column in columns) { %>
|
||||||
|
<section class="color-section color-<%=column%>">
|
||||||
|
<header>
|
||||||
|
<h3><%=utils.colorNames[column]%></h3>
|
||||||
|
</header>
|
||||||
|
</section>
|
||||||
|
<% } %>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
10
yarn.lock
10
yarn.lock
|
@ -40,6 +40,11 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@hapi/hoek" "^8.3.0"
|
"@hapi/hoek" "^8.3.0"
|
||||||
|
|
||||||
|
"@types/ejs@^2.6.3":
|
||||||
|
version "2.6.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/ejs/-/ejs-2.6.3.tgz#b6509e9925d7eb5e95c8c73b6492e5baae7c1e6a"
|
||||||
|
integrity sha512-/F+qQ0Fr0Dr1YvHjX+FCvbba4sQ27RdCPDqmP/si0e1v1GOkbQ3VRBvZPSQM7NoQ3iz3SyiJVscCP2f0vKuIhQ==
|
||||||
|
|
||||||
"@types/node@^12.12.11":
|
"@types/node@^12.12.11":
|
||||||
version "12.12.11"
|
version "12.12.11"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.11.tgz#bec2961975888d964196bf0016a2f984d793d3ce"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.11.tgz#bec2961975888d964196bf0016a2f984d793d3ce"
|
||||||
|
@ -171,6 +176,11 @@ ecc-jsbn@~0.1.1:
|
||||||
jsbn "~0.1.0"
|
jsbn "~0.1.0"
|
||||||
safer-buffer "^2.1.0"
|
safer-buffer "^2.1.0"
|
||||||
|
|
||||||
|
ejs@^2.7.4:
|
||||||
|
version "2.7.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.7.4.tgz#48661287573dcc53e366c7a1ae52c3a120eec9ba"
|
||||||
|
integrity sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==
|
||||||
|
|
||||||
extend@~3.0.2:
|
extend@~3.0.2:
|
||||||
version "3.0.2"
|
version "3.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
|
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
|
||||||
|
|
Loading…
Reference in a new issue