{-# LANGUAGE PostfixOperators #-}
module Drasil.GamePhysics.Requirements (funcReqs, nonfuncReqs) where

import Language.Drasil hiding (organization)
import Language.Drasil.Chunk.Concept.NamedCombinators
import qualified Language.Drasil.Sentence.Combinators as S

import qualified Drasil.DocLang.SRS as SRS (solCharSpec)
import Data.Drasil.Concepts.Documentation as Doc (body, funcReqDom, input_, 
  nonFuncReqDom, output_, physicalConstraint, physicalSim, property, solutionCharSpec)

import qualified Data.Drasil.Concepts.Physics as CP (collision, elasticity, 
  friction, rigidBody, space)
import qualified Data.Drasil.Concepts.Math as CM (surface)
import qualified Data.Drasil.Quantities.Math as QM (orientation)
import qualified Data.Drasil.Quantities.PhysicalProperties as QPP (mass)
import qualified Data.Drasil.Quantities.Physics as QP (angularVelocity, force, 
  position, time, velocity)

import Drasil.GamePhysics.Concepts (twoD)

------------------------------
-- SECTION 5 : REQUIREMENTS --
------------------------------

-----------------------------------
-- 5.1 : Functional Requirements --
-----------------------------------

-- Currently need separate chunks for plurals like rigid bodies,
-- velocities, etc.
funcReqs :: [ConceptInstance]
funcReqs :: [ConceptInstance]
funcReqs = [ConceptInstance
simSpace, ConceptInstance
inputInitialConds, ConceptInstance
inputSurfaceProps,
  ConceptInstance
verifyPhysCons, ConceptInstance
calcTransOverTime, ConceptInstance
calcRotOverTime, ConceptInstance
deterColls, ConceptInstance
deterCollRespOverTime]

simSpaceDesc, inputInitialCondsDesc, 
  inputSurfacePropsDesc, verifyPhysConsDesc,
  calcTransOverTimeDesc, calcRotOverTimeDesc,
  deterCollsDesc, deterCollRespOverTimeDesc :: Sentence

-- | template for requirements
requirementTemplate :: Sentence -> Sentence -> Sentence -> Sentence -> Sentence
requirementTemplate :: Sentence -> Sentence -> Sentence -> Sentence -> Sentence
requirementTemplate a :: Sentence
a b :: Sentence
b x :: Sentence
x z :: Sentence
z = [Sentence] -> Sentence
foldlSent [String -> Sentence
S "Determine the", Sentence
a Sentence -> Sentence -> Sentence
`S.and_` Sentence
b, 
  String -> Sentence
S "over a period of", UnitalChunk -> Sentence
forall n. (HasUID n, NamedIdea n) => n -> Sentence
phrase UnitalChunk
QP.time, String -> Sentence
S "of the", Sentence
x, Sentence
z]

-- | with added constraint
requirementS :: (NamedIdea a, NamedIdea b) => a -> b -> Sentence -> Sentence
requirementS :: a -> b -> Sentence -> Sentence
requirementS a :: a
a b :: b
b = Sentence -> Sentence -> Sentence -> Sentence -> Sentence
requirementTemplate (a -> Sentence
forall n. (HasUID n, NamedIdea n) => n -> Sentence
plural a
a) (b -> Sentence
forall n. (HasUID n, NamedIdea n) => n -> Sentence
plural b
b) (CI -> Sentence
getAcc CI
twoD
  Sentence -> Sentence -> Sentence
+:+ ConceptChunk -> Sentence
forall n. (HasUID n, NamedIdea n) => n -> Sentence
plural ConceptChunk
CP.rigidBody)

-- | without added constraint
requirementS' :: (NamedIdea a, NamedIdea b) => a -> b -> Sentence
requirementS' :: a -> b -> Sentence
requirementS' a :: a
a b :: b
b = a -> b -> Sentence -> Sentence
forall a b.
(NamedIdea a, NamedIdea b) =>
a -> b -> Sentence -> Sentence
requirementS a
a b
b Sentence
EmptyS 

-- some requirements look like they could be parametrized
simSpaceDesc :: Sentence
simSpaceDesc = [Sentence] -> Sentence
foldlSent [String -> Sentence
S "Create a", ConceptChunk -> Sentence
forall n. (HasUID n, NamedIdea n) => n -> Sentence
phrase ConceptChunk
CP.space, String -> Sentence
S "for all of the",
  NP -> Sentence
forall n. NounPhrase n => n -> Sentence
pluralNP (ConceptChunk
CP.rigidBody ConceptChunk -> NamedChunk -> NP
forall c d. (NamedIdea c, NamedIdea d) => c -> d -> NP
`inThePS` NamedChunk
physicalSim), 
  String -> Sentence
S "to interact in"]

inputInitialCondsDesc :: Sentence
inputInitialCondsDesc = [Sentence] -> Sentence
foldlSent [String -> Sentence
S "Input the initial", SepType -> FoldType -> [Sentence] -> Sentence
foldlList SepType
Comma FoldType
List
  [UnitalChunk -> Sentence
forall n. (HasUID n, NamedIdea n) => n -> Sentence
plural UnitalChunk
QPP.mass, UnitalChunk -> Sentence
forall n. (HasUID n, NamedIdea n) => n -> Sentence
plural UnitalChunk
QP.velocity, UnitalChunk -> Sentence
forall n. (HasUID n, NamedIdea n) => n -> Sentence
plural UnitalChunk
QM.orientation,
  UnitalChunk -> Sentence
forall n. (HasUID n, NamedIdea n) => n -> Sentence
plural UnitalChunk
QP.angularVelocity Sentence -> Sentence -> Sentence
`S.of_` Sentence
EmptyS, UnitalChunk -> Sentence
forall n. (HasUID n, NamedIdea n) => n -> Sentence
plural UnitalChunk
QP.force Sentence -> Sentence -> Sentence
+:+ String -> Sentence
S "applied on"],
  ConceptChunk -> Sentence
forall n. (HasUID n, NamedIdea n) => n -> Sentence
plural ConceptChunk
CP.rigidBody]

inputSurfacePropsDesc :: Sentence
inputSurfacePropsDesc = [Sentence] -> Sentence
foldlSent [String -> Sentence
S "Input", NP -> Sentence
forall n. NounPhrase n => n -> Sentence
pluralNP (ConceptChunk -> NamedChunk -> NP
forall c d. (NamedIdea c, NamedIdea d) => c -> d -> NP
combineNINI ConceptChunk
CM.surface
  NamedChunk
property) Sentence -> Sentence -> Sentence
`S.the_ofThe` NamedChunk -> Sentence
forall n. (HasUID n, NamedIdea n) => n -> Sentence
plural NamedChunk
body, String -> Sentence
S "such as", ConceptChunk -> Sentence
forall n. (HasUID n, NamedIdea n) => n -> Sentence
phrase ConceptChunk
CP.friction Sentence -> Sentence -> Sentence
`S.or_`
  ConceptChunk -> Sentence
forall n. (HasUID n, NamedIdea n) => n -> Sentence
phrase ConceptChunk
CP.elasticity]

verifyPhysConsDesc :: Sentence
verifyPhysConsDesc = [Sentence] -> Sentence
foldlSent [String -> Sentence
S "Verify that the", NamedChunk -> Sentence
forall n. (HasUID n, NamedIdea n) => n -> Sentence
plural NamedChunk
input_,
  String -> Sentence
S "satisfy the required", NamedChunk -> Sentence
forall n. (HasUID n, NamedIdea n) => n -> Sentence
plural NamedChunk
physicalConstraint, String -> Sentence
S "from the", 
  Section -> Sentence -> Sentence
forall r.
(HasUID r, HasRefAddress r, HasShortName r) =>
r -> Sentence -> Sentence
namedRef ([Contents] -> [Section] -> Section
SRS.solCharSpec [] []) (NamedChunk -> Sentence
forall n. (HasUID n, NamedIdea n) => n -> Sentence
phrase NamedChunk
solutionCharSpec)]

calcTransOverTimeDesc :: Sentence
calcTransOverTimeDesc = UnitalChunk -> UnitalChunk -> Sentence -> Sentence
forall a b.
(NamedIdea a, NamedIdea b) =>
a -> b -> Sentence -> Sentence
requirementS UnitalChunk
QP.position UnitalChunk
QP.velocity 
  (String -> Sentence
S "acted upon by a" Sentence -> Sentence -> Sentence
+:+ UnitalChunk -> Sentence
forall n. (HasUID n, NamedIdea n) => n -> Sentence
phrase UnitalChunk
QP.force)

calcRotOverTimeDesc :: Sentence
calcRotOverTimeDesc = UnitalChunk -> UnitalChunk -> Sentence
forall a b. (NamedIdea a, NamedIdea b) => a -> b -> Sentence
requirementS' UnitalChunk
QM.orientation UnitalChunk
QP.angularVelocity

deterCollsDesc :: Sentence
deterCollsDesc = [Sentence] -> Sentence
foldlSent [String -> Sentence
S "Determine if any of the", 
  NP -> Sentence
forall n. NounPhrase n => n -> Sentence
pluralNP (ConceptChunk
CP.rigidBody ConceptChunk -> ConceptChunk -> NP
forall c d. (NamedIdea c, NamedIdea d) => c -> d -> NP
`inThePS` ConceptChunk
CP.space), 
  String -> Sentence
S "have collided"]

deterCollRespOverTimeDesc :: Sentence
deterCollRespOverTimeDesc = UnitalChunk -> UnitalChunk -> Sentence -> Sentence
forall a b.
(NamedIdea a, NamedIdea b) =>
a -> b -> Sentence -> Sentence
requirementS UnitalChunk
QP.position UnitalChunk
QP.velocity 
  (String -> Sentence
S "that have undergone a" Sentence -> Sentence -> Sentence
+:+ ConceptChunk -> Sentence
forall n. (HasUID n, NamedIdea n) => n -> Sentence
phrase ConceptChunk
CP.collision)

simSpace, inputInitialConds, inputSurfaceProps, verifyPhysCons, calcTransOverTime,
  calcRotOverTime, deterColls, deterCollRespOverTime :: ConceptInstance

simSpace :: ConceptInstance
simSpace              = String -> Sentence -> String -> ConceptChunk -> ConceptInstance
forall c.
Concept c =>
String -> Sentence -> String -> c -> ConceptInstance
cic "simSpace"              Sentence
simSpaceDesc              "Simulation-Space"                       ConceptChunk
funcReqDom
inputInitialConds :: ConceptInstance
inputInitialConds     = String -> Sentence -> String -> ConceptChunk -> ConceptInstance
forall c.
Concept c =>
String -> Sentence -> String -> c -> ConceptInstance
cic "inputInitialConds"     Sentence
inputInitialCondsDesc     "Input-Initial-Conditions"               ConceptChunk
funcReqDom
inputSurfaceProps :: ConceptInstance
inputSurfaceProps     = String -> Sentence -> String -> ConceptChunk -> ConceptInstance
forall c.
Concept c =>
String -> Sentence -> String -> c -> ConceptInstance
cic "inputSurfaceProps"     Sentence
inputSurfacePropsDesc     "Input-Surface-Properties"               ConceptChunk
funcReqDom
verifyPhysCons :: ConceptInstance
verifyPhysCons        = String -> Sentence -> String -> ConceptChunk -> ConceptInstance
forall c.
Concept c =>
String -> Sentence -> String -> c -> ConceptInstance
cic "verifyPhysCons"        Sentence
verifyPhysConsDesc        "Verify-Physical_Constraints"            ConceptChunk
funcReqDom
calcTransOverTime :: ConceptInstance
calcTransOverTime     = String -> Sentence -> String -> ConceptChunk -> ConceptInstance
forall c.
Concept c =>
String -> Sentence -> String -> c -> ConceptInstance
cic "calcTransOverTime"     Sentence
calcTransOverTimeDesc     "Calculate-Translation-Over-Time"        ConceptChunk
funcReqDom
calcRotOverTime :: ConceptInstance
calcRotOverTime       = String -> Sentence -> String -> ConceptChunk -> ConceptInstance
forall c.
Concept c =>
String -> Sentence -> String -> c -> ConceptInstance
cic "calcRotOverTime"       Sentence
calcRotOverTimeDesc       "Calculate-Rotation-Over-Time"           ConceptChunk
funcReqDom
deterColls :: ConceptInstance
deterColls            = String -> Sentence -> String -> ConceptChunk -> ConceptInstance
forall c.
Concept c =>
String -> Sentence -> String -> c -> ConceptInstance
cic "deterColls"            Sentence
deterCollsDesc            "Determine-Collisions"                   ConceptChunk
funcReqDom
deterCollRespOverTime :: ConceptInstance
deterCollRespOverTime = String -> Sentence -> String -> ConceptChunk -> ConceptInstance
forall c.
Concept c =>
String -> Sentence -> String -> c -> ConceptInstance
cic "deterCollRespOverTime" Sentence
deterCollRespOverTimeDesc "Determine-Collision-Response-Over-Time" ConceptChunk
funcReqDom

--------------------------------------
-- 5.2 : Nonfunctional Requirements --
--------------------------------------

nonfuncReqs :: [ConceptInstance] 
nonfuncReqs :: [ConceptInstance]
nonfuncReqs = [ConceptInstance
performance, ConceptInstance
correctness, ConceptInstance
usability, ConceptInstance
understandability, ConceptInstance
maintainability]

performance :: ConceptInstance
performance :: ConceptInstance
performance = String -> Sentence -> String -> ConceptChunk -> ConceptInstance
forall c.
Concept c =>
String -> Sentence -> String -> c -> ConceptInstance
cic "performance" ([Sentence] -> Sentence
foldlSent [
  String -> Sentence
S "The execution time for collision detection and collision resolution shall be", 
  String -> Sentence
S "comparable to an existing 2D physics library on the market (e.g. Pymunk)"
  ]) "Performance" ConceptChunk
nonFuncReqDom

correctness :: ConceptInstance
correctness :: ConceptInstance
correctness = String -> Sentence -> String -> ConceptChunk -> ConceptInstance
forall c.
Concept c =>
String -> Sentence -> String -> c -> ConceptInstance
cic "correctness" ([Sentence] -> Sentence
foldlSent [
  NP -> Sentence
forall n. NounPhrase n => n -> Sentence
atStartNP (NamedChunk -> NP
forall t. NamedIdea t => t -> NP
the NamedChunk
output_) Sentence -> Sentence -> Sentence
`S.of_` String -> Sentence
S "simulation results shall be compared to", 
  String -> Sentence
S "an existing implementation like Pymunk (please refer to:", 
  String -> Sentence
S "http://www.pymunk.org/en/latest/)"
  ]) "Correctness" ConceptChunk
nonFuncReqDom
 
usability :: ConceptInstance
usability :: ConceptInstance
usability = String -> Sentence -> String -> ConceptChunk -> ConceptInstance
forall c.
Concept c =>
String -> Sentence -> String -> c -> ConceptInstance
cic "usability" ([Sentence] -> Sentence
foldlSent [
  String -> Sentence
S "Software shall be easy to learn" Sentence -> Sentence -> Sentence
`S.and_` String -> Sentence
S "use. Usability shall be measured by", 
  String -> Sentence
S "how long it takes a user to learn how to use the library to create a small program", 
  String -> Sentence
S "to simulate the movement" Sentence -> Sentence -> Sentence
`S.of_` String -> Sentence
S "2 bodies over time in space. Creating a program", 
  String -> Sentence
S "should take no less than 30 to 60 minutes for an intermediate to experienced programmer"
  ]) "Usability" ConceptChunk
nonFuncReqDom

understandability :: ConceptInstance
understandability :: ConceptInstance
understandability = String -> Sentence -> String -> ConceptChunk -> ConceptInstance
forall c.
Concept c =>
String -> Sentence -> String -> c -> ConceptInstance
cic "understandability" ([Sentence] -> Sentence
foldlSent [
  (String -> Sentence
S "Users" Sentence -> Sentence -> Sentence
`S.of_` String -> Sentence
S "Tamias2D shall be able to learn the software with ease" Sentence -> Sentence
!.), 
  (String -> Sentence
S "Users shall be able to easily create a small program using the library" Sentence -> Sentence
!.), 
  String -> Sentence
S "Creating a small program to simulate the movement of 2 bodies" Sentence -> Sentence -> Sentence
`S.in_` 
  String -> Sentence
S "space should take no less that 60 minutes"
  ]) "Understandability" ConceptChunk
nonFuncReqDom

maintainability :: ConceptInstance
maintainability :: ConceptInstance
maintainability = String -> Sentence -> String -> ConceptChunk -> ConceptInstance
forall c.
Concept c =>
String -> Sentence -> String -> c -> ConceptInstance
cic "maintainability" ([Sentence] -> Sentence
foldlSent [
  String -> Sentence
S "development time for any" Sentence -> Sentence -> Sentence
`S.the_ofTheC` String -> Sentence
S "likely changes should not exceed", 
  Integer -> Sentence
forall a. Show a => a -> Sentence
addPercent (10 :: Integer), String -> Sentence
S "percent of the original development time"
  ]) "Maintainability" ConceptChunk
nonFuncReqDom