Commit d22b9d9f authored by Allvey's avatar Allvey

矿卡型号控制,修复BUG

parent 8cc6dd61
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -47,6 +47,9 @@ class DumpInfo(WalkManage): ...@@ -47,6 +47,9 @@ class DumpInfo(WalkManage):
self.period_map_para_load() self.period_map_para_load()
self.period_walk_para_load() self.period_walk_para_load()
# 参数初始化
self.para_period_update()
def get_unloading_time(self): def get_unloading_time(self):
return self.unloading_time return self.unloading_time
......
...@@ -47,6 +47,9 @@ class ExcavatorInfo(WalkManage): ...@@ -47,6 +47,9 @@ class ExcavatorInfo(WalkManage):
self.period_map_para_load() self.period_map_para_load()
self.period_walk_para_load() self.period_walk_para_load()
# 参数初始化
self.para_period_update()
# def period_map_para_load(self): # def period_map_para_load(self):
# # 关系映射 # # 关系映射
# self.excavator_uuid_to_index_dict = device_map.excavator_uuid_to_index_dict # self.excavator_uuid_to_index_dict = device_map.excavator_uuid_to_index_dict
...@@ -177,7 +180,7 @@ class ExcavatorInfo(WalkManage): ...@@ -177,7 +180,7 @@ class ExcavatorInfo(WalkManage):
def update_excavator_material(self): def update_excavator_material(self):
for excavator_id in dynamic_excavator_set: for excavator_id in dynamic_excavator_set:
load_area_id = session_mysql.query(Dispatch).filter_by(exactor_id=excavator_id).first().load_area_id load_area_id = session_mysql.query(Dispatch).filter_by(exactor_id=excavator_id).first().load_area_id
excavator_material_id = session_postgre.query(DiggerArea).filter_by(Id=load_area_id).first().Material excavator_material_id = session_postgre.query(DiggingWorkArea).filter_by(Id=load_area_id).first().Material
self.excavator_material[excavator_id] = excavator_material_id self.excavator_material[excavator_id] = excavator_material_id
def para_period_update(self): def para_period_update(self):
......
...@@ -42,6 +42,14 @@ class TruckInfo(WalkManage): ...@@ -42,6 +42,14 @@ class TruckInfo(WalkManage):
# self.sim_truck_ava_time = np.zeros(self.dynamic_truck_num) # self.sim_truck_ava_time = np.zeros(self.dynamic_truck_num)
# 矿卡有效载重 # 矿卡有效载重
self.payload = np.zeros(self.dynamic_truck_num) self.payload = np.zeros(self.dynamic_truck_num)
# 矿卡时速
self.empty_speed = {}
self.heavy_speed = {}
# 矿卡长宽
self.geo_length = {}
self.geo_width = {}
# 矿卡型号
self.size = {}
# 矿卡当前行程(第一列为出发地序号, 第二列为目的地序号) # 矿卡当前行程(第一列为出发地序号, 第二列为目的地序号)
self.truck_current_trip = np.full((self.dynamic_truck_num, 2), -1) self.truck_current_trip = np.full((self.dynamic_truck_num, 2), -1)
# 矿卡挖机绑定关系 # 矿卡挖机绑定关系
...@@ -68,6 +76,8 @@ class TruckInfo(WalkManage): ...@@ -68,6 +76,8 @@ class TruckInfo(WalkManage):
self.period_map_para_load() self.period_map_para_load()
self.period_walk_para_load() self.period_walk_para_load()
self.para_period_update()
# def period_map_para_load(self): # def period_map_para_load(self):
# # 关系映射 # # 关系映射
# self.excavator_uuid_to_index_dict = device_map.excavator_uuid_to_index_dict # self.excavator_uuid_to_index_dict = device_map.excavator_uuid_to_index_dict
...@@ -118,6 +128,12 @@ class TruckInfo(WalkManage): ...@@ -118,6 +128,12 @@ class TruckInfo(WalkManage):
def get_payload(self): def get_payload(self):
return self.payload return self.payload
def get_width(self):
return self.geo_width
def get_length(self):
return self.geo_length
################################################ short term update ################################################ ################################################ short term update ################################################
# 更新矿卡当前任务 # 更新矿卡当前任务
...@@ -327,6 +343,8 @@ class TruckInfo(WalkManage): ...@@ -327,6 +343,8 @@ class TruckInfo(WalkManage):
logger.error("读取矿卡有效载重异常-矿卡型号信息缺失") logger.error("读取矿卡有效载重异常-矿卡型号信息缺失")
logger.error(es) logger.error(es)
print(self.payload)
def update_truck_priority(self): def update_truck_priority(self):
self.truck_priority = np.zeros(self.dynamic_truck_num) self.truck_priority = np.zeros(self.dynamic_truck_num)
...@@ -399,7 +417,6 @@ class TruckInfo(WalkManage): ...@@ -399,7 +417,6 @@ class TruckInfo(WalkManage):
logger.error(es) logger.error(es)
def update_truck_dump_exclude(self): def update_truck_dump_exclude(self):
pass pass
def update_truck_material(self): def update_truck_material(self):
...@@ -470,6 +487,17 @@ class TruckInfo(WalkManage): ...@@ -470,6 +487,17 @@ class TruckInfo(WalkManage):
if dump_material_id != material: if dump_material_id != material:
self.dump_material_bind_modify[truck_index][dump_index] = 1000000 self.dump_material_bind_modify[truck_index][dump_index] = 1000000
def update_truck_spec(self):
for truck_id in dynamic_truck_set:
self.size[truck_id] = session_mysql.query(Equipment).filter_by(id=truck_id).first().equipment_spec
def update_truck_size(self):
self.update_truck_spec()
for truck_id in dynamic_truck_set:
truck_spec_id = self.size[truck_id]
self.geo_length[truck_id] = session_mysql.query(EquipmentSpec).filter_by(id=truck_spec_id).first().length
self.geo_width[truck_spec_id] = session_mysql.query(EquipmentSpec).filter_by(id=truck_spec_id).first().width
# print("-------------------------------------------") # print("-------------------------------------------")
# print("truck") # print("truck")
# print(self.truck_uuid_to_index_dict) # print(self.truck_uuid_to_index_dict)
...@@ -482,6 +510,15 @@ class TruckInfo(WalkManage): ...@@ -482,6 +510,15 @@ class TruckInfo(WalkManage):
# print(dynamic_dump_set) # print(dynamic_dump_set)
# print(self.dump_material_bind_modify) # print(self.dump_material_bind_modify)
def update_truck_speed(self):
for truck_id in dynamic_truck_set:
self.empty_speed[truck_id] = session_mysql.query(EquipmentSpec.max_speed). \
Join(Equipment, EquipmentSpec.id == Equipment.equipment_spec). \
filter(Equipment.id == truck_id).first()
self.heavy_speed[truck_id] = session_mysql.query(EquipmentSpec.max_speed). \
Join(Equipment, EquipmentSpec.id == Equipment.equipment_spec). \
filter(Equipment.id == truck_id).first()
def para_period_update(self): def para_period_update(self):
# print("Para truck update!") # print("Para truck update!")
......
...@@ -11,6 +11,7 @@ from settings import * ...@@ -11,6 +11,7 @@ from settings import *
from static_data_process import * from static_data_process import *
from settings import * from settings import *
from para_config import * from para_config import *
from equipment.truck import TruckInfo
M = 1000000 M = 1000000
...@@ -22,7 +23,9 @@ class PathPlanner(WalkManage): ...@@ -22,7 +23,9 @@ class PathPlanner(WalkManage):
# 路段集合 # 路段集合
self.lane_set = {} self.lane_set = {}
# 车辆长度(暂) # 车辆长度(暂)
self.truck_length = 113 self.truck = TruckInfo()
self.truck.update_truck_size()
self.truck_length = float(sum(self.truck.get_length().values())) / len(self.truck.get_length())
# 装载区数量 # 装载区数量
self.num_of_load_area = len(set(update_load_area())) self.num_of_load_area = len(set(update_load_area()))
# 卸载区数量 # 卸载区数量
......
...@@ -537,9 +537,12 @@ class Dispatcher(WalkManage): ...@@ -537,9 +537,12 @@ class Dispatcher(WalkManage):
# 卸载设备卸载时间 # 卸载设备卸载时间
unloading_time = self.dump.get_unloading_time() unloading_time = self.dump.get_unloading_time()
# 路网信息 # 路网信息
walk_time_park_to_excavator = walk_manage.get_walk_time_park_to_excavator() walk_time_park_to_excavator = walk_manage.get_walk_time_park_to_excavator() \
walk_time_to_dump = walk_manage.get_walk_time_to_dump() * (empty_speed / self.truck.empty_speed[truck_id])
walk_time_to_excavator = walk_manage.get_walk_time_to_excavator() walk_time_to_dump = walk_manage.get_walk_time_to_dump() * \
(heavy_speed / self.truck.heavy_speed[truck_id])
walk_time_to_excavator = walk_manage.get_walk_time_to_excavator() * \
(empty_speed / self.truck.empty_speed[truck_id])
# 出入场时间 # 出入场时间
loading_task_time = self.excavator.get_loading_task_time() loading_task_time = self.excavator.get_loading_task_time()
......
#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2021/8/24 14:56
# @Author : Opfer
# @Site :
# @File : schedule_test.py
# @Software: PyCharm
import datetime
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.schedulers.blocking import BlockingScheduler
from apscheduler.jobstores.memory import MemoryJobStore
from apscheduler.executors.pool import ThreadPoolExecutor, ProcessPoolExecutor
def my_job(id='my_job'):
print(id, '-->', datetime.datetime.now())
jobstores = {'default': MemoryJobStore()}
executors = {'default': ThreadPoolExecutor(10)}
job_defaults = {'coalesce': False, 'max_instances': 10}
scheduler = BlockingScheduler(jobstores=jobstores, executors=executors, job_defaults=job_defaults)
scheduler.add_job(my_job, args=['job_interval'], id='ins1', trigger='interval', seconds=5)
scheduler.add_job(my_job, args=['job_interval'], id='ins2', trigger='interval', seconds=5)
if __name__ == '__main__':
try:
scheduler.start()
except SystemExit:
print('exit')
exit()
\ No newline at end of file
...@@ -324,11 +324,17 @@ class EquipmentSpec(Base): ...@@ -324,11 +324,17 @@ class EquipmentSpec(Base):
id = Column(VARCHAR(36), primary_key=True) id = Column(VARCHAR(36), primary_key=True)
capacity = Column(Integer) capacity = Column(Integer)
mining_abililty = Column(Float) mining_abililty = Column(Float)
length = Column(Float)
width = Column(Float)
max_speed = Column(Float)
def __init__(self, id, capacity, mining_abililty): def __init__(self, id, capacity, mining_abililty, length, width, max_speed):
self.id = id self.id = id
self.capacity = capacity self.capacity = capacity
self.mining_abililty = mining_abililty self.mining_abililty = mining_abililty
self.length = length
self.width = width
self.max_speed = max_speed
class LoadInfo(Base): class LoadInfo(Base):
__tablename__ = 'sys_loadinfo' __tablename__ = 'sys_loadinfo'
...@@ -393,6 +399,7 @@ class DumpArea(Base): ...@@ -393,6 +399,7 @@ class DumpArea(Base):
self.Disabled = Disabled self.Disabled = Disabled
self.Material = Material self.Material = Material
class DiggingWorkArea(Base): class DiggingWorkArea(Base):
__tablename__ = 'Geo_DiggingWorkArea' __tablename__ = 'Geo_DiggingWorkArea'
......
...@@ -19,6 +19,7 @@ from settings import * ...@@ -19,6 +19,7 @@ from settings import *
from equipment.truck import TruckInfo from equipment.truck import TruckInfo
from equipment.excavator import ExcavatorInfo from equipment.excavator import ExcavatorInfo
from equipment.dump import DumpInfo from equipment.dump import DumpInfo
from equipment.truck import TruckInfo
# 车流规划类 # 车流规划类
class Traffic_para(WalkManage): class Traffic_para(WalkManage):
...@@ -37,10 +38,10 @@ class Traffic_para(WalkManage): ...@@ -37,10 +38,10 @@ class Traffic_para(WalkManage):
# self.excavator_uuid_to_load_area_uuid_dict = {} # 用于保存挖机与装载区的绑定关系(uuid) # self.excavator_uuid_to_load_area_uuid_dict = {} # 用于保存挖机与装载区的绑定关系(uuid)
# self.dump_index_to_unload_area_index_dict = {} # 用于保存卸点与卸载区的绑定关系(id) # self.dump_index_to_unload_area_index_dict = {} # 用于保存卸点与卸载区的绑定关系(id)
# self.excavator_index_to_load_area_index_dict = {} # 用于保存挖机与装载区的绑定关系(id) # self.excavator_index_to_load_area_index_dict = {} # 用于保存挖机与装载区的绑定关系(id)
self.truck = TruckInfo()
self.empty_speed = empty_speed # 空载矿卡平均时速
self.empty_speed = 25 # 空载矿卡平均时速 self.heavy_speed = heavy_speed # 重载矿卡平均时速
self.heavy_speed = 22 # 重载矿卡平均时速
self.walk_time_to_load_area = np.zeros((num_of_unload_area, num_of_load_area)) # 空载运输路线距离 self.walk_time_to_load_area = np.zeros((num_of_unload_area, num_of_load_area)) # 空载运输路线距离
self.walk_time_to_unload_area = np.zeros((num_of_load_area, num_of_unload_area)) # 重载运输路线距离 self.walk_time_to_unload_area = np.zeros((num_of_load_area, num_of_unload_area)) # 重载运输路线距离
...@@ -51,7 +52,11 @@ class Traffic_para(WalkManage): ...@@ -51,7 +52,11 @@ class Traffic_para(WalkManage):
self.avg_goto_dump_weight = np.full((num_of_load_area, num_of_unload_area), 1) self.avg_goto_dump_weight = np.full((num_of_load_area, num_of_unload_area), 1)
self.walk_time_to_excavator = np.zeros((num_of_dump, num_of_excavator)) # 逻辑空载运输路线距离 self.walk_time_to_excavator = np.zeros((num_of_dump, num_of_excavator)) # 逻辑空载运输路线距离
self.walk_time_to_dump = np.zeros((num_of_excavator, num_of_dump)) # 逻辑重载运输路线距离 self.walk_time_to_dump = np.zeros((num_of_excavator, num_of_dump)) # 逻辑重载运输路线距离
self.payload = 20 # 有效载重(不同型号矿卡载重不同,这里暂时认为车队是同质的)
# self.payload = 200 # 有效载重(不同型号矿卡载重不同,这里暂时认为车队是同质的)
self.truck = TruckInfo()
self.payload = np.mean(self.truck.get_payload())
self.min_throughout = 200 # 最小产量约束 self.min_throughout = 200 # 最小产量约束
self.truck_total_num = 0 self.truck_total_num = 0
...@@ -196,32 +201,37 @@ class Traffic_para(WalkManage): ...@@ -196,32 +201,37 @@ class Traffic_para(WalkManage):
def extract_walk_time_info(self, include_material_type): def extract_walk_time_info(self, include_material_type):
try: # try:
# 车流规划部分矩阵格式与其余两个模块不同 # 车流规划部分矩阵格式与其余两个模块不同
cost_to_load_area = self.path_planner.cost_to_load_area cost_to_load_area = self.path_planner.cost_to_load_area
cost_to_unload_area = self.path_planner.cost_to_unload_area cost_to_unload_area = self.path_planner.cost_to_unload_area
distance_to_load_area = self.path_planner.distance_to_load_area distance_to_load_area = self.path_planner.distance_to_load_area
distance_to_unload_area = self.path_planner.distance_to_unload_area distance_to_unload_area = self.path_planner.distance_to_unload_area
self.load_area_material_type = {} self.load_area_material_type = {}
self.unload_area_material_type = {} self.unload_area_material_type = {}
for item in session_postgre.query(DiggingWorkArea).all(): for item in session_postgre.query(DiggingWorkArea).all():
if item.Material is not None: load_area_id = str(item.Id)
self.load_area_material_type[load_area_uuid_to_index_dict[item.Id]] = item.Material if load_area_id in load_area_uuid_to_index_dict:
self.load_area_material_type[load_area_id] = item.Material
for item in session_postgre.query(DumpArea).all():
if item.Material is not None: for item in session_postgre.query(DumpArea).all():
self.unload_area_material_type[unload_area_uuid_to_index_dict[item.Id]] = item.Material unload_area_id = str(item.Id)
if unload_area_id in unload_area_uuid_to_index_dict:
# 路网信息读取 self.unload_area_material_type[unload_area_id] = item.Material
for unload_area_index in range(unload_area_num):
for load_area_index in range(load_area_num): # 路网信息读取
# 是否考虑cost for unload_area_index in range(unload_area_num):
if include_material_type == True: for load_area_index in range(load_area_num):
logger.info(f'考虑物料类型') # 是否考虑cost
if self.unload_area_material_type[unload_area_index] == 'c481794b-6ced-45b9-a9c4-c4a388f44418' \ if include_material_type == True:
and self.load_area_material_type[load_area_index] == 'c481794b-6ced-45b9-a9c4-c4a388f44418': logger.info(f'考虑物料类型')
unload_area_id = unload_area_index_to_uuid_dict[unload_area_index]
load_area_id = load_area_index_to_uuid_dict[load_area_index]
if unload_area_id in unload_area_uuid_to_index_dict and load_area_id in load_area_uuid_to_index_dict:
if self.unload_area_material_type[unload_area_id] == 'c481794b-6ced-45b9-a9c4-c4a388f44418' \
and self.load_area_material_type[load_area_id] == 'c481794b-6ced-45b9-a9c4-c4a388f44418':
self.goto_load_area_factor[unload_area_index][load_area_index] = \ self.goto_load_area_factor[unload_area_index][load_area_index] = \
0.75*(cost_to_load_area[unload_area_index][load_area_index] / (empty_speed * 1000)) / self.payload 0.75*(cost_to_load_area[unload_area_index][load_area_index] / (empty_speed * 1000)) / self.payload
...@@ -234,18 +244,18 @@ class Traffic_para(WalkManage): ...@@ -234,18 +244,18 @@ class Traffic_para(WalkManage):
self.goto_unload_area_factor[load_area_index][unload_area_index] = \ self.goto_unload_area_factor[load_area_index][unload_area_index] = \
(cost_to_unload_area[unload_area_index][load_area_index] / (heavy_speed * 1000)) / self.payload (cost_to_unload_area[unload_area_index][load_area_index] / (heavy_speed * 1000)) / self.payload
# 不考虑物料类型的cost # 不考虑物料类型的cost
else: else:
self.goto_load_area_factor[unload_area_index][load_area_index] = \ self.goto_load_area_factor[unload_area_index][load_area_index] = \
(cost_to_load_area[unload_area_index][load_area_index] / (empty_speed * 1000)) / self.payload (cost_to_load_area[unload_area_index][load_area_index] / (empty_speed * 1000)) / self.payload
self.goto_unload_area_factor[load_area_index][unload_area_index] = \ self.goto_unload_area_factor[load_area_index][unload_area_index] = \
(cost_to_unload_area[unload_area_index][load_area_index] / (heavy_speed * 1000)) / self.payload (cost_to_unload_area[unload_area_index][load_area_index] / (heavy_speed * 1000)) / self.payload
except Exception as es: # except Exception as es:
logger.error(es) # logger.error(es)
logger.error("车流规划信息计算异常") # logger.error("车流规划路网信息计算异常")
# def extract_walk_time_info(self): # def extract_walk_time_info(self):
...@@ -300,57 +310,61 @@ class Traffic_para(WalkManage): ...@@ -300,57 +310,61 @@ class Traffic_para(WalkManage):
# 初始化车流规划类 # 初始化车流规划类
def Traffic_para_init(num_of_load_area, num_of_unload_area, num_of_excavator, num_of_dump): def Traffic_para_init(num_of_load_area, num_of_unload_area, num_of_excavator, num_of_dump):
try: # try:
tra_para = Traffic_para(num_of_load_area, num_of_unload_area, num_of_excavator, num_of_dump)
tra_para.period_map_para_load()
tra_para = Traffic_para(num_of_load_area, num_of_unload_area, num_of_excavator, num_of_dump) tra_para.period_walk_para_load()
tra_para.period_map_para_load() # Traffic_para.extract_walk_time_info(tra_para)
tra_para.period_walk_para_load() tra_para.extract_excavator_info()
# Traffic_para.extract_walk_time_info(tra_para) tra_para.extract_dump_info()
Traffic_para.extract_excavator_info(tra_para) tra_para.extract_walk_time_info(True)
Traffic_para.extract_dump_info(tra_para) tra_para.truck.update_truck_payload()
Traffic_para.extract_walk_time_info(tra_para) tra_para.payload = np.mean(tra_para.truck.get_payload())
# 全部矿卡设备集合 # 全部矿卡设备集合
truck_set = set(update_total_truck()) truck_set = set(update_total_truck())
# 固定派车矿卡集合 # 固定派车矿卡集合
fixed_truck_set = set(update_fixdisp_truck()) fixed_truck_set = set(update_fixdisp_truck())
# 动态派车矿卡集合 # 动态派车矿卡集合
tra_para.truck_total_num = len(truck_set.difference(fixed_truck_set)) tra_para.truck_total_num = len(truck_set.difference(fixed_truck_set))
# 计算逻辑道路因子 # 计算逻辑道路因子
for i in range(num_of_excavator): for i in range(num_of_excavator):
for j in range(num_of_dump): for j in range(num_of_dump):
# 查找挖机绑定的装载区, 卸载设备绑定的卸载区 # 查找挖机绑定的装载区, 卸载设备绑定的卸载区
load_area_index = tra_para.excavator_index_to_load_area_index_dict[i] load_area_index = tra_para.excavator_index_to_load_area_index_dict[i]
unload_area_index = tra_para.dump_index_to_unload_area_index_dict[j] unload_area_index = tra_para.dump_index_to_unload_area_index_dict[j]
# 逻辑道路因子赋值, 来自实际道路因子 # 逻辑道路因子赋值, 来自实际道路因子
tra_para.goto_excavator_factor[j][i] = \ tra_para.goto_excavator_factor[j][i] = \
tra_para.goto_load_area_factor[unload_area_index][load_area_index] tra_para.goto_load_area_factor[unload_area_index][load_area_index]
tra_para.goto_dump_factor[i][j] = \ tra_para.goto_dump_factor[i][j] = \
tra_para.goto_unload_area_factor[load_area_index][unload_area_index] tra_para.goto_unload_area_factor[load_area_index][unload_area_index]
# 每条卸载道路的优先级,等于电铲的优先级乘以卸载点的优先级 # 每条卸载道路的优先级,等于电铲的优先级乘以卸载点的优先级
tra_para.priority_coefficient[i][j] = tra_para.excavator_priority_coefficient[i] \ tra_para.priority_coefficient[i][j] = tra_para.excavator_priority_coefficient[i] \
* tra_para.dump_priority_coefficient[j] * tra_para.dump_priority_coefficient[j]
# # 逻辑距离赋值,来自实际道路距离 # # 逻辑距离赋值,来自实际道路距离
# tra_para.walk_time_to_excavator[j][i] = \ # tra_para.walk_time_to_excavator[j][i] = \
# tra_para.walk_time_to_load_area[unload_area_index][load_area_index] # tra_para.walk_time_to_load_area[unload_area_index][load_area_index]
# #
# tra_para.walk_time_to_dump[i][j] = \ # tra_para.walk_time_to_dump[i][j] = \
# tra_para.walk_time_to_unload_area[load_area_index][unload_area_index] # tra_para.walk_time_to_unload_area[load_area_index][unload_area_index]
except Exception as es: # except Exception as es:
logger.error(es) # logger.error(es)
logger.error("车流规划类比初始化异常") # logger.error("车流规划类比初始化异常")
return tra_para return tra_para
...@@ -196,7 +196,7 @@ def traffic_flow_plan(): ...@@ -196,7 +196,7 @@ def traffic_flow_plan():
return res["var_x"], res["var_y"] return res["var_x"], res["var_y"]
traffic_flow_plan() # traffic_flow_plan()
# end = time.time() # end = time.time()
# print("used {:.5}s".format(end-start)) # print("used {:.5}s".format(end-start))
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment