Write up initial Cow DSL.
This commit is contained in:
		
						commit
						321df82944
					
				
							
								
								
									
										99
									
								
								src/Cdl/Cow.hs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								src/Cdl/Cow.hs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,99 @@ | ||||
| module Cdl.Cow where | ||||
| import Control.Monad.State | ||||
| import Data.Fixed | ||||
| import Data.List | ||||
| 
 | ||||
| data Coord = Coord | ||||
|     { longitude :: Float | ||||
|     , latitude :: Float | ||||
|     } | ||||
| 
 | ||||
| data CowState = CowState | ||||
|     { id :: Int | ||||
|     , samplingFrequency :: Float | ||||
|     , movementSpeed :: Float | ||||
|     , movementDirection :: Float | ||||
|     , position :: Coord | ||||
|     , time :: Float | ||||
|     , dataPoints :: [Coord] | ||||
|     } | ||||
| 
 | ||||
| type CowBehavior = State CowState | ||||
| 
 | ||||
| type Collar = (Int, Float, Coord, CowBehavior ()) | ||||
| type DataPoint = (Int, Coord) | ||||
| 
 | ||||
| emitPoint :: Coord -> CowBehavior () | ||||
| emitPoint c = modify (\s -> s { dataPoints = c : dataPoints s }) | ||||
| 
 | ||||
| setPosition :: Coord -> CowBehavior () | ||||
| setPosition c = modify (\s -> s { position = c }) | ||||
| 
 | ||||
| setDirection :: Float -> CowBehavior () | ||||
| setDirection d = modify (\s -> s { movementDirection = d }) | ||||
| 
 | ||||
| increaseTime :: Float -> CowBehavior () | ||||
| increaseTime t = modify (\s -> s { time = time s + t }) | ||||
| 
 | ||||
| repeatUntil :: (CowState -> Bool) -> CowBehavior a -> CowBehavior a | ||||
| repeatUntil p m = ((,) <$> m <*> gets p) >>= (\(a,b) -> if b then return a else m) | ||||
| 
 | ||||
| repeatTimes :: Int -> CowBehavior a -> CowBehavior () | ||||
| repeatTimes n m = sequence_ $ replicate n m | ||||
| 
 | ||||
| addOffset :: (Float, Float) -> Coord -> Coord | ||||
| addOffset (x, y) c = Coord (longitude c + longitudeDelta) (latitude c + latitudeDelta) | ||||
|     where | ||||
|         latitudeDelta = y / 111111 | ||||
|         longitudeDelta = x / (111111 * cos (latitude c)) | ||||
| 
 | ||||
| samplingDeltas :: Float -> CowBehavior [Float] | ||||
| samplingDeltas t = do | ||||
|     currentTime <- gets time | ||||
|     frequency <- gets samplingFrequency | ||||
|     let firstDelta = (frequency * fromIntegral (ceiling (currentTime/frequency))) - currentTime | ||||
|     return $ takeWhile (< t) [firstDelta + frequency*i | i <- [0..]] | ||||
| 
 | ||||
| move :: Float -> CowBehavior () | ||||
| move d = do | ||||
|     speed <- gets movementSpeed | ||||
|     dir <- gets movementDirection | ||||
|     pos <- gets position | ||||
|     let movementTime = d/speed | ||||
|     deltas <- samplingDeltas movementTime | ||||
|     let coords = map (\d -> addOffset (speed * d * cos dir, speed * d * sin dir) pos) deltas | ||||
|     let finalPos = addOffset (d * cos dir, d * sin dir) pos | ||||
|     mapM emitPoint coords | ||||
|     increaseTime movementTime | ||||
|     setPosition finalPos | ||||
| 
 | ||||
| turn :: Float -> CowBehavior () | ||||
| turn a = do | ||||
|     dir <- gets movementDirection | ||||
|     let newDir = dir + (a/180 * pi) | ||||
|     setDirection (newDir `mod'` (2*pi)) | ||||
| 
 | ||||
| wait :: Float -> CowBehavior () | ||||
| wait t = do | ||||
|     deltas <- samplingDeltas t | ||||
|     pos <- gets position | ||||
|     mapM (const $ emitPoint pos) deltas | ||||
|     increaseTime t | ||||
| 
 | ||||
| runCow :: Float -> Collar -> [DataPoint] | ||||
| runCow f (id, speed, pos, behavior) = zip (cycle [id]) coords | ||||
|     where | ||||
|         coords = reverse (position finalState : dataPoints finalState) | ||||
|         finalState = snd $ runState behavior initialState | ||||
|         initialState = CowState | ||||
|             { Cdl.Cow.id = id | ||||
|             , samplingFrequency = f | ||||
|             , movementSpeed = speed | ||||
|             , movementDirection = 0 | ||||
|             , position = pos | ||||
|             , time = 0 | ||||
|             , dataPoints = [] | ||||
|             } | ||||
| 
 | ||||
| runCows :: Float -> [Collar] -> [[DataPoint]] | ||||
| runCows f cs = transpose $ map (runCow f) $ cs | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user