Refactor weapon data

This commit is contained in:
Sakura Knoll
2022-07-04 08:59:01 +09:00 Unverified
parent 3388151c42
commit f91d61dd93
13 changed files with 100 additions and 319 deletions
+5 -10
View File
@@ -1,22 +1,17 @@
/** @jsxImportSource theme-ui */
import { Box, Card, Text, Flex } from '@theme-ui/components'
import { useRouter } from 'next/router'
import { assetsBucketBaseUrl } from '../../lib/consts'
import { WeaponData } from '../../lib/honkai3rd/weapons'
import { translate } from '../../lib/i18n'
import PageLink from '../atoms/PageLink'
import SquareImageBox from '../atoms/SquareImageBox'
interface WeaponCardProps {
weapon: Pick<WeaponData, 'id' | 'name' | 'rarity' | 'krName'>
weapon: Pick<WeaponData, 'id' | 'name' | 'rarity'>
hidden?: boolean
size?: 'sm' | 'default'
}
const WeaponCard = ({ weapon, hidden, size = 'default' }: WeaponCardProps) => {
const { locale } = useRouter()
const weaponName = translate(locale, { 'ko-KR': weapon.krName }, weapon.name)
if (size === 'sm') {
return (
<Card
@@ -35,7 +30,7 @@ const WeaponCard = ({ weapon, hidden, size = 'default' }: WeaponCardProps) => {
<SquareImageBox
mr={2}
size={30}
alt={weaponName}
alt={weapon.name}
src={`${assetsBucketBaseUrl}/honkai3rd/weapons/${weapon.id}.png`}
/>
<Box
@@ -47,7 +42,7 @@ const WeaponCard = ({ weapon, hidden, size = 'default' }: WeaponCardProps) => {
textAlign: 'center',
}}
>
<Text sx={{ lineHeight: '30px' }}>{weaponName}</Text>
<Text sx={{ lineHeight: '30px' }}>{weapon.name}</Text>
</Box>
</Flex>
</PageLink>
@@ -70,7 +65,7 @@ const WeaponCard = ({ weapon, hidden, size = 'default' }: WeaponCardProps) => {
<PageLink href={`/honkai3rd/weapons/${weapon.id}`}>
<SquareImageBox
size={100}
alt={weaponName}
alt={weapon.name}
src={`${assetsBucketBaseUrl}/honkai3rd/weapons/${weapon.id}.png`}
/>
<Box
@@ -82,7 +77,7 @@ const WeaponCard = ({ weapon, hidden, size = 'default' }: WeaponCardProps) => {
textAlign: 'center',
}}
>
<Text>{weaponName}</Text>
<Text>{weapon.name}</Text>
</Box>
<Box sx={{ fontSize: 1, textAlign: 'center' }}>
{'⭐'.repeat(weapon.rarity)}
-4
View File
@@ -2,15 +2,12 @@ import { SourceData } from './sources'
export interface WeaponSkill {
name: string
krName?: string
description: string
krDescription?: string
}
export interface WeaponData {
id: string
name: string
krName?: string
atk: number
crt: number
category:
@@ -31,7 +28,6 @@ export interface WeaponData {
id: string
suitability?: number
description?: string
descriptionKr?: string
}[]
priWeapon?: string
originalWeapons?: string[]
@@ -293,7 +293,7 @@ export async function getStaticProps({
},
{ weaponIds: [], stigmataIds: [] }
)
const weaponMap = getWeaponMapByIds(weaponIds)
const weaponMap = getWeaponMapByIds(weaponIds, locale)
const stigmataMap = getStigmataMapByIds(stigmataIds)
+1 -1
View File
@@ -170,7 +170,7 @@ export default BattlesuitListPage
export async function getStaticProps({ locale }: NextPageContext) {
return {
props: {
battlesuits: listBattlesuits().map((battlesuit) => {
battlesuits: listBattlesuits(locale).map((battlesuit) => {
return {
id: battlesuit.id,
name: battlesuit.name,
@@ -2,6 +2,7 @@
import { Box, Card, Heading, Paragraph } from '@theme-ui/components'
import { NextPageContext } from 'next'
import SquareImageBox from '../../../../components/atoms/SquareImageBox'
import Breadcrumb from '../../../../components/organisms/Breadcrumb'
import { WeaponData } from '../../../../lib/honkai3rd/weapons'
import { generateI18NPaths, getI18NProps } from '../../../../server/i18n'
import {
@@ -9,8 +10,7 @@ import {
getWeaponMapByIds,
listWeapons,
} from '../../../../server/data/honkai3rd/weapons'
import { useRouter } from 'next/router'
import { useTranslation, translate } from '../../../../lib/i18n'
import { useTranslation } from '../../../../lib/i18n'
import PageLink from '../../../../components/atoms/PageLink'
import { assetsBucketBaseUrl } from '../../../../lib/consts'
import { getBattlesuitMapByIds } from '../../../../server/data/honkai3rd/battlesuits'
@@ -29,20 +29,29 @@ const WeaponShowPage = ({
battlesuitMap,
weaponMap,
}: WeaponShowPageProps) => {
const { locale } = useRouter()
const { t } = useTranslation()
const weaponName = translate(locale, { 'ko-KR': weapon.krName }, weapon.name)
const weaponCategory = t(`weapons-show.${weapon.category}`)
return (
<Box p={3}>
<Heading as='h1'>{weaponName}</Heading>
<Breadcrumb
items={[
{ href: '/honkai3rd', label: t('common.honkai-3rd') },
{ href: '/honkai3rd/weapons', label: t('common.weapons') },
{
href: `/honkai3rd/weapons/${weapon.id}`,
label: weapon.name,
},
]}
/>
<Heading as='h1'>{weapon.name}</Heading>
<Box mb={3}>
<SquareImageBox
size={100}
alt={weaponName}
alt={weapon.name}
src={`${assetsBucketBaseUrl}/honkai3rd/weapons/${weapon.id}.png`}
/>
</Box>
@@ -115,7 +124,7 @@ const WeaponShowPage = ({
return (
<Card key={skill.name} mb={3}>
<Heading as='h3' p={2} m={0} sx={{ borderBottom: 'default' }}>
{translate(locale, { 'ko-KR': skill.krName }, skill.name)}
{skill.name}
</Heading>
<Paragraph
p={2}
@@ -123,11 +132,7 @@ const WeaponShowPage = ({
whiteSpace: 'pre-wrap',
}}
>
{translate(
locale,
{ 'ko-KR': skill.krDescription },
skill.description
)}
{skill.description}
</Paragraph>
</Card>
)
@@ -143,7 +148,7 @@ export async function getStaticProps({
params,
locale,
}: NextPageContext & { params: { weaponId: string } }) {
const weapon = getWeaponById(params.weaponId)
const weapon = getWeaponById(params.weaponId, locale)
const battlesuitMap = getBattlesuitMapByIds(
weapon != null && weapon.battlesuits != null
? weapon.battlesuits.map(({ id }) => id)
@@ -160,7 +165,7 @@ export async function getStaticProps({
weaponIds.push(...weapon.originalWeapons)
}
}
const weaponMap = getWeaponMapByIds(weaponIds)
const weaponMap = getWeaponMapByIds(weaponIds, locale)
return {
props: {
+3 -8
View File
@@ -61,7 +61,7 @@ const VersionShowPage = ({
})
.join(',')} / ${t('versions.new-weapons')}: ${weapons
.map((weapon) => {
return translate(locale, { 'ko-KR': weapon.krName }, weapon.name)
return weapon.name
})
.join(',')}`}
/>
@@ -136,11 +136,6 @@ const VersionShowPage = ({
</Heading>
<Box mb={3} sx={{ display: 'inline-block' }}>
{weapons.map((weapon) => {
const weaponName = translate(
locale,
{ 'ko-KR': weapon.krName },
weapon.name
)
return (
<NextLink
key={weapon.id}
@@ -152,10 +147,10 @@ const VersionShowPage = ({
<SquareImageBox
size={40}
src={`${assetsBucketBaseUrl}/honkai3rd/weapons/${weapon.id}.png`}
alt={`${weaponName}`}
alt={`${weapon.name}`}
mr={2}
/>
<Text>{weaponName}</Text>
<Text>{weapon.name}</Text>
</Flex>
</Link>
</NextLink>
+2 -7
View File
@@ -130,11 +130,6 @@ const VersionIndexPage = ({
</Heading>
<Box mb={3} sx={{ display: 'inline-block' }}>
{currentVersionNewWeapons.map((weapon) => {
const weaponName = translate(
locale,
{ 'ko-KR': weapon.krName },
weapon.name
)
return (
<NextLink
key={weapon.id}
@@ -146,10 +141,10 @@ const VersionIndexPage = ({
<SquareImageBox
size={40}
src={`${assetsBucketBaseUrl}/honkai3rd/weapons/${weapon.id}.png`}
alt={`${weaponName}`}
alt={`${weapon.name}`}
mr={2}
/>
<Text>{weaponName}</Text>
<Text>{weapon.name}</Text>
</Flex>
</Link>
</NextLink>
+11 -18
View File
@@ -10,8 +10,7 @@ import {
getWeaponMapByIds,
listWeapons,
} from '../../../server/data/honkai3rd/weapons'
import { useRouter } from 'next/router'
import { useTranslation, translate } from '../../../lib/i18n'
import { useTranslation } from '../../../lib/i18n'
import Head from '../../../components/atoms/Head'
import PageLink from '../../../components/atoms/PageLink'
import { assetsBucketBaseUrl } from '../../../lib/consts'
@@ -20,7 +19,6 @@ import { getBattlesuitMapByIds } from '../../../server/data/honkai3rd/battlesuit
import { BattlesuitData } from '../../../lib/honkai3rd/battlesuits'
import BattlesuitCard from '../../../components/molecules/BattlesuitCard'
import WeaponCard from '../../../components/molecules/WeaponCard'
// import SourceCard from '../../../components/molecules/SourceCard'
interface WeaponShowPageProps {
weapon: WeaponData
@@ -33,16 +31,14 @@ const WeaponShowPage = ({
battlesuitMap,
weaponMap,
}: WeaponShowPageProps) => {
const { locale } = useRouter()
const { t } = useTranslation()
const weaponName = translate(locale, { 'ko-KR': weapon.krName }, weapon.name)
const weaponCategory = t(`weapons-show.${weapon.category}`)
return (
<Honkai3rdLayout>
<Head
title={`${weaponName} - ${t('common.honkai-3rd')} - ${t(
title={`${weapon.name} - ${t('common.honkai-3rd')} - ${t(
'common.abyss-lab'
)}`}
description={`${t('common.honkai-3rd')} ${t(
@@ -59,17 +55,17 @@ const WeaponShowPage = ({
{ href: '/honkai3rd/weapons', label: t('common.weapons') },
{
href: `/honkai3rd/weapons/${weapon.id}`,
label: weaponName,
label: weapon.name,
},
]}
/>
<Heading as='h1'>{weaponName}</Heading>
<Heading as='h1'>{weapon.name}</Heading>
<Box mb={3}>
<SquareImageBox
size={100}
alt={weaponName}
alt={weapon.name}
src={`${assetsBucketBaseUrl}/honkai3rd/weapons/${weapon.id}.png`}
/>
</Box>
@@ -142,7 +138,7 @@ const WeaponShowPage = ({
return (
<Card key={skill.name} mb={3}>
<Heading as='h3' p={2} m={0} sx={{ borderBottom: 'default' }}>
{translate(locale, { 'ko-KR': skill.krName }, skill.name)}
{skill.name}
</Heading>
<Paragraph
p={2}
@@ -150,11 +146,7 @@ const WeaponShowPage = ({
whiteSpace: 'pre-wrap',
}}
>
{translate(
locale,
{ 'ko-KR': skill.krDescription },
skill.description
)}
{skill.description}
</Paragraph>
</Card>
)
@@ -171,11 +163,12 @@ export async function getStaticProps({
params,
locale,
}: NextPageContext & { params: { weaponId: string } }) {
const weapon = getWeaponById(params.weaponId)
const weapon = getWeaponById(params.weaponId, locale)
const battlesuitMap = getBattlesuitMapByIds(
weapon != null && weapon.battlesuits != null
? weapon.battlesuits.map(({ id }) => id)
: []
: [],
locale
)
const weaponIds = []
@@ -187,7 +180,7 @@ export async function getStaticProps({
weaponIds.push(...weapon.originalWeapons)
}
}
const weaponMap = getWeaponMapByIds(weaponIds)
const weaponMap = getWeaponMapByIds(weaponIds, locale)
return {
props: {
+3 -3
View File
@@ -16,7 +16,7 @@ import Honkai3rdLayout from '../../../components/layouts/Honkai3rdLayout'
type WeaponListItemData = Pick<
WeaponData,
'id' | 'name' | 'rarity' | 'category' | 'krName'
'id' | 'name' | 'rarity' | 'category'
>
interface WeaponListPageProps {
@@ -110,8 +110,8 @@ export default WeaponListPage
export async function getStaticProps({ locale }: NextPageContext) {
return {
props: {
weaponDataList: listWeapons().map((weapon) => {
return pick(['name', 'id', 'rarity', 'category', 'krName'], weapon)
weaponDataList: listWeapons(locale).map((weapon) => {
return pick(['name', 'id', 'rarity', 'category'], weapon)
}),
...(await getI18NProps(locale)),
},
-141
View File
@@ -1,141 +0,0 @@
import { BattlesuitSkillGroup } from '../lib/honkai3rd/battlesuits'
import { existsSync, writeFileSync } from '../server/data/fs'
import { listBattlesuits } from '../server/data/honkai3rd/battlesuits'
import { listElfs } from '../server/data/honkai3rd/elfs'
import {
listStigmata,
listStigmataSet,
} from '../server/data/honkai3rd/stigmata'
import { listWeapons } from '../server/data/honkai3rd/weapons'
const locale = 'ko-KR'
export function generateStigmataData() {
const stigmataList = listStigmata()
stigmataList.forEach((stigmata) => {
const krStigmataDataPath = `honkai3rd/${locale}/stigmata/${stigmata.id}.md`
if (existsSync(krStigmataDataPath)) {
return
}
writeFileSync(
krStigmataDataPath,
[
`# ${stigmata.name}`,
`## ${stigmata.skill.name}`,
`${stigmata.skill.description}`,
].join('\n\n')
)
})
}
export function generateStigmataSetData() {
const stigmataSetList = listStigmataSet()
stigmataSetList.forEach((stigmataSet) => {
const krStigmataSetDataPath = `honkai3rd/${locale}/stigmata-sets/${stigmataSet.id}.md`
if (existsSync(krStigmataSetDataPath)) {
return
}
writeFileSync(
krStigmataSetDataPath,
[
`# ${stigmataSet.name}`,
stigmataSet.altName,
`## ${stigmataSet.twoSetSkill.name}`,
`${stigmataSet.twoSetSkill.description}`,
`## ${stigmataSet.threeSetSkill.name}`,
`${stigmataSet.threeSetSkill.description}`,
].join('\n\n')
)
})
}
export function generateWeaponData() {
const weaponList = listWeapons()
weaponList.forEach((weapon) => {
const krWeaponDataPath = `honkai3rd/${locale}/weapons/${weapon.id}.md`
if (existsSync(krWeaponDataPath)) {
return
}
writeFileSync(
krWeaponDataPath,
[
`# ${weapon.name}`,
...weapon.skills.map((skill) => {
return [`## ${skill.name}`, skill.description].join('\n\n')
}),
].join('\n\n')
)
})
}
export function generateElfData() {
const elfList = listElfs()
elfList.forEach((elf) => {
const krElfDataPath = `honkai3rd/${locale}/elfs/${elf.id}.md`
if (existsSync(krElfDataPath)) {
return
}
writeFileSync(
krElfDataPath,
[
`# ${elf.name}`,
...elf.skillRows.map((skillRow) => {
return skillRow
.map((skill, index) => {
return [
`${index === 0 ? '##' : '###'} ${skill.name}`,
skill.description,
].join('\n\n')
})
.join('\n\n')
}),
].join('\n\n')
)
})
}
export function generateBattlesuitData() {
const battlesuitList = listBattlesuits()
battlesuitList.forEach((battlesuit) => {
const krBattlesuitDataPath = `honkai3rd/${locale}/battlesuits/${battlesuit.id}.md`
if (existsSync(krBattlesuitDataPath)) {
return
}
writeFileSync(
krBattlesuitDataPath,
[
`# ${battlesuit.name}`,
stringifySkillGroup(battlesuit.leader),
stringifySkillGroup(battlesuit.passive),
stringifySkillGroup(battlesuit.evasion),
stringifySkillGroup(battlesuit.special),
stringifySkillGroup(battlesuit.ultimate),
stringifySkillGroup(battlesuit.basic),
battlesuit.sp != null ? stringifySkillGroup(battlesuit.sp) : '',
]
.join('\n\n')
.trim()
)
})
}
function stringifySkillGroup(skillGroup: BattlesuitSkillGroup) {
return [
`## ${skillGroup.core.name}`,
skillGroup.core.description,
...skillGroup.subskills.map((subskill) => {
return [`### ${subskill.name}`, subskill.description].join('\n\n')
}),
]
.join('\n\n')
.trim()
}
-41
View File
@@ -1,41 +0,0 @@
import { runScript } from '../lib/utils'
import fs from 'fs'
import path from 'path'
import yaml from 'yaml'
import sortKeys from 'sort-keys'
import { listWeapons } from '../../server/data/honkai3rd/weapons'
const order = [
'id',
'version',
'name',
'krName',
'category',
'rarity',
'atk',
'crt',
'battlesuits',
'originalWeapons',
'sources',
'skills',
'description',
'krDescription',
]
async function migrateWeapons() {
const weapons = listWeapons()
const newDataDir = path.join(__dirname, '../../../data/honkai3rd')
const sortedData = sortKeys(weapons, {
deep: true,
compare: (a, b) => {
return order.indexOf(a) - order.indexOf(b)
},
})
fs.writeFileSync(
path.join(newDataDir, 'weapons.yaml'),
yaml.stringify(sortedData)
)
}
runScript(migrateWeapons)
+4 -4
View File
@@ -4,11 +4,11 @@ import path from 'path'
import yaml from 'yaml'
import { omit } from 'ramda'
let parsedData: any = null
let cachedData: any = null
export function listBattlesuits(locale?: string): BattlesuitData[] {
if (parsedData == null) {
parsedData = yaml.parse(
if (cachedData == null) {
cachedData = yaml.parse(
fs
.readFileSync(
path.join(process.cwd(), 'data/honkai3rd/battlesuits.yaml')
@@ -16,7 +16,7 @@ export function listBattlesuits(locale?: string): BattlesuitData[] {
.toString('utf-8')
)
}
const battlesuits = parsedData
const battlesuits = cachedData
const localized = (battlesuits as any[]).map((battlesuit) => {
return {
+51 -67
View File
@@ -1,87 +1,71 @@
import { readdirSync, readFileSync, readJsonFileSync } from '../fs'
import { compareVersion } from '../../../lib/string'
import { WeaponData } from '../../../lib/honkai3rd/weapons'
import yaml from 'yaml'
import fs from 'fs'
import path from 'path'
import { omit } from 'ramda'
const weaponsFileNameList = readdirSync('honkai3rd/weapons')
const weaponDataList = weaponsFileNameList
.map((fileName) => {
const filePathname = 'honkai3rd/weapons/' + fileName
const data = readJsonFileSync(filePathname) as WeaponData
let cachedData: any = null
const krDataFilePath = `honkai3rd/ko-KR/weapons/${data.id}.md`
try {
const krData = parseWeaponData(readFileSync(krDataFilePath).toString())
export function listWeapons(locale?: string): WeaponData[] {
if (cachedData == null) {
cachedData = yaml.parse(
fs
.readFileSync(path.join(process.cwd(), 'data/honkai3rd/weapons.yaml'))
.toString('utf-8')
)
}
const weapons = cachedData
data.krName = krData.name
data.skills.forEach((skill, index) => {
skill.krName = krData.skills[index].name
skill.krDescription = krData.skills[index].description
})
} catch (error) {
// console.warn('Failed to read', krDataFilePath)
// console.warn(error)
}
const localized = (weapons as any[])
.map((weapon) => {
return {
...omit(['krName', 'krDescription'], weapon),
name: locale === 'ko-KR' ? weapon.krName : weapon.name,
skills: weapon.skills.map((skill: any) => localizeSkill(skill)),
} as any
})
.sort((a, b) => {
let compareResult = 0
return data
})
.sort((a, b) => {
let compareResult = 0
compareResult = compareVersion(b.version || '0.0', a.version || '0.0')
if (compareResult !== 0) {
return compareResult
}
compareResult = b.rarity - a.rarity
if (compareResult !== 0) {
return compareResult
}
compareResult = a.name
.replace(/ \(.\)/, '')
.localeCompare(b.name.replace(/ \(.\)/, ''))
compareResult = compareVersion(b.version || '0.0', a.version || '0.0')
if (compareResult !== 0) {
return compareResult
})
return localized
function localizeSkill(skill: any) {
return {
...omit(['krName', 'krDescription'], skill),
name: locale === 'ko-KR' ? skill.krName : skill.name,
description: locale === 'ko-KR' ? skill.krDescription : skill.description,
}
compareResult = b.rarity - a.rarity
if (compareResult !== 0) {
return compareResult
}
compareResult = a.name
.replace(/ \(.\)/, '')
.localeCompare(b.name.replace(/ \(.\)/, ''))
return compareResult
})
const weaponMap = weaponDataList.reduce((map, weapon) => {
map.set(weapon.id, weapon)
return map
}, new Map<string, WeaponData>())
export function listWeapons() {
return weaponDataList
}
}
export function getWeaponById(id: string) {
return weaponMap.get(id)
export function getWeaponById(id: string, locale?: string) {
return listWeapons(locale).find((weapon) => weapon.id === id, locale)
}
export function getWeaponMapByIds(idList: string[]) {
export function getWeaponMapByIds(idList: string[], locale?: string) {
return idList.reduce<{ [key: string]: WeaponData }>((map, id) => {
const weapon = getWeaponById(id)
const weapon = getWeaponById(id, locale)
if (weapon != null) {
map[id] = weapon
}
return map
}, {})
}
function parseWeaponData(rawData: string) {
const [name, ...skillSections] = rawData
.replace(/\\\*/g, '*')
.split('## ')
.map((data) => data.replace(/#+\s/, '').trim())
const skills = skillSections.map((skillSection) => {
const [skillName, skillDescription] = skillSection.split('\n\n')
return {
name: skillName,
description: skillDescription,
}
})
return {
name,
skills,
}
}