packages feed

flashblast-0.0.4.0: src/FlashBlast/Conventions.hs

{-# LANGUAGE TemplateHaskell #-}
{-# OPTIONS_GHC -fno-warn-incomplete-patterns #-}
module FlashBlast.Conventions where

import           Composite.Record
import           Composite.TH
import           Data.Align
import           Dhall            hiding (maybe)
import           Formatting
import           Lucid
import           Path
import           Path.Dhall       ()
import           Path.Utils
import           RIO
import           RIO.List.Partial
import qualified RIO.Text         as T
import qualified RIO.Text.Lazy    as LT
import qualified RIO.Text.Partial as T

data VF = Empty | Raw Text | Images [Path Rel File] | Audio (Path Rel File)
  deriving (Eq, Show ,Generic)

instance FromDhall VF

withLensesAndProxies [d|
  type FFront a     = "front" :-> a
  type FExtra a     = "extra" :-> a
  type FBack a      = "back"  :-> a
  type FFrom a      = "from" :-> a
  type FFromExtra a = "from-extra" :-> a
  type FTo a        = "to" :-> a
  type FToExtra a   = "to-extra" :-> a
  type FAudio1      = "audio1" :-> Maybe (Path Rel File)
  type FAudio2      = "audio2" :-> Maybe (Path Rel File)
  type FAudio3      = "audio3" :-> Maybe (Path Rel File)
  type FAudio4      = "audio4" :-> Maybe (Path Rel File)
  type FAudio5      = "audio5" :-> Maybe (Path Rel File)
  type FAudio6      = "audio6" :-> Maybe (Path Rel File)
  type FAudio7      = "audio7" :-> Maybe (Path Rel File)
  type FAudio8      = "audio8" :-> Maybe (Path Rel File)
  type FAudio9      = "audio9" :-> Maybe (Path Rel File)
  type FAudio10     = "audio10" :-> Maybe (Path Rel File)
  type FAudio11     = "audio11" :-> Maybe (Path Rel File)
  type FAudio12     = "audio12" :-> Maybe (Path Rel File)
  type FAudio13     = "audio13" :-> Maybe (Path Rel File)
  type FAudio14     = "audio14" :-> Maybe (Path Rel File)
  type FAudio15     = "audio15" :-> Maybe (Path Rel File)
  type FAudio16     = "audio16" :-> Maybe (Path Rel File)
  |]

type RBasicNote a b c = Record (FFront a : FExtra b : FBack c : '[])

type RBasicReversedNote a b c d = Record (FFrom a : FFromExtra b : FTo c : FToExtra d : '[])

type RMinimalNote a b = Record (FFrom a : FTo b : '[])

type RMultiAudioNote a b = Record (FFront a : FExtra b : FAudio1 : FAudio2 : FAudio3 : FAudio4 : FAudio5 : FAudio6 : FAudio7 : FAudio8 : FAudio9 : FAudio10 : FAudio11 : FAudio12 : FAudio13 : FAudio14 : FAudio15 : FAudio16 : '[])

type RExcerptNote = RBasicNote Text (Path Rel File) (Path Rel File)

type RForvoNote = RMultiAudioNote Text [Path Rel File]

type RMinimalNoteVF = RMinimalNote VF VF

type RBasicReversedNoteVF = RBasicReversedNote VF VF VF VF

forvoConvention :: MonadThrow m => Text -> Text -> m (Path Rel File)
forvoConvention locale word = parseRelFile . T.unpack $ sformat ("pronunciation_" % stext % "_" % stext % ".mp3") locale (T.replace " " "_" (T.toLower word))

ungroundedImage :: Path Rel File -> Html ()
ungroundedImage x = img_ [src_ $ toFilePathText x]

soundEmbed :: Path Rel File -> Text
soundEmbed = sformat ("[sound:" % stext % "]") . toFilePathText

-- TODO: do this as an interpretation
renderExcerptNote :: RExcerptNote -> Text
renderExcerptNote (a :*: b :*: c :*: RNil) = T.intercalate "\t" [a, LT.toStrict $ renderText $ ungroundedImage (filename b), soundEmbed c]

renderForvoNote :: RForvoNote -> Text
renderForvoNote (a :*: b :*: c :*: d :*: e :*: f :*: g :*: h :*: i :*: j :*: k :*: l :*: m :*: n :*: o :*: p :*: q :*: r :*: RNil)
  = T.intercalate "\t" $ [a, T.intercalate "\n" (LT.toStrict . renderText . ungroundedImage . filename <$> b)] ++ fmap (maybe "" soundEmbed) [c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r]

renderMinimalNoteVF :: RMinimalNoteVF -> Text
renderMinimalNoteVF (a :*: b :*: RNil) = T.intercalate "\t" $ renderVF <$> [a, b]

renderBasicReversedNoteVF :: RBasicReversedNoteVF -> Text
renderBasicReversedNoteVF (a :*: b :*: c :*: d :*: RNil) = T.intercalate "\t" $ renderVF <$> [a,b,c,d]

renderVF :: VF -> Text
renderVF Empty = ""
renderVF (Raw x) = x
renderVF (Images x) = T.intercalate "\n" $ LT.toStrict . renderText . ungroundedImage <$> x
renderVF (Audio x) = soundEmbed x

genForvos :: Text -> [Path Rel File] -> [Path Rel File] -> RForvoNote
genForvos x zs ys' =
  let ys = lpadZipWith (\a _ -> if isJust a then a else Nothing) ys' (replicate 16 ())
      k = ys !! 0 :*: ys !! 1 :*: ys !! 2 :*: ys !! 3 :*: ys !! 4 :*: ys !! 5 :*: ys !! 6 :*: ys !! 7 :*: ys !! 8 :*: ys !! 9 :*: ys !! 10 :*: ys !! 11 :*: ys !! 12 :*: ys !! 13 :*: ys !! 14 :*: ys !! 15 :*: RNil
  in x :*: zs :*: k

class RenderNote f where
  renderNote :: f -> Text

data SomeNote = forall e. RenderNote e => SomeNote e

instance RenderNote RBasicReversedNoteVF where
  renderNote = renderBasicReversedNoteVF

instance RenderNote RMinimalNoteVF where
  renderNote = renderMinimalNoteVF

instance RenderNote RExcerptNote where
  renderNote = renderExcerptNote

instance RenderNote RForvoNote where
  renderNote = renderForvoNote

instance RenderNote SomeNote where
  renderNote (SomeNote e) = renderNote e