commit 97d3cfe34b32caff1bc8b3cb869433c252271a9e
parent 54c64a507cfaefcdcde4ac47e3c7c14afabc4c37
Author: Jake Bauer <jbauer@paritybit.ca>
Date: Fri, 10 Feb 2023 11:33:09 -0500
Whoops, I wasn't tracking my scripts
Diffstat:
5 files changed, 786 insertions(+), 0 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -4,3 +4,5 @@ static/*/
static/feed.xml
# Don't ignore images
!static/img
+# Don't ignore javascript
+!static/js
diff --git a/static/js/initiative.js b/static/js/initiative.js
@@ -0,0 +1,159 @@
+/*initiative.js
+* Copyright (C) 2019,2022 Jake Bauer
+* Licensed under the ISC License.
+*/
+
+// Global variable keeping track of all characters added to the list.
+let charArray = [];
+
+/* draw()
+ * @brief Draws a character, their information, and the relevant buttons to the
+ * viewport.
+ * @input char The character to draw
+ * @input position That character's position in the charArray (used to give the
+ * div a corresponding id attribute);
+ */
+function draw(char, position) {
+ let list = document.getElementById("initiative-list");
+ let div = document.createElement('div');
+ div.setAttribute("class","initiative-div");
+ div.setAttribute("id", position);
+ list.insertBefore(div, list.childNodes[list.childNodes.length-1]);
+
+ let charName = document.createElement('p');
+ let textNode = document.createTextNode(char.name);
+ charName.appendChild(textNode);
+ charName.setAttribute("class", "in-name");
+ div.appendChild(charName);
+
+ let charInit = document.createElement('p');
+ textNode = document.createTextNode(char.initiative);
+ charInit.appendChild(textNode);
+ charInit.setAttribute("class", "in-val");
+ div.appendChild(charInit);
+
+ let editBtn = document.createElement('button');
+ let pencil = document.createElement('strong');
+ textNode = document.createTextNode("✎");
+ pencil.setAttribute("class", "green-pencil");
+ pencil.appendChild(textNode);
+ editBtn.setAttribute("class", "in-edit-btn");
+ editBtn.setAttribute("onClick", "editChar(this)");
+ div.appendChild(editBtn);
+ editBtn.appendChild(pencil);
+ textNode = document.createTextNode(" Edit");
+ editBtn.appendChild(textNode);
+
+ let removeBtn = document.createElement('button');
+ let x = document.createElement('strong');
+ textNode = document.createTextNode("X");
+ x.setAttribute("class", "red-x");
+ x.appendChild(textNode);
+ removeBtn.setAttribute("class", "in-rem-btn");
+ removeBtn.setAttribute("onClick", "removeChar(this)");
+ div.appendChild(removeBtn);
+ removeBtn.appendChild(x);
+ textNode = document.createTextNode(" Remove");
+ removeBtn.appendChild(textNode);
+}
+
+/* compare()
+ * @brief Used by sortList() to determine the sorted order. Sorts by greatest to
+ * least initative value for each character.
+ * @see sortList()
+ */
+function compare(a, b) {
+ if (a.initiative < b.initiative)
+ return 1;
+ if (a.initiative > b.initiative)
+ return -1;
+ else
+ return 0;
+}
+
+/* sortList()
+ * @brief Sort the list of characters by their initative value
+ * @see compare()
+ */
+function sortList() {
+ // Sorts in order largest to smallest
+ charArray.sort(compare);
+ // Delete all divs of class initiative-div
+ for (let i = 0; i < charArray.length; i++) {
+ let element = document.getElementById(i);
+ element.parentNode.removeChild(element);
+ }
+ // Then re-draw them
+ for (let i = 0; i < charArray.length; i++) {
+ draw(charArray[i], i);
+ }
+}
+
+/* addChar()
+ * @brief Add a character to the list and sort the list
+ */
+function addChar() {
+ let newChar = {};
+ nameField = document.getElementById("char-name");
+ initField = document.getElementById("init-val");
+ newChar.name = nameField.value;
+ newChar.initiative = Number(initField.value);
+ nameField.value = null;
+ initField.value = null;
+ if (newChar.name == "" || newChar.initiative == null) {
+ alert("Please fill out both fields before adding a character.");
+ return;
+ }
+ draw(newChar, charArray.length);
+ charArray.push(newChar);
+ sortList();
+}
+
+/* editChar()
+ * @brief Edit a characters initiative value and re-sort
+ * @input Elem The "edit" button clicked used to identify which character
+ * to edit
+ */
+function editChar(elem) {
+ let newVal = prompt("Enter the new value:", "0");
+ if (newVal != null) {
+ // Edit the value in the array of characters
+ let charIndex = elem.parentNode.getAttribute("id");
+ charArray[charIndex].initiative = Number(newVal);
+ // Modify the number displayed for that character
+ let parentNode = elem.parentNode;
+ for (let i = 0; i < elem.parentNode.childNodes.length; i++) {
+ if (parentNode.childNodes[i].className == "in-val") {
+ parentNode.childNodes[i].innerHTML = newVal;
+ break;
+ }
+ }
+ sortList();
+ }
+ else {
+ return;
+ }
+}
+
+/* removeChar()
+ * @brief Removes a character from the list of characters
+ * @input Elem The "remove" button clicked used to identify which character
+ * to remove
+ */
+function removeChar(elem) {
+ let charIndex = elem.parentNode.getAttribute("id");
+ for (let i = 0; i < charArray.length; i++) {
+ if (i == charIndex) {
+ charArray.splice(i,1);
+ }
+ }
+ // Delete all divs of class initiative-div
+ for (let i = 0; i <= charArray.length; i++) {
+ let element = document.getElementById(i);
+ element.parentNode.removeChild(element);
+ }
+ // Then re-draw them
+ for (let i = 0; i < charArray.length; i++) {
+ draw(charArray[i], i);
+ }
+}
diff --git a/static/js/morrowind-character-generator.js b/static/js/morrowind-character-generator.js
@@ -0,0 +1,374 @@
+/*
+* generator.js
+* Contains backend code for generation of game parameters
+*
+* This file is part of MorrowindGameGen
+* Copyright (C) 2019 Jake Bauer
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <https://www.gnu.org/licenses/>.
+*/
+
+function charGen() {
+
+ const firstNames = ["Adaves", "Adil", "Adondasi", "Adosi", "Adren", "Alam",
+ "Alanil", "Aldam", "Alds", "Alms", "Alnas", "Alvan", "Alven",
+ "Alvis", "Alvor", "Alvos", "Alvur", "Anas", "Anden", "Andril",
+ "Anel", "Angaredhel", "Aras", "Arelvam", "Aren", "Arethan", "Arnas",
+ "Aroa", "Aron", "Arsyn", "Arven", "Arver", "Arvs", "Arvyn", "Aryon",
+ "Athal", "Athanden", "Athelyn", "Ather", "Athyn", "Avron",
+ "Baladas", "Balver", "Balyn", "Banden", "Banor", "Baren", "Barusi",
+ "Bedal", "Belas", "Beldrose", "Belos", "Bels", "Belvis", "Benar",
+ "Beraren", "Berel", "Berela", "Bertis", "Bervaso", "Bervyn",
+ "Bethes", "Bevadar", "Bildren", "Bilen", "Bilos", "Birer", "Bolayn",
+ "Boler", "Bolnor", "Bols", "Bolvus", "Bolvyn", "Bolyn", "Boryn",
+ "Bradil", "Bralas", "Bralen", "Bralis", "Bralyn", "Brarayni",
+ "Bratheru", "Brathus", "Bravosi", "Braynas", "Brelar", "Brelo",
+ "Brelyn", "Brerama", "Brethas", "Breves", "Breynis", "Briras",
+ "Broder", "Broris", "Brothes", "Dalam", "Daldur", "Dalin", "Dalmil",
+ "Dalos", "Dals", "Dalvus", "Danar", "Dandras", "Danel", "Daral",
+ "Daras", "Daren", "Darns", "Daroder", "Dartis", "Darvam", "Daryn",
+ "Dather", "Dathus", "Davas", "Davis", "Davur", "Daynes", "Daynil",
+ "Dedaenc", "Delmon", "Delmus", "Delvam", "Deras", "Dethresa",
+ "Deval", "Devas", "Dils", "Dinor", "Dirver", "Divayth", "Dolmyn",
+ "Dolyn", "Dondos", "Donus", "Dovor", "Dovres", "Dralas", "Drals",
+ "Dralval", "Dram", "Dramis", "Drandryn", "Dranos", "Drarayne",
+ "Drarel", "Draron", "Drarus", "Draryn", "Drathyn", "Dravasa",
+ "Dredase", "Drelayn", "Drelis", "Drelse", "Drerel", "Dreynis",
+ "Dreynos", "Dridas", "Dridyn", "Drinar", "Drodos", "Dronos",
+ "Drores", "Drulvan", "Duldrar", "Dunel", "Edd", "Edras", "Edril",
+ "Elam", "Eldil", "Eldrar", "Elethus", "Elms", "Elo", "Elvas",
+ "Elvil", "Endar", "Endris", "Endryn", "Endul", "Erene", "Erer",
+ "Ereven", "Eris", "Ernil", "Erns", "Ervas", "Ethes", "Ethys", "Evo",
+ "Evos", "Fadren", "Falam", "Falso", "Falvel", "Falvis", "Farvam",
+ "Farvyn", "Favas", "Favel", "Faven", "Faver", "Faves", "Fedar",
+ "Felayn", "Felen", "Felisi", "Felsen", "Felvan", "Felvos", "Femer",
+ "Fendros", "Fendryn", "Feranos", "Ferele", "Feril", "Feruren",
+ "Fervas", "Fevris", "Fevus", "Fevyn", "Folms", "Folvys", "Folyni",
+ "Fons", "Fonus", "Forven", "Foryn", "Fothas", "Fothyna", "Foves",
+ "Fovus", "Gadayn", "Gaelion", "Galam", "Galdres", "Galen", "Galis",
+ "Galmis", "Galms", "Gals", "Gamin", "Ganalyn", "Ganus", "Garer",
+ "Garisa", "Garnas", "Garvs", "Garyn", "Gathal", "Gavas", "Gavesu",
+ "Gavis", "Gidar", "Giden", "Gilan", "Gilmyn", "Gilur", "Gilvas",
+ "Gilyan", "Gilyn", "Gilyne", "Gindas", "Ginur", "Giras", "Giren",
+ "Giron", "Giryn", "Golar", "Goldyn", "Goler", "Gols", "Golven",
+ "Goras", "Gordol", "Goren", "Goris", "Goron", "Gothren", "Goval",
+ "Gragus", "Gulmon", "Guls", "Guril", "Helseth", "Hlaren", "Hlaroi",
+ "Hlenil", "Hleras", "Hloris", "Hort", "Idros", "Ildos", "Ilen",
+ "Ilet", "Ilver", "Iner", "Irarak", "Irer", "Irver", "Ivulen",
+ "Jiub", "Llaals", "Llanas", "Llandras", "Llandris", "Llanel",
+ "Llarar", "Llarel", "Llaren", "Llaro", "Llavam", "Lleran", "Lleras",
+ "Lleris", "Llero", "Llether", "Llevas", "Llevel", "Lliram",
+ "Lliros", "Lliryn", "Lloden", "Llonas", "Llondryn", "Lloros",
+ "Llovyn", "Madran", "Madres", "Madsu", "Malar", "Mallam", "Mals",
+ "Manabi", "Mandran", "Mandur", "Mandyn", "Manel", "Maner",
+ "Manolos", "Marayn", "Maros", "Mastrius", "Mathis", "Mathyn",
+ "Mavis", "Mavon", "Mavus", "Meder", "Medyn", "Melar", "Melur",
+ "Menus", "Meril", "Mertis", "Mertisi", "Mervis", "Mervs", "Meryn",
+ "Methal", "Methas", "Mevel", "Meven", "Mevil", "Midar", "Milar",
+ "Mils", "Milyn", "Miner", "Miron", "Mirvon", "Mivul", "Mondros",
+ "Movis", "Muvis", "Nads", "Nalis", "Nalmen", "Nalosi", "Nals",
+ "Nalur", "Naral", "Naris", "Nathyn", "Navam", "Navil", "Neldris",
+ "Nelmil", "Nelos", "Neloth", "Nels", "Nelvon", "Nelyn", "Nerer",
+ "Nethyn", "Nevil", "Nevon", "Nevos", "Nevosi", "Niden", "Nilas",
+ "Nilos", "Niras", "Nivel", "Nivos", "Norus", "Odral", "Odron",
+ "Oisig", "Ondar", "Ondres", "Orns", "Orval", "Orvas", "Ovis",
+ "Ralam", "Ralds", "Ralmyn", "Ralos", "Ranes", "Ranor", "Rararyn",
+ "Raril", "Raryn", "Rathal", "Raviso", "Ravos", "Raynilie", "Relam",
+ "Relas", "Relen", "Relms", "Rels", "Relur", "Relyn", "Remas",
+ "Rernel", "Reron", "Rervam", "Reynis", "Rilas", "Rilos", "Rilver",
+ "Rindral", "Rirnas", "Rirns", "Rivame", "Rolis", "Rols", "Roner",
+ "Rothis", "Rovone", "Sadas", "Sadryn", "Salas", "Salen", "Salvas",
+ "Salver", "Salyn", "Sanvyn", "Saras", "Sarayn", "Sarvil", "Sarvur",
+ "Saryn", "Sathas", "Savor", "Savure", "Sedam", "Sedrane", "Seldus",
+ "Seler", "Selman", "Selmen", "Selvil", "Sendel", "Sendus", "Seras",
+ "Serer", "Serul", "Seryn", "Sevilo", "Shashev", "Sodres", "Sortis",
+ "Sovor", "Stlennius", "Sulen", "Sulis", "Sunel", "Sur", "Suryn",
+ "Suvryn", "Svadstar", "Tadas", "Talms", "Tandram", "Tanel", "Tanur",
+ "Tarar", "Tarer", "Taros", "Tarvus", "Tarvyn", "Taves", "Tedril",
+ "Tedryn", "Tedur", "Telis", "Tels", "Telvon", "Temis", "Tendren",
+ "Tendris", "Tens", "Terer", "Teres", "Teris", "Tervur", "Tevyn",
+ "Thadar", "Thaden", "Thanelen", "Tharer", "Thauraver", "Theldyn",
+ "Thervam", "Tholer", "Thoryn", "Threvul", "Tidras", "Tidros",
+ "Tinos", "Tiram", "Tiras", "Tirer", "Tirnur", "Tirvel", "Tivam",
+ "Toris", "Tralas", "Tralayn", "Traven", "Tredyn", "Trelam", "Trels",
+ "Trendrus", "Treram", "Treras", "Trevyn", "Trilam", "Trivon",
+ "Tuls", "Ultis", "Ulves", "Ulvil", "Ulvon", "Unel", "Uradras",
+ "Ureval", "Urnel", "Urvel", "Urven", "Uryn", "Uthrel", "Uvele",
+ "Uvren", "Vaden", "Vanel", "Vares", "Varis", "Varon", "Varvur",
+ "Vatollia", "Vaves", "Vavran", "Vedam", "Vedran", "Velis", "Velms",
+ "Velyn", "Veros", "Vevos", "Vevul", "Vilval", "Vilyn", "Viras",
+ "Virvyn", "Vobend", "Vonden", "Vonos", "Vorar", "Voruse",
+ "Vuvil", "Adrusu", "Alarvyne", "Alavesa", "Aldyne", "Alenus",
+ "Aleri", "Alfe", "Almse", "Almsi", "Aloie", "Alonisea", "Alurue",
+ "Alvela", "Alveno", "Alvura", "Alynu", "Amili", "Andalin", "Andilo",
+ "Andilu", "Ane", "Angahran", "Anis", "Anise", "Aralosea", "Arara",
+ "Arns", "Arnsa", "Arnsi", "Artisa", "Arvama", "Arvamea", "Arvela",
+ "Arvso", "Aryne", "Aryni", "Athesie", "Avoni", "Badala", "Badama",
+ "Balen", "Baleni", "Balsa", "Balynu", "Barenziah", "Bedenea",
+ "Bedynea", "Beleru", "Bevene", "Beyte", "Bidsi", "Bilsa", "Birama",
+ "Bivale", "Boderi", "Bodsa", "Boldrisa", "Bralsea", "Brara",
+ "Bravora", "Bredasu", "Brelayne", "Brelda", "Brelyna", "Brerayne",
+ "Brevasu", "Brevosi", "Brildraso", "Brilnosu", "Bronosa", "Dalami",
+ "Dalnorea", "Dalse", "Dalyne", "Danaronea", "Danasi", "Dandera",
+ "Dandynea", "Danoso", "Danso", "Darane", "Dareru", "Daroso",
+ "Darvala", "Darvame", "Darvasa", "Darvynea", "Daynali", "Daynas",
+ "Daynillo", "Deldasa", "Deldrise", "Delmene", "Delte", "Delyna",
+ "Derar", "Derayna", "Dilami", "Dileno", "Dilvene", "Dinara",
+ "Dinere", "Dinuro", "Diradeni", "Dirara", "Diren", "Dolmesa",
+ "Dolsa", "Dolvasie", "Domesea", "Dorisa", "Dorynu", "Dothasi",
+ "Dovrosi", "Dralasa", "Dralcea", "Dralisi", "Dralora", "Dralosa",
+ "Dralsea", "Draramu", "Drarayne", "Dratha", "Dravynea", "Dredyni",
+ "Drelasa", "Drelyne", "Drendrisa", "Dreveni", "Drilame", "Driloru",
+ "Drireri", "Drolora", "Drorayni", "Drulene", "Drurile", "Duldresi",
+ "Dulnea", "Edryno", "Eldrasea", "Eldrilu", "Elmera", "Elmussa",
+ "Elvasea", "Elynea", "Elynu", "Endase", "Endroni", "Eralane",
+ "Erirvase", "Ernse", "Ervesa", "Ervona", "Ervyna", "Ethal",
+ "Ethasi", "Evesa", "Evilu", "Fadase", "Fadile", "Falanu", "Falena",
+ "Falura", "Fanasa", "Fanisea", "Fanuse", "Faral", "Faralenu",
+ "Farare", "Faras", "Farena", "Farusea", "Fathasa", "Fathusa",
+ "Favani", "Favela", "Favilea", "Favise", "Favona", "Fedura",
+ "Feldrelo", "Felisa", "Felmena", "Felsa", "Felsu", "Feralea",
+ "Ferise", "Ferone", "Fervsea", "Ferynu", "Fevasa", "Fevila",
+ "Fieryra", "Folsi", "Folvalie", "Fomesa", "Fonari", "Fonas",
+ "Forvse", "Gadasu", "Gadela", "Gadyni", "Galas", "Galasa", "Galdal",
+ "Galeri", "Galero", "Galore", "Galsu", "Galuro", "Galvene",
+ "Galviso", "Galyn", "Gandela", "Gandosa", "Garalo", "Garas",
+ "Garila", "Garyne", "Gilse", "Ginadura", "Gindrala", "Girara",
+ "Girvani", "Girynu", "Golana", "Golena", "Golmerea", "Golveso",
+ "Golvyni", "Gomeso", "Gorenea", "Gorven", "Guldrise", "Gulena",
+ "Gulvilie", "Gureryne", "Haleneri", "Hlavora", "Hlendrisa",
+ "Hlevala", "Hlireni", "Hlodala", "Idrenie", "Idronea", "Idroso",
+ "Idula", "Ienasa", "Ienase", "Ienaso", "Ilmeni", "Ilmyna",
+ "Indrele", "Inera", "Irna", "Irvama", "Irvsie", "Ivela", "Iveri",
+ "Ivramie", "Ivrosa", "Lauravenya", "Llaalamu", "Llaalsa",
+ "Llandrale", "Llandreri", "Llarara", "Llaros", "Llarusea",
+ "Llathise", "Llathyno", "Llavane", "Llavelea", "Llavesa",
+ "Llaynasa", "Lledsa", "Lledsea", "Llemisa", "Llerusa", "Llevana",
+ "Llirala", "Llivas", "Llondresa", "Llorayna", "Llunela", "Madayna",
+ "Madaynu", "Madrale", "Madura", "Malsa", "Malven", "Manara",
+ "Manse", "Manwe", "Maralie", "Marasa", "Maren", "Marena", "Marilia",
+ "Mathesa", "Medila", "Medresi", "Melsu", "Meluria", "Melvona",
+ "Melvuli", "Melvure", "Meralyn", "Methulu", "Mevrenea", "Mevure",
+ "Miara", "Milara", "Miluru", "Milvela", "Milvonu", "Minasi",
+ "Mindeli", "Miraso", "Mirnelea", "Mornsu", "Moroni", "Morusu",
+ "Movisa", "Muldroni", "Mulvisie", "Mundrila", "Muvrulea", "Nadene",
+ "Nalami", "Nalasa", "Nalmila", "Nalsie", "Nalvilie", "Nalvyna",
+ "Narese", "Narile", "Narisa", "Nartise", "Nathala", "Nathyne",
+ "Nedeni", "Nelmyne", "Nelso", "Nerile", "Nervana", "Nevama",
+ "Nevena", "Nevrasa", "Nevrila", "Nevusa", "Nidara", "Nidryne",
+ "Nileno", "Nilera", "Nilvyn", "Nina", "Nirasa", "Nireli",
+ "Noldrasi", "Nothasea", "Novrynea", "Nuleno", "Nurisea", "Olvyne",
+ "Omesu", "Orero", "Orvona", "Radene", "Raldenu", "Ranis", "Ranosa",
+ "Rarusu", "Rarvela", "Rathyne", "Ravani", "Raven", "Ravoso",
+ "Rayna", "Raynasa", "Raynila", "Relamu", "Relmerea", "Relosa",
+ "Relvese", "Remasa", "Rerilie", "Rerynea", "Reynel", "Ridena",
+ "Rilasi", "Rilvase", "Rinori", "Riraynea", "Rolasa", "Runethyne",
+ "Ruthrisu", "Ruvene", "Sadal", "Sadela", "Salama", "Salora",
+ "Salyni", "Sanaso", "Saruse", "Sathasa", "Satheri", "Satyana",
+ "Savesea", "Savile", "Sedris", "Sedyni", "Selvura", "Senise",
+ "Serila", "Sernsi", "Seryne", "Sethesi", "Sevame", "Sevisa",
+ "Sevyni", "Sodrara", "Sondryn", "Sorosi", "Sovali", "Sovisa",
+ "Suldreni", "Tadara", "Tadera", "Talamu", "Talare", "Talmeni",
+ "Talmsa", "Talsi", "Taluri", "Taluro", "Tamira", "Tanar",
+ "Tandasea", "Tanisie", "Tanusea", "Tarani", "Tavilu", "Tavynu",
+ "Tedysa", "Teleri", "Telura", "Tenaru", "Tenisi", "Terenu",
+ "Tereri", "Teril", "Teruise", "Teryne", "Thalurea", "Thavere",
+ "Thelsa", "Thelvamu", "Therana", "Thilse", "Thovasi", "Thurisea",
+ "Tilena", "Tilore", "Tinaso", "Tirasie", "Tirele", "Tolmera",
+ "Tolvise", "Tolvone", "Tonas", "Tonasi", "Toranu", "Torasa",
+ "Torosi", "Traldrisa", "Traynili", "Tredere", "Tremona", "Trerayna",
+ "Trivura", "Tumsa", "Tunila", "Tuvene", "Tuvenie", "Tuveso",
+ "Ulenea", "Uleni", "Ulmesi", "Ulmiso", "Ulvena", "Ulveni", "Ulyne",
+ "Ulyno", "Unila", "Urandile", "Urene", "Uresa", "Ureso", "Urtisa",
+ "Urtiso", "Uryne", "Uupse", "Uvisea", "Uvoo", "Vadeni", "Vadramea",
+ "Vadusa", "Valveli", "Valvesu", "Valvosa", "Valyne", "Varasa",
+ "Varenu", "Varona", "Varvsa", "Vaveli", "Vedelea", "Velanda",
+ "Velyna", "Venasa", "Vendrela", "Verara", "Vevrana", "Vilvyni",
+ "Vindamea", "Vindyne", "Vireveri", "Vivyne", "Volene", "Volmyni",
+ "Voneri", "Vuldronu", "Vulyne"];
+
+ const surnames = ["Dagoth", "Andrano", "Andrethi", "Ienith", "Hlaalu",
+ "Arvel", "Dralor", "Llervu", "Sadri", "Saren", "Andas", "Dren",
+ "Faryon", "Girith", "Hleran", "Indaram", "Aryon", "Indaren",
+ "Indrano", "Sarano", "Seran", "Andarys", "Andus", "Arenim",
+ "Athren", "Farano", "Fyr", "Gilnith", "Hlaren", "Llethri", "Maryon",
+ "Omayn", "Relas", "Salas", "Saryon", "Uvayn", "Vendu", "Andaram",
+ "Aralas", "Arelas", "Arobar", "Helas", "Hlervu", "Llaren", "Lleran",
+ "Maren", "Nerethi", "Omoran", "Oran", "Othravel", "Othril",
+ "Rathryon", "Rethan", "Retheran", "Salvani", "Saram", "Sarethi",
+ "Seloth", "Senim", "Teran", "Tharen", "Ules", "Velas", "Venim",
+ "Veran", "Verethi", "Virith", "Adas", "Adren", "Alen", "Andalas",
+ "Andalen", "Andoril", "Andules", "Arano", "Aravel", "Aren",
+ "Arethan", "Arethi", "Beleth", "Berano", "Dral", "Dralas", "Drelas",
+ "Drenim", "Drethan", "Drothan", "Helvi", "Henim", "Ieneth",
+ "Indalas", "Irano", "Llaram", "Llarys", "Llenim", "Llethan",
+ "Lloran", "Mandas", "Nethan", "Omalen", "Omavel", "Oren", "Orethi",
+ "Oril", "Othan", "Othran", "Othren", "Radas", "Ralen", "Rendas",
+ "Sadus", "Sarendas", "Sarys", "Seleth", "Serethi", "Tedas", "Tenim",
+ "Thelas", "Thirandus", "Thirano", "Uvaren", "Uvenim", "Uveran",
+ "Varen", "Varis", "Alver", "Andaren", "Andavel", "Andoren",
+ "Andrelo", "Aralen", "Areleth", "Arinith", "Arothan", "Athram",
+ "Athrys", "Balen", "Belas", "Berendas", "Berethi", "Dalen",
+ "Darethi", "Daryon", "Darys", "Dran", "Drom", "Falas", "Falen",
+ "Faram", "Faren", "Farethi", "Farys", "Favelnim", "Gilvayn",
+ "Heleran", "Heran", "Hlaalo", "Hlan", "Hlas", "Hlen", "Hler",
+ "Hloran", "Indalen", "Indarys", "Llendu", "Marvel", "Marys",
+ "Moren", "Morvayn", "Mothryon", "Nelas", "Nerano", "Nirith",
+ "Norvayn", "Norvayne", "Omalas", "Omalor", "Omoril", "Omothan",
+ "Othralen", "Othrelas", "Othreleth", "Othreloth", "Othrenim",
+ "Ralas", "Raledran", "Ravel", "Releth", "Romoren", "Romori",
+ "Rothandus", "Samori", "Sarandas", "Sarothril", "Savel", "Savil",
+ "Sedas", "Selaren", "Selas", "Selvilo", "Sendas", "Sethan", "Telas",
+ "Thendas", "Tures", "Ulven", "Uvelas", "Uvirith", "Varam", "Vari",
+ "Varyon", "Varys", "Vedas", "Vedran", "Veleth", "Verano", "Vules",
+ "Adram", "Adryn", "Adus", "Alam", "Alan", "Alari", "Alvor", "Amori",
+ "Andalor", "Andothan", "Andral", "Andrani", "Andrilo", "Androm",
+ "Andromo", "Androthi", "Apo", "Aradil", "Aram", "Areloth", "Ares",
+ "Areth", "Arns", "Arval", "Athelvis", "Athin", "Athones", "Avani",
+ "Avel", "Avilo", "Balur", "Balvel", "Bandas", "Baram", "Barelo",
+ "Baren", "Baro", "Barus", "Baryon", "Barys", "Bavani", "Bedas",
+ "Belaal", "Belan", "Belaram", "Belden", "Beloren", "Bels",
+ "Belvani", "Belvayn", "Belvilo", "Bemis", "Benelas", "Beneran",
+ "Benethran", "Beni", "Bereloth", "Beren", "Berendus", "Berer",
+ "Bero", "Bethrano", "Bethrimo", "Bradyn", "Braryn", "Braven",
+ "Brenos", "Brenur", "Brilyn", "Carvaren", "Dalas", "Dalis",
+ "Dalobar", "Dalomo", "Dals", "Dalvani", "Damori", "Danoran",
+ "Daram", "Darano", "Daren", "Darethran", "Darothril", "Darvel",
+ "Dathren", "Davor", "Davus", "Daynes", "Delms", "Deltis", "Delvi",
+ "Demnevanni", "Deras", "Dilmyn", "Dobar", "Doran", "Doren",
+ "Dorvayn", "Doves", "Dradas", "Dralayn", "Dralen", "Dralno",
+ "Drals", "Drath", "Drathen", "Dredayn", "Dredil", "Dreleth",
+ "Dreloth", "Dres", "Dreth", "Driler", "Drilvi", "Drin", "Drinith",
+ "Drivam", "Drobar", "Drolan", "Drolnor", "Drora", "Droryn", "Droth",
+ "Drurel", "Dulfass", "Dulni", "Duro", "Elarven", "Elval", "Elvul",
+ "Ertis", "Evos", "Falandas", "Falavel", "Falos", "Fals", "Falvani",
+ "Famori", "Faralen", "Farandas", "Faravel", "Fareloth", "Farethan",
+ "Farothran", "Fatheran", "Fathyron", "Favani", "Faveran", "Fedos",
+ "Felas", "Felder", "Fels", "Fendyn", "Fererus", "Fevur", "Folvyn",
+ "Gadar", "Galen", "Gals", "Garer", "Garil", "Garvon", "Gavos",
+ "Gavyn", "Gidran", "Gilaram", "Gilvani", "Gilvilo", "Gimalvel",
+ "Gimayn", "Gindu", "Ginith", "Giral", "Giralvel", "Girando",
+ "Girano", "Girendas", "Girethi", "Girothran", "Girvayne",
+ "Githendas", "Githrano", "Givyn", "Gobor", "Golathyn", "Gols",
+ "Goran", "Gorvas", "Guls", "Guvron", "Hardil", "Heladren", "Helni",
+ "Helothan", "Helothran", "Helothren", "Herandus", "Herendas",
+ "Herothran", "Hlaano", "Hlando", "Hlarar", "Hlarys", "Hledas",
+ "Hledri", "Ildram", "Ilnith", "Imayn", "Indavel", "Indobar",
+ "Indoran", "Indules", "Inlador", "Irathi", "Irethi", "Ledd",
+ "Lladri", "Llandu", "Llendo", "Llerayn", "Llervi", "Lleryn",
+ "Lloryn", "Llothas", "Llothri", "Madalas", "Madalvel", "Madryon",
+ "Malas", "Maloren", "Malvayn", "Manas", "Manel", "Mano", "Marvayn",
+ "Marvos", "Mathendis", "Mavandes", "Mels", "Menas", "Mencele",
+ "Merys", "Milar", "Milo", "Mirel", "Molor", "Moran", "Nadram",
+ "Nadus", "Nalyn", "Naros", "Navur", "Nedalor", "Neladren",
+ "Nelaram", "Neleth", "Nelvani", "Nelvayn", "Nelvilo", "Nerandas",
+ "Nerothan", "Nerothren", "Nerus", "Nervion", "Nethalen", "Nilem",
+ "Nilvon", "Nithryon", "Nolar", "Nothro", "Nothryon", "Nulen",
+ "Ofemalen", "Omani", "Omaren", "Ondyn", "Onmar", "Orelu", "Ores",
+ "Oreyn", "Othralas", "Othrobar", "Quintella", "Radarys", "Radobar",
+ "Ralaal", "Raloran", "Ralvani", "Ralvayn", "Ramarys", "Ramoran",
+ "Ramori", "Ramothran", "Randas", "Raram", "Rathri", "Redas",
+ "Redothril", "Reladren", "Relarys", "Relavel", "Relenim", "Relnim",
+ "Reloro", "Reloth", "Relvani", "Rendo", "Reni", "Renim", "Reram",
+ "Rervam", "Rethelas", "Rethul", "Reyas", "Rilvayn", "Rindo",
+ "Rindu", "Rinith", "Rivul", "Rols", "Romandas", "Romari", "Romavel",
+ "Romayn", "Romoran", "Romothran", "Rothalen", "Rothalnim",
+ "Rothalor", "Rothan", "Rothari", "Rotheloth", "Rotheran",
+ "Rothrano", "Rothren", "Rurvyn", "Ryon", "Sadalas", "Sadalvel",
+ "Sadas", "Sadoro", "Sadralo", "Sadrano", "Sadryon", "Sadrys",
+ "Sala", "Salam", "Salandas", "Salaren", "Salaron", "Salavel",
+ "Salen", "Salenim", "Salmyn", "Salobar", "Salor", "Salvi",
+ "Samandas", "Sandus", "Sarandus", "Sarathram", "Sareloth",
+ "Sarethan", "Sari", "Sarinith", "Sarobar", "Sarothran", "Sarothren",
+ "Saryoni", "Sathendas", "Sathis", "Sathren", "Sathryon", "Savani",
+ "Sedrethi", "Sedri", "Selandas", "Selaro", "Selarys", "Seles",
+ "Selothan", "Selvayn", "Sendu", "Senoril", "Seralas", "Serano",
+ "Seri", "Serothan", "Serven", "Sethandas", "Sethandus", "Sethri",
+ "Surishpi", "Talds", "Tedalen", "Tedran", "Telandas", "Telmon",
+ "Telnim", "Telvani", "Teneran", "Terandas", "Terano", "Teri",
+ "Teria", "Terilu", "Tervayn", "Thalas", "Thalor", "Thando",
+ "Tharam", "Tharyon", "Tharys", "Theman", "Thenim", "Therayn",
+ "Therethi", "Thilandas", "Thilarvel", "Thimalvel", "Thindo",
+ "Thiralas", "Thireloth", "Thirith", "Thirothan", "Thirvayn",
+ "Tilvur", "Tistar", "Tobor", "Trandel", "Tunel", "Tyravel", "Uleni",
+ "Ulessen", "Ulom", "Ulvel", "Ulver", "Urns", "Urvon", "Urvyn",
+ "Uvalas", "Uvalen", "Uvalor", "Uvani", "Uvaram", "Uveleth",
+ "Uvulas", "Vadryon", "Valaai", "Valas", "Valen", "Valno", "Valor",
+ "Vando", "Vandram", "Varo", "Vavas", "Vavyn", "Vedaren", "Vedralu",
+ "Vedrano", "Velendas", "Velni", "Veloren", "Veloth", "Velothren",
+ "Velothril", "Veralor", "Verelas", "Verendas", "Veri", "Verilnith",
+ "Verothan", "Viake", "Vian", "Vibato", "Vidron", "Vilas", "Vinden",
+ "Volos", "Alas", "Aran", "Arys", "Beran", "Dareleth", "Dulo",
+ "Fadathram", "Favel", "Gimothran", "Helan", "Hlervi", "Llando",
+ "Marvani", "Raviro", "Redoran", "Rethandus", "Salothan",
+ "Salothran", "Salvel", "Samarys", "Sandas", "Telvayn", "Tharys",
+ "Vandus", "Verelnim"];
+
+ const factions = ["Great House Redoran", "Great House Hlaalu", "Great House Telvanni",
+ "Vampire Clan Aundae", "Vampire Clan Berne", "Vampire Clan Quarra",
+ "Tribunal Temple", "Imperial Cult", "Sixth House or a Daedra Cult",
+ "Fighter's Guild", "Mage's Guild", "Thieves Guild", "Blades",
+ "Morag Tong", "Imperial Legion", "East Empire Company"];
+
+ const classes = ["Acrobat", "Agent", "Archer", "Assassin", "Barbarian",
+ "Bard", "Battlemage", "Crusader", "Healer", "Knight", "Mage", "Monk",
+ "Nightblade", "Pilgrim", "Rogue", "Scout", "Sorcerer", "Spellsword",
+ "Thief", "Warrior", "Witchhunter"];
+
+ const hometowns = ["Ald Velothi", "Ald'ruhn", "Balmora", "Caldera",
+ "Dagon Fel", "Ebonheart", "Gnisis", "Hla Oad", "Khuul", "Maar Gan",
+ "Molag Mar", "Mournhold", "Pelagiad", "Sadrith Mora", "Seyda Neen",
+ "Skaal Village", "Suran", "Tel Aruhn", "Tel Branora", "Tel Fyr",
+ "Tel Mora", "Vivec", "Vos"];
+
+ const birthsigns = ["Warrior", "Mage", "Thief", "Serpent", "Lady", "Steed",
+ "Lord", "Apprentice", "Atronach", "Ritual", "Lover", "Shadow", "Tower"];
+
+ const races = ["Altmer", "Argonian", "Bosmer", "Breton", "Dunmer",
+ "Imperial", "Khajiit", "Nord", "Orc", "Redguard"];
+
+ let firstFaction = Math.floor(Math.random() * factions.length);
+ document.getElementById("nameField").value = firstNames[Math.floor(Math.random()*firstNames.length)] + " " + surnames[Math.floor(Math.random()*surnames.length)];
+ document.getElementById("factionField1").value = factions[firstFaction];
+ document.getElementById("factionField2").value = factions[secondFaction(firstFaction, factions)];
+ document.getElementById("classField").value = classes[Math.floor(Math.random()*classes.length)];
+ document.getElementById("hometownField").value = hometowns[Math.floor(Math.random()*hometowns.length)];
+ document.getElementById("birthsignField").value = birthsigns[Math.floor(Math.random()*birthsigns.length)];
+ document.getElementById("raceField").value = races[Math.floor(Math.random()*races.length)];
+}
+
+function secondFaction(firstFaction, factions){
+ let result = firstFaction;
+ // If the player has already been assigned a great house, choose a non-great
+ // house faction instead (player cannot be a member of more than one).
+ if (firstFaction <= 2)
+ while (result <= 2)
+ result = Math.floor(Math.random()*factions.length);
+ // If player is a member of one of the vampire clans, choose another faction
+ // that isn't a vampire clan (player cannot be a member of more than one).
+ else if (firstFaction >= 3 && firstFaction <= 5)
+ while (result >= 3 && result <= 5)
+ result = Math.floor(Math.random()*factions.length);
+ // If a player is a member of one of the cults, choose another faction that
+ // isn't another cult (otherwise it wouldn't make sense roleplay-wise).
+ else if (firstFaction >= 6 && firstFaction <= 8)
+ while (result >= 6 && result <= 8)
+ result = Math.floor(Math.random()*factions.length);
+ // If none of the above conditions are true, choose any faction other than
+ // the one already chosen.
+ else
+ while (result === firstFaction)
+ result = Math.floor(Math.random()*factions.length);
+ return (result);
+}
diff --git a/static/js/roll.js b/static/js/roll.js
@@ -0,0 +1,135 @@
+/*roll.js
+* Copyright (C) 2019,2022 Jake Bauer
+* Licensed under the ISC License.
+*/
+
+/* stringRoll()
+ * @brief This function rolls dice based on the input from the text-field
+ */
+function stringRoll() {
+ let rollString = document.getElementById("inputString").value;
+ let result = 0;
+ let numRolls, die, operation, modifier, resultStr = "";
+
+ // Parse values from string
+ try {
+ numRolls = rollString.match(/\d+d/ig)[0];
+ numRolls = numRolls.substring(0, numRolls.length-1);
+ die = rollString.match(/d\d+/ig)[0];
+ die = die.substring(1);
+ }
+ catch(err) {
+ console.log(err);
+ alert("Invalid text input! See example for proper string format.");
+ return;
+ }
+ try {
+ operation = rollString.match(/[\+\-]/ig)[0];
+ modifier = rollString.match(/\d+$/ig)[0];
+ }
+ catch(TypeError) {
+ // Ignore missing operation or modifier strings
+ }
+
+ // Conduct rolls
+ for (let i = 0; i < numRolls; i++) {
+ let intermediate = Math.floor((Math.random()*die)+1);
+ if (i == numRolls-1) {
+ // If it's the last roll, don't add a + symbol to the string
+ resultStr += intermediate;
+ }
+ else {
+ resultStr += intermediate + " + ";
+ }
+ result += intermediate;
+ }
+ // Finalize the result string
+ resultStr += " = " + result;
+ if (numRolls == 1) {
+ resultStr = result;
+ }
+ // Apply the modifier
+ resultStr = "d"+ die + ": " + resultStr;
+ if (operation === '-') {
+ result = Number(result) - Number(modifier);
+ resultStr += " - " + modifier + " = " + result;
+ }
+ else if (operation === '+') {
+ result = Number(result) + Number(modifier);
+ resultStr += " + " + modifier + " = " + result;
+ }
+ // Add the result to the history box
+ let hist = document.getElementById("history-text");
+ hist.innerHTML = (resultStr + "\n") + hist.innerHTML;
+}
+
+/* roll()
+ * @brief This function rolls the dice according to which button was pressed
+ * @input Element The button representing which dice to roll
+ */
+function roll(element) {
+ let btnId = (element.id).substring(1);
+ let numRolls = document.getElementById(('num'+btnId)).value;
+ let modifier = document.getElementById(('mod'+btnId)).value;
+ let result = 0;
+ let resultStr = "";
+ // Conduct rolls
+ for (let i = 0; i < numRolls; i++) {
+ let intermediate = Math.floor((Math.random()*btnId)+1);
+ if (i == numRolls-1) {
+ // If it's the last roll, don't add a + symbol to the string
+ resultStr += intermediate;
+ }
+ else {
+ resultStr += intermediate + " + ";
+ }
+ result += intermediate;
+ }
+ // Finalize the result string
+ resultStr += " = " + result;
+ if (numRolls == 1) {
+ resultStr = result;
+ }
+ // Apply the modifier
+ result = Number(result) + Number(modifier);
+ resultStr = "d"+ btnId + ": " + resultStr;
+ if (modifier < 0) {
+ resultStr += " - " + Math.abs(modifier) + " = " + result;
+ }
+ else if (modifier > 0) {
+ resultStr += " + " + modifier + " = " + result;
+ }
+ // Show the result as a number in the die's row
+ document.getElementById(("d"+btnId+"result")).innerHTML = result;
+ // Add the result to the history box
+ let hist = document.getElementById("history-text");
+ hist.innerHTML = resultStr + "<br />" + hist.innerHTML;
+}
+
+/* clear_history()
+ * @brief This function clears the history box, restting it back to default
+ * values while also clearing results and input boxes.
+ */
+function clear_history() {
+ let results = document.getElementsByTagName("p");
+ for (let i = 0; i < Object.keys(results).length; i++) {
+ element = results[i];
+ if (element.getAttribute("class") == "field") {
+ element.innerHTML = "0";
+ }
+ }
+ let inputs = document.getElementsByTagName("input");
+ for (let i = 0; i < Object.keys(inputs).length; i++) {
+ element = inputs[i];
+ if (element.getAttribute("type") == "number") {
+ if (element.getAttribute("min")) {
+ element.value = 1;
+ }
+ else {
+ element.value = 0;
+ }
+ }
+ }
+ let hist = document.getElementById("history-text");
+ hist.innerHTML = "";
+}
diff --git a/static/js/time-duration-calculator.js b/static/js/time-duration-calculator.js
@@ -0,0 +1,116 @@
+/*
+* time-duration-calculator.js
+*
+* Copyright (C) 2020 Jake Bauer <jbauer@paritybit.ca>
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <https://www.gnu.org/licenses/>.
+*/
+
+startTimeH = 0;
+startTimeM = 0;
+startTimeS = 0;
+
+endTimeH = 0;
+endTimeM = 0;
+endTimeS = 0;
+
+resultTimeH = 0;
+resultTimeM = 0;
+resultTimeS = 0;
+
+totalTimeH = 0;
+totalTimeM = 0;
+totalTimeS = 0;
+
+// From: https://gist.github.com/andrewrk/4382935
+function pad_with_zeros(number, size) {
+ number = number.toString();
+ while (number.length < size) number = "0" + number;
+ return number;
+}
+
+function clear_inputs() {
+ document.getElementById("start-time-h").value = "";
+ document.getElementById("start-time-m").value = "";
+ document.getElementById("start-time-s").value = "";
+ document.getElementById("end-time-h").value = "";
+ document.getElementById("end-time-m").value = "";
+ document.getElementById("end-time-s").value = "";
+}
+
+function get_inputs() {
+ startTimeH = Number(document.getElementById("start-time-h").value);
+ startTimeM = Number(document.getElementById("start-time-m").value);
+ startTimeS = Number(document.getElementById("start-time-s").value);
+ endTimeH = Number(document.getElementById("end-time-h").value);
+ endTimeM = Number(document.getElementById("end-time-m").value);
+ endTimeS = Number(document.getElementById("end-time-s").value);
+
+ if (startTimeH < 0 || startTimeH > 23 || endTimeH < 0 || endTimeH > 23) {
+ alert("Hours must be between 0 and 23");
+ throw "Error: Number out of bounds.";
+ }
+ if (startTimeM < 0 || startTimeM > 59 || endTimeM < 0 || endTimeM > 59
+ || startTimeS < 0 || startTimeS > 59 || endTimeS < 0 || endTimeS > 59) {
+ alert("Seconds/Minutes must be between 0 and 59");
+ throw "Error: Number out of bounds.";
+ }
+}
+
+function display_results() {
+ resultString = pad_with_zeros(resultTimeH, 2) +
+ "h:" + pad_with_zeros(resultTimeM, 2) +
+ "m:" + pad_with_zeros(resultTimeS, 2) + "s";
+ document.getElementById("result-field").innerHTML = resultString;
+ document.getElementById("result-field-hours").innerHTML = totalTimeH.toFixed(4);
+ document.getElementById("result-field-minutes").innerHTML = totalTimeM.toFixed(4);
+ document.getElementById("result-field-seconds").innerHTML = totalTimeS;
+}
+
+function calculate() {
+ get_inputs();
+
+ // Seconds
+ if (endTimeS < startTimeS) {
+ resultTimeS = (endTimeS + 60) - startTimeS;
+ endTimeM--;
+ }
+ else {
+ resultTimeS = endTimeS - startTimeS;
+ }
+
+ // Minutes
+ if (endTimeM < startTimeM) {
+ resultTimeM = (endTimeM + 60) - startTimeM;
+ endTimeH--;
+ }
+ else {
+ resultTimeM = endTimeM - startTimeM;
+ }
+
+ // Hours
+ if (endTimeH < startTimeH) {
+ resultTimeH = (endTimeH + 24) - startTimeH;
+ }
+ else {
+ resultTimeH = endTimeH - startTimeH;
+ }
+
+ // Single-unit totals
+ totalTimeH = resultTimeH + (resultTimeM / 60) + (resultTimeS / 3600);
+ totalTimeM = (resultTimeH * 60) + resultTimeM + (resultTimeS / 60);
+ totalTimeS = (resultTimeH * 3600) + (resultTimeM * 60) + resultTimeS;
+
+ display_results();
+}