From d457edc1bbe00f1c25601467e19e6eebe88accc3 Mon Sep 17 00:00:00 2001 From: Mariana Date: Tue, 3 Jun 2025 12:49:02 +0100 Subject: [PATCH 1/3] feat generators --- src/testgen/testgen/Generators.hs | 349 +++++++++++++++++++++++++++++- 1 file changed, 343 insertions(+), 6 deletions(-) diff --git a/src/testgen/testgen/Generators.hs b/src/testgen/testgen/Generators.hs index 5aba521..65c3441 100644 --- a/src/testgen/testgen/Generators.hs +++ b/src/testgen/testgen/Generators.hs @@ -14,19 +14,356 @@ module Generators (User(..)) where -import Test.QuickCheck (Arbitrary(..), elements, listOf) +import Test.QuickCheck (Arbitrary(..), elements, choose, oneof, vectorOf, Gen, listOf, frequency) +import Java (JavaData(..), toJavaExpression) -- | MakeItFit user data User = - Beginner + Amateur + UUID -- ^ User's identifier String -- ^ User's name + Int -- ^ User's age + Gender -- ^ User's gender + Float -- ^ User's weight + Int -- ^ User's height + Int -- ^ User's BPM + Int -- ^ User's level + String -- ^ User's address + String -- ^ User's phone + String -- ^ User's email + Float -- ^ User's index + [Activity] -- ^ User's activities | - Intermediate + Occasional + UUID -- ^ User's identifier String -- ^ User's name + Int -- ^ User's age + Gender -- ^ User's gender + Float -- ^ User's weight + Int -- ^ User's height + Int -- ^ User's BPM + Int -- ^ User's level + String -- ^ User's address + String -- ^ User's phone + String -- ^ User's email + Int -- ^ User's frequency + Float -- ^ User's index + [Activity] -- ^ User's activities + | + Professional + UUID -- ^ User's identifier + String -- ^ User's name + Int -- ^ User's age + Gender -- ^ User's gender + Float -- ^ User's weight + Int -- ^ User's height + Int -- ^ User's BPM + Int -- ^ User's level + String -- ^ User's address + String -- ^ User's phone + String -- ^ User's email + Int -- ^ User's frequency + String -- ^ User's specialization + Float -- ^ User's index + [Activity] -- ^ User's activities deriving (Show, Eq) +data Gender = Male | Female deriving (Show, Eq) + +instance JavaData Gender where + javaTypeName _ = "Gender" + toJavaExpression Male = "Gender.MALE" + toJavaExpression Female = "Gender.FEMALE" + +genUUID :: Gen UUID +genUUID = do + part1 <- vectorOf 8 (elements (['a'..'f'] ++ ['0'..'9'])) + part2 <- vectorOf 4 (elements (['a'..'f'] ++ ['0'..'9'])) + part3 <- vectorOf 4 (elements (['a'..'f'] ++ ['0'..'9'])) + part4 <- vectorOf 4 (elements (['a'..'f'] ++ ['0'..'9'])) + part5 <- vectorOf 12 (elements (['a'..'f'] ++ ['0'..'9'])) + return $ part1 ++ "-" ++ part2 ++ "-" ++ part3 ++ "-" ++ part4 ++ "-" ++ part5 + +genName :: Gen String +genName = elements + [ "Humberto" , "José" , "Mariana" , "André" , "Adriana" , "Bruno" , "Beatriz" , "Carlota" + , "Carlos" , "Dalila" , "Dinis" , "Eva", "Filipe" , "Hugo" , "Gabriel" , "Sofia" + , "Olívia" , "Henrique" , "Margarida" , "Elisabete" + ] + +genPhone :: Gen String +genPhone = do + secondDigit <- elements ['1', '2', '3', '6'] + rest <- sequence $ replicate 7 (elements ['0'..'9']) + return $ '9' : secondDigit : rest + +genEmail :: Gen String +genEmail = do + localPart <- listOf $ elements (['a'..'z'] ++ ['0'..'9']) + domain <- frequency + [ (32, return "gmail.com"), (30, return "yahoo.com"), (28, return "hotmail.com") + , (5, return "aol.com"), (2, return "hotmail.co.uk"), (2, return "hotmail.fr") + , (1, return "msn.com") + ] + return $ localPart ++ "@" ++ domain + +genAddress :: Gen String +genAddress = do + street <- genName + number <- elements [1..100] + city <- elements ["Braga", "Lisboa", "Porto", "Coimbra", "Leiria"] + return $ "Rua" ++ street ++ " " ++ show number ++ ", " ++ city + +genActivityName :: Gen String +genActivityName = elements + [ "Yoga", "Corrida", "Trail", "Musculação", "Caminhada", "Bicicleta", "Natação" + , "Pilates", "Boxe", "Zumba", "Body Pump", "Cycling" + ] + +genSpecialization :: Gen String +genSpecialization = elements + [ "Ballet", "Musculação", "Cardio", "Pilates", "Yoga", "Body Pump", "Localizada" + , "Zumba", "Natação", "Cycling", "Boxe" + ] + instance Arbitrary User where arbitrary = do - constructor <- elements [Beginner, Intermediate] - name <- listOf $ elements (['A'..'Z'] ++ ['a'..'z'] ++ [' ']) - return $ constructor name + code <- genUUID + tag <- elements ["Amateur", "Occasional", "Professional"] + name <- genName + age <- elements [18..80] + gender <- elements [Male, Female] + weight <- elements [50.0..100.00] + height <- elements [150..195] + bpm <- elements [60..100] + level <- arbitrary + address <- genAddress + phone <- genPhone + email <- genEmail + index <- choose (0.0, 10.0) + n <- choose (1, 30) + activities <- vectorOf n arbitrary + case tag of + "Amateur" -> + return $ Amateur code name age gender weight height bpm level address phone + email index activities + "Occasional" -> do + freq <- elements [1..14] + return $ Occasional code name age gender weight height bpm level address phone email + freq index activities + "Professional" -> do + freq <- elements [1..21] + spec <- genSpecialization + return $ Professional code name age gender weight height bpm level address phone email freq + spec index activities + +instance JavaData User where + javaTypeName _ = "User" + toJavaExpression u = case u of + Amateur uuid name age gender weight height bpm lvl addr phone email idx acts -> + "new Amateur(" ++ intercalate ", " (map toJavaExpression + [uuid, name, age, gender, weight, height, bpm, lvl, addr, phone, email, idx]) ++ + ", " ++ toJavaExpression acts ++ ")" + + Occasional uuid name age gender weight height bpm lvl addr phone email freq idx acts -> + "new Occasional(" ++ intercalate ", " (map toJavaExpression + [uuid, name, age, gender, weight, height, bpm, lvl, addr, phone, email, freq, idx]) ++ + ", " ++ toJavaExpression acts ++ ")" + + Professional uuid name age gender weight height bpm lvl addr phone email freq spec idx acts -> + "new Professional(" ++ intercalate ", " (map toJavaExpression + [uuid, name, age, gender, weight, height, bpm, lvl, addr, phone, email, freq, spec, idx]) ++ + ", " ++ toJavaExpression acts ++ ")" + +-- | MakeItFit Date +data MakeItFitDate = MakeItFitDate (Int, Int, Int) deriving (Show, Eq, Ord) + +type UUID = String + +instance Arbitrary MakeItFitDate where + arbitrary = do + year <- elements [2001..2025] + month <- elements [1..12] + let daysInMonth m y + | m == 2 = if y `mod` 4 == 0 && (y `mod` 100 /= 0 || y `mod` 400 == 0) then 29 else 28 + | m `elem` [4, 6, 9, 11] = 30 + | otherwise = 31 + day <- elements [1..daysInMonth month year] + return $ MakeItFitDate (year, month, day) + +instance JavaData MakeItFitDate where + javaTypeName _ = "MakeItFitDate" + toJavaExpression (MakeItFitDate (y, m, d)) = + "new MakeItFitDate(" ++ show y ++ ", " ++ show m ++ ", " ++ show d ++ ")" + +-- | MakeItFit activity +data Activity + = PushUp + UUID -- ^ Activity's user code identifier + UUID -- ^ Activity's code + MakeItFitDate -- ^ Date when the activity was performed + Int -- ^ Expected duration of the activity (in minutes) + String -- ^ Designation for the activity + String -- ^ Name of the activity + String -- ^ Specialization of the activity + Int -- ^ Activity's duration + Int -- ^ Calories wasted during the activity + Int -- ^ Number of repetitions + Int -- ^ Number of series + | Running + UUID -- ^ Activity's user code identifier + UUID -- ^ Activity's code + MakeItFitDate -- ^ Date when the activity was performed + Int -- ^ Expected duration of the activity (in minutes) + String -- ^ Designation for the activity + String -- ^ Name of the activity + String -- ^ Specialization of the activity + Int -- ^ Activity's duration + Int -- ^ Calories wasted during the activity + Double -- ^ Distance covered + Double -- ^ Average speed + | Trail + UUID -- ^ Activity's user code identifier + UUID -- ^ Activity's code + MakeItFitDate -- ^ Date when the activity was performed + Int -- ^ Expected duration of the activity (in minutes) + String -- ^ Designation for the activity + String -- ^ Name of the activity + String -- ^ Specialization of the activity + Int -- ^ Activity's duration + Int -- ^ Calories wasted during the activity + Double -- ^ Distance covered + Double -- ^ Elevation gain + Double -- ^ Elevation loss + TrailType -- ^ Type of trail (Easy, Medium, Hard) + | WeightSquat + UUID -- ^ Activity's user code identifier + UUID -- ^ Activity's code + MakeItFitDate -- ^ Date when the activity was performed + Int -- ^ Expected duration of the activity (in minutes) + String -- ^ Designation for the activity + String -- ^ Name of the activity + String -- ^ Specialization of the activity + Int -- ^ Activity's duration + Int -- ^ Calories wasted during the activity + Int -- ^ Number of repetitions + Int -- ^ Number of series + Double -- ^ Weight used in the repetitions + deriving (Show, Eq) + +data TrailType = TrailEasy | TrailMedium | TrailHard + deriving (Show, Eq) + +genDesignation :: Gen String +genDesignation = elements + [ "Treino das 9h", "Treino do 12h", "Treino das 15h", "Treino das 17h", "Treino das 19h" + , "Treino para emagrecer", "Passeio"] + +instance JavaData TrailType where + javaTypeName _ = "TrailType" + toJavaExpression TrailEasy = "TrailType.EASY" + toJavaExpression TrailMedium = "TrailType.MEDIUM" + toJavaExpression TrailHard = "TrailType.HARD" + +instance Arbitrary Activity where + arbitrary = do + tag <- elements ["PushUp", "Running", "Trail", "WeightSquat"] + userCode <- genUUID + activityCode <- genUUID + date <- arbitrary + expDur <- elements [10,15,20,30,45,60] + designation <- genDesignation + name <- genActivityName + let spec = tag + dur <- elements [5,10,15,20,30,45,60] + cal <- elements [20,50,100,150,172,200,300] + case tag of + "PushUp" -> do + reps <- elements [5..100] + series <- elements [1..10] + return $ PushUp userCode activityCode date expDur designation name spec dur cal reps series + "Running" -> do + dist <- choose (1.0, 45.0) + speed <- choose (6.0, 15.0) + return $ Running userCode activityCode date expDur designation name spec dur cal dist speed + "Trail" -> do + dist <- frequency[(5, choose(2.0, 10.0)),(3, choose(10.0, 25.0)),(2, choose(25.0, 50.0))] + elevGain <- choose (0.0, 20.0) + elevLoss <- choose (0.0, 20.0) + trailtype <- arbitrary + return $ Trail userCode activityCode date expDur designation name spec dur cal dist + elevGain elevLoss trailtype + "WeightSquat" -> do + reps <- elements [5..30] + series <- elements [1..8] + weight <- choose (10.0, 200.0) + return $ WeightSquat userCode activityCode date expDur designation name spec dur cal reps + series weight + +instance JavaData Activity where + javaTypeName _ = "Activity" + toJavaExpression a = case a of + PushUp uc ac date ed des name spec dur cal reps series -> + "new PushUp(" ++ intercalate ", " (map toJavaExpression + [uc, ac]) ++ ", " ++ + toJavaExpression date ++ ", " ++ + intercalate ", " (map toJavaExpression + [ed, des, name, spec, dur, cal, reps, series]) ++ ")" + + Running uc ac date ed des name spec dur cal dist speed -> + "new Running(" ++ intercalate ", " (map toJavaExpression + [uc, ac]) ++ ", " ++ + toJavaExpression date ++ ", " ++ + intercalate ", " (map toJavaExpression + [ed, des, name, spec, dur, cal]) ++ ", " ++ + toJavaExpression dist ++ ", " ++ toJavaExpression speed ++ ")" + + Trail uc ac date ed des name spec dur cal dist eg el tt -> + "new Trail(" ++ intercalate ", " (map toJavaExpression + [uc, ac]) ++ ", " ++ + toJavaExpression date ++ ", " ++ + intercalate ", " (map toJavaExpression + [ed, des, name, spec, dur, cal]) ++ ", " ++ + toJavaExpression dist ++ ", " ++ + toJavaExpression eg ++ ", " ++ + toJavaExpression el ++ ", " ++ + toJavaExpression tt ++ ")" + + WeightSquat uc ac date ed des name spec dur cal reps series weight -> + "new WeightSquat(" ++ intercalate ", " (map toJavaExpression + [uc, ac]) ++ ", " ++ + toJavaExpression date ++ ", " ++ + intercalate ", " (map toJavaExpression + [ed, des, name, spec, dur, cal, reps, series, weight]) ++ ")" + +-- | MakeItFit training plan +data TrainingPlan = TrainingPlan + UUID -- ^ user code + UUID -- ^ training plan code + String -- ^ training plan name + [MyTuple Int Activity] -- ^ activities (list of (Integer, Activity) tuples) + MakeItFitDate -- ^ date when the training plan was created + deriving (Show, Eq) + +data MyTuple a b = MyTuple a b + deriving (Eq, Show) + +instance Arbitrary TrainingPlan where + arbitrary = do + userCode <- genUUID + planCode <- genUUID + letter <- elements ['A'..'Z'] + let name = "Plano " ++ [letter] + n <- choose (1, 7) + activities <- vectorOf n arbitrary + date <- arbitrary + return $ TrainingPlan userCode planCode name (zip [1..n] activities) date + +instance JavaData TrainingPlan where + toJava (TrainingPlan name duration activities) = + "new TrainingPlan(" ++ + toJava name ++ ", " ++ + show duration ++ ", " ++ + "List.of(" ++ intercalate ", " (map toJava activities) ++ ")" ++ + ")" + From 9c9f46566e017a06dd90f8f7dfb67787aaaa9748 Mon Sep 17 00:00:00 2001 From: voidbert Date: Tue, 3 Jun 2025 15:11:11 +0100 Subject: [PATCH 2/3] Minor Java API change --- src/testgen/testgen/Java.hs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/testgen/testgen/Java.hs b/src/testgen/testgen/Java.hs index 9fbd4a9..4eb667f 100644 --- a/src/testgen/testgen/Java.hs +++ b/src/testgen/testgen/Java.hs @@ -18,6 +18,7 @@ module Java ( JavaData(..) + , toJavaExpressionList , indent , decorateTest , assertTrue @@ -46,10 +47,11 @@ class JavaData a where -- Creates a Java variable declaration, where the variable is initialized to the given value -- -- Example output: @List list = Arrays.asList(1, 2, 3)@ - toJavaVariable :: String -- ^ Variable name - -> a -- ^ Input value - -> String -- ^ Java variable declation - toJavaVariable name obj = javaTypeName obj ++ " " ++ name ++ " = " ++ toJavaExpression obj ++ ";" + toJavaVariable :: String -- ^ Variable name + -> a -- ^ Input value + -> [String] -- ^ Java variable declation (lines of code) + toJavaVariable name obj = + [javaTypeName obj ++ " " ++ name ++ " = " ++ toJavaExpression obj ++ ";"] -- Basic scalar types @@ -99,7 +101,9 @@ instance JavaData String where -- Lists -toJavaExpressionList :: JavaData a => [a] -> String +-- | Creates the expression for a list of Java objects +toJavaExpressionList :: JavaData a => [a] -- ^ List of Java objects + -> String -- ^ Java expression toJavaExpressionList xs = "Arrays.asList(" ++ intercalate ", " (map toJavaExpression xs) ++ ")" instance JavaData [Bool] where From 71afa6a62275622cfc96167e8fdccd2c01d11f13 Mon Sep 17 00:00:00 2001 From: voidbert Date: Tue, 3 Jun 2025 17:14:16 +0100 Subject: [PATCH 3/3] Make generators work with code Untested, but it should now be following the constructors --- src/testgen/testgen/Generators.hs | 677 +++++++++++++++++------------- 1 file changed, 382 insertions(+), 295 deletions(-) diff --git a/src/testgen/testgen/Generators.hs b/src/testgen/testgen/Generators.hs index 65c3441..f6154ac 100644 --- a/src/testgen/testgen/Generators.hs +++ b/src/testgen/testgen/Generators.hs @@ -12,95 +12,110 @@ -- See the License for the specific language governing permissions and -- limitations under the License. -module Generators (User(..)) where +{-# LANGUAGE FlexibleInstances #-} -import Test.QuickCheck (Arbitrary(..), elements, choose, oneof, vectorOf, Gen, listOf, frequency) -import Java (JavaData(..), toJavaExpression) +module Generators + ( + Gender(..) + , User(..) + , MakeItFitDate(..) + , Activity(..) + , TrainingPlan(..) + , genActivity + , genTrainingPlan + ) where --- | MakeItFit user +import Data.List (intercalate) +import Test.QuickCheck (Arbitrary(..), Gen, choose, elements, frequency, listOf1, oneof, vectorOf) +import Java (JavaData(..), toJavaExpressionList) + +-- | A MakeItFit gender +data Gender = Male | Female | Other deriving (Show, Eq) + +instance Arbitrary Gender where + arbitrary = elements [Male, Female, Other] + +instance JavaData Gender where + javaTypeName = const "Gender" + toJavaExpression Male = "Gender.Male" + toJavaExpression Female = "Gender.Female" + toJavaExpression Other = "Gender.Other" + +-- | A MakeItFit user data User = Amateur - UUID -- ^ User's identifier - String -- ^ User's name - Int -- ^ User's age - Gender -- ^ User's gender - Float -- ^ User's weight - Int -- ^ User's height - Int -- ^ User's BPM - Int -- ^ User's level - String -- ^ User's address - String -- ^ User's phone - String -- ^ User's email - Float -- ^ User's index + String -- ^ User's name + Int -- ^ User's age + Gender -- ^ User's gender + Float -- ^ User's weight + Int -- ^ User's height + Int -- ^ User's BPM + Int -- ^ User's level + String -- ^ User's address + String -- ^ User's phone + String -- ^ User's email [Activity] -- ^ User's activities | Occasional - UUID -- ^ User's identifier - String -- ^ User's name - Int -- ^ User's age - Gender -- ^ User's gender - Float -- ^ User's weight - Int -- ^ User's height - Int -- ^ User's BPM - Int -- ^ User's level - String -- ^ User's address - String -- ^ User's phone - String -- ^ User's email - Int -- ^ User's frequency - Float -- ^ User's index + String -- ^ User's name + Int -- ^ User's age + Gender -- ^ User's gender + Float -- ^ User's weight + Int -- ^ User's height + Int -- ^ User's BPM + Int -- ^ User's level + String -- ^ User's address + String -- ^ User's phone + String -- ^ User's email + Int -- ^ User's frequency [Activity] -- ^ User's activities | Professional - UUID -- ^ User's identifier - String -- ^ User's name - Int -- ^ User's age - Gender -- ^ User's gender - Float -- ^ User's weight - Int -- ^ User's height - Int -- ^ User's BPM - Int -- ^ User's level - String -- ^ User's address - String -- ^ User's phone - String -- ^ User's email - Int -- ^ User's frequency - String -- ^ User's specialization - Float -- ^ User's index + String -- ^ User's name + Int -- ^ User's age + Gender -- ^ User's gender + Float -- ^ User's weight + Int -- ^ User's height + Int -- ^ User's BPM + Int -- ^ User's level + String -- ^ User's address + String -- ^ User's phone + String -- ^ User's email + Int -- ^ User's frequency [Activity] -- ^ User's activities deriving (Show, Eq) -data Gender = Male | Female deriving (Show, Eq) - -instance JavaData Gender where - javaTypeName _ = "Gender" - toJavaExpression Male = "Gender.MALE" - toJavaExpression Female = "Gender.FEMALE" - -genUUID :: Gen UUID -genUUID = do - part1 <- vectorOf 8 (elements (['a'..'f'] ++ ['0'..'9'])) - part2 <- vectorOf 4 (elements (['a'..'f'] ++ ['0'..'9'])) - part3 <- vectorOf 4 (elements (['a'..'f'] ++ ['0'..'9'])) - part4 <- vectorOf 4 (elements (['a'..'f'] ++ ['0'..'9'])) - part5 <- vectorOf 12 (elements (['a'..'f'] ++ ['0'..'9'])) - return $ part1 ++ "-" ++ part2 ++ "-" ++ part3 ++ "-" ++ part4 ++ "-" ++ part5 - -genName :: Gen String -genName = elements - [ "Humberto" , "José" , "Mariana" , "André" , "Adriana" , "Bruno" , "Beatriz" , "Carlota" - , "Carlos" , "Dalila" , "Dinis" , "Eva", "Filipe" , "Hugo" , "Gabriel" , "Sofia" - , "Olívia" , "Henrique" , "Margarida" , "Elisabete" - ] +genUserName :: Gen String +genUserName = do + name <- elements + [ "Humberto" , "José" , "Mariana" , "André" , "Adriana" , "Bruno" , "Beatriz" , "Carlota" + , "Carlos" , "Dalila" , "Dinis" , "Eva", "Filipe" , "Hugo" , "Gabriel" , "Sofia" , "Olívia" + , "Henrique" , "Margarida" , "Elisabete" + ] + surname <- elements + [ + "Gomes", "Lopes", "Rocha", "Campos", "Silva", "Pereira", "Coelho", "Gonçalves", "Dias" + ] + return $ name ++ " " ++ surname genPhone :: Gen String -genPhone = do - secondDigit <- elements ['1', '2', '3', '6'] - rest <- sequence $ replicate 7 (elements ['0'..'9']) - return $ '9' : secondDigit : rest +genPhone = oneof [genMobile, genLandline] + where + genMobile :: Gen String + genMobile = do + secondDigit <- elements ['1', '2', '3', '6'] + rest <- vectorOf 7 (elements ['0'..'9']) + return $ '9' : secondDigit : rest + + genLandline :: Gen String + genLandline = do + rest <- vectorOf 8 (elements ['0'..'9']) + return $ '2' : rest genEmail :: Gen String genEmail = do - localPart <- listOf $ elements (['a'..'z'] ++ ['0'..'9']) - domain <- frequency + localPart <- listOf1 $ elements (['a'..'z'] ++ ['0'..'9']) + domain <- frequency [ (32, return "gmail.com"), (30, return "yahoo.com"), (28, return "hotmail.com") , (5, return "aol.com"), (2, return "hotmail.co.uk"), (2, return "hotmail.fr") , (1, return "msn.com") @@ -109,261 +124,333 @@ genEmail = do genAddress :: Gen String genAddress = do - street <- genName + street <- genUserName number <- elements [1..100] - city <- elements ["Braga", "Lisboa", "Porto", "Coimbra", "Leiria"] - return $ "Rua" ++ street ++ " " ++ show number ++ ", " ++ city - -genActivityName :: Gen String -genActivityName = elements - [ "Yoga", "Corrida", "Trail", "Musculação", "Caminhada", "Bicicleta", "Natação" - , "Pilates", "Boxe", "Zumba", "Body Pump", "Cycling" - ] - -genSpecialization :: Gen String -genSpecialization = elements - [ "Ballet", "Musculação", "Cardio", "Pilates", "Yoga", "Body Pump", "Localizada" - , "Zumba", "Natação", "Cycling", "Boxe" - ] + city <- frequency + [(40, return "Lisboa"), (30, return "Porto"), (20, return "Braga"), (10, return "Coimbra")] + apartment <- oneof [return "", genApartment >>= return . (", " ++)] + return $ "Rua " ++ street ++ " " ++ show number ++ apartment ++ ", " ++ city + where + genApartment :: Gen String + genApartment = do + floor <- choose (1, 10) :: Gen Int + side <- elements ["esq.", "dto."] + return $ (show floor) ++ "º " ++ side instance Arbitrary User where arbitrary = do - code <- genUUID - tag <- elements ["Amateur", "Occasional", "Professional"] - name <- genName - age <- elements [18..80] - gender <- elements [Male, Female] - weight <- elements [50.0..100.00] - height <- elements [150..195] - bpm <- elements [60..100] - level <- arbitrary - address <- genAddress - phone <- genPhone - email <- genEmail - index <- choose (0.0, 10.0) - n <- choose (1, 30) - activities <- vectorOf n arbitrary + tag <- elements ["Amateur", "Occasional", "Professional"] + name <- genUserName + age <- choose (18, 80) + gender <- arbitrary :: Gen Gender + weight <- elements [50.0..100.00] -- NOTE: elements is used to avoid fractional numbers + height <- choose (150, 195) + bpm <- choose (60, 100) + level <- choose (1, 10) + address <- genAddress + phone <- genPhone + email <- genEmail + n <- choose (1, 30) + activities <- vectorOf n (genActivity "ERROR") case tag of - "Amateur" -> - return $ Amateur code name age gender weight height bpm level address phone - email index activities + "Amateur" -> return $ + Amateur name age gender weight height bpm level address phone email activities "Occasional" -> do freq <- elements [1..14] - return $ Occasional code name age gender weight height bpm level address phone email - freq index activities + return $ + Occasional name age gender weight height bpm level address phone email freq activities "Professional" -> do - freq <- elements [1..21] - spec <- genSpecialization - return $ Professional code name age gender weight height bpm level address phone email freq - spec index activities + freq <- elements [7..21] + return $ + Professional name age gender weight height bpm level address phone email freq activities instance JavaData User where - javaTypeName _ = "User" - toJavaExpression u = case u of - Amateur uuid name age gender weight height bpm lvl addr phone email idx acts -> - "new Amateur(" ++ intercalate ", " (map toJavaExpression - [uuid, name, age, gender, weight, height, bpm, lvl, addr, phone, email, idx]) ++ - ", " ++ toJavaExpression acts ++ ")" + javaTypeName = const "User" - Occasional uuid name age gender weight height bpm lvl addr phone email freq idx acts -> - "new Occasional(" ++ intercalate ", " (map toJavaExpression - [uuid, name, age, gender, weight, height, bpm, lvl, addr, phone, email, freq, idx]) ++ - ", " ++ toJavaExpression acts ++ ")" - - Professional uuid name age gender weight height bpm lvl addr phone email freq spec idx acts -> - "new Professional(" ++ intercalate ", " (map toJavaExpression - [uuid, name, age, gender, weight, height, bpm, lvl, addr, phone, email, freq, spec, idx]) ++ - ", " ++ toJavaExpression acts ++ ")" - --- | MakeItFit Date -data MakeItFitDate = MakeItFitDate (Int, Int, Int) deriving (Show, Eq, Ord) + -- NOTE: this won't have the activities set + toJavaExpression u = case u of + Amateur name age gender weight height bpm level address phone email _ -> + "new Amateur(" ++ intercalate ", " [ + toJavaExpression name + , toJavaExpression age + , toJavaExpression gender + , toJavaExpression weight + , toJavaExpression bpm + , toJavaExpression level + , toJavaExpression address + , toJavaExpression phone + , toJavaExpression email + ] ++ ")" + + Occasional name age gender weight height bpm level address phone email frequency _ -> + "new Occasional(" ++ intercalate ", " [ + toJavaExpression name + , toJavaExpression age + , toJavaExpression gender + , toJavaExpression weight + , toJavaExpression bpm + , toJavaExpression level + , toJavaExpression address + , toJavaExpression phone + , toJavaExpression email + , toJavaExpression frequency + ] ++ ")" + + Professional name age gender weight height bpm level address phone email frequency _ -> + "new Professional(" ++ intercalate ", " [ + toJavaExpression name + , toJavaExpression age + , toJavaExpression gender + , toJavaExpression weight + , toJavaExpression bpm + , toJavaExpression level + , toJavaExpression address + , toJavaExpression phone + , toJavaExpression email + , toJavaExpression frequency + ] ++ ")" + + toJavaVariable name user = + [ + javaTypeName user ++ " " ++ name ++ " = " ++ toJavaExpression user ++ ";" + , name ++ ".addActivities(" ++ toJavaExpression + ( + map (changeActivityUserUUID (name ++ ".getCode()")) activities + ) ++ ");" + ] + where + activities = case user of + Amateur _ _ _ _ _ _ _ _ _ _ activities -> activities + Occasional _ _ _ _ _ _ _ _ _ _ _ activities -> activities + Professional _ _ _ _ _ _ _ _ _ _ _ activities -> activities -type UUID = String +-- | A MakeItFit date (YYYY/MM/DD) +data MakeItFitDate = MakeItFitDate Int Int Int deriving (Show, Eq, Ord) instance Arbitrary MakeItFitDate where arbitrary = do - year <- elements [2001..2025] + year <- elements [2001..2025] month <- elements [1..12] - let daysInMonth m y - | m == 2 = if y `mod` 4 == 0 && (y `mod` 100 /= 0 || y `mod` 400 == 0) then 29 else 28 - | m `elem` [4, 6, 9, 11] = 30 - | otherwise = 31 - day <- elements [1..daysInMonth month year] - return $ MakeItFitDate (year, month, day) + day <- elements [1..daysInMonth month year] + return $ MakeItFitDate year month day + where + daysInMonth m y + | m == 2 = if y `mod` 4 == 0 && (y `mod` 100 /= 0 || y `mod` 400 == 0) then 29 else 28 + | m `elem` [4, 6, 9, 11] = 30 + | otherwise = 31 instance JavaData MakeItFitDate where - javaTypeName _ = "MakeItFitDate" - toJavaExpression (MakeItFitDate (y, m, d)) = - "new MakeItFitDate(" ++ show y ++ ", " ++ show m ++ ", " ++ show d ++ ")" - --- | MakeItFit activity -data Activity - = PushUp - UUID -- ^ Activity's user code identifier - UUID -- ^ Activity's code - MakeItFitDate -- ^ Date when the activity was performed - Int -- ^ Expected duration of the activity (in minutes) - String -- ^ Designation for the activity - String -- ^ Name of the activity - String -- ^ Specialization of the activity - Int -- ^ Activity's duration - Int -- ^ Calories wasted during the activity - Int -- ^ Number of repetitions - Int -- ^ Number of series - | Running - UUID -- ^ Activity's user code identifier - UUID -- ^ Activity's code - MakeItFitDate -- ^ Date when the activity was performed - Int -- ^ Expected duration of the activity (in minutes) - String -- ^ Designation for the activity - String -- ^ Name of the activity - String -- ^ Specialization of the activity - Int -- ^ Activity's duration - Int -- ^ Calories wasted during the activity - Double -- ^ Distance covered - Double -- ^ Average speed - | Trail - UUID -- ^ Activity's user code identifier - UUID -- ^ Activity's code - MakeItFitDate -- ^ Date when the activity was performed - Int -- ^ Expected duration of the activity (in minutes) - String -- ^ Designation for the activity - String -- ^ Name of the activity - String -- ^ Specialization of the activity - Int -- ^ Activity's duration - Int -- ^ Calories wasted during the activity - Double -- ^ Distance covered - Double -- ^ Elevation gain - Double -- ^ Elevation loss - TrailType -- ^ Type of trail (Easy, Medium, Hard) - | WeightSquat - UUID -- ^ Activity's user code identifier - UUID -- ^ Activity's code - MakeItFitDate -- ^ Date when the activity was performed - Int -- ^ Expected duration of the activity (in minutes) - String -- ^ Designation for the activity - String -- ^ Name of the activity - String -- ^ Specialization of the activity - Int -- ^ Activity's duration - Int -- ^ Calories wasted during the activity - Int -- ^ Number of repetitions - Int -- ^ Number of series - Double -- ^ Weight used in the repetitions - deriving (Show, Eq) + javaTypeName = const "MakeItFitDate" + toJavaExpression (MakeItFitDate y m d) = + "new MakeItFitDate(" ++ intercalate ", " (map toJavaExpression [y, m, d]) ++ ")" -data TrailType = TrailEasy | TrailMedium | TrailHard - deriving (Show, Eq) - -genDesignation :: Gen String -genDesignation = elements - [ "Treino das 9h", "Treino do 12h", "Treino das 15h", "Treino das 17h", "Treino das 19h" - , "Treino para emagrecer", "Passeio"] +-- | MakeItFit TrailType +data TrailType = TrailEasy | TrailMedium | TrailHard deriving (Show, Eq) instance JavaData TrailType where javaTypeName _ = "TrailType" - toJavaExpression TrailEasy = "TrailType.EASY" - toJavaExpression TrailMedium = "TrailType.MEDIUM" - toJavaExpression TrailHard = "TrailType.HARD" + toJavaExpression TrailEasy = "Trail.TRAIL_TYPE_EASY" + toJavaExpression TrailMedium = "Trail.TRAIL_TYPE_MEDIUM" + toJavaExpression TrailHard = "Trail.TRAIL_TYPE_HARD" + +instance Arbitrary TrailType where + arbitrary = elements [TrailEasy, TrailMedium, TrailHard] + +-- | A MakeItFit activity +data Activity = + PushUp + String -- ^ Java expression for the user's UUID + MakeItFitDate -- ^ Date when the activity was performed + Int -- ^ Expected duration (in minutes) + String -- ^ Activity's designation + String -- ^ Activity's name + Int -- ^ Number of repetitions + Int -- ^ Number of series + | + Running + String -- ^ Java expression for the user's UUID + MakeItFitDate -- ^ Date when the activity was performed + Int -- ^ Expected duration (in minutes) + String -- ^ Activity's designation + String -- ^ Activity's name + Double -- ^ Distance ran + Double -- ^ Running velocity + | + Trail + String -- ^ Java expression for the user's UUID + MakeItFitDate -- ^ Date when the activity was performed + Int -- ^ Expected duration (in minutes) + String -- ^ Activity's designation + String -- ^ Activity's name + Double -- ^ Distance walked + Double -- ^ Elevation gain + Double -- ^ Elevation loss + TrailType -- ^ Type of trail + | + WeightSquat + String -- ^ Java expression for the user's UUID + MakeItFitDate -- ^ Date when the activity was performed + Int -- ^ Expected duration of the activity (in minutes) + String -- ^ Designation for the activity + String -- ^ Name of the activity + Int -- ^ Number of repetitions + Int -- ^ Number of series + Double -- ^ Weight used in the repetitions + deriving (Show, Eq) -instance Arbitrary Activity where - arbitrary = do - tag <- elements ["PushUp", "Running", "Trail", "WeightSquat"] - userCode <- genUUID - activityCode <- genUUID - date <- arbitrary - expDur <- elements [10,15,20,30,45,60] - designation <- genDesignation - name <- genActivityName - let spec = tag - dur <- elements [5,10,15,20,30,45,60] - cal <- elements [20,50,100,150,172,200,300] - case tag of - "PushUp" -> do - reps <- elements [5..100] - series <- elements [1..10] - return $ PushUp userCode activityCode date expDur designation name spec dur cal reps series - "Running" -> do - dist <- choose (1.0, 45.0) - speed <- choose (6.0, 15.0) - return $ Running userCode activityCode date expDur designation name spec dur cal dist speed - "Trail" -> do - dist <- frequency[(5, choose(2.0, 10.0)),(3, choose(10.0, 25.0)),(2, choose(25.0, 50.0))] - elevGain <- choose (0.0, 20.0) - elevLoss <- choose (0.0, 20.0) - trailtype <- arbitrary - return $ Trail userCode activityCode date expDur designation name spec dur cal dist - elevGain elevLoss trailtype - "WeightSquat" -> do - reps <- elements [5..30] - series <- elements [1..8] - weight <- choose (10.0, 200.0) - return $ WeightSquat userCode activityCode date expDur designation name spec dur cal reps - series weight +changeActivityUserUUID :: String -> Activity -> Activity +changeActivityUserUUID userCode (PushUp _ date duration designation name repetitions series) = + PushUp userCode date duration designation name repetitions series +changeActivityUserUUID userCode (Running _ date duration designation name distance speed) = + Running userCode date duration designation name distance speed +changeActivityUserUUID + userCode (Trail _ date duration designation name distance elevationGain elevationLoss trailType) = + Trail userCode date duration designation name distance elevationGain elevationLoss trailType +changeActivityUserUUID + userCode (WeightSquat _ date duration designation name repetitions series weight) = + WeightSquat userCode date duration designation name repetitions series weight + +genActivityName :: Gen String +genActivityName = elements + [ "Yoga", "Corrida", "Trail", "Musculação", "Caminhada", "Bicicleta", "Natação" , "Pilates" + , "Boxe", "Zumba", "Body Pump", "Cycling" + ] + +genActivityDesignation :: Gen String +genActivityDesignation = elements + [ "Treino das 9h", "Treino do 12h", "Treino das 15h", "Treino das 17h", "Treino das 19h" + , "Treino para emagrecer", "Passeio" + ] + +-- | Generates a MakeItFit activity +genActivity :: String -- ^ Java expression with the activity's user UUID + -> Gen Activity -- ^ Generated activity +genActivity userCode = do + tag <- elements ["PushUp", "Running", "Trail", "WeightSquat"] + date <- arbitrary + duration <- elements [10, 15, 20, 30, 45, 60] + designation <- genActivityDesignation + name <- genActivityName + case tag of + "PushUp" -> do + repetitions <- choose (5, 100) + series <- choose (1, 10) + return $ PushUp userCode date duration designation name repetitions series + "Running" -> do + distance <- choose (1.0, 45.0) + speed <- choose (6.0, 15.0) + return $ Running userCode date duration designation name distance speed + "Trail" -> do + distance <- choose (1.0, 45.0) + elevationGain <- choose (0.0, 20.0) + elevationLoss <- choose (0.0, 20.0) + trailType <- arbitrary + return $ Trail + userCode date duration designation name distance elevationGain elevationLoss trailType + "WeightSquat" -> do + repetitions <- choose (5, 100) + series <- choose (1, 10) + weight <- choose (10.0, 200.0) + return $ WeightSquat userCode date duration designation name repetitions series weight instance JavaData Activity where javaTypeName _ = "Activity" + toJavaExpression a = case a of - PushUp uc ac date ed des name spec dur cal reps series -> - "new PushUp(" ++ intercalate ", " (map toJavaExpression - [uc, ac]) ++ ", " ++ - toJavaExpression date ++ ", " ++ - intercalate ", " (map toJavaExpression - [ed, des, name, spec, dur, cal, reps, series]) ++ ")" - - Running uc ac date ed des name spec dur cal dist speed -> - "new Running(" ++ intercalate ", " (map toJavaExpression - [uc, ac]) ++ ", " ++ - toJavaExpression date ++ ", " ++ - intercalate ", " (map toJavaExpression - [ed, des, name, spec, dur, cal]) ++ ", " ++ - toJavaExpression dist ++ ", " ++ toJavaExpression speed ++ ")" - - Trail uc ac date ed des name spec dur cal dist eg el tt -> - "new Trail(" ++ intercalate ", " (map toJavaExpression - [uc, ac]) ++ ", " ++ - toJavaExpression date ++ ", " ++ - intercalate ", " (map toJavaExpression - [ed, des, name, spec, dur, cal]) ++ ", " ++ - toJavaExpression dist ++ ", " ++ - toJavaExpression eg ++ ", " ++ - toJavaExpression el ++ ", " ++ - toJavaExpression tt ++ ")" - - WeightSquat uc ac date ed des name spec dur cal reps series weight -> - "new WeightSquat(" ++ intercalate ", " (map toJavaExpression - [uc, ac]) ++ ", " ++ - toJavaExpression date ++ ", " ++ - intercalate ", " (map toJavaExpression - [ed, des, name, spec, dur, cal, reps, series, weight]) ++ ")" + PushUp userCode date duration designation name repetitions series -> + "new PushUp(" ++ intercalate ", " [ + userCode + , toJavaExpression date + , toJavaExpression duration + , toJavaExpression designation + , toJavaExpression name + , toJavaExpression repetitions + , toJavaExpression series + ] ++ ")" + + Running userCode date duration designation name distance speed -> + "new Running(" ++ intercalate ", " [ + userCode + , toJavaExpression date + , toJavaExpression duration + , toJavaExpression designation + , toJavaExpression name + , toJavaExpression distance + , toJavaExpression speed + ] ++ ")" + + Trail userCode date duration designation name distance elevationGain elevationLoss trailType -> + "new Trail(" ++ intercalate ", " [ + userCode + , toJavaExpression date + , toJavaExpression duration + , toJavaExpression designation + , toJavaExpression name + , toJavaExpression distance + , toJavaExpression elevationGain + , toJavaExpression elevationLoss + , toJavaExpression trailType + ] ++ ")" + + WeightSquat userCode date duration designation name repetitions series weight -> + "new WeightSquat(" ++ intercalate ", " [ + userCode + , toJavaExpression date + , toJavaExpression duration + , toJavaExpression designation + , toJavaExpression name + , toJavaExpression repetitions + , toJavaExpression series + , toJavaExpression weight + ] ++ ")" + +instance JavaData [Activity] where + javaTypeName = const "List" + toJavaExpression = toJavaExpressionList -- | MakeItFit training plan data TrainingPlan = TrainingPlan - UUID -- ^ user code - UUID -- ^ training plan code - String -- ^ training plan name - [MyTuple Int Activity] -- ^ activities (list of (Integer, Activity) tuples) - MakeItFitDate -- ^ date when the training plan was created + String -- ^ Java expression for the user's UUID + [(Int, Activity)] -- ^ Activities [(Repetitions, Activity)] + MakeItFitDate -- ^ Training plan Start date deriving (Show, Eq) -data MyTuple a b = MyTuple a b - deriving (Eq, Show) - -instance Arbitrary TrainingPlan where - arbitrary = do - userCode <- genUUID - planCode <- genUUID - letter <- elements ['A'..'Z'] - let name = "Plano " ++ [letter] - n <- choose (1, 7) - activities <- vectorOf n arbitrary - date <- arbitrary - return $ TrainingPlan userCode planCode name (zip [1..n] activities) date +genTrainingPlanActivity :: String -> Gen (Int, Activity) +genTrainingPlanActivity userCode = do + repetitions <- choose (1, 10) + activity <- genActivity userCode + return (repetitions, activity) + +-- | Generates a MakeItFit activity +genTrainingPlan :: String -- ^ Java expression with the activity's user UUID + -> Gen TrainingPlan -- ^ Generated training plan +genTrainingPlan userCode = do + activityCount <- choose (1, 7) + activities <- vectorOf activityCount (genTrainingPlanActivity userCode) + date <- arbitrary + return $ TrainingPlan userCode activities date + +instance JavaData (Int, Activity) where + javaTypeName = const "MyTuple" + toJavaExpression (i, a) = + "new MyTuple(" ++ toJavaExpression i ++ ", " ++ toJavaExpression a ++ ")" + +instance JavaData [(Int, Activity)] where + javaTypeName = const "List>" + toJavaExpression = toJavaExpressionList instance JavaData TrainingPlan where - toJava (TrainingPlan name duration activities) = - "new TrainingPlan(" ++ - toJava name ++ ", " ++ - show duration ++ ", " ++ - "List.of(" ++ intercalate ", " (map toJava activities) ++ ")" ++ - ")" - + javaTypeName = const "TrainingPlan" + + -- NOTE: this won't have the activities set + toJavaExpression (TrainingPlan userCode _ date) = + "new TrainingPlan(" ++ userCode ++ ", " ++ toJavaExpression date ++ ")" + + toJavaVariable name plan@(TrainingPlan userCode activities _) = + [ + javaTypeName plan ++ " " ++ name ++ " = " ++ toJavaExpression plan ++ ";" + , name ++ ".addActivities(" ++ toJavaExpression + ( + map (\(i, a) -> (i, changeActivityUserUUID (userCode) a)) activities + ) ++ ");" + ]