feat(runner): process charword_table.json
This commit is contained in:
@@ -3,6 +3,7 @@ folder:
|
|||||||
release: ./release/
|
release: ./release/
|
||||||
background: background
|
background: background
|
||||||
directory: _assets
|
directory: _assets
|
||||||
|
share: _share
|
||||||
operators:
|
operators:
|
||||||
chen: !include config/chen.yaml
|
chen: !include config/chen.yaml
|
||||||
dusk: !include config/dusk.yaml
|
dusk: !include config/dusk.yaml
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export default class Background {
|
|||||||
#files
|
#files
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.#backgroundFolder = path.join(__dirname, __config.folder.operator, '_share', __config.folder.background);
|
this.#backgroundFolder = path.join(__dirname, __config.folder.operator, __config.folder.share, __config.folder.background);
|
||||||
this.#extractFolder = path.join(this.#backgroundFolder, 'extracted');
|
this.#extractFolder = path.join(this.#backgroundFolder, 'extracted');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
121
libs/charword_table.js
Normal file
121
libs/charword_table.js
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
import fetch from "node-fetch"
|
||||||
|
import path from "path"
|
||||||
|
import { exists, writeSync, readdirSync, rm, readSync } from "./file.js"
|
||||||
|
|
||||||
|
// TODO: zh_TW uses an older version of charword_table.json
|
||||||
|
// const REGIONS = ["zh_CN", "en_US", "ja_JP", "ko_KR", "zh_TW"]
|
||||||
|
const REGIONS = ["zh_CN", "en_US", "ja_JP", "ko_KR"]
|
||||||
|
const DEFAULT_REGION = REGIONS[0]
|
||||||
|
const NICKNAME = {
|
||||||
|
"zh_CN": "博士",
|
||||||
|
"en_US": "Doctor",
|
||||||
|
"ja_JP": "ドクター",
|
||||||
|
"ko_KR": "박사",
|
||||||
|
"zh_TW": "博士",
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class CharwordTable {
|
||||||
|
#operatorIDs = Object.values(__config.operators).map(operator => { return operator.filename.replace(/^(dyn_illust_)(char_[\d]+)(_[\w]+)(|(_.+))$/g, '$2$3$4') })
|
||||||
|
#charwordTable = {
|
||||||
|
config: {
|
||||||
|
default_region: DEFAULT_REGION,
|
||||||
|
regions: REGIONS,
|
||||||
|
},
|
||||||
|
operators: [],
|
||||||
|
}
|
||||||
|
#charwordTablePath = path.join(__dirname, __config.folder.operator, __config.folder.share)
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
// TODO: use object instead of array
|
||||||
|
this.#charwordTable.operators = this.#operatorIDs.map(id => {
|
||||||
|
return {
|
||||||
|
mainId: id,
|
||||||
|
alternativeId: id.replace(/^(char_)([\d]+)(_[\w]+)(|(_.+))$/g, '$1$2$3'),
|
||||||
|
voice: REGIONS.reduce((acc, cur) => ({ ...acc, [cur]: [] }), {}), // use array to store voice lines
|
||||||
|
info: REGIONS.reduce((acc, cur) => ({ ...acc, [cur]: {} }), {}), // use object to store voice actor info
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async process() {
|
||||||
|
for (const region of REGIONS) {
|
||||||
|
await this.load(region)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async load(region) {
|
||||||
|
const data = await this.#download(region)
|
||||||
|
|
||||||
|
// put voice actor info into charword_table
|
||||||
|
this.#charwordTable.operators.forEach(element => {
|
||||||
|
let operatorId = element.mainId
|
||||||
|
if (typeof data.voiceLangDict[operatorId] === 'undefined') {
|
||||||
|
operatorId = element.alternativeId
|
||||||
|
}
|
||||||
|
// not available in other region
|
||||||
|
if (typeof data.voiceLangDict[operatorId] === 'undefined') {
|
||||||
|
console.log(`Voice actor info of ${element.mainId} is not available in ${region}.`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
Object.values(data.voiceLangDict[operatorId].dict).forEach(item => {
|
||||||
|
if (typeof element.info[region][item.wordkey] === 'undefined') {
|
||||||
|
element.info[region][item.wordkey] = []
|
||||||
|
}
|
||||||
|
element.info[region][item.wordkey].push({
|
||||||
|
lang: item.voiceLangType,
|
||||||
|
cvName: item.cvName,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
// put voice lines into charword_table
|
||||||
|
Object.values(data.charWords).forEach(item => {
|
||||||
|
const operatorInfo = this.#charwordTable.operators.filter(element => element.info[region][item.wordKey])
|
||||||
|
if (operatorInfo.length > 0) {
|
||||||
|
operatorInfo[0].voice[region].push({
|
||||||
|
ref: false,
|
||||||
|
id: item.voiceId,
|
||||||
|
title: item.voiceTitle,
|
||||||
|
text: item.voiceText.replace(/{@nickname}/g, NICKNAME[region]),
|
||||||
|
wordKey: item.wordKey,
|
||||||
|
})
|
||||||
|
if (operatorInfo.length > 1) {
|
||||||
|
operatorInfo[1].voice[region].push({
|
||||||
|
ref: true,
|
||||||
|
id: item.voiceId,
|
||||||
|
wordKey: item.wordKey,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
writeSync(JSON.stringify(this.#charwordTable), path.join(this.#charwordTablePath, 'charword_table.json'))
|
||||||
|
}
|
||||||
|
|
||||||
|
async #download(region) {
|
||||||
|
const historyResponse = await fetch(`https://api.github.com/repos/Kengxxiao/ArknightsGameData/commits?path=${region}/gamedata/excel/charword_table.json`)
|
||||||
|
const historyData = await historyResponse.json()
|
||||||
|
const lastCommit = historyData[0]
|
||||||
|
const lastCommitDate = new Date(lastCommit.commit.committer.date)
|
||||||
|
const filepath = path.join(this.#charwordTablePath, `charword_table_${region}_${lastCommitDate.getTime()}.json`)
|
||||||
|
console.log(`Last commit date: ${lastCommitDate.getTime()}`)
|
||||||
|
|
||||||
|
if (exists(filepath)) {
|
||||||
|
console.log(`charword_table_${region}.json is the latest version.`)
|
||||||
|
return JSON.parse(readSync(filepath))
|
||||||
|
}
|
||||||
|
const response = await fetch(`https://raw.githubusercontent.com/Kengxxiao/ArknightsGameData/master/${region}/gamedata/excel/charword_table.json`)
|
||||||
|
const data = await response.json()
|
||||||
|
writeSync(JSON.stringify(data), filepath)
|
||||||
|
console.log(`charword_table_${region}.json is updated.`)
|
||||||
|
|
||||||
|
// remove old file
|
||||||
|
const files = readdirSync(path.join(__dirname, __config.folder.operator, __config.folder.share))
|
||||||
|
for (const file of files) {
|
||||||
|
if (file.startsWith(`charword_table_${region}`) && file !== path.basename(filepath)) {
|
||||||
|
rm(path.join(__dirname, __config.folder.operator, __config.folder.share, file))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -53,3 +53,7 @@ export async function copy(sourcePath, targetPath) {
|
|||||||
export function appendSync(content, filePath) {
|
export function appendSync(content, filePath) {
|
||||||
return fs.appendFileSync(filePath, content, 'utf8');
|
return fs.appendFileSync(filePath, content, 'utf8');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function readdirSync(dir) {
|
||||||
|
return fs.readdirSync(dir)
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
"vite": "^4.0.0"
|
"vite": "^4.0.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"node-fetch": "^3.3.0",
|
||||||
"sharp": "^0.31.3",
|
"sharp": "^0.31.3",
|
||||||
"yaml": "^2.2.1"
|
"yaml": "^2.2.1"
|
||||||
}
|
}
|
||||||
|
|||||||
41
pnpm-lock.yaml
generated
41
pnpm-lock.yaml
generated
@@ -1,11 +1,13 @@
|
|||||||
lockfileVersion: 5.4
|
lockfileVersion: 5.4
|
||||||
|
|
||||||
specifiers:
|
specifiers:
|
||||||
|
node-fetch: ^3.3.0
|
||||||
sharp: ^0.31.3
|
sharp: ^0.31.3
|
||||||
vite: ^4.0.0
|
vite: ^4.0.0
|
||||||
yaml: ^2.2.1
|
yaml: ^2.2.1
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
|
node-fetch: 3.3.0
|
||||||
sharp: 0.31.3
|
sharp: 0.31.3
|
||||||
yaml: 2.2.1
|
yaml: 2.2.1
|
||||||
|
|
||||||
@@ -261,6 +263,11 @@ packages:
|
|||||||
color-string: 1.9.1
|
color-string: 1.9.1
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/data-uri-to-buffer/4.0.1:
|
||||||
|
resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==}
|
||||||
|
engines: {node: '>= 12'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/decompress-response/6.0.0:
|
/decompress-response/6.0.0:
|
||||||
resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==}
|
resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
@@ -319,6 +326,21 @@ packages:
|
|||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/fetch-blob/3.2.0:
|
||||||
|
resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==}
|
||||||
|
engines: {node: ^12.20 || >= 14.13}
|
||||||
|
dependencies:
|
||||||
|
node-domexception: 1.0.0
|
||||||
|
web-streams-polyfill: 3.2.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/formdata-polyfill/4.0.10:
|
||||||
|
resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==}
|
||||||
|
engines: {node: '>=12.20.0'}
|
||||||
|
dependencies:
|
||||||
|
fetch-blob: 3.2.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/fs-constants/1.0.0:
|
/fs-constants/1.0.0:
|
||||||
resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==}
|
resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==}
|
||||||
dev: false
|
dev: false
|
||||||
@@ -409,6 +431,20 @@ packages:
|
|||||||
resolution: {integrity: sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==}
|
resolution: {integrity: sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/node-domexception/1.0.0:
|
||||||
|
resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==}
|
||||||
|
engines: {node: '>=10.5.0'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/node-fetch/3.3.0:
|
||||||
|
resolution: {integrity: sha512-BKwRP/O0UvoMKp7GNdwPlObhYGB5DQqwhEDQlNKuoqwVYSxkSZCSbHjnFFmUEtwSKRPU4kNK8PbDYYitwaE3QA==}
|
||||||
|
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||||
|
dependencies:
|
||||||
|
data-uri-to-buffer: 4.0.1
|
||||||
|
fetch-blob: 3.2.0
|
||||||
|
formdata-polyfill: 4.0.10
|
||||||
|
dev: false
|
||||||
|
|
||||||
/once/1.4.0:
|
/once/1.4.0:
|
||||||
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
|
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -623,6 +659,11 @@ packages:
|
|||||||
fsevents: 2.3.2
|
fsevents: 2.3.2
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/web-streams-polyfill/3.2.1:
|
||||||
|
resolution: {integrity: sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==}
|
||||||
|
engines: {node: '>= 8'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/wrappy/1.0.2:
|
/wrappy/1.0.2:
|
||||||
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
|
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import init from './libs/initializer.js'
|
|||||||
import directory from './libs/directory.js'
|
import directory from './libs/directory.js'
|
||||||
import { appendReadme } from './libs/append.js'
|
import { appendReadme } from './libs/append.js'
|
||||||
import Background from './libs/background.js'
|
import Background from './libs/background.js'
|
||||||
|
import CharwordTable from './libs/charword_table.js';
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
global.__dirname = path.dirname(fileURLToPath(import.meta.url))
|
global.__dirname = path.dirname(fileURLToPath(import.meta.url))
|
||||||
@@ -37,6 +38,10 @@ async function main() {
|
|||||||
for (const [key, _] of Object.entries(__config.operators)) {
|
for (const [key, _] of Object.entries(__config.operators)) {
|
||||||
OPERATOR_NAMES.push(key)
|
OPERATOR_NAMES.push(key)
|
||||||
}
|
}
|
||||||
|
case 'test':
|
||||||
|
const charwordTable = new CharwordTable()
|
||||||
|
await charwordTable.process()
|
||||||
|
process.exit(0)
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -48,7 +53,7 @@ async function main() {
|
|||||||
const OPERATOR_RELEASE_FOLDER = path.join(__dirname, __config.folder.release, OPERATOR_NAME)
|
const OPERATOR_RELEASE_FOLDER = path.join(__dirname, __config.folder.release, OPERATOR_NAME)
|
||||||
const SHOWCASE_PUBLIC_ASSSETS_FOLDER = path.join(OPERATOR_RELEASE_FOLDER, "assets")
|
const SHOWCASE_PUBLIC_ASSSETS_FOLDER = path.join(OPERATOR_RELEASE_FOLDER, "assets")
|
||||||
const EXTRACTED_FOLDER = path.join(OPERATOR_SOURCE_FOLDER, OPERATOR_NAME, 'extracted')
|
const EXTRACTED_FOLDER = path.join(OPERATOR_SOURCE_FOLDER, OPERATOR_NAME, 'extracted')
|
||||||
const OPERATOR_SHARE_FOLDER = path.join(OPERATOR_SOURCE_FOLDER, '_share')
|
const OPERATOR_SHARE_FOLDER = path.join(OPERATOR_SOURCE_FOLDER, __config.folder.share)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Skip assets generation part
|
* Skip assets generation part
|
||||||
|
|||||||
Reference in New Issue
Block a user