module HarmTrace.Matching.Sim where
import HarmTrace.HAnTree.HAn
import HarmTrace.HAnTree.Tree
import HarmTrace.Base.MusicRep
import HarmTrace.Models.ChordTokens (ChordToken)
class Sim a where
sim :: a -> a -> Int
instance Sim a => Sim (Tree a) where
sim (Node l _ _) (Node l' _ _) = sim l l'
instance Sim a => Sim [a] where
sim [ha] [hb] = sim ha hb
sim (ha:ta) (hb:tb) = sim ha hb + sim ta tb
sim _ _ = 0
instance Sim HAn where
sim (HAn _ a) (HAn _ b) = if a == b then 1 else 0
sim (HAnFunc a) (HAnFunc b) = sim a b
sim (HAnPrep a) (HAnPrep b) = sim a b
sim (HAnTrans a) (HAnTrans b) = sim a b
sim (HAnChord a) (HAnChord b) = sim a b
sim _ _ = 0
instance Sim Int where
sim i j = if i == j then 1 else 0
instance Sim HFunc where
sim (Ton _ _m c _) (Ton _ _m2 c2 _) = if c == c2 then 1 else 0
sim (Dom _ _m c _) (Dom _ _m2 c2 _) = if c == c2 then 1 else 0
sim (Sub _ _m c _) (Sub _ _m2 c2 _) = if c == c2 then 1 else 0
sim P P = 1
sim PD PD = 1
sim PT PT = 1
sim _ _ = 0
instance Sim Mode where
sim MajMode MajMode = 1
sim MinMode MinMode = 1
sim _ _ = 0
instance Sim Trans where
sim (Trit _v sd) (Trit _v2 sd2) = if sd == sd2 then 1 else 0
sim (DimTrit _v sd) (DimTrit _v2 sd2) = if sd == sd2 then 1 else 0
sim (DimTrans _v sd) (DimTrans _v2 sd2) = if sd == sd2 then 1 else 0
sim _ _ =0
instance Sim Prep where
sim (DiatDom _v sd) (DiatDom _v2 sd2) = if sd == sd2 then 3 else 2
sim (SecDom _v sd) (SecDom _v2 sd2) = if sd == sd2 then 3 else 2
sim (SecMin _v sd) (SecMin _v2 sd2) = if sd == sd2 then 3 else 2
sim (SecMin _v sd) (DiatDom _v2 sd2) = if sd == sd2 then 2 else 1
sim (DiatDom _v sd) (SecMin _v2 sd2) = if sd == sd2 then 2 else 1
sim (SecMin _v sd) (SecDom _v2 sd2) = if sd == sd2 then 2 else 1
sim (SecDom _v sd) (SecMin _v2 sd2) = if sd == sd2 then 2 else 1
sim (DiatDom _v sd) (SecDom _v2 sd2) = if sd == sd2 then 2 else 1
sim (SecDom _v sd) (DiatDom _v2 sd2) = if sd == sd2 then 2 else 1
sim _ _ = 0
instance Sim ChordToken where
sim c1 c2 = if c1 == c2 then 2 else 0
maxSim :: Sim a => [a] -> Int
maxSim = foldr (\a b -> sim a a + b) 0
div1 :: Int -> Int -> Int
div1 n c = if n == 1 then 1 else n `div` c