{-
	Copyright (C) 2018 Dr. Alistair Ward

	This file is part of BishBosh.

	BishBosh is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	BishBosh is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with BishBosh.  If not, see <http://www.gnu.org/licenses/>.
-}
{- |
 [@AUTHOR@]	Dr. Alistair Ward

 [@DESCRIPTION@]

	* Defines the weight associated with some /criterion/.

	* Each weighting is constrained to the unsigned /closed unit-interval/; negative values aren't permitted.

	* If the /criterion/ is considered unimportant, then its weight can be set to '0', whilst concepts of great significance can be set to '1'.

 [@CAVEAT@]

	* While this data-type could implement the classes 'Functor', 'Num', 'Fractional' & 'Real', these interfaces allow one to construct invalid instances.
-}

module BishBosh.Attribute.CriterionWeight(
-- * Types
-- ** Data-types
	CriterionWeight(
--		MkCriterionWeight,
		deconstruct
	),
-- * Functions
-- ** Constructor
	mkCriterionWeight
) where

import qualified	BishBosh.Data.Exception		as Data.Exception
import qualified	BishBosh.Data.Num		as Data.Num
import qualified	BishBosh.Text.ShowList		as Text.ShowList
import qualified	Control.DeepSeq
import qualified	Control.Exception
import qualified	Data.Default
import qualified	Text.XML.HXT.Arrow.Pickle	as HXT

-- | Quantifies the relative significance, of a criterion; the larger the value, the more significant the criterion is relative to other criteria.
newtype CriterionWeight criterionWeight	= MkCriterionWeight {
	CriterionWeight criterionWeight -> criterionWeight
deconstruct	:: criterionWeight
} deriving (CriterionWeight criterionWeight
-> CriterionWeight criterionWeight -> Bool
(CriterionWeight criterionWeight
 -> CriterionWeight criterionWeight -> Bool)
-> (CriterionWeight criterionWeight
    -> CriterionWeight criterionWeight -> Bool)
-> Eq (CriterionWeight criterionWeight)
forall criterionWeight.
Eq criterionWeight =>
CriterionWeight criterionWeight
-> CriterionWeight criterionWeight -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CriterionWeight criterionWeight
-> CriterionWeight criterionWeight -> Bool
$c/= :: forall criterionWeight.
Eq criterionWeight =>
CriterionWeight criterionWeight
-> CriterionWeight criterionWeight -> Bool
== :: CriterionWeight criterionWeight
-> CriterionWeight criterionWeight -> Bool
$c== :: forall criterionWeight.
Eq criterionWeight =>
CriterionWeight criterionWeight
-> CriterionWeight criterionWeight -> Bool
Eq, Eq (CriterionWeight criterionWeight)
Eq (CriterionWeight criterionWeight)
-> (CriterionWeight criterionWeight
    -> CriterionWeight criterionWeight -> Ordering)
-> (CriterionWeight criterionWeight
    -> CriterionWeight criterionWeight -> Bool)
-> (CriterionWeight criterionWeight
    -> CriterionWeight criterionWeight -> Bool)
-> (CriterionWeight criterionWeight
    -> CriterionWeight criterionWeight -> Bool)
-> (CriterionWeight criterionWeight
    -> CriterionWeight criterionWeight -> Bool)
-> (CriterionWeight criterionWeight
    -> CriterionWeight criterionWeight
    -> CriterionWeight criterionWeight)
-> (CriterionWeight criterionWeight
    -> CriterionWeight criterionWeight
    -> CriterionWeight criterionWeight)
-> Ord (CriterionWeight criterionWeight)
CriterionWeight criterionWeight
-> CriterionWeight criterionWeight -> Bool
CriterionWeight criterionWeight
-> CriterionWeight criterionWeight -> Ordering
CriterionWeight criterionWeight
-> CriterionWeight criterionWeight
-> CriterionWeight criterionWeight
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall criterionWeight.
Ord criterionWeight =>
Eq (CriterionWeight criterionWeight)
forall criterionWeight.
Ord criterionWeight =>
CriterionWeight criterionWeight
-> CriterionWeight criterionWeight -> Bool
forall criterionWeight.
Ord criterionWeight =>
CriterionWeight criterionWeight
-> CriterionWeight criterionWeight -> Ordering
forall criterionWeight.
Ord criterionWeight =>
CriterionWeight criterionWeight
-> CriterionWeight criterionWeight
-> CriterionWeight criterionWeight
min :: CriterionWeight criterionWeight
-> CriterionWeight criterionWeight
-> CriterionWeight criterionWeight
$cmin :: forall criterionWeight.
Ord criterionWeight =>
CriterionWeight criterionWeight
-> CriterionWeight criterionWeight
-> CriterionWeight criterionWeight
max :: CriterionWeight criterionWeight
-> CriterionWeight criterionWeight
-> CriterionWeight criterionWeight
$cmax :: forall criterionWeight.
Ord criterionWeight =>
CriterionWeight criterionWeight
-> CriterionWeight criterionWeight
-> CriterionWeight criterionWeight
>= :: CriterionWeight criterionWeight
-> CriterionWeight criterionWeight -> Bool
$c>= :: forall criterionWeight.
Ord criterionWeight =>
CriterionWeight criterionWeight
-> CriterionWeight criterionWeight -> Bool
> :: CriterionWeight criterionWeight
-> CriterionWeight criterionWeight -> Bool
$c> :: forall criterionWeight.
Ord criterionWeight =>
CriterionWeight criterionWeight
-> CriterionWeight criterionWeight -> Bool
<= :: CriterionWeight criterionWeight
-> CriterionWeight criterionWeight -> Bool
$c<= :: forall criterionWeight.
Ord criterionWeight =>
CriterionWeight criterionWeight
-> CriterionWeight criterionWeight -> Bool
< :: CriterionWeight criterionWeight
-> CriterionWeight criterionWeight -> Bool
$c< :: forall criterionWeight.
Ord criterionWeight =>
CriterionWeight criterionWeight
-> CriterionWeight criterionWeight -> Bool
compare :: CriterionWeight criterionWeight
-> CriterionWeight criterionWeight -> Ordering
$ccompare :: forall criterionWeight.
Ord criterionWeight =>
CriterionWeight criterionWeight
-> CriterionWeight criterionWeight -> Ordering
$cp1Ord :: forall criterionWeight.
Ord criterionWeight =>
Eq (CriterionWeight criterionWeight)
Ord)

instance Show criterionWeight => Show (CriterionWeight criterionWeight) where
	showsPrec :: Int -> CriterionWeight criterionWeight -> ShowS
showsPrec Int
_ (MkCriterionWeight criterionWeight
criterionWeight)	= criterionWeight -> ShowS
forall a. Show a => a -> ShowS
shows criterionWeight
criterionWeight

instance Num criterionWeight => Bounded (CriterionWeight criterionWeight) where
	minBound :: CriterionWeight criterionWeight
minBound	= criterionWeight -> CriterionWeight criterionWeight
forall criterionWeight.
criterionWeight -> CriterionWeight criterionWeight
MkCriterionWeight criterionWeight
0
	maxBound :: CriterionWeight criterionWeight
maxBound	= criterionWeight -> CriterionWeight criterionWeight
forall criterionWeight.
criterionWeight -> CriterionWeight criterionWeight
MkCriterionWeight criterionWeight
1

instance Num criterionWeight => Data.Default.Default (CriterionWeight criterionWeight) where
	def :: CriterionWeight criterionWeight
def	= CriterionWeight criterionWeight
forall a. Bounded a => a
minBound

instance Control.DeepSeq.NFData criterionWeight => Control.DeepSeq.NFData (CriterionWeight criterionWeight) where
	rnf :: CriterionWeight criterionWeight -> ()
rnf (MkCriterionWeight criterionWeight
criterionWeight)	= criterionWeight -> ()
forall a. NFData a => a -> ()
Control.DeepSeq.rnf criterionWeight
criterionWeight

instance (
	HXT.XmlPickler	criterionWeight,
	Num		criterionWeight,
	Ord		criterionWeight,
	Show		criterionWeight
 ) => HXT.XmlPickler (CriterionWeight criterionWeight) where
	xpickle :: PU (CriterionWeight criterionWeight)
xpickle	= (criterionWeight -> CriterionWeight criterionWeight,
 CriterionWeight criterionWeight -> criterionWeight)
-> PU criterionWeight -> PU (CriterionWeight criterionWeight)
forall a b. (a -> b, b -> a) -> PU a -> PU b
HXT.xpWrap (criterionWeight -> CriterionWeight criterionWeight
forall criterionWeight.
(Num criterionWeight, Ord criterionWeight, Show criterionWeight) =>
criterionWeight -> CriterionWeight criterionWeight
mkCriterionWeight, CriterionWeight criterionWeight -> criterionWeight
forall criterionWeight.
CriterionWeight criterionWeight -> criterionWeight
deconstruct) PU criterionWeight
forall a. XmlPickler a => PU a
HXT.xpickle

-- | Smart constructor.
mkCriterionWeight :: (
	Num	criterionWeight,
	Ord	criterionWeight,
	Show	criterionWeight
 ) => criterionWeight -> CriterionWeight criterionWeight
mkCriterionWeight :: criterionWeight -> CriterionWeight criterionWeight
mkCriterionWeight criterionWeight
criterionWeight
	| criterionWeight -> Bool
forall n. (Num n, Ord n) => n -> Bool
Data.Num.inClosedUnitInterval criterionWeight
criterionWeight	= criterionWeight -> CriterionWeight criterionWeight
forall criterionWeight.
criterionWeight -> CriterionWeight criterionWeight
MkCriterionWeight criterionWeight
criterionWeight
	| Bool
otherwise					= Exception -> CriterionWeight criterionWeight
forall a e. Exception e => e -> a
Control.Exception.throw (Exception -> CriterionWeight criterionWeight)
-> (String -> Exception)
-> String
-> CriterionWeight criterionWeight
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Exception
Data.Exception.mkOutOfBounds (String -> Exception) -> ShowS -> String -> Exception
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"BishBosh.Attribute.CriterionWeight.mkCriterionWeight:\tweight" ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShowS
Text.ShowList.showsAssociation (String -> CriterionWeight criterionWeight)
-> String -> CriterionWeight criterionWeight
forall a b. (a -> b) -> a -> b
$ criterionWeight -> ShowS
forall a. Show a => a -> ShowS
shows criterionWeight
criterionWeight String
" must be within the closed unit-interval, '[0,1]'."