Add signet pages

This commit is contained in:
Sakura Knoll
2023-07-13 19:55:43 +09:00 Unverified
parent 53396776df
commit 2edb2cde77
16 changed files with 655 additions and 4 deletions
+43
View File
@@ -0,0 +1,43 @@
import { Box, Flex, Image } from 'theme-ui'
interface SquareImageProps {
src: string
originalSize: number
size?: number
alt?: string
}
const SquareImage = ({ src, originalSize, size, alt }: SquareImageProps) => {
if (size == null) {
size = originalSize
}
const ratio = size / originalSize
return (
<Box sx={{ width: size, height: size, position: 'relative' }}>
<Box
sx={{
position: 'absolute',
left: (size - originalSize) / 2,
top: (size - originalSize) / 2
}}
>
<Flex
sx={{
position: 'absolute',
width: originalSize,
height: originalSize,
alignItems: 'center',
justifyContent: 'center',
zIndex: 1,
transform: `scale(${ratio})`
}}
>
<Image src={src} alt={alt} />
</Flex>
</Box>
</Box>
)
}
export default SquareImage
+16
View File
@@ -0,0 +1,16 @@
export const signetGroups = [
{ id: '1', name: '[구원]의 각인', icon: 'Kevin' },
{ id: '2', name: '[황금]의 각인', icon: 'Eden' },
{ id: '3', name: '[오멸]의 각인', icon: 'Kalpas' },
{ id: '4', name: '[천혜]의 각인', icon: 'Su' },
{ id: '5', name: '[찰나]의 각인', icon: 'Sakura' },
{ id: '6', name: '[무한]의 각인', icon: 'Mobius' },
{ id: '7', name: '[부생]의 각인', icon: 'Hua' },
// { id: '8', name: '[■■]의 각인', icon: 'Elysia' },
// { id: '9', name: '[■■]의 각인', icon: 'Elysia' },
{ id: '10', name: '[계율]의 각인', icon: 'Aponia' },
{ id: '11', name: '[나선]의 각인', icon: 'Verve' },
{ id: '12', name: '[욱광]의 각인', icon: 'Kosma' },
{ id: '13', name: '[번성]의 각인', icon: 'Griseo' },
{ id: '14', name: '[환몽]의 각인', icon: 'Pardofelis' }
]
-1
View File
@@ -23,7 +23,6 @@ describe('formatSubSkillInfo', () => {
it('appends 0, based on precision, if the calculated value does not have decimals', () => {
const params = {
info: '전투 중 초기 SP가 #1[f1] 증가하며, 오픈월드에서는 10분에 1회 발동한다.',
maxLv: 11,
paramBase1: 20,
paramBase2: 0,
+15
View File
@@ -223,3 +223,18 @@ export function getTagTypeLabel(type: TagType) {
return `Unknown Tag Type (${type})`
}
}
export function getErSignetTypeLabel(quality: number) {
switch (quality) {
case 1:
return '일반 각인'
case 2:
return '증폭 각인'
case 3:
return '코어 각인'
case 4:
return '전용 각인'
default:
return `Unknown (${quality})`
}
}
+30
View File
@@ -261,3 +261,33 @@ export interface StigmataSetCatalogItem {
name: string
stigmataList: { id: string; icon: string; maxRarity: number }[]
}
export interface ErSignet {
id: string
name: string
desc: string
buffSuit: string
quality: number
}
export interface ErBattlesuit {
battlesuit: string
abilities: ErBattlesuitAbility[]
signets: ErSignet[]
}
export interface ErBattlesuitCatalogItem {
battlesuit: string
}
export interface ErBattlesuitAbility {
id: string
type: number
name: string
desc: string
}
export interface ErSignetGroup {
id: string
name: string
icon: string
}
@@ -0,0 +1,45 @@
import { compileGodWarData } from './compileGodWarData'
describe('compileGodWarData', () => {
it('compiles main battlesuit abilities and signets', () => {
const { mainAvatarList } = compileGodWarData()
const targetItem = mainAvatarList[11]
expect(targetItem).toMatchObject({
battlesuit: expect.any(String),
abilities: expect.arrayContaining([
expect.objectContaining({
name: expect.any(String),
desc: expect.any(String)
})
]),
signets: expect.arrayContaining([
{
id: expect.any(String),
buffSuit: expect.any(String),
name: expect.any(String),
desc: expect.any(String),
quality: expect.any(Number)
}
])
})
})
it('compiles buff list per suit', () => {
const { buffSuitBuffListMap } = compileGodWarData()
const targetItem = buffSuitBuffListMap.get('3')
expect(targetItem).toEqual(
expect.arrayContaining([
expect.objectContaining({
id: expect.any(String),
buffSuit: expect.any(String),
name: expect.any(String),
desc: expect.any(String),
quality: expect.any(Number)
})
])
)
})
})
@@ -0,0 +1,83 @@
import { ErBattlesuit, ErBattlesuitAbility, ErSignet, ErSignetGroup } from '../../data/types'
import { getRawGodWarAvatarAbilityMap } from '../raw/godWarAvatarAbility'
import { getRawGodWarBuffMap } from '../raw/godWarBuff'
import { getRawGodWarBuffSuitMap } from '../raw/godWarBuffSuit'
import { getRawGodWarMainAvatarMap } from '../raw/godWarMainAvatar'
import { getText } from './utils'
export function compileGodWarData() {
const rawMainAvatarMap = getRawGodWarMainAvatarMap()['1']
const rawGodWarAvatarAbilityMap = getRawGodWarAvatarAbilityMap()
const rawGodWarBuffMap = getRawGodWarBuffMap()
const rawGodWarBuffSuitMap = getRawGodWarBuffSuitMap()
const battlesuitIdRawBuffListMap = new Map<string, ErSignet[]>()
const buffSuitBuffListMap = new Map<string, ErSignet[]>()
Object.entries(rawGodWarBuffMap).forEach(([id1, rawbuffMap]) => {
const rawBuffList = Object.entries(rawbuffMap)
rawBuffList.forEach(([id2, rawBuff]) => {
const buffSuit = rawBuff.BuffSuit.toString()
// No data
if (buffSuit === '0') {
return
}
if (buffSuit === '8') {
const buffGroupId = rawBuff.BuffGroup.toString()
let buffList = battlesuitIdRawBuffListMap.get(buffGroupId)
if (buffList == null) {
buffList = []
battlesuitIdRawBuffListMap.set(buffGroupId, buffList)
}
buffList.push({
id: `${id1}-${id2}`,
name: getText(rawBuff.BuffName),
desc: getText(rawBuff.BuffDesc),
buffSuit,
quality: rawBuff.BuffQuality
})
} else {
if (rawBuff.BuffSuit < 10 && id1.length > 4) {
return
}
let buffList = buffSuitBuffListMap.get(buffSuit)
if (buffList == null) {
buffList = []
buffSuitBuffListMap.set(buffSuit, buffList)
}
buffList.push({
id: `${id1}-${id2}`,
name: getText(rawBuff.BuffName),
desc: getText(rawBuff.BuffDesc),
buffSuit,
quality: rawBuff.BuffQuality
})
}
})
})
const mainAvatarList = Object.entries(rawMainAvatarMap).map<ErBattlesuit>(([id, rawData]) => {
const abilities = rawData.AvatarAbilityID.map<ErBattlesuitAbility>(id => {
const stringId = id.toString()
const rawAbility = rawGodWarAvatarAbilityMap[stringId]
return {
id: stringId,
type: rawAbility.AbilityType,
name: getText(rawAbility.AbilityTitle),
desc: getText(rawAbility.AbilityDes)
}
})
const signets = battlesuitIdRawBuffListMap.get(id)!
return {
battlesuit: id,
abilities,
signets
}
})
return {
buffSuitBuffListMap,
mainAvatarList
}
}
+32 -3
View File
@@ -1,7 +1,17 @@
import fs from 'fs'
import path from 'path'
import YAML from 'yaml'
import { BattlesuitCatalogItem, RootStigma, StigmataSet, WeaponCatalogItem } from '../data/types'
import {
BattlesuitCatalogItem,
ErBattlesuit,
ErBattlesuitCatalogItem,
ErSignet,
RootStigma,
StigmataCatalogItem,
StigmataSet,
StigmataSetCatalogItem,
WeaponCatalogItem
} from '../data/types'
export const dataDir = path.join(process.cwd(), 'data/v2-pre')
@@ -17,6 +27,11 @@ export const stigmataCatalogPath = path.join(dataDir, 'stigmata-catalog.yaml')
export const stigmataSetsDir = path.join(dataDir, 'stigmata-sets')
export const stigmataSetCatalogPath = path.join(dataDir, 'stigmata-set-catalog.yaml')
export const erBattlesuitCatalogPath = path.join(dataDir, 'er-battlesuits-catalog.yaml')
export const erBattlesuitsDir = path.join(dataDir, 'er-battlesuits')
export const erSignetsDir = path.join(dataDir, 'er-signets')
export const erSignetGroupsPath = path.join(dataDir, 'er-signet-groups.yaml')
export function loadBattlesuitCatalog(): BattlesuitCatalogItem[] {
return readYamlFile(battlesuitCatalogPath)
}
@@ -35,7 +50,7 @@ export function loadWeaponData(id: string) {
return readYamlFile(weaponDataPath)
}
export function loadStigmataCatalog(): WeaponCatalogItem[] {
export function loadStigmataCatalog(): StigmataCatalogItem[] {
return readYamlFile(stigmataCatalogPath)
}
@@ -44,7 +59,7 @@ export function loadStigmaData(id: string): RootStigma {
return readYamlFile(stigmaDataPath)
}
export function loadStigmataSetCatalog(): WeaponCatalogItem[] {
export function loadStigmataSetCatalog(): StigmataSetCatalogItem[] {
return readYamlFile(stigmataSetCatalogPath)
}
@@ -53,6 +68,20 @@ export function loadStigmataSetData(id: string): StigmataSet {
return readYamlFile(stigmataSetPath)
}
export function loadErBattlesuitCatalog(): ErBattlesuitCatalogItem[] {
return readYamlFile(erBattlesuitCatalogPath)
}
export function loadErBattlesuit(id: string): ErBattlesuit {
const erBattlesuitPath = path.join(erBattlesuitsDir, `${id}.yaml`)
return readYamlFile(erBattlesuitPath)
}
export function loadErSignets(id: string): ErSignet[] {
const erSignetsPath = path.join(erSignetsDir, `${id}.yaml`)
return readYamlFile(erSignetsPath)
}
function readYamlFile(pathname: string) {
return YAML.parse(fs.readFileSync(pathname).toString())
}
@@ -0,0 +1,17 @@
import { loadRawData } from './loadRawData'
export function getRawGodWarAvatarAbilityMap(): RawGodWarAvatarAbilityMap {
return loadRawData('GodWarAvatarAbility.json')
}
export type RawGodWarAvatarAbilityMap = {
[key: string]: RawGodWarAvatarAbility
}
export interface RawGodWarAvatarAbility {
AbilityType: number
AbilityTitle: number
AbilityDes: number
AbilityIcon: string
IsShowInAvatarChallenge: boolean
}
+26
View File
@@ -0,0 +1,26 @@
import { loadRawData } from './loadRawData'
export function getRawGodWarBuffMap(): RawGodWarBuffMap {
return loadRawData('GodWarBuff.json')
}
export type RawGodWarBuffMap = {
[key: string]: {
[key: string]: RawGodWarBuff
}
}
export interface RawGodWarBuff {
BuffSuit: number
BuffQuality: number
AbilityName: string
ParamList: string[]
BuffIcon: string // 'SpriteOutput/Rogue/BuffIcon/RogueGodIcon_1'
BuffName: number
BuffDesc: number
BuffUpDesc: number
SimpleBuffDesc: number
BuffTagList: unknown[]
ShowBuffIconEffect: boolean
BuffGroup: number
}
@@ -0,0 +1,18 @@
import { loadRawData } from './loadRawData'
export function getRawGodWarBuffSuitMap(): RawGodWarBuffSuitMap {
return loadRawData('GodWarBuffSuit.json')
}
export type RawGodWarBuffSuitMap = {
[key: string]: RawGodWarBuffSuit
}
export interface RawGodWarBuffSuit {
SuitIcon: string
SuitName: number
SuitDesc: number
SuitImage: string
ShowSuitIconEffect: boolean
ShowFilterOption: boolean
}
@@ -0,0 +1,24 @@
import { loadRawData } from './loadRawData'
export function getRawGodWarMainAvatarMap(): RawGodWarMainAvataMap {
return loadRawData('GodWarMainAvatar.json')
}
export type RawGodWarMainAvataMap = {
[key: string]: {
[key: string]: RawGodWarAvatarData
}
}
export interface RawGodWarAvatarData {
AbilityName: string
ParamList: string[]
StepUnlockMissionMap: {
MissionID: number
StepID: number
}[]
AvatarAbilityID: number[]
AvatarMissionList: number[]
RecommendLink: string
AvatarChallengeStageIDList: number[]
}
@@ -0,0 +1,115 @@
import { NextPageContext } from 'next'
import { Box, Card, Flex, Heading, Image } from 'theme-ui'
import AvatarFigureImage from '../../../../components/v2-pre/AvatarFigureImage'
import { loadBattlesuitData, loadErBattlesuit, loadErBattlesuitCatalog } from '../../../../lib/v2-pre/server/loadData'
import { Battlesuit, ErBattlesuit, ErSignet } from '../../../../lib/v2-pre/data/types'
import { Fragment, useMemo } from 'react'
import { assetsBucketBaseUrl } from '../../../../lib/consts'
interface BattlesuitShowPageProps {
battlesuit: Battlesuit
erBattlesuit: ErBattlesuit
}
const BattlesuitShowPage = ({ battlesuit, erBattlesuit }: BattlesuitShowPageProps) => {
const signetSets = useMemo(() => {
const signetSetMap = erBattlesuit.signets
.slice()
.sort((a, b) => {
return a.id.localeCompare(b.id)
})
.reduce<Map<string, ErSignet[]>>((map, signet) => {
const result = signet.id.match(/([12])([0-9]+)([1-5])-[0-9]/)
if (result != null) {
const [, _lv, _battlesuit, signetOrder] = result
let set = map.get(signetOrder)
if (set == null) {
set = []
map.set(signetOrder, set)
}
set.push(signet)
}
return map
}, new Map())
return [...signetSetMap.values()]
}, [erBattlesuit.signets])
return (
<Box>
<Heading as="h1">{battlesuit.fullName}</Heading>
<AvatarFigureImage battlesuitId={battlesuit.id} sx={{ height: 400 }} />
<Heading as="h2">ER Adjustments</Heading>
<Card mb={3}>
{erBattlesuit.abilities.map(ability => {
return (
<Fragment key={ability.id}>
<Box sx={{ p: 1, borderBottom: 'default' }}>
<Heading as="h3" m={0}>
{ability.name}
</Heading>
</Box>
<Box sx={{ p: 1, borderBottom: 'default', '&:last-child': { borderBottom: 'none' } }}>{ability.desc}</Box>
</Fragment>
)
})}
</Card>
<Heading as="h2">Exclusive Signets</Heading>
{signetSets.map((set, index) => {
return (
<Card key={index} mb={2}>
{set.map(signet => {
return (
<Fragment key={signet.id}>
<Flex sx={{ p: 1, borderBottom: 'default', alignItems: 'center' }}>
<Image
src={`${assetsBucketBaseUrl}/raw/supportbufficon/Elysia.png`}
width={30}
sx={{ flexShrink: 0 }}
alt={'Elysia'}
/>
<Heading as="h3" m={0}>
{signet.name}
</Heading>
</Flex>
<Box sx={{ p: 1, borderBottom: 'default', '&:last-child': { borderBottom: 'none' } }}>
{signet.desc}
</Box>
</Fragment>
)
})}
</Card>
)
})}
</Box>
)
}
export default BattlesuitShowPage
export async function getStaticProps({ locale, params }: NextPageContext & { params: { battlesuitId: string } }) {
const battlesuit = loadBattlesuitData(params.battlesuitId)
const erBattlesuit = loadErBattlesuit(params.battlesuitId)
return {
props: { battlesuit, erBattlesuit }
}
}
export async function getStaticPaths() {
const battlesuitCatalog = loadErBattlesuitCatalog()
return {
paths: battlesuitCatalog.map(catalogItem => {
return {
params: { battlesuitId: catalogItem.battlesuit }
}
}),
fallback: false
}
}
+75
View File
@@ -0,0 +1,75 @@
/** @jsxImportSource theme-ui */
import { Box, Heading, Flex, Link, Card } from '@theme-ui/components'
import { NextPageContext } from 'next'
import { loadBattlesuitCatalog, loadErBattlesuitCatalog } from '../../../lib/v2-pre/server/loadData'
import { BattlesuitCatalogItem, ErBattlesuitCatalogItem } from '../../../lib/v2-pre/data/types'
import { useMemo } from 'react'
import BattlesuitCatalogItemCard from '../../../components/v2-pre/BattlesuitCatalogItemCard'
import { assetsBucketBaseUrl } from '../../../lib/consts'
import SquareImage from '../../../components/v2-pre/SquareImage'
import { signetGroups } from '../../../lib/v2-pre/data/er'
interface ErPageProps {
erBattlesuitCatalog: ErBattlesuitCatalogItem[]
battlesuitCatalog: BattlesuitCatalogItem[]
}
const ErPage = ({ erBattlesuitCatalog, battlesuitCatalog }: ErPageProps) => {
const battlesuitCatalogMap = useMemo(() => {
return battlesuitCatalog.reduce((map, item) => {
map.set(item.id, item)
return map
}, new Map<string, BattlesuitCatalogItem>())
}, [battlesuitCatalog])
return (
<Box>
<h1>Elysian Realm</h1>
<Heading as="h2">Signets</Heading>
<Flex sx={{ flexWrap: 'wrap' }}>
{signetGroups.map(signetGroup => {
return (
<Link href={`/v2-pre/er/signets/${signetGroup.id}`} key={signetGroup.id}>
<Card p={1} m={1}>
<Flex sx={{ alignItems: 'center' }}>
<SquareImage
src={`${assetsBucketBaseUrl}/raw/supportbufficon/${signetGroup.icon}.png`}
originalSize={120}
size={40}
/>
<Box p={1}>{signetGroup.name}</Box>
</Flex>
</Card>
</Link>
)
})}
</Flex>
<Heading as="h2">Battlesuits</Heading>
<Flex sx={{ flexWrap: 'wrap' }}>
{erBattlesuitCatalog.map(erBattlesuit => {
const battlesuit = battlesuitCatalogMap.get(erBattlesuit.battlesuit)!
return (
<Box key={battlesuit.id}>
<Link href={`/v2-pre/er/battlesuits/${battlesuit.id}`}>
<BattlesuitCatalogItemCard battlesuit={battlesuit} />
</Link>
</Box>
)
})}
</Flex>
<Heading as="h2">Supports</Heading>
</Box>
)
}
export default ErPage
export async function getStaticProps({ locale }: NextPageContext) {
const erBattlesuitCatalog = loadErBattlesuitCatalog()
const battlesuitCatalog = loadBattlesuitCatalog()
return {
props: { erBattlesuitCatalog, battlesuitCatalog }
}
}
+89
View File
@@ -0,0 +1,89 @@
import { NextPageContext } from 'next'
import { Box, Card, Flex, Heading } from 'theme-ui'
import { loadErSignets } from '../../../../lib/v2-pre/server/loadData'
import { ErSignet, ErSignetGroup } from '../../../../lib/v2-pre/data/types'
import { Fragment, useMemo } from 'react'
import { assetsBucketBaseUrl } from '../../../../lib/consts'
import { signetGroups } from '../../../../lib/v2-pre/data/er'
import SquareImage from '../../../../components/v2-pre/SquareImage'
import { getErSignetTypeLabel } from '../../../../lib/v2-pre/data/text'
interface BattlesuitShowPageProps {
group: ErSignetGroup
signets: ErSignet[]
}
const BattlesuitShowPage = ({ signets, group }: BattlesuitShowPageProps) => {
const signetSets = useMemo(() => {
const signetSetMap = signets.reduce<Map<string, ErSignet[]>>((map, signet) => {
const [id1, _id2] = signet.id.split('-')
let set = map.get(id1)
if (set == null) {
set = []
map.set(id1, set)
}
set.push(signet)
return map
}, new Map())
return [...signetSetMap.values()]
}, [signets])
return (
<Box>
<Heading as="h1">{group.name}</Heading>
{signetSets.map((set, index) => {
return (
<Card key={index} mb={2}>
{set.map(signet => {
return (
<Fragment key={signet.id}>
<Flex sx={{ p: 1, borderBottom: 'default', alignItems: 'center' }}>
<SquareImage
src={`${assetsBucketBaseUrl}/raw/supportbufficon/${group.icon}.png`}
size={30}
originalSize={120}
/>
<Heading as="h3" my={0} ml={1}>
{signet.name}
</Heading>
<Box sx={{ ml: 12, color: 'textMuted' }}>{getErSignetTypeLabel(signet.quality)}</Box>
</Flex>
<Box sx={{ p: 1, borderBottom: 'default', '&:last-child': { borderBottom: 'none' } }}>
{signet.desc}
</Box>
</Fragment>
)
})}
</Card>
)
})}
{/*
<pre>
<code>{JSON.stringify(signets, null, 2)}</code>
</pre> */}
</Box>
)
}
export default BattlesuitShowPage
export async function getStaticProps({ locale, params }: NextPageContext & { params: { groupId: string } }) {
const signets = loadErSignets(params.groupId)
const group = signetGroups.find(group => group.id === params.groupId)
return {
props: { signets, group }
}
}
export async function getStaticPaths() {
return {
paths: signetGroups.map(group => {
return {
params: { groupId: group.id }
}
}),
fallback: false
}
}
+27
View File
@@ -7,6 +7,9 @@ import {
battlesuitCatalogPath,
battlesuitsDir,
dataDir,
erBattlesuitCatalogPath,
erBattlesuitsDir,
erSignetsDir,
stigmataCatalogPath,
stigmataDir,
stigmataSetCatalogPath,
@@ -23,12 +26,14 @@ import {
import { compileBattlesuitData } from '../lib/v2-pre/server/compileData/compileBattlesuitData'
import { compileWeaponData } from '../lib/v2-pre/server/compileData/compileWeaponData'
import { compileStigmataData } from '../lib/v2-pre/server/compileData/compileStigmataData'
import { compileGodWarData } from '../lib/v2-pre/server/compileData/compileGodWarData'
runScript(async () => {
createDirIfNotExist(dataDir)
writeBattlesuitData()
writeWeaponData()
writeStigmataData()
writeErData()
})
function writeBattlesuitData() {
@@ -126,3 +131,25 @@ function writeStigmataData() {
fs.writeFileSync(stigmaSetDataPath, YAML.stringify(stigmataSet))
}
}
function writeErData() {
const { buffSuitBuffListMap, mainAvatarList } = compileGodWarData()
const erBattlesuitCatalog = mainAvatarList.map(mainAvatar => {
return { battlesuit: mainAvatar.battlesuit }
})
fs.writeFileSync(erBattlesuitCatalogPath, YAML.stringify(erBattlesuitCatalog))
createDirIfNotExist(erBattlesuitsDir)
for (const erBattlesuit of mainAvatarList) {
const erBattlesuitPath = path.join(erBattlesuitsDir, `${erBattlesuit.battlesuit}.yaml`)
fs.writeFileSync(erBattlesuitPath, YAML.stringify(erBattlesuit))
}
createDirIfNotExist(erSignetsDir)
for (const [buffSuit, list] of buffSuitBuffListMap) {
const erSignetsPath = path.join(erSignetsDir, `${buffSuit}.yaml`)
fs.writeFileSync(erSignetsPath, YAML.stringify(list))
}
}