import 'dart:convert'; import 'dart:developer'; // πŸ‘ˆ [μΆ”κ°€] log ν•¨μˆ˜λ₯Ό μœ„ν•œ μž„ν¬νŠΈ import 'package:http/http.dart' as http; import 'package:sudoku_app/models/sudoku_game_dto.dart'; import 'package:sudoku_app/models/unified_rank_dto.dart'; import 'package:sudoku_app/models/game_rank_dto.dart'; class PuzzleService { final String _baseUrl = "https://lunaticbum.kr"; // ... (startGame ν•¨μˆ˜λŠ” 동일) ... Future startGame(String difficulty) async { final response = await http.get( Uri.parse('$_baseUrl/puzzle/sudoku/start?difficulty=$difficulty'), ); if (response.statusCode == 200) { final data = jsonDecode(utf8.decode(response.bodyBytes)); return SudokuGameDto.fromJson(data); } else { throw Exception('κ²Œμž„ λ‘œλ”© μ‹€νŒ¨: ${response.statusCode}'); } } // ... (validateSolution ν•¨μˆ˜λŠ” 동일) ... Future validateSolution(int puzzleId, String answer) async { final response = await http.post( Uri.parse('$_baseUrl/puzzle/sudoku/validate'), headers: {'Content-Type': 'application/json'}, body: jsonEncode({ 'puzzleId': puzzleId, 'answer': answer, }), ); if (response.statusCode == 200) { return jsonDecode(response.body)['correct'] ?? false; } else { log("μ •λ‹΅ 확인 μ‹€νŒ¨: ${response.statusCode}"); log("응닡 λ³Έλ¬Έ: ${response.body}"); throw Exception('μ •λ‹΅ 확인 μ‹€νŒ¨: ${response.statusCode}'); } } // POST /api/ranks/submit Future submitRank(UnifiedRankDto rankDto) async { final requestBody = jsonEncode(rankDto.toJson()); // πŸ”½ [둜그 μΆ”κ°€] 1. μ„œλ²„λ‘œ μ „μ†‘ν•˜λŠ” JSON 데이터 좜λ ₯ log(">>> λž­ν‚Ή 등둝 μš”μ²­: $requestBody"); final response = await http.post( Uri.parse('$_baseUrl/api/ranks/submit'), headers: {'Content-Type': 'application/json'}, body: requestBody, ); if (response.statusCode != 200) { // πŸ”½ [둜그 μΆ”κ°€] 2. μ„œλ²„κ°€ 200(OK)이 μ•„λ‹Œ 응닡을 쀬을 λ•Œ log("<<< λž­ν‚Ή 등둝 μ‹€νŒ¨: ${response.statusCode}"); try { final errorBody = utf8.decode(response.bodyBytes); log("<<< μ„œλ²„ μ—λŸ¬ λ©”μ‹œμ§€: $errorBody"); // πŸ‘ˆ (예: "이미 μ‚¬μš© 쀑인 μ΄λ¦„μž…λ‹ˆλ‹€.") throw Exception(errorBody); } catch (e) { throw Exception('λž­ν‚Ή 등둝 μ‹€νŒ¨: ${response.reasonPhrase}'); } } // πŸ”½ [둜그 μΆ”κ°€] 3. 성곡 μ‹œ log("<<< λž­ν‚Ή 등둝 성곡: 200 OK"); } // ... (fetchRanks ν•¨μˆ˜λŠ” 동일) ... Future> fetchRanks(String gameType, String? contextId) async { final queryParams = { 'gameType': gameType, if (contextId != null) 'contextId': contextId, }; final uri = Uri.parse('$_baseUrl/api/ranks/list').replace(queryParameters: queryParams); final response = await http.get(uri); if (response.statusCode == 200) { final List data = jsonDecode(utf8.decode(response.bodyBytes)); return data.map((json) => GameRankDto.fromJson(json)).toList(); } else { throw Exception('λž­ν‚Ή λ‘œλ”© μ‹€νŒ¨'); } } }