module Math.OEIS.Internal where
import Control.Arrow (second, (***))
import Data.Char (isSpace, toUpper, toLower)
import Data.List (intercalate, isPrefixOf, foldl')
import Network.HTTP (simpleHTTP, rspBody, rspCode, rqBody, rqHeaders, rqMethod, rqURI, Request(..), RequestMethod(GET))
import Network.URI (parseURI, URI)
import Math.OEIS.Types
baseSearchURI :: String
baseSearchURI :: String
baseSearchURI = String
"http://oeis.org/search?fmt=text&q="
idSearchURI :: String -> String
idSearchURI :: String -> String
idSearchURI String
n = String
baseSearchURI forall a. [a] -> [a] -> [a]
++ String
"id:" forall a. [a] -> [a] -> [a]
++ String
n
seqSearchURI :: SequenceData -> String
seqSearchURI :: SequenceData -> String
seqSearchURI SequenceData
xs = String
baseSearchURI forall a. [a] -> [a] -> [a]
++ forall a. [a] -> [[a]] -> [a]
intercalate String
"," (forall a b. (a -> b) -> [a] -> [b]
map forall a. Show a => a -> String
show SequenceData
xs)
getOEIS :: (a -> String) -> a -> IO [OEISSequence]
getOEIS :: forall a. (a -> String) -> a -> IO [OEISSequence]
getOEIS a -> String
toURI a
key =
case String -> Maybe URI
parseURI (a -> String
toURI a
key) of
Maybe URI
Nothing -> forall (m :: * -> *) a. Monad m => a -> m a
return []
Just URI
uri -> do
Maybe String
mbody <- URI -> IO (Maybe String)
get URI
uri
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] String -> [OEISSequence]
parseOEIS Maybe String
mbody
get :: URI -> IO (Maybe String)
get :: URI -> IO (Maybe String)
get URI
uri = do
Result (Response String)
ersp <- forall ty. HStream ty => Request ty -> IO (Result (Response ty))
simpleHTTP (URI -> Request String
request URI
uri)
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ case Result (Response String)
ersp of
Left ConnError
_ -> forall a. Maybe a
Nothing
Right Response String
rsp
| forall a. Response a -> ResponseCode
rspCode Response String
rsp forall a. Eq a => a -> a -> Bool
== (Int
2,Int
0,Int
0) -> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall a. Response a -> a
rspBody Response String
rsp
| Bool
otherwise -> forall a. Maybe a
Nothing
request :: URI -> Request String
request :: URI -> Request String
request URI
uri = Request
{ rqURI :: URI
rqURI = URI
uri
, rqMethod :: RequestMethod
rqMethod = RequestMethod
GET
, rqHeaders :: [Header]
rqHeaders = []
, rqBody :: String
rqBody = String
""
}
readKeyword :: String -> Keyword
readKeyword :: String -> Keyword
readKeyword = forall a. Read a => String -> a
read forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String
capitalize
capitalize :: String -> String
capitalize :: String -> String
capitalize String
"" = String
""
capitalize (Char
c:String
cs) = Char -> Char
toUpper Char
c forall a. a -> [a] -> [a]
: forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower String
cs
emptyOEIS :: OEISSequence
emptyOEIS :: OEISSequence
emptyOEIS = [String]
-> SequenceData
-> SequenceData
-> String
-> [String]
-> [String]
-> [String]
-> [String]
-> String
-> Int
-> Int
-> [(Language, String)]
-> [String]
-> [String]
-> [Keyword]
-> [String]
-> OEISSequence
OEIS [] [] [] String
"" [] [] [] [] String
"" Int
0 Int
0 [] [] [] [] []
addElement :: (Char, String) -> OEISSequence -> OEISSequence
addElement :: (Char, String) -> OEISSequence -> OEISSequence
addElement (Char
'I', String
x) OEISSequence
c = OEISSequence
c { catalogNums :: [String]
catalogNums = String -> [String]
words String
x }
addElement (Char
t, String
x) OEISSequence
c | Char
t forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` String
"STU" = OEISSequence
c { sequenceData :: SequenceData
sequenceData = SequenceData
nums forall a. [a] -> [a] -> [a]
++ OEISSequence -> SequenceData
sequenceData OEISSequence
c }
where nums :: SequenceData
nums = forall a b. (a -> b) -> [a] -> [b]
map forall a. Read a => String -> a
read forall a b. (a -> b) -> a -> b
$ String -> [String]
csvItems String
x
addElement (Char
t, String
x) OEISSequence
c | Char
t forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` String
"VWX" = OEISSequence
c { signedData :: SequenceData
signedData = SequenceData
nums forall a. [a] -> [a] -> [a]
++ OEISSequence -> SequenceData
signedData OEISSequence
c }
where nums :: SequenceData
nums = forall a b. (a -> b) -> [a] -> [b]
map forall a. Read a => String -> a
read forall a b. (a -> b) -> a -> b
$ String -> [String]
csvItems String
x
addElement (Char
'N', String
x) OEISSequence
c = OEISSequence
c { description :: String
description = String
x }
addElement (Char
'D', String
x) OEISSequence
c = OEISSequence
c { references :: [String]
references = String
x forall a. a -> [a] -> [a]
: OEISSequence -> [String]
references OEISSequence
c }
addElement (Char
'H', String
x) OEISSequence
c = OEISSequence
c { links :: [String]
links = String
x forall a. a -> [a] -> [a]
: OEISSequence -> [String]
links OEISSequence
c }
addElement (Char
'F', String
x) OEISSequence
c = OEISSequence
c { formulas :: [String]
formulas = String
x forall a. a -> [a] -> [a]
: OEISSequence -> [String]
formulas OEISSequence
c }
addElement (Char
'Y', String
x) OEISSequence
c = OEISSequence
c { xrefs :: [String]
xrefs = String
x forall a. a -> [a] -> [a]
: OEISSequence -> [String]
xrefs OEISSequence
c }
addElement (Char
'A', String
x) OEISSequence
c = OEISSequence
c { author :: String
author = String
x }
addElement (Char
'O', String
x) OEISSequence
c = OEISSequence
c { offset :: Int
offset = forall a. Read a => String -> a
read String
o
, firstGT1 :: Int
firstGT1 = forall a. Read a => String -> a
read String
f }
where (String
o,String
f) = forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (d, b) (d, c)
second forall a. [a] -> [a]
tail forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> Bool) -> [a] -> ([a], [a])
span (forall a. Eq a => a -> a -> Bool
/=Char
',') forall a b. (a -> b) -> a -> b
$ String
x
addElement (Char
'p', String
x) OEISSequence
c = OEISSequence
c { programs :: [(Language, String)]
programs = (Language
Maple, String
x) forall a. a -> [a] -> [a]
:
OEISSequence -> [(Language, String)]
programs OEISSequence
c }
addElement (Char
't', String
x) OEISSequence
c = OEISSequence
c { programs :: [(Language, String)]
programs = (Language
Mathematica, String
x) forall a. a -> [a] -> [a]
:
OEISSequence -> [(Language, String)]
programs OEISSequence
c }
addElement (Char
'o', String
x) OEISSequence
c = OEISSequence
c { programs :: [(Language, String)]
programs = (Language
Other, String
x) forall a. a -> [a] -> [a]
:
OEISSequence -> [(Language, String)]
programs OEISSequence
c }
addElement (Char
'E', String
x) OEISSequence
c = OEISSequence
c { extensions :: [String]
extensions = String
x forall a. a -> [a] -> [a]
: OEISSequence -> [String]
extensions OEISSequence
c }
addElement (Char
'e', String
x) OEISSequence
c = OEISSequence
c { examples :: [String]
examples = String
x forall a. a -> [a] -> [a]
: OEISSequence -> [String]
examples OEISSequence
c }
addElement (Char
'K', String
x) OEISSequence
c = OEISSequence
c { keywords :: [Keyword]
keywords = String -> [Keyword]
parseKeywords String
x }
addElement (Char
'C', String
x) OEISSequence
c = OEISSequence
c { comments :: [String]
comments = String
x forall a. a -> [a] -> [a]
: OEISSequence -> [String]
comments OEISSequence
c }
addElement (Char, String)
_ OEISSequence
c = OEISSequence
c
parseOEIS :: String -> [OEISSequence]
parseOEIS :: String -> [OEISSequence]
parseOEIS String
x = if String
"No results." forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf` ([String]
lsforall a. [a] -> Int -> a
!!Int
3)
then []
else [(Char, String)] -> [OEISSequence]
go forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> Bool) -> [a] -> [a]
dropWhile ((forall a. Eq a => a -> a -> Bool
/= Char
'I') forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> a
fst) forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> [(Char, String)]
parseRawOEIS forall a b. (a -> b) -> a -> b
$ [String]
ls'
where ls :: [String]
ls = String -> [String]
lines String
x
ls' :: [String]
ls' = forall a. [a] -> [a]
init forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Int -> [a] -> [a]
drop Int
5 forall a b. (a -> b) -> a -> b
$ [String]
ls
go :: [(Char, String)] -> [OEISSequence]
go [] = []
go ((Char, String)
i:[(Char, String)]
xs) = forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (forall a b c. (a -> b -> c) -> b -> a -> c
flip (Char, String) -> OEISSequence -> OEISSequence
addElement) OEISSequence
emptyOEIS (forall a. [a] -> [a]
reverse ((Char, String)
iforall a. a -> [a] -> [a]
:[(Char, String)]
ys)) forall a. a -> [a] -> [a]
: [(Char, String)] -> [OEISSequence]
go [(Char, String)]
zs
where ([(Char, String)]
ys, [(Char, String)]
zs) = forall a. (a -> Bool) -> [a] -> ([a], [a])
break ((forall a. Eq a => a -> a -> Bool
== Char
'I') forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> a
fst) [(Char, String)]
xs
parseRawOEIS :: [String] -> [(Char, String)]
parseRawOEIS :: [String] -> [(Char, String)]
parseRawOEIS = forall a b. (a -> b) -> [a] -> [b]
map String -> (Char, String)
parseItem forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> [String]
combineConts
parseKeywords :: String -> [Keyword]
parseKeywords :: String -> [Keyword]
parseKeywords = forall a b. (a -> b) -> [a] -> [b]
map String -> Keyword
readKeyword forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
csvItems
csvItems :: String -> [String]
csvItems :: String -> [String]
csvItems String
"" = []
csvItems String
x = String
item forall a. a -> [a] -> [a]
: [String]
others
where (String
item, String
rest) = forall a. (a -> Bool) -> [a] -> ([a], [a])
span (forall a. Eq a => a -> a -> Bool
/=Char
',') String
x
others :: [String]
others = String -> [String]
csvItems forall a b. (a -> b) -> a -> b
$ Char -> String -> String
del Char
',' String
rest
del :: Char -> String -> String
del :: Char -> String -> String
del Char
_ String
"" = String
""
del Char
c (Char
x:String
xs) | Char
cforall a. Eq a => a -> a -> Bool
==Char
x = String
xs
| Bool
otherwise = Char
xforall a. a -> [a] -> [a]
:String
xs
parseItem :: String -> (Char, String)
parseItem :: String -> (Char, String)
parseItem String
s = (Char
c, String
str)
where ( Char
'%':Char
c:String
_ , String
rest) = String -> (String, String)
splitWord String
s
(String
_, String
str ) = if Char
c forall a. Eq a => a -> a -> Bool
== Char
'I' then (String
"", String
rest)
else String -> (String, String)
splitWord String
rest
combineConts :: [String] -> [String]
combineConts :: [String] -> [String]
combineConts (s :: String
s@(Char
'%':Char
_:String
_) : [String]
ss) =
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry (:) forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> [String] -> String
joinConts String
s forall (a :: * -> * -> *) b c b' c'.
Arrow a =>
a b c -> a b' c' -> a (b, b') (c, c')
*** [String] -> [String]
combineConts) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> Bool) -> [a] -> ([a], [a])
break String -> Bool
isItem forall a b. (a -> b) -> a -> b
$ [String]
ss
combineConts [String]
ss = [String]
ss
splitWord :: String -> (String, String)
splitWord :: String -> (String, String)
splitWord = forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (d, b) (d, c)
second String -> String
trimLeft forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> Bool) -> [a] -> ([a], [a])
break Char -> Bool
isSpace
isItem :: String -> Bool
isItem :: String -> Bool
isItem String
x = Bool -> Bool
not (forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
x) Bool -> Bool -> Bool
&& Char
'%' forall a. Eq a => a -> a -> Bool
== forall a. [a] -> a
head String
x
joinConts :: String -> [String] -> String
joinConts :: String -> [String] -> String
joinConts String
s [String]
conts = String
s forall a. [a] -> [a] -> [a]
++ forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap String -> String
trimLeft [String]
conts
trimLeft :: String -> String
trimLeft :: String -> String
trimLeft = forall a. (a -> Bool) -> [a] -> [a]
dropWhile Char -> Bool
isSpace