diff --git a/.idea/FE_Charts.iml b/.idea/FE_Charts.iml
index 24643cc..29290ea 100644
--- a/.idea/FE_Charts.iml
+++ b/.idea/FE_Charts.iml
@@ -5,6 +5,7 @@
+
diff --git a/server/dist/importCharGrowthRates.js b/server/dist/importCharGrowthRates.js
new file mode 100644
index 0000000..5bfebec
--- /dev/null
+++ b/server/dist/importCharGrowthRates.js
@@ -0,0 +1,67 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+require("dotenv").config();
+const axios = require('axios').default;
+const cheerio = require('cheerio');
+const { CharacterGrowthRate } = require("./mapping");
+const index_1 = require("./index");
+const url = "https://serenesforest.net/three-houses/characters/growth-rates/";
+const mainCharName = "Byleth";
+const mainCharAlternativeName = "Protagonist";
+const nameIndex = 0;
+function importCharGrowthRates() {
+ return __awaiter(this, void 0, void 0, function* () {
+ const characters = yield index_1.FE_Charts.getAllCharacters();
+ const stats = yield index_1.FE_Charts.getAllStats();
+ axios.get(url)
+ .then(res => {
+ // We need to remove all line breaks to avoid bad html format
+ const html = res.data.replace(/[\n\r]/g, "");
+ const $ = cheerio.load(html);
+ // parse each tables in the html
+ $("tbody").each(function (i, elem) {
+ // parse each rows of the table
+ elem.children.forEach((row, rowIndex) => {
+ // The first element is the header of the table, so we must skip it
+ if (rowIndex != 0) {
+ let name = $(row.children[nameIndex]).text();
+ if (name == mainCharAlternativeName) {
+ name = mainCharName;
+ }
+ const char = characters.find(x => x.firstName == name);
+ if (char !== undefined) {
+ for (let j = 0; j < stats.length; j++) {
+ const charGrowthRate = new CharacterGrowthRate();
+ charGrowthRate.idCharacter = char.id;
+ charGrowthRate.idStat = stats[j].id;
+ charGrowthRate.value = parseInt($(row.children[j + 1]).text()); // the first col of the table is for the name, so we have to add 1 to the index
+ CharacterGrowthRate.upsert({
+ Id_Character: charGrowthRate.idCharacter,
+ Id_Stat: charGrowthRate.idStat,
+ value: charGrowthRate.value,
+ }).catch(err => index_1.FE_Charts.logError(err));
+ }
+ }
+ else {
+ console.log(`Unknown character ${name}`);
+ }
+ }
+ });
+ });
+ })
+ .catch(err => {
+ index_1.FE_Charts.logError(err);
+ });
+ });
+}
+importCharGrowthRates();
+//# sourceMappingURL=importCharGrowthRates.js.map
\ No newline at end of file
diff --git a/server/dist/importCharGrowthRates.js.map b/server/dist/importCharGrowthRates.js.map
new file mode 100644
index 0000000..d15a9e2
--- /dev/null
+++ b/server/dist/importCharGrowthRates.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"importCharGrowthRates.js","sourceRoot":"","sources":["../src/importCharGrowthRates.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/server/dist/importClassGrowthRates.js b/server/dist/importClassGrowthRates.js
new file mode 100644
index 0000000..5c09866
--- /dev/null
+++ b/server/dist/importClassGrowthRates.js
@@ -0,0 +1,64 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+require("dotenv").config();
+const axios = require('axios').default;
+const cheerio = require('cheerio');
+const { ClassGrowthRate } = require("./mapping");
+const index_1 = require("./index");
+const url = "https://serenesforest.net/three-houses/classes/growth-rates/";
+const nameIndex = 0;
+function importClassGrowthRates() {
+ return __awaiter(this, void 0, void 0, function* () {
+ const classes = yield index_1.FE_Charts.getAllClasses();
+ const stats = yield index_1.FE_Charts.getAllStats();
+ axios.get(url)
+ .then(res => {
+ // We need to remove all line breaks to avoid bad html format
+ const html = res.data.replace(/[\n\r]/g, "");
+ const $ = cheerio.load(html);
+ $("#enemy").remove(); // Remove all contents for enemies
+ $("tbody").first().remove(); // Remove the first table who isn't for the growth rates
+ $("tbody").last().remove(); // Remove the last table who is for enemies and not playable character
+ // parse each tables in the html
+ $("tbody").each(function (i, elem) {
+ // parse each rows of the table
+ elem.children.forEach((row, rowIndex) => {
+ // The first element is the header of the table, so we must skip it
+ if (rowIndex != 0) {
+ const name = $(row.children[nameIndex]).text();
+ const feClass = classes.find(x => x.name == name);
+ if (feClass !== undefined) {
+ for (let j = 0; j < stats.length; j++) {
+ const classGrowthRate = new ClassGrowthRate();
+ classGrowthRate.idClass = feClass.id;
+ classGrowthRate.idStat = stats[j].id;
+ classGrowthRate.value = parseInt($(row.children[j + 1]).text()); // the first col of the table is for the name, so we have to add 1 to the index
+ if (classGrowthRate.value) {
+ ClassGrowthRate.upsert({
+ Id_Class: classGrowthRate.idClass,
+ Id_Stat: classGrowthRate.idStat,
+ value: classGrowthRate.value,
+ }).catch(err => index_1.FE_Charts.logError(err));
+ }
+ }
+ }
+ }
+ });
+ });
+ })
+ .catch(err => {
+ index_1.FE_Charts.logError(err);
+ });
+ });
+}
+importClassGrowthRates();
+//# sourceMappingURL=importClassGrowthRates.js.map
\ No newline at end of file
diff --git a/server/dist/importClassGrowthRates.js.map b/server/dist/importClassGrowthRates.js.map
new file mode 100644
index 0000000..931b074
--- /dev/null
+++ b/server/dist/importClassGrowthRates.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"importClassGrowthRates.js","sourceRoot":"","sources":["../src/importClassGrowthRates.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/server/dist/importData.js b/server/dist/importData.js
new file mode 100644
index 0000000..deb7c19
--- /dev/null
+++ b/server/dist/importData.js
@@ -0,0 +1,106 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+require("dotenv").config();
+const axios = require('axios').default;
+const cheerio = require('cheerio');
+const { Catalogue, Character, CharacterGrowthRate, ClassGrowthRate, FE_Class, Gender, House, Stat, RestrictedCharacterClass } = require("./mapping");
+const index_1 = require("./index");
+function importCharGrowthRates() {
+ return __awaiter(this, void 0, void 0, function* () {
+ const characters = yield index_1.FE_Charts.getAllCharacters();
+ const stats = yield index_1.FE_Charts.getAllStats();
+ axios.get("https://serenesforest.net/three-houses/characters/growth-rates/")
+ .then(res => {
+ // We need to remove all line breaks to avoid bad html format
+ const html = res.data.replace(/[\n\r]/g, "");
+ const $ = cheerio.load(html);
+ // parse each tables in the html
+ $("tbody").each(function (i, elem) {
+ // parse each rows of the table
+ elem.children.forEach((row, rowIndex) => {
+ // The first element is the header of the table, so we must skip it
+ if (rowIndex != 0) {
+ let name = $(row.children[0]).text();
+ if (name == "Protagonist") {
+ name = "Byleth";
+ }
+ const char = characters.find(x => x.firstName == name);
+ if (char !== undefined) {
+ for (let j = 0; j < stats.length; j++) {
+ const charGrowthRate = new CharacterGrowthRate();
+ charGrowthRate.idCharacter = char.id;
+ charGrowthRate.idStat = stats[j].id;
+ charGrowthRate.value = parseInt($(row.children[j + 1]).text()); // the first col of the table is for the name, so we have to add 1 to the index
+ CharacterGrowthRate.upsert({
+ Id_Character: charGrowthRate.idCharacter,
+ Id_Stat: charGrowthRate.idStat,
+ value: charGrowthRate.value,
+ }).catch(err => index_1.FE_Charts.logError(err));
+ }
+ }
+ else {
+ console.log(`Unknown character ${name}`);
+ }
+ }
+ });
+ });
+ })
+ .catch(err => {
+ index_1.FE_Charts.logError(err);
+ });
+ });
+}
+function importClassGrowthRates() {
+ return __awaiter(this, void 0, void 0, function* () {
+ const classes = yield index_1.FE_Charts.getAllClasses();
+ const stats = yield index_1.FE_Charts.getAllStats();
+ axios.get("https://serenesforest.net/three-houses/classes/growth-rates/")
+ .then(res => {
+ // We need to remove all line breaks to avoid bad html format
+ const html = res.data.replace(/[\n\r]/g, "");
+ const $ = cheerio.load(html);
+ $("#enemy").remove(); // Remove all contents for enemies
+ $("tbody").first().remove(); // Remove the first table who isn't for the growth rates
+ $("tbody").last().remove(); // Remove the last table who is for enemies and not playable character
+ // parse each tables in the html
+ $("tbody").each(function (i, elem) {
+ // parse each rows of the table
+ elem.children.forEach((row, rowIndex) => {
+ // The first element is the header of the table, so we must skip it
+ if (rowIndex != 0) {
+ const name = $(row.children[0]).text();
+ const feClass = classes.find(x => x.name == name);
+ if (feClass !== undefined) {
+ for (let j = 0; j < stats.length; j++) {
+ const classGrowthRate = new ClassGrowthRate();
+ classGrowthRate.idClass = feClass.id;
+ classGrowthRate.idStat = stats[j].id;
+ classGrowthRate.value = parseInt($(row.children[j + 1]).text()); // the first col of the table is for the name, so we have to add 1 to the index
+ if (classGrowthRate.value) {
+ ClassGrowthRate.upsert({
+ Id_Class: classGrowthRate.idClass,
+ Id_Stat: classGrowthRate.idStat,
+ value: classGrowthRate.value,
+ }).catch(err => index_1.FE_Charts.logError(err));
+ }
+ }
+ }
+ }
+ });
+ });
+ })
+ .catch(err => {
+ index_1.FE_Charts.logError(err);
+ });
+ });
+}
+//# sourceMappingURL=importData.js.map
\ No newline at end of file
diff --git a/server/dist/importData.js.map b/server/dist/importData.js.map
new file mode 100644
index 0000000..c276084
--- /dev/null
+++ b/server/dist/importData.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"importData.js","sourceRoot":"","sources":["../src/importData.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/server/dist/index.js b/server/dist/index.js
index 13b63fc..0b249f2 100644
--- a/server/dist/index.js
+++ b/server/dist/index.js
@@ -1,11 +1,24 @@
"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
Object.defineProperty(exports, "__esModule", { value: true });
require("dotenv").config();
+const axios = require('axios').default;
+const cheerio = require('cheerio');
const express = require("express");
const bodyParser = require("body-parser");
-require("./mapping");
+const status = require("http-status");
+const { Catalogue, Character, CharacterGrowthRate, ClassGrowthRate, FE_Class, Gender, House, Stat, RestrictedCharacterClass } = require("./mapping");
const app = express();
const port = process.env.NODE_PORT || 3000;
+const argImport = "importing";
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(function (req, res, next) {
@@ -15,10 +28,130 @@ app.use(function (req, res, next) {
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
+class FE_Charts {
+ static logError(err) {
+ // TODO: Log to file and manage the error
+ console.log(err);
+ }
+ static getAllCharacters() {
+ return __awaiter(this, void 0, void 0, function* () {
+ let characters = null;
+ yield Character.findAll().then(results => {
+ characters = results;
+ }).catch(err => FE_Charts.logError(err));
+ return characters;
+ });
+ }
+ static getAllCharactersGrowthRates() {
+ return __awaiter(this, void 0, void 0, function* () {
+ let charactersGrowRates = null;
+ yield CharacterGrowthRate.findAll().then(results => {
+ charactersGrowRates = results;
+ }).catch(err => FE_Charts.logError(err));
+ return charactersGrowRates;
+ });
+ }
+ static getAllClassesGrowthRates() {
+ return __awaiter(this, void 0, void 0, function* () {
+ let classesGrowRates = null;
+ yield ClassGrowthRate.findAll().then(results => {
+ classesGrowRates = results;
+ }).catch(err => FE_Charts.logError(err));
+ return classesGrowRates;
+ });
+ }
+ static getAllClasses() {
+ return __awaiter(this, void 0, void 0, function* () {
+ let classes = null;
+ yield FE_Class.findAll().then(results => {
+ classes = results;
+ }).catch(err => FE_Charts.logError(err));
+ return classes;
+ });
+ }
+ static getAllGenders() {
+ return __awaiter(this, void 0, void 0, function* () {
+ let genders = null;
+ yield Gender.findAll().then(results => {
+ genders = results;
+ }).catch(err => FE_Charts.logError(err));
+ return genders;
+ });
+ }
+ static getAllHouses() {
+ return __awaiter(this, void 0, void 0, function* () {
+ let houses = null;
+ yield House.findAll().then(results => {
+ houses = results;
+ }).catch(err => FE_Charts.logError(err));
+ return houses;
+ });
+ }
+ static getAllRestrictedClasses() {
+ return __awaiter(this, void 0, void 0, function* () {
+ let restrictedClasses = null;
+ yield RestrictedCharacterClass.findAll().then(results => {
+ restrictedClasses = results;
+ }).catch(err => FE_Charts.logError(err));
+ return restrictedClasses;
+ });
+ }
+ static getAllStats() {
+ return __awaiter(this, void 0, void 0, function* () {
+ let stats = null;
+ yield Stat.findAll().then(results => {
+ stats = results;
+ }).catch(err => FE_Charts.logError(err));
+ return stats;
+ });
+ }
+ static getCatalogueLastVersion() {
+ return __awaiter(this, void 0, void 0, function* () {
+ let version = null;
+ yield Catalogue.findAll({
+ attributes: ["version", ["Dttm_Last_Update", "lastUpdate"]],
+ limit: 1,
+ order: [["Dttm_Last_Update", "DESC"]],
+ }).then(results => {
+ version = results;
+ }).catch(err => FE_Charts.logError(err));
+ return version;
+ });
+ }
+}
+exports.FE_Charts = FE_Charts;
app.get('/', (req, res) => {
res.send('Hello World!');
});
-app.listen(port, () => {
- console.log(`Example app listening on port ${port}!`);
+app.get('/version', (req, res) => {
+ FE_Charts.getCatalogueLastVersion().then(version => {
+ res.status(status.OK).send(version);
+ });
});
+app.get('/all', (req, res) => __awaiter(void 0, void 0, void 0, function* () {
+ const characters = yield FE_Charts.getAllCharacters();
+ const characterGrowthRates = yield FE_Charts.getAllCharactersGrowthRates();
+ const classesGrowthRates = yield FE_Charts.getAllClassesGrowthRates();
+ const classes = yield FE_Charts.getAllClasses();
+ const genders = yield FE_Charts.getAllGenders();
+ const houses = yield FE_Charts.getAllHouses();
+ const restrictedClasses = yield FE_Charts.getAllRestrictedClasses();
+ const stats = yield FE_Charts.getAllStats();
+ res.status(status.OK).send({
+ characters: characters,
+ charGrowthRates: characterGrowthRates,
+ classGrowthRates: classesGrowthRates,
+ classes: classes,
+ genders: genders,
+ houses: houses,
+ restrictedClasses: restrictedClasses,
+ stats: stats,
+ });
+}));
+// Don't start the server if we're importing some data
+if (process.argv.find(x => x == argImport) == undefined) {
+ app.listen(port, () => {
+ console.log(`Example app listening on port ${port}!`);
+ });
+}
//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/server/dist/index.js.map b/server/dist/index.js.map
index 58e61a0..4001ada 100644
--- a/server/dist/index.js.map
+++ b/server/dist/index.js.map
@@ -1 +1 @@
-{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;AAAA,OAAO,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,CAAC;AAC3B,mCAAmC;AACnC,0CAA0C;AAG1C,OAAO,CAAC,WAAW,CAAC,CAAC;AAErB,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;AACtB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,IAAI,CAAC;AAE3C,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,EAAC,QAAQ,EAAE,KAAK,EAAC,CAAC,CAAC,CAAC;AAClD,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC;AAE3B,GAAG,CAAC,GAAG,CAAC,UAAU,GAAG,EAAE,GAAG,EAAE,IAAI;IAC5B,mCAAmC;IACnC,uDAAuD;IACvD,GAAG,CAAC,MAAM,CAAC,6BAA6B,EAAE,GAAG,CAAC,CAAC;IAC/C,GAAG,CAAC,MAAM,CAAC,8BAA8B,EAAE,gDAAgD,CAAC,CAAC;IAC7F,IAAI,EAAE,CAAC;AACX,CAAC,CAAC,CAAC;AAEH,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;IACtB,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;AAC7B,CAAC,CAAC,CAAC;AAEH,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;IAClB,OAAO,CAAC,GAAG,CAAC,iCAAiC,IAAI,GAAG,CAAC,CAAC;AAC1D,CAAC,CAAC,CAAC"}
\ No newline at end of file
+{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/server/package-lock.json b/server/package-lock.json
index 32e74d3..6c22340 100644
--- a/server/package-lock.json
+++ b/server/package-lock.json
@@ -88,6 +88,15 @@
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
"integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
},
+ "axios": {
+ "version": "0.19.0",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.0.tgz",
+ "integrity": "sha512-1uvKqKQta3KBxIz14F2v06AEHZ/dIoeKfbTRkK1E5oqjDnuEerLmYTgJB5AiQZHJcljpg1TuRzdjDR06qNk0DQ==",
+ "requires": {
+ "follow-redirects": "1.5.10",
+ "is-buffer": "^2.0.2"
+ }
+ },
"bluebird": {
"version": "3.7.1",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.1.tgz",
@@ -125,6 +134,11 @@
}
}
},
+ "boolbase": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
+ "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24="
+ },
"bytes": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
@@ -139,6 +153,19 @@
"redeyed": "~2.1.0"
}
},
+ "cheerio": {
+ "version": "1.0.0-rc.3",
+ "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.3.tgz",
+ "integrity": "sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA==",
+ "requires": {
+ "css-select": "~1.2.0",
+ "dom-serializer": "~0.1.1",
+ "entities": "~1.1.1",
+ "htmlparser2": "^3.9.1",
+ "lodash": "^4.15.0",
+ "parse5": "^3.0.1"
+ }
+ },
"cls-bluebird": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/cls-bluebird/-/cls-bluebird-2.1.0.tgz",
@@ -171,6 +198,22 @@
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
},
+ "css-select": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz",
+ "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=",
+ "requires": {
+ "boolbase": "~1.0.0",
+ "css-what": "2.1",
+ "domutils": "1.5.1",
+ "nth-check": "~1.0.1"
+ }
+ },
+ "css-what": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz",
+ "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg=="
+ },
"debug": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
@@ -194,6 +237,37 @@
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
},
+ "dom-serializer": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz",
+ "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==",
+ "requires": {
+ "domelementtype": "^1.3.0",
+ "entities": "^1.1.1"
+ }
+ },
+ "domelementtype": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
+ "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w=="
+ },
+ "domhandler": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz",
+ "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==",
+ "requires": {
+ "domelementtype": "1"
+ }
+ },
+ "domutils": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz",
+ "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=",
+ "requires": {
+ "dom-serializer": "0",
+ "domelementtype": "1"
+ }
+ },
"dotenv": {
"version": "8.2.0",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz",
@@ -214,6 +288,11 @@
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
},
+ "entities": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
+ "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w=="
+ },
"escape-html": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
@@ -310,6 +389,29 @@
}
}
},
+ "follow-redirects": {
+ "version": "1.5.10",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz",
+ "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==",
+ "requires": {
+ "debug": "=3.1.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+ "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ }
+ }
+ },
"forwarded": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
@@ -328,6 +430,19 @@
"is-property": "^1.0.2"
}
},
+ "htmlparser2": {
+ "version": "3.10.1",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz",
+ "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==",
+ "requires": {
+ "domelementtype": "^1.3.1",
+ "domhandler": "^2.3.0",
+ "domutils": "^1.5.1",
+ "entities": "^1.1.1",
+ "inherits": "^2.0.1",
+ "readable-stream": "^3.1.1"
+ }
+ },
"http-errors": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
@@ -373,6 +488,11 @@
"resolved": "https://registry.npmjs.org/is-bluebird/-/is-bluebird-1.0.2.tgz",
"integrity": "sha1-CWQ5Bg9KpBGr7hkUOoTWpVNG1uI="
},
+ "is-buffer": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz",
+ "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A=="
+ },
"is-property": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
@@ -502,6 +622,14 @@
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
"integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
},
+ "nth-check": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz",
+ "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==",
+ "requires": {
+ "boolbase": "~1.0.0"
+ }
+ },
"on-finished": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
@@ -510,6 +638,14 @@
"ee-first": "1.1.1"
}
},
+ "parse5": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz",
+ "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==",
+ "requires": {
+ "@types/node": "*"
+ }
+ },
"parseurl": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
@@ -555,6 +691,16 @@
"unpipe": "1.0.0"
}
},
+ "readable-stream": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz",
+ "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==",
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ },
"redeyed": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz",
@@ -691,6 +837,21 @@
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
},
+ "string_decoder": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "requires": {
+ "safe-buffer": "~5.2.0"
+ },
+ "dependencies": {
+ "safe-buffer": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
+ "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg=="
+ }
+ }
+ },
"toidentifier": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
@@ -721,6 +882,11 @@
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
"integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
},
+ "util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
+ },
"utils-merge": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
diff --git a/server/package.json b/server/package.json
index ab72d16..813a9dd 100644
--- a/server/package.json
+++ b/server/package.json
@@ -2,9 +2,11 @@
"name": "fe-charts",
"version": "0.1.0",
"description": "API for Fire Emblem Three Houses",
- "main": "index.js",
+ "main": "./dist/index.js",
"scripts": {
- "start": "tsc && node ./dist/server.js",
+ "start": "tsc && node ./dist/index.js",
+ "import-char-gr": "tsc && node ./dist/importCharGrowthRates.js importing",
+ "import-class-gr": "tsc && node ./dist/importClassGrowthRates.js importing",
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
@@ -25,6 +27,8 @@
"homepage": "https://github.com/dario-cfpt/FE_Charts#readme",
"dependencies": {
"@types/express": "^4.17.2",
+ "axios": "^0.19.0",
+ "cheerio": "^1.0.0-rc.3",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"http-status": "^1.4.1",
diff --git a/server/scripts/Tbl_Catalogue.sql b/server/scripts/Tbl_Catalogue.sql
new file mode 100644
index 0000000..53b4403
--- /dev/null
+++ b/server/scripts/Tbl_Catalogue.sql
@@ -0,0 +1,17 @@
+SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
+SET AUTOCOMMIT = 0;
+START TRANSACTION;
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8mb4 */;
+
+
+INSERT INTO `Tbl_Catalogue` (`Id_Catalogue`, `No_Version`, `Dttm_Last_Update`) VALUES
+(1, '1.0.0', '2019-12-03 00:00:00');
+COMMIT;
+
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
diff --git a/server/scripts/Tbl_Character.sql b/server/scripts/Tbl_Character.sql
new file mode 100644
index 0000000..785e4e3
--- /dev/null
+++ b/server/scripts/Tbl_Character.sql
@@ -0,0 +1,53 @@
+SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
+SET AUTOCOMMIT = 0;
+START TRANSACTION;
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8mb4 */;
+
+
+INSERT INTO `Tbl_Character` (`Id_Character`, `Nm_First`, `Nm_Last`, `Nm_File_Img`, `Id_House`, `Id_Gender`) VALUES
+(1, 'Byleth', 'Eisner', NULL, 1, 3),
+(2, 'Byleth', 'Eisner', NULL, 1, 2),
+(3, 'Edelgard', 'von Hresvelg', NULL, 2, 2),
+(4, 'Hubert', 'von Vestra', NULL, 2, 3),
+(5, 'Ferdinand', 'von Aegir', NULL, 2, 3),
+(6, 'Linhardt', 'von Hevring', NULL, 2, 3),
+(7, 'Caspar', 'von Bergliez', NULL, 2, 3),
+(8, 'Bernadetta', 'von Varley', NULL, 2, 2),
+(9, 'Dorothea', 'Arnault', NULL, 2, 2),
+(10, 'Petra', 'Macneary', NULL, 2, 2),
+(11, 'Dimitri', 'Alexandre Blaiddyd', NULL, 3, 3),
+(12, 'Dedue', 'Dedue Molinaro', NULL, 3, 3),
+(13, 'Felix', 'Hugo Fraldarius', NULL, 3, 3),
+(14, 'Ashe', 'Ubert', NULL, 3, 3),
+(15, 'Sylvain', 'Jose Gautier', NULL, 3, 3),
+(16, 'Mercedes', 'von Martritz', NULL, 3, 2),
+(17, 'Annette', 'Fantine Dominic', NULL, 3, 2),
+(18, 'Ingrid', 'Brandl Galatea', NULL, 3, 2),
+(19, 'Claude', 'von Riegan', NULL, 4, 3),
+(20, 'Lorenz', 'Hellman Gloucester', NULL, 4, 3),
+(21, 'Raphael', 'Kirsten', NULL, 4, 3),
+(22, 'Ignatz', 'Victor', NULL, 4, 3),
+(23, 'Lysithea', 'von Cordelia', NULL, 4, 2),
+(24, 'Marianne', 'von Edmund', NULL, 4, 2),
+(25, 'Hilda', 'Valentine Goneril', NULL, 4, 2),
+(26, 'Leonie', 'Pinelli', NULL, 4, 2),
+(27, 'Seteth', NULL, NULL, 5, 3),
+(28, 'Flayn', NULL, NULL, 5, 2),
+(29, 'Hanneman', 'von Essar', NULL, 5, 3),
+(30, 'Manuela', 'Casagranda', NULL, 5, 2),
+(31, 'Gilbert', 'Pronislav', NULL, 5, 3),
+(32, 'Alois', 'Rangeld', NULL, 5, 3),
+(33, 'Catherine', 'Rubens Charon', NULL, 5, 2),
+(34, 'Shamir', 'Nevrand', NULL, 5, 2),
+(35, 'Cyril', NULL, NULL, 5, 3),
+(36, 'Jeritza', 'von Hrym', NULL, 1, 3),
+(37, 'Anna', NULL, NULL, 1, 2);
+COMMIT;
+
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
diff --git a/server/scripts/Tbl_Class.sql b/server/scripts/Tbl_Class.sql
new file mode 100644
index 0000000..d987ad3
--- /dev/null
+++ b/server/scripts/Tbl_Class.sql
@@ -0,0 +1,64 @@
+SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
+SET AUTOCOMMIT = 0;
+START TRANSACTION;
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8mb4 */;
+
+
+INSERT INTO `Tbl_Class` (`Id_Class`, `Nm_Class`, `Is_Available_For_All`, `Id_Gender`) VALUES
+(1, 'Noble', 0, 1),
+(2, 'Commoner', 0, 1),
+(3, 'Myrmidon', 1, 1),
+(4, 'Soldier', 1, 1),
+(5, 'Figther', 1, 1),
+(6, 'Monk', 1, 1),
+(7, 'Lord', 0, 1),
+(8, 'Mercenary', 1, 1),
+(9, 'Thief', 1, 1),
+(10, 'Armored Knight', 1, 1),
+(11, 'Cavalier', 1, 1),
+(12, 'Brigand', 1, 1),
+(13, 'Archer', 1, 1),
+(14, 'Brawler', 1, 3),
+(15, 'Mage', 1, 1),
+(16, 'Dark Mage', 1, 3),
+(17, 'Priest', 1, 1),
+(18, 'Pegasus Knight', 1, 2),
+(19, 'Hero', 1, 3),
+(20, 'Swordmaster', 1, 1),
+(21, 'Assassin', 1, 1),
+(22, 'Fortress Knight', 1, 1),
+(23, 'Paladin', 1, 1),
+(24, 'Wyvern Rider', 1, 1),
+(25, 'Warrior', 1, 1),
+(26, 'Sniper', 1, 1),
+(27, 'Grappler', 1, 3),
+(28, 'Warlkock', 1, 1),
+(29, 'Dark Bishop', 1, 3),
+(30, 'Bishop', 1, 2),
+(31, 'Dancer', 0, 1),
+(32, 'Enlightened One', 0, 1),
+(33, 'Armored Lord', 0, 2),
+(34, 'High Lord', 0, 3),
+(35, 'Wyvern Master', 0, 3),
+(36, 'Emperor', 0, 2),
+(37, 'Great Lord', 0, 3),
+(38, 'Barbarossa', 0, 3),
+(39, 'Death Knight', 0, 3),
+(40, 'Falcon Knight', 1, 2),
+(41, 'Wyvern Lord', 1, 1),
+(42, 'Mortal Savant', 1, 1),
+(43, 'Great Knight', 1, 1),
+(44, 'Bow Knight', 1, 1),
+(45, 'Dark Knight', 1, 1),
+(46, 'Holy Knight', 1, 1),
+(47, 'War Master', 1, 3),
+(48, 'Gremory', 1, 2);
+COMMIT;
+
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
diff --git a/server/scripts/Tbl_Gender.sql b/server/scripts/Tbl_Gender.sql
new file mode 100644
index 0000000..c647b04
--- /dev/null
+++ b/server/scripts/Tbl_Gender.sql
@@ -0,0 +1,19 @@
+SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
+SET AUTOCOMMIT = 0;
+START TRANSACTION;
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8mb4 */;
+
+
+INSERT INTO `Tbl_Gender` (`Id_Gender`, `Nm_Gender`) VALUES
+(1, 'For all'),
+(3, 'Male'),
+(2, 'Female');
+COMMIT;
+
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
diff --git a/server/scripts/Tbl_House.sql b/server/scripts/Tbl_House.sql
new file mode 100644
index 0000000..9977b6f
--- /dev/null
+++ b/server/scripts/Tbl_House.sql
@@ -0,0 +1,21 @@
+SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
+SET AUTOCOMMIT = 0;
+START TRANSACTION;
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8mb4 */;
+
+
+INSERT INTO `Tbl_House` (`Id_House`, `Nm_House`) VALUES
+(2, 'Black Eagles'),
+(3, 'Blue Lions'),
+(5, 'Church of Seiros'),
+(4, 'Golden Deer'),
+(1, 'None');
+COMMIT;
+
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
diff --git a/server/scripts/Tbl_Stat.sql b/server/scripts/Tbl_Stat.sql
new file mode 100644
index 0000000..7a4d608
--- /dev/null
+++ b/server/scripts/Tbl_Stat.sql
@@ -0,0 +1,25 @@
+SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
+SET AUTOCOMMIT = 0;
+START TRANSACTION;
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8mb4 */;
+
+
+INSERT INTO `Tbl_Stat` (`Id_Stat`, `Nm_Stat`, `Nm_Short`) VALUES
+(1, 'Health points', 'HP'),
+(2, 'Strength', 'Str'),
+(3, 'Magic', 'Mag'),
+(4, 'Dexterity', 'Dex'),
+(5, 'Speed', 'Spd'),
+(6, 'Luck', 'Lck'),
+(7, 'Defense', 'Def'),
+(8, 'Resistance', 'Res'),
+(9, 'Charm', 'Cha');
+COMMIT;
+
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
diff --git a/server/src/importCharGrowthRates.ts b/server/src/importCharGrowthRates.ts
new file mode 100644
index 0000000..ddb9577
--- /dev/null
+++ b/server/src/importCharGrowthRates.ts
@@ -0,0 +1,61 @@
+require("dotenv").config();
+const axios = require('axios').default;
+const cheerio = require('cheerio');
+
+const {CharacterGrowthRate} = require("./mapping");
+import {FE_Charts} from "./index";
+
+const url:string = "https://serenesforest.net/three-houses/characters/growth-rates/";
+const mainCharName:string = "Byleth";
+const mainCharAlternativeName:string = "Protagonist";
+const nameIndex:number = 0;
+
+
+async function importCharGrowthRates() {
+ const characters = await FE_Charts.getAllCharacters();
+ const stats = await FE_Charts.getAllStats();
+ axios.get(url)
+ .then(res => {
+ // We need to remove all line breaks to avoid bad html format
+ const html = res.data.replace(/[\n\r]/g, "");
+ const $ = cheerio.load(html);
+
+ // parse each tables in the html
+ $("tbody").each(function (i, elem) {
+ // parse each rows of the table
+ elem.children.forEach((row, rowIndex) => {
+ // The first element is the header of the table, so we must skip it
+ if (rowIndex != 0) {
+ let name = $(row.children[nameIndex]).text();
+ if (name == mainCharAlternativeName) {
+ name = mainCharName;
+ }
+ const char = characters.find(x => x.firstName == name);
+
+ if (char !== undefined) {
+ for (let j = 0; j < stats.length; j++) {
+ const charGrowthRate = new CharacterGrowthRate();
+ charGrowthRate.idCharacter = char.id;
+ charGrowthRate.idStat = stats[j].id;
+ charGrowthRate.value = parseInt($(row.children[j + 1]).text()); // the first col of the table is for the name, so we have to add 1 to the index
+
+ CharacterGrowthRate.upsert({
+ Id_Character: charGrowthRate.idCharacter,
+ Id_Stat: charGrowthRate.idStat,
+ value: charGrowthRate.value,
+ }).catch(err => FE_Charts.logError(err));
+ }
+ } else {
+ console.log(`Unknown character ${name}`);
+ }
+ }
+ });
+ });
+
+ })
+ .catch(err => {
+ FE_Charts.logError(err);
+ });
+}
+
+importCharGrowthRates();
diff --git a/server/src/importClassGrowthRates.ts b/server/src/importClassGrowthRates.ts
new file mode 100644
index 0000000..38d6545
--- /dev/null
+++ b/server/src/importClassGrowthRates.ts
@@ -0,0 +1,60 @@
+require("dotenv").config();
+const axios = require('axios').default;
+const cheerio = require('cheerio');
+
+const {ClassGrowthRate} = require("./mapping");
+import {FE_Charts} from "./index";
+
+const url:string = "https://serenesforest.net/three-houses/classes/growth-rates/";
+const nameIndex:number = 0;
+
+
+async function importClassGrowthRates() {
+ const classes = await FE_Charts.getAllClasses();
+ const stats = await FE_Charts.getAllStats();
+ axios.get(url)
+ .then(res => {
+ // We need to remove all line breaks to avoid bad html format
+ const html = res.data.replace(/[\n\r]/g, "");
+ const $ = cheerio.load(html);
+
+ $("#enemy").remove(); // Remove all contents for enemies
+ $("tbody").first().remove(); // Remove the first table who isn't for the growth rates
+ $("tbody").last().remove(); // Remove the last table who is for enemies and not playable character
+
+ // parse each tables in the html
+ $("tbody").each(function (i, elem) {
+
+ // parse each rows of the table
+ elem.children.forEach((row, rowIndex) => {
+ // The first element is the header of the table, so we must skip it
+ if (rowIndex != 0) {
+ const name = $(row.children[nameIndex]).text();
+ const feClass = classes.find(x => x.name == name);
+
+ if (feClass !== undefined) {
+ for (let j = 0; j < stats.length; j++) {
+ const classGrowthRate = new ClassGrowthRate();
+ classGrowthRate.idClass = feClass.id;
+ classGrowthRate.idStat = stats[j].id;
+ classGrowthRate.value = parseInt($(row.children[j + 1]).text()); // the first col of the table is for the name, so we have to add 1 to the index
+
+ if (classGrowthRate.value) {
+ ClassGrowthRate.upsert({
+ Id_Class: classGrowthRate.idClass,
+ Id_Stat: classGrowthRate.idStat,
+ value: classGrowthRate.value,
+ }).catch(err => FE_Charts.logError(err));
+ }
+ }
+ }
+ }
+ });
+ });
+ })
+ .catch(err => {
+ FE_Charts.logError(err);
+ });
+}
+
+importClassGrowthRates();
\ No newline at end of file
diff --git a/server/src/index.ts b/server/src/index.ts
index c1c72ff..62dd9d8 100644
--- a/server/src/index.ts
+++ b/server/src/index.ts
@@ -1,12 +1,15 @@
require("dotenv").config();
+const axios = require('axios').default;
+const cheerio = require('cheerio');
import * as express from "express";
import * as bodyParser from "body-parser";
import * as status from "http-status";
-require("./mapping");
+const {Catalogue, Character, CharacterGrowthRate, ClassGrowthRate, FE_Class, Gender, House, Stat, RestrictedCharacterClass} = require("./mapping");
const app = express();
const port = process.env.NODE_PORT || 3000;
+const argImport:string = "importing";
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());
@@ -19,10 +22,126 @@ app.use(function (req, res, next) {
next();
});
+abstract class FE_Charts {
+ static logError(err) {
+ // TODO: Log to file and manage the error
+ console.log(err);
+ }
+
+ static async getAllCharacters() {
+ let characters = null;
+ await Character.findAll().then(results => {
+ characters = results;
+ }).catch(err => FE_Charts.logError(err));
+ return characters;
+ }
+
+ static async getAllCharactersGrowthRates() {
+ let charactersGrowRates = null;
+ await CharacterGrowthRate.findAll().then(results => {
+ charactersGrowRates = results
+ }).catch(err => FE_Charts.logError(err));
+ return charactersGrowRates;
+ }
+
+ static async getAllClassesGrowthRates() {
+ let classesGrowRates = null;
+ await ClassGrowthRate.findAll().then(results => {
+ classesGrowRates = results
+ }).catch(err => FE_Charts.logError(err));
+ return classesGrowRates;
+ }
+
+ static async getAllClasses() {
+ let classes = null;
+ await FE_Class.findAll().then(results => {
+ classes = results
+ }).catch(err => FE_Charts.logError(err));
+ return classes;
+ }
+
+ static async getAllGenders() {
+ let genders = null;
+ await Gender.findAll().then(results => {
+ genders = results
+ }).catch(err => FE_Charts.logError(err));
+ return genders;
+ }
+
+ static async getAllHouses() {
+ let houses = null;
+ await House.findAll().then(results => {
+ houses = results
+ }).catch(err => FE_Charts.logError(err));
+ return houses;
+ }
+
+ static async getAllRestrictedClasses() {
+ let restrictedClasses = null;
+ await RestrictedCharacterClass.findAll().then(results => {
+ restrictedClasses = results
+ }).catch(err => FE_Charts.logError(err));
+ return restrictedClasses;
+ }
+
+ static async getAllStats() {
+ let stats = null;
+ await Stat.findAll().then(results => {
+ stats = results
+ }).catch(err => FE_Charts.logError(err));
+ return stats;
+ }
+
+ static async getCatalogueLastVersion() {
+ let version = null;
+ await Catalogue.findAll({
+ attributes: ["version", ["Dttm_Last_Update", "lastUpdate"]],
+ limit: 1,
+ order: [["Dttm_Last_Update", "DESC"]],
+ }).then(results => {
+ version = results
+ }).catch(err => FE_Charts.logError(err));
+ return version;
+ }
+}
+
app.get('/', (req, res) => {
res.send('Hello World!');
});
-app.listen(port, () => {
- console.log(`Example app listening on port ${port}!`);
+app.get('/version', (req, res) => {
+ FE_Charts.getCatalogueLastVersion().then(version => {
+ res.status(status.OK).send(version);
+ });
});
+
+app.get('/all', async (req, res) => {
+ const characters = await FE_Charts.getAllCharacters();
+ const characterGrowthRates = await FE_Charts.getAllCharactersGrowthRates();
+ const classesGrowthRates = await FE_Charts.getAllClassesGrowthRates();
+ const classes = await FE_Charts.getAllClasses();
+ const genders = await FE_Charts.getAllGenders();
+ const houses = await FE_Charts.getAllHouses();
+ const restrictedClasses = await FE_Charts.getAllRestrictedClasses();
+ const stats = await FE_Charts.getAllStats();
+
+ res.status(status.OK).send({
+ characters: characters,
+ charGrowthRates: characterGrowthRates,
+ classGrowthRates: classesGrowthRates,
+ classes: classes,
+ genders: genders,
+ houses: houses,
+ restrictedClasses: restrictedClasses,
+ stats: stats,
+ });
+});
+
+// Don't start the server if we're importing some data
+if (process.argv.find(x => x == argImport) == undefined) {
+ app.listen(port, () => {
+ console.log(`Example app listening on port ${port}!`);
+ });
+}
+
+export {FE_Charts}
\ No newline at end of file