commit 60a0cc74a33aaad215d3dde735d7aedd77d5c359 Author: Nathan McRae Date: Mon Jul 14 18:21:18 2025 -0700 Add initial files diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..30efe19 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +/bower_components/ +/node_modules/ +/.pulp-cache/ +/output/ +/generated-docs/ +/.psc-package/ +/.psc* +/.purs* +/.psa* +/.spago diff --git a/packages.dhall b/packages.dhall new file mode 100644 index 0000000..cd89c9c --- /dev/null +++ b/packages.dhall @@ -0,0 +1,105 @@ +{- +Welcome to your new Dhall package-set! + +Below are instructions for how to edit this file for most use +cases, so that you don't need to know Dhall to use it. + +## Use Cases + +Most will want to do one or both of these options: +1. Override/Patch a package's dependency +2. Add a package not already in the default package set + +This file will continue to work whether you use one or both options. +Instructions for each option are explained below. + +### Overriding/Patching a package + +Purpose: +- Change a package's dependency to a newer/older release than the + default package set's release +- Use your own modified version of some dependency that may + include new API, changed API, removed API by + using your custom git repo of the library rather than + the package set's repo + +Syntax: +where `entityName` is one of the following: +- dependencies +- repo +- version +------------------------------- +let upstream = -- +in upstream + with packageName.entityName = "new value" +------------------------------- + +Example: +------------------------------- +let upstream = -- +in upstream + with halogen.version = "master" + with halogen.repo = "https://example.com/path/to/git/repo.git" + + with halogen-vdom.version = "v4.0.0" + with halogen-vdom.dependencies = [ "extra-dependency" ] # halogen-vdom.dependencies +------------------------------- + +### Additions + +Purpose: +- Add packages that aren't already included in the default package set + +Syntax: +where `` is: +- a tag (i.e. "v4.0.0") +- a branch (i.e. "master") +- commit hash (i.e. "701f3e44aafb1a6459281714858fadf2c4c2a977") +------------------------------- +let upstream = -- +in upstream + with new-package-name = + { dependencies = + [ "dependency1" + , "dependency2" + ] + , repo = + "https://example.com/path/to/git/repo.git" + , version = + "" + } +------------------------------- + +Example: +------------------------------- +let upstream = -- +in upstream + with benchotron = + { dependencies = + [ "arrays" + , "exists" + , "profunctor" + , "strings" + , "quickcheck" + , "lcg" + , "transformers" + , "foldable-traversable" + , "exceptions" + , "node-fs" + , "node-buffer" + , "node-readline" + , "datetime" + , "now" + ] + , repo = + "https://github.com/hdgarrood/purescript-benchotron.git" + , version = + "v7.0.0" + } +------------------------------- +-} +let upstream = + https://github.com/purescript/package-sets/releases/download/psc-0.15.15-20250622/packages.dhall + sha256:2d1b91988594be9ec99cee86ca4f0a85efe36d51fd24cb1305b27a9611406e13 + +in upstream diff --git a/spago.dhall b/spago.dhall new file mode 100644 index 0000000..87c8b13 --- /dev/null +++ b/spago.dhall @@ -0,0 +1,26 @@ +{- +Welcome to a Spago project! +You can edit this file as you like. + +Need help? See the following resources: +- Spago documentation: https://github.com/purescript/spago +- Dhall language tour: https://docs.dhall-lang.org/tutorials/Language-Tour.html + +When creating a new Spago project, you can use +`spago init --no-comments` or `spago init -C` +to generate this file without the comments in this block. +-} +{ name = "my-project" +, dependencies = + [ "arrays" + , "console" + , "effect" + , "integers" + , "lists" + , "numbers" + , "prelude" + , "tuples" + ] +, packages = ./packages.dhall +, sources = [ "src/**/*.purs", "test/**/*.purs" ] +} diff --git a/src/Main.purs b/src/Main.purs new file mode 100644 index 0000000..11fc281 --- /dev/null +++ b/src/Main.purs @@ -0,0 +1,131 @@ +module Main where + +import Prelude (discard, class Monoid, class Semigroup, Unit, ($), (<>), (>>>)) + +import Data.Array (range, cons) +import Data.Field (div) +import Data.Functor (map) +import Data.Int (toNumber) +import Data.Number (cos, pi, sin) +import Data.Number.Format (toString) +import Data.List (fold) +import Data.Ord ((<)) +import Data.Ring (add, mul, negate, sub) +import Data.Tuple.Nested (Tuple3, tuple3, get1, get2, get3) +import Effect (Effect) +import Effect.Console (log) + +type Point = + { x :: Number + , y :: Number + } + +type Line = + { start :: Point + , end :: Point + } + +-- TODO: How to do more normal math expressions? +rotate :: Number -> Point -> Point +rotate angle { x: x, y: y} = { + x: sub (mul (cos angle) x) (mul (sin angle) y), + y: add (mul (sin angle) x) (mul (cos angle) y) +} + +transform :: Number -> Number -> Number -> Point -> Point +transform scale xOffset yOffset { x: x, y: y} = { + x: (add (mul scale x) xOffset), + y: (add (mul scale y) yOffset) +} + +rotateLine :: Number -> Line -> Line +rotateLine angle { start: p1, end: p2} = { + start: rotate angle p1, + end: rotate angle p2 +} + +transformLine :: Number -> Number -> Number -> Line -> Line +transformLine scale xOffset yOffset { start: start, end: end } = { +start : t start, +end : t end +} + where t = transform scale xOffset yOffset + +-- How to handle the different coordinate systems? +-- These things should be generated in the basic coordinate system +-- * ticks via generateTicks +-- * axis labels +-- * axis lines +-- There should be a transform function that these should be passed through directly after generation + +newtype XMLFragment = XMLFragment String + +derive newtype instance xmlFragmentSemiGroup :: Semigroup XMLFragment +derive newtype instance xmlFragmentMonoid :: Monoid XMLFragment + +-- TODO: Add style configuration +svgLine :: Line -> XMLFragment +svgLine { start: {x: x1, y: y1}, end: {x: x2, y: y2} } = + XMLFragment $ """ (toString x1) <> "," <> (toString y1) <> " " <> (toString x2) <> "," <> (toString y2) <> "\"/>" + +-- TODO: Make axis tick size a parameter +getTick :: Number -> Int -> Int -> Line +getTick scale numTicks tickI = + {start: {x: x, y: negate (add 0.5 (div 5.0 scale))}, end: {x: x, y: y}} + where + x = (sub (div (mul 2.0 (mul (sin (div pi 3.0)) (toNumber tickI))) (toNumber numTicks)) (sin (div pi 3.0))) + y = if tickI < (div numTicks 2) + then (add 1.0 (mul x (div 1.5 (sin (div pi 3.0))))) + else (sub 1.0 (mul x (div 1.5 (sin (div pi 3.0))))) + +getTicks :: Number -> Number -> Int -> Tuple3 (Array Line) (Array Line) (Array Line) +getTicks scale angle numTicks = --tuple3 [] [] [] + tuple3 axis1Lines axis2Lines axis3Lines + where + foo = map (getTick scale numTicks) (range 0 numTicks) + axis1Lines = map (rotateLine angle) foo + axis2Lines = map (rotateLine (mul 2.0 (div pi 3.0))) axis1Lines + axis3Lines = map (rotateLine (mul 2.0 (div pi 3.0))) axis2Lines + +-- There's probably a better way to do this +unfragment :: XMLFragment -> String +unfragment (XMLFragment frag) = frag + +ternaryGraphSvg :: Array XMLFragment -> String +ternaryGraphSvg fragments = """ + +""" <> unfragment (fold fragments) <> "" + +axesPoints :: Number -> Array Point +axesPoints angle = [ + rotate angle { x: 0, y: 1 }, + rotate angle { x: (negate (sin (mul 2.0 (div pi 3.0)))), y : (negate 0.5)}, + rotate angle { x: (sin (mul (div pi 3.0))), y: (negate 0.5) } +] + +ternaryGraph :: Number -> Number -> Number -> Int -> String +ternaryGraph scale xOffset yOffset numTicks = ternaryGraphSvg [tickLinesSvg, axesPathSvg, axisTitleSvg, tickLabelsSvg] + where + axisTickLines = getTicks scale pi numTicks + axis1TickLines = get1 axisTickLines + axis2TickLines = get2 axisTickLines + axis3TickLines = get3 axisTickLines + tickLines = (cons axis1TickLines (cons axis2TickLines axis3TickLines)) + transformMyLine = transformLine scale xOffset yOffset + tickLinesSvg = fold $ map (svgLine >>> transformMyLine) tickLines + + axesPathSvg = + +main :: Effect Unit +main = do + log $ ternaryGraphSvg [XMLFragment "", XMLFragment ""] + log $ toString $ toNumber (div 5 3) diff --git a/test/Main.purs b/test/Main.purs new file mode 100644 index 0000000..f91f98c --- /dev/null +++ b/test/Main.purs @@ -0,0 +1,11 @@ +module Test.Main where + +import Prelude + +import Effect (Effect) +import Effect.Class.Console (log) + +main :: Effect Unit +main = do + log "🍝" + log "You should add some tests."