Skip to content

Commit bb850da

Browse files
authored
Merge pull request #12 from orchetect/dev
1.0.11
2 parents 16adee2 + ac733a5 commit bb850da

File tree

3 files changed

+113
-6
lines changed

3 files changed

+113
-6
lines changed

Sources/TimecodeKit/FrameRate/FrameRate CompatibleGroup.swift

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ extension Timecode.FrameRate {
2929
/// - 00:59:56:12 @ 29.97 fps
3030
public static var table: [CompatibleGroup : [Timecode.FrameRate]] =
3131
[
32-
3332
.NTSC: [
3433
._23_976,
3534
._24_98,
@@ -61,11 +60,42 @@ extension Timecode.FrameRate {
6160
._60_drop,
6261
._120_drop
6362
]
64-
6563
]
6664

6765
}
6866

67+
}
68+
69+
extension Timecode.FrameRate.CompatibleGroup: CustomStringConvertible {
70+
71+
public var description: String {
72+
73+
stringValue
74+
75+
}
76+
77+
/// Returns human-readable group string.
78+
public var stringValue: String {
79+
switch self {
80+
case .NTSC:
81+
return "NTSC"
82+
83+
case .NTSC_drop:
84+
return "NTSC Drop-Frame"
85+
86+
case .ATSC:
87+
return "ATSC"
88+
89+
case .ATSC_drop:
90+
return "ATSC Drop-Frame"
91+
92+
}
93+
}
94+
95+
}
96+
97+
extension Timecode.FrameRate {
98+
6999
/// Returns the frame rate's `CompatibleGroup` categorization.
70100
@inlinable public var compatibleGroup: CompatibleGroup {
71101

@@ -77,19 +107,30 @@ extension Timecode.FrameRate {
77107

78108
}
79109

80-
/// Returns true if the source `FrameRate` shares a compatible grouping with the passed `timecode`.
110+
/// Returns the members of the frame rate's `CompatibleGroup` categorization.
111+
@inlinable public var compatibleGroupRates: [Self] {
112+
113+
// Force-unwrap here will never crash because the unit tests ensure the table contains all Timecode.FrameRate cases.
114+
115+
Self.CompatibleGroup.table
116+
.first(where: { $0.value.contains(self) })!
117+
.value
118+
119+
}
120+
121+
/// Returns true if the source `FrameRate` shares a compatible grouping with the passed `other` frame rate.
81122
///
82123
/// For example, at the same point of elapsed real time, 30 and 60 fps are compatible with each other, but 29.97 is not:
83124
///
84125
/// - 01:00:00:00 @ 30 fps
85126
/// - 01:00:00:00 @ 60 fps
86127
/// - 00:59:56:12 @ 29.97 fps
87-
@inlinable public func isCompatible(with timecode: Self) -> Bool {
128+
@inlinable public func isCompatible(with other: Self) -> Bool {
88129

89130
Self.CompatibleGroup.table
90131
.values
91132
.first(where: { $0.contains(self) })?
92-
.contains(timecode)
133+
.contains(other)
93134
?? false
94135

95136
}

Sources/TimecodeKit/FrameRate/FrameRate.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,3 +131,12 @@ extension Timecode.FrameRate: CaseIterable {
131131
public static let allNonDrop: [Self] = allCases.filter { !$0.isDrop }
132132

133133
}
134+
135+
@available(macOS 10.15, macCatalyst 13, iOS 13, *)
136+
extension Timecode.FrameRate: Identifiable {
137+
138+
public var id: String {
139+
rawValue
140+
}
141+
142+
}

Tests/TimecodeKit-Unit-Tests/Unit Tests/FrameRate/FrameRate CompatibleGroup Tests.swift

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
import XCTest
1212
@testable import TimecodeKit
13+
import OTCore
1314

1415
class Timecode_UT_FrameRate_CompatibleGroup: XCTestCase {
1516

@@ -28,7 +29,7 @@ class Timecode_UT_FrameRate_CompatibleGroup: XCTestCase {
2829

2930
}
3031

31-
func testCompatibleGroup_Basic() {
32+
func testCompatibleGroup_compatibleGroup() {
3233

3334
// methods basic spot-check
3435

@@ -54,6 +55,62 @@ class Timecode_UT_FrameRate_CompatibleGroup: XCTestCase {
5455

5556
}
5657

58+
func testCompatibleGroup_compatibleGroupRates() {
59+
60+
for grouping in Timecode.FrameRate.CompatibleGroup.table {
61+
62+
let otherGroupingsRates = Timecode.FrameRate.CompatibleGroup.table
63+
.compactMap { $0.key != grouping.key ? $0 : nil }
64+
.reduce(into: [], { $0 += ($1.value) })
65+
66+
for rate in grouping.value {
67+
XCTAssertEqual(
68+
rate.compatibleGroupRates,
69+
grouping.value
70+
)
71+
}
72+
73+
for rate in otherGroupingsRates {
74+
XCTAssertNotEqual(
75+
rate.compatibleGroupRates,
76+
grouping.value
77+
)
78+
}
79+
80+
}
81+
82+
}
83+
84+
func testCompatibleGroup_isCompatible() {
85+
86+
for grouping in Timecode.FrameRate.CompatibleGroup.table {
87+
88+
let otherGroupingsRates = Timecode.FrameRate.CompatibleGroup.table
89+
.compactMap { $0.key != grouping.key ? $0 : nil }
90+
.reduce(into: [], { $0 += ($1.value) })
91+
92+
// test against other rates in the same grouping
93+
for srcRate in grouping.value {
94+
for destRate in grouping.value {
95+
96+
XCTAssertTrue(srcRate.isCompatible(with: destRate))
97+
98+
}
99+
}
100+
101+
// test against rates in all the other groupings
102+
for srcRate in grouping.value {
103+
for destRate in otherGroupingsRates {
104+
105+
XCTAssertFalse(srcRate.isCompatible(with: destRate))
106+
107+
}
108+
}
109+
110+
}
111+
112+
}
113+
57114
}
58115

59116
#endif

0 commit comments

Comments
 (0)