Compare View

switch
from
...
to
 
Commits (3)
src/core/pyros_django/majordome/agent/Agent.py
... ... @@ -154,7 +154,7 @@ import config.old_config as config_old
154 154 #from config import *
155 155  
156 156 from majordome.models import AgentSurvey, AgentCmd, AgentLogs
157   -from user_mgmt.models import Period
  157 +from user_mgmt.models import Period, Quota
158 158  
159 159 from vendor.guitastro.src.guitastro import Ephemeris
160 160 import pickle
... ... @@ -3592,7 +3592,17 @@ class Agent:
3592 3592 val[0] = d_total
3593 3593 val[-1] = d_total - val[-2]
3594 3594 # --- update db TODO
3595   -
  3595 + quota = Quota()
  3596 + quota_attributes = {}
  3597 + quota_attributes["id_period"] = operiod.id
  3598 + quota_attributes["night_id"] = night
  3599 + quota_attributes["d_previousq"] = d_prev
  3600 + quota_attributes["d_currentq"] = d_cur
  3601 + quota_attributes["d_totalq"] = d_total
  3602 + quota_attributes["d_nextq"] = d_total - d_cur
  3603 + quota.set_attributes_and_save(quota_attributes)
  3604 + operiod.quota = quota
  3605 + operiod.save()
3596 3606 #log.info(f"Write {filename=}")
3597 3607 #pickle.dump(night_info, open(filename, "wb"))
3598 3608 return night_info
... ...
src/core/pyros_django/misc/fixtures/initial_fixture_dev_TZ.json
... ... @@ -287,8 +287,7 @@
287 287 "fields": {
288 288 "name": "Admin",
289 289 "desc": "",
290   - "priority": 8,
291   - "quota": 9999.0
  290 + "priority": 8
292 291 }
293 292 },
294 293 {
... ... @@ -297,8 +296,7 @@
297 296 "fields": {
298 297 "name": "Observer",
299 298 "desc": "",
300   - "priority": 2,
301   - "quota": 9999.0
  299 + "priority": 2
302 300 }
303 301 },
304 302 {
... ... @@ -307,8 +305,7 @@
307 305 "fields": {
308 306 "name": "TAC",
309 307 "desc": "",
310   - "priority": 1,
311   - "quota": 9999.0
  308 + "priority": 1
312 309 }
313 310 },
314 311 {
... ... @@ -317,8 +314,7 @@
317 314 "fields": {
318 315 "name": "Management board member",
319 316 "desc": "",
320   - "priority": 3,
321   - "quota": 9999.0
  317 + "priority": 3
322 318 }
323 319 },
324 320 {
... ... @@ -327,8 +323,7 @@
327 323 "fields": {
328 324 "name": "Operator",
329 325 "desc": "",
330   - "priority": 4,
331   - "quota": 9999.0
  326 + "priority": 4
332 327 }
333 328 },
334 329 {
... ... @@ -337,8 +332,7 @@
337 332 "fields": {
338 333 "name": "Unit-PI",
339 334 "desc": "",
340   - "priority": 7,
341   - "quota": 9999.0
  335 + "priority": 7
342 336 }
343 337 },
344 338 {
... ... @@ -347,8 +341,7 @@
347 341 "fields": {
348 342 "name": "Unit-board",
349 343 "desc": "",
350   - "priority": 6,
351   - "quota": 9999.0
  344 + "priority": 6
352 345 }
353 346 },
354 347 {
... ... @@ -357,8 +350,7 @@
357 350 "fields": {
358 351 "name": "Visitor",
359 352 "desc": "Account without any privilege",
360   - "priority": 0,
361   - "quota": 0.0
  353 + "priority": 0
362 354 }
363 355 },
364 356 {
... ... @@ -366,7 +358,7 @@
366 358 "pk": 2,
367 359 "fields": {
368 360 "name": "CNRS",
369   - "quota": 20
  361 + "f_quota": 0.2
370 362 }
371 363 },
372 364 {
... ... @@ -374,7 +366,7 @@
374 366 "pk": 1,
375 367 "fields": {
376 368 "name": "CNES",
377   - "quota": 80
  369 + "f_quota": 0.8
378 370 }
379 371 },
380 372 {
... ...
src/core/pyros_django/scheduling/A_Scheduler.py
... ... @@ -222,6 +222,12 @@ class A_Scheduler(Agent):
222 222 # 'vote_referee2'
223 223 """
224 224  
  225 +
  226 + def update_db_quota_sequence(sequence, quota_attributes, id_period, night_id, d_total=sequence_info['duration']):
  227 + sequence_quota = sequence.quota
  228 + sp_quota = sequence.scientific_program
  229 + institute_quota =
  230 +
225 231 def _compute_schedule_1(self):
226 232 """Simple scheduler based on selection-insertion one state algorithm.
227 233  
... ...
src/core/pyros_django/scp_mgmt/A_SCP_Manager.py
... ... @@ -17,7 +17,7 @@ for short_path in short_paths:
17 17  
18 18 # Project imports
19 19 from majordome.agent.Agent import Agent, build_agent
20   -from user_mgmt.models import PyrosUser, SP_Period, Period, SP_Period, SP_Period_Guest, SP_PeriodWorkflow
  20 +from user_mgmt.models import PyrosUser, Institute, SP_Period, Period, SP_Period, SP_Period_Guest, SP_PeriodWorkflow
21 21 import vendor.guitastro.src.guitastro as guitastro
22 22  
23 23 # Django imports
... ... @@ -229,6 +229,9 @@ class A_SCP_Manager(Agent):
229 229 next_sp_to_be_notified = next_sp.filter(status=SP_Period.STATUSES_ACCEPTED,is_valid = True)
230 230 self.send_mail_to_observers_for_notification(next_sp_to_be_notified)
231 231 SP_PeriodWorkflow.objects.create(period=self.period,action=SP_PeriodWorkflow.NOTIFICATION)
  232 + self.update_sun_moon_ephems()
  233 + self.set_quota_for_institutes(self.period.id)
  234 + self.set_quota_for_sp(self.period.id)
232 235  
233 236 def routine_process_body(self):
234 237 print("routine automatic period workflow")
... ... @@ -243,66 +246,27 @@ class A_SCP_Manager(Agent):
243 246 for n in range(int((end_date - start_date).days)):
244 247 yield start_date + timedelta(n)
245 248  
246   - def do_generate_ephem_moon_and_sun_for_period(self, period_id:int):
247   - # Obsolete TODO
248   - period = Period.objects.get(id=period_id)
249   - period_start_date = period.start_date
250   - period_end_date = period.end_date
251   -
252   - root_path = os.environ.get("PROJECT_ROOT_PATH")
253   - os.chdir(root_path)
254   -
255   - home = guitastro.Home(self._oc["config"].getHome())
256   - self._fn.longitude(home.longitude)
257   -
258   - ephem_data_night_folder = self._fn.rootdir
259   - if os.path.exists(ephem_data_night_folder):
260   - period_id = str(period.id)
261   - # form correct period string
262   - if len(str(period.id)) < 3:
263   - while len(period_id) < 3:
264   - period_id = "0" + period_id
265   - period_id = "P" + period_id
266   - ephem_data_night_folder = os.path.join(ephem_data_night_folder, period_id)
267   - if not os.path.exists(ephem_data_night_folder):
268   - os.makedirs(ephem_data_night_folder, exist_ok=True)
269   - for single_date in self.daterange(period_start_date, period_end_date):
270   - current_date = single_date.strftime("%Y%m%d")
271   -
272   - eph = guitastro.Ephemeris()
273   - target_sun = "sun"
274   - ephem_sun = eph.target2night(target_sun, current_date, None, None)
275   -
276   - self._fn.fcontext_create("pyros_eph", "Ephemeris PyROS")
277   - self._fn.fcontext = "pyros_eph"
278   - self._fn.pathnaming("PyROS.eph.1")
279   - self._fn.rootdir = "/tmp/eph"
280   - self._fn.extension = ".f"
281   - param = {}
282   - param['period'] = period_id
283   - param['date'] = current_date
284   - param['unit'] = self.pconfig.unit_name
285   - param['version'] = 1
286   - param['target'] = "sun"
287   - fname = self._fn.naming_set(param)
288   - file_name_sun = self._fn.join(fname)
289   -
290   - # moon parameters
291   - param['target'] = "moon"
292   - fname = self._fn.naming_set(param)
293   - file_name_moon = self._fn.join(fname)
294   - os.chdir(ephem_data_night_folder)
295   - pickle.dump(ephem_sun, open(f"{file_name_sun}.f","wb"))
296   - target_moon = "moon"
297   - ephem_moon = eph.target2night(target_moon, current_date, None, None)
298   - pickle.dump(ephem_moon, open(f"{file_name_moon}.f","wb"))
299   -
300   -
301   -
302   -
303   - # lire tous les fichiers sun de la period et appliquer le sky_elev pour déterminer le quota total de période
304   - # prendre le champ alt &
305   - # -> prendre tous les éléments en dessous de duskelev (cf l412 d'A_Sheduler, exemple 14 des éphémérides pour trier ces éléménts) et faire un sum
  249 + def set_quota_for_institutes(self, id_period):
  250 + for institute in Institute.objects.all():
  251 + f_quota = institute.f_quota
  252 + # the lowest id of quota table for this period should be the first night of the period
  253 + period_quota = Period.objects.get(id=id_period).quota
  254 + institute_quota = period_quota.convert_to_quota(f_quota)
  255 + new_quota = Quota()
  256 + new_quota.set_attributes_and_save(institute_quota)
  257 + institute.quota = new_quota
  258 + institute.save()
  259 +
  260 + def set_quota_for_SP(self, id_period):
  261 + period = Period.objects.get(id=id_period)
  262 + for sp_period in SP_Period.objects.filter(period=period)
  263 + sp = sp_period.scientific_program
  264 + institute = sp.institute
  265 + institute_quota = institute.quota
  266 + new_quota = Quota()
  267 + quota_attributes = institute_quota.convert_to_quota(sp.f_quota)
  268 + new_quota.set_attributes_and_save(quota_attributes)
  269 +
306 270  
307 271 if __name__ == "__main__":
308 272  
... ...
src/core/pyros_django/scp_mgmt/forms.py
... ... @@ -39,13 +39,13 @@ class SP_PeriodForm(forms.ModelForm):
39 39 fields = (
40 40 #"period",
41 41 "public_visibility",
42   - "quota_minimal",
43   - "quota_nominal",
44   - "quota_allocated",
45   - "over_quota_duration",
46   - "over_quota_duration_allocated",
47   - "token",
48   - "token_allocated",
  42 + # "quota_minimal",
  43 + # "quota_nominal",
  44 + # "quota_allocated",
  45 + # "over_quota_duration",
  46 + # "over_quota_duration_allocated",
  47 + # "token",
  48 + # "token_allocated",
49 49 "vote_referee1",
50 50 "reason_referee1",
51 51 "vote_referee2",
... ...
src/core/pyros_django/scp_mgmt/models.py
1   -#from django.db import models
  1 +from django.db import models
  2 +
  3 +
  4 +class Quota(models.Model):
  5 + id_period = models.BigIntegerField(blank=True, null=True)
  6 + night_id = models.CharField(max_length=8, null=True, blank=True, db_index=True)
  7 + d_totalq = models.BigIntegerField(default=0, blank=True, null=True)
  8 + d_totalx = models.BigIntegerField(default=0, blank=True, null=True)
  9 +
  10 + d_previousq = models.BigIntegerField(default=0, blank=True, null=True)
  11 + d_previousx = models.BigIntegerField(default=0, blank=True, null=True)
  12 +
  13 + d_currentq = models.BigIntegerField(default=0, blank=True, null=True)
  14 + d_currentx = models.BigIntegerField(default=0, blank=True, null=True)
  15 +
  16 + d_passedq = models.BigIntegerField(default=0, blank=True, null=True)
  17 + d_passedx = models.BigIntegerField(default=0, blank=True, null=True)
  18 +
  19 + d_scheduleq = models.BigIntegerField(default=0, blank=True, null=True)
  20 + d_schedulex = models.BigIntegerField(default=0, blank=True, null=True)
  21 +
  22 + d_nextq = models.BigIntegerField(default=0, blank=True, null=True)
  23 + d_nextx = models.BigIntegerField(default=0, blank=True, null=True)
  24 +
  25 + @property
  26 + def d_total(self):
  27 + return self.d_totalq + self.d_totalx
  28 +
  29 + @property
  30 + def d_previous(self):
  31 + return self.d_previousq + self.d_previousx
  32 +
  33 + @property
  34 + def d_current(self):
  35 + return self.d_currentq + self.d_currentx
  36 +
  37 + @property
  38 + def d_passed(self):
  39 + return self.d_passedq + self.d_passedx
  40 +
  41 + @property
  42 + def d_schedule(self):
  43 + return self.d_scheduleq + self.d_schedulex
  44 +
  45 + @property
  46 + def d_next(self):
  47 + return self.d_nextq + self.d_nextx
  48 +
  49 + def set_attributes_and_save(self, quota_attributes:dict):
  50 +
  51 + if quota_attributes.get("id_period") != None:
  52 + self.id_period = quota_attributes["id_period"]
  53 + if quota_attributes.get("night_id") != None:
  54 + self.night_id = quota_attributes["night_id"]
  55 + if quota_attributes.get("d_totalq") != None:
  56 + self.d_totalq = quota_attributes["d_totalq"]
  57 + if quota_attributes.get("d_totalx") != None:
  58 + self.d_totalx = quota_attributes["d_totalx"]
  59 + if quota_attributes.get("d_previousq") != None:
  60 + self.d_previousq = quota_attributes["d_previousq"]
  61 + if quota_attributes.get("d_previousx") != None:
  62 + self.d_previousx = quota_attributes["d_previousx"]
  63 + if quota_attributes.get("d_currentq") != None:
  64 + self.d_currentq = quota_attributes["d_currentq"]
  65 + if quota_attributes.get("d_currentx") != None:
  66 + self.d_currentx = quota_attributes["d_currentx"]
  67 + if quota_attributes.get("d_scheduleq") != None:
  68 + self.d_scheduleq = quota_attributes["d_scheduleq"]
  69 + if quota_attributes.get("d_schedulex") != None:
  70 + self.d_schedule = quota_attributes["d_schedulex"]
  71 + if quota_attributes.get("d_nextq") != None:
  72 + self.d_nextq = quota_attributes["d_nextq"]
  73 + if quota_attributes.get("d_nextx") != None:
  74 + self.d_nextx = quota_attributes["d_nextx"]
  75 + self.save()
  76 +
  77 + def convert_to_quota(self, f_quota):
  78 + quota_institute = {}
  79 +
  80 + quota_institute["d_totalq"] = self.d_totalq * f_quota
  81 + quota_institute["d_totalx"] = self.d_totalx * f_quota
  82 + quota_institute["d_previousq"] = self.d_previousq * f_quota
  83 + quota_institute["d_previousx"] = self.d_previousx * f_quota
  84 + quota_institute["d_currentq"] = self.d_currentq * f_quota
  85 + quota_institute["d_currentx"] = self.d_currentx * f_quota
  86 + quota_institute["d_passedq"] = self.d_passedq * f_quota
  87 + quota_institute["d_passedx"] = self.d_passedx * f_quota
  88 + quota_institute["d_scheduleq"] = self.d_scheduleq * f_quota
  89 + quota_institute["d_schedulex"] = self.d_schedulex * f_quota
  90 + quota_institute["d_nextq"] = self.d_nextq * f_quota
  91 + quota_institute["d_nextx"] = self.d_nextx * f_quota
  92 +
  93 + return quota_institute
... ...
src/core/pyros_django/seq_submit/models.py
... ... @@ -34,6 +34,7 @@ from django.db.models import Q
34 34  
35 35 # Project imports
36 36 from user_mgmt.models import PyrosUser, ScientificProgram, Period
  37 +from scp_mgmt.models import Quota
37 38 # DeviceCommand is used by class Command
38 39 sys.path.append("../../..")
39 40 from vendor.guitastro.src.guitastro import FileNames, Ima
... ... @@ -349,8 +350,9 @@ class Sequence(models.Model):
349 350 obsolete = models.BooleanField(default=False)
350 351 processing = models.BooleanField(default=False)
351 352 flag = models.CharField(max_length=45, blank=True, null=True)
352   - period = models.ForeignKey(Period, on_delete=models.DO_NOTHING, related_name="sequences", blank=True, null=True)
  353 + period = models.ForeignKey(Period, on_delete=models.DO_NOTHING, related_name="sequence_period", blank=True, null=True)
353 354 #period = models.ForeignKey("Period", on_delete=models.DO_NOTHING, related_name="sequences", blank=True, null=True)
  355 + quota = models.ForeignKey(Quota, on_delete=models.DO_NOTHING,related_name="sequence_quotas", blank=True, null=True)
354 356  
355 357 start_date = models.DateTimeField(
356 358 blank=True, null=True, default=timezone.now, editable=True)
... ...
src/core/pyros_django/user_mgmt/models.py
... ... @@ -37,6 +37,11 @@ from django.db.models.query import QuerySet
37 37 from django.utils import timezone
38 38  
39 39  
  40 +# Pyros import
  41 +
  42 +from scp_mgmt.models import Quota
  43 +
  44 +
40 45  
41 46  
42 47 # Project imports
... ... @@ -52,7 +57,6 @@ class UserLevel(models.Model):
52 57 name = models.CharField(max_length=45, blank=True, null=True)
53 58 desc = models.TextField(blank=True, null=True)
54 59 priority = models.IntegerField(blank=True, null=True)
55   - quota = models.FloatField(blank=True, null=True)
56 60  
57 61 class Meta:
58 62 managed = True
... ... @@ -79,9 +83,11 @@ class Country(models.Model):
79 83 class Institute(models.Model):
80 84 name = models.CharField(max_length=100, blank=False,
81 85 null=False, unique=True)
82   - # quota %
83   - quota = models.IntegerField(
84   - validators=[MinValueValidator(0), MaxValueValidator(100)])
  86 + # fraction quota
  87 + f_quota = models.FloatField(
  88 + validators=[MinValueValidator(0), MaxValueValidator(1)], blank=True, null=True)
  89 +
  90 + quota = models.ForeignKey(Quota, on_delete=models.DO_NOTHING,related_name="institute_quotas", blank=True, null=True)
85 91 #representative_user = models.ForeignKey("PyrosUser", on_delete=models.DO_NOTHING,related_name="institutes",default=1)
86 92  
87 93 def __str__(self) -> str:
... ... @@ -90,6 +96,8 @@ class Institute(models.Model):
90 96 class Meta:
91 97 db_table = "institute"
92 98  
  99 +
  100 +
93 101 class ScienceTheme(models.Model):
94 102 name = models.CharField(max_length=120, blank=False, null=False, default="", unique=True)
95 103 def __str__(self) -> str:
... ... @@ -367,6 +375,8 @@ class Period(models.Model):
367 375 data_accessibility_duration = models.PositiveIntegerField(
368 376 blank=True, null=True, default=365*10, editable=True)
369 377  
  378 + quota = models.ForeignKey(Quota, on_delete=models.DO_NOTHING,related_name="period_quotas", blank=True, null=True)
  379 +
370 380 @property
371 381 def end_date(self):
372 382 return self.start_date + relativedelta(days=self.exploitation_duration)
... ... @@ -461,11 +471,11 @@ class ScientificProgram(models.Model):
461 471 description_short = models.TextField(default="", max_length=320)
462 472 description_long = models.TextField(default="")
463 473 institute = models.ForeignKey('Institute', on_delete=models.DO_NOTHING, related_name="scientific_programs")
464   - sp_pi = models.ForeignKey('PyrosUser', on_delete=models.DO_NOTHING, related_name="Scientific_Program_Users")
  474 + sp_pi = models.ForeignKey('PyrosUser', on_delete=models.DO_NOTHING, related_name="scientific_Program_Users")
465 475 science_theme = models.ForeignKey(ScienceTheme, on_delete=models.DO_NOTHING, related_name="scientific_program_theme", default=1)
466 476 is_auto_validated = models.BooleanField(default=False)
467 477 objects = ScientificProgramManager()
468   -
  478 + quota = models.ForeignKey(Quota, on_delete=models.DO_NOTHING,related_name="scientific_program_quotas", blank=True, null=True)
469 479 class Meta:
470 480 managed = True
471 481 db_table = 'scientific_program'
... ... @@ -525,14 +535,6 @@ class SP_Period(models.Model):
525 535 is_valid = models.TextField(
526 536 choices=IS_VALID, default=IS_VALID_REJECTED, blank=True)
527 537 status = models.TextField(choices=STATUSES, default=STATUSES_DRAFT)
528   - quota_minimal = models.PositiveIntegerField(default=0)
529   - quota_nominal = models.PositiveIntegerField(default=0)
530   - quota_allocated = models.PositiveIntegerField(default=0, blank=True)
531   - quota_remaining = models.PositiveIntegerField(default=0, blank=True)
532   - over_quota_duration = models.PositiveIntegerField(default=0)
533   - over_quota_duration_allocated = models.PositiveIntegerField(
534   - default=0, blank=True)
535   - over_quota_duration_remaining = models.PositiveIntegerField(default=0)
536 538 token = models.PositiveIntegerField(default=0)
537 539 token_allocated = models.PositiveIntegerField(default=0, blank=True)
538 540 token_remaining = models.PositiveIntegerField(default=0, blank=True)
... ...