first commit

This commit is contained in:
sigmasternchen 2024-12-07 22:15:59 +01:00
commit 4211fc3074
12 changed files with 267 additions and 0 deletions

23
.github/workflows/test.yml vendored Normal file
View file

@ -0,0 +1,23 @@
name: test
on:
push:
branches:
- master
- main
pull_request:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: erlef/setup-beam@v1
with:
otp-version: "26.0.2"
gleam-version: "1.5.1"
rebar3-version: "3"
# elixir-version: "1.15.4"
- run: gleam deps download
- run: gleam test
- run: gleam format --check src test

4
.gitignore vendored Normal file
View file

@ -0,0 +1,4 @@
*.beam
*.ez
/build
erl_crash.dump

26
README.md Normal file
View file

@ -0,0 +1,26 @@
# queermandelbrot
[![Package Version](https://img.shields.io/hexpm/v/queermandelbrot)](https://hex.pm/packages/queermandelbrot)
[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/queermandelbrot/)
```sh
gleam add queermandelbrot@1
```
```gleam
import queermandelbrot
pub fn main() {
// TODO: An example of the project in use
}
```
Further documentation can be found at <https://hexdocs.pm/queermandelbrot>.
## Development
```sh
gleam run -m esgleam/install # Install esbuild dependency
gleam build # Build the project to JS
gleam run -m build # Create bundle in /dist
gleam run -m serve # Start dev webserver on part 8000
```

1
dist/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
queermandelbrot.js

10
dist/index.html vendored Normal file
View file

@ -0,0 +1,10 @@
<!DOCTYPE html>
<html>
<head>
<title>Queer Mandelbrot</title>
</head>
<body>
<canvas id="mandelbrot" width="600" height="400"></canvas>
<script src="./queermandelbrot.js"></script>
</body>
</html>

21
gleam.toml Normal file
View file

@ -0,0 +1,21 @@
name = "queermandelbrot"
version = "1.0.0"
target = "js"
# Fill out these fields if you intend to generate HTML documentation or publish
# your project to the Hex package manager.
#
# description = ""
# licences = ["Apache-2.0"]
# repository = { type = "github", user = "", repo = "" }
# links = [{ title = "Website", href = "" }]
#
# For a full reference of all the available options, you can have a look at
# https://gleam.run/writing-gleam/gleam-toml/.
[dependencies]
gleam_stdlib = ">= 0.34.0 and < 2.0.0"
esgleam = ">= 0.7.0 and < 1.0.0"
[dev-dependencies]
gleeunit = ">= 1.0.0 and < 2.0.0"

15
manifest.toml Normal file
View file

@ -0,0 +1,15 @@
# This file was generated by Gleam
# You typically do not need to edit this file
packages = [
{ name = "esgleam", version = "0.7.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "simplifile"], otp_app = "esgleam", source = "hex", outer_checksum = "8EBF4DB26902950919B046B2283B0E45B5A49B986AAB6AFB06A729EF254321E6" },
{ name = "filepath", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "filepath", source = "hex", outer_checksum = "67A6D15FB39EEB69DD31F8C145BB5A421790581BD6AA14B33D64D5A55DBD6587" },
{ name = "gleam_stdlib", version = "0.45.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "206FCE1A76974AECFC55AEBCD0217D59EDE4E408C016E2CFCCC8FF51278F186E" },
{ name = "gleeunit", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "F7A7228925D3EE7D0813C922E062BFD6D7E9310F0BEE585D3A42F3307E3CFD13" },
{ name = "simplifile", version = "2.2.0", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "0DFABEF7DC7A9E2FF4BB27B108034E60C81BEBFCB7AB816B9E7E18ED4503ACD8" },
]
[requirements]
esgleam = { version = ">= 0.7.0 and < 1.0.0" }
gleam_stdlib = { version = ">= 0.34.0 and < 2.0.0" }
gleeunit = { version = ">= 1.0.0 and < 2.0.0" }

10
src/build.gleam Normal file
View file

@ -0,0 +1,10 @@
import esgleam
pub fn main() {
esgleam.new("./dist/")
|> esgleam.entry("queermandelbrot.gleam")
|> esgleam.kind(esgleam.Script)
|> esgleam.format(esgleam.Iife)
|> esgleam.raw("--outfile=./dist/queermandelbrot.js")
|> esgleam.bundle
}

8
src/canvas.mjs Normal file
View file

@ -0,0 +1,8 @@
export const getContext = (id) =>
document.getElementById(id).getContext("2d");
export const setPixel = (ctx, x, y, color) => {
ctx.fillStyle = color;
ctx.fillRect(x, y, 1, 1);
};

22
src/complex.gleam Normal file
View file

@ -0,0 +1,22 @@
import gleam/float
pub type Complex {
Complex(real: Float, imaginary: Float)
}
pub fn add(x: Complex, y: Complex) -> Complex {
Complex(real: x.real +. y.real, imaginary: x.imaginary +. y.imaginary)
}
pub fn multiply(x: Complex, y: Complex) -> Complex {
Complex(
real: x.real *. y.real -. x.imaginary *. y.imaginary,
imaginary: x.imaginary *. y.real +. x.real *. y.imaginary,
)
}
pub fn absolute(x: Complex) -> Float {
let assert Ok(result) =
float.square_root(x.real *. x.real +. x.imaginary *. x.imaginary)
result
}

116
src/queermandelbrot.gleam Normal file
View file

@ -0,0 +1,116 @@
import gleam/int
import gleam/io
import gleam/list
import complex.{type Complex, Complex, absolute, add, multiply}
type MandelbrotValue {
Converges
Diverges(Int)
}
fn square(x: Complex) -> Complex {
multiply(x, x)
}
fn get_mandelbrot_value(
location: Complex,
threshold: Float,
current: Complex,
iteration: Int,
) -> MandelbrotValue {
case iteration > 100 {
True -> Converges
False -> {
let next = square(current) |> add(location)
case absolute(next) >. threshold {
True -> Diverges(iteration)
False -> get_mandelbrot_value(location, threshold, next, iteration + 1)
}
}
}
}
type ColorScheme {
Rainbow
Trans
Lesbian
}
fn value_to_color(colorscheme: ColorScheme, value: Int) -> String {
case colorscheme {
Rainbow ->
case value {
n if n < 5 -> "#732982"
n if n < 6 -> "#004CFF"
n if n < 7 -> "#008026"
n if n < 9 -> "#FFED00"
n if n < 13 -> "#FF8C00"
_ -> "#E40303"
}
Trans ->
case value {
n if n < 6 -> "#5BCFFB"
n if n < 7 -> "#F5ABB9"
n if n < 9 -> "#FFFFFF"
n if n < 13 -> "#F5ABB9"
_ -> "#5BCFFB"
}
Lesbian ->
case value {
n if n < 5 -> "#D52D00"
n if n < 6 -> "#EF7627"
n if n < 7 -> "#FF9A56"
n if n < 8 -> "#FFFFFF"
n if n < 9 -> "#D162A4"
n if n < 13 -> "#B55690"
_ -> "#A30262"
}
}
}
pub fn main() {
let colorscheme = Lesbian
let ctx = get_context("mandelbrot")
let canvas_width = 600
let canvas_height = 400
let min_x = -2.0
let max_x = 1.0
let min_y = -1.0
let max_y = 1.0
list.range(0, canvas_width - 1)
|> list.each(fn(x) {
list.range(0, canvas_height - 1)
|> list.each(fn(y) {
let location =
Complex(
real: int.to_float(x)
/. int.to_float(canvas_width)
*. { max_x -. min_x }
+. min_x,
imaginary: int.to_float(y)
/. int.to_float(canvas_height)
*. { max_y -. min_y }
+. min_y,
)
let value = get_mandelbrot_value(location, 1000.0, Complex(0.0, 0.0), 0)
case value {
Converges -> set_pixel(ctx, x, y, "#000")
Diverges(value) ->
set_pixel(ctx, x, y, value_to_color(colorscheme, value))
}
})
})
}
type Context2D
@external(javascript, "./canvas.mjs", "getContext")
fn get_context(id: String) -> Context2D
@external(javascript, "./canvas.mjs", "setPixel")
fn set_pixel(ctx: Context2D, x: Int, y: Int, color: String) -> Nil

11
src/serve.gleam Normal file
View file

@ -0,0 +1,11 @@
import esgleam
pub fn main() {
esgleam.new("./dist/")
|> esgleam.entry("queermandelbrot.gleam")
|> esgleam.kind(esgleam.Script)
|> esgleam.format(esgleam.Iife)
|> esgleam.raw("--outfile=./dist/queermandelbrot.js")
|> esgleam.serve("./dist/")
|> esgleam.bundle
}