packages feed

flashblast-0.0.7.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           FlashBlast.VF
import           Formatting
import           Lucid
import           Path
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

withLensesAndProxies [d|
  type FFront        = "front" :-> VF
  type FExtra        = "extra" :-> VFC
  type FBack         = "back"  :-> VF
  type FFrontExtra   = "front-extra" :-> VFC
  type FBackExtra    = "back-extra" :-> VFC
  type FAudio1       = "audio1" :-> VF
  type FAudio2       = "audio2" :-> VF
  type FAudio3       = "audio3" :-> VF
  type FAudio4       = "audio4" :-> VF
  type FAudio5       = "audio5" :-> VF
  type FAudio6       = "audio6" :-> VF
  type FAudio7       = "audio7" :-> VF
  type FAudio8       = "audio8" :-> VF
  type FAudio9       = "audio9" :-> VF
  type FAudio10      = "audio10" :-> VF
  type FAudio11      = "audio11" :-> VF
  type FAudio12      = "audio12" :-> VF
  type FAudio13      = "audio13" :-> VF
  type FAudio14      = "audio14" :-> VF
  type FAudio15      = "audio15" :-> VF
  type FAudio16      = "audio16" :-> VF
  |]

type RBasicNote = Record (FFront : FFrontExtra : FBack : FBackExtra : '[])

type RMinimalNote = Record (FFront : FBack : '[])

type RExcerptNote = Record (FFront : FExtra : FBack : '[] )

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

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

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

renderExcerptNote :: RExcerptNote -> Text
renderExcerptNote (a :*: b :*: c :*: RNil) =
  T.intercalate "\t" [renderVF a, renderVF b, renderVF c]

renderPronunciationNote :: RPronunciationNote -> Text
renderPronunciationNote (a :*: b :*: c :*: d :*: e :*: f :*: g :*: h :*: i :*: j :*: k :*: l :*: m :*: n :*: o :*: p :*: q :*: r :*: RNil)
  = T.intercalate "\t" $ [renderVF a, renderVF b] ++ (renderVF <$> [c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r])

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

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

class RenderVF a where
  renderVF :: a -> Text

instance RenderVF VF where
  renderVF Blank       = ""
  renderVF (RawText x) = x
  renderVF (Image x)   = LT.toStrict . renderText . ungroundedImage $ x
  renderVF (Audio x)   = soundEmbed x
  renderVF (Video x)   = undefined

instance RenderVF VFC where
  renderVF (Single x) = renderVF x
  renderVF (Multi xs) = mconcat $ fmap renderVF xs

genForvos :: Text -> VFC -> [VF] -> RPronunciationNote
genForvos x zs ys' =
  let ys = lpadZipWith (\a _ -> case a of
                          Nothing -> Blank
                          Just a  -> a
                       ) ys' (replicate 16 ())
      ks = 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 RawText x :*: zs :*: ks

class RenderNote f where
  renderNote :: f -> Text

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

instance RenderNote RBasicNote where
  renderNote = renderBasicReversedNote

instance RenderNote RMinimalNote where
  renderNote = renderMinimalNote

instance RenderNote RExcerptNote where
  renderNote = renderExcerptNote

instance RenderNote RPronunciationNote where
  renderNote = renderPronunciationNote

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

class HasMedia f where
  getMedia :: f -> [Path Rel File]

instance HasMedia VF where
  getMedia (Image x) = [x]
  getMedia (Audio x) = [x]
  getMedia (Video x) = [x]
  getMedia _ = []

instance HasMedia VFC where
  getMedia (Single x) = getMedia x
  getMedia (Multi xs) = foldMap getMedia xs

instance HasMedia RBasicNote where
  getMedia f = getMedia (view fFront f) <> getMedia (view fBack f) <> getMedia (view fFrontExtra f) <> getMedia (view fBackExtra f)

instance HasMedia RMinimalNote where
  getMedia f = getMedia (view fFront f) <> getMedia (view fBack f)

instance HasMedia RExcerptNote where
  getMedia f = getMedia (view fExtra f) <> getMedia (view fBack f)

instance HasMedia RPronunciationNote where
  getMedia f = mconcat $ getMedia <$>
                [ view fAudio1 f, view fAudio2 f, view fAudio3 f, view fAudio4 f
                , view fAudio5 f, view fAudio6 f, view fAudio7 f, view fAudio8 f
                , view fAudio9 f, view fAudio10 f, view fAudio11 f, view fAudio12 f
                , view fAudio13 f, view fAudio14 f, view fAudio15 f, view fAudio16 f]