simulator.py
5.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
from scheduler.models import Scheduler
from pyrosapp.models import *
from django.contrib.auth.models import User
import urllib.request as urllib2
from html.parser import HTMLParser
import math
import operator
from decimal import Decimal
import time
from operator import attrgetter
class MyHTMLParser(HTMLParser):
'''
Subclassing HTMLParser to access the data properly
'''
def __init__(self):
HTMLParser.__init__(self)
self.data = []
def handle_data(self, data):
self.data.append(data)
def handle_comment(self, data):
pass
class Simulator():
'''
Simulates the creation of a planning thanks to an HTML file
'''
def __init__(self):
pass
def simulate(self, sequences_file):
'''
ENTRY POINT
Parse the file with sequences, then call the Scheduler simulation function and give the result to the view
:param sequences_file : HTML file containing sequences description
:returns : a tuple (Schedule, list of sequences) after the scheduling process
'''
file = urllib2.urlopen(sequences_file)
data = str(file.read())
parser = MyHTMLParser()
parser.feed(data)
"""filter unwanted \n and other data"""
filteredList = list(map(lambda s: s.strip(), parser.data))
pageText = "".join(filteredList[11:])
rawSequences = pageText.split("\\n")
del rawSequences[0]
del rawSequences[len(rawSequences)-1]
rawSequences = [sequence for sequence in rawSequences if len(sequence) > 0]
"""Create the default models linked to the sequences"""
sp = ScientificProgram()
country = Country()
usr_lvl = UserLevel()
usr = User(username="toto")
py_usr = PyrosUser(user=usr, country=country, userlevel=usr_lvl, quota=1000)
req = Request(scientificprogram=sp, pyros_user=py_usr)
seq_type = SequenceType()
scheduler = Scheduler()
"""Create the sequences"""
sequences = []
for rawSequence in rawSequences:
sequenceArray = rawSequence.split(" ")
id_seq = sequenceArray[0]
priority = int(sequenceArray[2])
''' transforms the duration (seconds) in days (86,400s in a day)'''
duration = Decimal(float(sequenceArray[4]) / 86400.0)
jd1 = Decimal("%.8f" % float(sequenceArray[5]))
jd2 = Decimal("%.8f" % float(sequenceArray[6]))
sequence = Sequence(request=req, sequencetype=seq_type, schedule=scheduler.schedule, status=Sequence.OBSERVABLE,
name="sequence", id=id_seq, priority=priority, duration=duration, jd1=jd1, jd2=jd2, t_prefered=-1)
sequences.append(sequence)
# 1) trouver le nombre qu'on retrouve le plus souvent en troncature de jd1 (faire un dico)
days = {}
for sequence in sequences:
truncated = math.floor(float(sequence.jd1))
if truncated in days.keys():
days[truncated] += 1
else:
days[truncated] = 1
maximum_truncated = max(days.keys(), key=(lambda key: days[key]))
# 2) virer toutes les séquences qui n'ont pas ce jd1 en troncature
sequences = [sequence for sequence in sequences if math.floor(float(sequence.jd1)) == maximum_truncated]
# 3) set le plan_start et le plan_end en fonction du plus petit jd1 et du plus grand jd2
scheduler.schedule.plan_start = -1
scheduler.schedule.plan_end = -1
for sequence in sequences:
if scheduler.schedule.plan_start == -1 or sequence.jd1 < scheduler.schedule.plan_start:
scheduler.schedule.plan_start = sequence.jd1
if scheduler.schedule.plan_end == -1 or sequence.jd2 > scheduler.schedule.plan_end:
scheduler.schedule.plan_end = sequence.jd2
start = time.time()
schedule, sequences = scheduler.simulate_schedule(sequences)
end = time.time()
print("Duration : ", end - start)
self.test_sequences_validity(schedule, sequences)
return (schedule, sequences)
def test_sequences_validity(self, schedule, sequences):
'''
For PLANNED sequences, tests if :
- all the sequences are in the schedule
- there is no overlap between sequences
- [tsp - tep] is in [jd1 - jd2]
- tep < tsp
'''
sequences.sort(key=attrgetter('tsp'))
for index, sequence in enumerate(sequences):
if sequence.status == Sequence.PLANNED:
if sequence.tsp > sequence.tep:
raise ValueError("tep < tsp ...")
if sequence.tsp < schedule.plan_start or schedule.plan_end < sequence.tep:
raise ValueError("[tsp;tep] not in [plan_start;plan_end]")
if sequence.tsp < sequence.jd1 or sequence.jd2 < sequence.tep:
raise ValueError("[tsp;tep] not in [jd1;jd2]")
if index > 0 and sequence.tsp < sequences[index - 1].tep:
raise ValueError("There is a sequence overlap")