/* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD SPDX-License-Identifier: MIT */ // // Dance.swift // StackChan // // Created by on 2026/1/16. // import Foundation struct DanceList: Codable, Identifiable { var danceData: [DanceData]? var danceIndex: Int? var danceName: String? var id: String = UUID().uuidString enum CodingKeys: String, CodingKey { case danceData case danceIndex case danceName } } struct DanceData : Codable,Identifiable { var leftEye: ExpressionItem // Left eye, default weight = 100 var rightEye: ExpressionItem // Right eye, default weight = 100 var mouth: ExpressionItem // Mouth, default weight = 0 var yawServo: MotionDataItem // Yaw rotation, angle range (-1280 ~ 1280), default 0 var pitchServo: MotionDataItem // Pitch movement, angle range (0 ~ 900), default 0 var leftRgbColor: String = "#00000000" var rightRgbColor: String = "#00000000" var durationMs: Int // Duration in milliseconds, default 1000 var id: String = UUID().uuidString enum CodingKeys: String, CodingKey { case leftEye, rightEye, mouth, yawServo, pitchServo, leftRgbColor, rightRgbColor, durationMs } static func from(jsonString: String) -> DanceData? { guard !jsonString.isEmpty else { return nil } guard let jsonData = jsonString.data(using: .utf8) else { return nil } do { let decoder = JSONDecoder() let danceData = try decoder.decode(DanceData.self, from: jsonData) return danceData } catch { return nil } } init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) leftEye = try container.decode(ExpressionItem.self, forKey: .leftEye) rightEye = try container.decode(ExpressionItem.self, forKey: .rightEye) mouth = try container.decode(ExpressionItem.self, forKey: .mouth) yawServo = try container.decode(MotionDataItem.self, forKey: .yawServo) pitchServo = try container.decode(MotionDataItem.self, forKey: .pitchServo) leftRgbColor = try container.decodeIfPresent(String.self, forKey: .leftRgbColor) ?? "#00000000" rightRgbColor = try container.decodeIfPresent(String.self, forKey: .rightRgbColor) ?? "#00000000" durationMs = try container.decode(Int.self, forKey: .durationMs) id = UUID().uuidString } init( leftEye: ExpressionItem, rightEye: ExpressionItem, mouth: ExpressionItem, yawServo: MotionDataItem, pitchServo: MotionDataItem, leftRgbColor: String = "#00000000", rightRgbColor: String = "#00000000", durationMs: Int, id: String = UUID().uuidString ) { self.leftEye = leftEye self.rightEye = rightEye self.mouth = mouth self.yawServo = yawServo self.pitchServo = pitchServo self.leftRgbColor = leftRgbColor self.rightRgbColor = rightRgbColor self.durationMs = durationMs self.id = id } func copy() -> DanceData { DanceData( leftEye: self.leftEye.copy(), rightEye: self.rightEye.copy(), mouth: self.mouth.copy(), yawServo: self.yawServo.copy(), pitchServo: self.pitchServo.copy(), leftRgbColor: self.leftRgbColor, rightRgbColor: self.rightRgbColor, durationMs: self.durationMs, id: UUID().uuidString ) } }