This commit is contained in:
@@ -5,7 +5,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"generate:data": "node scripts/generate-data-manifest.mjs",
|
"generate:data": "tsx scripts/generate-data-manifest.ts",
|
||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
"@vitejs/plugin-vue": "^2.3.4",
|
"@vitejs/plugin-vue": "^2.3.4",
|
||||||
"vite": "^2.9.16",
|
"vite": "^2.9.16",
|
||||||
"typescript": "^4.9.5",
|
"typescript": "^4.9.5",
|
||||||
"vue-tsc": "^1.0.24"
|
"vue-tsc": "^1.0.24",
|
||||||
|
"tsx": "^4.7.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,68 +0,0 @@
|
|||||||
import fs from 'fs'
|
|
||||||
import path from 'path'
|
|
||||||
|
|
||||||
const projectRoot = process.cwd()
|
|
||||||
const dataRoot = path.join(projectRoot, 'public', 'Data')
|
|
||||||
const outputPath = path.join(projectRoot, 'public', 'data.json')
|
|
||||||
|
|
||||||
const isDirectory = (target) => {
|
|
||||||
try {
|
|
||||||
return fs.statSync(target).isDirectory()
|
|
||||||
} catch {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const listDirectories = (target) => {
|
|
||||||
if (!isDirectory(target)) return []
|
|
||||||
return fs.readdirSync(target).filter((entry) => isDirectory(path.join(target, entry)))
|
|
||||||
}
|
|
||||||
|
|
||||||
const buildManifest = () => {
|
|
||||||
const games = []
|
|
||||||
const gameNames = listDirectories(dataRoot)
|
|
||||||
gameNames.forEach((gameName) => {
|
|
||||||
const gamePath = path.join(dataRoot, gameName)
|
|
||||||
const categories = []
|
|
||||||
const categoryNames = listDirectories(gamePath)
|
|
||||||
categoryNames.forEach((categoryName) => {
|
|
||||||
const songsDir = path.join(gamePath, categoryName, 'Songs')
|
|
||||||
const answersDir = path.join(gamePath, categoryName, 'Answers')
|
|
||||||
const clues = []
|
|
||||||
for (let i = 1; i <= 5; i += 1) {
|
|
||||||
const songPath = path.join('Data', gameName, categoryName, 'Songs', `${i}.mp3`)
|
|
||||||
const answerPath = path.join('Data', gameName, categoryName, 'Answers', `${i}.mp3`)
|
|
||||||
const songExists = fs.existsSync(path.join(dataRoot, gameName, categoryName, 'Songs', `${i}.mp3`))
|
|
||||||
const answerExists = fs.existsSync(
|
|
||||||
path.join(dataRoot, gameName, categoryName, 'Answers', `${i}.mp3`)
|
|
||||||
)
|
|
||||||
clues.push({
|
|
||||||
number: i,
|
|
||||||
points: i * 100,
|
|
||||||
song: songExists ? `/${songPath.replace(/\\/g, '/')}` : null,
|
|
||||||
answer: answerExists ? `/${answerPath.replace(/\\/g, '/')}` : null
|
|
||||||
})
|
|
||||||
}
|
|
||||||
categories.push({
|
|
||||||
name: categoryName,
|
|
||||||
clues
|
|
||||||
})
|
|
||||||
})
|
|
||||||
games.push({
|
|
||||||
name: gameName,
|
|
||||||
categories
|
|
||||||
})
|
|
||||||
})
|
|
||||||
return games
|
|
||||||
}
|
|
||||||
|
|
||||||
const main = () => {
|
|
||||||
if (!isDirectory(dataRoot)) {
|
|
||||||
fs.writeFileSync(outputPath, JSON.stringify([], null, 2))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const manifest = buildManifest()
|
|
||||||
fs.writeFileSync(outputPath, JSON.stringify(manifest, null, 2))
|
|
||||||
}
|
|
||||||
|
|
||||||
main()
|
|
||||||
105
scripts/generate-data-manifest.ts
Normal file
105
scripts/generate-data-manifest.ts
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
import fs from 'fs'
|
||||||
|
import path from 'path'
|
||||||
|
|
||||||
|
type Clue = {
|
||||||
|
number: number
|
||||||
|
points: number
|
||||||
|
song: string | null
|
||||||
|
answer: string | null
|
||||||
|
}
|
||||||
|
|
||||||
|
type Category = {
|
||||||
|
name: string
|
||||||
|
clues: Clue[]
|
||||||
|
}
|
||||||
|
|
||||||
|
type Game = {
|
||||||
|
name: string
|
||||||
|
categories: Category[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const projectRoot = process.cwd()
|
||||||
|
const publicRoot = path.join(projectRoot, 'public')
|
||||||
|
const dataRoot = path.join(publicRoot, 'Data')
|
||||||
|
const outputPath = path.join(publicRoot, 'data.json')
|
||||||
|
|
||||||
|
const isDirectory = (target: string) => {
|
||||||
|
try {
|
||||||
|
return fs.statSync(target).isDirectory()
|
||||||
|
} catch {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const listDirectories = (target: string) => {
|
||||||
|
if (!isDirectory(target)) return []
|
||||||
|
return fs.readdirSync(target).filter((entry) => isDirectory(path.join(target, entry)))
|
||||||
|
}
|
||||||
|
|
||||||
|
const findSubdirCaseInsensitive = (baseDir: string, desiredName: string) => {
|
||||||
|
if (!isDirectory(baseDir)) return null
|
||||||
|
const entries = fs.readdirSync(baseDir)
|
||||||
|
const match = entries.find(
|
||||||
|
(entry) => entry.toLowerCase() === desiredName.toLowerCase() && isDirectory(path.join(baseDir, entry))
|
||||||
|
)
|
||||||
|
return match ? path.join(baseDir, match) : null
|
||||||
|
}
|
||||||
|
|
||||||
|
const findFileCaseInsensitive = (baseDir: string, fileName: string) => {
|
||||||
|
if (!isDirectory(baseDir)) return null
|
||||||
|
const entries = fs.readdirSync(baseDir)
|
||||||
|
const match = entries.find((entry) => entry.toLowerCase() === fileName.toLowerCase())
|
||||||
|
return match ? path.join(baseDir, match) : null
|
||||||
|
}
|
||||||
|
|
||||||
|
const buildManifest = (): Game[] => {
|
||||||
|
const games: Game[] = []
|
||||||
|
const gameNames = listDirectories(dataRoot)
|
||||||
|
gameNames.forEach((gameName) => {
|
||||||
|
const gamePath = path.join(dataRoot, gameName)
|
||||||
|
const categories: Category[] = []
|
||||||
|
const categoryNames = listDirectories(gamePath)
|
||||||
|
categoryNames.forEach((categoryName) => {
|
||||||
|
const categoryPath = path.join(gamePath, categoryName)
|
||||||
|
const songsDir = findSubdirCaseInsensitive(categoryPath, 'Songs')
|
||||||
|
const answersDir = findSubdirCaseInsensitive(categoryPath, 'Answers')
|
||||||
|
const clues: Clue[] = []
|
||||||
|
for (let i = 1; i <= 5; i += 1) {
|
||||||
|
const songFile = songsDir ? findFileCaseInsensitive(songsDir, `${i}.mp3`) : null
|
||||||
|
const answerFile = answersDir ? findFileCaseInsensitive(answersDir, `${i}.mp3`) : null
|
||||||
|
const songRelPath = songFile
|
||||||
|
? `/${path.relative(publicRoot, songFile).replace(/\\/g, '/')}`
|
||||||
|
: null
|
||||||
|
const answerRelPath = answerFile
|
||||||
|
? `/${path.relative(publicRoot, answerFile).replace(/\\/g, '/')}`
|
||||||
|
: null
|
||||||
|
clues.push({
|
||||||
|
number: i,
|
||||||
|
points: i * 100,
|
||||||
|
song: songRelPath,
|
||||||
|
answer: answerRelPath
|
||||||
|
})
|
||||||
|
}
|
||||||
|
categories.push({
|
||||||
|
name: categoryName,
|
||||||
|
clues
|
||||||
|
})
|
||||||
|
})
|
||||||
|
games.push({
|
||||||
|
name: gameName,
|
||||||
|
categories
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return games
|
||||||
|
}
|
||||||
|
|
||||||
|
const main = () => {
|
||||||
|
if (!isDirectory(dataRoot)) {
|
||||||
|
fs.writeFileSync(outputPath, JSON.stringify([], null, 2))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const manifest = buildManifest()
|
||||||
|
fs.writeFileSync(outputPath, JSON.stringify(manifest, null, 2))
|
||||||
|
}
|
||||||
|
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user