def get_stock_at_time(self, day_ago=None, time=None): def count_bobine_mere_in_plan_prod(p_plan_prod): tours = p_plan_prod.tours length_tour = p_plan_prod.bobines_filles_selected[0].length length_bobine_mere = self.length bobine_mere = (tours * length_tour) / length_bobine_mere return bobine_mere if day_ago is None and not time: return from gestion.stores.plan_prod_store import plan_prod_store stock = self.init_stock stock_therme = self.init_stock_therme from commun.utils.timestamp import timestamp_at_day_ago ts = time if time else timestamp_at_day_ago(day_ago) for plan_prod in plan_prod_store.plans_prods: if timestamp_at_day_ago(0) <= plan_prod.start < ts: code_bobine_mere_plan_prod = \ plan_prod.bobine_papier_selected.code if self.color != "POLYPRO" else plan_prod.bobine_poly_selected.code if code_bobine_mere_plan_prod == self.code: stock -= count_bobine_mere_in_plan_prod(plan_prod) stock_therme -= count_bobine_mere_in_plan_prod(plan_prod) if day_ago is not None: self.stock_at_day_ago = round(stock, 1) self.stock_therme_at_day_ago = round(stock_therme, 1) else: self.stock_at_time = round(stock, 1) self.stock_therme_at_time = round(stock_therme, 1)
def get_stock_at_time(self, day_ago=None, time=None): def get_piste_in_plan_prod(p_bobine, p_plan_prod): piste = 0 for p_bobine_in_plan_prod in p_plan_prod.bobines_filles_selected: if p_bobine.code == p_bobine_in_plan_prod.code: piste += 1 if p_bobine_in_plan_prod.pose == 0 else p_bobine_in_plan_prod.pose return piste if piste > 0 else None if day_ago is None and not time: return from gestion.stores.plan_prod_store import plan_prod_store stock = self.init_stock stock_therme = self.init_stock_therme from commun.utils.timestamp import timestamp_at_day_ago ts = time if time else timestamp_at_day_ago(day_ago) for plan_prod in plan_prod_store.plans_prods: if timestamp_at_day_ago(0) <= plan_prod.start < ts: piste_in_plan_prod = get_piste_in_plan_prod(self, plan_prod) if piste_in_plan_prod: stock += piste_in_plan_prod * plan_prod.tours stock_therme += piste_in_plan_prod * plan_prod.tours if day_ago is not None: self.stock_at_day_ago = stock self.stock_therme_at_day_ago = stock_therme else: self.stock_at_time = stock self.stock_therme_at_time = stock_therme self.get_etat()
def update_data(self, prods, events, day_ago): self.start_day = timestamp_at_time(timestamp_at_day_ago(day_ago), hours=DEBUT_PROD_MATIN) self.end_day = timestamp_at_time(timestamp_at_day_ago(day_ago), hours=FIN_PROD_SOIR) self.prods = prods self.events = events self.update_ui()
def get_bobines(self): self.dict_bobines.clear() from gestion.stores.plan_prod_store import plan_prod_store day_ago = settings_store_gestion.day_ago start = timestamp_at_day_ago(day_ago) end = timestamp_at_day_ago(settings_store_gestion.day_ago - 1) for prod in plan_prod_store.plans_prods: if start <= prod.start < end: self.dict_bobines = self.add_bobines_from_prod(prod=prod, p_dict=self.dict_bobines)
def add_defaut_stop_prod(self): day_ago = settings_store_gestion.day_ago start_defaut_stop_prod = timestamp_at_time( timestamp_at_day_ago(day_ago), hours=FIN_PROD_SOIR_VENDREDI) end_defaut_stop_prod = timestamp_at_time(timestamp_at_day_ago(day_ago), hours=FIN_PROD_SOIR) Database.create_event_prod(start=start_defaut_stop_prod, end=end_defaut_stop_prod, p_type="stop") self.update()
def update_plans_prods(self, tasks=None, day_ago=None): def get_end_from_index_task(index, p_day_ago): for p_task in tasks: if p_task.index == index and p_task.day_ago == p_day_ago: return p_task.plan_prod.end def get_task_from_index(index, p_day_ago): for p_task in tasks: if p_task.index == index and p_task.day_ago == p_day_ago: return p_task day_ago_for_next_update = [] current_day_ago = self.day_ago if day_ago is None else day_ago if tasks is None: tasks = self.get_tasks_at_day_ago(day_ago=current_day_ago) for task in tasks: if task.index == 0: if current_day_ago != task.day_ago: current_day_ago = task.day_ago from gestion.stores.plan_prod_store import plan_prod_store start_day = timestamp_at_time( timestamp_at_day_ago(day_ago=current_day_ago), hours=DEBUT_PROD_MATIN) last_plan_prod = plan_prod_store.get_last_plan_prod( start_plan_prod=start_day) task.plan_prod.update_from_start(start=start_day, last_plan_prod=last_plan_prod) else: last_plan_prod = get_task_from_index( task.index - 1, p_day_ago=current_day_ago).plan_prod start = get_end_from_index_task(index=task.index - 1, p_day_ago=current_day_ago) fin_prod = FIN_PROD_SOIR_VENDREDI if is_vendredi( last_plan_prod.start) else FIN_PROD_SOIR if start > timestamp_at_time( timestamp_at_day_ago(day_ago=current_day_ago), hours=fin_prod): start = timestamp_at_time( timestamp_at_day_ago(day_ago=current_day_ago - 1), hours=DEBUT_PROD_MATIN - 1) task.plan_prod.update_from_start( start=start, last_plan_prod=last_plan_prod) if current_day_ago - 1 not in day_ago_for_next_update: day_ago_for_next_update.append(current_day_ago - 1) else: task.plan_prod.update_from_start( start=start, last_plan_prod=last_plan_prod) self.update_plan_prod_on_database(plan_prod=task.plan_prod) from gestion.stores.plan_prod_store import plan_prod_store plan_prod_store.sort_plans_prods() if day_ago_for_next_update: for day_ago in day_ago_for_next_update: self.update_plans_prods(day_ago=day_ago) self.SETTINGS_CHANGED_SIGNAL.emit()
def add_data(self): try: ts = timestamp_at_day_ago(self.day_ago) self.update_raison_from_database() if self.data and self.day_ago > 0: pass else: new_data = Database.get_speeds(self.start * 1000, self.end * 1000) if not new_data: return False, [] self.data = clean_data_per_second(data=new_data, start=self.start, end=self.end) if self.day_ago > 0: metrage = Database.get_metrages_for_one_day(start_time=ts) metrage = metrage[0] if not metrage: metrage = self.get_live_stat(self.data, ts) else: metrage = self.get_live_stat(self.data, ts) self.metrage_matin = round(metrage[0]) self.metrage_soir = round(metrage[1]) return True, self.update_arret() except: return False, []
def get_start_for_new_plan_prod(self): tasks = self.get_tasks_at_day_ago(day_ago=self.day_ago) start = timestamp_at_time(timestamp_at_day_ago(self.day_ago), hours=DEBUT_PROD_MATIN) for task in tasks: if task.start == start: start = task.end return start
def update_arret(self): ts = timestamp_at_day_ago(self.day_ago) list_arrets_database = Database.get_arret(self.start, self.end) self.dic_arret_from_database(list_arrets_database) list_arrets_data = self.list_new_arret_data() list_new_arret = self.update_dic_arret(list_arrets_data) self.arrets = self.convert_dic_to_array(self.dic_arret) if self.arrets: self.get_arret_stat(ts) return list_new_arret
def set_day_ago(self, day_ago): # Test si nouveau jour est un samedi ou dimanche new_day = timestamp_at_day_ago(day_ago) week_day = datetime.fromtimestamp(new_day).weekday() if 5 <= week_day <= 6: if self.day_ago < day_ago: self.set_day_ago(day_ago + 1) else: self.set_day_ago(day_ago - 1) else: self.set(day_ago=day_ago, zoom=1)
def get_pdf(self): defaut_path = 'I:\Programme mondon\Rapport production bobines' ts = timestamp_at_day_ago(settings_store.day_ago) defaut_name = "{} Rapport production bobines".format( timestamp_to_inverse_date(ts)) file_names = QFileDialog.getSaveFileName(self, caption='Enregistrer sous', directory='{}\{}.pdf'.format( defaut_path, defaut_name), filter="Fichiers pdf (*.pdf)") if not file_names[0]: return save_pdf(self.rapport, filename=file_names[0], preview=True)
def get_tasks_at_day_ago(day_ago): tasks = [] from gestion.stores.plan_prod_store import plan_prod_store for plan_prod in plan_prod_store.plans_prods: if plan_prod.start > timestamp_at_day_ago(day_ago): if plan_prod.start > timestamp_at_day_ago(day_ago - 1): day_ago -= 1 tasks.append( Task(start=plan_prod.start, plan_prod=plan_prod, end=plan_prod.end, day_ago=day_ago)) tasks = sorted(tasks, key=lambda t: t.get_start()) index = 0 day_ago = None for task in tasks: if day_ago is None: day_ago = task.day_ago if task.day_ago < day_ago: day_ago = task.day_ago index = 0 task.index = index index += 1 return tasks
def list_new_arret_data(self): """ S'occupe de créer la liste des arrêts machines du store par rapport aux nouvelles données :return: Un tableau de tuple de timestamp (début de l'arrêt, fin de l'arrêt) """ # Récupère la liste des vitesses speeds = self.data # Récupère le timestamp du jours du store ts = timestamp_at_day_ago(self.day_ago) # Test si on est un vendredi vendredi = is_vendredi(ts) # Les équipes commence toujours à 6H start = DEBUT_PROD_MATIN # La fin de journée est 22h sauf le vendredi 20h end = FIN_PROD_SOIR_VENDREDI if vendredi else FIN_PROD_SOIR # Définit les bornes de recherche d'arrêt dans les données start_ts = timestamp_at_time(ts, hours=start) end_ts = timestamp_at_time(ts, hours=end) # Initialisation des variables speed_is_0 = False arrets = [] start = 0 end = 0 # On boucle sur le tableau de vitesse de store for value in speeds: # On test si la vitesse est dans la borne de recherche if value[0] < end_ts: # On test si la vitesse est inférieure à 60 # On assimile une vitesse inférieure à 60 à machine à l'arrêt if 0 <= value[1] <= VITESSE_LIMITE_ASSIMILATION_ARRET: # Si on est pas déja dans un arrêt on définit le début de l'arrêt if not speed_is_0: start = value[0] end = value[0] speed_is_0 = True # Si on vient de sortir d'un arrêt on ajoute l'arrêt à la liste d'arrêts elif speed_is_0: if start != end: arrets.append((start, end)) start = 0 end = 0 speed_is_0 = False else: continue # Si on sort de la boucle avec un arrêt en cours on ajoute le dernier arrêt à la liste d'arrêts if speed_is_0 and start != end: arrets.append((start, end)) return arrets
def get_event_from_database(self): self.events = [] event_on_data_base = Database.get_event_prod() day_ago = settings_store_gestion.day_ago if settings_store_gestion.day_ago > 0 else 0 start_ts = timestamp_at_day_ago(day_ago) for event in event_on_data_base: if start_ts < event[2]: from commun.model.event import Event event = Event(p_type=event[1], start=event[2], end=event[3], info=event[4], p_id=event[0], ensemble=event[5]) self.events.append(event) self.sort_events()
def get_arret(self): """ S'occupe de créer une liste de models Arret pour le moment de la journée courante :return: """ # Récupere le store courant store = data_store_manager.get_current_store() # Stock la liste des arrets trier par ordre croissant (par rapport au start) arrets = store.arrets # Récupere le dictionnaire des arrets dic_arret = store.dic_arret # Récupere le timestamp du jours actuel ts = timestamp_at_day_ago(self.day_ago) # Check si on est un vendredi # Dans ce cas les équipes travail 7h (6h-13h,13h-21h) vendredi = timestamp_to_day(ts) == "vendredi" start = DEBUT_PROD_MATIN mid = FIN_PROD_MATIN_VENDREDI if vendredi else DEBUT_PROD_SOIR end = FIN_PROD_SOIR_VENDREDI if vendredi else FIN_PROD_SOIR # Definit les bornes de sélection des arret en fonction du moment de la journée (matin ou soir) if self.moment == "matin": end = mid if self.moment == "soir": start = mid start_ts = timestamp_at_time(ts, hours=start) end_ts = timestamp_at_time(ts, hours=end) # Initialise la liste d'arret list_arret = [] # Parcours la liste des arret for arret in arrets: start_arret = arret[0] end_arret = arret[1] # Si le debut de l'arret est compris dans les bornes de selection if end_ts >= start_arret >= start_ts: # Et si la fin de l'arret est bien definit if end_arret > 0: # On ajoute a la liste des arrets l'models Arret stocké dans le dictionnaire list_arret.append(dic_arret[start_arret]) # Sinon on continue la boucle else: continue self.list_arret = list_arret
def draw_speed(self, p): def get_speed(): speeds = data_store_manager.get_current_store().data i = 0 current_sum = 0 new_data = [] for speed in speeds: if i < 90: value = speed[1] current_sum += value else: i = 0 new_data.append(round(current_sum / 90)) current_sum = 0 i += 1 new_data.append(round(current_sum / 90)) return new_data speeds = get_speed() i = 0 for speed in speeds: speed = speed if speed < 190 else 190 color = color_vert if speed > VITESSE_LIMITE_ASSIMILATION_ARRET else color_rouge draw_rectangle(p, self.X_CHART + i, self.H_CHART - speed + self.Y_CHART, 1, speed + 1, color) i += 1 current_store = data_store_manager.get_current_store() vendredi = timestamp_to_day(timestamp_at_day_ago( current_store.day_ago)) == "vendredi" if vendredi: draw_rectangle(p, self.X_CHART + (40 * 14), self.Y_CHART, 40 * 2, self.H_CHART, color_gris_moyen) draw_text(p, self.X_CHART + (40 * 14), self.Y_CHART, 40 * 2, self.H_CHART, color_gris_fonce, align="C", font_size=10, text="Vendredi")
def get_ratio_prod(moment): from production.stores.data_store_manager import data_store_manager current_store = data_store_manager.get_current_store() # Récupere le ts actuel ts_actuel = timestamp_now() # Calcul de la production maximum vendredi = timestamp_to_day(timestamp_at_day_ago( current_store.day_ago)) == "vendredi" if moment == "soir": debut_prod = FIN_PROD_MATIN_VENDREDI if vendredi else FIN_PROD_MATIN else: debut_prod = DEBUT_PROD_MATIN if moment == "matin": fin_prod = FIN_PROD_MATIN_VENDREDI if vendredi else FIN_PROD_MATIN else: fin_prod = FIN_PROD_SOIR_VENDREDI if vendredi else FIN_PROD_SOIR if ts_actuel < timestamp_at_time(current_store.start, hours=fin_prod): total_s = (ts_actuel - timestamp_at_time(current_store.start, hours=debut_prod)) else: total_s = 3600 * (fin_prod - debut_prod) max_prod = VITESSE_MOYENNE_MAXI * total_s / 60 # Calcul le métrage total de la période metrage_total = 0 if moment == "total": metrage_total = current_store.metrage_matin + current_store.metrage_soir if moment == "matin": metrage_total = current_store.metrage_matin if moment == "soir": metrage_total = current_store.metrage_soir # Calcul ratio if max_prod > 0 and metrage_total >= 0: ratio = metrage_total / max_prod * 100 if ratio > 100: ratio = 100 else: ratio = 0 return round(ratio, 1)
def create_master_stat(): back_ground_master_stat = MondonWidget() back_ground_master_stat.set_background_color(color_blanc) back_ground_master_stat.set_border(color=color_bleu_dune, size=1) hbox_master_stat = QHBoxLayout(back_ground_master_stat) current_store = data_store_manager.get_current_store() date = timestamp_to_date_little(timestamp_at_day_ago(current_store.day_ago)) label_date = QLabel(date) label_date.setStyleSheet(black_16_label_stylesheet) time_imprevu = current_store.imprevu_arret_time_matin + current_store.imprevu_arret_time_soir imprevu_time_str = str(timedelta(seconds=round(time_imprevu))) text_imprevu_time = ("{time} d'arrêt imprévu".format(time=imprevu_time_str)) label_imprevu_time = QLabel(text_imprevu_time) imprevu_time_label_stylesheet = red_16_bold_label_stylesheet if time_imprevu > 0 \ else green_16_bold_label_stylesheet label_imprevu_time.setStyleSheet(imprevu_time_label_stylesheet) metrage_total = current_store.metrage_matin + current_store.metrage_soir label_metrage_total = QLabel("{}m".format(affiche_entier(metrage_total))) label_metrage_total.setStyleSheet(black_16_label_stylesheet) percent = get_ratio_prod("total") label_percent = QLabel("{}%".format(percent)) if percent < 25: percent_stylesheet = red_16_bold_label_stylesheet elif percent < 50: percent_stylesheet = orange_16_bold_label_stylesheet else: percent_stylesheet = green_16_bold_label_stylesheet label_percent.setStyleSheet(percent_stylesheet) hbox_master_stat.addWidget(label_date, alignment=Qt.AlignLeft) hbox_master_stat.addWidget(label_percent) hbox_master_stat.addWidget(label_metrage_total) hbox_master_stat.addWidget(label_imprevu_time, alignment=Qt.AlignRight) return back_ground_master_stat
def create_bloc_arret(moment): vbox = QVBoxLayout() current_store = data_store_manager.get_current_store() arrets = current_store.arrets vendredi = timestamp_to_day(timestamp_at_day_ago(current_store.day_ago)) == "vendredi" if moment == "matin": start_hour = DEBUT_PROD_MATIN end_hour = FIN_PROD_MATIN_VENDREDI if vendredi else FIN_PROD_MATIN else: start_hour = FIN_PROD_MATIN_VENDREDI if vendredi else FIN_PROD_MATIN end_hour = FIN_PROD_SOIR_VENDREDI if vendredi else FIN_PROD_SOIR start_ts = timestamp_at_time(timestamp_at_day_ago(current_store.day_ago), hours=start_hour) end_ts = timestamp_at_time(timestamp_at_day_ago(current_store.day_ago), hours=end_hour) # Trie les arrets par ordre chronologique arrets = sorted(arrets, key=lambda arret: arret[0]) limit_imprevu = 0 def count_valid_arret(arrets, limit_imprevu): count = 0 for arret in arrets: start_arret = arret[0] end_arret = arret[1] type = arret[2][0].type if arret[2] else "non renseigné" if (start_ts <= start_arret <= end_ts and end_arret - start_arret >= 1800)\ or (start_ts <= start_arret <= end_ts and type == "Imprévu" and end_arret - start_arret >= limit_imprevu): count += 1 return count > 10 while count_valid_arret(arrets, limit_imprevu): limit_imprevu += 10 for arret in arrets: container_arret = QVBoxLayout() container_arret.setSpacing(0) start_arret = arret[0] end_arret = arret[1] type = arret[2][0].type if arret[2] else "non renseigné" if (start_ts <= start_arret <= end_ts and end_arret - start_arret >= 1800) \ or (start_ts <= start_arret <= end_ts and type == "Imprévu" and end_arret - start_arret >= limit_imprevu): start = str(timestamp_to_hour_little(start_arret)) duree = str(timedelta(seconds=round(end_arret - start_arret))) text_arret = "Arrêt {type} à {start}, durée {duree}".format(type=type, start=start, duree=duree) if type == "Imprévu" or type == "non renseigné": stylesheet = red_12_bold_label_stylesheet else: stylesheet = blue_12_bold_label_stylesheet title_arret = QLabel(text_arret) title_arret.setStyleSheet(stylesheet) container_arret.addWidget(title_arret, alignment=Qt.AlignTop) def add_label_to_container(vbox, label): label.setStyleSheet(black_12_label_stylesheet) label.setWordWrap(True) vbox.addWidget(label, alignment=Qt.AlignTop) vbox.addLayout(container_arret) if arret[2]: if type == "Imprévu": for raison in arret[2]: if raison.type == "Nettoyage" or raison.type == "Prévu": continue add_label_to_container(container_arret, QLabel(raison.raison)) else: add_label_to_container(container_arret, QLabel(arret[2][0].raison)) else: add_label_to_container(container_arret, QLabel("")) vbox.addLayout(container_arret) vbox.addStretch(1) return vbox
def update_data_metrage(): """ Donnee enregistree de maniere fiable depuis le 23/10/2017 semaine 43 (timestamp: 1508709600) Fonction appele a chaque demarrage de l'application Parcour tout les jours depuis le 23/10/2017 jusqu'a hier Verifie si les donnees metrages de chaque jour est renseigne en base de donnee Si les donnees metrages n'existes pas on les calculs et on les inserts en base de donnee """ def get_jour_metrage(): """ Recupere les jours ou les metrages sont deja renseignees en base de donnee :return: Une liste des jours """ list_jour_metrage = Database.get_all_jour_metrages() clean_list = [] for jour_metrage in list_jour_metrage: ts = jour_metrage[0] clean_list.append(ts) return clean_list def is_vendredi(ts): """ Test si le jour d'un timestamp est vendredi :param ts: L etimestamp a tester :return: True si on est vendredi """ return timestamp_to_day(ts) == "vendredi" def get_metrage(data, vendredi): """ Calcul les metrages de l'equipe du matin et du soir Prend en compte si on est vendredi :param data: Les donnees triees par seconde :param vendredi: True si on traite des donnees d'un vendredi :return: Les valeurs arrondies du metrage matin et soir """ metrage_matin = 0 metrage_soir = 0 fin_prod_matin = FIN_PROD_MATIN_VENDREDI if vendredi else FIN_PROD_MATIN for value in data: ts = value[0] metrage = value[1] / 60 if value[1] > 0 else 0 if ts < timestamp_at_time(ts, hours=fin_prod_matin): metrage_matin += metrage else: metrage_soir += metrage return round(metrage_matin), round(metrage_soir) # On recupere la liste des jours ou le metrage est renseigne en base de donnee list_jour_metrage_on_db = get_jour_metrage() # Debut des donnees fiable start_data_record = 1508709600 # Duree d'un jour en ms ts_to_one_day = 86400 # Timestamp du debut du jour actuel start_ts_of_current_day = timestamp_at_day_ago(day_ago=0) start_day = start_data_record while start_day < start_ts_of_current_day: if start_day in list_jour_metrage_on_db: pass else: start_time = timestamp_at_time(ts=start_day, hours=DEBUT_PROD_MATIN) end_time = timestamp_at_time(start_day, hours=FIN_PROD_SOIR) speed_data = Database.get_speeds(start_time=start_time * 1000, end_time=end_time * 1000) clean_speed_data = clean_data_per_second(speed_data, start_time, end_time) total_metrage = get_metrage(data=clean_speed_data, vendredi=is_vendredi(start_day)) Database.insert_jour_metrages(ts_jour=start_day, metrage_matin=total_metrage[0], metrage_soir=total_metrage[1]) start_day = timestamp_after_day_ago(start_day, day_ago=1) return True
def get_timestamp_at_time(hours, p_min): ts_at_day_ago = timestamp_at_day_ago(settings_store_gestion.day_ago) ts = timestamp_at_time(ts=ts_at_day_ago, hours=hours, min=p_min) return ts
def update_label(self): ts = timestamp_at_day_ago(settings_store.day_ago) date = timestamp_to_date(ts).capitalize() self.label_date.setMinimumWidth(self.MINIMUN_WIDTH_LABEL) self.label_date.setAlignment(Qt.AlignCenter) self.label_date.setText(date)
def get_drawing_info(self): timestamp = timestamp_at_day_ago(settings_store.day_ago) debut = timestamp_at_time(timestamp, hours=chart_min_hour) fin = timestamp_at_time(timestamp, hours=chart_max_hour) ech = (fin - debut) / (settings_store.zoom * self.get_chart_width()) return debut, fin, ech
def externat_get_pdf(self): ts = timestamp_at_day_ago(settings_store.day_ago) file_names =\ 'I:\Programme mondon/rp_prod/{} Rapport production bobines.pdf'.format(timestamp_to_inverse_date(ts)) save_pdf(self.rapport, filename=file_names, preview=False)
def update_data(self): day_ago = settings_store_gestion.day_ago self.prods = self.get_prods(start=timestamp_at_day_ago(day_ago)) self.events = self.get_events(start=timestamp_at_day_ago(day_ago)) self.gant_prod.update_data(prods=self.prods, events=self.events, day_ago=day_ago)