From 3ac3511ce2535a438232f780cf32153f232854bd Mon Sep 17 00:00:00 2001 From: Sylvain Gougouzian Date: Thu, 18 Apr 2024 08:35:23 +0200 Subject: [PATCH] feat: :sparkles: add Commander --- bun.lockb | Bin 3152 -> 3508 bytes index.ts | 115 --------------------------------------------------- package.json | 12 ++++-- src/choc.ts | 102 +++++++++++++++++++++++++++++++++++++++++++++ src/index.ts | 28 +++++++++++++ src/types.ts | 45 ++++++++++++++++++++ src/utils.ts | 22 ++++++++++ 7 files changed, 205 insertions(+), 119 deletions(-) delete mode 100644 index.ts create mode 100644 src/choc.ts create mode 100644 src/index.ts create mode 100644 src/types.ts create mode 100644 src/utils.ts diff --git a/bun.lockb b/bun.lockb index e5609bc6a582cc1b09eb635cc4a6800bee6c1b39..98fa3416a8a15a6d5cf69149cad96845acc72359 100755 GIT binary patch delta 807 zcmca0u|;}2ecp1QeV`8{` zR0aox10iJ@7#a+LOim!J4y3t&^eQO-2b6vbq`86O`HTz3lK8_F&mW64y9p!fYCrKhfN%xmq}Tj$?l_u|>4EkPSY{ybACnEtqDonS_pi_h(3wN*E>ui2KJxB0<8 z|L48b{qL%-KC3&Sw8FbWnql%;W{JtY%-)R5lW#JIPwrshoovhE&B!{rlO=qz1uO65 zw?H2IWJ}iLlNd!dv1Kz(c3?K-+5q*&5st~F?DnAG{r4XNK>h;x`2$o159j1_>}Eo& zP+<#Tw1GebNLWb=q!JWbppXNF1V|Yu1VJzRFp-AEJuD8HK>ER8 z)#SY#lG3oapQs6tLB04699c)>NJ-Wn1=t*BqZ%X2g1KbQ?z|Jr+ zKx|?jhjBJLL;ym{GB7l#1DRYvIt@s30_iPKdL@ts>Tb}UxKVuKg$hQ)$(@Y$tocAu ztI55L)=YaDCUY^_F@0p1?8RiqXg;}<$)2%g@<}G^$qtMxiA+Fsj6lo`#2_{+l+OmG zVa|ZjKw+>tqV-L#WG+dZ%=kb;791c+28IxjkeV9I z?I1U@05QmKAR6Si4yaN)&dEufY9N`(?VP64X+Q=jP^;ghpY0HOt;ED=sAs5W02Ez0 z`6H(!T!kg5O% jE)US)77Noej1_$Uen6G%;GX=6D}3?;9_h_1xOtcW>nCug diff --git a/index.ts b/index.ts deleted file mode 100644 index c446e56..0000000 --- a/index.ts +++ /dev/null @@ -1,115 +0,0 @@ -type TalkRow = { - position?: number; - title?: string; - format?: string; - categories?: string; - speakers?: string; - rating?: number; - loves?: number; - hates?: number; -}; - -type Format = { - id: string; - name: string; -}; - -type Speaker = { - uid: string; - displayName: string; -}; - -type Talk = { - title: string; - speakers: string[]; - formats: string; - categories: string; - rating: number; - loves: number; - hates: number; -}; - -const splitString = (str: string, n: number): string[] => { - let arr = str?.split(" "); - let result = []; - let subStr = arr[0]; - for (let i = 1; i < arr.length; i++) { - let word = arr[i]; - if (subStr.length + word.length + 1 <= n) { - subStr = subStr + " " + word; - } else { - result.push(subStr); - subStr = word; - } - } - if (subStr.length) { - result.push(subStr); - } - return result; -}; - -const removeEmojis = (str: string): string => { - return str?.replace(/[^\p{L}\p{N}\p{P}\p{Z}^$\n]/gu, "").trim(); -}; - -const argv = Bun.argv; - -if (argv.length > 2) { - const file = argv[2]; - - let titleSize: number = 100; - if (argv.length > 3) titleSize = Number(argv[3]) || 100; - - const { talks, speakers, formats, categories } = await Bun.file(file).json(); - const formatsHash = new Map(); - (formats as Format[]).forEach(({ id, name }) => { - formatsHash.set(id, removeEmojis(name)); - }); - const speakerHash = new Map(); - (speakers as Speaker[]).forEach(({ uid, displayName }) => { - speakerHash.set(uid, displayName); - }); - const categoriesHash = new Map(); - (categories as Format[]).forEach(({ id, name }) => { - categoriesHash.set(id, removeEmojis(name)); - }); - console.table( - (talks as Talk[]) - .sort((a, b) => (a.rating <= b.rating ? 1 : -1)) - .flatMap( - ( - { title, speakers, formats, categories, rating, loves, hates }, - position: number - ) => { - const lines: TalkRow[] = []; - let titleSplit: string[] = splitString( - removeEmojis(title), - titleSize - ).map((text) => text.padEnd(titleSize, " ")); - speakers.forEach((uid: string, i: number) => { - if (i === 0) - lines.push({ - position: position + 1, - title: titleSplit.shift(), - format: formatsHash.get(formats), - categories: categoriesHash.get(categories), - speakers: speakerHash.get(uid), - rating: Number(rating.toFixed(2)), - loves, - hates, - }); - else - lines.push({ - title: titleSplit.shift() ?? "", - speakers: speakerHash.get(uid), - }); - }); - titleSplit.forEach((title) => lines.push({ title })); - lines.push({}); - return lines; - } - ) - ); -} else { - console.log("Usage: coc "); -} diff --git a/package.json b/package.json index 35c31c9..cb9ec90 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,7 @@ { - "name": "conferencehall-orga-classment", - "module": "index.ts", + "name": "choc", + "version": "0.1.0", + "module": "src/index.ts", "type": "module", "devDependencies": { "@types/bun": "latest" @@ -9,9 +10,12 @@ "typescript": "^5.0.0" }, "bin": { - "coc": "./bin/index.js" + "choc": "./bin/index.js" }, "scripts": { - "make": "bun build index.ts --outfile exe/coc --compile --minify --sourcemap=none" + "make": "bun build src/index.ts --outfile exe/choc --compile --minify --sourcemap=none" + }, + "dependencies": { + "commander": "^12.0.0" } } diff --git a/src/choc.ts b/src/choc.ts new file mode 100644 index 0000000..135ef31 --- /dev/null +++ b/src/choc.ts @@ -0,0 +1,102 @@ +import type { + Format, + Options, + Speaker, + SpeakerData, + Talk, + TalkRow, +} from "./types"; +import { removeEmojis, splitString } from "./utils"; + +const choc = async (file: string, options: Options) => { + const { talks, speakers, formats, categories } = await Bun.file(file).json(); + const formatsHash = new Map(); + (formats as Format[]).forEach(({ id, name }) => { + formatsHash.set(id, removeEmojis(name)); + }); + const speakerHash = new Map(); + (speakers as Speaker[]).forEach(({ uid, displayName, company }) => { + speakerHash.set(uid, { + name: removeEmojis(displayName), + company: removeEmojis(company ?? ""), + }); + }); + const categoriesHash = new Map(); + (categories as Format[]).forEach(({ id, name }) => { + categoriesHash.set(id, removeEmojis(name)); + }); + console.table( + (talks as Talk[]) + .sort((a, b) => (a.rating <= b.rating ? 1 : -1)) + .flatMap( + ( + { + title, + speakers, + formats, + categories, + rating, + loves, + hates, + language, + }, + position: number + ) => { + const lines: TalkRow[] = []; + let titleSplit: string[] = splitString( + removeEmojis(title), + options.titlelength + ).map((text) => text.padEnd(options.titlelength, " ")); + speakers.forEach((uid: string, i: number) => { + let addCompanies = {}; + if (options.withCompanies) + addCompanies = { + company: speakerHash.get(uid)?.company, + }; + if (i === 0) { + const line = { + position: position + 1, + title: titleSplit.shift(), + }; + let addFormats = {}; + if (options.withFormats) + addFormats = { + format: formatsHash.get(formats), + }; + let addCategories = {}; + if (options.withCategories) + addCategories = { + categories: categoriesHash.get(categories), + }; + let addLanguages = {}; + if (options.withLanguages) + addLanguages = { + language: language, + }; + lines.push({ + ...line, + ...addFormats, + ...addCategories, + speakers: speakerHash.get(uid)?.name, + ...addCompanies, + ...addLanguages, + rating: Number(rating.toFixed(2)), + loves, + hates, + }); + } else + lines.push({ + title: titleSplit.shift() ?? "", + speakers: speakerHash.get(uid)?.name, + ...addCompanies, + }); + }); + titleSplit.forEach((title) => lines.push({ title })); + lines.push({}); + return lines; + } + ) + ); +}; + +export default choc; diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..0b8c1c5 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,28 @@ +#!/usr/bin/env bun +import { CommanderError, program } from "commander"; +import packagejson from "../package.json"; +import choc from "./choc"; + +function myParseInt(value: string) { + const parsedValue = parseInt(value, 10); + if (isNaN(parsedValue)) { + throw new CommanderError(0, "nan", "Not a number."); + } + return parsedValue; +} + +program + .name("choc") + .description("ConferenceHall organization companion") + .version(packagejson.version, "-v, --version"); + +program + .argument("", "the json export file") + .option("-c, --with-categories", "view categories", false) + .option("-f, --with-formats", "view formats", false) + .option("-e, --with-companies", "view speakers company", false) + .option("-l, --with-languages", "view talks language", false) + .option("-t, --titlelength ", "the title length", myParseInt, 100) + .action(choc); + +program.parse(); diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 0000000..f98cc20 --- /dev/null +++ b/src/types.ts @@ -0,0 +1,45 @@ +export type TalkRow = { + position?: number; + title?: string; + format?: string; + categories?: string; + speakers?: string; + rating?: number; + loves?: number; + hates?: number; +}; + +export type Format = { + id: string; + name: string; +}; + +export type Speaker = { + uid: string; + displayName: string; + company: string; +}; + +export type SpeakerData = { + name: string; + company: string; +}; + +export type Talk = { + title: string; + speakers: string[]; + formats: string; + categories: string; + rating: number; + loves: number; + hates: number; + language: string; +}; + +export type Options = { + withCategories: boolean; + withCompanies: boolean; + withFormats: boolean; + withLanguages: boolean; + titlelength: number; +}; diff --git a/src/utils.ts b/src/utils.ts new file mode 100644 index 0000000..ab9d4a7 --- /dev/null +++ b/src/utils.ts @@ -0,0 +1,22 @@ +export const splitString = (str: string, n: number): string[] => { + let arr = str?.split(" "); + let result = []; + let subStr = arr[0]; + for (let i = 1; i < arr.length; i++) { + let word = arr[i]; + if (subStr.length + word.length + 1 <= n) { + subStr = subStr + " " + word; + } else { + result.push(subStr); + subStr = word; + } + } + if (subStr.length) { + result.push(subStr); + } + return result; +}; + +export const removeEmojis = (str: string): string => { + return str?.replace(/[^\p{L}\p{N}\p{P}\p{Z}^$\n]/gu, "").trim(); +};