add vp symbols
This commit is contained in:
		| @@ -1,13 +1,13 @@ | |||||||
| import { useState } from "react"; | import { useState } from "react"; | ||||||
| import { sampleCard1, sampleCard2, sampleCard3 } from "../sampleData.ts"; | import { sampleCards } from "../sampleData.ts"; | ||||||
| import { Card } from "./Card.tsx"; | import { Card } from "./Card.tsx"; | ||||||
|  |  | ||||||
| export const App = () => { | export const App = () => { | ||||||
| 	const [count, setCount] = useState(0); | 	const [count, setCount] = useState(0); | ||||||
| 	return <div> | 	return <div> | ||||||
| 		<Card key={`1-${count}`} card={sampleCard1}/> | 		{sampleCards.map((sampleCard) => { | ||||||
| 		<Card key={`2-${count}`} card={sampleCard2}/> | 			return <Card key={`${sampleCard.title}-${count}`} card={sampleCard}/> | ||||||
| 		<Card key={`3-${count}`} card={sampleCard3}/> | 		})} | ||||||
| 		<button onClick={() => {setCount(c => c+1)}}>Rerender (for fonts)</button> | 		<button onClick={() => {setCount(c => c+1)}}>Rerender (for fonts)</button> | ||||||
| 	</div>; | 	</div>; | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -5,9 +5,12 @@ export type Piece = | |||||||
| 	| { type: "text"; text: string; isBold?: boolean; isItalic?: boolean } | 	| { type: "text"; text: string; isBold?: boolean; isItalic?: boolean } | ||||||
| 	| { type: "space" } | 	| { type: "space" } | ||||||
| 	| { type: "break" } | 	| { type: "break" } | ||||||
| 	| { type: "coin"; text: string } | 	| { | ||||||
| 	| { type: "debt"; text: string } | 			type: "symbol"; | ||||||
| 	| { type: "potion"; text: string }; | 			symbol: "coin" | "debt" | "potion" | "vp" | "vp-token"; | ||||||
|  | 			text: string; | ||||||
|  | 			textColor: string; | ||||||
|  | 	  }; | ||||||
|  |  | ||||||
| type PromiseOr<T> = T | Promise<T>; | type PromiseOr<T> = T | Promise<T>; | ||||||
|  |  | ||||||
| @@ -124,14 +127,14 @@ const breakPiece = pieceDef({ | |||||||
| 	render() {}, | 	render() {}, | ||||||
| }); | }); | ||||||
|  |  | ||||||
| const coinPiece = pieceDef({ | const symbolPiece = pieceDef({ | ||||||
| 	type: "coin", | 	type: "symbol", | ||||||
| 	measure(context, _piece) { | 	measure(context, piece) { | ||||||
| 		context.save(); | 		context.save(); | ||||||
| 		const metrics = context.measureText(" "); | 		const metrics = context.measureText(" "); | ||||||
| 		const height = | 		const height = | ||||||
| 			metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent; | 			metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent; | ||||||
| 		const coinImage = getImage("coin"); | 		const coinImage = getImage(piece.symbol); | ||||||
| 		context.restore(); | 		context.restore(); | ||||||
| 		return { | 		return { | ||||||
| 			type: "content", | 			type: "content", | ||||||
| @@ -146,7 +149,7 @@ const coinPiece = pieceDef({ | |||||||
| 		const height = measure.ascent + measure.descent; | 		const height = measure.ascent + measure.descent; | ||||||
| 		// context.fillRect(x, y - measure.ascent, measure.width, height); | 		// context.fillRect(x, y - measure.ascent, measure.width, height); | ||||||
| 		context.drawImage( | 		context.drawImage( | ||||||
| 			getImage("coin"), | 			getImage(piece.symbol), | ||||||
| 			x, | 			x, | ||||||
| 			y - measure.ascent, | 			y - measure.ascent, | ||||||
| 			measure.width, | 			measure.width, | ||||||
| @@ -158,103 +161,14 @@ const coinPiece = pieceDef({ | |||||||
| 		fontInfo.size = parseInt(fontInfo.size.toString()) * 1.2; | 		fontInfo.size = parseInt(fontInfo.size.toString()) * 1.2; | ||||||
| 		const font = stringifyFont(fontInfo); | 		const font = stringifyFont(fontInfo); | ||||||
| 		context.font = font; | 		context.font = font; | ||||||
| 		context.fillStyle = "black"; | 		context.fillStyle = piece.textColor; | ||||||
| 		context.textAlign = "center"; | 		context.textAlign = "center"; | ||||||
| 		context.fillText(piece.text, x + measure.width / 2, y); | 		context.fillText(piece.text, x + measure.width / 2, y); | ||||||
| 		context.restore(); | 		context.restore(); | ||||||
| 	}, | 	}, | ||||||
| }); | }); | ||||||
|  |  | ||||||
| const debtPiece = pieceDef({ | const pieceDefs = [textPiece, spacePiece, breakPiece, symbolPiece]; | ||||||
| 	type: "debt", |  | ||||||
| 	measure(context, _piece) { |  | ||||||
| 		context.save(); |  | ||||||
| 		const metrics = context.measureText(" "); |  | ||||||
| 		const height = |  | ||||||
| 			metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent; |  | ||||||
| 		const coinImage = getImage("debt"); |  | ||||||
| 		context.restore(); |  | ||||||
| 		return { |  | ||||||
| 			type: "content", |  | ||||||
| 			width: coinImage.width * (height / coinImage.height), |  | ||||||
| 			ascent: metrics.fontBoundingBoxAscent, |  | ||||||
| 			descent: metrics.fontBoundingBoxDescent, |  | ||||||
| 		}; |  | ||||||
| 	}, |  | ||||||
| 	render(context, piece, x, y, measure) { |  | ||||||
| 		context.save(); |  | ||||||
| 		// context.fillStyle = "yellow"; |  | ||||||
| 		const height = measure.ascent + measure.descent; |  | ||||||
| 		// context.fillRect(x, y - measure.ascent, measure.width, height); |  | ||||||
| 		context.drawImage( |  | ||||||
| 			getImage("debt"), |  | ||||||
| 			x, |  | ||||||
| 			y - measure.ascent, |  | ||||||
| 			measure.width, |  | ||||||
| 			height |  | ||||||
| 		); |  | ||||||
| 		const fontInfo = parseFont(context.font); |  | ||||||
| 		fontInfo.family = ["DominionSpecial"]; |  | ||||||
| 		fontInfo.weight = "bold"; |  | ||||||
| 		fontInfo.size = parseInt(fontInfo.size.toString()) * 1.2; |  | ||||||
| 		const font = stringifyFont(fontInfo); |  | ||||||
| 		context.font = font; |  | ||||||
| 		context.fillStyle = "white"; |  | ||||||
| 		context.textAlign = "center"; |  | ||||||
| 		context.fillText(piece.text, x + measure.width / 2, y); |  | ||||||
| 		context.restore(); |  | ||||||
| 	}, |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| const potionPiece = pieceDef({ |  | ||||||
| 	type: "potion", |  | ||||||
| 	measure(context, _piece) { |  | ||||||
| 		context.save(); |  | ||||||
| 		const metrics = context.measureText(" "); |  | ||||||
| 		const height = |  | ||||||
| 			metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent; |  | ||||||
| 		const coinImage = getImage("potion"); |  | ||||||
| 		context.restore(); |  | ||||||
| 		return { |  | ||||||
| 			type: "content", |  | ||||||
| 			width: coinImage.width * (height / coinImage.height), |  | ||||||
| 			ascent: metrics.fontBoundingBoxAscent, |  | ||||||
| 			descent: metrics.fontBoundingBoxDescent, |  | ||||||
| 		}; |  | ||||||
| 	}, |  | ||||||
| 	render(context, piece, x, y, measure) { |  | ||||||
| 		context.save(); |  | ||||||
| 		// context.fillStyle = "yellow"; |  | ||||||
| 		const height = measure.ascent + measure.descent; |  | ||||||
| 		// context.fillRect(x, y - measure.ascent, measure.width, height); |  | ||||||
| 		context.drawImage( |  | ||||||
| 			getImage("potion"), |  | ||||||
| 			x, |  | ||||||
| 			y - measure.ascent, |  | ||||||
| 			measure.width, |  | ||||||
| 			height |  | ||||||
| 		); |  | ||||||
| 		const fontInfo = parseFont(context.font); |  | ||||||
| 		fontInfo.family = ["DominionSpecial"]; |  | ||||||
| 		fontInfo.weight = "bold"; |  | ||||||
| 		fontInfo.size = parseInt(fontInfo.size.toString()) * 1.2; |  | ||||||
| 		const font = stringifyFont(fontInfo); |  | ||||||
| 		context.font = font; |  | ||||||
| 		context.fillStyle = "white"; |  | ||||||
| 		context.textAlign = "center"; |  | ||||||
| 		context.fillText(piece.text, x + measure.width / 2, y); |  | ||||||
| 		context.restore(); |  | ||||||
| 	}, |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| const pieceDefs = [ |  | ||||||
| 	textPiece, |  | ||||||
| 	spacePiece, |  | ||||||
| 	breakPiece, |  | ||||||
| 	coinPiece, |  | ||||||
| 	debtPiece, |  | ||||||
| 	potionPiece, |  | ||||||
| ]; |  | ||||||
|  |  | ||||||
| const tools: PieceTools = {} as any; | const tools: PieceTools = {} as any; | ||||||
|  |  | ||||||
| @@ -406,23 +320,28 @@ export const renderDominionText = async ( | |||||||
|  |  | ||||||
| export const parse = (text: string): Piece[] => { | export const parse = (text: string): Piece[] => { | ||||||
| 	const pieces: Piece[] = []; | 	const pieces: Piece[] = []; | ||||||
|  | 	const symbolMap = { | ||||||
|  | 		"$": { symbol: "coin", textColor: "black" }, | ||||||
|  | 		"@": { symbol: "debt", textColor: "white" }, | ||||||
|  | 		"^": { symbol: "potion", textColor: "white" }, | ||||||
|  | 		"%": { symbol: "vp", textColor: "white" }, | ||||||
|  | 		"#": { symbol: "vp-token", textColor: "black" }, | ||||||
|  | 	} as const; | ||||||
| 	for (let i = 0; i < text.length; i++) { | 	for (let i = 0; i < text.length; i++) { | ||||||
| 		const char = text[i]; | 		const char = text[i]; | ||||||
| 		if (char === " ") { | 		if (char === " ") { | ||||||
| 			pieces.push({ type: "space" }); | 			pieces.push({ type: "space" }); | ||||||
| 		} else if (char === "\n") { | 		} else if (char === "\n") { | ||||||
| 			pieces.push({ type: "break" }); | 			pieces.push({ type: "break" }); | ||||||
| 		} else if (char === "$") { | 		} else if (char && char in symbolMap) { | ||||||
| 			const end = text.slice(i).match(/\$\d*/)![0].length; | 			const c = char as keyof typeof symbolMap; | ||||||
| 			pieces.push({ type: "coin", text: text.slice(i + 1, i + end) }); | 			const end = text.slice(i).match(new RegExp(`\\${c}\\w*`))![0] | ||||||
| 			i += end - 1; | 				.length; | ||||||
| 		} else if (char === "@") { | 			pieces.push({ | ||||||
| 			const end = text.slice(i).match(/@\d*/)![0].length; | 				type: "symbol", | ||||||
| 			pieces.push({ type: "debt", text: text.slice(i + 1, i + end) }); | 				...symbolMap[c], | ||||||
| 			i += end - 1; | 				text: text.slice(i + 1, i + end), | ||||||
| 		} else if (char === "^") { | 			}); | ||||||
| 			const end = text.slice(i).match(/\^\d*/)![0].length; |  | ||||||
| 			pieces.push({ type: "potion", text: text.slice(i + 1, i + end) }); |  | ||||||
| 			i += end - 1; | 			i += end - 1; | ||||||
| 		} else if (char === "+") { | 		} else if (char === "+") { | ||||||
| 			const match = text.slice(i).match(/\+\d* \w+/); | 			const match = text.slice(i).match(/\+\d* \w+/); | ||||||
|   | |||||||
| @@ -59,6 +59,14 @@ const imageList = [ | |||||||
| 		key: "potion", | 		key: "potion", | ||||||
| 		src: "/static/assets/Potion.png", | 		src: "/static/assets/Potion.png", | ||||||
| 	}, | 	}, | ||||||
|  | 	{ | ||||||
|  | 		key: "vp", | ||||||
|  | 		src: "/static/assets/VP.png", | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		key: "vp-token", | ||||||
|  | 		src: "/static/assets/VP-Token.png", | ||||||
|  | 	}, | ||||||
| ]; | ]; | ||||||
|  |  | ||||||
| export const loadImages = async () => { | export const loadImages = async () => { | ||||||
|   | |||||||
| @@ -3,45 +3,58 @@ import { | |||||||
| 	TYPE_ACTION, | 	TYPE_ACTION, | ||||||
| 	TYPE_REACTION, | 	TYPE_REACTION, | ||||||
| 	TYPE_TREASURE, | 	TYPE_TREASURE, | ||||||
|  | 	TYPE_VICTORY, | ||||||
| } from "./types.ts"; | } from "./types.ts"; | ||||||
|  |  | ||||||
| export const sampleCard1: DominionCard = { | export const sampleCards: DominionCard[] = [ | ||||||
| 	orientation: "card", | 	{ | ||||||
| 	title: "Title", | 		orientation: "card", | ||||||
| 	description: | 		title: "Title", | ||||||
| 		"+1 Action\n\nReveal the top card of your deck. If it's an Action card, +1 Action.", | 		description: | ||||||
| 	types: [TYPE_ACTION, TYPE_REACTION], | 			"+1 Action\n\nReveal the top card of your deck. If it's an Action card, +1 Action. If it has ^ in its cost, +1 Card.", | ||||||
| 	image: "https://wiki.dominionstrategy.com/images/7/76/AdventurerArt.jpg", | 		types: [TYPE_ACTION, TYPE_REACTION], | ||||||
| 	artist: "Dall-E", | 		image: "https://wiki.dominionstrategy.com/images/7/76/AdventurerArt.jpg", | ||||||
| 	author: "John Doe", | 		artist: "Dall-E", | ||||||
| 	version: "", | 		author: "John Doe", | ||||||
| 	cost: "@8", | 		version: "", | ||||||
| 	preview: "", | 		cost: "@8", | ||||||
| }; | 		preview: "", | ||||||
|  | 	}, | ||||||
| export const sampleCard2: DominionCard = { | 	{ | ||||||
| 	orientation: "card", | 		orientation: "card", | ||||||
| 	title: "Market", | 		title: "Market", | ||||||
| 	description: "+1 Card\n+1 Action\n+1 Buy\n+$1", | 		description: "+1 Card\n+1 Action\n+1 Buy\n+$1", | ||||||
| 	types: [TYPE_ACTION], | 		types: [TYPE_ACTION], | ||||||
| 	image: "", | 		image: "", | ||||||
| 	artist: "Leonardo DaVinci", | 		artist: "Leonardo DaVinci", | ||||||
| 	author: "Jane Smith", | 		author: "Jane Smith", | ||||||
| 	version: "", | 		version: "", | ||||||
| 	cost: "$4", | 		cost: "$4", | ||||||
| 	preview: "", | 		preview: "", | ||||||
| }; | 	}, | ||||||
|  | 	{ | ||||||
| export const sampleCard3: DominionCard = { | 		orientation: "card", | ||||||
| 	orientation: "card", | 		title: "Flask", | ||||||
| 	title: "Flask", | 		description: | ||||||
| 	description: | 			"+2 Cards\n\nAt the start of your Clean-up phase, you may put a card from your hand onto your deck.", | ||||||
| 		"+2 Cards\n\nAt the start of your Clean-up phase, you may put a card from your hand onto your deck.", | 		types: [TYPE_TREASURE], | ||||||
| 	types: [TYPE_TREASURE], | 		image: "", | ||||||
| 	image: "", | 		artist: "", | ||||||
| 	artist: "", | 		author: "", | ||||||
| 	author: "", | 		version: "", | ||||||
| 	version: "", | 		cost: "$6", | ||||||
| 	cost: "$6", | 		preview: "", | ||||||
| 	preview: "", | 	}, | ||||||
| }; | 	{ | ||||||
|  | 		orientation: "card", | ||||||
|  | 		title: "Flask", | ||||||
|  | 		description: "+1 #\n\n-\n\n2 %", | ||||||
|  | 		types: [TYPE_VICTORY], | ||||||
|  | 		image: "", | ||||||
|  | 		artist: "", | ||||||
|  | 		author: "", | ||||||
|  | 		version: "", | ||||||
|  | 		cost: "$6", | ||||||
|  | 		preview: "", | ||||||
|  | 	}, | ||||||
|  | ]; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user