# ###############################################
# ################ TRAIN 1 RULES ################
# ###############################################
# intervals while the train 1 is away.
away1 = [train1.status == "away"];

#  *******    RULE 1   ********
#=======================================================
# the speed of the train while is away must be greater
# than 60 and less than 61
#=======================================================
speed1 = train1.speed;
forall it2_1: away1 {
       it2_1 always ((speed1 > 60) && (speed1 < 61))
};
 

#  *******    RULE 2  (DSL 5, T5)  ********
#=======================================================
# Train 1 and 2 can't cross at the same time
#=======================================================

cross2 = [train2.status == "crossing"];

forall c1 : [train1.status == "crossing"] {
       forall c2 : cross2 {
              !(c1 intersects c2)
      }
};

# OR

cross1 = [train1.status == "crossing"];

forall c1 : cross1 {
       forall c2 : cross2 {
              (end(c1) is_before [,] start(c2)) ||
              (end(c2) is_before [,] start(c1))
      }
};
#  *******    RULE 3   ********
#=======================================================
# After crossing, the train has to start reporting
#=======================================================

report1 = [train1.status == "reporting"];

forall c1 : cross1 {
       exists c2 : report1 {
              end(c1) == start(c2)
      }
};

#  *******    RULE 4  ********
#=======================================================
# After crossing, the train has to be reporting
#=======================================================
#JLF report1 is an interval
forall c1 : cross1 {
      c1 after report1
};
 

#  *******    RULE 5   ********
#=======================================================
# After waiting, the train has to be crossing
#=======================================================

wait1 = [train1.status == "waiting"];
wait2 = [train2.status == "waiting"];

forall c1 : wait1 {
      c1 after cross1
};

# In this case the result if false because of the last
# interval.

forall c2 : wait2 {
      c2 after cross2
};

#  *******    RULE 6   ********
#=======================================================
# Before reporting, the train was crossing
#=======================================================

forall c1 : report1 {
      c1 before cross1
};

#  *******    RULE 7   ********
#=======================================================
#  1 second after crossing, the report must be finished.
#=======================================================
 
forall c1 : cross1 {
       exists c2 : report1 {
           end(c1) -> end(c1)~> 1 include end(c2)
      }
};

#  *******    RULE 7   ********
#=======================================================
#  Within 4 and 6 miliseconds, the report must be finished.
#=======================================================
forall c1 : cross1 {
       exists c2 : report1 {
           end(c1)~> 0.004 -> end(c1)~> 0.006 include end(c2)
      }
};

# OR:

forall c1 : cross1 {
      exists c2 : report1 {
           (time(end(c1)) <= time(start(c2))) &&
           (time(end(c1)) <= time(start(c2)))
      }
};

# ----------------------------------------------
#
# Basic examples
#
# ----------------------------------------------

#  *******    RULE (DSL 8)   ********
#=======================================================
# always the speed have to be possitive.
#=======================================================

-> always (train1.speed >= 0);

# OR

speed1 = train1.speed;
-> always (speed1 >= 0);

# but sometimes is waiting so, this should be false.
-> always (speed1 > 0);

#  *******    RULE (DSL 14)   ********
#=======================================================
# Allways, the duration of crossing has to be greater than 2 msec.
# and less than 15 msec.
#=======================================================
forall a_1:cross1 {
    (duration(a_1) > 0.002) &&
    (duration(a_1) < 0.015)
};

#  *******    RULE (DSL 17, 20, 21, 22, 24 and 25)  ********
#=======================================================
# the status of the train is never unknown.
#=======================================================
unknown = [train1.status == "unknown"];
cardinal( unknown ) == 0;

#  *******    RULE (DSL 27, 28)   ********
#=======================================================
# if the train is not waiting, it has to be moving (speed >0).
#=======================================================
not_waiting1 = -> -- wait1;
moving = [train1.speed >0];
empty = not_waiting1 -- moving;
cardinal(empty) == 0;
empty = moving -- not_waiting1;
cardinal(empty) == 0;
 

# ----------------------------------------------
#
# Relations between actions
#
# ----------------------------------------------

#  *******    RULE (DSL 12)   ********
#=======================================================
# After the train is away, it has to be crossing or waiting
#=======================================================
after_away1 = wait1 union cross1;
forall a_1:away1 {
       exists a2_1:after_away1 {
              a_1 after a2_1
        }
};

# OR

forall a_1:away1 {
              a_1 after after_away1
};

#  *******    RULE T1, T4    ********
#=======================================================
#  between 4 and 6 miliseconds
#  after crossing, the report must be finished.
#=======================================================
forall c1 : cross1 {
       exists c2 : report1 {
           time(end(c1)) > (time(end(c2)) - 0.006) &&
           time(end(c1)) < (time(end(c2)) - 0.004)
      }
};

#  *******    RULE    ********
#=======================================================
# The train can't go from away to report without crossing
#=======================================================
away_report1 = end(away1) -> start(report1);

forall a2_1:away_report1 {
       exists a1_1:cross1 {
              a2_1 include a1_1
        }
};

# NOTE: An interval
# include the start event but not the end. That explains why
# the first print returns true and the second false.
a2_1 include start(a2_1);
a2_1 include end(a2_1);

#  *******    RULE (DSL 9)   ********
#=======================================================
# if train 1 is not waiting, then it has to be crossing, away
# or reporting.
#=======================================================
cross_away_rep1 = cross1 union away1 union report1;
not_wait1 = -> -- wait1;
cardinal(cross_away_rep1 -- not_wait1)== 0;

# OR BETTER

cross_away_rep1 = cross1 | away1 | report1;
not_wait1 = -> -- wait1;
cardinal(cross_away_rep1 -- not_wait1)== 0;

#  *******    RULE    ********
#=======================================================
# train 1 can be either waiting or in one of these states:
#  crossing, away or reporting.
#=======================================================
cross_away_rep1 = cross1 | away1 |  report1;
not_wait1 = -> -- wait1;
(cardinal(cross_away_rep1 -- not_wait1) == 0) &&
       (cardinal(not_wait1 -- cross_away_rep1) == 0);

# OR
#  PROBLEMS WITH THE NULL INTERVALS!!!

forall a_1:wait1 {
        forall a2_1:cross_away_rep1 {
               !(a2_1 intersects a_1)
        }
 };

#  *******    RULE 6   ********
#=======================================================
# 1 milisecond before start reporting, the semaphore must
# be in green
#=======================================================
one_msec_bef =  0.001 <~ start(report1);
trail_in_green = [train1.semaphore == "green"];
forall e1_1:one_msec_bef {
     exists a1_1:trail_in_green {
               (a1_1 include e1_1)
      }
 };
 
# OR

train1semaphore = train1.semaphore;
forall a1_1:report1 {
           0.001 <~ start(a1_1) -> start(a1_1) begin
               (train1semaphore == "green")
};
# printclock x;
#  *******    RULE 6   ********
#=======================================================
# 1 milisecond before start reporting, the semaphore must
# be in green and must keep in red at least until start
# reporting.
#=======================================================
one_msec_bef_int = 0.001 <~ start(report1) -> start(report1);
trail_in_green = [train1.semaphore == "green"];
forall a2_1:one_msec_bef_int {
     exists a1_1:trail_in_green {
               (a1_1 include a2_1)
     }
};
 
# OR
# A SOLUTION VERY TIME CONSUMING:
forall a1_1:report1 {
           0.001 <~ start(a1_1) -> start(a1_1) always
               (train1semaphore == "green")
};
 

#  *******    RULE 6   ********
#=======================================================
# only one train can be waiting on the first trail
# this is, between two crossing only one arrival is possible
#=======================================================
btw_cross1 = end(cross1) -> end(cross1);
forall a1_1:btw_cross1 {
       (cardinal(tmp:wait1 st start(tmp) inside a1_1) == 1)
};

#  *******    RULE 6 (GENERAL CASE)  ********
#=======================================================
# only N trains can be waiting on the first trail
# this is, between two crossing only one arrival is possible
#=======================================================
N = 10;
before_cross1 =  <- start(cross1);
forall a1_1:before_cross1 {
       (cardinal(tmp:wait1 st start(tmp) inside a1_1) <=
            (N + cardinal(tmp:cross1 st start(tmp) inside a1_1)))
};
 

#  *******    RULE   ********
#=======================================================
# in a interval of T msec the train 1 can't change the speed in
# more than max;
#=======================================================
T = 0.001;
max = 70;
speed1 = train1.speed;
# forall a1_1:train1. ->train1.~>T {
#       tmp = (speed1 - speed1[time(start(a1_1))]);
#        a1_1 always ((tmp < max) &&
#                    (tmp > (-max)))
# };
forall a1_1:train1. ->train1.~>T {
       a1_1 always (((speed1 - speed1[time(start(a1_1))]) < max) &&
                     ((speed1 - speed1[time(start(a1_1))]) > (0-max)))
};

#=======================================================
#
#               END OF FILE
#
#=======================================================