This commit is contained in:
Jörg Lohrer 2025-10-01 16:27:33 +02:00
parent 59e8ab2d72
commit 3208344018

186
test-batch.js Normal file
View file

@ -0,0 +1,186 @@
/**
* Batch-Test: Analysiert mehrere Posts aus dem Repository
* und zeigt Statistiken über die Metadaten-Qualität
*/
import { createForgejoClient, parseMarkdownString, validateAMBMetadata } from './src/index.js'
const colors = {
reset: '\x1b[0m',
bright: '\x1b[1m',
green: '\x1b[32m',
yellow: '\x1b[33m',
red: '\x1b[31m',
blue: '\x1b[34m',
cyan: '\x1b[36m'
}
function print(text, color = 'reset') {
console.log(`${colors[color]}${text}${colors.reset}`)
}
async function testMultiplePosts() {
print('\n🔍 BATCH-TEST: Mehrere Posts analysieren\n', 'bright')
const client = createForgejoClient()
// Alle Posts abrufen
print('📡 Rufe alle Posts ab...', 'cyan')
const allPosts = await client.listPosts()
print(`${allPosts.length} Posts gefunden\n`, 'green')
// Alle Posts testen
const postsToTest = allPosts
const results = []
const stats = {
total: 0,
withLicense: 0,
withCreator: 0,
withOrcid: 0,
withRor: 0,
withAbout: 0,
withLearningResourceType: 0,
withEducationalLevel: 0,
valid: 0,
avgContentLength: 0,
errors: []
}
print('🔬 Analysiere Posts...\n', 'cyan')
for (let i = 0; i < postsToTest.length; i++) {
const post = postsToTest[i]
const num = `[${i + 1}/${postsToTest.length}]`
try {
const markdown = await client.getPostContent(post.name)
const result = await parseMarkdownString(markdown)
stats.total++
stats.avgContentLength += result.content.length
const meta = result.metadata
const validation = validateAMBMetadata(meta)
// Statistiken sammeln
if (meta.license) stats.withLicense++
if (meta.creator && meta.creator.length > 0) {
stats.withCreator++
if (meta.creator.some(c => c.id && c.id.includes('orcid'))) stats.withOrcid++
if (meta.creator.some(c => c.affiliation?.id && c.affiliation.id.includes('ror'))) stats.withRor++
}
if (meta.about && meta.about.length > 0) stats.withAbout++
if (meta.learningResourceType && meta.learningResourceType.length > 0) stats.withLearningResourceType++
if (meta.educationalLevel && meta.educationalLevel.length > 0) stats.withEducationalLevel++
if (validation.valid) stats.valid++
// Detaillierte Ausgabe
const status = validation.valid ? '✅' : '⚠️'
console.log(`${status} ${num} ${post.name}`)
console.log(` Titel: ${meta.name || 'N/A'}`)
console.log(` Lizenz: ${meta.license ? '✅' : '❌'}`)
console.log(` Creator: ${meta.creator?.length || 0} (ORCID: ${meta.creator?.some(c => c.id?.includes('orcid')) ? '✅' : '❌'})`)
console.log(` About: ${meta.about?.length || 0} Themen`)
console.log(` LearningResourceType: ${meta.learningResourceType?.length || 0}`)
console.log(` Content: ${result.content.length} Zeichen`)
console.log(` Validierung: ${validation.valid ? 'GÜLTIG' : `${validation.errors.length} Fehler`}`)
if (validation.errors.length > 0) {
console.log(` Fehler: ${validation.errors.join(', ')}`)
}
console.log()
results.push({
name: post.name,
metadata: meta,
validation,
contentLength: result.content.length
})
} catch (error) {
print(`${num} ${post.name}`, 'red')
print(` Fehler: ${error.message}`, 'red')
console.log()
stats.errors.push({ post: post.name, error: error.message })
}
}
// Zusammenfassung
print('\n' + '='.repeat(70), 'bright')
print('📊 ZUSAMMENFASSUNG', 'bright')
print('='.repeat(70) + '\n', 'bright')
console.log('📈 Statistiken:')
console.log(` Analysiert: ${stats.total} Posts`)
console.log(` Gültig (AMB): ${stats.valid} / ${stats.total} (${Math.round(stats.valid/stats.total*100)}%)`)
console.log()
console.log('📋 Metadaten-Vollständigkeit:')
console.log(` Lizenz: ${stats.withLicense} / ${stats.total} (${Math.round(stats.withLicense/stats.total*100)}%)`)
console.log(` Creator: ${stats.withCreator} / ${stats.total} (${Math.round(stats.withCreator/stats.total*100)}%)`)
console.log(` └─ mit ORCID: ${stats.withOrcid} / ${stats.withCreator} (${stats.withCreator ? Math.round(stats.withOrcid/stats.withCreator*100) : 0}%)`)
console.log(` └─ mit ROR: ${stats.withRor} / ${stats.withCreator} (${stats.withCreator ? Math.round(stats.withRor/stats.withCreator*100) : 0}%)`)
console.log(` About (Themen): ${stats.withAbout} / ${stats.total} (${Math.round(stats.withAbout/stats.total*100)}%)`)
console.log(` LearningResourceType: ${stats.withLearningResourceType} / ${stats.total} (${Math.round(stats.withLearningResourceType/stats.total*100)}%)`)
console.log(` EducationalLevel: ${stats.withEducationalLevel} / ${stats.total} (${Math.round(stats.withEducationalLevel/stats.total*100)}%)`)
console.log()
console.log('📝 Content:')
console.log(` Durchschnittliche Länge: ${Math.round(stats.avgContentLength / stats.total)} Zeichen`)
console.log(` Kürzester: ${Math.min(...results.map(r => r.contentLength))} Zeichen`)
console.log(` Längster: ${Math.max(...results.map(r => r.contentLength))} Zeichen`)
console.log()
if (stats.errors.length > 0) {
print(`❌ Fehler: ${stats.errors.length}`, 'red')
stats.errors.forEach(err => {
console.log(` - ${err.post}: ${err.error}`)
})
console.log()
}
// Top 5 Posts mit vollständigsten Metadaten
print('🏆 TOP 5 Posts mit vollständigsten Metadaten:', 'cyan')
const scored = results.map(r => {
let score = 0
if (r.metadata.license) score++
if (r.metadata.creator?.length > 0) score++
if (r.metadata.creator?.some(c => c.id)) score++
if (r.metadata.about?.length > 0) score++
if (r.metadata.learningResourceType?.length > 0) score++
if (r.metadata.educationalLevel?.length > 0) score++
if (r.validation.valid) score++
return { ...r, score }
})
scored.sort((a, b) => b.score - a.score)
scored.slice(0, 5).forEach((r, i) => {
console.log(` ${i + 1}. ${r.name}`)
console.log(` Score: ${r.score}/7`)
console.log(` Titel: ${r.metadata.name}`)
})
console.log()
// Posts mit fehlenden Pflichtfeldern
const incomplete = results.filter(r => !r.validation.valid)
if (incomplete.length > 0) {
print(`⚠️ ${incomplete.length} Posts mit fehlenden Pflichtfeldern:`, 'yellow')
incomplete.forEach(r => {
console.log(` - ${r.name}`)
if (r.validation.errors.length > 0) {
console.log(` Fehlt: ${r.validation.errors.join(', ')}`)
}
})
}
print('\n✅ Batch-Test abgeschlossen!\n', 'green')
}
// Ausführen
testMultiplePosts().catch(error => {
console.error('\n❌ Fehler:', error.message)
console.error(error.stack)
process.exit(1)
})