Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
I
integrated-scheduling-v3
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
张晓彤
integrated-scheduling-v3
Commits
b9fd0034
Commit
b9fd0034
authored
Jun 23, 2022
by
张晓彤
Committed by
z5335534 Ao Guo
Jun 23, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Upadte debug
parent
aed9900d
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
171 additions
and
154 deletions
+171
-154
settings.cpython-37.pyc
__pycache__/settings.cpython-37.pyc
+0
-0
algorithm.cpython-37.pyc
alg/__pycache__/algorithm.cpython-37.pyc
+0
-0
group.cpython-37.pyc
core/__pycache__/group.cpython-37.pyc
+0
-0
group.py
core/group.py
+74
-57
dispatchInfo.cpython-37.pyc
data/__pycache__/dispatchInfo.cpython-37.pyc
+0
-0
dispatchInfo.py
data/dispatchInfo.py
+3
-3
realtime_dispatch.py
realtime_dispatch.py
+94
-94
No files found.
__pycache__/settings.cpython-37.pyc
View file @
b9fd0034
No preview for this file type
alg/__pycache__/algorithm.cpython-37.pyc
View file @
b9fd0034
No preview for this file type
core/__pycache__/group.cpython-37.pyc
View file @
b9fd0034
No preview for this file type
core/group.py
View file @
b9fd0034
...
@@ -15,11 +15,11 @@
...
@@ -15,11 +15,11 @@
# @File : group.py
# @File : group.py
# @Software: PyCharm
# @Software: PyCharm
from
data.dispatchInfo
import
DispatchInfo
from
data.dispatchInfo
import
*
from
bidict
import
bidict
from
bidict
import
bidict
from
alg.algorithm
import
AlgorithmBase
from
alg.algorithm
import
AlgorithmBase
import
numpy
as
np
import
numpy
as
np
# from settings import get_logger
class
CurrentTruck
:
class
CurrentTruck
:
""" class for the information of current dispatching truck.
""" class for the information of current dispatching truck.
...
@@ -61,6 +61,7 @@ class Group:
...
@@ -61,6 +61,7 @@ class Group:
""" Generate a group obj.
""" Generate a group obj.
:param group_id: (uuid) group_id
:param group_id: (uuid) group_id
"""
"""
self
.
logger
=
get_logger
(
"ga.Group"
)
# basic info.
# basic info.
self
.
group_id
=
group_id
self
.
group_id
=
group_id
self
.
group_mode
=
1
self
.
group_mode
=
1
...
@@ -93,6 +94,7 @@ class Group:
...
@@ -93,6 +94,7 @@ class Group:
:return:
:return:
"""
"""
# DispatchInfo.update_group_mode()
# DispatchInfo.update_group_mode()
self
.
group_mode
=
1
self
.
group_mode
=
DispatchInfo
.
get_group_mode
(
self
.
group_id
)
self
.
group_mode
=
DispatchInfo
.
get_group_mode
(
self
.
group_id
)
def
update_group_device
(
self
):
def
update_group_device
(
self
):
...
@@ -102,6 +104,9 @@ class Group:
...
@@ -102,6 +104,9 @@ class Group:
"""
"""
# update group devices
# update group devices
# DispatchInfo.update_device_group_structure()
# DispatchInfo.update_device_group_structure()
self
.
excavators
=
{}
self
.
unload_areas
=
{}
self
.
truck_set
=
set
()
self
.
excavators
=
DispatchInfo
.
get_excavator
(
self
.
group_id
)
self
.
excavators
=
DispatchInfo
.
get_excavator
(
self
.
group_id
)
self
.
unload_areas
=
DispatchInfo
.
get_unload_area
(
self
.
group_id
)
self
.
unload_areas
=
DispatchInfo
.
get_unload_area
(
self
.
group_id
)
self
.
truck_set
=
DispatchInfo
.
get_truck_set
(
self
.
group_id
)
self
.
truck_set
=
DispatchInfo
.
get_truck_set
(
self
.
group_id
)
...
@@ -112,6 +117,9 @@ class Group:
...
@@ -112,6 +117,9 @@ class Group:
:return:
:return:
"""
"""
# DispatchInfo.update_route_distance()
# DispatchInfo.update_route_distance()
self
.
to_excavator_distance
=
None
self
.
to_unload_area_distance
=
None
self
.
park_to_excavator_distance
=
None
self
.
to_excavator_distance
=
DispatchInfo
.
get_to_excavator_distance
(
self
.
group_id
)
self
.
to_excavator_distance
=
DispatchInfo
.
get_to_excavator_distance
(
self
.
group_id
)
self
.
to_unload_area_distance
=
DispatchInfo
.
get_to_unload_area_distance
(
self
.
group_id
)
self
.
to_unload_area_distance
=
DispatchInfo
.
get_to_unload_area_distance
(
self
.
group_id
)
self
.
park_to_excavator_distance
=
DispatchInfo
.
get_park_to_excavator_distance
(
self
.
group_id
)
self
.
park_to_excavator_distance
=
DispatchInfo
.
get_park_to_excavator_distance
(
self
.
group_id
)
...
@@ -122,18 +130,24 @@ class Group:
...
@@ -122,18 +130,24 @@ class Group:
:return:
:return:
"""
"""
# excavator_index = 0
# excavator_index = 0
self
.
excavator_uuid_index_dict
=
{}
self
.
unload_area_uuid_index_dict
=
{}
self
.
truck_uuid_index_dict
=
{}
for
i
in
range
(
len
(
self
.
excavators
)):
for
i
in
range
(
len
(
self
.
excavators
)):
self
.
excavator_uuid_index_dict
[
list
(
self
.
excavators
)[
i
]]
=
i
self
.
excavator_uuid_index_dict
[
list
(
self
.
excavators
)[
i
]]
=
i
for
i
in
range
(
len
(
self
.
unload_areas
)):
for
i
in
range
(
len
(
self
.
unload_areas
)):
self
.
unload_area_uuid_index_dict
[
list
(
self
.
unload_areas
)[
i
]]
=
i
self
.
unload_area_uuid_index_dict
[
list
(
self
.
unload_areas
)[
i
]]
=
i
b
=
self
.
truck_set
for
i
in
range
(
len
(
self
.
truck_set
)):
for
i
in
range
(
len
(
self
.
truck_set
)):
self
.
truck_uuid_index_dict
[
list
(
self
.
truck_set
)[
i
]]
=
i
self
.
truck_uuid_index_dict
[
list
(
self
.
truck_set
)[
i
]]
=
i
self
.
truck_uuid_index_dict
=
bidict
(
self
.
truck_uuid_index_dict
)
self
.
excavator_uuid_index_dict
=
bidict
(
self
.
excavator_uuid_index_dict
)
self
.
excavator_uuid_index_dict
=
bidict
(
self
.
excavator_uuid_index_dict
)
self
.
unload_area_uuid_index_dict
=
bidict
(
self
.
unload_area_uuid_index_dict
)
self
.
unload_area_uuid_index_dict
=
bidict
(
self
.
unload_area_uuid_index_dict
)
self
.
truck_uuid_index_dict
=
bidict
(
self
.
truck_uuid_index_dict
)
# group_excavator_dict = {group_1: {excavator_1: load_area_1}, group_2: {excavator_2: load_area_2}}
# group_excavator_dict = {group_1: {excavator_1: load_area_1}, group_2: {excavator_2: load_area_2}}
...
@@ -156,60 +170,64 @@ class Group:
...
@@ -156,60 +170,64 @@ class Group:
"""
"""
truck_dispatch
=
{}
truck_dispatch
=
{}
# 全智能模式
try
:
if
self
.
group_mode
==
1
:
# 全智能模式
assert
issubclass
(
solver
,
AlgorithmBase
)
if
self
.
group_mode
==
1
:
s
=
solver
(
self
,
self
.
truck
,
self
.
pre_sch
)
# algorithm init
assert
issubclass
(
solver
,
AlgorithmBase
)
s
=
solver
(
self
,
self
.
truck
,
self
.
pre_sch
)
# algorithm init
for
i
in
list
(
self
.
truck_set
):
truck_trip
=
self
.
truck
.
get_truck_current_trip
()[
self
.
truck_uuid_index_dict
[
i
]]
for
i
in
list
(
self
.
truck_set
):
truck_task
=
self
.
truck
.
get_truck_current_task
()[
i
]
truck_trip
=
self
.
truck
.
get_truck_current_trip
()[
self
.
truck_uuid_index_dict
[
i
]]
truck_info
=
CurrentTruck
(
i
,
self
.
group_id
,
truck_trip
,
truck_task
)
truck_task
=
self
.
truck
.
get_truck_current_task
()[
i
]
if
truck_task
in
[
-
2
,
3
,
4
]:
truck_info
=
CurrentTruck
(
i
,
self
.
group_id
,
truck_trip
,
truck_task
)
next_excavator_value
=
s
.
solve
(
i
,
truck_info
)
if
truck_task
in
[
-
2
,
3
,
4
]:
# min_index = next_excavator_list.index(min(next_excavator_list))
next_excavator_value
=
s
.
solve
(
i
,
truck_info
)
min_index
=
np
.
argmin
(
next_excavator_value
)
# min_index = next_excavator_list.index(min(next_excavator_list))
next_excavator_id
=
self
.
excavator_uuid_index_dict
.
inverse
[
min_index
]
min_index
=
np
.
argmin
(
next_excavator_value
)
if
truck_task
==
-
2
:
next_excavator_id
=
self
.
excavator_uuid_index_dict
.
inverse
[
min_index
]
next_unload_area_id
=
"Park"
if
truck_task
==
-
2
:
else
:
next_unload_area_id
=
"Park"
next_unload_area_id
=
self
.
unload_area_uuid_index_dict
.
inverse
[
truck_trip
[
-
1
]]
else
:
truck_dispatch
[
i
]
=
[
next_excavator_id
,
next_unload_area_id
]
next_unload_area_id
=
self
.
unload_area_uuid_index_dict
.
inverse
[
truck_trip
[
-
1
]]
truck_dispatch
[
i
]
=
[
next_excavator_id
,
next_unload_area_id
]
if
truck_task
in
[
0
,
1
]:
next_unload_area_value
=
s
.
solve
(
i
)
if
truck_task
in
[
0
,
1
]:
min_index
=
np
.
argmin
(
next_unload_area_value
)
next_unload_area_value
=
s
.
solve
(
i
)
next_unload_area_id
=
self
.
unload_area_uuid_index_dict
.
inverse
[
min_index
]
min_index
=
np
.
argmin
(
next_unload_area_value
)
next_excavator_id
=
self
.
excavator_uuid_index_dict
.
inverse
[
truck_trip
[
-
1
]]
next_unload_area_id
=
self
.
unload_area_uuid_index_dict
.
inverse
[
min_index
]
truck_dispatch
[
i
]
=
[
next_excavator_id
,
next_unload_area_id
]
next_excavator_id
=
self
.
excavator_uuid_index_dict
.
inverse
[
truck_trip
[
-
1
]]
# 空车智能模式
truck_dispatch
[
i
]
=
[
next_excavator_id
,
next_unload_area_id
]
elif
self
.
group_mode
==
2
:
# 空车智能模式
assert
issubclass
(
solver
,
AlgorithmBase
)
elif
self
.
group_mode
==
2
:
s
=
solver
(
self
,
self
.
truck
,
self
.
pre_sch
)
# algorithm init
assert
issubclass
(
solver
,
AlgorithmBase
)
s
=
solver
(
self
,
self
.
truck
,
self
.
pre_sch
)
# algorithm init
for
i
in
list
(
self
.
truck_set
):
truck_trip
=
self
.
truck
.
get_truck_current_trip
()[
self
.
truck_uuid_index_dict
[
i
]]
for
i
in
list
(
self
.
truck_set
):
truck_task
=
self
.
truck
.
get_truck_current_task
()[
i
]
truck_trip
=
self
.
truck
.
get_truck_current_trip
()[
self
.
truck_uuid_index_dict
[
i
]]
truck_info
=
CurrentTruck
(
i
,
self
.
group_id
,
truck_trip
,
truck_task
)
truck_task
=
self
.
truck
.
get_truck_current_task
()[
i
]
if
truck_task
in
[
-
2
,
3
,
4
]:
truck_info
=
CurrentTruck
(
i
,
self
.
group_id
,
truck_trip
,
truck_task
)
next_excavator_value
=
s
.
solve
(
i
,
truck_info
)
if
truck_task
in
[
-
2
,
3
,
4
]:
# min_index = next_excavator_list.index(min(next_excavator_list))
next_excavator_value
=
s
.
solve
(
i
,
truck_info
)
min_index
=
np
.
argmin
(
next_excavator_value
)
# min_index = next_excavator_list.index(min(next_excavator_list))
next_excavator_id
=
self
.
excavator_uuid_index_dict
.
inverse
[
min_index
]
min_index
=
np
.
argmin
(
next_excavator_value
)
if
truck_task
==
-
2
:
next_excavator_id
=
self
.
excavator_uuid_index_dict
.
inverse
[
min_index
]
next_unload_area_id
=
"Park"
if
truck_task
==
-
2
:
else
:
next_unload_area_id
=
"Park"
next_unload_area_id
=
self
.
unload_area_uuid_index_dict
.
inverse
[
truck_trip
[
-
1
]]
else
:
truck_dispatch
[
i
]
=
[
next_excavator_id
,
next_unload_area_id
]
next_unload_area_id
=
self
.
unload_area_uuid_index_dict
.
inverse
[
truck_trip
[
-
1
]]
if
truck_task
in
[
0
,
1
]:
truck_dispatch
[
i
]
=
[
next_excavator_id
,
next_unload_area_id
]
if
truck_task
in
[
0
,
1
]:
truck_dispatch
[
i
]
=
DispatchInfo
.
get_truck_match
(
i
)
# 定铲派车
elif
self
.
group_mode
==
3
:
for
i
in
list
(
self
.
truck_set
):
truck_dispatch
[
i
]
=
DispatchInfo
.
get_truck_match
(
i
)
truck_dispatch
[
i
]
=
DispatchInfo
.
get_truck_match
(
i
)
# 定铲派车
elif
self
.
group_mode
==
3
:
for
i
in
list
(
self
.
truck_set
):
truck_dispatch
[
i
]
=
DispatchInfo
.
get_truck_match
(
i
)
elif
self
.
group_mode
==
4
:
elif
self
.
group_mode
==
4
:
pass
pass
except
Exception
as
es
:
self
.
logger
.
error
(
"group调度出错"
)
self
.
logger
.
error
(
es
)
# return dispatch plan
# return dispatch plan
return
truck_dispatch
return
truck_dispatch
\ No newline at end of file
data/__pycache__/dispatchInfo.cpython-37.pyc
View file @
b9fd0034
No preview for this file type
data/dispatchInfo.py
View file @
b9fd0034
...
@@ -269,20 +269,20 @@ class DispatchInfo:
...
@@ -269,20 +269,20 @@ class DispatchInfo:
def
get_truck_match
(
cls
,
truck_id
):
def
get_truck_match
(
cls
,
truck_id
):
return
cls
.
truck_match_dict
[
truck_id
]
return
cls
.
truck_match_dict
[
truck_id
]
@classmethod
@classmethod
def
get_park_to_excavator_distance
(
cls
,
group_id
):
def
get_park_to_excavator_distance
(
cls
,
group_id
):
excavators
=
cls
.
group_excavator_dict
[
group_id
]
excavators
=
cls
.
group_excavator_dict
[
group_id
]
park_matrix
=
np
.
ones
((
1
,
len
(
excavators
)))
park_matrix
=
np
.
ones
((
1
,
len
(
excavators
)))
try
:
try
:
b
=
excavators
for
i
in
range
(
len
(
excavators
)):
for
i
in
range
(
len
(
excavators
)):
load_area_id
=
cls
.
excavator_load_dict
[
excavators
[
i
]]
load_area_id
=
cls
.
excavator_load_dict
[
excavators
[
i
]]
try
:
try
:
distance
=
session_postgre
.
query
(
WalkTimePark
)
.
filter_by
(
load_area_id
=
load_area_id
)
.
first
()
.
park_load_distance
distance
=
session_postgre
.
query
(
WalkTimePark
)
.
filter_by
(
load_area_id
=
load_area_id
)
.
first
()
.
park_load_distance
park_matrix
[
0
][
i
]
=
distance
park_matrix
[
0
][
i
]
=
distance
except
Exception
as
es
:
except
Exception
as
es
:
logger
.
error
(
"查询不到距离,设置为100000000"
)
logger
.
warning
(
"查询不到距离,设置为100000000"
)
logger
.
error
(
es
)
logger
.
warning
(
es
)
park_matrix
[
0
][
i
]
=
100000000
# 设置为一个很大的数字
park_matrix
[
0
][
i
]
=
100000000
# 设置为一个很大的数字
except
Exception
as
es
:
except
Exception
as
es
:
logger
.
error
(
"park->load距离更新异常, 存在备停区不可达的装载区"
)
logger
.
error
(
"park->load距离更新异常, 存在备停区不可达的装载区"
)
...
...
realtime_dispatch.py
View file @
b9fd0034
...
@@ -62,101 +62,101 @@ def process(dispatcher):
...
@@ -62,101 +62,101 @@ def process(dispatcher):
# # 直接读取数据库写入redis
# # 直接读取数据库写入redis
# direct2redis()
# direct2redis()
try
:
#
try:
# 更新周期参数
# 更新周期参数
logger
.
info
(
"#####################################周期更新开始#####################################"
)
logger
.
info
(
"#####################################周期更新开始#####################################"
)
global_period_para_update
()
global_period_para_update
()
if
get_value
(
"dynamic_dump_num"
)
*
get_value
(
"dynamic_excavator_num"
)
==
0
:
if
get_value
(
"dynamic_dump_num"
)
*
get_value
(
"dynamic_excavator_num"
)
==
0
:
raise
Exception
(
"无动态派车计划可用"
)
raise
Exception
(
"无动态派车计划可用"
)
return
return
if
get_value
(
"dynamic_truck_num"
)
==
0
:
if
get_value
(
"dynamic_truck_num"
)
==
0
:
raise
Exception
(
"无动态派车可用矿卡"
)
raise
Exception
(
"无动态派车可用矿卡"
)
return
return
# 清空数据库缓存
# 清空数据库缓存
session_mysql
.
commit
()
session_mysql
.
commit
()
session_mysql
.
flush
()
session_mysql
.
flush
()
# 清空数据库缓存
# 清空数据库缓存
session_postgre
.
commit
()
session_postgre
.
commit
()
session_postgre
.
flush
()
session_postgre
.
flush
()
global_period_para_update
()
global_period_para_update
()
# 更新调度信息
# 更新调度信息
DispatchInfo
.
reset
()
DispatchInfo
.
reset
()
DispatchInfo
.
update_device_group_structure
()
DispatchInfo
.
update_device_group_structure
()
DispatchInfo
.
update_route_distance
()
DispatchInfo
.
update_route_distance
()
DispatchInfo
.
update_group_mode
()
DispatchInfo
.
update_group_mode
()
DispatchInfo
.
update_group_name
()
DispatchInfo
.
update_group_name
()
# logger.info
# logger.info
# group_set = set()
# group_set = set()
#
#
# # device group structure
# # device group structure
# load_excavator_dict = {} # 装载区id-->>电铲编号的映射
# load_excavator_dict = {} # 装载区id-->>电铲编号的映射
# excavator_load_dict = {} # 电铲编号->>装载区id的映射
# excavator_load_dict = {} # 电铲编号->>装载区id的映射
#
#
# group_excavator_dict = {} # team_id -> dict {[excavator_id, excavator_id], ...}
# group_excavator_dict = {} # team_id -> dict {[excavator_id, excavator_id], ...}
# excavator_group_dict = {} # excavator_id -> team_id 问题:多个key值对应一个value值
# excavator_group_dict = {} # excavator_id -> team_id 问题:多个key值对应一个value值
#
#
# group_dump_dict = {} # team_id -> dict {unload_area_id, unload_area_id, ...}
# group_dump_dict = {} # team_id -> dict {unload_area_id, unload_area_id, ...}
# dump_group_dict = {} # unload_area_id -> team_id
# dump_group_dict = {} # unload_area_id -> team_id
#
#
# group_truck_dict = {} # team_id -> dict # {group_id:[truck_id,truck_id],...}
# group_truck_dict = {} # team_id -> dict # {group_id:[truck_id,truck_id],...}
# truck_group_dict = {} # truck_id -> team_id
# truck_group_dict = {} # truck_id -> team_id
#
#
# # group feature
# # group feature
# group_mode = {} # 数据格式: {team_id:mode_code}
# group_mode = {} # 数据格式: {team_id:mode_code}
#
#
# # route_distance(路网距离)
# # route_distance(路网距离)
# load_distance = {}
# load_distance = {}
# unload_distance = {}
# unload_distance = {}
logger
.
info
(
"Dispatchinfo,更新后信息"
)
logger
.
info
(
"Dispatchinfo,更新后信息"
)
logger
.
info
(
"group_set"
)
logger
.
info
(
"group_set"
)
logger
.
info
(
DispatchInfo
.
group_set
)
logger
.
info
(
DispatchInfo
.
group_set
)
logger
.
info
(
"group_excavator_dict"
)
logger
.
info
(
"group_excavator_dict"
)
logger
.
info
(
DispatchInfo
.
group_excavator_dict
)
logger
.
info
(
DispatchInfo
.
group_excavator_dict
)
logger
.
info
(
"group_unload_area_dict"
)
logger
.
info
(
"group_unload_area_dict"
)
logger
.
info
(
DispatchInfo
.
group_unload_area_dict
)
logger
.
info
(
DispatchInfo
.
group_unload_area_dict
)
logger
.
info
(
"group_truck_dict"
)
logger
.
info
(
"group_truck_dict"
)
logger
.
info
(
DispatchInfo
.
group_truck_dict
)
logger
.
info
(
DispatchInfo
.
group_truck_dict
)
logger
.
info
(
"group_mode"
)
logger
.
info
(
"group_mode"
)
logger
.
info
(
DispatchInfo
.
group_mode
)
logger
.
info
(
DispatchInfo
.
group_mode
)
logger
.
info
(
"load_distance"
)
logger
.
info
(
"load_distance"
)
logger
.
info
(
DispatchInfo
.
load_distance
)
logger
.
info
(
DispatchInfo
.
load_distance
)
logger
.
info
(
"unload_distance"
)
logger
.
info
(
"unload_distance"
)
logger
.
info
(
DispatchInfo
.
unload_distance
)
logger
.
info
(
DispatchInfo
.
unload_distance
)
# logger.info("load_excavator_dict")
# logger.info("load_excavator_dict")
# logger.info(DispatchInfo.load_excavator_dict)
# logger.info(DispatchInfo.load_excavator_dict)
# logger.info("excavator_load_dict")
# logger.info("excavator_load_dict")
# logger.info(DispatchInfo.excavator_load_dict)
# logger.info(DispatchInfo.excavator_load_dict)
# logger.info(DispatchInfo.excavator_group_dict)
# logger.info(DispatchInfo.excavator_group_dict)
# logger.info(DispatchInfo.dump_group_dict)
# logger.info(DispatchInfo.dump_group_dict)
# logger.info(DispatchInfo.truck_group_dict)
# logger.info(DispatchInfo.truck_group_dict)
# 调度生成
# 调度生成
dispatcher
.
period_update
()
dispatcher
.
period_update
()
dispatcher
.
group_generate
()
dispatcher
.
group_generate
()
dispatcher
.
group_info_update
()
dispatcher
.
group_info_update
()
dispatcher
.
group_dispatch
()
dispatcher
.
group_dispatch
()
logger
.
info
(
"#####################################周期更新结束#####################################"
)
logger
.
info
(
"#####################################周期更新结束#####################################"
)
except
Exception
as
es
:
#
except Exception as es:
logger
.
error
(
"最外层异常捕获"
)
#
logger.error("最外层异常捕获")
logger
.
error
(
es
)
#
logger.error(es)
def
perform
(
inc
,
dispatcher
):
def
perform
(
inc
,
dispatcher
):
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment