Skip to content

Commit a0b1e87

Browse files
committed
🎱
0 parents  commit a0b1e87

36 files changed

+3168
-0
lines changed

.circleci/config.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
version: 2
2+
3+
jobs:
4+
build:
5+
macos:
6+
xcode: "10.1.0"
7+
8+
steps:
9+
- checkout
10+
11+
- run:
12+
name: Mac Info
13+
command: system_profiler SPSoftwareDataType
14+
15+
- run:
16+
name: Simulator Info
17+
command: instruments -s devices
18+
19+
- run:
20+
name: Run iOS tests
21+
command: make test-ios
22+
23+
- run:
24+
name: Run macOS tests
25+
command: make test-macos
26+
27+
- run:
28+
name: Run Swift tests
29+
command: make test-swift

.gitignore

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# Xcode
2+
#
3+
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4+
5+
## Build generated
6+
build/
7+
DerivedData/
8+
9+
## Various settings
10+
*.pbxuser
11+
!default.pbxuser
12+
*.mode1v3
13+
!default.mode1v3
14+
*.mode2v3
15+
!default.mode2v3
16+
*.perspectivev3
17+
!default.perspectivev3
18+
xcuserdata/
19+
20+
## Other
21+
*.moved-aside
22+
*.xccheckout
23+
*.xcscmblueprint
24+
25+
## Obj-C/Swift specific
26+
*.hmap
27+
*.ipa
28+
*.dSYM.zip
29+
*.dSYM
30+
31+
## Playgrounds
32+
timeline.xctimeline
33+
playground.xcworkspace
34+
35+
# Swift Package Manager
36+
#
37+
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
38+
# Packages/
39+
# Package.pins
40+
.build/
41+
42+
# CocoaPods
43+
#
44+
# We recommend against adding the Pods directory to your .gitignore. However
45+
# you should judge for yourself, the pros and cons are mentioned at:
46+
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
47+
#
48+
# Pods/
49+
50+
# Carthage
51+
#
52+
# Add this line if you want to avoid checking in source code from Carthage dependencies.
53+
# Carthage/Checkouts
54+
55+
Carthage/Build
56+
57+
# fastlane
58+
#
59+
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
60+
# screenshots whenever they are needed.
61+
# For more information about the recommended setup visit:
62+
# https://docs.fastlane.tools/best-practices/source-control/#source-control
63+
64+
fastlane/report.xml
65+
fastlane/Preview.html
66+
fastlane/screenshots
67+
fastlane/test_output
68+
69+
.DS_Store

.swift-version

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
4.2.1

.travis.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
os:
2+
- linux
3+
env:
4+
language: generic
5+
sudo: required
6+
dist: trusty
7+
install:
8+
- if [ $TRAVIS_OS_NAME = linux ]; then
9+
eval "$(curl -sL https://swiftenv.fuller.li/install.sh)";
10+
fi
11+
script:
12+
- swift test

CODE_OF_CONDUCT.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Contributor Covenant Code of Conduct
2+
3+
## Our Pledge
4+
5+
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
6+
7+
## Our Standards
8+
9+
Examples of behavior that contributes to creating a positive environment include:
10+
11+
* Using welcoming and inclusive language
12+
* Being respectful of differing viewpoints and experiences
13+
* Gracefully accepting constructive criticism
14+
* Focusing on what is best for the community
15+
* Showing empathy towards other community members
16+
17+
Examples of unacceptable behavior by participants include:
18+
19+
* The use of sexualized language or imagery and unwelcome sexual attention or advances
20+
* Trolling, insulting/derogatory comments, and personal or political attacks
21+
* Public or private harassment
22+
* Publishing others' private information, such as a physical or electronic address, without explicit permission
23+
* Other conduct which could reasonably be considered inappropriate in a professional setting
24+
25+
## Our Responsibilities
26+
27+
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
28+
29+
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
30+
31+
## Scope
32+
33+
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
34+
35+
## Enforcement
36+
37+
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at [email protected]. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
38+
39+
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
40+
41+
## Attribution
42+
43+
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
44+
45+
[homepage]: http://contributor-covenant.org
46+
[version]: http://contributor-covenant.org/version/1/4/

Dockerfile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
FROM swift:4.2
2+
3+
WORKDIR /package
4+
5+
COPY . ./
6+
7+
RUN swift package resolve
8+
RUN swift package clean
9+
CMD swift test --parallel
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
import Gen
2+
import UIKit
3+
4+
// We want to create a random art generator that creates UIImages.
5+
// ⚠️ Run this playground with the live view open. ⚠️
6+
7+
let canvas = CGRect(x: 0, y: 0, width: 600, height: 600)
8+
let mainArea = canvas.insetBy(dx: 130, dy: 100)
9+
let numLines = 60
10+
let numPointsPerLine = 60
11+
let dx = mainArea.width / CGFloat(numPointsPerLine)
12+
let dy = mainArea.height / CGFloat(numLines)
13+
14+
func bump(
15+
amplitude: CGFloat,
16+
center: CGFloat,
17+
plateauSize: CGFloat,
18+
curveSize: CGFloat
19+
) -> (CGFloat) -> CGFloat {
20+
21+
// A nice smooth curve that starts at zero and trends towards 1 asymptotically
22+
func f(_ x: CGFloat) -> CGFloat {
23+
if x <= 0 { return 0 }
24+
return exp(-1 / x)
25+
}
26+
27+
// A nice smooth curve that starts at zero and curves up to 1 on the unit interval.
28+
func g(_ x: CGFloat) -> CGFloat {
29+
return f(x) / (f(x) + f(1 - x))
30+
}
31+
32+
return { x in
33+
let plateauSize = plateauSize / 2
34+
let curveSize = curveSize / 2
35+
let size = plateauSize + curveSize
36+
let x = x - center
37+
return amplitude * (1 - g((x * x - plateauSize * plateauSize) / (size * size - plateauSize * plateauSize)))
38+
}
39+
}
40+
41+
func noisyBump(
42+
amplitude: CGFloat,
43+
center: CGFloat,
44+
plateauSize: CGFloat,
45+
curveSize: CGFloat
46+
) -> (CGFloat) -> Gen<CGFloat> {
47+
48+
let curve = bump(amplitude: amplitude, center: center, plateauSize: plateauSize, curveSize: curveSize)
49+
50+
return { x in
51+
let y = curve(x)
52+
return Gen<CGFloat>.float(in: 0...3).map { $0 * (y / amplitude + 0.5) + y }
53+
}
54+
}
55+
56+
let curve = zip(
57+
Gen<CGFloat>.float(in: -30...(-1)),
58+
Gen<CGFloat>.float(in: -60...60)
59+
.map { $0 + canvas.width / 2 },
60+
Gen<CGFloat>.float(in: 0...60),
61+
Gen<CGFloat>.float(in: 10...60)
62+
)
63+
.map(noisyBump(amplitude:center:plateauSize:curveSize:))
64+
65+
func path(from min: CGFloat, to max: CGFloat, baseline: CGFloat) -> Gen<CGPath> {
66+
return Gen<CGPath> { rng in
67+
let bumps = curve.array(of: .int(in: 1...4))
68+
.run(using: &rng)
69+
70+
let path = CGMutablePath()
71+
path.move(to: CGPoint(x: min, y: baseline))
72+
stride(from: min, to: max, by: dx).forEach { x in
73+
let ys = bumps.map { $0(x).run(using: &rng) }
74+
let average = ys.reduce(0, +) / CGFloat(ys.count)
75+
path.addLine(to: CGPoint(x: x, y: baseline + average))
76+
}
77+
path.addLine(to: CGPoint.init(x: max, y: baseline))
78+
return path
79+
}
80+
}
81+
82+
let paths = stride(from: mainArea.minY, to: mainArea.maxY, by: dy)
83+
.map { path(from: mainArea.minX, to: mainArea.maxX, baseline: $0) }
84+
.sequence()
85+
86+
let colors = [
87+
UIColor(red: 0.47, green: 0.95, blue: 0.69, alpha: 1),
88+
UIColor(red: 1, green: 0.94, blue: 0.5, alpha: 1),
89+
UIColor(red: 0.3, green: 0.80, blue: 1, alpha: 1),
90+
UIColor(red: 0.59, green: 0.30, blue: 1, alpha: 1)
91+
]
92+
93+
let image = paths.map { paths in
94+
UIGraphicsImageRenderer(bounds: canvas).image { ctx in
95+
let ctx = ctx.cgContext
96+
97+
ctx.setFillColor(UIColor.black.cgColor)
98+
ctx.fill(canvas)
99+
100+
paths.enumerated().forEach { idx, path in
101+
ctx.setStrokeColor(
102+
colors[colors.count * idx / paths.count].cgColor
103+
)
104+
ctx.addPath(path)
105+
ctx.drawPath(using: .fillStroke)
106+
}
107+
}
108+
}
109+
110+
let imageView = image.map(UIImageView.init)
111+
112+
import PlaygroundSupport
113+
PlaygroundPage.current.liveView = imageView.run()
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import Gen
2+
3+
// We want to generate passwords in the same format as those suggested by the iCloud keychain, for example `huwKun-1zyjxi-nyxseh`. It takes very little work! We're just three operations away:
4+
5+
let password = Gen.letterOrNumber
6+
// Generate a 6-character string of random letters and numbers.
7+
.string(of: .always(6))
8+
// Generate 3 segments of these strings.
9+
.array(of: .always(3))
10+
// And join them.
11+
.map { $0.joined(separator: "-") }
12+
13+
password.run()
14+
password.run()
15+
password.run()
16+
password.run()
17+
password.run()
18+
19+
// The passwords Apple generates appears to strongly preference lowercase letters over uppercase letters. To get a bit closer we can dip down for a few lower-level combinators:
20+
let iCloudPassword = Gen
21+
// Rather than work with evenly-distributed randomness across lowercase letters, uppercase letters, and numbers, let's weight lowercase letters much higher.
22+
.frequency(
23+
(12, .lowercaseLetter),
24+
(1, .uppercaseLetter),
25+
(1, .number)
26+
)
27+
// And do the same work as before.
28+
.string(of: .always(6))
29+
.array(of: .always(3))
30+
.map { $0.joined(separator: "-") }
31+
32+
iCloudPassword.run()
33+
iCloudPassword.run()
34+
iCloudPassword.run()
35+
iCloudPassword.run()
36+
iCloudPassword.run()
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import Gen
2+
3+
zip(.bool, .bool).dictionary(ofAtMost: .always(1)).run()
4+
Gen.bool.set(ofAtMost: .always(3)).run()
5+
Gen.float(in: 0...1)
6+
7+
import CoreGraphics
8+
Gen.float80(in: 0...1)
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import Gen
2+
3+
// We want to create a generator that can randomly "Zalgo-ify" any string, which mean sit will glitch it
4+
// out with random artifacts, as seen here: http://www.eeemo.net
5+
6+
// A Zalgo character is a UTF8 character in the "combining character" range.
7+
// See: https://en.wikipedia.org/wiki/Combining_character
8+
let zalgo = Gen.int(in: 0x300 ... 0x36f)
9+
.map { String(UnicodeScalar($0)!) }
10+
11+
// Here's what some Zalgo characters look like
12+
zalgo.run()
13+
zalgo.run()
14+
zalgo.run()
15+
zalgo.run()
16+
17+
// Given an intensity, combines a random number of Zalgo characters into a single string.
18+
func zalgos(intensity: Gen<Int>) -> Gen<String> {
19+
return zalgo
20+
.array(of: intensity)
21+
.map { $0.joined() }
22+
}
23+
24+
let tameZalgos = zalgos(intensity: .int(in: 0...1))
25+
let lowZalgos = zalgos(intensity: .int(in: 1...5))
26+
let mediumZalgos = zalgos(intensity: .int(in: 0...10))
27+
let highZalgos = zalgos(intensity: .int(in: 0...20))
28+
29+
"a" + tameZalgos.run()
30+
31+
"a" + lowZalgos.run()
32+
33+
"a" + mediumZalgos.run()
34+
35+
"a" + highZalgos.run()
36+
37+
// Given a way to generate a bunch of Zalgo characters, this will return a function that can "Zalgo-ify" any string given to it.
38+
func zalgoify(with zalgos: Gen<String>) -> (String) -> Gen<String> {
39+
return { string in
40+
return Gen { rng in
41+
string
42+
.map { char in String(char) + zalgos.run(using: &rng) }
43+
.joined()
44+
}
45+
}
46+
}
47+
48+
let tameZalgoify = zalgoify(with: tameZalgos)
49+
let lowZalgoify = zalgoify(with: lowZalgos)
50+
let mediumZalgoify = zalgoify(with: mediumZalgos)
51+
let highZalgoify = zalgoify(with: highZalgos)
52+
53+
tameZalgoify("What’s the point?").run()
54+
55+
lowZalgoify("What’s the point?").run()
56+
57+
mediumZalgoify("What’s the point?").run()
58+
59+
highZalgoify("What’s the point?").run()

0 commit comments

Comments
 (0)