refactor several parts

This commit is contained in:
Oystein Kristoffer Tveit 2021-01-13 16:39:19 +01:00
parent 35bfb83ca4
commit 8be562048a
6 changed files with 133 additions and 132 deletions

View File

@ -26,6 +26,7 @@ async function main(grade) {
let resultPage = ''; let resultPage = '';
for (kanji of texData) { for (kanji of texData) {
resultPage+=`${kanji.kanjiPageHeader} resultPage+=`${kanji.kanjiPageHeader}
${kanji.label}
${kanji.kanjiMeaning ? kanji.kanjiMeaning : ''} ${kanji.kanjiMeaning ? kanji.kanjiMeaning : ''}
${kanji.kunyomi ? kanji.kunyomi : ''} ${kanji.kunyomi ? kanji.kunyomi : ''}
${kanji.onyomi ? kanji.onyomi : ''} ${kanji.onyomi ? kanji.onyomi : ''}
@ -56,4 +57,4 @@ async function argWrapper() {
} }
} }
argWrapper(); argWrapper();

View File

@ -1,58 +1,57 @@
function makeNumberRow(rowLength) {
let numberRow = [...Array(rowLength).keys()]; // Array containing numbers 0 to rowLength-1 const makeNumberRow = (length) => {
numberRow = numberRow.map((number) => (number + 1).toString()); // Correct numbers and convert to string const numberRow = [ ' ',
numberRow = numberRow.map((number) => `{\\large ${number}}`); // Encapsulate numbers in TeX code ...[...Array(length).keys()]
numberRow = [' ', ...numberRow]; .map(num => `{\\large ${num+1}}`),
' ' ].join(' & ');
return ` return `
${numberRow.join(' & ')} \\\\ ${numberRow} \\\\
\\hline \\hline
\\endhead\n`; \\endhead\n`;
} }
function kanjiRow(index, rowLength, kanjiArray) { const lastNonEmptyChar = (chars) => {
let result = []; let index = chars.length - 1;
for (let rowIndex = 0; rowIndex < rowLength; rowIndex++) { while (chars[index] == '') index--;
const currentIndex = index + rowIndex; return chars[index]
result.push(kanjiArray[currentIndex] ? kanjiArray[currentIndex] : '');
}
return result;
} }
function makeRows(rowLength, columnLength, kanjiArray) { const makeKanjiRow = (index, chars) =>
let result = ''; [ `{\\large ${index}}`,
for (let columnIndex = 0; columnIndex < columnLength; columnIndex++) { ...chars.map(chara => `\\hyperref[${chara}]{${chara}}`),
let line = new Array; `p.\\pageref{${lastNonEmptyChar(chars)}}` ].join(' & ');
const index = columnIndex * rowLength;
// Add the number of current character const splitBy = (array, num) => {
line.push(`{\\large ${index}}`); let results = [];
while (array.length) {
// Concatenate the number with the rest of the row results.push(array.splice(0, num));
line = [...line, ...kanjiRow(index, rowLength, kanjiArray)];
// Convert the line array into a tex row and add it to result.
result += `${line.join(' & ')} \\\\\n`;
} }
results[results.length-1].length = num;
return result; results[results.length-1] = Array.from(results[results.length-1], chara => chara || '');
return results;
} }
const makeRows = (length, kanjiArray) =>
[ ...splitBy(kanjiArray, length)
.map((row, i) => makeKanjiRow(i*length,row)),
'' ].join(' \\\\\n');
/** /**
* Turns an array of kanji into a tabular for a chapter overview * Turns an array of kanji into a tabular for a chapter overview
* @param {string[]} kanjiArray An array of kanji characters to put into the tabular * @param {string[]} kanjiArray An array of kanji characters to put into the tabular
* @param {number} rowLength The length of each row * @param {number} rowLength The length of each row
* @returns {string} A tex tabular * @returns {string} A tex tabular
*/ */
function chapterTabular(kanjiArray, rowLength) { function chapterTabular(kanjiArray, length) {
const columnLength = Math.ceil(kanjiArray.length/rowLength); // const height = Math.ceil(kanjiArray.length/length);
let tabularString = ''; let tabularString = '';
tabularString += makeNumberRow(rowLength); tabularString += makeNumberRow(length);
tabularString += makeRows(rowLength, columnLength, kanjiArray); tabularString += makeRows(length, kanjiArray);
return `\\begin{chapterTabular}{ ${' l | ' + 'l '.repeat(rowLength)}} return `\\begin{chapterTabular}{ ${' l | ' + 'l '.repeat(length + 1)}}
${tabularString}\\end{chapterTabular}` ${tabularString}\\end{chapterTabular}`
} }
exports.chapterTabular = chapterTabular; exports.chapterTabular = chapterTabular;

View File

@ -1,49 +1,40 @@
const fs = require('fs'); const fs = require('fs');
const util = require('util'); const util = require('util');
const jishoApi = require('unofficial-jisho-api'); const jishoApi = require('unofficial-jisho-api');
const jisho = new jishoApi(); const jisho = new jishoApi();
const txtFolder = './data/jouyou/'; const txtFolder = './data/jouyou/';
const jishoBufferFolder = './data/jisho/'; const jishoBufferFolder = './data/jisho/';
/* Async version of fs.readFile */ const fetchCharactersFromTxt = file => [...fs.readFileSync(file, 'utf8')];
const readFile = util.promisify(fs.readFile); const fetchBufferedJishoResults = file => JSON.parse(fs.readFileSync(file, 'utf8'));
async function fetchCharactersFromTxt(file) { const makeDelayedJishoRequest = (kanji, delay) =>
const data = await readFile(file, 'utf8'); new Promise(
return [...data]; (res, rej) => setTimeout(() => res(jisho.searchForKanji(kanji)), delay)
} );
async function fetchBufferedJishoResults(file) {
const data = await readFile(file, 'utf8');
return JSON.parse(data);
}
async function makeDelayedJishoRequest(kanji, delay) {
return new Promise((res, rej) => {
setTimeout(() => { res(jisho.searchForKanji(kanji)); }, delay);
});
}
/* Sort array of jisho results based on stroke count */ /* Sort array of jisho results based on stroke count */
const sortJishoResults = (jishoResult) => jishoResult.sort((a, b) => (a.strokeCount > b.strokeCount) ? 1 : -1); const sortJishoResults = jishoResult => jishoResult.sort((a, b) => a.strokeCount > b.strokeCount);
/* Fetches Jisho results with a delay of 50ms between each request */ /* Fetches Jisho results with a delay of 50ms between each request */
async function fetchKanjiFromJisho(kanjiArray) { const fetchKanjiFromJisho = async (kanjiArray) => {
const delayedRequests = kanjiArray.map(async (kanji, i) => await makeDelayedJishoRequest(kanji, i*50)); const delayedRequests = kanjiArray.map((kanji, i) => makeDelayedJishoRequest(kanji, i*50));
const data = await Promise.all(delayedRequests); const data = await Promise.all(delayedRequests);
return sortJishoResults(data); return sortJishoResults(data);
} }
async function fetchJishoDataAndWriteToBuffer(grade) { async function fetchJishoDataAndWriteToBuffer(grade) {
const kanjiArray = await fetchCharactersFromTxt(`${txtFolder}${grade}.txt`); const kanjiArray = fetchCharactersFromTxt(`${txtFolder}${grade}.txt`);
const jishoResults = await fetchKanjiFromJisho(kanjiArray); const jishoResults = await fetchKanjiFromJisho(kanjiArray);
fs.writeFile(
fs.writeFileSync(
`${jishoBufferFolder}${grade}.json`, `${jishoBufferFolder}${grade}.json`,
JSON.stringify(jishoResults, null, " "), JSON.stringify(jishoResults, null, " "),
(err) => { if (err) console.error(err) } (err) => { if (err) console.error(err) }
); );
return jishoResults; return jishoResults;
} }
@ -58,12 +49,12 @@ async function fetchJishoResults(grade, log) {
const bufferFileExists = fs.existsSync(`${jishoBufferFolder}${grade}.json`); const bufferFileExists = fs.existsSync(`${jishoBufferFolder}${grade}.json`);
if(bufferFileExists) { if(bufferFileExists) {
log('Fetching Jisho data from buffer', grade) log('Fetching Jisho data from buffer', grade);
return await fetchBufferedJishoResults(`${jishoBufferFolder}${grade}.json`); return fetchBufferedJishoResults(`${jishoBufferFolder}${grade}.json`);
} else { } else {
log('Fetching data from Jisho and writing to buffer', grade) log('Fetching data from Jisho and writing to buffer', grade);
return await fetchJishoDataAndWriteToBuffer(grade); return await fetchJishoDataAndWriteToBuffer(grade);
} }
} }
exports.fetchJishoResults = fetchJishoResults; exports.fetchJishoResults = fetchJishoResults;

View File

@ -5,77 +5,77 @@ const stylingBrackets = {
const yomiConnector = '、 '; const yomiConnector = '、 ';
const yomiDash = '—'; const yomiDash = '—';
const styleText = (string) => `\\emphasize{${string}}`; const regexes = [
[/"|\[|\]/g, ''], // Remove all []
[/\\/g, '\\\\'], // Escape \
[/%/g, '\\%'], //Escape %
[/&/g, '\\&'], // Escape &
[/,/g, yomiConnector] // convert all , to yomiConnector
]
function styleCharactersBeforeDot(string) { const styleText = string => `\\emphasize{${string}}`;
// ab.c -> \emph{ab}.c
const styleCharactersBeforeDot = string => {
const words = string.split('.'); const words = string.split('.');
words[0] = styleText(words[0]); words[0] = styleText(words[0]);
return words.join(''); return words.join('');
} }
function styleEverythingExceptDash(string) { // abc- -> \emph{abc}-
const words = string.split(/(?<=\-)/); const styleEverythingExceptDash = string => {
if (words[0] === '-') { // ['-', 'word'] const parts = string.split(/(?<=\-)/);
words[0] = yomiDash; if (parts[0] === '-') { // ['-', 'abc']
words[1] = styleText(words[1]); parts[0] = yomiDash;
} else { // ['Word-', ''] parts[1] = styleText(parts[1]);
words[1] = yomiDash; } else { // ['abc-', '']
words[0] = words[0].slice(0, words[0].length-1); parts[1] = yomiDash;
words[0] = styleText(words[0]); parts[0] = parts[0].slice(0, -1);
parts[0] = styleText(parts[0]);
} }
return words.join(''); return parts.join('');
} }
function convertKunyomi(jishoResult) { const convertKunyomi = jishoResult =>
jishoResult.kunyomi.length === 0
? ''
: JSON.stringify(jishoResult.kunyomi)
.replace(/"|\[|\]/g, '')
.replace(/\\/g, '\\\\')
.replace(/%/g, '\\%')
.replace(/&/g, '\\&')
.split(',')
.map(reading => {
if (reading.includes('.') && reading.includes('-'))
return `${yomiDash}${styleCharactersBeforeDot(reading.slice(1))}`
else if (reading.includes('.'))
return styleCharactersBeforeDot(reading);
else if (reading.includes('-'))
return styleEverythingExceptDash(reading);
else
return styleText(reading);
})
.join(yomiConnector);
if (jishoResult.kunyomi.length === 0) return ''; const convertOnyomi = jishoResult =>
JSON.stringify(jishoResult.onyomi)
const kunyomi = JSON.stringify(jishoResult.kunyomi)
.replace(/"|\[|\]/g, '') .replace(/"|\[|\]/g, '')
.replace(/\\/g, '\\\\') .replace(/\\/g, '\\\\')
.replace(/%/g, '\\%') .replace(/%/g, '\\%')
.replace(/&/g, '\\&') .replace(/&/g, '\\&')
.split(','); .split(',')
.map(styleText)
for (const i in kunyomi) { .join(yomiConnector);
instance = kunyomi[i];
if (instance.includes('.') && instance.includes('-')) {
//TODO: Apply combinated logic here
}
else if (instance.includes('.')) {
kunyomi[i] = styleCharactersBeforeDot(instance);
}
else if (instance.includes('-')) {
kunyomi[i] = styleEverythingExceptDash(instance);
}
else {
kunyomi[i] = styleText(instance);
}
}
return kunyomi.join(yomiConnector);
}
function convertOnyomi(jishoResult) {
return JSON.stringify(jishoResult.onyomi)
.replace(/"|\[|\]/g, '')
.replace(/\\/g, '\\\\')
.replace(/%/g, '\\%')
.replace(/,/g, yomiConnector)
.replace(/&/g, '\\&');
//TODO: Style only the words, and not the yomiConnector inbetween //TODO: Style only the words, and not the yomiConnector inbetween
}
function convertMeaning(jishoResult) { const convertMeaning = jishoResult =>
return jishoResult.meaning jishoResult.meaning
.replace(/\\/g, '\\\\') .replace(/\\/g, '\\\\')
.replace(/%/g, '\\%') .replace(/%/g, '\\%')
.replace(/&/g, '\\&'); .replace(/&/g, '\\&');
}
const makeFirstLetterUppercase = (string) => string.charAt(0).toUpperCase() + string.slice(1); const makeFirstLetterUppercase = string => string.charAt(0).toUpperCase() + string.slice(1);
/** /**
* Generate TeX strings from Jisho data * Generate TeX strings from Jisho data
@ -83,26 +83,27 @@ const makeFirstLetterUppercase = (string) => string.charAt(0).toUpperCase() + st
* @param {string} grade * @param {string} grade
* @returns {object} An object containg TeX strings * @returns {object} An object containg TeX strings
*/ */
function getKanjiTexData(jishoResults, grade) { const getKanjiTexData = (jishoResults, grade) => {
return jishoResults.map(jishoResult => {
grade = grade.slice(0,5) + ' ' + grade.slice(5); // graden -> grade n
grade = makeFirstLetterUppercase(grade);
if (grade === 'Grade 7') grade = 'Junior High';
return jishoResults.map(jishoResult => {
const meaning = convertMeaning(jishoResult); const meaning = convertMeaning(jishoResult);
const kunyomi = convertKunyomi(jishoResult); const kunyomi = convertKunyomi(jishoResult);
const onyomi = convertOnyomi(jishoResult); const onyomi = convertOnyomi(jishoResult);
grade = grade.slice(0,5) + ' ' + grade.slice(5);
grade = makeFirstLetterUppercase(grade);
if (grade === 'Grade 7') grade = 'Junior high'
return { return {
kanjiPageHeader: `\\kanjiPageHeader{${jishoResult.query}}{${grade}}{${jishoResult.jlptLevel}}{${jishoResult.strokeCount}}{${jishoResult.radical.symbol}}`, kanjiPageHeader: `\\kanjiPageHeader{${jishoResult.query}}{${grade}}{${jishoResult.jlptLevel}}{${jishoResult.strokeCount}}{${jishoResult.radical.symbol}}`,
label: `\\label{${jishoResult.query}}`,
kanjiMeaning: meaning ? `\\kanjiMeaning{${meaning}}` : '', kanjiMeaning: meaning ? `\\kanjiMeaning{${meaning}}` : '',
kunyomi: kunyomi ? `\\kunyomi{${kunyomi}}` : '', kunyomi: kunyomi ? `\\kunyomi{${kunyomi}}` : '',
onyomi: onyomi ? `\\onyomi{${onyomi}}` : '', onyomi: onyomi ? `\\onyomi{${onyomi}}` : '',
kanjiRow: `\\kanjiRow{${jishoResult.query}}` kanjiRow: `\\kanjiRow{${jishoResult.query}}`
} }
}); });
} }
exports.getKanjiTexData = getKanjiTexData; exports.getKanjiTexData = getKanjiTexData;

View File

@ -12,9 +12,7 @@
% Chapter Introduction % % Chapter Introduction %
% ---------------------------------------------------------------------------- % % ---------------------------------------------------------------------------- %
\setcounter{secnumdepth}{0} \newcommand{\tocPiece}[2]{
\newcommand{\chapterIntroduction}[2]{
% For some reason, I'm not able to use \uppercase in order to use % For some reason, I'm not able to use \uppercase in order to use
% a single argument. In the end, I found that just using two arguments % a single argument. In the end, I found that just using two arguments
% was going to be easier than trying to override the way the LaTeX % was going to be easier than trying to override the way the LaTeX
@ -23,11 +21,15 @@
\begin{center} \begin{center}
\fontsize{16}{16} \fontsize{16}{16}
\rowcolors{1}{}{kanjiColor!20!white}
\input{./data/tables/#2.tex} \input{./data/tables/#2.tex}
\end{center} \end{center}
}
\localtableofcontents \setcounter{secnumdepth}{0}
\newcommand{\chapterIntroduction}[2]{
\tocPiece{#1}{#2}
\break \break
} }

View File

@ -31,7 +31,7 @@
\input{./kanjiLib.tex} \input{./kanjiLib.tex}
\usepackage{etoc} % For local tocs containing level based kanji list. % \usepackage{etoc} % For local tocs containing level based kanji list.
\begin{document} \begin{document}
@ -43,7 +43,14 @@
\break \break
\tableofcontents \tocPiece{Grade 1}{grade1}
\tocPiece{Grade 2}{grade2}
\tocPiece{Grade 3}{grade3}
\tocPiece{Grade 4}{grade4}
\tocPiece{Grade 5}{grade5}
\tocPiece{Grade 6}{grade6}
\tocPiece{Junior High}{grade7}
\break \break
\section*{Preface} \section*{Preface}
@ -60,21 +67,21 @@
\input{./data/pages/grade1.tex} \input{./data/pages/grade1.tex}
\chapterIntroduction{Grade 2}{grade2} \chapterIntroduction{Grade 2}{grade2}
% \input{./data/pages/grade2.tex} \input{./data/pages/grade2.tex}
\chapterIntroduction{Grade 3}{grade3} \chapterIntroduction{Grade 3}{grade3}
% \input{./data/pages/grade3.tex} \input{./data/pages/grade3.tex}
\chapterIntroduction{Grade 4}{grade4} \chapterIntroduction{Grade 4}{grade4}
% \input{./data/pages/grade4.tex} \input{./data/pages/grade4.tex}
\chapterIntroduction{Grade 5}{grade5} \chapterIntroduction{Grade 5}{grade5}
% \input{./data/pages/grade5.tex} \input{./data/pages/grade5.tex}
\chapterIntroduction{Grade 6}{grade6} \chapterIntroduction{Grade 6}{grade6}
% \input{./data/pages/grade6.tex} \input{./data/pages/grade6.tex}
\chapterIntroduction{Junior High}{grade7} \chapterIntroduction{Junior High}{grade7}
% \input{./data/pages/grade7.tex} \input{./data/pages/grade7.tex}
\end{document} \end{document}