parent
7a9ae3f7ff
commit
ef1bfb7352
@ -0,0 +1,52 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> |
||||||
|
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="21513" systemVersion="22A400" minimumToolsVersion="Automatic" sourceLanguage="Swift" usedWithCloudKit="YES" userDefinedModelVersionIdentifier=""> |
||||||
|
<entity name="AbstractSoundTimer" representedClassName="AbstractSoundTimer" isAbstract="YES" parentEntity="AbstractTimer" elementID="soundList" syncable="YES"> |
||||||
|
<attribute name="confirmationSoundList" optional="YES" attributeType="String"/> |
||||||
|
<attribute name="playableIds" optional="YES" attributeType="String" elementID="soundList"/> |
||||||
|
<attribute name="repeatCount" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/> |
||||||
|
</entity> |
||||||
|
<entity name="AbstractTimer" representedClassName="AbstractTimer" isAbstract="YES" syncable="YES"> |
||||||
|
<attribute name="image" optional="YES" attributeType="String"/> |
||||||
|
<attribute name="order" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/> |
||||||
|
<relationship name="activity" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Activity" inverseName="timers" inverseEntity="Activity"/> |
||||||
|
</entity> |
||||||
|
<entity name="Activity" representedClassName="Activity" syncable="YES"> |
||||||
|
<attribute name="name" attributeType="String" defaultValueString=""/> |
||||||
|
<relationship name="records" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="Record" inverseName="activity" inverseEntity="Record"/> |
||||||
|
<relationship name="timers" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="AbstractTimer" inverseName="activity" inverseEntity="AbstractTimer"/> |
||||||
|
</entity> |
||||||
|
<entity name="Alarm" representedClassName="Alarm" parentEntity="AbstractSoundTimer" syncable="YES"> |
||||||
|
<attribute name="fireDate" optional="YES" attributeType="Date" usesScalarValueType="NO"/> |
||||||
|
</entity> |
||||||
|
<entity name="Countdown" representedClassName="Countdown" parentEntity="AbstractSoundTimer" syncable="YES"> |
||||||
|
<attribute name="duration" attributeType="Double" defaultValueString="0" usesScalarValueType="YES"/> |
||||||
|
<relationship name="group" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="IntervalGroup" inverseName="countdown" inverseEntity="IntervalGroup"/> |
||||||
|
</entity> |
||||||
|
<entity name="CustomSound" representedClassName="CustomSound" syncable="YES"> |
||||||
|
<attribute name="file" optional="YES" attributeType="String"/> |
||||||
|
<attribute name="text" optional="YES" attributeType="String"/> |
||||||
|
</entity> |
||||||
|
<entity name="Interval" representedClassName="Interval" syncable="YES"> |
||||||
|
<attribute name="duration" attributeType="Double" defaultValueString="0.0" usesScalarValueType="YES"/> |
||||||
|
<attribute name="soundList" optional="YES" attributeType="String"/> |
||||||
|
<relationship name="group" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="IntervalGroup" inverseName="intervals" inverseEntity="IntervalGroup"/> |
||||||
|
</entity> |
||||||
|
<entity name="IntervalGroup" representedClassName="IntervalGroup" syncable="YES"> |
||||||
|
<attribute name="repeatCount" optional="YES" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/> |
||||||
|
<relationship name="countdown" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Countdown" inverseName="group" inverseEntity="Countdown"/> |
||||||
|
<relationship name="intervals" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="Interval" inverseName="group" inverseEntity="Interval"/> |
||||||
|
</entity> |
||||||
|
<entity name="Record" representedClassName="Record" syncable="YES"> |
||||||
|
<attribute name="duration" attributeType="Double" defaultValueString="0.0" usesScalarValueType="YES"/> |
||||||
|
<attribute name="end" attributeType="Date" defaultDateTimeInterval="696425400" usesScalarValueType="NO"/> |
||||||
|
<attribute name="month" optional="YES" attributeType="Integer 16" usesScalarValueType="YES"/> |
||||||
|
<attribute name="start" attributeType="Date" defaultDateTimeInterval="696425400" usesScalarValueType="NO"/> |
||||||
|
<attribute name="year" optional="YES" attributeType="Integer 16" usesScalarValueType="YES"/> |
||||||
|
<relationship name="activity" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Activity" inverseName="records" inverseEntity="Activity"/> |
||||||
|
</entity> |
||||||
|
<entity name="Stopwatch" representedClassName="Stopwatch" parentEntity="AbstractSoundTimer" syncable="YES"> |
||||||
|
<attribute name="end" optional="YES" attributeType="Date" usesScalarValueType="NO"/> |
||||||
|
<attribute name="sound" optional="YES" attributeType="Integer 16" usesScalarValueType="YES"/> |
||||||
|
<attribute name="start" optional="YES" attributeType="Date" usesScalarValueType="NO"/> |
||||||
|
</entity> |
||||||
|
</model> |
||||||
@ -0,0 +1,45 @@ |
|||||||
|
// |
||||||
|
// Extensions.swift |
||||||
|
// LeCountdown |
||||||
|
// |
||||||
|
// Created by Laurent Morvillier on 28/03/2023. |
||||||
|
// |
||||||
|
|
||||||
|
import Foundation |
||||||
|
|
||||||
|
// MARK: - Storage convenience |
||||||
|
|
||||||
|
let idSeparator = "|" |
||||||
|
let numberFormatter: NumberFormatter = NumberFormatter() |
||||||
|
|
||||||
|
extension String { |
||||||
|
|
||||||
|
func enumItems<T : RawRepresentable<Int>>() -> [T] { |
||||||
|
let ids: [String] = self.components(separatedBy: idSeparator) |
||||||
|
let intIds: [Int] = ids.compactMap { numberFormatter.number(from: $0)?.intValue } |
||||||
|
return intIds.compactMap { T(rawValue: $0) } |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
//extension Sequence where Element : RawRepresentable<Int> { |
||||||
|
// var stringRepresentation: String { |
||||||
|
// let ids = self.compactMap { formatter.string(from: NSNumber(value: $0.rawValue)) } |
||||||
|
// return ids.joined(separator: separator) |
||||||
|
// } |
||||||
|
//} |
||||||
|
|
||||||
|
extension Sequence where Element : StringRepresentable { |
||||||
|
var stringRepresentation: String { |
||||||
|
let ids = self.compactMap { $0.stringValue } |
||||||
|
return ids.joined(separator: idSeparator) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
protocol StringRepresentable { |
||||||
|
var stringValue: String { get } |
||||||
|
} |
||||||
|
|
||||||
|
extension String: StringRepresentable { |
||||||
|
var stringValue: String { self } |
||||||
|
} |
||||||
Loading…
Reference in new issue