diff options
Diffstat (limited to 'elm/Lib/Util.elm')
-rw-r--r-- | elm/Lib/Util.elm | 102 |
1 files changed, 74 insertions, 28 deletions
diff --git a/elm/Lib/Util.elm b/elm/Lib/Util.elm index f5954772..edde2e37 100644 --- a/elm/Lib/Util.elm +++ b/elm/Lib/Util.elm @@ -1,9 +1,12 @@ module Lib.Util exposing (..) -import Dict +import Set import Task +import Process import Regex import Lib.Ffi as Ffi +import Gen.Api as GApi +import Gen.Types as GT -- Delete an element from a List delidx : Int -> List a -> List a @@ -28,45 +31,44 @@ hasDuplicates l = step e acc = case acc of Nothing -> Nothing - Just m -> if Dict.member e m then Nothing else Just (Dict.insert e True m) + Just m -> if Set.member e m then Nothing else Just (Set.insert e m) in - case List.foldr step (Just Dict.empty) l of + case List.foldr step (Just Set.empty) l of Nothing -> True Just _ -> False +-- Returns true if list a contains elements also in list b +contains : List comparable -> List comparable -> Bool +contains a b = + let d = Set.fromList b + in List.any (\e -> Set.member e d) a + + -- Haskell's 'lookup' - find an entry in an association list lookup : a -> List (a,b) -> Maybe b lookup n l = List.filter (\(a,_) -> a == n) l |> List.head |> Maybe.map Tuple.second +-- Have to use Process.sleep instead of Task.succeed here, otherwise any +-- subscriptions are not updated. selfCmd : msg -> Cmd msg -selfCmd m = Task.perform (always m) (Task.succeed True) - - --- Based on VNDBUtil::gtintype() -validateGtin : String -> Bool -validateGtin = - let check = String.fromInt - >> String.reverse - >> String.toList - >> List.indexedMap (\i c -> (Char.toCode c - Char.toCode '0') * if modBy 2 i == 0 then 1 else 3) - >> List.sum - inval n = - n < 1000000000 - || (n >= 200000000000 && n < 600000000000) - || (n >= 2000000000000 && n < 3000000000000) - || n >= 9770000000000 - || modBy 10 (check n) /= 0 - in String.filter Char.isDigit >> String.toInt >> Maybe.map (not << inval) >> Maybe.withDefault False - - --- Convert an image ID (e.g. "sf500") into a URL. -imageUrl : String -> String -imageUrl id = +selfCmd m = Task.perform (always m) (Process.sleep 1.0) + + +-- Convert a dir suffix ("" or ".t") and an image ID (e.g. "sf500") into a URL. +imageUrl : String -> String -> String +imageUrl suff id = let num = String.dropLeft 2 id |> String.toInt |> Maybe.withDefault 0 - in Ffi.urlStatic ++ "/" ++ String.left 2 id ++ "/" ++ String.fromInt (modBy 10 (num // 10)) ++ String.fromInt (modBy 10 num) ++ "/" ++ String.fromInt num ++ ".jpg" + in Ffi.urlStatic ++ "/" ++ String.left 2 id ++ suff ++ "/" ++ String.fromInt (modBy 10 (num // 10)) ++ String.fromInt (modBy 10 num) ++ "/" ++ String.fromInt num ++ ".jpg" + +vndbidNum : String -> Int +vndbidNum = String.dropLeft 1 >> String.toInt >> Maybe.withDefault 0 + + +vndbid : Char -> Int -> String +vndbid c n = String.fromChar c ++ String.fromInt n jap_ : Regex.Regex @@ -74,10 +76,54 @@ jap_ = Maybe.withDefault Regex.never (Regex.fromString "[\\u3000-\\u9fff\\uff00- -- Not even close to comprehensive, just excludes a few scripts commonly found on VNDB. nonlatin_ : Regex.Regex -nonlatin_ = Maybe.withDefault Regex.never (Regex.fromString "[\\u3000-\\u9fff\\uff00-\\uff9f\\u0400-\\u04ff\\u1100-\\u11ff\\uac00-\\ud7af]") +nonlatin_ = Maybe.withDefault Regex.never (Regex.fromString "[\\u0400-\\u04ff\\u0600-\\u06ff\\u0e00-\\u0e7f\\u1100-\\u11ff\\u1400-\\u167f\\u3040-\\u3099\\u30a1-\\u30fa\\u3100-\\u9fff\\uac00-\\ud7af\\uff66-\\uffdc\\u{20000}-\\u{323af}]") +-- This regex can't differentiate between Japanese and Chinese, so has a good chance of returning true for Chinese as well. containsJapanese : String -> Bool containsJapanese = Regex.contains jap_ containsNonLatin : String -> Bool containsNonLatin = Regex.contains nonlatin_ + + +-- List of script-languages (i.e. not the generic "Chinese" option), with JA and EN ordered first. +scriptLangs : List (String, String) +scriptLangs = + (List.filter (\(l,_) -> l == "ja") GT.languages) + ++ (List.filter (\(l,_) -> l == "en") GT.languages) + ++ (List.filter (\(l,_) -> l /= "zh" && l /= "en" && l /= "ja") GT.languages) + +-- "Location languages", i.e. generic language without script indicator, again with JA and EN ordered first. +locLangs : List (String, String) +locLangs = + (List.filter (\(l,_) -> l == "ja") GT.languages) + ++ (List.filter (\(l,_) -> l == "en") GT.languages) + ++ (List.filter (\(l,_) -> l /= "zh-Hans" && l /= "zh-Hant" && l /= "en" && l /= "ja") GT.languages) + + +-- Format a release resolution, first argument indicates whether empty string is to be used for "unknown" +resoFmt : Bool -> Int -> Int -> String +resoFmt empty x y = + case (x,y) of + (0,0) -> if empty then "" else "Unknown" + (0,1) -> "Non-standard" + _ -> String.fromInt x ++ "x" ++ String.fromInt y + +-- Inverse of resoFmt +resoParse : Bool -> String -> Maybe (Int, Int) +resoParse empty s = + let t = String.replace "*" "x" s + |> String.replace "×" "x" + |> String.replace " " "" + |> String.replace "\t" "" + |> String.toLower |> String.trim + in + case (t, String.split "x" t) of + ("", _) -> if empty then Just (0,0) else Nothing + ("unknown", _) -> Just (0,0) + ("non-standard", _) -> Just (0,1) + (_, [sx,sy]) -> + case (String.toInt sx, String.toInt sy) of + (Just ix, Just iy) -> if ix < 1 || ix > 32767 || iy < 1 || iy > 32767 then Nothing else Just (ix,iy) + _ -> Nothing + _ -> Nothing |