2025-11-21 15:54:17 +09:00
// packages/feature_game_finddiff/lib/models/finddiff_models.dart
2025-11-19 18:00:41 +09:00
import ' package:flutter/material.dart ' ;
import ' package:service_api/service_api.dart ' ;
2025-11-21 15:54:17 +09:00
/// 문제 유형
2025-11-19 18:00:41 +09:00
enum FindDiffType {
2025-11-21 15:54:17 +09:00
color , // 색상이 다름
icon , // 모양이 다름
rotate , // 각도가 다름
category , // 범주가 다름
word , // 글자가 다름
mix , // 무작위
2025-11-19 18:00:41 +09:00
}
/// 개별 아이템 데이터
class FindDiffItem {
final int id ;
2025-11-21 15:54:17 +09:00
final IconData ? icon ;
final String ? textContent ;
2025-11-19 18:00:41 +09:00
final Color color ;
2025-11-21 15:54:17 +09:00
final double angle ;
final bool isTarget ;
2025-11-19 18:00:41 +09:00
FindDiffItem ( {
required this . id ,
2025-11-21 15:54:17 +09:00
this . icon ,
this . textContent ,
2025-11-19 18:00:41 +09:00
required this . color ,
this . angle = 0.0 ,
this . isTarget = false ,
} ) ;
}
class FindDiffDifficulty extends GameDifficulty {
final int levelIndex ;
2025-11-21 15:54:17 +09:00
final int rows ;
final int cols ;
final int timeLimitSeconds ;
final FindDiffType diffType ;
2025-11-19 18:00:41 +09:00
const FindDiffDifficulty ( {
required this . levelIndex ,
required super . name ,
required super . contextId ,
required this . rows ,
required this . cols ,
required this . timeLimitSeconds ,
required this . diffType ,
} ) ;
int get totalItems = > rows * cols ;
}
class FindDiffDifficulties {
2025-11-21 15:54:17 +09:00
// --- [🔥 확장] 모양 찾기용 아이콘 쌍 (20쌍) ---
2025-11-19 18:00:41 +09:00
static const List < List < IconData > > iconPairs = [
[ Icons . sentiment_satisfied_alt , Icons . sentiment_satisfied ] , // 웃음 vs 미소
[ Icons . star , Icons . star_border ] , // 별 vs 빈별
[ Icons . check_circle , Icons . check_circle_outline ] , // 체크 vs 빈체크
[ Icons . favorite , Icons . favorite_border ] , // 하트 vs 빈하트
[ Icons . lock , Icons . lock_open ] , // 잠금 vs 열림
[ Icons . brightness_5 , Icons . brightness_4 ] , // 해 vs 달
2025-11-21 15:54:17 +09:00
[ Icons . mic , Icons . mic_off ] , // 마이크 vs 꺼짐
[ Icons . videocam , Icons . videocam_off ] , // 캠 vs 꺼짐
[ Icons . notifications , Icons . notifications_off ] , // 알림 vs 꺼짐
[ Icons . wifi , Icons . wifi_off ] , // 와이파이 vs 꺼짐
// 추가된 쌍
[ Icons . volume_up , Icons . volume_off ] , // 소리 vs 무음
[ Icons . visibility , Icons . visibility_off ] , // 보임 vs 안보임
[ Icons . thumb_up , Icons . thumb_down ] , // 따봉 vs 역따봉
[ Icons . battery_full , Icons . battery_alert ] , // 배터리 vs 경고
[ Icons . signal_cellular_4_bar , Icons . signal_cellular_off ] , // 신호 vs 꺼짐
[ Icons . folder , Icons . folder_open ] , // 폴더 vs 열림
[ Icons . email , Icons . drafts ] , // 메일 vs 편지
[ Icons . cloud , Icons . cloud_queue ] , // 구름 vs 윤곽선
[ Icons . location_on , Icons . location_off ] , // 위치 vs 꺼짐
[ Icons . bookmark , Icons . bookmark_border ] , // 북마크 vs 빈북마크
] ;
// --- [🔥 신규] 회전 찾기용 아이콘 (방향성이 명확한 것들만) ---
static const List < IconData > rotateIcons = [
Icons . flight , Icons . navigation , Icons . send , Icons . north , Icons . cut ,
Icons . vpn_key , Icons . gavel , Icons . umbrella , Icons . music_note , Icons . flash_on ,
Icons . thumb_up , Icons . pan_tool , Icons . pets , Icons . star , Icons . favorite ,
Icons . play_arrow , Icons . call , Icons . build , Icons . brush , Icons . edit ,
Icons . search , Icons . flag , Icons . push_pin , Icons . local_dining , Icons . local_taxi
2025-11-19 18:00:41 +09:00
] ;
2025-11-21 15:54:17 +09:00
// --- 색상 찾기용 아이콘 (단순한 모양) ---
static const List < IconData > colorIcons = [
2025-11-19 18:00:41 +09:00
Icons . circle , Icons . square , Icons . star , Icons . favorite , Icons . change_history ,
Icons . hexagon , Icons . pentagon , Icons . emoji_emotions , Icons . pets , Icons . flight ,
2025-11-21 15:54:17 +09:00
Icons . cloud , Icons . local_fire_department , Icons . water_drop , Icons . grass , Icons . sunny
2025-11-19 18:00:41 +09:00
] ;
2025-11-21 15:54:17 +09:00
// --- [🔥 확장] 카테고리별 이모지 풀 (6개 카테고리) ---
static const Map < String , List < String > > emojiCategories = {
' animal ' : [ " 🐶 " , " 🐱 " , " 🐭 " , " 🐹 " , " 🐰 " , " 🦊 " , " 🐻 " , " 🐼 " , " 🐯 " , " 🦁 " , " 🐮 " , " 🐷 " , " 🐸 " , " 🐔 " , " 🐧 " , " 🐦 " , " 🐤 " , " 🦆 " , " 🦅 " , " 🦉 " ] ,
' food ' : [ " 🍎 " , " 🍌 " , " 🍇 " , " 🍓 " , " 🍊 " , " 🍋 " , " 🍉 " , " 🍔 " , " 🍕 " , " 🌭 " , " 🍿 " , " 🍩 " , " 🍪 " , " 🍰 " , " 🍫 " , " 🍬 " , " 🍭 " , " 🍮 " , " 🍯 " , " 🥐 " ] ,
' vehicle ' : [ " 🚗 " , " 🚕 " , " 🚙 " , " 🚌 " , " 🚎 " , " 🏎️ " , " 🚓 " , " 🚑 " , " 🚒 " , " ✈️ " , " 🚀 " , " 🚁 " , " 🚂 " , " 🚆 " , " 🚲 " , " 🛵 " , " 🏍️ " , " ⛵ " , " 🚤 " , " 🛳️ " ] ,
' face ' : [ " 😀 " , " 😃 " , " 😄 " , " 😁 " , " 😆 " , " 😅 " , " 🤣 " , " 😂 " , " 🙂 " , " 🙃 " , " 😉 " , " 😊 " , " 😇 " , " 🥰 " , " 😍 " , " 🤩 " , " 😘 " , " 😗 " , " 😚 " , " 😙 " ] ,
' plant ' : [ " 🌵 " , " 🎄 " , " 🌲 " , " 🌳 " , " 🌴 " , " 🌱 " , " 🌿 " , " ☘️ " , " 🍀 " , " 🎍 " , " 🎋 " , " 🍃 " , " 🍂 " , " 🍁 " , " 🍄 " , " 🌾 " , " 💐 " , " 🌷 " , " 🌹 " , " 🥀 " ] ,
' sports ' : [ " ⚽ " , " 🏀 " , " 🏈 " , " ⚾ " , " 🥎 " , " 🎾 " , " 🏐 " , " 🏉 " , " 🎱 " , " 🏓 " , " 🏸 " , " 🥅 " , " 🥊 " , " 🥋 " , " 🥇 " , " 🥈 " , " 🥉 " , " 🏅 " , " 🎖 " , " 🏆 " ] ,
} ;
2025-11-19 18:00:41 +09:00
2025-11-21 15:54:17 +09:00
// --- 유사 단어 풀 (오타 찾기용) - 기존 100개 단어 사용 (이전 코드 유지)
// (HangulUtils를 사용하므로 baseWords 리스트만 있으면 됩니다. 여기서는 생략하지 않고 포함합니다)
static const List < String > baseWords = [
" 강아지 " , " 고양이 " , " 코끼리 " , " 원숭이 " , " 호랑이 " , " 사자 " , " 기린 " , " 토끼 " , " 다람쥐 " , " 거북이 " ,
" 독수리 " , " 갈매기 " , " 비둘기 " , " 참새 " , " 까치 " , " 펭귄 " , " 돌고래 " , " 고래 " , " 상어 " , " 문어 " ,
" 선풍기 " , " 냉장고 " , " 세탁기 " , " 청소기 " , " 텔레비전 " , " 컴퓨터 " , " 노트북 " , " 스마트폰 " , " 카메라 " , " 시계 " ,
" 자동차 " , " 자전거 " , " 비행기 " , " 지하철 " , " 버스 " , " 기차 " , " 택시 " , " 오토바이 " , " 트럭 " , " 배 " ,
" 사과 " , " 바나나 " , " 포도 " , " 수박 " , " 딸기 " , " 오렌지 " , " 키위 " , " 복숭아 " , " 자두 " , " 레몬 " ,
" 짜장면 " , " 짬뽕 " , " 탕수육 " , " 김치찌개 " , " 된장찌개 " , " 비빔밥 " , " 불고기 " , " 떡볶이 " , " 김밥 " , " 라면 " ,
" 하늘 " , " 구름 " , " 바람 " , " 태양 " , " 달 " , " 별 " , " 우주 " , " 바다 " , " 강 " , " 산 " ,
" 학교 " , " 병원 " , " 은행 " , " 우체국 " , " 경찰서 " , " 소방서 " , " 도서관 " , " 박물관 " , " 공원 " , " 시장 " ,
" 사랑 " , " 행복 " , " 우정 " , " 가족 " , " 친구 " , " 선생님 " , " 학생 " , " 의사 " , " 군인 " , " 요리사 " ,
" 대한민국 " , " 무궁화 " , " 태극기 " , " 애국가 " , " 한글 " , " 세종대왕 " , " 이순신 " , " 독도 " , " 서울 " , " 부산 " ,
] ;
2025-11-19 18:00:41 +09:00
2025-11-21 15:54:17 +09:00
// [15단계 난이도 구성]
static final List < FindDiffDifficulty > allDifficulties = [
const FindDiffDifficulty ( levelIndex: 1 , name: ' Lv. 1: 색상 기초 (2x2) ' , contextId: ' DIFF_L1_COLOR ' , rows: 2 , cols: 2 , timeLimitSeconds: 15 , diffType: FindDiffType . color ) ,
const FindDiffDifficulty ( levelIndex: 2 , name: ' Lv. 2: 색상 심화 (3x3) ' , contextId: ' DIFF_L2_COLOR ' , rows: 3 , cols: 3 , timeLimitSeconds: 15 , diffType: FindDiffType . color ) ,
const FindDiffDifficulty ( levelIndex: 3 , name: ' Lv. 3: 모양 기초 (3x3) ' , contextId: ' DIFF_L3_ICON ' , rows: 3 , cols: 3 , timeLimitSeconds: 15 , diffType: FindDiffType . icon ) ,
const FindDiffDifficulty ( levelIndex: 4 , name: ' Lv. 4: 모양 심화 (4x4) ' , contextId: ' DIFF_L4_ICON ' , rows: 4 , cols: 4 , timeLimitSeconds: 15 , diffType: FindDiffType . icon ) ,
const FindDiffDifficulty ( levelIndex: 5 , name: ' Lv. 5: 미세 색상 (4x4) ' , contextId: ' DIFF_L5_COLOR_HARD ' , rows: 4 , cols: 4 , timeLimitSeconds: 15 , diffType: FindDiffType . color ) ,
const FindDiffDifficulty ( levelIndex: 6 , name: ' Lv. 6: 회전 (4x4) ' , contextId: ' DIFF_L6_ROT ' , rows: 4 , cols: 4 , timeLimitSeconds: 15 , diffType: FindDiffType . rotate ) ,
const FindDiffDifficulty ( levelIndex: 7 , name: ' Lv. 7: 회전 (5x5) ' , contextId: ' DIFF_L7_ROT ' , rows: 5 , cols: 5 , timeLimitSeconds: 15 , diffType: FindDiffType . rotate ) ,
const FindDiffDifficulty ( levelIndex: 8 , name: ' Lv. 8: 범주 판단 (4x4) ' , contextId: ' DIFF_L8_CAT ' , rows: 4 , cols: 4 , timeLimitSeconds: 15 , diffType: FindDiffType . category ) ,
const FindDiffDifficulty ( levelIndex: 9 , name: ' Lv. 9: 단어 찾기 (3x3) ' , contextId: ' DIFF_L9_WORD ' , rows: 3 , cols: 3 , timeLimitSeconds: 15 , diffType: FindDiffType . word ) ,
const FindDiffDifficulty ( levelIndex: 10 , name: ' Lv. 10: 단어 찾기 (4x4) ' , contextId: ' DIFF_L10_WORD ' , rows: 4 , cols: 4 , timeLimitSeconds: 15 , diffType: FindDiffType . word ) ,
const FindDiffDifficulty ( levelIndex: 11 , name: ' Lv. 11: 믹스 챌린지 (4x4) ' , contextId: ' DIFF_L11_MIX ' , rows: 4 , cols: 4 , timeLimitSeconds: 15 , diffType: FindDiffType . mix ) ,
const FindDiffDifficulty ( levelIndex: 12 , name: ' Lv. 12: 믹스 챌린지 (5x5) ' , contextId: ' DIFF_L12_MIX ' , rows: 5 , cols: 5 , timeLimitSeconds: 15 , diffType: FindDiffType . mix ) ,
const FindDiffDifficulty ( levelIndex: 13 , name: ' Lv. 13: 마스터 (6x6) ' , contextId: ' DIFF_L13_MASTER ' , rows: 6 , cols: 6 , timeLimitSeconds: 15 , diffType: FindDiffType . mix ) ,
const FindDiffDifficulty ( levelIndex: 14 , name: ' Lv. 14: 그랜드마스터 (7x7) ' , contextId: ' DIFF_L14_GM ' , rows: 7 , cols: 7 , timeLimitSeconds: 15 , diffType: FindDiffType . mix ) ,
const FindDiffDifficulty ( levelIndex: 15 , name: ' Lv. 15: 갓모드 (8x8) ' , contextId: ' DIFF_L15_GOD ' , rows: 8 , cols: 8 , timeLimitSeconds: 15 , diffType: FindDiffType . mix ) ,
2025-11-19 18:00:41 +09:00
] ;
static FindDiffDifficulty 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 ] ) ;
}
}