-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmetar.hs
57 lines (46 loc) · 1.39 KB
/
metar.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import Text.ParserCombinators.ReadP
import Data.Char
import Control.Monad
import Control.Applicative
data Timestamp = Timestamp {day :: Int, hour :: Int, minute :: Int} deriving Show
data WindInfo = WindInfo {dir :: Int, speed :: Int, gusts :: Maybe Int} deriving Show
data Report = Report {station :: String, time :: Timestamp, wind :: WindInfo} deriving Show
metar :: ReadP Report
metar = do
code <- airport
time <- timestamp
wind <- windInfo
return $ Report code time wind
airport :: ReadP String
airport = do
code <- many1 . satisfy $ isUpper
satisfy (==' ')
return code
timestamp :: ReadP Timestamp
timestamp = do
day <- numbers 2
guard $ day `elem` [1..31]
hour <- numbers 2
guard $ hour `elem` [0..23]
minute <- numbers 2
guard $ minute `elem` [0..59]
string "Z "
return $ Timestamp day hour minute
numbers :: Int -> ReadP Int
numbers cnt = fmap read . count cnt . satisfy $ isDigit
windInfo :: ReadP WindInfo
windInfo = do
direction <- numbers 3
speed <- numbers 2 <|> numbers 3
gusts <- option Nothing (fmap Just gust)
unit <- string "KT" <|> string "MPS"
string " "
return $ WindInfo direction (toMPS unit speed) (fmap (toMPS unit) gusts)
toMPS :: String -> Int -> Int
toMPS unit speed = case unit of
"KT" -> speed `div` 2
"MPS" -> speed
gust :: ReadP Int
gust = do
satisfy (== 'G')
numbers 2 <|> numbers 3