// // Player.swift // BerryLeaderboards // // Created by Lncvrt on 6/9/25. // import Foundation struct LeaderboardResponse: Codable { let success: Bool let message: String? let data: [PlayerData] } struct PlayerData: Codable { let id: Int let username: String let value: Int let icon: IntOrString let overlay: IntOrString let birdColor: [Int] let overlayColor: [Int] let customIcon: String? } enum IntOrString: Codable { case int(Int) case string(String) init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() if let int = try? container.decode(Int.self) { self = .int(int) } else if let str = try? container.decode(String.self) { self = .string(str) } else { throw DecodingError.dataCorrupted(.init(codingPath: decoder.codingPath, debugDescription: "Invalid value")) } } func encode(to encoder: Encoder) throws { var container = encoder.singleValueContainer() switch self { case .int(let i): try container.encode(i) case .string(let s): try container.encode(s) } } } struct Player: Codable { let username: String let score: Int } func parseLeaderboard(_ raw: String) -> [Player] { guard let data = raw.data(using: .utf8) else { return [] } guard let response = try? JSONDecoder().decode(LeaderboardResponse.self, from: data) else { return [] } return response.data.map { Player(username: $0.username, score: $0.value) } }