From 4007862149c5065ea7dc5d9c747ae3fd7dadc648 Mon Sep 17 00:00:00 2001 From: NilsUeter Date: Sun, 9 Apr 2023 17:55:17 +0200 Subject: [PATCH] first commit --- .gitignore | 24 + index.html | 19 + package.json | 22 + public/vite.svg | 1 + src/App.jsx | 80 ++ src/Roster.jsx | 517 +++++++++++++ src/assets/adeptusAstartesIcon.png | Bin 0 -> 10393 bytes src/assets/factionBackground.png | Bin 0 -> 7700 bytes src/assets/icons.jsx | 5 + src/assets/keywordsBackground.png | Bin 0 -> 4321 bytes src/assets/meleeIcon.png | Bin 0 -> 1177 bytes src/assets/rangedIcon.png | Bin 0 -> 1312 bytes src/assets/react.svg | 1 + src/index.css | 122 +++ src/main.jsx | 10 + src/roster40k.js | 1161 ++++++++++++++++++++++++++++ vite.config.js | 7 + yarn.lock | 787 +++++++++++++++++++ 18 files changed, 2756 insertions(+) create mode 100644 .gitignore create mode 100644 index.html create mode 100644 package.json create mode 100644 public/vite.svg create mode 100644 src/App.jsx create mode 100644 src/Roster.jsx create mode 100644 src/assets/adeptusAstartesIcon.png create mode 100644 src/assets/factionBackground.png create mode 100644 src/assets/icons.jsx create mode 100644 src/assets/keywordsBackground.png create mode 100644 src/assets/meleeIcon.png create mode 100644 src/assets/rangedIcon.png create mode 100644 src/assets/react.svg create mode 100644 src/index.css create mode 100644 src/main.jsx create mode 100644 src/roster40k.js create mode 100644 vite.config.js create mode 100644 yarn.lock diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/index.html b/index.html new file mode 100644 index 0000000..bcbcbd6 --- /dev/null +++ b/index.html @@ -0,0 +1,19 @@ + + + + + + + Vite + React + + + + + +
+ + + diff --git a/package.json b/package.json new file mode 100644 index 0000000..3bf8f13 --- /dev/null +++ b/package.json @@ -0,0 +1,22 @@ +{ + "name": "fancyscribe", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "jszip": "^3.10.1", + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@types/react": "^18.0.28", + "@types/react-dom": "^18.0.11", + "@vitejs/plugin-react": "^3.1.0", + "vite": "^4.2.0" + } +} diff --git a/public/vite.svg b/public/vite.svg new file mode 100644 index 0000000..e7b8dfb --- /dev/null +++ b/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/App.jsx b/src/App.jsx new file mode 100644 index 0000000..022860e --- /dev/null +++ b/src/App.jsx @@ -0,0 +1,80 @@ +import JSZip from "jszip"; +import { Create40kRoster } from "./roster40k"; +import { useState } from "react"; +import { Roster } from "./Roster"; + +function App() { + const [roster, setRoster] = useState(); + function handleFileSelect(event) { + const files = event?.target?.files; + + if (files) { + const reader = new FileReader(); + reader.onerror = () => { + reader.abort(); + console.log("Failed to read roster file."); + }; + reader.onloadend = async () => { + const content = reader.result; + const xmldata = await unzip(content); + parseXML(xmldata); + }; + reader.readAsBinaryString(files[0]); + } + } + + const unzip = async (file) => { + if (file.charAt(0) !== "P") { + return file; + } else { + const jszip = new JSZip(); + const zip = await jszip.loadAsync(file); + return zip.file(/[^/]+\.ros/)[0].async("string"); // Get roster files that are in the root + } + }; + + function parseXML(xmldata) { + const parser = new DOMParser(); + const doc = parser.parseFromString(xmldata, "text/xml"); + if (!doc) return; + + // Determine roster type (game system). + const info = doc.querySelector("roster"); + if (!info) return; + + const gameType = info.getAttribute("gameSystemName"); + if (!gameType) return; + + const rosterName = info.getAttribute("name"); + if (rosterName) { + document.title = `PrettyScribe ${rosterName}`; + } + + if (gameType == "Warhammer 40,000 9th Edition") { + console.log(doc); + const roster = Create40kRoster(doc); + console.log(roster); + if (roster && roster._forces.length > 0) { + setRoster(roster); + /* const renderer = new Renderer40k(roster); + renderer.render(rosterTitle, rosterList, forceUnits); */ + } + } else { + console.log("No support for game type '" + gameType + "'."); + } + } + + return ( +
+ +
+ +
+
+ ); +} + +export default App; diff --git a/src/Roster.jsx b/src/Roster.jsx new file mode 100644 index 0000000..2531349 --- /dev/null +++ b/src/Roster.jsx @@ -0,0 +1,517 @@ +import factionBackground from "./assets/factionBackground.png"; +import adeptusAstartesIcon from "./assets/adeptusAstartesIcon.png"; +import meleeIcon from "./assets/meleeIcon.png"; +import rangedIcon from "./assets/rangedIcon.png"; +import { Arrow } from "./assets/icons"; + +export const Roster = ({ roster }) => { + if (!roster) { + return null; + } + const { _name, _forces } = roster; + return ( + <> +
+ {_name} +
+ {_forces.map((force, index) => ( + + ))} + + ); +}; + +const Force = ({ force }) => { + const { _units, rules } = force; + return ( + <> + {_units.map((unit, index) => ( + + ))} + + + ); +}; + +const Unit = ({ unit }) => { + const { _name, weapons, abilities, keywords, factions, rules, modelStats } = + unit; + + const meleeWeapons = weapons + .filter((weapon) => weapon._range === "Melee") + .sort((a, b) => a._selectionName.localeCompare(b._selectionName)); + const rangedWeapons = weapons + .filter((weapon) => weapon._range !== "Melee") + .sort((a, b) => a._selectionName.localeCompare(b._selectionName)); + return ( +
+
+
+
+ {_name} +
+
+ {modelStats.map((model, index) => ( + 1} + /> + ))} +
+
+
+
+
+ + + +
+
+ { + + + + + +
{Arrow} + Before selecting targets for this weapon, select one of its + profiles to make attacks with. +
+ } + +
+
+
+ ABILITIES +
+ + + + +
+
+
+ ); +}; + +const ModelStats = ({ modelStats, index, showName }) => { + let { move, toughness, save, wounds, leadership, _name } = modelStats; + if (!wounds) { + wounds = "/"; + } + return ( +
+ + + + + + {showName && ( +
+ {_name} +
+ )} +
+ ); +}; + +const FactionIcon = () => { + return ( +
+
+
+ ); +}; + +const Keywords = ({ keywords }) => { + return ( +
+ KEYWORDS: + + {[...keywords].join(", ")} + +
+ ); +}; + +const Factions = ({ factions }) => { + return ( +
+ + FACTION KEYWORDS: + + + {[...factions].join(", ")} + +
+ ); +}; + +const Rules = ({ rules }) => { + return ( +
+ RULES: + + {[...rules.keys()].map((rule) => rule).join(", ")} + +
+ ); +}; + +const Abilities = ({ abilities }) => { + return ( +
+ {[...abilities.keys()].map((ability) => ( +
+ {ability}:{" "} + {abilities.get(ability)} +
+ ))} +
+ ); +}; + +const Characteristic = ({ title, characteristic, index }) => { + return ( +
+ {index === 0 && ( +
{title}
+ )} + {characteristic} +
+ ); +}; + +const FancyBox = ({ children }) => { + return ( +
+
+
{children}
+
+
+ ); +}; + +const Weapons = ({ title, weapons, modelStats }) => { + const isMelee = title === "MELEE WEAPONS"; + return ( + <> + {weapons.length > 0 && ( + + + +
+ +
+ + {title} + RANGE + A + {isMelee ? "WS" : "BS"} + S + AP + D + + + )} + + {weapons.map((weapon, index) => ( + + ))} + {weapons.length > 0 && ( + + + + )} + + + ); +}; + +const Weapon = ({ weapon, modelStats, isMelee, index }) => { + let { _name, _selectionName, _range, _type, str, _ap, _damage } = weapon; + const [type, attacks] = _type.split(" "); + const bs = modelStats[0]._bs; + const ws = modelStats[0]._ws; + const strModel = modelStats[0].str; + const meleeAttacks = modelStats[0]._attacks; + + const differentProfiles = _selectionName !== _name; + const interestingType = type !== "Melee"; + if (differentProfiles && _name.endsWith(" grenades")) { + _name = _name.replace(" grenades", ""); + } + return ( + + + {differentProfiles && Arrow} + + +
+ {differentProfiles && _selectionName + " - "} + {_name} + {interestingType && ( + + [{type}] + + )} +
+ + {_range} + {isMelee ? meleeAttacks : attacks} + {isMelee ? ws : bs} + {isMelee ? calculateWeaponStrength(strModel, str) : str} + {_ap} + {_damage} + + ); +}; + +const calculateWeaponStrength = (strModel, strWeapon) => { + if (strWeapon.startsWith("x")) + return strModel * parseInt(strWeapon.replace("x", "")); + return strModel + parseInt(strWeapon, 10); +}; + +const ForceRules = ({ rules }) => { + return ( +
+ {[...rules.keys()] + .filter((rule) => !rule.startsWith("Explodes")) + .map((rule) => ( +
+ {rule}: {rules.get(rule)} +
+ ))} +
+ ); +}; diff --git a/src/assets/adeptusAstartesIcon.png b/src/assets/adeptusAstartesIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..f598e404ae6150b75548d6b5549940c12fa6a5e9 GIT binary patch literal 10393 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 + + +); diff --git a/src/assets/keywordsBackground.png b/src/assets/keywordsBackground.png new file mode 100644 index 0000000000000000000000000000000000000000..75c10cd9fb3937e7fc7a99e4eb00fa8edb5eeb94 GIT binary patch literal 4321 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 P00000NkvXXu0mjf!GijA literal 0 HcmV?d00001 diff --git a/src/assets/meleeIcon.png b/src/assets/meleeIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..ed5ea7399a2bd9eead1b988318c2b20a53864803 GIT binary patch literal 1177 zcmV;K1ZMk*P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D1TINLK~y+TEmYf6 z8fO&WE4!?)Ad2w<;x$-FR3ctSlSY%N>4UX8(?nY@GaB5 z?)GrP0<{l4Eh=l44wIxszn=8%jeDV54Z zEG|hB!_W~SnoK53%1TqIR3eecWwLp+Jex(L5uTFMI-TxcE{tLrisSg@_BI^D0sPOQ zFB}e=Os0eS&5hYiRuBYM zsl3|NJv2DfbM;z9RYg1&vv1oIqDYgn_j+#(-@en-(3r1Q$4*Zj4ku)h&1Q25g4efL zFcd|k%s~GKQ{&?o3JT(4ytuGPrB>}Y90Je3d+plbz=s;8Dj_Cot13;VOF-=PdLaP< zC$OxP@g5vZjExWU_hSeWj_@p#CngimZJROS6j~EJ3iu8WfejK#if4tIg1eJby3(>( zRNy!c*Ou$+jddfp?+_S%mQ2ZMI>dz*9z9xJSy8Li8jWUWXXnW0XIWNTsHJEcPE2Ja z9LIPe8jT8AU0vPG%#1>zplOO#FnJWIR)3cqm#IrJZ`tgeZoI5~ZHY-}u($?UjXeSLkOe*Rf!XXoyo=kFIU z1u>~nu?TW50s<=JmlW^1-Q8VX@woWQ!op7vA0|`D_SUuwCB<=3{B!Nu@W@D4N9XSA zz3;yN;Ww)lDypuo`uWKd+w;x9@iE@e(RLgN*zIi-@Dgy z{rckK;;)Y%M|fV&F#8@4SfJ5tZf r-C#gFKP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D1hq*-K~y+TEmZ4I z6jv0VnLE#YvkSXGSsn!zVO1WB3n&$dG$~*!nx^&DFN%KgU+^!mwkB=AwCM+wwDFUD zMAJ5awI*UsWRqeIL3egxLD1dJ?yx)0ombB$y_w0}x%b?2&-tC-@8C1Dmn_S|aojKr z48sV5P*qjaG>^v<3uq_)Ah@vSN6+<^I3myVT1kEyV2}98}UazJo8%e&9%{2x? zhvP%B?(Y7c9;{M%olc8_fZK2Y(@h;ixJ_Udj-k$2zp5w{Nn*C0+1#{E>*G_WuUx)7 z(AUp0v?xk-wSmJUBdu+%LQ%-&a&R+&6V+gFj3g=4)!zq+1?%cI(i;%`XBRGw6vs~hCdKcR8^Ejmnm+p?wtb7-zgil*>8g+c+53TK!vGFyh5=52bwpiVouVku z*IzOu@$cID_uqcEwzlSASvX7*2pqvKOEXTEyLa#2{QP{WRLToNNh}i-3DFVY=KlTr zH*em2wV4TpLM+P)f&dH+1Onhfk>rL@J;!m`Y&Mxp0#p2c|HFq5uU)&gyu1w1qSk0n zu_$b9Z2@`S8$Hs{(D?Yta*F3Y9yiOez)Rb*Qm>Mwy}jwF6IZWZ1zbP>;>Pywj>G9> zI2H{Y9fkB94kyp^K3`3IC=T;XCL=-e%w4z5CN& zj~)S$p)X)$Rk$9H7xj(|15Q9D%QQp5pe#uXON%Rs1c;=oqeC?eNfhUQ_;GIT*4p|y z>)=B5_1oLq4vrH=5t|8E{{8#&+WX~&5I%cUJyknn5e1@#}On2 zEOa?sM#XTmPUr+E8XK%i5maCrph^f2{!9!|xAw&H^A|5(@_ag-)(qY2^#b4wO+)0+ zCNL;Iyr-|sT9^$~kyQn>1QEijqN!j32+N}6_Ikup8P2#IPG}ymZdj(1b3p&VZR|f} WxNQKI#~tAS0000