diff --git a/package.json b/package.json index 7e438c5..1dc4f51 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,8 @@ "@types/react": "^18.2.15", "@types/react-dom": "^18.2.7", "bootstrap": "^5.3.0", + "downloadjs": "^1.4.7", + "pdf-lib": "^1.17.1", "react": "^18.2.0", "react-bootstrap": "^2.8.0", "react-dom": "^18.2.0", @@ -45,6 +47,7 @@ }, "devDependencies": { "@babel/plugin-proposal-private-property-in-object": "^7.21.11", + "@types/downloadjs": "^1.4.3", "less": "^4.2.0", "less-loader": "^11.1.3" } diff --git a/public/index.html b/public/index.html index 1df5935..c4a30b5 100644 --- a/public/index.html +++ b/public/index.html @@ -24,6 +24,9 @@ work correctly both with client-side routing and a non-root public URL. Learn how to configure a non-root public URL by running `npm run build`. --> + + + Kém Karakter App diff --git a/public/km_karakterlap_hysteria_1.2.pdf b/public/km_karakterlap_hysteria_1.2.pdf new file mode 100644 index 0000000..1120e6b Binary files /dev/null and b/public/km_karakterlap_hysteria_1.2.pdf differ diff --git a/src/components/KarakterKepzettsegek.tsx b/src/components/KarakterKepzettsegek.tsx index d9d0364..450710e 100644 --- a/src/components/KarakterKepzettsegek.tsx +++ b/src/components/KarakterKepzettsegek.tsx @@ -7,7 +7,20 @@ import { TolvajKepzettsegList, } from "../domain-models/kepzettsegek"; -function InternalKepzettsegekSelector(props: {title: string, numberOfKepzettseg: number, getKepzettsegListaN: (n: number) => Kepzettseg[], kepzettsegek: KepzettsegId[], changeKepzettsegek: (newKepzettsegek: KepzettsegId[]) => void}) { +function arraySetN(array: T[], n: number, elem: T): T[] { + if (array.length < n || n < 0) { + return array + } + return [...array.slice(0, n), elem, ...array.slice(n+1)] +} + +function InternalKepzettsegekSelector(props: { + title: string, + numberOfKepzettseg: number, + getKepzettsegListaN: (n: number) => Kepzettseg[], + kepzettsegek: KepzettsegId[], + changeKepzettsegek: (newKepzettsegek: KepzettsegId[]) => void +}) { const {title, numberOfKepzettseg, getKepzettsegListaN, kepzettsegek, changeKepzettsegek} = props const klist = Array.from(new Array(numberOfKepzettseg).keys()) @@ -22,7 +35,7 @@ function InternalKepzettsegekSelector(props: {title: string, numberOfKepzettseg: preCalculated.push({ kepzettsegek: getKepzettsegListaN(i), selected: Kepzettsegek[kepzettsegek[i]], - changeKepzettseg: (newKepzettseg: KepzettsegId) => { changeKepzettsegek([...kepzettsegek.slice(0, i), newKepzettseg, ...kepzettsegek.slice(i+1)]) } + changeKepzettseg: (newKepzettseg: KepzettsegId) => changeKepzettsegek(arraySetN(kepzettsegek, i, newKepzettseg)) }) } @@ -34,7 +47,7 @@ function InternalKepzettsegekSelector(props: {title: string, numberOfKepzettseg:
- {klist.filter(i => i < preCalculated.length && preCalculated[i].selected != null).map((idx) => + {klist.map((idx) => tulajdonsagok.t_ero) { - return base + Modifier(tulajdonsagok.t_ugy) - } - return base + Modifier(tulajdonsagok.t_ero) -} - -function KitartasMento(osztaly: Osztaly) : number { - switch (osztaly){ - case Osztaly.Barbar: - case Osztaly.Amazon: - case Osztaly.Ijasz: - case Osztaly.Kaloz: - case Osztaly.Harcos: - case Osztaly.Pap: - return 2; - case Osztaly.Tolvaj: - case Osztaly.Varazslo: - case Osztaly.Illuzionista: - return 0; - } -} - -function ReflexMento(osztaly: Osztaly) : number { - switch (osztaly){ - case Osztaly.Tolvaj: - return 2; - case Osztaly.Barbar: - case Osztaly.Amazon: - case Osztaly.Ijasz: - case Osztaly.Kaloz: - case Osztaly.Harcos: - case Osztaly.Pap: - case Osztaly.Varazslo: - case Osztaly.Illuzionista: - return 0; - } -} - -function AkarateroMento(osztaly: Osztaly) : number { - switch (osztaly){ - case Osztaly.Pap: - case Osztaly.Varazslo: - case Osztaly.Illuzionista: - return 2; - case Osztaly.Tolvaj: - case Osztaly.Barbar: - case Osztaly.Amazon: - case Osztaly.Ijasz: - case Osztaly.Kaloz: - case Osztaly.Harcos: - return 0; - } -} - -function MasodlagosErtekek(props: {osztaly: Osztaly, tulajdonsagok: KarakterTulajdonsagok}) { - - const { osztaly, tulajdonsagok } = props; + const { ertekek } = props const tooltip = ( @@ -125,33 +26,33 @@ function MasodlagosErtekek(props: {osztaly: Osztaly, tulajdonsagok: KarakterTula (HP) -

{HP(osztaly, tulajdonsagok.t_egs)}

+

{ertekek.HP}

-

{10+Modifier(tulajdonsagok.t_ugy)}

+

{ertekek.VO}

-

{SignedNumberToText(KozelharciTB(osztaly, tulajdonsagok))}

+

{SignedNumberToText(ertekek.KozelHarciTB)}

-

{SignedNumberToText(TamadasBonusz(osztaly) + Modifier(tulajdonsagok.t_ugy))}

+

{SignedNumberToText(ertekek.CelzoTB)}

-

{SignedNumberToText(KitartasMento(osztaly) + Modifier(tulajdonsagok.t_egs))}

+

{SignedNumberToText(ertekek.KitartasMento)}

-

{SignedNumberToText(ReflexMento(osztaly) + Modifier(tulajdonsagok.t_ugy))}

+

{SignedNumberToText(ertekek.ReflexMento)}

-

{SignedNumberToText(AkarateroMento(osztaly) + Modifier(tulajdonsagok.t_bol))}

+

{SignedNumberToText(ertekek.AkarateroMento)}

diff --git a/src/domain-models/karakter.ts b/src/domain-models/karakter.ts new file mode 100644 index 0000000..bb65393 --- /dev/null +++ b/src/domain-models/karakter.ts @@ -0,0 +1,12 @@ +import {Faj} from "./faj"; +import {Osztaly} from "./osztaly"; +import {KarakterTulajdonsagok} from "./tulajdonsag"; +import {KarakterMasodlagosErtekek} from "./masodlagos_ertekek"; + +export interface Karakter { + Name: string + Faj: Faj + Osztaly: Osztaly + Tulajdonsagok: KarakterTulajdonsagok, + MasodlagosErtekek: KarakterMasodlagosErtekek +} \ No newline at end of file diff --git a/src/domain-models/masodlagos_ertekek.ts b/src/domain-models/masodlagos_ertekek.ts new file mode 100644 index 0000000..ff49c93 --- /dev/null +++ b/src/domain-models/masodlagos_ertekek.ts @@ -0,0 +1,124 @@ +import {Osztaly} from "./osztaly"; +import {KarakterTulajdonsagok, Modifier} from "./tulajdonsag"; + +export interface KarakterMasodlagosErtekek { + HP: number + VO: number + CelzoTB: number + KozelHarciTB: number + KitartasMento: number + ReflexMento: number + AkarateroMento: number +} + +export function CalculateMasodlagosErtekek(osztaly: Osztaly, tulajdonsagok: KarakterTulajdonsagok) : KarakterMasodlagosErtekek { + return { + HP: HP(osztaly, tulajdonsagok.t_egs), + VO: 10 + Modifier(tulajdonsagok.t_ugy), + KozelHarciTB: KozelharciTB(osztaly, tulajdonsagok), + CelzoTB: TamadasBonusz(osztaly) + Modifier(tulajdonsagok.t_ugy), + + KitartasMento: KitartasMento(osztaly) + Modifier(tulajdonsagok.t_egs), + ReflexMento: ReflexMento(osztaly) + Modifier(tulajdonsagok.t_ugy), + AkarateroMento: AkarateroMento(osztaly) + Modifier(tulajdonsagok.t_bol), + } +} + +function HP(osztaly: Osztaly, egeszseg: number) { + let base = 4; + switch (osztaly){ + case Osztaly.Barbar: + base = 12 + break; + case Osztaly.Amazon: + case Osztaly.Ijasz: + case Osztaly.Kaloz: + case Osztaly.Harcos: + base = 10; + break + case Osztaly.Pap: + base = 8; + break; + case Osztaly.Tolvaj: + base = 6; + break; + case Osztaly.Varazslo: + case Osztaly.Illuzionista: + base = 4; + break; + } + return base + Modifier(egeszseg) +} + +function TamadasBonusz(osztaly: Osztaly) : number { + switch (osztaly){ + case Osztaly.Barbar: + case Osztaly.Amazon: + case Osztaly.Ijasz: + case Osztaly.Kaloz: + case Osztaly.Harcos: + return 2; + case Osztaly.Pap: + case Osztaly.Tolvaj: + return 0; + case Osztaly.Varazslo: + case Osztaly.Illuzionista: + return 0; + } +} + +function KozelharciTB(osztaly: Osztaly, tulajdonsagok: KarakterTulajdonsagok): number { + const base = TamadasBonusz(osztaly); + if (osztaly === Osztaly.Kaloz && tulajdonsagok.t_ugy > tulajdonsagok.t_ero) { + return base + Modifier(tulajdonsagok.t_ugy) + } + return base + Modifier(tulajdonsagok.t_ero) +} + +function KitartasMento(osztaly: Osztaly) : number { + switch (osztaly){ + case Osztaly.Barbar: + case Osztaly.Amazon: + case Osztaly.Ijasz: + case Osztaly.Kaloz: + case Osztaly.Harcos: + case Osztaly.Pap: + return 2; + case Osztaly.Tolvaj: + case Osztaly.Varazslo: + case Osztaly.Illuzionista: + return 0; + } +} + +function ReflexMento(osztaly: Osztaly) : number { + switch (osztaly){ + case Osztaly.Tolvaj: + return 2; + case Osztaly.Barbar: + case Osztaly.Amazon: + case Osztaly.Ijasz: + case Osztaly.Kaloz: + case Osztaly.Harcos: + case Osztaly.Pap: + case Osztaly.Varazslo: + case Osztaly.Illuzionista: + return 0; + } +} + +function AkarateroMento(osztaly: Osztaly) : number { + switch (osztaly){ + case Osztaly.Pap: + case Osztaly.Varazslo: + case Osztaly.Illuzionista: + return 2; + case Osztaly.Tolvaj: + case Osztaly.Barbar: + case Osztaly.Amazon: + case Osztaly.Ijasz: + case Osztaly.Kaloz: + case Osztaly.Harcos: + return 0; + } +} diff --git a/src/pages/CreateCharacter.tsx b/src/pages/CreateCharacter.tsx index 1298a97..fc7509c 100644 --- a/src/pages/CreateCharacter.tsx +++ b/src/pages/CreateCharacter.tsx @@ -1,7 +1,7 @@ import React, {useState} from 'react'; import './CreateCharacter.css' -import {Faj} from "../domain-models/faj"; -import {Osztaly} from "../domain-models/osztaly" +import {Faj, FajLabel} from "../domain-models/faj"; +import {Osztaly, OsztalyLabel} from "../domain-models/osztaly" import FajSelector from "../components/FajSelector"; import Tulajdonsagok from "../components/Tulajdonsagok"; import OsztalySelector from "../components/OsztalySelector"; @@ -9,6 +9,10 @@ import KarakterKepzettsegek from "../components/KarakterKepzettsegek"; import {KarakterTulajdonsagok, Modifier} from "../domain-models/tulajdonsag"; import MasodlagosErtekek from "../components/MasodlagosErtekek"; import {AvailableKezpettsegList, KepzettsegId, TolvajKepzettsegList} from "../domain-models/kepzettsegek"; +import {PDFDocument, rgb, StandardFonts} from 'pdf-lib' +import download from 'downloadjs' +import {CalculateMasodlagosErtekek} from "../domain-models/masodlagos_ertekek"; +import {Karakter} from "../domain-models/karakter"; const tulajdonsagDefaults: KarakterTulajdonsagok = { t_ero: 10, @@ -33,22 +37,65 @@ function getNumberOfKepzettsegek(t_int: number, faj: Faj, max: number) { return numberOfKepzettseg; } +async function createPDF(karakter: Karakter) { + + const existingPdfBytes = await fetch('/km_karakterlap_hysteria_1.2.pdf').then(res => res.arrayBuffer()) + const pdfDoc = await PDFDocument.load(existingPdfBytes) + + const timesRomanFont = await pdfDoc.embedFont(StandardFonts.Helvetica) + + const page = pdfDoc.getPage(0) + const fontSize = 12 + page.drawText(karakter.Name, { + x: 60, + y: 710, + size: fontSize, + font: timesRomanFont, + color: rgb(0, 0, 0), + }) + page.drawText(OsztalyLabel(karakter.Osztaly), { + x: 60, + y: 672, + size: fontSize, + font: timesRomanFont, + color: rgb(0, 0, 0), + }) + page.drawText('1', { + x: 264, + y: 682, + size: fontSize * 3, + font: timesRomanFont, + color: rgb(0, 0, 0), + }) + page.drawText(FajLabel(karakter.Faj), { + x: 304, + y: 710, + size: fontSize, + font: timesRomanFont, + color: rgb(0, 0, 0), + }) + + + const pdfBytes = await pdfDoc.save(); + download(pdfBytes, "karakter.pdf", "application/pdf"); +} + function CreateCharacterPage() { - let [name, changeName] = useState("Névtelen kanadozó") + let [name, changeName] = useState("Névtelen kalandozó") let [faj, changeFaj] = useState(Faj.Ember) let [tulajdonsagok, changeTulajdonsagok] = useState(tulajdonsagDefaults) - let [currentOsztaly, changeOsztaly] = useState(Osztaly.Harcos) + let [osztaly, changeOsztaly] = useState(Osztaly.Harcos) let [kepzettsegek, changeKepzettsegek] = useState([]) let [tolvajKepzettsegek, changeTolvajKepzettsegek] = useState([]) - const availableKepzettsegList = AvailableKezpettsegList(currentOsztaly) + const availableKepzettsegList = AvailableKezpettsegList(osztaly) - if (currentOsztaly !== Osztaly.Tolvaj && tolvajKepzettsegek.length > 0) { + if (osztaly !== Osztaly.Tolvaj && tolvajKepzettsegek.length > 0) { tolvajKepzettsegek = [] changeTolvajKepzettsegek([]) } - if (currentOsztaly === Osztaly.Tolvaj && tolvajKepzettsegek.length === 0) { + if (osztaly === Osztaly.Tolvaj && tolvajKepzettsegek.length === 0) { tolvajKepzettsegek = TolvajKepzettsegList.slice(0, 4).map(x => x.Id) changeTolvajKepzettsegek(tolvajKepzettsegek) } @@ -59,7 +106,13 @@ function CreateCharacterPage() {

Karakter létrehozása

-
console.log("Character created!")}> + { event.preventDefault(); await createPDF({ + Name: name, + Faj: faj, + MasodlagosErtekek: CalculateMasodlagosErtekek(osztaly, tulajdonsagok), + Osztaly: osztaly, + Tulajdonsagok: tulajdonsagok + })} }>
Származás
@@ -86,7 +139,7 @@ function CreateCharacterPage() {

- +
diff --git a/yarn.lock b/yarn.lock index 4c0166e..9d1e498 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1675,6 +1675,20 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@pdf-lib/standard-fonts@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@pdf-lib/standard-fonts/-/standard-fonts-1.0.0.tgz#8ba691c4421f71662ed07c9a0294b44528af2d7f" + integrity sha512-hU30BK9IUN/su0Mn9VdlVKsWBS6GyhVfqjwl1FjZN4TxP6cCw0jP2w7V3Hf5uX7M0AZJ16vey9yE0ny7Sa59ZA== + dependencies: + pako "^1.0.6" + +"@pdf-lib/upng@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@pdf-lib/upng/-/upng-1.0.1.tgz#7dc9c636271aca007a9df4deaf2dd7e7960280cb" + integrity sha512-dQK2FUMQtowVP00mtIksrlZhdFXQZPC+taih1q4CvPZ5vqdxR/LKBaFg0oAfzd1GlHZXXSPdQfzQnt+ViGvEIQ== + dependencies: + pako "^1.0.10" + "@pmmmwh/react-refresh-webpack-plugin@^0.5.3": version "0.5.10" resolved "https://registry.yarnpkg.com/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.10.tgz#2eba163b8e7dbabb4ce3609ab5e32ab63dda3ef8" @@ -2038,6 +2052,11 @@ dependencies: "@types/node" "*" +"@types/downloadjs@^1.4.3": + version "1.4.3" + resolved "https://registry.yarnpkg.com/@types/downloadjs/-/downloadjs-1.4.3.tgz#01c0414a9756afa2bd438b1e2ec6c50de7df316d" + integrity sha512-MjJepFle/tLtT2/jmDNth6ZnwWzEhm40L+olE5HKR70ISUCfgT55eqreeHldAzFLY2HDUGsn8zgyto8KygN0CA== + "@types/eslint-scope@^3.7.3": version "3.7.4" resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.4.tgz#37fc1223f0786c39627068a12e94d6e6fc61de16" @@ -4018,6 +4037,11 @@ dotenv@^10.0.0: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81" integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q== +downloadjs@^1.4.7: + version "1.4.7" + resolved "https://registry.yarnpkg.com/downloadjs/-/downloadjs-1.4.7.tgz#f69f96f940e0d0553dac291139865a3cd0101e3c" + integrity sha512-LN1gO7+u9xjU5oEScGFKvXhYf7Y/empUIIEAGBs1LzUq/rg5duiDrkuH5A2lQGd5jfMOb9X9usDa2oVXwJ0U/Q== + duplexer@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" @@ -6912,6 +6936,11 @@ p-try@^2.0.0: resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== +pako@^1.0.10, pako@^1.0.11, pako@^1.0.6: + version "1.0.11" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" + integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== + param-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5" @@ -6995,6 +7024,16 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== +pdf-lib@^1.17.1: + version "1.17.1" + resolved "https://registry.yarnpkg.com/pdf-lib/-/pdf-lib-1.17.1.tgz#9e7dd21261a0c1fb17992580885b39e7d08f451f" + integrity sha512-V/mpyJAoTsN4cnP31vc0wfNA1+p20evqqnap0KLoRUN0Yk/p3wN52DOEsL4oBFcLdb76hlpKPtzJIgo67j/XLw== + dependencies: + "@pdf-lib/standard-fonts" "^1.0.0" + "@pdf-lib/upng" "^1.0.1" + pako "^1.0.11" + tslib "^1.11.1" + performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" @@ -8966,7 +9005,7 @@ tsconfig-paths@^3.14.1: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@^1.8.1: +tslib@^1.11.1, tslib@^1.8.1: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==