diff options
Diffstat (limited to '')
| -rw-r--r-- | app/Main.hs | 103 | ||||
| -rw-r--r-- | app/Util.hs | 16 |
2 files changed, 66 insertions, 53 deletions
diff --git a/app/Main.hs b/app/Main.hs index 0f2e3e7..b6ba540 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -50,12 +50,13 @@ instance FromRecord Platform where Platform <$> v .! 0 <*> v .! 1 <*> - v .! 2 <*> - v .! 3 <*> - (v .! 4 <|> v .! 5) <*> - v .! 6 <*> - v .! 7 <*> - v .! 8 + v .!? 2 <*> + v .!? 3 <*> + (v .!? 4 <|> v .!? 5) <*> + v .!? 6 <*> + v .!? 7 <*> + v .!? 8 + where v .!? b = fromMaybe (pure Nothing) $ fmap parseField (v V.!? b) data Answer = Redirect Text @@ -85,47 +86,21 @@ app :: AppData -> Application app AppData{..} request respond = mkAnswer >>= (respond . toResponse) where mkAnswer :: IO Answer - mkAnswer = case filter (/= mempty) (pathInfo request) of - [] -> pure helptext - ["favicon.ico"] -> pure Notfound - ["cache"] -> do + mkAnswer = case unsnoc (filter (/= mempty) (pathInfo request)) of + Nothing -> pure helptext + Just ([], "favicon.ico") -> pure Notfound + Just ([], "cache") -> do cache <- readTVarIO platformCache now <- getCurrentTime M.toList cache & fmap (\(ril100, (age, _)) -> (T.pack . show) (unRil100 ril100, now `diffUTCTime` age)) & T.unlines & (pure . Plaintext) - [query] - | not (T.any isLower query) && host `elem` ["leitpunkt"] - -> lookupName query leitpunktMap - >>= (`lookupCode` ril100map) - & maybeAnswer Plaintext & pure - | not (T.any isLower query) && host `elem` ["rnv"] - -> lookupCode (RnvId query) rnvMap - & maybeAnswer Plaintext & pure - | not (T.any isLower query) - -> lookupCode (Ril100 query) ril100map - & maybeAnswer Plaintext & pure - | host `elem` ["leitpunkt"] - -> pure $ case findStationName query ril100set of - None -> Notfound - Exact (_,match) -> lookupName match ril100map - >>= (`lookupCode` leitpunktMap) - & maybeAnswer Plaintext - Fuzzy (_,match) -> Redirect (leitpunktBaseUrl <> "/" <> match) - | host `elem` ["rnv"] - -> lookupName query rnvMap - & maybeAnswer (Plaintext . unRnv) & pure - | otherwise - -> pure $ case findStationName query ril100set of - None -> Notfound - Exact (_,match) -> lookupName match ril100map - & maybeAnswer (Plaintext . unRil100) - Fuzzy (_,match) -> Redirect (ril100BaseUrl <> "/" <> match) - [query, segment] | segment `elem` ["gleis", "track", "tracks", "gleise", "platform", "platforms", "fetch"] - -> case queriedRil100 query of + Just (query, segment) | segment `elem` ["gleis", "track", "tracks", "gleise", "platform", "platforms", "fetch"] + -> case queriedRil100 (T.intercalate "/" query) of None -> pure Notfound Fuzzy url -> pure (Redirect (T.intercalate "/" [url, segment])) + Ambiguous possibilities -> pure (listOfCompletions possibilities) Exact ril100 -> do maybeCache <- readTVarIO platformCache <&> M.lookup ril100 now <- getCurrentTime @@ -208,26 +183,51 @@ app AppData{..} request respond = mkAnswer >>= (respond . toResponse) & T.intercalate " " mkAnchor p inner = "<a href=\"https://osm.org/"<>osmType p<>"/"<>osmId p<>"\">"<>inner<>"</a>" - _ -> pure Notfound - queriedRil100 :: Text -> MatchResult Ril100 Text - queriedRil100 query = if + Just _ | not (T.any isLower query) && host `elem` ["leitpunkt"] -> lookupName query leitpunktMap - & maybe None Exact + >>= (`lookupCode` ril100map) + & maybeAnswer Plaintext & pure + | not (T.any isLower query) && host `elem` ["rnv"] + -> lookupCode (RnvId query) rnvMap + & maybeAnswer Plaintext & pure | not (T.any isLower query) - -> Exact (Ril100 query) + -> lookupCode (Ril100 query) ril100map + & maybeAnswer Plaintext & pure | host `elem` ["leitpunkt"] - -> case findStationName query ril100set of - None -> None + -> pure $ case findStationName query ril100set of + None -> Notfound + Ambiguous possibilities -> listOfLinks leitpunktBaseUrl possibilities + Exact (_,match) -> lookupName match ril100map + >>= (`lookupCode` leitpunktMap) + & maybeAnswer Plaintext + Fuzzy (_,match) -> Redirect (leitpunktBaseUrl <> "/" <> match) + | host `elem` ["rnv"] + -> lookupName query rnvMap + & maybeAnswer (Plaintext . unRnv) & pure + | otherwise + -> pure $ case findStationName query ril100set of + None -> Notfound + Ambiguous possibilities -> listOfLinks ril100BaseUrl possibilities Exact (_,match) -> lookupName match ril100map + & maybeAnswer (Plaintext . unRil100) + Fuzzy (_,match) -> Redirect (ril100BaseUrl <> "/" <> match) + where query = T.intercalate "/" (pathInfo request) + queriedRil100 :: Text -> MatchResult Ril100 Text (Text, Text) + queriedRil100 query = if + | not (T.any isLower query) && host `elem` ["leitpunkt"] + -> lookupName query leitpunktMap & maybe None Exact - Fuzzy (_,match) -> Fuzzy (leitpunktBaseUrl <> "/" <> match) + | not (T.any isLower query) + -> Exact (Ril100 query) | otherwise -> case findStationName query ril100set of None -> None + Ambiguous possibilities -> Ambiguous (fmap (\(_, t) -> (baseUrl <> "/" <> t, t)) possibilities) Exact (_,match) -> lookupName match ril100map & maybe None Exact - Fuzzy (_,match) -> Fuzzy (ril100BaseUrl <> "/" <> match) + Fuzzy (_,match) -> Fuzzy (baseUrl <> "/" <> match) + where baseUrl = if host `elem` ["leitpunkt"] then leitpunktBaseUrl else ril100BaseUrl helptext = Html $ "\ \<pre>\ \ril100 → Name: " <> ril100BaseUrl <> "/RM\n\ @@ -270,6 +270,13 @@ app AppData{..} request respond = mkAnswer >>= (respond . toResponse) , ("x-data-by", "OpenStreetMap Contributors https://www.openstreetmap.org/copyright/") , ("x-sources-at", "https://stuebinm.eu/git/bahnhof.name") ] + listOfCompletions possibilities = possibilities + & fmap (\(href, text) -> "<a href=\"" <> href <> "\">" <> text <> "</a>") + & T.intercalate "<br>" + & Html + listOfLinks baseUrl possibilities = possibilities + & fmap (\(_, t) -> (baseUrl <> "/" <> t, t)) + & listOfCompletions diff --git a/app/Util.hs b/app/Util.hs index 094f229..ee8a5e6 100644 --- a/app/Util.hs +++ b/app/Util.hs @@ -23,9 +23,10 @@ import qualified Data.Vector as V import Text.FuzzyFind (Alignment (score), bestMatch) -data MatchResult a b +data MatchResult a b c = Exact a | Fuzzy b + | Ambiguous [c] | None deriving Show @@ -41,18 +42,22 @@ data DoubleMap code long = DoubleMap , back :: Map long code } -findStationName :: T.Text -> FuzzySet -> MatchResult (Double, Text) (Double, Text) +findStationName :: T.Text -> FuzzySet -> MatchResult (Double, Text) (Double, Text) (Double, Text) findStationName query set = case sorted of [exact] -> Exact exact _ -> case maybeHbf of station:_ -> Fuzzy station _ -> case results of - station:_ -> Fuzzy station - _ -> None + [] -> None + [station] -> Fuzzy station + s1:s2:_ + | fst s1 - fst s2 < 10 -> Ambiguous $ (takeWhile ((> fst s1 - 10) . fst) results) + | otherwise -> Fuzzy s1 where sorted = results & fmap (\(_, match) -> (fromIntegral . maybe 0 score . bestMatch (T.unpack query) $ T.unpack match, match)) & sortOn (Down . fst) + -- check if difference between first two is <10 or such results = find query set maybeHbf = filter (T.isInfixOf "Hbf" . snd) sorted @@ -102,7 +107,8 @@ readData = do putStrLn "Static data ready." let betriebsstellenFiltered = betriebsstellen - & V.filter (\line -> line !! 4 `notElem` ["BUSH", "LGR", "ÜST", "BFT", "ABZW", "BK", "AWAN", "ANST", "LGR"]) + & V.filter (\line -> line !! 4 `notElem` ["BUSH", "LGR", "ÜST", "ABZW", "BK", "AWAN", "ANST", "LGR"] + && line !! 5 `notElem` [ "TrSt" ]) let ril100set = addMany (V.toList (V.map (!! 2) betriebsstellenFiltered)) (emptySet 5 6 False) let ril100map = mkDoubleMap $ fmap (\line -> (Ril100 (line !! 1), line !! 2)) betriebsstellen |
