<commit_before>{-
  Copyright 2017 The CodeWorld Authors. All rights reserved.

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-}

import CodeWorld.Prediction

import qualified Data.IntMap as IM
import qualified Data.Map as M
import Data.Bifunctor
import Data.List
import Text.Printf
import System.Exit
import Test.QuickCheck

type Event = Int
type TimeStamp = Double
type TEvent = (TimeStamp, Maybe Event)

type EventsTodo = ([TimeStamp], IM.IntMap [TEvent])
type EventsDone = ([TimeStamp], IM.IntMap [TEvent])

type LogEntry = Either Double Event
type Log = [LogEntry]

type Check = (EventsDone, Either Double (Int, TEvent))
type CheckReport = (Check, Future Log, Future Log, Future Log)

-- Fake state and handle functions

step :: Double -> Log -> Log
step dt = (Left dt :)

handle :: Event -> Log -> Log
handle dt = (Right dt :)

-- Global constant
rate :: Double
rate = 1/4 -- decimal display


-- Generation of random schedules

newtype GenEventsTodo = GenEventsTodo EventsTodo

instance Arbitrary GenEventsTodo where
    arbitrary = do
        -- get ascending positive timestamps
        tss  <- map getPositive . getOrdered <$> arbitrary
        p1ts <- map getPositive . getOrdered <$> arbitrary
        p2ts <- map getPositive . getOrdered <$> arbitrary
        -- some are just pings, some are real events
        p1 <- traverse (addEvent 0) p1ts
        p2 <- traverse (addEvent 1) p2ts
        return $ GenEventsTodo (tss, IM.fromList [(0,p1), (1,p2)])
      where addEvent i ts = do
               coin <- arbitrary
               if coin then return $ (ts, Nothing)
                       else return $ (ts, Just i)

    -- shrinking removes poitns of the list, and
    -- further reduces singleton lists mildly
    -- (the original shrink would get us too close to epsilon)
    shrink (GenEventsTodo (tss,m)) = map GenEventsTodo $ unShrinkOne $
        ((,) <$> listShrinkOne' mildlySmaller tss
             <*> traverse (listShrinkOne' (firstA mildlySmaller)) m)
      where mildlySmaller x | x > 1     = [x - 1]
                            | otherwise = []

-- The actual check:
-- Exhaustively search the order in which these events could happen
-- Memoize every initial segment
-- Ensure that all possible ways reach the same conclusion.

failedChecks :: EventsTodo -> [CheckReport]
failedChecks schedule = map mkReport $ filter (not . check) allChecks<commit_msg>Update the test to produce test chases with non-unique timestamps<commit_after>{-
  Copyright 2017 The CodeWorld Authors. All rights reserved.

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-}

import CodeWorld.Prediction

import qualified Data.IntMap as IM
import qualified Data.Map as M
import Data.Bifunctor
import Data.List
import Text.Printf
import System.Exit
import Test.QuickCheck

type Event = Int
type TimeStamp = Double
type TEvent = (TimeStamp, Maybe Event)

type EventsTodo = ([TimeStamp], IM.IntMap [TEvent])
type EventsDone = ([TimeStamp], IM.IntMap [TEvent])

type LogEntry = Either Double Event
type Log = [LogEntry]

type Check = (EventsDone, Either Double (Int, TEvent))
type CheckReport = (Check, Future Log, Future Log, Future Log)

-- Fake state and handle functions

step :: Double -> Log -> Log
step dt = (Left dt :)

handle :: Event -> Log -> Log
handle dt = (Right dt :)

-- Global constant
rate :: Double
rate = 1/4 -- decimal display


-- Generation of random schedules

newtype GenEventsTodo = GenEventsTodo EventsTodo deriving Show

genTimeStamps :: Gen [Double]
genTimeStamps = fmap (drop 1 . scanl (+) 0) $
    sized $ \n -> do
        k <- choose (0,n)
        sequence [ genOne | _ <- [1..k] ]
  where
    genOne = frequency [(5, getPositive <$> arbitrary), (1, return 0)]

instance Arbitrary GenEventsTodo where
    arbitrary = do
        -- get ascending positive timestamps
        tss <- genTimeStamps
        qts <- sublistOf tss
        p1ts  <- sublistOf tss
        p2ts  <- sublistOf tss
        -- some are just pings, some are real events
        p1 <- traverse (addEvent 0) p1ts
        p2 <- traverse (addEvent 1) p2ts
        return $ GenEventsTodo (qts, IM.fromList [(0,p1), (1,p2)])
      where addEvent i ts = do
               coin <- arbitrary
               if coin then return $ (ts, Nothing)
                       else return $ (ts, Just i)

    -- shrinking removes poitns of the list, and
    -- further reduces singleton lists mildly
    -- (the original shrink would get us too close to epsilon)
    shrink (GenEventsTodo (tss,m)) = map GenEventsTodo $ unShrinkOne $
        ((,) <$> listShrinkOne' mildlySmaller tss
             <*> traverse (listShrinkOne' (firstA mildlySmaller)) m)
      where mildlySmaller x | x > 1     = [x - 1]
                            | otherwise = []

-- The actual check:
-- Exhaustively search the order in which these events could happen
-- Memoize every initial segment
-- Ensure that all possible ways reach the same conclusion.

failedChecks :: EventsTodo -> [CheckReport]
failedChecks schedule = map mkReport $ filter (not . check) allChecks
{'fraction_non_alphanumeric': 0.08444148936170212, 'fraction_numerical': 0.009142287234042553, 'mean_word_length': 2.9046073977936406, 'pattern_counts': {'":': 0, '<': 26, '<?xml version=': 0, '>': 24, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3617099', 'n_tokens_mistral': 1766, 'n_tokens_neox': 1683, 'n_words': 711}