commit 4211fc3074c03bfb3832bcd52382e5d4c394a673 Author: sigmasternchen Date: Sat Dec 7 22:15:59 2024 +0100 first commit diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..be97e7a --- /dev/null +++ b/.github/workflows/test.yml @@ -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 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..599be4e --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.beam +*.ez +/build +erl_crash.dump diff --git a/README.md b/README.md new file mode 100644 index 0000000..8343828 --- /dev/null +++ b/README.md @@ -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 . + +## 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 +``` diff --git a/dist/.gitignore b/dist/.gitignore new file mode 100644 index 0000000..66fb253 --- /dev/null +++ b/dist/.gitignore @@ -0,0 +1 @@ +queermandelbrot.js diff --git a/dist/index.html b/dist/index.html new file mode 100644 index 0000000..2efed2a --- /dev/null +++ b/dist/index.html @@ -0,0 +1,10 @@ + + + + Queer Mandelbrot + + + + + + diff --git a/gleam.toml b/gleam.toml new file mode 100644 index 0000000..cb4c3fb --- /dev/null +++ b/gleam.toml @@ -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" diff --git a/manifest.toml b/manifest.toml new file mode 100644 index 0000000..05aa327 --- /dev/null +++ b/manifest.toml @@ -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" } diff --git a/src/build.gleam b/src/build.gleam new file mode 100644 index 0000000..2756c39 --- /dev/null +++ b/src/build.gleam @@ -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 +} diff --git a/src/canvas.mjs b/src/canvas.mjs new file mode 100644 index 0000000..9d7af0c --- /dev/null +++ b/src/canvas.mjs @@ -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); +}; diff --git a/src/complex.gleam b/src/complex.gleam new file mode 100644 index 0000000..4ed5601 --- /dev/null +++ b/src/complex.gleam @@ -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 +} diff --git a/src/queermandelbrot.gleam b/src/queermandelbrot.gleam new file mode 100644 index 0000000..650a646 --- /dev/null +++ b/src/queermandelbrot.gleam @@ -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 diff --git a/src/serve.gleam b/src/serve.gleam new file mode 100644 index 0000000..50953b6 --- /dev/null +++ b/src/serve.gleam @@ -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 +}