module CodeWorld.Test.AbstractHelpers where


import Data.Tuple.Extra                 (both)
import CodeWorld.Tasks.Picture
import CodeWorld.Tasks.Color            (Color(..))
import CodeWorld.Test.Abstract          (AbstractPicture, toConcretePicture)
import CodeWorld.Test.Rewrite           (normalizeAndAbstract)



{- |
Draw an abstract, hollow square.
-}
someSquare :: AbstractPicture
someSquare :: AbstractPicture
someSquare = Picture -> AbstractPicture
normalizeAndAbstract (Picture -> AbstractPicture) -> Picture -> AbstractPicture
forall a b. (a -> b) -> a -> b
$ Double -> Double -> Picture
rectangle Double
1 Double
1

{- |
Draw an abstract, filled in square.
-}
someSolidSquare :: AbstractPicture
someSolidSquare :: AbstractPicture
someSolidSquare = Picture -> AbstractPicture
normalizeAndAbstract (Picture -> AbstractPicture) -> Picture -> AbstractPicture
forall a b. (a -> b) -> a -> b
$ Double -> Double -> Picture
solidRectangle Double
1 Double
1

{- |
Draw an abstract, hollow rectangle.
This is an alias for `someSquare`.
-}
someRectangle :: AbstractPicture
someRectangle :: AbstractPicture
someRectangle = AbstractPicture
someSquare

{- |
Draw an abstract, filled in rectangle.
This is an alias for `someSolidSquare`.
-}
someSolidRectangle :: AbstractPicture
someSolidRectangle :: AbstractPicture
someSolidRectangle = AbstractPicture
someSolidSquare

{- |
Draw an abstract, hollow rectangle that is wider than tall.
-}
someWideRectangle :: AbstractPicture
someWideRectangle :: AbstractPicture
someWideRectangle = Picture -> AbstractPicture
normalizeAndAbstract (Picture -> AbstractPicture) -> Picture -> AbstractPicture
forall a b. (a -> b) -> a -> b
$ Double -> Double -> Picture
rectangle Double
2 Double
1

{- |
Draw an abstract, filled in rectangle that is wider than tall.
-}
someWideSolidRectangle :: AbstractPicture
someWideSolidRectangle :: AbstractPicture
someWideSolidRectangle = Picture -> AbstractPicture
normalizeAndAbstract (Picture -> AbstractPicture) -> Picture -> AbstractPicture
forall a b. (a -> b) -> a -> b
$ Double -> Double -> Picture
solidRectangle Double
2 Double
1

{- |
Draw an abstract, hollow rectangle that is taller than wide.
-}
someTallRectangle :: AbstractPicture
someTallRectangle :: AbstractPicture
someTallRectangle = Picture -> AbstractPicture
normalizeAndAbstract (Picture -> AbstractPicture) -> Picture -> AbstractPicture
forall a b. (a -> b) -> a -> b
$ Double -> Double -> Picture
rectangle Double
1 Double
2

{- |
Draw an abstract, filled in rectangle that is taller than wide.
-}
someTallSolidRectangle :: AbstractPicture
someTallSolidRectangle :: AbstractPicture
someTallSolidRectangle = Picture -> AbstractPicture
normalizeAndAbstract (Picture -> AbstractPicture) -> Picture -> AbstractPicture
forall a b. (a -> b) -> a -> b
$ Double -> Double -> Picture
solidRectangle Double
1 Double
2

{- |
Draw an abstract, hollow circle.
-}
someCircle :: AbstractPicture
someCircle :: AbstractPicture
someCircle = Picture -> AbstractPicture
normalizeAndAbstract (Picture -> AbstractPicture) -> Picture -> AbstractPicture
forall a b. (a -> b) -> a -> b
$ Double -> Picture
circle Double
1

{- |
Draw an abstract, filled in circle.
-}
someSolidCircle :: AbstractPicture
someSolidCircle :: AbstractPicture
someSolidCircle = Picture -> AbstractPicture
normalizeAndAbstract (Picture -> AbstractPicture) -> Picture -> AbstractPicture
forall a b. (a -> b) -> a -> b
$ Double -> Picture
solidCircle Double
1

{- |
Provide an abstract shape with a wildcard color.
The color will be treated as equal to any other color.
-}
someColor :: AbstractPicture -> AbstractPicture
someColor :: AbstractPicture -> AbstractPicture
someColor = (Picture -> Picture) -> AbstractPicture -> AbstractPicture
reNormalize ((Picture -> Picture) -> AbstractPicture -> AbstractPicture)
-> (Picture -> Picture) -> AbstractPicture -> AbstractPicture
forall a b. (a -> b) -> a -> b
$ Color -> Picture -> Picture
colored Color
AnyColor

{- |
Provide an abstract shape with a specific color.
The color will be treated as equal to any color with *similar* HSL values.
(See 'CodeWorld.Test.isSameColor' for more information)
-}
withColor :: Color -> AbstractPicture -> AbstractPicture
withColor :: Color -> AbstractPicture -> AbstractPicture
withColor Color
color = (Picture -> Picture) -> AbstractPicture -> AbstractPicture
reNormalize ((Picture -> Picture) -> AbstractPicture -> AbstractPicture)
-> (Picture -> Picture) -> AbstractPicture -> AbstractPicture
forall a b. (a -> b) -> a -> b
$ Color -> Picture -> Picture
colored Color
color

{- |
Rotate an abstract shape by up to a quarter turn.
-}
rotatedQuarter :: AbstractPicture -> AbstractPicture
rotatedQuarter :: AbstractPicture -> AbstractPicture
rotatedQuarter = (Picture -> Picture) -> AbstractPicture -> AbstractPicture
reNormalize ((Picture -> Picture) -> AbstractPicture -> AbstractPicture)
-> (Picture -> Picture) -> AbstractPicture -> AbstractPicture
forall a b. (a -> b) -> a -> b
$ Double -> Picture -> Picture
rotated (Double -> Picture -> Picture) -> Double -> Picture -> Picture
forall a b. (a -> b) -> a -> b
$ Double
forall a. Floating a => a
piDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
4

{- |
Rotate an abstract shape by between a quarter and half turn.
-}
rotatedHalf :: AbstractPicture -> AbstractPicture
rotatedHalf :: AbstractPicture -> AbstractPicture
rotatedHalf = (Picture -> Picture) -> AbstractPicture -> AbstractPicture
reNormalize ((Picture -> Picture) -> AbstractPicture -> AbstractPicture)
-> (Picture -> Picture) -> AbstractPicture -> AbstractPicture
forall a b. (a -> b) -> a -> b
$ Double -> Picture -> Picture
rotated (Double -> Picture -> Picture) -> Double -> Picture -> Picture
forall a b. (a -> b) -> a -> b
$ Double
3Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
forall a. Floating a => a
piDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
4

{- |
Rotate an abstract shape by between a half and three quarters turn.
-}
rotatedThreeQuarters :: AbstractPicture -> AbstractPicture
rotatedThreeQuarters :: AbstractPicture -> AbstractPicture
rotatedThreeQuarters = (Picture -> Picture) -> AbstractPicture -> AbstractPicture
reNormalize ((Picture -> Picture) -> AbstractPicture -> AbstractPicture)
-> (Picture -> Picture) -> AbstractPicture -> AbstractPicture
forall a b. (a -> b) -> a -> b
$ Double -> Picture -> Picture
rotated (Double -> Picture -> Picture) -> Double -> Picture -> Picture
forall a b. (a -> b) -> a -> b
$ Double
5Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
forall a. Floating a => a
piDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
4

{- |
Rotate an abstract shape by between a three quarters and up to a full turn.
The full turn itself is excluded.
-}
rotatedUpToFull :: AbstractPicture -> AbstractPicture
rotatedUpToFull :: AbstractPicture -> AbstractPicture
rotatedUpToFull = (Picture -> Picture) -> AbstractPicture -> AbstractPicture
reNormalize ((Picture -> Picture) -> AbstractPicture -> AbstractPicture)
-> (Picture -> Picture) -> AbstractPicture -> AbstractPicture
forall a b. (a -> b) -> a -> b
$ Double -> Picture -> Picture
rotated (Double -> Picture -> Picture) -> Double -> Picture -> Picture
forall a b. (a -> b) -> a -> b
$ Double
7Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
forall a. Floating a => a
piDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
4

{- |
Shrink an abstract shape.
Both directions are scaled an equal amount.
-}
smaller :: AbstractPicture -> AbstractPicture
smaller :: AbstractPicture -> AbstractPicture
smaller = (Picture -> Picture) -> AbstractPicture -> AbstractPicture
reNormalize ((Picture -> Picture) -> AbstractPicture -> AbstractPicture)
-> (Picture -> Picture) -> AbstractPicture -> AbstractPicture
forall a b. (a -> b) -> a -> b
$ Double -> Picture -> Picture
dilated Double
0.5

{- |
Enlarge an abstract shape.
Both directions are scaled an equal amount.
-}
larger :: AbstractPicture -> AbstractPicture
larger :: AbstractPicture -> AbstractPicture
larger = (Picture -> Picture) -> AbstractPicture -> AbstractPicture
reNormalize ((Picture -> Picture) -> AbstractPicture -> AbstractPicture)
-> (Picture -> Picture) -> AbstractPicture -> AbstractPicture
forall a b. (a -> b) -> a -> b
$ Double -> Picture -> Picture
dilated Double
2

{- |
Shrink an abstract shape in X-direction.
The Y-direction is unchanged.
-}
smallerX :: AbstractPicture -> AbstractPicture
smallerX :: AbstractPicture -> AbstractPicture
smallerX = (Picture -> Picture) -> AbstractPicture -> AbstractPicture
reNormalize ((Picture -> Picture) -> AbstractPicture -> AbstractPicture)
-> (Picture -> Picture) -> AbstractPicture -> AbstractPicture
forall a b. (a -> b) -> a -> b
$ Double -> Double -> Picture -> Picture
scaled Double
0.5 Double
1

{- |
Enlarge an abstract shape in X-direction.
The Y-direction is unchanged.
-}
largerX :: AbstractPicture -> AbstractPicture
largerX :: AbstractPicture -> AbstractPicture
largerX = (Picture -> Picture) -> AbstractPicture -> AbstractPicture
reNormalize ((Picture -> Picture) -> AbstractPicture -> AbstractPicture)
-> (Picture -> Picture) -> AbstractPicture -> AbstractPicture
forall a b. (a -> b) -> a -> b
$ Double -> Double -> Picture -> Picture
scaled Double
2 Double
1

{- |
Shrink an abstract shape in Y-direction.
The X-direction is unchanged.
-}
smallerY :: AbstractPicture -> AbstractPicture
smallerY :: AbstractPicture -> AbstractPicture
smallerY = (Picture -> Picture) -> AbstractPicture -> AbstractPicture
reNormalize ((Picture -> Picture) -> AbstractPicture -> AbstractPicture)
-> (Picture -> Picture) -> AbstractPicture -> AbstractPicture
forall a b. (a -> b) -> a -> b
$ Double -> Double -> Picture -> Picture
scaled Double
1 Double
0.5

{- |
Enlarge an abstract shape in Y-direction.
The X-direction is unchanged.
-}
largerY :: AbstractPicture -> AbstractPicture
largerY :: AbstractPicture -> AbstractPicture
largerY = (Picture -> Picture) -> AbstractPicture -> AbstractPicture
reNormalize ((Picture -> Picture) -> AbstractPicture -> AbstractPicture)
-> (Picture -> Picture) -> AbstractPicture -> AbstractPicture
forall a b. (a -> b) -> a -> b
$ Double -> Double -> Picture -> Picture
scaled Double
1 Double
2

{- |
Draw an abstract, open curve with this many segments.
-}
someCurve :: Int -> AbstractPicture
someCurve :: Int -> AbstractPicture
someCurve Int
points = Picture -> AbstractPicture
normalizeAndAbstract (Picture -> AbstractPicture) -> Picture -> AbstractPicture
forall a b. (a -> b) -> a -> b
$
  [Point] -> Picture
curve ([Point] -> Picture) -> [Point] -> Picture
forall a b. (a -> b) -> a -> b
$ Int -> [Point] -> [Point]
forall a. Int -> [a] -> [a]
take (Int
pointsInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) ([Point] -> [Point]) -> [Point] -> [Point]
forall a b. (a -> b) -> a -> b
$ (Point -> Point) -> Point -> [Point]
forall a. (a -> a) -> a -> [a]
iterate ((Double -> Double) -> Point -> Point
forall a b. (a -> b) -> (a, a) -> (b, b)
both (Double -> Double -> Double
forall a. Num a => a -> a -> a
+Double
0.1)) (Double
1,Double
0)

{- |
Draw an abstract, filled in and closed curve with this many segments.
-}
someSolidCurve :: Int -> AbstractPicture
someSolidCurve :: Int -> AbstractPicture
someSolidCurve Int
points = Picture -> AbstractPicture
normalizeAndAbstract (Picture -> AbstractPicture) -> Picture -> AbstractPicture
forall a b. (a -> b) -> a -> b
$
  [Point] -> Picture
solidClosedCurve ([Point] -> Picture) -> [Point] -> Picture
forall a b. (a -> b) -> a -> b
$ Int -> [Point] -> [Point]
forall a. Int -> [a] -> [a]
take (Int
pointsInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) ([Point] -> [Point]) -> [Point] -> [Point]
forall a b. (a -> b) -> a -> b
$ (Point -> Point) -> Point -> [Point]
forall a. (a -> a) -> a -> [a]
iterate ((Double -> Double) -> Point -> Point
forall a b. (a -> b) -> (a, a) -> (b, b)
both (Double -> Double -> Double
forall a. Num a => a -> a -> a
+Double
0.1)) (Double
1,Double
0)

{- |
Compose two abstract pictures.
-}
(.&.) :: AbstractPicture -> AbstractPicture -> AbstractPicture
AbstractPicture
p .&. :: AbstractPicture -> AbstractPicture -> AbstractPicture
.&. AbstractPicture
q = Picture -> AbstractPicture
normalizeAndAbstract (Picture -> AbstractPicture) -> Picture -> AbstractPicture
forall a b. (a -> b) -> a -> b
$ AbstractPicture -> Picture
toConcretePicture AbstractPicture
p Picture -> Picture -> Picture
& AbstractPicture -> Picture
toConcretePicture AbstractPicture
q

reNormalize :: (Picture -> Picture) -> (AbstractPicture -> AbstractPicture)
reNormalize :: (Picture -> Picture) -> AbstractPicture -> AbstractPicture
reNormalize Picture -> Picture
f = Picture -> AbstractPicture
normalizeAndAbstract (Picture -> AbstractPicture)
-> (AbstractPicture -> Picture)
-> AbstractPicture
-> AbstractPicture
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Picture -> Picture
f (Picture -> Picture)
-> (AbstractPicture -> Picture) -> AbstractPicture -> Picture
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AbstractPicture -> Picture
toConcretePicture