Alpha Release 0.3.0 - Runnercard generation #25

Merged
niggl merged 37 commits from dev into main 2021-02-12 17:03:29 +00:00
10 changed files with 364 additions and 16 deletions

View File

@ -2,30 +2,72 @@
All notable changes to this project will be documented in this file. Dates are displayed in UTC. All notable changes to this project will be documented in this file. Dates are displayed in UTC.
#### [v0.1.3](https://git.odit.services/lfk/document-server/compare/v0.1.2...v0.1.3) #### [v0.3.0](https://git.odit.services/lfk/document-server/compare/v0.2.0...v0.3.0)
- Merge pull request 'Barcode generation feature/13-barcode_generation' (#21) from feature/13-barcode_generation into dev [`ff36b48`](https://git.odit.services/lfk/document-server/commit/ff36b4871f2d696c0b86883d529365ee8f1c6132) - 🚀Bumped version to v0.3.0 [`449a96b`](https://git.odit.services/lfk/document-server/commit/449a96b3027fe93d8042b30420245f66e92f14b8)
- 🚀Bumped version to v0.1.3 [`6a14232`](https://git.odit.services/lfk/document-server/commit/6a142328898d5b89fa11eaf033372971d1093b0c) - Merge pull request 'Card generation feature/14-card_generation' (#24) from feature/14-card_generation into dev [`703eaa0`](https://git.odit.services/lfk/document-server/commit/703eaa0e9d667b628eab4e8496689fe66238f896)
- 🧾New changelog file version [CI SKIP] [skip ci] [`ad9a8a4`](https://git.odit.services/lfk/document-server/commit/ad9a8a4fe0649d48db924771be8ecb4cbf5c162a) - 🚀Bumped version to v0.2.0 [`491cdb8`](https://git.odit.services/lfk/document-server/commit/491cdb8d71a80ea196d16334c0c80b8f7cc859c5)
- Added card generation speed tests (part 1) [`68572b1`](https://git.odit.services/lfk/document-server/commit/68572b194eb740238be8101efed6fdb2a207f65b)
- Implemented first experimental speedtest [`e3a45a6`](https://git.odit.services/lfk/document-server/commit/e3a45a61ac3b2d691c2f75d36155896b7ed301d8)
- Added basic logic to generate two-sided runnercards [`d3a213c`](https://git.odit.services/lfk/document-server/commit/d3a213ce3326aeb96d924e16a31fc87bf82eb5b3)
- 🧾New changelog file version [CI SKIP] [skip ci] [`149bf18`](https://git.odit.services/lfk/document-server/commit/149bf1849db20b863ec998a72c77559ec401bc32)
- Fixed double-sided printing [`7f58dd6`](https://git.odit.services/lfk/document-server/commit/7f58dd694b53152069c2095b2e18dd3a46cd04dd)
- Added basic card generation function [`8fc6c71`](https://git.odit.services/lfk/document-server/commit/8fc6c7176ee92f813db1e1d4b3e5ef1b2f4e1aef)
- Beautified output a bit [`aefe549`](https://git.odit.services/lfk/document-server/commit/aefe5493b06c04cc2b20029e1f7fc5f15ec9c04e)
- Added barcode generatin [`5c075bc`](https://git.odit.services/lfk/document-server/commit/5c075bce8b94ff4482448c3cd56bdc28cbe0a7d9)
- Implemented runner generation using fakerjs [`0894446`](https://git.odit.services/lfk/document-server/commit/08944460854c78cd4368cf178b022c31b624c8d9)
- Styled front [`016f746`](https://git.odit.services/lfk/document-server/commit/016f746c7cec29ab391b3918c7589dea0cff9890)
- Now loading sponsor logos from env [`29376a7`](https://git.odit.services/lfk/document-server/commit/29376a7782ce39f04f856ec78775e65aa11f0ed7)
- Implmented sponsoring image selection from array [`68a1b8f`](https://git.odit.services/lfk/document-server/commit/68a1b8f3e0515e56c7c6069f7f3ef8db24c92674)
- 📖New license file version [CI SKIP] [skip ci] [`dbccbf6`](https://git.odit.services/lfk/document-server/commit/dbccbf68f4e22470b4fc93c894527cc78973e324)
- Added cards api endpoint [`929ac81`](https://git.odit.services/lfk/document-server/commit/929ac81515b3b426ff06f1d6d913bab930421a92)
- 🧾New changelog file version [CI SKIP] [skip ci] [`96204d8`](https://git.odit.services/lfk/document-server/commit/96204d809e852c1bcea808a9c8f5ca0f8475c87f)
- Fixed runnercard backside padding [`08e8587`](https://git.odit.services/lfk/document-server/commit/08e858726c1462b599ba9cb3f7fb057f35178b83)
- Added sizing for the real cards [`b92a6f7`](https://git.odit.services/lfk/document-server/commit/b92a6f7b2b98fb0074d5a563d9918295e9ec0274)
- 🧾New changelog file version [CI SKIP] [skip ci] [`8a90f63`](https://git.odit.services/lfk/document-server/commit/8a90f63b0919376beefef6a52aae9a59337aea59)
- Added speedtest script to package [`75b8b28`](https://git.odit.services/lfk/document-server/commit/75b8b281b87d9b173093f16beae12d707ec05052)
- Fixed bug in array swapping function [`9697d53`](https://git.odit.services/lfk/document-server/commit/9697d53a1527854536f8ddf5426f7ca902772f51)
- Added **very** basic backside [`68f46a4`](https://git.odit.services/lfk/document-server/commit/68f46a45b5a51c8a8edafca852cb274af388fa76)
- Added card generation speed tests (part 2) [`d38923c`](https://git.odit.services/lfk/document-server/commit/d38923c4ad3a2cf8872e236dd42f078e2a0e1045)
- Implemented basic contracts tests in various sizes [`a1b0a19`](https://git.odit.services/lfk/document-server/commit/a1b0a1918db552eb385fedcbaa576ad493a1d605)
- tmp [`0d27916`](https://git.odit.services/lfk/document-server/commit/0d27916188114fa41e666170135de2b714ff113a)
- Added new env vars to readme [`cf0f583`](https://git.odit.services/lfk/document-server/commit/cf0f5839ee1e1b87f7b5bd5a299a35574fd1bb3c)
- Merge pull request 'Added speedtest feature/19-speed_test' (#23) from feature/19-speed_test into dev [`7ac8edb`](https://git.odit.services/lfk/document-server/commit/7ac8edb5cf4b7317a703faa32ded482a8c2b9b91)
#### [v0.2.0](https://git.odit.services/lfk/document-server/compare/v0.1.3...v0.2.0)
> 9 February 2021
- Merge pull request 'Alpha Release 0.2.0 - The barcode release' (#22) from dev into main [`b952ac4`](https://git.odit.services/lfk/document-server/commit/b952ac4d728952e1fb6d26b0929e3f946748b85b)
- Implemented async barcode generation using async helpers [`edc846a`](https://git.odit.services/lfk/document-server/commit/edc846ab05319a4e60422625678f204bc145884c) - Implemented async barcode generation using async helpers [`edc846a`](https://git.odit.services/lfk/document-server/commit/edc846ab05319a4e60422625678f204bc145884c)
- 📖New license file version [CI SKIP] [skip ci] [`fea0b1d`](https://git.odit.services/lfk/document-server/commit/fea0b1dc0582d2906bad22f2ff5e5aad90a1c885)
- Reworked template layout for barcode [`1c06689`](https://git.odit.services/lfk/document-server/commit/1c066898009883f510fa204c66800e5f6228a15d) - Reworked template layout for barcode [`1c06689`](https://git.odit.services/lfk/document-server/commit/1c066898009883f510fa204c66800e5f6228a15d)
- Added basic barcode generation [`8072d0b`](https://git.odit.services/lfk/document-server/commit/8072d0b1940ef6f316ce78dcbcb9e5af5bab04e7) - 🧾New changelog file version [CI SKIP] [skip ci] [`7122fe7`](https://git.odit.services/lfk/document-server/commit/7122fe7dbe3fae64806492636255147078eb03c8)
- 🧾New changelog file version [CI SKIP] [skip ci] [`03f63e3`](https://git.odit.services/lfk/document-server/commit/03f63e3777381a4475910e6fa4a3986f87b73f39) - Merge pull request 'Barcode generation feature/13-barcode_generation' (#21) from feature/13-barcode_generation into dev [`ff36b48`](https://git.odit.services/lfk/document-server/commit/ff36b4871f2d696c0b86883d529365ee8f1c6132)
- Merge pull request 'Alpha Release 0.1.3 - More env vars' (#20) from dev into main [`ecd02a1`](https://git.odit.services/lfk/document-server/commit/ecd02a1af7431d0bf615c4ec064f64e023946e49)
- Now with working code scaleing [`4b79b29`](https://git.odit.services/lfk/document-server/commit/4b79b29ee6319559c9d68ddb11f831d25f12b3da) - Now with working code scaleing [`4b79b29`](https://git.odit.services/lfk/document-server/commit/4b79b29ee6319559c9d68ddb11f831d25f12b3da)
- Added basic barcode generation [`8072d0b`](https://git.odit.services/lfk/document-server/commit/8072d0b1940ef6f316ce78dcbcb9e5af5bab04e7)
- Now loading barcode format from env with overwrite via query param [`9a7c1d6`](https://git.odit.services/lfk/document-server/commit/9a7c1d64fdbdadbd104739133a87773e4d2bca01) - Now loading barcode format from env with overwrite via query param [`9a7c1d6`](https://git.odit.services/lfk/document-server/commit/9a7c1d64fdbdadbd104739133a87773e4d2bca01)
- Added fallback error image [`5023457`](https://git.odit.services/lfk/document-server/commit/502345782f26895ccf3089d15c3817709b62dfcc) - Added fallback error image [`5023457`](https://git.odit.services/lfk/document-server/commit/502345782f26895ccf3089d15c3817709b62dfcc)
- First part of the handlebars barcode generation [`a35f8cf`](https://git.odit.services/lfk/document-server/commit/a35f8cfd3aa94923968fd77425c074844d28ec0d) - First part of the handlebars barcode generation [`a35f8cf`](https://git.odit.services/lfk/document-server/commit/a35f8cfd3aa94923968fd77425c074844d28ec0d)
- 🧾New changelog file version [CI SKIP] [skip ci] [`b6296b8`](https://git.odit.services/lfk/document-server/commit/b6296b8d97cda943dfb5e11bc9dfbb2f363f5b81)
- Added todo [`75d2ac3`](https://git.odit.services/lfk/document-server/commit/75d2ac3c5f80f8440b6d48c33b15ef17565559b3) - Added todo [`75d2ac3`](https://git.odit.services/lfk/document-server/commit/75d2ac3c5f80f8440b6d48c33b15ef17565559b3)
- Removed promise [`e1ec193`](https://git.odit.services/lfk/document-server/commit/e1ec193a4ff1cd618da90f5f2d029ec848a6f669) - Removed promise [`e1ec193`](https://git.odit.services/lfk/document-server/commit/e1ec193a4ff1cd618da90f5f2d029ec848a6f669)
- Added new env vars to config [`3bb322e`](https://git.odit.services/lfk/document-server/commit/3bb322ede5db15a147c0d7a8db2a68ccb7fa2112) - 🧾New changelog file version [CI SKIP] [skip ci] [`03f63e3`](https://git.odit.services/lfk/document-server/commit/03f63e3777381a4475910e6fa4a3986f87b73f39)
- Now loading interpolation vars from config/env [`b4ebae2`](https://git.odit.services/lfk/document-server/commit/b4ebae283b472b2f0c6e28caed49b30edb119585)
- Fixed broken mime-type [`4187a8e`](https://git.odit.services/lfk/document-server/commit/4187a8e82015495c0e0362e957e236ed6935a908) - Fixed broken mime-type [`4187a8e`](https://git.odit.services/lfk/document-server/commit/4187a8e82015495c0e0362e957e236ed6935a908)
- Merge pull request 'Load more stuff from env feature/16-env_vars' (#17) from feature/16-env_vars into dev [`bc4d16e`](https://git.odit.services/lfk/document-server/commit/bc4d16e6f8959ed35d7e87647de84584cdfddd7b)
- Added new env vars to readme [`b77bb3a`](https://git.odit.services/lfk/document-server/commit/b77bb3ad9dba9d73c2c81215ba57936192155a9a)
- Switched to using the current runner's id as the barcode text [`3e2b011`](https://git.odit.services/lfk/document-server/commit/3e2b011d2887d261fb9c36820982095d6dd6d847) - Switched to using the current runner's id as the barcode text [`3e2b011`](https://git.odit.services/lfk/document-server/commit/3e2b011d2887d261fb9c36820982095d6dd6d847)
- Added barcode field to template [`27d1d69`](https://git.odit.services/lfk/document-server/commit/27d1d69360c8513079abcfe3a6fc2a50309a2b61) - Added barcode field to template [`27d1d69`](https://git.odit.services/lfk/document-server/commit/27d1d69360c8513079abcfe3a6fc2a50309a2b61)
#### [v0.1.3](https://git.odit.services/lfk/document-server/compare/v0.1.2...v0.1.3)
> 9 February 2021
- Merge pull request 'Alpha Release 0.1.3 - More env vars' (#20) from dev into main [`ecd02a1`](https://git.odit.services/lfk/document-server/commit/ecd02a1af7431d0bf615c4ec064f64e023946e49)
- 🚀Bumped version to v0.1.3 [`6a14232`](https://git.odit.services/lfk/document-server/commit/6a142328898d5b89fa11eaf033372971d1093b0c)
- 🧾New changelog file version [CI SKIP] [skip ci] [`ad9a8a4`](https://git.odit.services/lfk/document-server/commit/ad9a8a4fe0649d48db924771be8ecb4cbf5c162a)
- 🧾New changelog file version [CI SKIP] [skip ci] [`b6296b8`](https://git.odit.services/lfk/document-server/commit/b6296b8d97cda943dfb5e11bc9dfbb2f363f5b81)
- Merge pull request 'Load more stuff from env feature/16-env_vars' (#17) from feature/16-env_vars into dev [`bc4d16e`](https://git.odit.services/lfk/document-server/commit/bc4d16e6f8959ed35d7e87647de84584cdfddd7b)
- Added new env vars to config [`3bb322e`](https://git.odit.services/lfk/document-server/commit/3bb322ede5db15a147c0d7a8db2a68ccb7fa2112)
- Added new env vars to readme [`b77bb3a`](https://git.odit.services/lfk/document-server/commit/b77bb3ad9dba9d73c2c81215ba57936192155a9a)
- Now loading interpolation vars from config/env [`b4ebae2`](https://git.odit.services/lfk/document-server/commit/b4ebae283b472b2f0c6e28caed49b30edb119585)
- 🧾New changelog file version [CI SKIP] [skip ci] [`a306009`](https://git.odit.services/lfk/document-server/commit/a30600943d01116b99e946cb705a16d0372b5095) - 🧾New changelog file version [CI SKIP] [skip ci] [`a306009`](https://git.odit.services/lfk/document-server/commit/a30600943d01116b99e946cb705a16d0372b5095)
#### [v0.1.2](https://git.odit.services/lfk/document-server/compare/v0.1.1...v0.1.2) #### [v0.1.2](https://git.odit.services/lfk/document-server/compare/v0.1.1...v0.1.2)

View File

@ -34,6 +34,7 @@ The basic generation mechanism makes the templates and routes interchangeable (i
| EVENT_NAME | String | "Please set the event name" | The event's name - used to generate pdf text. | EVENT_NAME | String | "Please set the event name" | The event's name - used to generate pdf text.
| CURRENCY_SYMBOL | String | "€" | The your currency's symbol - used to generate pdf text. | CURRENCY_SYMBOL | String | "€" | The your currency's symbol - used to generate pdf text.
| SPONSORING_RECEIPT_MINIMUM_AMOUNT | String | "10" | The mimimum total donation amount a sponsor has to donate to be able to receive a donation receipt - used to generate pdf text. | SPONSORING_RECEIPT_MINIMUM_AMOUNT | String | "10" | The mimimum total donation amount a sponsor has to donate to be able to receive a donation receipt - used to generate pdf text.
| SPONOR_LOGOS | Array<String> | Empty png | The sponsor images you want to loop through. You can provide them via http url, local file or base64-encoded image.
## Templates ## Templates
> The document server uses html templates to generate various pdf documents. > The document server uses html templates to generate various pdf documents.

View File

@ -877,6 +877,14 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
# faker
**Author**: undefined
**Repo**: [object Object]
**License**: MIT
**Description**: Generate massive amounts of fake contextual data
## License Text
# nodemon # nodemon
**Author**: [object Object] **Author**: [object Object]
**Repo**: [object Object] **Repo**: [object Object]
@ -958,6 +966,14 @@ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
# start-server-and-test
**Author**: Gleb Bahmutov <gleb.bahmutov@gmail.com>
**Repo**: [object Object]
**License**: MIT
**Description**: Starts server, waits for URL, then runs test command; when the tests end, shuts down server
## License Text
# ts-node # ts-node
**Author**: [object Object] **Author**: [object Object]
**Repo**: [object Object] **Repo**: [object Object]

View File

@ -1,6 +1,6 @@
{ {
"name": "@odit/lfk-document-server", "name": "@odit/lfk-document-server",
"version": "0.1.3", "version": "0.3.0",
"description": "The document generation server for the LfK! runner system. This generates certificates, sponsoring aggreements and more", "description": "The document generation server for the LfK! runner system. This generates certificates, sponsoring aggreements and more",
"main": "src/app.ts", "main": "src/app.ts",
"scripts": { "scripts": {
@ -8,7 +8,9 @@
"build": "rimraf ./dist && tsc && cp-cli ./src/templates ./dist/templates && cp-cli ./src/locales ./dist/locales", "build": "rimraf ./dist && tsc && cp-cli ./src/templates ./dist/templates && cp-cli ./src/locales ./dist/locales",
"licenses:export": "license-exporter --markdown", "licenses:export": "license-exporter --markdown",
"release": "release-it --only-version", "release": "release-it --only-version",
"translations:sort": "node sort_translations.js" "translations:sort": "node sort_translations.js",
"test:speed": "start-server-and-test dev http://localhost:4010/docs/openapi.json test:speed:run",
"test:speed:run": "ts-node src/tests/speedtest.ts"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@ -66,9 +68,11 @@
"@types/node": "^14.14.22", "@types/node": "^14.14.22",
"@types/puppeteer": "^5.4.3", "@types/puppeteer": "^5.4.3",
"cp-cli": "^2.0.0", "cp-cli": "^2.0.0",
"faker": "^5.3.1",
"nodemon": "^2.0.7", "nodemon": "^2.0.7",
"release-it": "^14.2.2", "release-it": "^14.2.2",
"rimraf": "^3.0.2", "rimraf": "^3.0.2",
"start-server-and-test": "^1.12.0",
"ts-node": "^9.1.1", "ts-node": "^9.1.1",
"typescript": "^4.1.3" "typescript": "^4.1.3"
}, },

View File

@ -11,6 +11,7 @@ import puppeteer from "puppeteer";
import { awaitAsyncHandlebarHelpers, helpers } from './asyncHelpers'; import { awaitAsyncHandlebarHelpers, helpers } from './asyncHelpers';
import { config } from './config'; import { config } from './config';
import { Runner } from './models/Runner'; import { Runner } from './models/Runner';
import { RunnerCard } from './models/RunnerCard';
import { RunnerGroup } from './models/RunnerGroup'; import { RunnerGroup } from './models/RunnerGroup';
/** /**
@ -86,6 +87,15 @@ export class PdfCreator {
return i18next.t(str, PdfCreator.interpolations).toString(); return i18next.t(str, PdfCreator.interpolations).toString();
} }
); );
await Handlebars.registerHelper('--sponsor',
function (str) {
const index = (parseInt(str) % config.sponor_logos.length);
if (isNaN(index)) {
return "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+P+/HgAFhAJ/wlseKgAAAABJRU5ErkJggg=="
}
return config.sponor_logos[index];
}
);
this.browser = await puppeteer.launch({ headless: true, args: minimal_args }); this.browser = await puppeteer.launch({ headless: true, args: minimal_args });
} }
@ -117,6 +127,33 @@ export class PdfCreator {
return pdf return pdf
} }
/**
* Generate runner card pdfs.
* @param cards The runner cars you want to generate the cards for.
* @param locale The locale used for the cards (default:en)
*/
public async generateRunnerCards(cards: RunnerCard[], locale: string = "en", codeformat: string = config.codeformat): Promise<Buffer> {
if (cards.length > 10) {
let pdf_promises = new Array<Promise<Buffer>>();
let i, j;
for (i = 0, j = cards.length; i < j; i += 10) {
let chunk = cards.slice(i, i + 10);
pdf_promises.push(this.generateRunnerCards(chunk, locale));
}
const pdfs = await Promise.all(pdf_promises);
return await this.mergePdfs(pdfs);
}
const cards_swapped = this.swapArrayPairs(cards);
await i18next.changeLanguage(locale);
const template_source = fs.readFileSync(`${this.templateDir}/runner_card.html`, 'utf8');
const template = Handlebars.compile(template_source);
let result = template({ cards, cards_swapped, eventname: "LfK! 2069", codeformat: "qrcode" })
result = await awaitAsyncHandlebarHelpers(result);
fs.writeFileSync("lelelelele.tmp", result);
const pdf = await this.renderPdf(result, { format: "A4", landscape: false });
return pdf
}
/** /**
* Converts all images in html to base64. * Converts all images in html to base64.
* Works with image files in the template directory or images from urls. * Works with image files in the template directory or images from urls.
@ -203,4 +240,26 @@ export class PdfCreator {
runner.group = group; runner.group = group;
return runner; return runner;
} }
/**
* Swaps pairs (0/1, 2/3, ...) of elements in an array recursively.
* If the last element has no partner it inserts an empty element at the end and swaps the two
* This is needed to generate pdfs with front- and backside that get printet on one paper.
* @param array The array which's pairs shall get switched.
* @returns Array with swapped pairs,
*/
private swapArrayPairs(array): Array<any> {
if (array.length == 1) {
return [null, array[0]];
}
if (array.length == 0) {
return null;
}
const rest = this.swapArrayPairs(array.slice(2))
if (!rest) {
return [array[1], array[0]]
}
return [array[1], array[0]].concat(rest);
}
} }

View File

@ -3,6 +3,7 @@ import bwipjs from "bwip-js";
export const asyncHelpers = new AsyncHelpers(); export const asyncHelpers = new AsyncHelpers();
async function generateBarcode(str, options, emtpy, cb) { async function generateBarcode(str, options, emtpy, cb) {
if (str == null) { cb(null, "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+P+/HgAFhAJ/wlseKgAAAABJRU5ErkJggg=="); return; }
let res = await generateBase64Barcode(options.toString(), str.toString()); let res = await generateBase64Barcode(options.toString(), str.toString());
cb(null, res); cb(null, res);
} }
@ -18,7 +19,7 @@ export async function generateBase64Barcode(type: string, content: string): Prom
height: 10, height: 10,
width: 10, width: 10,
includetext: true, includetext: true,
textxalign: 'center', textxalign: 'center'
} }
if (type != "qrcode") { if (type != "qrcode") {
delete options.width; delete options.width;

View File

@ -8,7 +8,8 @@ export const config = {
eventname: process.env.EVENT_NAME || "Please set the event name", eventname: process.env.EVENT_NAME || "Please set the event name",
currency_symbol: process.env.CURRENCY_SYMBOL || "€", currency_symbol: process.env.CURRENCY_SYMBOL || "€",
sponsoring_receipt_minimum_amount: process.env.SPONSORING_RECEIPT_MINIMUM_AMOUNT || "10", sponsoring_receipt_minimum_amount: process.env.SPONSORING_RECEIPT_MINIMUM_AMOUNT || "10",
codeformat: process.env.CODEFORMAT || "qrcode" codeformat: process.env.CODEFORMAT || "qrcode",
sponor_logos: getSponsorLogos()
} }
let errors = 0 let errors = 0
if (typeof config.internal_port !== "number") { if (typeof config.internal_port !== "number") {
@ -17,4 +18,13 @@ if (typeof config.internal_port !== "number") {
if (typeof config.development !== "boolean") { if (typeof config.development !== "boolean") {
errors++ errors++
} }
function getSponsorLogos(): string[] {
try {
const logos = JSON.parse(process.env.SPONOR_LOGOS);
if (!Array.isArray(logos)) { throw new Error("Not an array.") }
return logos;
} catch (error) {
return ["data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+P+/HgAFhAJ/wlseKgAAAABJRU5ErkJggg=="];
}
}
export let e = errors export let e = errors

View File

@ -1,6 +1,7 @@
import { Body, JsonController, Post, QueryParam, Res } from 'routing-controllers'; import { Body, JsonController, Post, QueryParam, Res } from 'routing-controllers';
import { OpenAPI } from 'routing-controllers-openapi'; import { OpenAPI } from 'routing-controllers-openapi';
import { Runner } from '../models/Runner'; import { Runner } from '../models/Runner';
import { RunnerCard } from '../models/RunnerCard';
import { PdfCreator } from '../PdfCreator'; import { PdfCreator } from '../PdfCreator';
/** /**
@ -27,4 +28,19 @@ export class PdfController {
res.setHeader('content-type', 'application/pdf'); res.setHeader('content-type', 'application/pdf');
return contracts; return contracts;
} }
@Post('/cards')
@OpenAPI({ description: "Generate runner card pdfs from runner card objects.<br>You can choose your prefered locale by passing the 'locale' query-param." })
async generateCards(@Body({ validate: true, options: { limit: "500mb" } }) cards: RunnerCard | RunnerCard[], @Res() res: any, @QueryParam("locale") locale: string) {
if (!this.initialized) {
await this.pdf.init();
this.initialized = true;
}
if (!Array.isArray(cards)) {
cards = [cards];
}
const contracts = await this.pdf.generateRunnerCards(cards, locale);
res.setHeader('content-type', 'application/pdf');
return contracts;
}
} }

View File

@ -0,0 +1,71 @@
<html>
<head>
<meta charset="utf8">
<title>Sponsoring contract</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.1/css/bulma.min.css">
<style>
.sheet {
margin: 0;
overflow: hidden;
position: relative;
box-sizing: border-box;
page-break-after: always;
padding: 1.2cm 2cm 1.2cm 2cm
}
body.A4 .sheet {
width: 210mm;
height: 296mm
}
.runnercard {
border: 1px solid;
height: 5.5cm;
overflow: hidden;
}
</style>
</head>
<body class="A4 landscape">
<div class="sheet">
<div class="columns is-multiline">
{{#each cards}}
<div class="column is-half runnercard">
<p class="title is-5" style="text-align: center; padding-bottom: 0; margin-top: -0.75rem;">{{../eventname}}</p>
<p style="text-align: center; margin-top: -1.5rem; font-size: small;">lauf-fuer-kaya.de - am 01.01.2021</p>
<p style="font-size: small;">Mit unterstützung von:</p>
<div class="columns" style="height: 6rem; overflow: hidden;">
<div class="column is-two-thirds">
<!--SPONSOR LOGO HERE-->
<img style="vertical-align: revert; margin-top: auto; object-fit: cover; max-height: 2cm;"
src="{{--sponsor this.id}}" />
</div>
<div class="column is-one-third">
<!--BARCODE HERE-->
<img style="vertical-align: revert; margin-top: auto; object-fit: cover; max-height: 2cm;"
src="{{--bc this.id ../codeformat}}" />
</div>
</div>
<p>{{this.runner.lastname}}, {{this.runner.firstname}} {{this.runner.middlename}}</p>
<p>{{this.runner.group.name}}</p>
</div>
{{/each}}
</div>
</div>
<div class="sheet">
<div class="columns is-multiline">
{{#each cards_swapped}}
<div class="column is-half runnercard" style="justify-content: center; align-items: center; text-align: center;">
<!--SPONSOR LOGO FIRST-->
<div style="height: 2cm; padding: 0 0 2.25cm 0">
<img style="object-fit: cover; max-height: 2cm;" src="{{--sponsor this.id}}" />
</div>
<img style="object-fit: cover; max-height: 2.5cm; position: relative;" src="{{--bc this.id ../codeformat}}" />
</div>
{{/each}}
</div>
</div>
</body>
</html>

128
src/tests/speedtest.ts Normal file
View File

@ -0,0 +1,128 @@
import axios from "axios"
import faker from "faker"
import { Runner } from '../models/Runner'
import { RunnerCard } from '../models/RunnerCard'
import { RunnerGroup } from '../models/RunnerGroup'
const baseurl = "http://localhost:4010"
axios.interceptors.request.use((config) => {
config.headers['request-startTime'] = process.hrtime()
return config
})
axios.interceptors.response.use((response) => {
const start = response.config.headers['request-startTime']
const end = process.hrtime(start)
const milliseconds = Math.round((end[0] * 1000) + (end[1] / 1000000))
response.headers['request-duration'] = milliseconds
return response
})
function generateRunners(amount: number): Runner[] {
let runners: Runner[] = new Array<Runner>();
let group = new RunnerGroup();
let runner = new Runner();
for (var i = 0; i < amount; i++) {
group.name = faker.company.bsBuzz();
group.id = Math.floor(Math.random() * (9999999 - 1) + 1);
runner.firstname = faker.name.firstName();
runner.lastname = faker.name.lastName();
runner.id = Math.floor(Math.random() * (9999999 - 1) + 1);
runners.push(runner);
}
return runners;
}
function generateCards(amount: number): RunnerCard[] {
let cards: RunnerCard[] = new Array<RunnerCard>();
let card = new RunnerCard();
for (let runner of generateRunners(amount)) {
card.id = runner.id;
card.code = idToEan13(card.id);
card.runner = runner;
cards.push(card);
}
return cards;
}
function idToEan13(id): string {
const multiply = [1, 3];
id = id.toString();
if (id.length > 12) {
throw new Error("id too long");
}
while (id.length < 12) { id = '0' + id; }
let total = 0;
id.split('').forEach((letter, index) => {
total += parseInt(letter, 10) * multiply[index % 2];
});
const checkSum = (Math.ceil(total / 10) * 10) - total;
return id + checkSum.toString();
}
async function postContracts(runners: Runner[]): Promise<Measurement> {
const res = await axios.post(`${baseurl}/contracts`, runners);
return new Measurement("contract", runners.length, parseInt(res.headers['request-duration']))
}
async function postCards(cards: RunnerCard[]): Promise<Measurement> {
const res = await axios.post(`${baseurl}/cards`, cards);
return new Measurement("card", cards.length, parseInt(res.headers['request-duration']))
}
async function testContracts(sizes): Promise<Measurement[]> {
let measurements = new Array<Measurement>();
console.log("#### Testing contracts ####");
for (let size of sizes) {
const m = await postContracts(generateRunners(size));
console.log(m.toString());
measurements.push(m);
}
return measurements;
}
async function testCards(sizes): Promise<Measurement[]> {
let measurements = new Array<Measurement>();
console.log("#### Testing Cards ####");
for (let size of sizes) {
const m = await postCards(generateCards(size));
console.log(m.toString());
measurements.push(m);
}
return measurements;
}
async function main() {
const sizes = [0, 1, 10, 50, 100, 200, 500, 1000]
console.log("########### Speedtest ###########");
console.log(`Document server version (according to the api): ${(await axios.get("http://localhost:4010/version")).data.version}`);
console.log("####### Running tests #######");
const contractResults = await testContracts(sizes);
const cardResults = await testCards(sizes);
console.log("####### Results #######");
console.table(contractResults);
console.table(cardResults);
}
main();
class Measurement {
public type: string;
public inputcount: number;
public responsetime: number;
constructor(type: string, input: number, time: number) {
this.type = type;
this.inputcount = input;
this.responsetime = time;
}
public toString(): string {
return `It took ${this.responsetime}ms to generate ${this.inputcount} pdfs for the type ${this.type}.`
}
}