Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in / Register
Toggle navigation
S
Scott
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Scott Sun
Scott
Commits
6f787924
Commit
6f787924
authored
May 29, 2020
by
Scott Sun
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
scott
parent
149f666c
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
480 additions
and
94 deletions
+480
-94
analysis_test.js
ats/scott_test/analysis_test.js
+149
-87
input_test.js
ats/scott_test/input_test.js
+2
-7
config_ats.js
config_ats.js
+329
-0
No files found.
ats/scott_test/analysis_test.js
View file @
6f787924
...
@@ -286,6 +286,10 @@ try {
...
@@ -286,6 +286,10 @@ try {
console
.
log
(
now_profile
.
match
(
/
\n
/ig
).
length
);
console
.
log
(
now_profile
.
match
(
/
\n
/ig
).
length
);
if
(
now_profile
.
match
(
/
\n
/ig
).
length
==
1
){
// 如果没有profile
if
(
now_profile
.
match
(
/
\n
/ig
).
length
==
1
){
// 如果没有profile
createOutline
({
job
:
job
,
step
:
pcs_step
,
matrix
:
tmp_matrix
})
createOutline
({
job
:
job
,
step
:
pcs_step
,
matrix
:
tmp_matrix
})
var
hasProfile
=
GEN
.
getProfile
({
job
:
job
,
step
:
pcs_step
})
if
(
hasProfile
.
match
(
/
\n
/ig
).
length
==
1
){
throw
"创建profile失败"
}
}
else
{
}
else
{
GEN
.
affectedLayer
({
affected
:
'yes'
,
layer
:
board_layer
,
clear_before
:
"yes"
})
GEN
.
affectedLayer
({
affected
:
'yes'
,
layer
:
board_layer
,
clear_before
:
"yes"
})
GEN
.
selectByFilter
({
profile
:
"out"
})
GEN
.
selectByFilter
({
profile
:
"out"
})
...
@@ -383,13 +387,13 @@ try {
...
@@ -383,13 +387,13 @@ try {
milling_bit_size
:
true
,
// todo 检查array中pcs的最小间距值
milling_bit_size
:
true
,
// todo 检查array中pcs的最小间距值
milling_length
:
true
,
// todo 检查array中铣切长度
milling_length
:
true
,
// todo 检查array中铣切长度
vc_src_01005_pad_result
:
{
api
:
"board_has_attr"
,
props
:
vc_src_01005_pad_result
},
// 本地使用 .pth_pad ats 01005_pad
vc_src_01005_pad_result
:
{
api
:
"board_has_attr"
,
props
:
vc_src_01005_pad_result
},
// 本地使用 .pth_pad ats 01005_pad
ATS_technology_25dc
:
{
api
:
"layer_exist"
,
props
:[
"b
end
"
,
"top_coverlay"
]},
// yes|no:存在cavity层别时存yes
ATS_technology_25dc
:
{
api
:
"layer_exist"
,
props
:[
"b
ot_coverlay
"
,
"top_coverlay"
]},
// yes|no:存在cavity层别时存yes
ATS_technology_25dr
:
{
api
:
"layer_exist"
,
props
:
"nclegend-1-2"
},
// yes|no:存在cavity层别时存yes
ATS_technology_25dr
:
{
api
:
"layer_exist"
,
props
:
[
"bot_coverlay"
,
"top_coverlay"
]
},
// yes|no:存在cavity层别时存yes
// vc_src_EDGE_PLATING: true, // yes|no:检查线路外形是否存在物件,存在则存yes // !料号需要有rout层
// vc_src_EDGE_PLATING: true, // yes|no:检查线路外形是否存在物件,存在则存yes // !料号需要有rout层
vc_src_EDGE_PLATING
:
{
api
:
"layer_exist2"
,
props
:[
"fab_page2"
]},
// fab_page2
vc_src_EDGE_PLATING
:
{
api
:
"layer_exist2"
,
props
:[
"fab_page2"
]},
// fab_page2
edge_plating_length
:
true
,
// todo 检查线路外形处物件的长度
edge_plating_length
:
true
,
// todo 检查线路外形处物件的长度
gold_finger
:
tru
e
,
//
gold_finger
:
fals
e
,
//
glod_finger_area
:
tru
e
,
//
glod_finger_area
:
fals
e
,
//
ATS_sm_side
:
true
,
// top|bot|both:检查防焊层所在面次 ATS_sm_side
ATS_sm_side
:
true
,
// top|bot|both:检查防焊层所在面次 ATS_sm_side
vc_id_print_side
:
true
,
// top|bot|both:检查文字层所在面次 vc_id_print_side
vc_id_print_side
:
true
,
// top|bot|both:检查文字层所在面次 vc_id_print_side
min_drl_size
:
true
,
// todo 0.5mm 最小圆孔
min_drl_size
:
true
,
// todo 0.5mm 最小圆孔
...
@@ -443,34 +447,69 @@ try {
...
@@ -443,34 +447,69 @@ try {
console
.
log
(
"===================================> 5 save drill info"
)
console
.
log
(
"===================================> 5 save drill info"
)
// * 获取pcs_step 和 array_step的钻孔信息
// * 获取pcs_step 和 array_step的钻孔信息
var
drill_info
=
{};
var
drill_
tool_
info
=
{};
var
drillLayers
=
analysis_obj
.
matrixInfo
.
mDrills
;
var
drillLayers
=
analysis_obj
.
matrixInfo
.
mDrills
;
[
pcs_step
,
array_step
].
forEach
(
function
(
step
){
var
pcs_steps
=
[
par
.
pcs_step
]
if
(
step
){
var
arr_steps
=
[
par
.
array_step
]
var
tmp_step
=
step
+
"_tmp"
drillLayers
.
forEach
(
function
(
item
){
GEN
.
matrixCopyStep
({
job
:
job
,
step
:
tmp_step
,
step
:
tmp_step
})
var
layer
=
item
.
name
GEN
.
COM
(
"copy_entity"
,{
type
:
"step"
,
source_job
:
job
,
source_name
:
step
,
dest_job
:
job
,
dest_name
:
tmp_step
})
if
(
pcs_steps
.
length
>
0
){
GEN
.
openStep
({
job
:
job
,
name
:
tmp_step
})
pcs_steps
.
forEach
(
function
(
step
){
GEN
.
COM
(
'sredit_reduce_nesting,mode=one_highest'
)
if
(
!
GEN
.
isLayerEmpty
({
job
:
job
,
step
:
step
,
layer
:
layer
})){
drill_info
[
step
]
=
drill_info
[
step
]
||
{};
var
tool
=
GEN
.
getTool
({
job
:
job
,
step
:
step
,
layer
:
layer
,
units
:
"mm"
});
drillLayers
.
forEach
(
function
(
layer
){
if
(
drill_tool_info
[
layer
]){
var
layer_tool_manager
=
GEN
.
getTool
({
job
:
job
,
step
:
step
,
layer
:
layer
.
name
,
units
:
"mm"
})
Object
.
keys
(
tool
).
forEach
(
function
(
hashkey
){
drill_info
[
step
][
layer
.
name
]
=
layer_tool_manager
if
(
drill_tool_info
[
layer
][
hashkey
]){
if
(
!
drill_tool_info
[
layer
][
hashkey
].
pcs_count
){
drill_tool_info
[
layer
][
hashkey
].
pcs_count
=
0
}
drill_tool_info
[
layer
][
hashkey
].
pcs_count
+=
Number
(
tool
[
hashkey
].
count
)
;
}
})
})
GEN
.
closeStep
()
}
else
{
GEN
.
deleteStep
({
job
:
job
,
step
:
tmp_step
})
drill_tool_info
[
layer
]
=
tool
;
Object
.
keys
(
tool
).
forEach
(
function
(
hashkey
){
if
(
!
drill_tool_info
[
layer
][
hashkey
].
pcs_count
){
drill_tool_info
[
layer
][
hashkey
].
pcs_count
=
0
}
drill_tool_info
[
layer
][
hashkey
].
pcs_count
+=
Number
(
tool
[
hashkey
].
count
)
;
})
}
}
})
}
if
(
arr_steps
.
length
>
0
){
arr_steps
.
forEach
(
function
(
step
){
if
(
!
GEN
.
isLayerEmpty
({
job
:
job
,
step
:
step
,
layer
:
layer
})){
var
tool
=
GEN
.
getTool
({
job
:
job
,
step
:
step
,
layer
:
layer
,
units
:
"mm"
});
if
(
drill_tool_info
[
layer
]){
Object
.
keys
(
tool
).
forEach
(
function
(
hashkey
){
if
(
drill_tool_info
[
layer
][
hashkey
]){
if
(
!
drill_tool_info
[
layer
][
hashkey
].
array_count
){
drill_tool_info
[
layer
][
hashkey
].
array_count
=
0
}
drill_tool_info
[
layer
][
hashkey
].
array_count
+=
Number
(
tool
[
hashkey
].
count
)
;
}
})
}
else
{
drill_tool_info
[
layer
]
=
tool
;
Object
.
keys
(
tool
).
forEach
(
function
(
hashkey
){
if
(
!
drill_tool_info
[
layer
][
hashkey
].
array_count
){
drill_tool_info
[
layer
][
hashkey
].
array_count
=
0
}
drill_tool_info
[
layer
][
hashkey
].
array_count
+=
Number
(
tool
[
hashkey
].
count
)
;
})
}
}
}
})
})
var
pcs_tool_manager
=
drill_info
[
pcs_step
];
}
var
array_tool_manager
=
drill_info
[
array_step
];
})
Object
.
keys
(
pcs_tool_manager
).
forEach
(
function
(
layer
){
// 删除
Object
.
keys
(
pcs_tool_manager
[
layer
]).
forEach
(
function
(
key
){
db
.
query
(
""
,
function
(
q
){
var
tool
=
pcs_tool_manager
[
layer
][
key
];
return
q
.
deleteRow
({
var
array_count
;
table
:
'pdm_job_cam_drill'
,
if
(
array_tool_manager
&&
array_tool_manager
[
layer
]
&&
array_tool_manager
[
layer
][
key
]){
array_count
=
array_tool_manager
[
layer
][
key
].
count
}
where
:{
job_id
:
JobId
}
})
});
var
seq_index
=
1
;
Object
.
keys
(
drill_tool_info
).
forEach
(
function
(
layer
){
var
datalist
=
[]
var
tool_num
=
1
;
_
.
values
(
drill_tool_info
[
layer
]).
sort
(
function
(
a
,
b
){
return
a
.
drill_size
-
b
.
drill_size
}).
forEach
(
function
(
item
){
var
layer_name
=
layer
var
layer_name
=
layer
var
drill_type
=
tool
.
type
var
drill_type
=
item
.
type
var
finish_size
=
tool
.
finish_size
-
0
if
(
matrix
[
layer
].
type
==
"laser_drill"
&&
/^
[^\d]
+
(\d
+
)
-
(\d
+
)[^\d]?
$/
.
test
(
layer_name
)){
if
(
matrix
[
layer
].
type
==
"laser_drill"
&&
/^
[^\d]
+
(\d
+
)
-
(\d
+
)[^\d]?
$/
.
test
(
layer_name
)){
drill_type
=
"laser"
drill_type
=
"laser"
var
info_drilll
=
/^
[^\d]
+
(\d
+
)
-
(\d
+
)[^\d]?
$/
.
exec
(
layer_name
);
var
info_drilll
=
/^
[^\d]
+
(\d
+
)
-
(\d
+
)[^\d]?
$/
.
exec
(
layer_name
);
...
@@ -481,54 +520,39 @@ try {
...
@@ -481,54 +520,39 @@ try {
var
info_drilll
=
/^
[^\d]
+
(\d
+
)
-
(\d
+
)[^\d]?
$/
.
exec
(
layer_name
);
var
info_drilll
=
/^
[^\d]
+
(\d
+
)
-
(\d
+
)[^\d]?
$/
.
exec
(
layer_name
);
layer_name
=
"d"
+
info_drilll
[
1
]
+
"-"
+
info_drilll
[
2
];
layer_name
=
"d"
+
info_drilll
[
1
]
+
"-"
+
info_drilll
[
2
];
}
}
if
(
matrix
[
layer
].
type
==
"bury_drill"
){
if
(
matrix
[
layer
].
type
==
"bury_drill"
){
drill_type
=
"via"
drill_type
=
"via"
}
}
var
data
=
{
var
data
=
{
job_id
:
JobId
,
job_id
:
JobId
,
layer_name
:
layer_name
,
layer_name
:
layer_name
,
tool_num
:
key
,
tool_num
:
"T"
+
tool_num
,
tool_flag
:
key
,
tool_flag
:
tool_num
,
tool_type
:
tool
.
shape
,
tool_type
:
item
.
shape
,
drill_type
:
drill_type
,
drill_type
:
drill_type
,
// drill_size : tool.drill_size,
// drill_size : item.drill_size,
// drill_slot_length: tool.slot_len,
drill_slot_length
:
Number
(
item
.
slot_len
),
finish_size
:
finish_size
.
toFixed
(
3
),
finish_size
:
Number
(
item
.
finish_size
).
toFixed
(
3
),
finish_slot_length
:
tool
.
slot_len
,
finish_slot_length
:
Number
(
item
.
slot_len
),
// size_tol_lower: tool.min_tol,
// size_tol_lower: item.min_tol,
// size_tol_upper: tool.max_tol,
// size_tol_upper: item.max_tol,
pcs_count
:
tool
.
count
,
pcs_count
:
item
.
pcs_count
||
0
,
array_count
:
array_count
,
array_count
:
item
.
array_count
||
0
,
attr_data
:
{
"org_layer_name"
:
layer
,
row
:
tmp_matrix
[
layer
].
row
}
// {"allowance": 2, "org_layer_name": "hhhh"}
seq
:
seq_index
+
tool_num
/
100
,
}
attr_data
:
{
"org_layer_name"
:
layer
}
if
(
!
array_count
){
delete
data
.
array_count
}
}
var
id
=
db
.
query
(
""
,
function
(
q
){
datalist
.
push
(
data
)
return
q
.
selectValue
({
tool_num
++
table
:
'pdm_job_cam_drill'
,
})
field
:
"id"
,
seq_index
++
where
:{
job_id
:
JobId
,
layer_name
:
layer
,
tool_num
:
key
}
// datalist存入
})
datalist
.
forEach
(
function
(
data
){
});
console
.
log
(
"=========>drillid:"
+
id
)
if
(
/done/ig
.
test
(
id
)
||
!
id
){
db
.
query
(
""
,
function
(
q
){
db
.
query
(
""
,
function
(
q
){
return
q
.
insertRow
({
return
q
.
insertRow
({
table
:
'pdm_job_cam_drill'
,
table
:
'pdm_job_cam_drill'
,
data
:
data
,
data
:
data
return_field
:
'id'
,
})
});
}
else
{
db
.
query
(
""
,
function
(
q
){
return
q
.
updateRow
({
table
:
'pdm_job_cam_drill'
,
where
:
{
id
:
id
},
data
:
data
,
update_policy
:{
tags
:
'array_append'
,
attr_data
:
'json_merge'
}
})
})
});
});
}
})
})
})
})
...
@@ -682,7 +706,7 @@ try {
...
@@ -682,7 +706,7 @@ try {
})
})
stepList
.
forEach
(
function
(
step
){
stepList
.
forEach
(
function
(
step
){
GEN
.
openStep
({
job
:
job
,
name
:
step
})
GEN
.
openStep
({
job
:
job
,
name
:
step
})
// GEN.units({type:'mm'})
// 曝光
// 曝光
analysis_obj
.
matrixInfo
.
mOuters
.
forEach
(
function
(
item
){
analysis_obj
.
matrixInfo
.
mOuters
.
forEach
(
function
(
item
){
if
(
ALL
.
gold_fingers
.
length
>
0
){
if
(
ALL
.
gold_fingers
.
length
>
0
){
...
@@ -692,16 +716,27 @@ try {
...
@@ -692,16 +716,27 @@ try {
})
})
var
layer_gold_type
=
/top/ig
.
test
(
item
.
signalL
)
?
"top"
:
"bot"
var
layer_gold_type
=
/top/ig
.
test
(
item
.
signalL
)
?
"top"
:
"bot"
if
(
tmp_gold_info
[
layer_gold_type
]){
if
(
tmp_gold_info
[
layer_gold_type
]){
var
tmp_info
=
GEN
.
exposedArea
({
layer1
:
item
.
signalL
,
mask1
:
tmp_gold_info
[
layer_gold_type
]})
var
tmp_info
=
GEN
.
copperArea
({
layer1
:
tmp_gold_info
[
layer_gold_type
],
resolution_value
:
1
})
// console.log(_.toString({
// var tmp_info = GEN.exposedArea({layer1:item.signalL,mask1:tmp_gold_info[layer_gold_type]})
// ref_layer: tmp_gold_info[item.type],
var
tmp_data
=
{}
// exposed_area: tmp_info
if
(
layer_gold_type
==
"top"
)
{
// }));
tmp_data
.
sf_area_ref_layer_front
=
tmp_gold_info
[
layer_gold_type
]
tmp_data
.
sf_area_gold_area_front
=
tmp_info
.
area
}
if
(
layer_gold_type
==
"bot"
){
tmp_data
.
sf_area_ref_layer_back
=
tmp_gold_info
[
layer_gold_type
]
tmp_data
.
sf_area_gold_area_back
=
tmp_info
.
area
}
save_job_info
({
jobid
:
JobId
,
jobinfohash
:
tmp_data
})
save_layerinfo
({
save_layerinfo
({
jobid
:
JobId
,
jobid
:
JobId
,
layer
:
item
.
signalL
,
layer
:
item
.
signalL
,
layerinfohash
:
{
layerinfohash
:
{
sf_area_gold_area
:
tmp_info
.
percent
sf_area_ref_layer
:
tmp_gold_info
[
layer_gold_type
],
sf_area_gold_area
:
tmp_info
.
area
}
}
})
})
}
}
...
@@ -711,23 +746,24 @@ try {
...
@@ -711,23 +746,24 @@ try {
// {"area":"0.73817","percent":"8.986"}
// {"area":"0.73817","percent":"8.986"}
var
tmp_area
=
tmp_info
.
area
var
tmp_area
=
tmp_info
.
area
var
tmp_percent
=
tmp_info
.
percent
;
var
tmp_percent
=
tmp_info
.
percent
;
var
tmp_data
=
/top/ig
.
test
(
item
.
signalL
)
?
{
carbon_Area_front
:
tmp_area
}
:
{
carbon_Area_back
:
tmp_area
}
// todo carbon
var tmp_data = /top/ig.test(item.signalL) ? {carbon_Area_front:tmp_area} : {carbon_Area_back:tmp_area}
save_job_info
({
//
save_job_info({
jobid
:
JobId
,
//
jobid: JobId,
jobinfohash
:
tmp_data
//
jobinfohash: tmp_data
})
//
})
save_layerinfo
({
save_layerinfo
({
jobid
:
JobId
,
jobid
:
JobId
,
layer
:
item
.
signalL
,
layer
:
item
.
signalL
,
layerinfohash
:
{
layerinfohash
:
{
ref_layer
:
item
.
solderL
,
ref_layer
:
item
.
solderL
,
exposed_area
:
tmp_
percent
exposed_area
:
tmp_
area
}
}
})
})
}
}
})
})
GEN
.
clearLayers
()
GEN
.
clearLayers
()
GEN
.
affectedLayer
({
affected
:
'no'
,
mode
:
'all'
})
GEN
.
affectedLayer
({
affected
:
'no'
,
mode
:
'all'
})
// GEN.units({type:'inch'})
console
.
log
(
"==================================> Drill analysis"
)
console
.
log
(
"==================================> Drill analysis"
)
// 钻孔
// 钻孔
...
@@ -1189,7 +1225,20 @@ function analysis(props){
...
@@ -1189,7 +1225,20 @@ function analysis(props){
}
}
T_m_p
.
prototype
.
analysis_vc_array_size
=
function
(
props
){
// array长边尺寸 string
T_m_p
.
prototype
.
analysis_vc_array_size
=
function
(
props
){
// array长边尺寸 string
if
(
!
this
.
array_step
){
return
"_error"
}
if
(
!
this
.
array_step
){
return
"_error"
}
return
GEN
.
getProfileLimits
({
job
:
this
.
job
,
step
:
this
.
array_step
,
units
:
"mm"
})[
props
].
toFixed
(
2
)
var
tmp
=
GEN
.
getProfileLimits
({
job
:
this
.
job
,
step
:
this
.
array_step
,
units
:
"mm"
})
var
size1
=
Number
(
tmp
.
xsize
)
var
size2
=
Number
(
tmp
.
ysize
)
if
(
size1
>
size2
){
var
tmpsize
=
size2
size2
=
size1
size1
=
tmpsize
}
if
(
props
==
"xsize"
){
return
size1
.
toFixed
(
2
)
}
if
(
props
==
"ysize"
){
return
size2
.
toFixed
(
2
)
}
}
}
T_m_p
.
prototype
.
analysis_vc_pcs_count_on_panel
=
function
(
props
){
//
T_m_p
.
prototype
.
analysis_vc_pcs_count_on_panel
=
function
(
props
){
//
if
(
!
this
.
array_step
){
return
"_error"
}
if
(
!
this
.
array_step
){
return
"_error"
}
...
@@ -1812,7 +1861,10 @@ function min_symbols_anal(props){ // 分析最 symbols
...
@@ -1812,7 +1861,10 @@ function min_symbols_anal(props){ // 分析最 symbols
GEN
.
selectByFilter
({
include_syms
:
symbols
.
symbol
})
GEN
.
selectByFilter
({
include_syms
:
symbols
.
symbol
})
var
tmp_layer
=
layer
.
signalL
+
"_tmp_1"
var
tmp_layer
=
layer
.
signalL
+
"_tmp_1"
selCopyLayer
({
job
:
job
,
layer
:
tmp_layer
})
selCopyLayer
({
job
:
job
,
layer
:
tmp_layer
})
// 留下pitch最小的bga 如果pitch都一样大 就跳过
res
.
min_bga_pitch
=
(
bgaPitch
({
job
:
job
,
step
:
step
,
layer
:
tmp_layer
})
-
0
)
+
(
symbols
.
size
-
0
)
// 分析数据
// 分析数据
GEN
.
clearLayers
()
// 尺寸
// 尺寸
res
.
min_bga_size
=
symbols
.
size
res
.
min_bga_size
=
symbols
.
size
// 开窗大小
// 开窗大小
...
@@ -1864,8 +1916,6 @@ function min_symbols_anal(props){ // 分析最 symbols
...
@@ -1864,8 +1916,6 @@ function min_symbols_anal(props){ // 分析最 symbols
}
}
GEN
.
deleteLayer
({
job
:
job
,
layer
:[
solderL_tmp
,
solderL_tmp
+
"+++"
]})
GEN
.
deleteLayer
({
job
:
job
,
layer
:[
solderL_tmp
,
solderL_tmp
+
"+++"
]})
}
}
// 间距
res
.
min_bga_pitch
=
(
bgaPitch
({
job
:
job
,
step
:
step
,
layer
:
tmp_layer
})
-
0
)
+
(
symbols
.
size
-
0
)
GEN
.
deleteLayer
({
job
:
job
,
layer
:
tmp_layer
})
GEN
.
deleteLayer
({
job
:
job
,
layer
:
tmp_layer
})
return
res
return
res
}
}
...
@@ -2016,6 +2066,9 @@ function bgaPitch(props){
...
@@ -2016,6 +2066,9 @@ function bgaPitch(props){
var
job
=
props
.
job
var
job
=
props
.
job
var
step
=
props
.
step
var
step
=
props
.
step
var
layer
=
props
.
layer
var
layer
=
props
.
layer
var
ck
=
"tmp_chk"
var
ck
=
"tmp_chk"
if
(
GEN
.
isChklistExists
({
job
:
job
,
step
:
step
,
chklist
:
ck
})){
if
(
GEN
.
isChklistExists
({
job
:
job
,
step
:
step
,
chklist
:
ck
})){
GEN
.
COM
(
"chklist_delete"
,
{
chklist
:
ck
})
GEN
.
COM
(
"chklist_delete"
,
{
chklist
:
ck
})
...
@@ -2067,10 +2120,20 @@ function bgaPitch(props){
...
@@ -2067,10 +2120,20 @@ function bgaPitch(props){
GEN
.
COM
(
"chklist_create_lyrs,chklist="
+
ck
+
",severity=3,suffix=pitch"
);
GEN
.
COM
(
"chklist_create_lyrs,chklist="
+
ck
+
",severity=3,suffix=pitch"
);
GEN
.
workLayer
({
name
:
tmp_layer2
,
display_number
:
1
,
clear_before
:
'yes'
});
GEN
.
workLayer
({
name
:
tmp_layer2
,
display_number
:
1
,
clear_before
:
'yes'
});
GEN
.
selectByFilter
({
attribute
:[{
attribute
:
".string"
,
text
:
"p2p"
}]})
GEN
.
selectByFilter
({
attribute
:[{
attribute
:
".string"
,
text
:
"p2p"
}]})
GEN
.
saveJob
({
job
:
job
})
var
tmp_layer
=
tmp_layer2
+
"_tmp"
var
tmp_layer
=
tmp_layer2
+
"_tmp"
selCopyLayer
({
job
:
job
,
layer
:
tmp_layer
})
selCopyLayer
({
job
:
job
,
layer
:
tmp_layer
})
GEN
.
workLayer
({
name
:
tmp_layer
,
display_number
:
1
,
clear_before
:
'yes'
});
GEN
.
workLayer
({
name
:
tmp_layer
,
display_number
:
1
,
clear_before
:
'yes'
});
// var symbollists = GEN.getLayerSymsHist({job:job,step:step,layer:tmp_layer})
// var sys = Object.keys(symbollists)
// if(sys.length > 1){
// sys = sys.sort(function(a,b){return symbollists[a].size - symbollists[b].size})
// // todo 如何找到线距离最小的pad 删除其他的
// }
var
features
=
GEN
.
getFeatures
({
job
:
job
,
step
:
step
,
layer
:
tmp_layer
})
var
features
=
GEN
.
getFeatures
({
job
:
job
,
step
:
step
,
layer
:
tmp_layer
})
console
.
log
(
"---------features:"
,
_
.
toString
(
features
))
var
tmp
=
features
.
map
(
function
(
v
){
var
tmp
=
features
.
map
(
function
(
v
){
var
num
=
Math
.
sqrt
((
v
.
xe
-
v
.
xs
)
*
(
v
.
xe
-
v
.
xs
)
+
(
v
.
ye
-
v
.
ys
)
*
(
v
.
ye
-
v
.
ys
))
*
1000
var
num
=
Math
.
sqrt
((
v
.
xe
-
v
.
xs
)
*
(
v
.
xe
-
v
.
xs
)
+
(
v
.
ye
-
v
.
ys
)
*
(
v
.
ye
-
v
.
ys
))
*
1000
return
num
.
toFixed
(
4
)
return
num
.
toFixed
(
4
)
...
@@ -2139,7 +2202,6 @@ function createOutline(props){
...
@@ -2139,7 +2202,6 @@ function createOutline(props){
GEN
.
deleteLayer
({
job
:
job
,
layer
:
tmp_layer
})
GEN
.
deleteLayer
({
job
:
job
,
layer
:
tmp_layer
})
return
false
return
false
}
}
}
}
function
has_steps
(
props
){
function
has_steps
(
props
){
...
...
ats/scott_test/input_test.js
View file @
6f787924
...
@@ -130,18 +130,12 @@ try {
...
@@ -130,18 +130,12 @@ try {
if
(
!
fs
.
exists
(
path
)){
throw
"path error"
}
if
(
!
fs
.
exists
(
path
)){
throw
"path error"
}
var
pathInfo
=
fs
.
listDir
(
path
+
"/"
+
db_customer
.
toLowerCase
(),
1
)
var
pathInfo
=
fs
.
listDir
(
path
+
"/"
+
db_customer
.
toLowerCase
(),
1
)
// 判断存不存在料号文件
// 判断存不存在料号文件
var
vc_position
=
db
.
query
(
""
,
function
(
q
){
return
q
.
selectValue
({
table
:
'pdm_job'
,
field
:
'version'
,
where
:{
id
:
JobId
}
})
});
var
job_file_baseName
=
job
var
job_file_baseName
=
job
// if(vc_position && vc_position != "" && !(/null/ig.test(vc_position))){
// if(vc_position && vc_position != "" && !(/null/ig.test(vc_position))){
// job_file_baseName = job_file_baseName + "_" + vc_position
// job_file_baseName = job_file_baseName + "_" + vc_position
// }
// }
var
jobFile
=
pathInfo
.
filter
(
function
(
v
){
return
v
.
baseName
.
toLowerCase
()
==
job_file_baseName
})
var
jobFile
=
pathInfo
.
filter
(
function
(
v
){
return
v
.
baseName
.
toLowerCase
()
==
job_file_baseName
})
if
(
jobFile
.
length
==
0
){
throw
"job file is not exist"
}
if
(
jobFile
.
length
==
0
){
throw
"job file is not exist"
}
var
jobFiles
=
[]
// 记录要分析的文件
var
jobFiles
=
[]
// 记录要分析的文件
if
(
!
jobFile
[
0
].
isDir
)
{
if
(
!
jobFile
[
0
].
isDir
)
{
...
@@ -155,6 +149,7 @@ try {
...
@@ -155,6 +149,7 @@ try {
var
importOk
=
false
;
// 是否成功导入
var
importOk
=
false
;
// 是否成功导入
if
(
/odb/ig
.
test
(
jobInfo
.
type
)){
// odb导入
if
(
/odb/ig
.
test
(
jobInfo
.
type
)){
// odb导入
if
(
jobInfo
.
data
.
length
==
1
){
// 只分析到一个tgz文件 直接导入
if
(
jobInfo
.
data
.
length
==
1
){
// 只分析到一个tgz文件 直接导入
console
.
log
(
"========= import one ====>path:"
+
_
.
toString
(
jobInfo
.
data
))
// ? tmp
var
err
=
importJob
({
name
:
job
,
db
:
custCfg
.
db
,
path
:
jobInfo
.
data
[
0
].
file
.
path
},
config
.
delSameJob
)
var
err
=
importJob
({
name
:
job
,
db
:
custCfg
.
db
,
path
:
jobInfo
.
data
[
0
].
file
.
path
},
config
.
delSameJob
)
if
(
err
){
throw
err
}
if
(
err
){
throw
err
}
}
else
{
// 多个tgz文件 说明需要合并
}
else
{
// 多个tgz文件 说明需要合并
...
...
config_ats.js
View file @
6f787924
...
@@ -46,6 +46,46 @@
...
@@ -46,6 +46,46 @@
"signed_coords"
:
"no"
,
"signed_coords"
:
"no"
,
"text_line_width"
:
0.0024
"text_line_width"
:
0.0024
},
},
"Gerber274x_3"
:
{
"nf1"
:
3
,
"nf2"
:
5
,
"units"
:
"mm"
,
"zeroes"
:
"leading"
,
"decimal"
:
"no"
,
"nf_comp"
:
0
,
"break_sr"
:
"yes"
,
"data_type"
:
"ascii"
,
"separator"
:
"*"
,
"threshold"
:
200
,
"drill_only"
:
"no"
,
"multiplier"
:
1
,
"resolution"
:
3
,
"tool_units"
:
"inch"
,
"coordinates"
:
"absolute"
,
"merge_by_rule"
:
"no"
,
"signed_coords"
:
"no"
,
"text_line_width"
:
0.0024
},
"Gerber274x_4"
:
{
"nf1"
:
2
,
"nf2"
:
3
,
"units"
:
"mm"
,
"zeroes"
:
"none"
,
"decimal"
:
"no"
,
"nf_comp"
:
0
,
"break_sr"
:
"yes"
,
"data_type"
:
"ascii"
,
"separator"
:
"*"
,
"threshold"
:
200
,
"drill_only"
:
"no"
,
"multiplier"
:
1
,
"resolution"
:
3
,
"tool_units"
:
"mm"
,
"coordinates"
:
"absolute"
,
"merge_by_rule"
:
"no"
,
"signed_coords"
:
"no"
,
"text_line_width"
:
0.0024
},
"Excellon1_1"
:{
"Excellon1_1"
:{
"nf1"
:
3
,
"nf1"
:
3
,
"nf2"
:
0
,
"nf2"
:
0
,
...
@@ -126,6 +166,66 @@
...
@@ -126,6 +166,66 @@
"signed_coords"
:
"no"
,
"signed_coords"
:
"no"
,
"text_line_width"
:
0.0024
"text_line_width"
:
0.0024
},
},
"Excellon2_4"
:
{
"nf1"
:
2
,
"nf2"
:
3
,
"units"
:
"mm"
,
"zeroes"
:
"leading"
,
"decimal"
:
"no"
,
"nf_comp"
:
0
,
"break_sr"
:
"yes"
,
"data_type"
:
"ascii"
,
"separator"
:
"nl"
,
"threshold"
:
200
,
"drill_only"
:
"no"
,
"multiplier"
:
1
,
"resolution"
:
3
,
"tool_units"
:
"mm"
,
"coordinates"
:
"absolute"
,
"merge_by_rule"
:
"no"
,
"signed_coords"
:
"no"
,
"text_line_width"
:
0.0024
},
"Excellon2_5"
:
{
"nf1"
:
3
,
"nf2"
:
2
,
"units"
:
"mm"
,
"zeroes"
:
"leading"
,
"decimal"
:
"no"
,
"nf_comp"
:
0
,
"break_sr"
:
"yes"
,
"data_type"
:
"ascii"
,
"separator"
:
"nl"
,
"threshold"
:
200
,
"drill_only"
:
"no"
,
"multiplier"
:
1
,
"resolution"
:
3
,
"tool_units"
:
"mm"
,
"coordinates"
:
"absolute"
,
"merge_by_rule"
:
"no"
,
"signed_coords"
:
"no"
,
"text_line_width"
:
0.0024
},
"Excellon2_6"
:
{
"nf1"
:
2
,
"nf2"
:
4
,
"units"
:
"mm"
,
"zeroes"
:
"leading"
,
"decimal"
:
"no"
,
"nf_comp"
:
0
,
"break_sr"
:
"yes"
,
"data_type"
:
"ascii"
,
"separator"
:
"nl"
,
"threshold"
:
200
,
"drill_only"
:
"no"
,
"multiplier"
:
1
,
"resolution"
:
3
,
"tool_units"
:
"mm"
,
"coordinates"
:
"absolute"
,
"merge_by_rule"
:
"no"
,
"signed_coords"
:
"no"
,
"text_line_width"
:
0.0024
},
"IPC356_1"
:
{
"IPC356_1"
:
{
"nf1"
:
2
,
"nf1"
:
2
,
"nf2"
:
4
,
"nf2"
:
4
,
...
@@ -145,6 +245,26 @@
...
@@ -145,6 +245,26 @@
"merge_by_rule"
:
"no"
,
"merge_by_rule"
:
"no"
,
"signed_coords"
:
"no"
,
"signed_coords"
:
"no"
,
"text_line_width"
:
0.0024
"text_line_width"
:
0.0024
},
"IPC356A_1"
:{
"nf1"
:
2
,
"nf2"
:
4
,
"units"
:
"inch"
,
"zeroes"
:
"none"
,
"decimal"
:
"no"
,
"nf_comp"
:
0
,
"break_sr"
:
"yes"
,
"data_type"
:
"ascii"
,
"separator"
:
"*"
,
"threshold"
:
200
,
"drill_only"
:
"no"
,
"multiplier"
:
1
,
"resolution"
:
3
,
"tool_units"
:
"inch"
,
"coordinates"
:
"absolute"
,
"merge_by_rule"
:
"no"
,
"signed_coords"
:
"no"
,
"text_line_width"
:
0.0024
}
}
},
},
"customer"
:
{
"customer"
:
{
...
@@ -545,6 +665,215 @@
...
@@ -545,6 +665,215 @@
{
"orig_name"
:
"fab_page2"
,
"tl_name"
:
"fab_page2"
},
{
"orig_name"
:
"fab_page2"
,
"tl_name"
:
"fab_page2"
},
{
"orig_name"
:
[
"_d(
\\
d)(
\\
d+)
\\
.drd"
,
"_d(
\\
d)(
\\
d+)
\\
.fdr"
,
"^d(
\\
d)(
\\
d+)
\\
.art$"
,
"(
\\
d+)-(
\\
d+)-laser
\\
.drl"
,
"d(
\\
d+)-(
\\
d+)"
],
"tl_name"
:
"d_($1)-($2)"
}
{
"orig_name"
:
[
"_d(
\\
d)(
\\
d+)
\\
.drd"
,
"_d(
\\
d)(
\\
d+)
\\
.fdr"
,
"^d(
\\
d)(
\\
d+)
\\
.art$"
,
"(
\\
d+)-(
\\
d+)-laser
\\
.drl"
,
"d(
\\
d+)-(
\\
d+)"
],
"tl_name"
:
"d_($1)-($2)"
}
]
]
},
"Wistron"
:{
"step"
:
"cad"
,
"rules"
:
[
{
"valid"
:
function
(
props
){
var
file
=
props
.
file
;
return
/.+
\.
tgz$/ig
.
test
(
file
.
name
)
},
"type"
:
"ODB"
,
"format"
:
"ODB"
},
{
"valid"
:
function
(
props
){
var
file
=
props
.
file
;
return
/.+
\.
btd$|.+
\.
rou$/ig
.
test
(
file
.
name
)
},
"type"
:
"IPC356A"
,
"format"
:
"IPC356A_1"
},
{
"valid"
:
function
(
props
){
var
file
=
props
.
file
;
return
/.+
\.
ger$/ig
.
test
(
file
.
name
)
||
/
\.
gdo$|
\.
bol$|
\.
gdo$|
\.
pma$|
\.
sma$|
\.
smb$|
\.
ssa$|
\.
ssb$/ig
.
test
(
file
.
name
)
||
/.+
\.
l
\d
+$/ig
.
test
(
file
.
name
)
},
"type"
:
"Gerber274x"
,
"format"
:
"Gerber274x_3"
},
{
"valid"
:
function
(
props
){
var
file
=
props
.
file
;
return
/.+
\.
ncd$/ig
.
test
(
file
.
name
)
},
"type"
:
"Excellon2"
,
"format"
:
"Excellon2_4"
},
{
"valid"
:
function
(
props
){
var
file
=
props
.
file
;
return
/.+
\.
d
\d
+$/ig
.
test
(
file
.
name
)
},
"type"
:
"Excellon2"
,
"format"
:
"Excellon2_6"
},
{
"valid"
:
function
(
props
){
var
file
=
props
.
file
;
return
/.+
\.
art$/ig
.
test
(
file
.
name
)
},
"type"
:
"Gerber274x"
,
"format"
:
"Gerber274x_3"
,
"format_params"
:
function
(
props
){
var
params
=
props
.
params
if
(
params
.
art_param
){
var
leading
=
params
.
art_param
[
"SUPPRESS_LEAD_ZEROES"
]
var
trailing
=
params
.
art_param
[
"SUPPRESS_TRAIL_ZEROES"
]
var
zeroes
=
"none"
if
(
/yes/ig
.
test
(
leading
)){
zeroes
=
"leading"
}
if
(
/yes/ig
.
test
(
trailing
)){
zeroes
=
"trailing"
}
var
nf1
,
nf2
if
(
params
.
art_param
.
hasOwnProperty
(
"FORMAT"
)){
var
tmp
=
params
.
art_param
[
"FORMAT"
].
split
(
"."
)
if
(
/
\d
+/ig
.
test
(
tmp
[
0
])){
nf1
=
Number
(
tmp
[
0
])}
if
(
/
\d
+/ig
.
test
(
tmp
[
1
])){
nf2
=
Number
(
tmp
[
1
])}
}
return
{
"nf1"
:
nf1
||
3
,
"nf2"
:
nf2
||
5
,
"units"
:
/
METRIC
|
MM
/
ig
.
test
(
params
.
art_param
[
"OUTPUT_UNITS"
])?
"mm"
:
"inch"
,
"zeroes"
:
zeroes
,
"decimal"
:
"no"
,
"nf_comp"
:
0
,
"break_sr"
:
"yes"
,
"data_type"
:
"ascii"
,
"separator"
:
"*"
,
"threshold"
:
200
,
"drill_only"
:
"no"
,
"multiplier"
:
1
,
"resolution"
:
3
,
"tool_units"
:
/
METRIC
|
MM
/
ig
.
test
(
params
.
art_param
[
"OUTPUT_UNITS"
])?
"mm"
:
"inch"
,
"coordinates"
:
"absolute"
,
"merge_by_rule"
:
"no"
,
"signed_coords"
:
"no"
,
"text_line_width"
:
0.0024
}
}
}
},
{
"valid"
:
function
(
props
){
var
file
=
props
.
file
;
return
/.+
\.
drl$/ig
.
test
(
file
.
name
)
},
"type"
:
"Excellon2"
,
"format"
:
"Excellon2_4"
,
"format_params"
:
function
(
props
){
var
params
=
props
.
params
if
(
params
.
nc_param
){
var
leading
=
params
.
nc_param
[
"SUPPRESS_LEAD_ZEROES"
]
var
trailing
=
params
.
nc_param
[
"SUPPRESS_TRAIL_ZEROES"
]
var
zeroes
=
"none"
if
(
/yes/ig
.
test
(
leading
)){
zeroes
=
"leading"
}
if
(
/yes/ig
.
test
(
trailing
)){
zeroes
=
"trailing"
}
return
{
"nf1"
:
params
.
nc_param
[
"INTEGER_PLACES"
]?
Number
(
params
.
nc_param
[
"INTEGER_PLACES"
])
:
3
,
"nf2"
:
params
.
nc_param
[
"DECIMAL_PLACES"
]?
Number
(
params
.
nc_param
[
"DECIMAL_PLACES"
])
:
5
,
"units"
:
/
METRIC
|
MM
/
ig
.
test
(
params
.
nc_param
[
"OUTPUT_UNITS"
])?
"mm"
:
"inch"
,
"zeroes"
:
zeroes
,
"decimal"
:
"no"
,
"nf_comp"
:
0
,
"break_sr"
:
"yes"
,
"data_type"
:
"ascii"
,
"separator"
:
"nl"
,
"threshold"
:
200
,
"drill_only"
:
"no"
,
"multiplier"
:
1
,
"resolution"
:
3
,
"tool_units"
:
/
METRIC
|
MM
/
ig
.
test
(
params
.
nc_param
[
"OUTPUT_UNITS"
])?
"mm"
:
"inch"
,
"coordinates"
:
params
.
nc_param
[
"COORDINATES"
]?
params
.
nc_param
[
"COORDINATES"
].
toLowerCase
()
:
"absolute"
,
"merge_by_rule"
:
"no"
,
"signed_coords"
:
"no"
,
"text_line_width"
:
0.0024
}
}
}
}
],
"tl_name"
:
[
{
"orig_name"
:
[
"assytop.art"
,
"past_top"
],
"tl_name"
:
"past_top"
},
{
"orig_name"
:
[
"assybot.art"
,
"past_botm"
],
"tl_name"
:
"past_botm"
},
{
"orig_name"
:
[
"pleg.art"
,
"^ss_top"
,
"silk_top"
],
"tl_name"
:
"silk_top"
},
{
"orig_name"
:
[
"sleg.art"
,
"^ss_bot"
,
"silk_bot"
],
"tl_name"
:
"silk_bot"
},
{
"orig_name"
:
[
"ssm.art"
,
"sm_top"
],
"tl_name"
:
"sm_top"
},
{
"orig_name"
:
[
"psm.art"
,
"sm_bot"
],
"tl_name"
:
"sm_botm"
},
{
"orig_name"
:
[
"^top$"
,
"^top.art$"
],
"tl_name"
:
"top"
},
{
"orig_name"
:
[
"^0(
\\
d+).*ccp_ms"
,
"^s(
\\
d+)
\
.art"
,
"lay(
\\
d+)
\\
.art"
,
"layer_(
\\
d+)"
],
"tl_name"
:
"l_($1)"
},
{
"orig_name"
:
[
"^bottom$"
,
"^bottom.art$"
],
"tl_name"
:
"bottom"
},
{
"orig_name"
:
[
"-(
\\
d+)-(
\\
d+)
\
.drl$"
,
"(
\\
d+)-(
\\
d+)-laser
\
.drl$"
,
"d(
\\
d+)-(
\\
d+)"
],
"tl_name"
:
"d_($1)-($2)"
},
{
"orig_name"
:
[
"
\\
.rou$"
,
"^rout$"
],
"tl_name"
:
"rout"
},
{
"orig_name"
:
"fab.art"
,
"tl_name"
:
"fab.art"
},
{
"orig_name"
:
[
"multipack.art"
,
"^array$"
],
"tl_name"
:
"array"
},
{
"orig_name"
:
[
"^outline"
],
"tl_name"
:
"outline"
},
{
"orig_name"
:
[
"top-enig"
,
"enig_top"
],
"tl_name"
:
"enig_top"
},
{
"orig_name"
:
[
"bot-enig"
,
"enig_bot"
],
"tl_name"
:
"enig_bot"
},
]
},
"Vivo"
:{
"step"
:
"cad"
,
"rules"
:
[
{
"valid"
:
function
(
props
){
var
file
=
props
.
file
;
return
/.+
\.
tgz$/ig
.
test
(
file
.
name
)
},
"type"
:
"ODB"
,
"format"
:
"ODB"
},
{
"valid"
:
function
(
props
){
var
file
=
props
.
file
;
return
/.+
\.
btd$|.+
\.
rou$/ig
.
test
(
file
.
name
)
},
"type"
:
"IPC356A"
,
"format"
:
"IPC356A_1"
},
{
"valid"
:
function
(
props
){
var
file
=
props
.
file
;
return
/
\.
gdo$/ig
.
test
(
file
.
name
)
},
"type"
:
"Gerber274x"
,
"format"
:
"Gerber274x_4"
},
{
"valid"
:
function
(
props
){
var
file
=
props
.
file
;
return
/.+
\.
ncd$/ig
.
test
(
file
.
name
)
||
/.+
\.
d
\d
+$/ig
.
test
(
file
.
name
)
},
"type"
:
"Excellon2"
,
"format"
:
"Excellon2_5"
}
],
"tl_name"
:
[
{
"orig_name"
:
[
"assytop.art"
,
"past_top"
],
"tl_name"
:
"past_top"
},
{
"orig_name"
:
[
"assybot.art"
,
"past_botm"
],
"tl_name"
:
"past_botm"
},
{
"orig_name"
:
[
"pleg.art"
,
"^ss_top"
,
"silk_top"
],
"tl_name"
:
"silk_top"
},
{
"orig_name"
:
[
"sleg.art"
,
"^ss_bot"
,
"silk_bot"
],
"tl_name"
:
"silk_bot"
},
{
"orig_name"
:
[
"ssm.art"
,
"sm_top"
],
"tl_name"
:
"sm_top"
},
{
"orig_name"
:
[
"psm.art"
,
"sm_bot"
],
"tl_name"
:
"sm_botm"
},
{
"orig_name"
:
[
"^top$"
,
"^top.art$"
],
"tl_name"
:
"top"
},
{
"orig_name"
:
[
"^0(
\\
d+).*ccp_ms"
,
"^s(
\\
d+)
\
.art"
,
"lay(
\\
d+)
\\
.art"
,
"layer_(
\\
d+)"
],
"tl_name"
:
"l_($1)"
},
{
"orig_name"
:
[
"^bottom$"
,
"^bottom.art$"
],
"tl_name"
:
"bottom"
},
{
"orig_name"
:
[
"-(
\\
d+)-(
\\
d+)
\
.drl$"
,
"(
\\
d+)-(
\\
d+)-laser
\
.drl$"
,
"d(
\\
d+)-(
\\
d+)"
],
"tl_name"
:
"d_($1)-($2)"
},
{
"orig_name"
:
[
"
\\
.rou$"
,
"^rout$"
],
"tl_name"
:
"rout"
},
{
"orig_name"
:
"fab.art"
,
"tl_name"
:
"fab.art"
},
{
"orig_name"
:
[
"multipack.art"
,
"^array$"
],
"tl_name"
:
"array"
},
{
"orig_name"
:
[
"^outline"
],
"tl_name"
:
"outline"
},
{
"orig_name"
:
[
"top-enig"
,
"enig_top"
],
"tl_name"
:
"enig_top"
},
{
"orig_name"
:
[
"bot-enig"
,
"enig_bot"
],
"tl_name"
:
"enig_bot"
},
]
}
}
},
},
"data_format"
:
[
"data_format"
:
[
...
...
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