Last active
May 16, 2024 19:46
-
-
Save theoknock/b757d1600f19cce840632a8de2a5224f to your computer and use it in GitHub Desktop.
Using a serial and global dispatch queue to synchronize calls to functions that should be executed one after another, preventing overlap.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
public func randomizeDurationSplits(group: DispatchGroup? = nil, completion: @escaping ([[Double]]) -> Void) { | |
group?.enter() | |
DispatchQueue.global().async { | |
let dyad0harmony0: Double = Double.random(in: durationLowerBound ... durationUpperBound) | |
var dyad1harmony0: Double = dyad0harmony0 | |
repeat { | |
dyad1harmony0 = Double.random(in: durationLowerBound ... durationUpperBound) | |
} while (abs(dyad0harmony0 - dyad1harmony0) < durationTolerance) | |
let dyad0harmony1 = durationLength - dyad0harmony0 | |
let dyad1harmony1 = durationLength - dyad1harmony0 | |
let result = [[dyad0harmony0, dyad0harmony1], [dyad1harmony0, dyad1harmony1]] | |
group?.leave() | |
DispatchQueue.main.async { | |
completion(result) | |
} | |
} | |
} | |
// Usage Example | |
let group = DispatchGroup() | |
randomizeDurationSplits(group: group) { result in | |
print(result) | |
} | |
randomizeDurationSplits(group: group) { result in | |
print(result) | |
} | |
group.notify(queue: .main) { | |
print("All tasks are complete.") | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
let semaphore = DispatchSemaphore(value: 1) | |
public func randomizeDurationSplits(completion: @escaping ([[Double]]) -> Void) { | |
DispatchQueue.global().async { | |
semaphore.wait() // Wait for the semaphore | |
let dyad0harmony0: Double = Double.random(in: durationLowerBound ... durationUpperBound) | |
var dyad1harmony0: Double = dyad0harmony0 | |
repeat { | |
dyad1harmony0 = Double.random(in: durationLowerBound ... durationUpperBound) | |
} while (abs(dyad0harmony0 - dyad1harmony0) < durationTolerance) | |
let dyad0harmony1 = durationLength - dyad0harmony0 | |
let dyad1harmony1 = durationLength - dyad1harmony0 | |
let result = [[dyad0harmony0, dyad0harmony1], [dyad1harmony0, dyad1harmony1]] | |
semaphore.signal() // Release the semaphore | |
DispatchQueue.main.async { | |
completion(result) | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import SwiftUI | |
import Foundation | |
import Combine | |
import Observation | |
@Observable class Durations { | |
var durationLength: Double = 2.0000 | |
var durationLowerBound: Double = 0.3125 | |
var durationUpperBound: Double = 1.6875 | |
var durationTolerance: Double = 0.3125 | |
init(length: Double?, lowerBound: Double?, upperBound: Double?, tolerance: Double?) { | |
self.durationLength = length ?? durationLength | |
self.durationLowerBound = lowerBound ?? durationLowerBound | |
self.durationUpperBound = upperBound ?? durationUpperBound | |
self.durationTolerance = tolerance ?? durationTolerance | |
// Ensure the range is valid | |
guard (durationUpperBound - durationLowerBound) >= durationTolerance else { | |
fatalError("The range defined by durationLowerBound and durationUpperBound is too small for the given durationTolerance.") | |
} | |
} | |
func scale(oldMin: CGFloat, oldMax: CGFloat, value: CGFloat, newMin: CGFloat, newMax: CGFloat) -> CGFloat { | |
return newMin + ((newMax - newMin) * ((value - oldMin) / (oldMax - oldMin))) | |
} | |
// Generates randomized durations within these constraints: | |
// durationLowerBound > []dyad0harmony0, dyad1harmony0] < durationUpperBound and |dyad0harmony0 - dyad1harmony0| >= durationTolerance | |
let serialQueue = DispatchQueue(label: "com.example.serialQueue") | |
public func randomizeDurationSplits(completion: @escaping ([[Double]]) -> Void) { | |
serialQueue.async { [self] in | |
let dyad0harmony0: Double = Double.random(in: durationLowerBound...durationUpperBound) | |
var dyad1harmony0: Double = dyad0harmony0 | |
repeat { | |
dyad1harmony0 = Double.random(in: durationLowerBound...durationUpperBound) | |
} while (abs(dyad0harmony0 - dyad1harmony0) < durationTolerance) | |
let dyad0harmony1 = durationLength - dyad0harmony0 | |
let dyad1harmony1 = durationLength - dyad1harmony0 | |
let result = [[dyad0harmony0, dyad0harmony1], [dyad1harmony0, dyad1harmony1]] | |
DispatchQueue.main.async { | |
completion(result) | |
} | |
} | |
} | |
} | |
struct ContentView: View { | |
private var durations: Durations = Durations(length: nil, lowerBound: nil, upperBound: nil, tolerance: nil) | |
@State private var results: [[[Double]]] = [] | |
var body: some View { | |
ZStack(alignment: Alignment(horizontal: .center, vertical: .center), content: { | |
List(results, id: \.self) { result in | |
let diff = abs(result[0][0] - result[1][0]) | |
let sum = result[0][0] + result[0][1] | |
let formattedDiff = String(format: "-%.4f", diff) | |
let formattedSum = String(format: "+%.4f", sum) | |
let diffColor = diff >= 0.3125 ? UIColor.green : UIColor.red | |
let sumColor = sum == 2.0000 ? UIColor.green : UIColor.red | |
let text = NSMutableAttributedString(string: "\(result[0][0])\n\(result[1][0])\n") | |
let coloredDiff = NSAttributedString( | |
string: formattedDiff, | |
attributes: [.foregroundColor: diffColor] | |
) | |
text.append(coloredDiff) | |
text.append(NSAttributedString(string: "\n")) | |
let coloredSum = NSAttributedString( | |
string: formattedSum, | |
attributes: [.foregroundColor: sumColor] | |
) | |
text.append(coloredSum) | |
// | |
return Text(AttributedString(text)) | |
.frame(alignment: .leading) | |
.border(.white) | |
.padding() | |
} | |
Button("Randomize Duration Splits") { | |
durations.randomizeDurationSplits { result in | |
print(result) | |
results.append(result) | |
} | |
} | |
.safeAreaPadding() | |
.border(.white) | |
}) | |
} | |
} | |
@main | |
struct MyApp: App { | |
var body: some Scene { | |
WindowGroup { | |
ContentView() | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment