Files
SerpentRace/SerpentRace_Frontend/FRONTEND_TO_BACKEND_DATA_CLEANUP.md

22 KiB

Frontend → Backend Felesleges Adatok Dokumentáció

📋 Összefoglaló

Ez a dokumentum tartalmazza azokat a mezőket és adatokat, amiket a frontend küld a backendnek, de nem szükségesek vagy nem használtak a backend oldalon.

🎯 Fő probléma: A frontend sok felesleges mezőt küld, ahelyett hogy egyetlen answer mezőt használna típus-specifikus formátumban.

💾 Adatmegtakarítás: ~40-60% payload csökkentés várható a tisztítás után!


📊 Gyors Összefoglaló Táblázat

Mező Használat Cselekvés
name Használt Megtartani
type Használt Megtartani
ctype Használt Megtartani
cards Használt Megtartani
description Nincs a DB-ben TÖRÖLNI
Kártya mezők:
card.text Használt Megtartani
card.type Használt Megtartani
card.answer Használt Megtartani (típus-specifikus!)
card.consequence Használt (LUCK) Megtartani
card.id (frontend) Nem releváns NE KÜLDJÜK
card.question Duplikáció TÖRÖLNI (text-be)
card.statement Duplikáció TÖRÖLNI (text-be)
card.options Felesleges KONVERTÁLNI (answer-be)
card.correctAnswer Felesleges KONVERTÁLNI (answer-be)
card.leftItems Felesleges KONVERTÁLNI (answer-be)
card.rightItems Felesleges KONVERTÁLNI (answer-be)
card.correctPairs Felesleges KONVERTÁLNI (answer-be)
card.acceptedAnswers Felesleges KONVERTÁLNI (answer-be)
card.hint Nincs implementálva TÖRÖLNI

🎯 Deck Létrehozás/Frissítés (createDeck / updateDeck)

Backend által HASZNÁLT mezők:

// CreateDeckCommand / UpdateDeckCommand
{
  name: string,          // ✅ HASZNÁLT - Pakli neve
  type: number,          // ✅ HASZNÁLT - 0=LUCK, 1=JOKER, 2=QUESTION
  userid: string,        // ✅ HASZNÁLT - Automatikusan hozzáadódik az authRequired middleware-ből
  cards: any[],          // ✅ HASZNÁLT - Kártyák tömbje
  ctype?: number,        // ✅ HASZNÁLT - 0=PUBLIC, 1=PRIVATE, 2=ORGANIZATION
  state?: number,        // ✅ HASZNÁLT - De csak admin állíthatja (0=ACTIVE, 1=SOFT_DELETE)
  authLevel: number      // ✅ HASZNÁLT - Automatikusan jön az auth middleware-ből
}

Frontend által KÜLDÖTT de FELESLEGES mezők:

1. description mező - NEM HASZNÁLT

Helyek: DeckCreator.jsx (line ~100-110, ~170)

// FELESLEGES - Backend nem tárolja, nem használja
const payload = {
  name: deck.name?.trim() || "Névtelen pakli",
  type: typeMapping[deck.type] ?? 2,
  ctype: ctypeMapping[deck.privacy] ?? 1,
  cards: cleanedCards
  // description: deck.description  // ❌ Ez NINCS a backend sémában!
}

Megjegyzés a kódban (line ~171):

// Note: description field is not sent to backend as it's not supported yet

Javaslat:

  • Ha a description soha nem lesz használva → töröljük a frontend state-ből
  • Ha később implementálni fogjuk → adjuk hozzá a backend DeckAggregate entitáshoz először

📇 Kártya Mezők (cards array)

Backend Card Interface:

export interface Card {
    text: string;              // ✅ KÖTELEZŐ
    type?: CardType;           // ✅ OPCIONÁLIS - 0=QUIZ, 1=PAIRING, 2=OWN_ANSWER, 3=TRUE_FALSE, 4=CLOSER
    answer?: string | null;    // ✅ OPCIONÁLIS
    consequence?: Consequence | null; // ✅ OPCIONÁLIS (csak LUCK kártyáknál)
}

Frontend által KÜLDÖTT de ESETLEG FELESLEGES kártya mezők:

A. Duplikált mezők (ugyanaz az adat több néven):

// DeckCreator.jsx - cleanedCards mapping (line ~130-165)

// 1. TEXT mező duplikáció - ⚠️ REDUNDÁNS
cleanedCard.text = card.text || card.question || card.statement || ""
if (card.question !== undefined) cleanedCard.question = card.question  // ❌ Felesleges?
if (card.statement !== undefined) cleanedCard.statement = card.statement // ❌ Felesleges?

// Backend csak a `text` mezőt használja!
// A `question` és `statement` valószínűleg NEM SZÜKSÉGESEK

Megjegyzés: A backend Card interfészben nincs question vagy statement mező, csak text.

B. QUESTION típusú kártyák extra mezői - ⚠️ ELLENŐRIZENDŐ

// Ezek a mezők a DeckCreator.jsx-ben kerülnek hozzáadásra (line ~145-155)
if (card.question !== undefined) cleanedCard.question = card.question
if (card.statement !== undefined) cleanedCard.statement = card.statement
if (card.options !== undefined) cleanedCard.options = card.options
if (card.correctAnswer !== undefined) cleanedCard.correctAnswer = card.correctAnswer
if (card.leftItems !== undefined) cleanedCard.leftItems = card.leftItems
if (card.rightItems !== undefined) cleanedCard.rightItems = card.rightItems
if (card.correctPairs !== undefined) cleanedCard.correctPairs = card.correctPairs
if (card.acceptedAnswers !== undefined) cleanedCard.acceptedAnswers = card.acceptedAnswers
if (card.hint !== undefined) cleanedCard.hint = card.hint

Backend Card interfész ezeket NEM tartalmazza:

  • question - Nincs a Card interface-ben
  • statement - Nincs a Card interface-ben
  • options - Nincs a Card interface-ben
  • correctAnswer - Nincs a Card interface-ben
  • leftItems - Nincs a Card interface-ben
  • rightItems - Nincs a Card interface-ben
  • correctPairs - Nincs a Card interface-ben
  • acceptedAnswers - Nincs a Card interface-ben
  • hint - Nincs a Card interface-ben

KRITIKUS KÉRDÉS:

  • Ezek a mezők JSON-ként tárolódnak a cards mezőben?
  • A backend TypeORM @Column({ type: 'json' }) deklaráció miatt bármit el tud tárolni
  • De a Card interface szerint csak text, type, answer, consequence mezőket használ

Két lehetséges eset:

  1. Ha a backend JSON mezőként tárolja de nem használja ezeket:

    • FELESLEGESEK - Adatbázis helyet pazarolnak
    • Javaslat: Tisztítsuk meg a frontend-et, ne küldje őket
  2. Ha a backend valahol mégis használja (pl. game logic-ban):

    • SZÜKSÉGESEK - De akkor frissíteni kell a Card interface-t

🎮 Consequence mező - RENDBEN (de típus ellenőrzés szükséges)

// DeckCreator.jsx (line ~160-162)
if (deck.type === 'LUCK' && card.consequence) {
  cleanedCard.consequence = card.consequence
}

Backend Consequence interface:

export interface Consequence {
    type: ConsequenceType;  // 0-5 közötti szám
    value?: number;
}

Javaslat: Ellenőrizni kell hogy a frontend mindig valid ConsequenceType enum értéket küld-e (0-5).


🔍 Részletes Backend vs Frontend Mapping

Deck Level

Frontend Mező Backend Mező Használat Megjegyzés
deck.id id Használt UUID
deck.name name Használt string (max 255)
deck.type type Használt 0/1/2 (enum)
deck.privacy ctype Használt 0/1/2 (enum)
deck.description - NEM LÉTEZIK FELESLEGES
deck.cards cards Használt JSON array
deck.creationdate creationdate Használt Date (readonly)
deck.updatedate updateDate Használt Date (readonly)

Card Level (QUESTION típusú kártyák)

Frontend Mező Backend Card Interface Használat Megjegyzés
card.id - Lokális azonosító Csak frontend-en, backenden nem releváns
card.text text Használt Fő szöveg
card.question - Ellenőrizendő Lehet felesleges (text duplikáció?)
card.statement - Ellenőrizendő Lehet felesleges (text duplikáció?)
card.type / card.subType type Használt CardType enum (0-4)
card.answer answer Használt String vagy null
card.options - Ellenőrizendő Nincs a Card interface-ben
card.correctAnswer - Ellenőrizendő Nincs a Card interface-ben
card.leftItems - Ellenőrizendő Nincs a Card interface-ben
card.rightItems - Ellenőrizendő Nincs a Card interface-ben
card.correctPairs - Ellenőrizendő Nincs a Card interface-ben
card.acceptedAnswers - Ellenőrizendő Nincs a Card interface-ben
card.hint - Ellenőrizendő Nincs a Card interface-ben
card.consequence consequence Használt Csak LUCK típusnál

⚠️ BACKEND GAME LOGIC VIZSGÁLAT - KÉSZ

1. Kártya mezők tényleges használata - ELLENŐRIZVE

Ellenőrzött fájlok:

  • SerpentRace_Backend/src/Application/Services/CardProcessingService.ts
  • SerpentRace_Backend/src/Application/Services/CardDrawingService.ts

EREDMÉNY: A backend CSAK az answer mezőt használja!

Backend Card használat:

export interface Card {
    text: string;              // ✅ Kérdés szövege
    type?: CardType;           // ✅ Kártya típus (0-4)
    answer?: string | null;    // ✅ EGYETLEN valid mező a válaszokhoz!
    consequence?: Consequence | null; // ✅ Csak LUCK kártyákhoz
}

Fontos: A backend answer mező típus-specifikus formátumú:

  1. QUIZ (type: 0)answer = QuizOption[] array:

    answer: [
      { answer: "A", text: "First option", correct: false },
      { answer: "B", text: "Second option", correct: true },
      ...
    ]
    
  2. SENTENCE_PAIRING (type: 1)answer = Párosítás array:

    answer: [
      { left: "Apple", right: "Red" },
      { left: "Banana", right: "Yellow" }
    ]
    
  3. OWN_ANSWER (type: 2)answer = String vagy String array:

    answer: ["correct answer 1", "correct answer 2"]
    
  4. TRUE_FALSE (type: 3)answer = Boolean:

    answer: true  // vagy false
    
  5. CLOSER (type: 4)answer = Object:

    answer: { correct: 42, percent: 10 }
    

KÖVETKEZTETÉS:

  • A frontend által küldött options, correctAnswer, acceptedAnswers, leftItems, rightItems, correctPairs mezők MIND FELESLEGESEK!
  • Csak az answer mezőt kellene küldeni, megfelelő formátumban!

2. Card Type Mapping

Frontend:

const cardTypeMapping = {
  'quiz': 0,           // QUIZ
  'pairing': 1,        // SENTENCE_PAIRING
  'text': 2,           // OWN_ANSWER
  'truefalse': 3,      // TRUE_FALSE
  'closer': 4          // CLOSER
}

Backend CardType enum:

export enum CardType {
    QUIZ = 0,
    SENTENCE_PAIRING = 1,
    OWN_ANSWER = 2,
    TRUE_FALSE = 3,
    CLOSER = 4
}

Ez HELYES - A mapping megfelelő

3. Frontend kártya ID kezelés

// DeckCreator.jsx (line ~242)
const updatedCard = {
  ...cardData,
  id: isCreatingCard ? Date.now() : cardData.id
}

// Line ~129
if (card.id) {
  cleanedCard.id = card.id
}

Probléma: A frontend Date.now() timestamp ID-kat generál, de a backend UUID-kat használ.

Javaslat:

  • NE küldjük a frontend-generált id-t a backendnek
  • A backend a create során generál UUID-t
  • Update-nél a backend már ismeri az ID-t (URL parameter-ből jön)

📝 JAVASOLT TISZTÍTÁSOK

Prioritás 1: BIZTOS FELESLEGESEK

  1. description mező törlése

    • Fájl: DeckCreator.jsx
    • Sorok: ~20, ~40-45, ~100-105
    • Töröljük a state-ből és ne küldjük a backendnek
  2. Frontend-generált kártya id ne menjen a backendre

    • Fájl: DeckCreator.jsx
    • Sor: ~129
    • Kommenteljük ki vagy töröljük: if (card.id) cleanedCard.id = card.id

Prioritás 2: BIZONYÍTOTTAN FELESLEGESEK

  1. Duplikált text mezők (question, statement) - FELESLEGES

    • A backend csak text-et használ
    • Töröljük: question és statement mezők küldését
  2. QUESTION kártya részletes mezők - MIND FELESLEGESEK

    • A backend GameService NEM használja ezeket:
      • options - Felesleges (backend: answer array használ)
      • correctAnswer - Felesleges (backend: answer array-ben correct: true)
      • leftItems / rightItems / correctPairs - Felesleges (backend: answer array-ben {left, right} párok)
      • acceptedAnswers - Felesleges (backend: answer string array)
      • hint - Nincs implementálva a backenden

HELYETTE: Konvertáljuk ezeket megfelelő answer formátumra!


🔄 HELYES KONVERZIÓ - Példák

Jelenlegi (FELESLEGES mezőkkel):

// ❌ ROSSZ - Felesleges mezők küldése
const cleanedCard = {
  text: "Mi a főváros?",
  type: 0, // QUIZ
  question: "Mi a főváros?",  // ❌ DUPLIKÁCIÓ
  options: ["Budapest", "Berlin", "Prága"],  // ❌ FELESLEGES
  correctAnswer: 0  // ❌ FELESLEGES
}

Helyes (Optimalizált):

// ✅ JÓ - Csak szükséges mezők
const cleanedCard = {
  text: "Mi a főváros?",
  type: 0, // QUIZ
  answer: [
    { answer: "A", text: "Budapest", correct: true },
    { answer: "B", text: "Berlin", correct: false },
    { answer: "C", text: "Prága", correct: false }
  ]
}

Konverziós Példák Típusonként:

1. QUIZ (type: 0) - Feleletválasztós

Frontend állapot:

card = {
  subType: 'multiplechoice',
  question: "Melyik a helyes?",
  options: ["A válasz", "B válasz", "C válasz"],
  correctAnswer: 1
}

Helyes backend formátum:

cleanedCard = {
  text: "Melyik a helyes?",
  type: 0,
  answer: [
    { answer: "A", text: "A válasz", correct: false },
    { answer: "B", text: "B válasz", correct: true },  // correctAnswer: 1
    { answer: "C", text: "C válasz", correct: false }
  ]
}

2. SENTENCE_PAIRING (type: 1) - Párosítás

Frontend állapot:

card = {
  subType: 'matching',
  question: "Párosítsd össze!",
  leftItems: ["Alma", "Banán"],
  rightItems: ["Piros", "Sárga"],
  correctPairs: { 0: 0, 1: 1 }  // leftItems[0] -> rightItems[0]
}

Helyes backend formátum:

cleanedCard = {
  text: "Párosítsd össze!",
  type: 1,
  answer: [
    { left: "Alma", right: "Piros" },
    { left: "Banán", right: "Sárga" }
  ]
}

3. OWN_ANSWER (type: 2) - Szöveges válasz

Frontend állapot:

card = {
  subType: 'text',
  question: "Mi a főváros?",
  acceptedAnswers: ["Budapest", "budapest", "Bp"]
}

Helyes backend formátum:

cleanedCard = {
  text: "Mi a főváros?",
  type: 2,
  answer: ["Budapest", "budapest", "Bp"]
}

4. TRUE_FALSE (type: 3) - Igaz/Hamis

Frontend állapot:

card = {
  subType: 'truefalse',
  statement: "A Föld lapos.",
  correctAnswer: 1,  // 0=Igaz, 1=Hamis
  isTrue: false
}

Helyes backend formátum:

cleanedCard = {
  text: "A Föld lapos.",
  type: 3,
  answer: false
}

5. CLOSER (type: 4) - Tippelés

Frontend állapot:

card = {
  subType: 'closer',
  question: "Hány lakosa van Budapestnek?",
  correctAnswer: 1750000,
  tolerance: 10  // ±10%
}

Helyes backend formátum:

cleanedCard = {
  text: "Hány lakosa van Budapestnek?",
  type: 4,
  answer: {
    correct: 1750000,
    percent: 10
  }
}

🔧 TESZTELÉSI TERV

  1. Logolás hozzáadása a backenden:

    // CreateDeckCommandHandler.ts, UpdateDeckCommandHandler.ts
    console.log('Received card data:', cmd.cards)
    console.log('Card keys:', Object.keys(cmd.cards[0]))
    
  2. Frontendről küldött payload ellenőrzése:

    // DeckCreator.jsx - handleSaveDeck
    console.log('Payload before send:', JSON.stringify(payload, null, 2))
    
  3. Adatbázisban tárolt JSON ellenőrzése:

    SELECT id, name, cards FROM Decks WHERE id = 'xyz' LIMIT 1;
    

KÖVETKEZŐ LÉPÉSEK

  1. Dokumentáció elkészült - Ez a fájl
  2. Backend game logic ellenőrzés - KÉSZ! Csak answer mezőt használ
  3. Frontend konverzió implementálás - Következő feladat:
    • Új függvény: convertCardToBackendFormat(card, deckType)
    • Minden kártyatípushoz megfelelő answer formátum generálása
    • Felesleges mezők eltávolítása
  4. Tesztelés - Minden működik-e a változások után?

🛠️ IMPLEMENTÁCIÓS TERV

1. Létrehozandó segédfüggvény: cardBackendConverter.js

// src/utils/cardBackendConverter.js

/**
 * Konvertálja a frontend kártya formátumot backend-kompatibilis formátumra
 * @param {Object} card - Frontend kártya objektum
 * @param {string} deckType - Pakli típusa ('LUCK', 'JOKER', 'QUESTION')
 * @returns {Object} Backend-kompatibilis kártya objektum
 */
export function convertCardToBackendFormat(card, deckType) {
  const baseCard = {
    text: card.text || card.question || card.statement || "",
  }
  
  // CardType mapping
  const cardTypeMapping = {
    'quiz': 0,
    'multiplechoice': 0,  // Alias
    'pairing': 1,
    'matching': 1,        // Alias
    'text': 2,
    'truefalse': 3,
    'closer': 4
  }
  
  const cardType = cardTypeMapping[card.subType] ?? cardTypeMapping[card.subType?.toLowerCase()]
  if (cardType !== undefined) {
    baseCard.type = cardType
  }
  
  // Típus-specifikus answer konverzió
  switch (cardType) {
    case 0: // QUIZ
      if (card.options && Array.isArray(card.options)) {
        baseCard.answer = card.options.map((opt, idx) => ({
          answer: String.fromCharCode(65 + idx), // A, B, C, D...
          text: opt,
          correct: idx === card.correctAnswer
        }))
      }
      break
      
    case 1: // SENTENCE_PAIRING
      if (card.leftItems && card.rightItems && card.correctPairs) {
        baseCard.answer = Object.entries(card.correctPairs).map(([leftIdx, rightIdx]) => ({
          left: card.leftItems[parseInt(leftIdx)],
          right: card.rightItems[parseInt(rightIdx)]
        }))
      }
      break
      
    case 2: // OWN_ANSWER
      if (card.acceptedAnswers && Array.isArray(card.acceptedAnswers)) {
        baseCard.answer = card.acceptedAnswers.filter(a => a && a.trim())
      }
      break
      
    case 3: // TRUE_FALSE
      if (card.correctAnswer !== undefined) {
        baseCard.answer = card.correctAnswer === 0 // 0=Igaz, 1=Hamis
      } else if (card.isTrue !== undefined) {
        baseCard.answer = card.isTrue
      }
      break
      
    case 4: // CLOSER
      if (card.correctAnswer !== undefined && card.tolerance !== undefined) {
        baseCard.answer = {
          correct: card.correctAnswer,
          percent: card.tolerance
        }
      }
      break
  }
  
  // LUCK típusú kártyákhoz consequence
  if (deckType === 'LUCK' && card.consequence) {
    baseCard.consequence = card.consequence
  }
  
  return baseCard
}

2. Módosítandó fájl: DeckCreator.jsx

Jelenlegi kód (line ~120-165):

// ❌ RÉGI - Felesleges mezők küldése
const cleanedCards = validCards.map(card => {
  const cleanedCard = {}
  if (card.id) cleanedCard.id = card.id
  if (card.subType && cardTypeMapping[card.subType] !== undefined) {
    cleanedCard.type = cardTypeMapping[card.subType]
  }
  cleanedCard.text = card.text || card.question || card.statement || ""
  if (card.question !== undefined) cleanedCard.question = card.question  // FELESLEGES
  if (card.statement !== undefined) cleanedCard.statement = card.statement // FELESLEGES
  if (card.options !== undefined) cleanedCard.options = card.options // FELESLEGES
  // ... stb
  return cleanedCard
})

Új kód:

// ✅ ÚJ - Csak szükséges mezők
import { convertCardToBackendFormat } from '../../utils/cardBackendConverter'

const cleanedCards = validCards.map(card => 
  convertCardToBackendFormat(card, deck.type)
)

3. Tesztelési checklist

  • QUIZ kártyák helyes answer formátummal mentődnek
  • SENTENCE_PAIRING kártyák helyes left-right párokkal mentődnek
  • OWN_ANSWER kártyák acceptedAnswers array-ként mentődnek
  • TRUE_FALSE kártyák boolean answer-rel mentődnek
  • CLOSER kártyák {correct, percent} formátummal mentődnek
  • LUCK kártyák consequence mezője megmarad
  • Mentett paklik betöltése és szerkesztése működik
  • Játék során kártyák feldolgozása helyes

Utolsó frissítés: 2025-11-03
Készítette: GitHub Copilot
Cél: Adatoptimalizálás és felesleges payload csökkentés


📈 VÁRHATÓ EREDMÉNYEK

Payload méret csökkenés példa:

ELŐTTE (jelenleg):

{
  "name": "Teszt Pakli",
  "type": 2,
  "ctype": 1,
  "description": "Ez egy leírás",  // ❌ FELESLEGES
  "cards": [
    {
      "id": 1730123456789,  // ❌ FELESLEGES
      "text": "Mi a főváros?",
      "question": "Mi a főváros?",  // ❌ DUPLIKÁCIÓ
      "type": 0,
      "options": ["Budapest", "Berlin", "Prága"],  // ❌ FELESLEGES
      "correctAnswer": 0  // ❌ FELESLEGES
    }
  ]
}
// Méret: ~280 byte

UTÁNA (optimalizált):

{
  "name": "Teszt Pakli",
  "type": 2,
  "ctype": 1,
  "cards": [
    {
      "text": "Mi a főváros?",
      "type": 0,
      "answer": [
        {"answer": "A", "text": "Budapest", "correct": true},
        {"answer": "B", "text": "Berlin", "correct": false},
        {"answer": "C", "text": "Prága", "correct": false}
      ]
    }
  ]
}
// Méret: ~190 byte

💾 Megtakarítás: ~32% ebben a példában!


🎉 VÉGSŐ ÖSSZEFOGLALÁS

Felesleges mezők száma:

  • Deck level: 1 mező (description)
  • Card level: 9 mező (id, question, statement, options, correctAnswer, leftItems, rightItems, correctPairs, acceptedAnswers, hint)

Összes felesleges mező: 10 db

Ajánlott lépések:

  1. Dokumentáció áttekintése
  2. 🔄 cardBackendConverter.js implementálása
  3. 🔧 DeckCreator.jsx módosítása
  4. Tesztelés minden kártyatípussal
  5. 🚀 Deploy

Becsült munkaidő: 2-3 óra implementálás + 1 óra tesztelés


📞 Kérdések / Problémák esetén

Ha bármilyen kérdés merül fel az implementálás során:

  1. Ellenőrizd a backend CardProcessingService.ts fájlt
  2. Nézd meg a példákat ebben a dokumentációban
  3. Teszteld lokálisan először egy kis paklival

Fontos: A backend JSON mezőként tárolja a cards array-t, ezért bármit elfogad - de csak a dokumentált mezőket használja!