...
This commit is contained in:
@@ -0,0 +1,275 @@
|
||||
// packages/feature_game_mathquiz/lib/models/math_quiz_difficulty.dart
|
||||
import 'package:service_api/service_api.dart';
|
||||
|
||||
/// 빈칸의 유형을 정의
|
||||
enum MathQuizBlankType {
|
||||
numbersOnly, // 숫자만
|
||||
operatorsOnly, // 연산자만
|
||||
numbersAndOperators, // 둘 다
|
||||
}
|
||||
|
||||
/// 퍼즐의 레이아웃 형태를 정의
|
||||
enum MathQuizLayout {
|
||||
singleLine,
|
||||
dualLine,
|
||||
linkedL,
|
||||
gridSquare,
|
||||
}
|
||||
|
||||
/// 'extends GameDifficulty' 추가
|
||||
class MathQuizDifficulty extends GameDifficulty {
|
||||
final int levelIndex;
|
||||
final MathQuizLayout layout;
|
||||
final String operators;
|
||||
final int blankCount;
|
||||
final MathQuizBlankType blankType;
|
||||
final int operationCount;
|
||||
final int puzzleCount;
|
||||
|
||||
const MathQuizDifficulty({
|
||||
required this.levelIndex,
|
||||
required super.name,
|
||||
required super.contextId,
|
||||
required this.layout,
|
||||
required this.operators,
|
||||
required this.blankCount,
|
||||
required this.blankType,
|
||||
required this.operationCount,
|
||||
required this.puzzleCount,
|
||||
});
|
||||
}
|
||||
|
||||
/// 앱 전역에서 사용할 수학 퀴즈 난이도 목록 (19단계)
|
||||
class MathQuizDifficulties {
|
||||
static final List<MathQuizDifficulty> allDifficulties = [
|
||||
// --- 패턴 1: 숫자 2개 (A op B = C) [Lv 1-3] ---
|
||||
const MathQuizDifficulty(
|
||||
levelIndex: 1,
|
||||
name: 'Lv. 1: 숫자 2개 (숫자 빈칸)',
|
||||
contextId: 'MATH_L1_OP2_NUM',
|
||||
layout: MathQuizLayout.singleLine,
|
||||
operators: '+,-',
|
||||
blankCount: 1,
|
||||
blankType: MathQuizBlankType.numbersOnly,
|
||||
operationCount: 2,
|
||||
puzzleCount: 10,
|
||||
),
|
||||
const MathQuizDifficulty(
|
||||
levelIndex: 2,
|
||||
name: 'Lv. 2: 숫자 2개 (연산자 빈칸)',
|
||||
contextId: 'MATH_L2_OP2_OP',
|
||||
layout: MathQuizLayout.singleLine,
|
||||
operators: '+,-',
|
||||
blankCount: 1,
|
||||
blankType: MathQuizBlankType.operatorsOnly,
|
||||
operationCount: 2,
|
||||
puzzleCount: 10,
|
||||
),
|
||||
const MathQuizDifficulty(
|
||||
levelIndex: 3,
|
||||
name: 'Lv. 3: 숫자 2개 (사칙연산)',
|
||||
contextId: 'MATH_L3_OP2_ANY',
|
||||
layout: MathQuizLayout.singleLine,
|
||||
operators: '+,-,*,/',
|
||||
blankCount: 2,
|
||||
blankType: MathQuizBlankType.numbersAndOperators,
|
||||
operationCount: 2,
|
||||
puzzleCount: 10,
|
||||
),
|
||||
// --- 패턴 2: 숫자 3개 (A op1 B op2 C = D) [Lv 4-6] ---
|
||||
const MathQuizDifficulty(
|
||||
levelIndex: 4,
|
||||
name: 'Lv. 4: 숫자 3개 (숫자 빈칸)',
|
||||
contextId: 'MATH_L4_OP3_NUM',
|
||||
layout: MathQuizLayout.singleLine,
|
||||
operators: '+,-,*,/',
|
||||
blankCount: 2,
|
||||
blankType: MathQuizBlankType.numbersOnly,
|
||||
operationCount: 3,
|
||||
puzzleCount: 8,
|
||||
),
|
||||
const MathQuizDifficulty(
|
||||
levelIndex: 5,
|
||||
name: 'Lv. 5: 숫자 3개 (연산자 빈칸)',
|
||||
contextId: 'MATH_L5_OP3_OP',
|
||||
layout: MathQuizLayout.singleLine,
|
||||
operators: '+,-,*,/',
|
||||
blankCount: 2,
|
||||
blankType: MathQuizBlankType.operatorsOnly,
|
||||
operationCount: 3,
|
||||
puzzleCount: 8,
|
||||
),
|
||||
const MathQuizDifficulty(
|
||||
levelIndex: 6,
|
||||
name: 'Lv. 6: 숫자 3개 (랜덤 빈칸)',
|
||||
contextId: 'MATH_L6_OP3_ANY',
|
||||
layout: MathQuizLayout.singleLine,
|
||||
operators: '+,-,*,/',
|
||||
blankCount: 3,
|
||||
blankType: MathQuizBlankType.numbersAndOperators,
|
||||
operationCount: 3,
|
||||
puzzleCount: 8,
|
||||
),
|
||||
// --- 패턴 3: 독립된 2줄 (숫자 4개) [Lv 7-9] ---
|
||||
const MathQuizDifficulty(
|
||||
levelIndex: 7,
|
||||
name: 'Lv. 7: 독립 2줄 (숫자)',
|
||||
contextId: 'MATH_L7_OP4_DUAL_NUM',
|
||||
layout: MathQuizLayout.dualLine,
|
||||
operators: '+,-',
|
||||
blankCount: 2,
|
||||
blankType: MathQuizBlankType.numbersOnly,
|
||||
operationCount: 4,
|
||||
puzzleCount: 6,
|
||||
),
|
||||
const MathQuizDifficulty(
|
||||
levelIndex: 8,
|
||||
name: 'Lv. 8: 독립 2줄 (연산자)',
|
||||
contextId: 'MATH_L8_OP4_DUAL_OP',
|
||||
layout: MathQuizLayout.dualLine,
|
||||
operators: '+,-',
|
||||
blankCount: 2,
|
||||
blankType: MathQuizBlankType.operatorsOnly,
|
||||
operationCount: 4,
|
||||
puzzleCount: 6,
|
||||
),
|
||||
const MathQuizDifficulty(
|
||||
levelIndex: 9,
|
||||
name: 'Lv. 9: 독립 2줄 (사칙연산)',
|
||||
contextId: 'MATH_L9_OP4_DUAL_ANY',
|
||||
layout: MathQuizLayout.dualLine,
|
||||
operators: '+,-,*,/',
|
||||
blankCount: 3,
|
||||
blankType: MathQuizBlankType.numbersAndOperators,
|
||||
operationCount: 4,
|
||||
puzzleCount: 6,
|
||||
),
|
||||
// --- 패턴 4: 2x2 그리드 (숫자 4개) [Lv 10-12] ---
|
||||
const MathQuizDifficulty(
|
||||
levelIndex: 10,
|
||||
name: 'Lv. 10: 2x2 그리드 (숫자)',
|
||||
contextId: 'MATH_L10_OP4_L_NUM',
|
||||
layout: MathQuizLayout.linkedL,
|
||||
operators: '+,-',
|
||||
blankCount: 2,
|
||||
blankType: MathQuizBlankType.numbersOnly,
|
||||
operationCount: 4,
|
||||
puzzleCount: 4,
|
||||
),
|
||||
const MathQuizDifficulty(
|
||||
levelIndex: 11,
|
||||
name: 'Lv. 11: 2x2 그리드 (연산자)',
|
||||
contextId: 'MATH_L11_OP4_L_OP',
|
||||
layout: MathQuizLayout.linkedL,
|
||||
operators: '+,-',
|
||||
blankCount: 2,
|
||||
blankType: MathQuizBlankType.operatorsOnly,
|
||||
operationCount: 4,
|
||||
puzzleCount: 4,
|
||||
),
|
||||
const MathQuizDifficulty(
|
||||
levelIndex: 12,
|
||||
name: 'Lv. 12: 2x2 그리드 (사칙연산)',
|
||||
contextId: 'MATH_L12_OP4_L_ANY',
|
||||
layout: MathQuizLayout.linkedL,
|
||||
operators: '+,-,*,/',
|
||||
blankCount: 3,
|
||||
blankType: MathQuizBlankType.numbersAndOperators,
|
||||
operationCount: 4,
|
||||
puzzleCount: 4,
|
||||
),
|
||||
// --- 패턴 5: 3x3 그리드 (숫자 9개) [Lv 13-15] ---
|
||||
const MathQuizDifficulty(
|
||||
levelIndex: 13,
|
||||
name: 'Lv. 13: 3x3 그리드 (숫자)',
|
||||
contextId: 'MATH_L13_OP9_NUM',
|
||||
layout: MathQuizLayout.gridSquare,
|
||||
operators: '+,-',
|
||||
blankCount: 3,
|
||||
blankType: MathQuizBlankType.numbersOnly,
|
||||
operationCount: 9,
|
||||
puzzleCount: 3,
|
||||
),
|
||||
const MathQuizDifficulty(
|
||||
levelIndex: 14,
|
||||
name: 'Lv. 14: 3x3 그리드 (연산자)',
|
||||
contextId: 'MATH_L14_OP9_OP',
|
||||
layout: MathQuizLayout.gridSquare,
|
||||
operators: '+,-',
|
||||
blankCount: 3,
|
||||
blankType: MathQuizBlankType.operatorsOnly,
|
||||
operationCount: 9,
|
||||
puzzleCount: 3,
|
||||
),
|
||||
const MathQuizDifficulty(
|
||||
levelIndex: 15,
|
||||
name: 'Lv. 15: 3x3 그리드 (사칙연산)',
|
||||
contextId: 'MATH_L15_OP9_ANY',
|
||||
layout: MathQuizLayout.gridSquare,
|
||||
operators: '+,-,*,/',
|
||||
blankCount: 4,
|
||||
blankType: MathQuizBlankType.numbersAndOperators,
|
||||
operationCount: 9,
|
||||
puzzleCount: 3,
|
||||
),
|
||||
// --- 패턴 6: 4x4 그리드 (숫자 16개) [Lv 16-18] ---
|
||||
const MathQuizDifficulty(
|
||||
levelIndex: 16,
|
||||
name: 'Lv. 16: 4x4 그리드 (숫자)',
|
||||
contextId: 'MATH_L16_OP16_NUM',
|
||||
layout: MathQuizLayout.gridSquare,
|
||||
operators: '+,-,*,/',
|
||||
blankCount: 5,
|
||||
blankType: MathQuizBlankType.numbersOnly,
|
||||
operationCount: 16,
|
||||
puzzleCount: 2,
|
||||
),
|
||||
const MathQuizDifficulty(
|
||||
levelIndex: 17,
|
||||
name: 'Lv. 17: 4x4 그리드 (연산자)',
|
||||
contextId: 'MATH_L17_OP16_OP',
|
||||
layout: MathQuizLayout.gridSquare,
|
||||
operators: '+,-,*,/',
|
||||
blankCount: 5,
|
||||
blankType: MathQuizBlankType.operatorsOnly,
|
||||
operationCount: 16,
|
||||
puzzleCount: 2,
|
||||
),
|
||||
const MathQuizDifficulty(
|
||||
levelIndex: 18,
|
||||
name: 'Lv. 18: 4x4 그리드 (랜덤)',
|
||||
contextId: 'MATH_L18_OP16_ANY',
|
||||
layout: MathQuizLayout.gridSquare,
|
||||
operators: '+,-,*,/',
|
||||
blankCount: 6,
|
||||
blankType: MathQuizBlankType.numbersAndOperators,
|
||||
operationCount: 16,
|
||||
puzzleCount: 2,
|
||||
),
|
||||
// --- [신규] 패턴 7: 4x4 그리드 (고난도) [Lv 19] ---
|
||||
const MathQuizDifficulty(
|
||||
levelIndex: 19,
|
||||
name: 'Lv. 19: 4x4 그리드 (최상)',
|
||||
contextId: 'MATH_L19_OP16_HARD',
|
||||
layout: MathQuizLayout.gridSquare,
|
||||
operators: '+,-,*,/',
|
||||
blankCount: 8,
|
||||
blankType: MathQuizBlankType.numbersAndOperators,
|
||||
operationCount: 16,
|
||||
puzzleCount: 1,
|
||||
),
|
||||
];
|
||||
|
||||
/// 레벨 인덱스로 레벨 정보 찾기
|
||||
static MathQuizDifficulty getLevel(int levelIndex) {
|
||||
if (levelIndex < 1) levelIndex = 1;
|
||||
if (levelIndex > allDifficulties.length) levelIndex = allDifficulties.length;
|
||||
return allDifficulties.firstWhere((level) => level.levelIndex == levelIndex,
|
||||
orElse: () => allDifficulties[0]);
|
||||
}
|
||||
|
||||
/// 랭킹 화면용 맵 (ContextId -> 이름)
|
||||
static Map<String, String> get contextIdToNameMap {
|
||||
return {for (var level in allDifficulties) level.contextId: level.name};
|
||||
}
|
||||
}
|
||||
@@ -1,29 +1,36 @@
|
||||
// packages/feature_game_mathquiz/lib/models/math_quiz_models.dart
|
||||
|
||||
/// 개별 빈칸의 타입을 정의
|
||||
enum PuzzleBlankType { number, operator }
|
||||
|
||||
/// 검증해야 할 단일 방정식을 정의
|
||||
class MathQuizEquation {
|
||||
final List<int> expressionIndices;
|
||||
final int resultIndex;
|
||||
|
||||
MathQuizEquation({
|
||||
required this.expressionIndices,
|
||||
required this.resultIndex,
|
||||
});
|
||||
}
|
||||
|
||||
/// 퍼즐 한 판의 데이터 구조
|
||||
class MathQuizPuzzle {
|
||||
/// [수정] 그리드 셀 데이터
|
||||
///
|
||||
/// '?'는 빈칸, ' '는 공백(빈 셀)입니다.
|
||||
///
|
||||
/// 예: ["?", "+", "3", "=", "8"] (5x1 그리드)
|
||||
/// 예: ["?", "+", "2", "=", "5", "+", " ", "+", ... ] (5x5 그리드)
|
||||
final List<String> gridCells;
|
||||
|
||||
/// 그리드의 가로 칸 수 (예: 5)
|
||||
final int gridCrossAxisCount;
|
||||
|
||||
/// 유저가 채워야 할 정답 목록 (순서대로)
|
||||
final List<String> solutions;
|
||||
|
||||
/// 유저에게 제공될 숫자/기호 버튼 옵션
|
||||
final List<String> options;
|
||||
final List<MathQuizEquation> equations;
|
||||
final List<String> solutions;
|
||||
|
||||
/// 빈칸의 타입 목록 (solutions와 1:1 매칭)
|
||||
final List<PuzzleBlankType> blankTypes;
|
||||
|
||||
MathQuizPuzzle({
|
||||
// ❌ puzzleType 삭제
|
||||
required this.gridCells,
|
||||
required this.gridCrossAxisCount,
|
||||
required this.solutions,
|
||||
required this.options,
|
||||
required this.equations,
|
||||
required this.solutions,
|
||||
required this.blankTypes, // 👈 [추가]
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user