module CodeWorld.Test.Animation (
  samplesUntil,
  irregularSamples,
  ) where



{- |
An infinite list of animation sampling points.
The basis is made of irrational square roots, exp(1) and π.
The provided samples should not overlap with
any particular phase a student submitted animation may have.
-}
irregularSamples :: [Double]
irregularSamples :: [Double]
irregularSamples = Double
0 Double -> [Double] -> [Double]
forall a. a -> [a] -> [a]
: (Double -> Double) -> [Double] -> [Double]
forall a b. (a -> b) -> [a] -> [b]
map (Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
5) ([[Double]] -> [Double]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[Double]] -> [Double]) -> [[Double]] -> [Double]
forall a b. (a -> b) -> a -> b
$ ([Double] -> [Double]) -> [Double] -> [[Double]]
forall a. (a -> a) -> a -> [a]
iterate ((Double -> Double) -> [Double] -> [Double]
forall a b. (a -> b) -> [a] -> [b]
map (Double -> Double -> Double
forall a. Num a => a -> a -> a
+Double
3)) [Double]
base)
  where base :: [Double]
base = [Double -> Double
forall a. Floating a => a -> a
sqrt (Double
1Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
5), Double -> Double
forall a. Floating a => a -> a
sqrt (Double
1Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
2), Double -> Double
forall a. Floating a => a -> a
sqrt Double
1.2, Double -> Double
forall a. Floating a => a -> a
sqrt Double
2, Double -> Double
forall a. Floating a => a -> a
sqrt Double
3, Double -> Double
forall a. Floating a => a -> a
sqrt Double
5, Double -> Double
forall a. Floating a => a -> a
exp Double
1, Double
forall a. Floating a => a
pi]


{- |
Generates irregular sample frames starting from 0 with given step size and cutoff point.
The step size is only an approximation, since the generated values are based on irrational numbers.
-}
samplesUntil :: Double -> Double -> [Double]
samplesUntil :: Double -> Double -> [Double]
samplesUntil Double
stepSize Double
cutOff = [Double] -> [Double]
fuzzyNub ([Double] -> [Double]) -> [Double] -> [Double]
forall a b. (a -> b) -> a -> b
$ (Double -> Bool) -> [Double] -> [Double]
forall a. (a -> Bool) -> [a] -> [a]
filter (Double -> [Double] -> Bool
`fuzzyElem` [Double
0, Double
stepSize .. Double
cutOff]) [Double]
rawSamples
  where
    rawSamples :: [Double]
rawSamples = (Double -> Bool) -> [Double] -> [Double]
forall a. (a -> Bool) -> [a] -> [a]
takeWhile (Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<= Double
cutOffDouble -> Double -> Double
forall a. Num a => a -> a -> a
+Double
epsilon) [Double]
irregularSamples

    fuzzyElem :: Double -> [Double] -> Bool
fuzzyElem Double
_ []     = Bool
False
    fuzzyElem Double
x (Double
y:[Double]
xs) = Double -> Double
forall a. Num a => a -> a
abs (Double
xDouble -> Double -> Double
forall a. Num a => a -> a -> a
-Double
y) Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
epsilon Bool -> Bool -> Bool
|| Double -> [Double] -> Bool
fuzzyElem Double
x [Double]
xs

    fuzzyNub :: [Double] -> [Double]
fuzzyNub (Double
x:Double
y:[Double]
xs) = Double
x Double -> [Double] -> [Double]
forall a. a -> [a] -> [a]
: [Double] -> [Double]
fuzzyNub (if Double -> Double
forall a. Num a => a -> a
abs (Double
xDouble -> Double -> Double
forall a. Num a => a -> a -> a
-Double
y)Double -> Double -> Double
forall a. Num a => a -> a -> a
+Double
epsilon Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
stepSize then [Double]
xs else Double
yDouble -> [Double] -> [Double]
forall a. a -> [a] -> [a]
:[Double]
xs)
    fuzzyNub [Double]
xs = [Double]
xs

    epsilon :: Double
epsilon = Double
0.05