Commit ba8d156b authored by Scott Sun's avatar Scott Sun

s

parent 1dbd449a
......@@ -3,18 +3,6 @@
DESCRIPTION: 客户数据分析
PARAMETER:
[
{
name : 'step_filter',
title : 'Step过滤',
type : 'LineEdit',
property : {tool_tip : '过滤step信息'}
},
{
name : 'erf',
title : 'erf名称',
type : 'LineEdit',
property : {tool_tip : ''}
},
{
name : 'auto_save',
title : '自动保存',
......@@ -44,79 +32,326 @@
<br>
</body></html>
*/
console.log("=============================================>anaysis_start");
// 引入模块 包
var $ = require('topcam.scriptfunc').argv();
var fs = require('fs');
var _ = require('lodash');
var IKM = $.ikm;
var GEN = $.gen;
var GUI = $.gui;
var Job = $.job;
var JobId = $.job_id;
var mode = "develop" // 运行模式 develop 开发模式 方便调试
var database = require("topsin.database");
database.addConnection($.conf.database_conf, "DFM");
var QDfm = database.query("DFM");
if ($.conf.product_type == "aimdfm") {
QDfm.updateRow({
table: "pdm_aimdfm_task",
data: {
current_process_title: $.process_title
},
where: { id: $.task_id }
});
}
var GEN = $.gen;
var Job = $.job_name;
var db = $.db;
var Status = 'ok';
var resultData = [];
var PAR = {};
if ($.hasOwnProperty('script_parameter')){
PAR = JSON.parse($.script_parameter);
}
try {
IKM.crud("insertRow",{
table:'pdm_job_org_drill',
data:{
step_name:"cad"
// job_id:"1",step_name:"cad",step_type:"pcs", std_layer_name:"d_1-2",odb_layer_name:"d1-2",
// row_num:"1", drill_size:"r2",finish_size:"r2.1",drill_type:"laser_drill",drill_shape:"s",
// slot_length:"12", count:"231",drill_size_lower_tol:"23",drill_size_upper_tol:"asd"
var job = Job;
var pcs_step = "cad", array_step = "stp";
var matrix = UPLOAD_LAYER_MATRIX({job:job}) // 分析matrix 获得分析后的matrix信息
console.log("===================================> 1matrix")
var analysis_obj = analysis({job:job,jobId:JobId,pcs_step:pcs_step,array_step:array_step,matrix:matrix})
var config = {
jobInfo: {
layer_count: ["signal","power_ground"], // Board属性的signal或者power_ground层
vc_card_size_w: {api:"vc_card_size", props:"xsize"}, // card短边尺寸 // ? 保留小数
vc_card_size_l: {api:"vc_card_size", props:"ysize"}, // card长边尺寸 // ? 保留小数
vc_array_size_w: {api:"vc_array_size", props:"xsize"}, // ! array短边尺寸 需要arr_step // ? 保留小数
vc_array_size_l: {api:"vc_array_size", props:"ysize"}, // ! array长边尺寸 需要arr_step // ? 保留小数
vc_pcs_count_on_panel: true, // todo array中pcs的数量 ! 需要arr_step
stack_vias_number: true, // via孔连续叠加的层数
stack_vias_more: {only_value:true}, // yes|no : 14层板以上时,Stack Vias >=12时,存yes // ! 需要分析完via连续叠加层数
depth_drilling: {api:"layer_exist", props:"depth_drill"}, // yes|no :存在depth_drill 层时 ,存yes
depth_routing: {api:"layer_exist", props:"depth_routing"}, // tmp yes|no :存在depth_routing 层时,,存yes
laser_via_on_buried_hole: true, // todo via孔在埋孔上时,存yes
milling_bit_size: true, // todo 检查array中pcs的最小间距值
milling_length: true, // todo 检查array中铣切长度
vc_src_01005_pad_result: {api:"board_has_attr", props:".smd"}, // * yes|no:board 层中检查存在01005属性物件时,存yes 这里先拿.smd代替了
ATS_technology_25dc: {api:"layer_exist", props:"cavity"}, // yes|no:存在cavity层别时存yes
ATS_technology_25dr: {api:"layer_exist", props:"cavity"}, // yes|no:存在cavity层别时存yes
vc_src_EDGE_PLATING: true, // yes|no:检查线路外形是否存在物件,存在则存yes // !料号需要有rout层
edge_plating_length: true, // todo 检查线路外形处物件的长度
glod_finger: true, // todo yes|no:暂无逻辑
glod_finger_area: true, // todo 暂无逻辑
solder_mask_side: true, // top|bot|both:检查防焊层所在面次
silk_screen_side: true, // top|bot|both:检查文字层所在面次
min_drl_size: true, // todo 0.5mm 最小圆孔
max_pth_drl_size: true, // todo 3.5mm 最大pth圆孔
max_npth_drl_size: true, // todo 6.0mm 最大npth圆孔
min_slot_drl_size: true, // todo 0.8mm 最小槽孔
max_slot_drl_size: true, // todo 1.2mm 最大槽孔
max_slot_drl_length: true, // todo 2.0mm 最大槽孔
max_spec_slot_drl_size: true, // todo 2.1mm 最大异形槽孔
max_spec_slot_drl_length: true, // todo 3.0mm 最大异形槽孔
},
return_field:'uid',
layerInfo: {
}
}
console.log("===================================> 2analysis_obj")
// 分析料号info
var jobInfo = {}
Object.keys(config.jobInfo).forEach(function(key){
var props = config.jobInfo[key];
if(props){
try {
if(props.hasOwnProperty("api") && props.hasOwnProperty("props")){
jobInfo[key] = analysis_obj["analysis_"+props.api](props.props)
} else if(props.only_value){
jobInfo[key] = analysis_obj.jobInfo[key]
} else {
jobInfo[key] = analysis_obj["analysis_"+key](props)
}
} catch (e) {
console.log(e);
jobInfo[key] = "_error"
}
}
})
var job = "1"
console.log("===================================> 3 jobinfo")
var matrix = UPLOAD_LAYER_MATRIX({job:job}) // 分析matrix 获得分析后的matrix信息
// 过滤掉料号信息的 _todo 和 _error
for (var key in jobInfo) {
if(jobInfo[key] === "_todo" || jobInfo[key] === "_error"){
delete jobInfo[key]
}
}
console.log("===================================> 4 save job info")
// 获得镭射层
// 上传jobInfo IKM版本
// IKM.save_job_info({
// jobid: JobId,
// jobinfohash:jobInfo
// })
// 上传jobInfo topjs3版本
save_job_info({
jobid: JobId,
jobinfohash: jobInfo
})
console.log("===================================> 5 save drill info")
var laser_drills = _.values(matrix).filter(function(v){return v.type == "laser_drill"})
// todo 设置钻孔层孔属性,镭射孔via,无铜孔npth,其余孔pth
laser_drills.forEach(function(layer){
GEN.workLayer({name:layer.name, display_number:1,clear_before:"yes"})
GEN.selClearFeature()
GEN.selAllFeat()
var count = GEN.getSelectCount()
if(GEN.getSelectCount()>0){
// GEN.selAddAttr({attribute:"via"})
// todo 上传钻孔信息
// 获取pcs_step 和 array_step的钻孔信息
var drill_info = {};
var drillLayers = analysis_obj.matrixInfo.mDrills;
[pcs_step, array_step].forEach(function(step){
drill_info[step] = drill_info[step] || {};
drillLayers.forEach(function(layer){
var layer_tool_manager = GEN.getTool({job:job, step:step,layer:layer.name})
drill_info[step][layer.name] = layer_tool_manager
})
})
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){
var tool = pcs_tool_manager[layer][key];
var array_count;
if(array_tool_manager && array_tool_manager[layer] && array_tool_manager[layer][key]){array_count = array_tool_manager[layer][key].count}
var data = {
job_id: JobId,
step_name: "cad",
odb_layer_name: layer.odb_name,
row_num: layer.row_num,
drill_type:layer.type,
count:count
layer_name: layer,
tool_num: key,
tool_flag: key,
tool_type: tool.shape,
drill_type:tool.type,
drill_size : tool.drill_size,
drill_slot_length: tool.slot_len,
finish_size : tool.finish_size,
finish_slot_length: tool.slot_len,
size_tol_lower: tool.min_tol,
size_tol_upper: tool.max_tol,
pcs_count: tool.count,
array_count: array_count, // todo
attr_data: {} // {"allowance": 2, "org_layer_name": "hhhh"}
}
if(!array_count){delete data.array_count}
var id = db.query("",function(q){
return q.selectValue({
table:'pdm_job_cam_drill',
field:"id",
where:{job_id:JobId, layer_name: layer,tool_num: key}
})
});
if(/done/ig.test(id)){
db.query("",function(q){
return q.insertRow({
table:'pdm_job_cam_drill',
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'}
})
});
}
GEN.selClearFeature()
GEN.clearLayers()
})
var laser_drills_info = laser_drills
// 获取钻孔信息
})
console.log("===================================> 6 layer info")
// 分析layer info
var stepList = [pcs_step];
var oChecklistName = "mychecklist"
var signalLayers = analysis_obj.matrixInfo.mSignal.map(function(v){return v.name})
var drillLayers = analysis_obj.matrixInfo.mDrill.map(function(v){return v.name})
var info = {
min_line_width: ["line"],
min_line_spacing: ["l2l"],
min_line2pad: ["p2line"],
min_pad2pad: ["p2p", "smd2smd", "smd2pad"],
min_ar: ["ar","pth_ar"]
}
stepList.forEach(function(step){
GEN.openStep({ job: job, name: step })
GEN.clearLayers()
GEN.affectedLayer({ affected: 'no', mode: 'all' })
// 创建chklist并运行 如果chklist存在先删除
if (GEN.isChklistExists({ job: job, step: step, chklist: oChecklistName })) {
GEN.COM("chklist_delete", { chklist: oChecklistName })
}
createChklistAndRun({ // 创建checklist并运行
layers: signalLayers,
items: [{
name: "signal_layer_checks",
nact: 1,
action: "valor_analysis_signal",
erf: "S2_conductor_Check",
params: { // ?
pp_layer: ".affected",
pp_spacing: 20,
pp_selected: "All",
pp_r2c: 10,
pp_d2c: 15,
pp_sliver: 8,
pp_min_pad_overlap: 5,
pp_check_missing_pads_for_drills: "Yes",
pp_use_compensated_rout: "Skeleton",
pp_sm_spacing: "Yes"
}
}]
})
// signal层分析结果
var res = analysisChkAttr({layers:signalLayers, info:info, step:step, job:job, oChecklistName:oChecklistName})
// 铜面积
var copper_percent_pcs = signalLayers.map(function(v){
var tmp = {layer:v}
tmp.copper_percent = GEN.copperArea({layer1:v}).percent + "%"
return tmp
})
// 钻孔
var drillToSignals = drillLayers.map(function(v){ // 获取到钻孔层对应的顶层和底层
var simbols = GEN.getLayerSymsHist({job:job,step:step,layer:v})
var symbol = _.values(simbols).sort(function(a,b){return Number(a.size)-Number(b.size)})
.reduce(function(a,b){
if(b.pad!="0"){
a.push(b.symbol)
}
return a
},[])[0]
return {layer:v,symbol:symbol,start:matrix[v]["drl_start"],end:matrix[v]["drl_end"]}
})
var drillRes = analysisDrill(drillToSignals,step) // 钻孔分析结果
// 数据入库
Object.keys(res).forEach(function(key){
var val = res[key]
save_layerinfo({
jobid: JobId,
layer: key,
layerinfohash: val
})
})
copper_percent_pcs.forEach(function(item){
save_layerinfo({
jobid: JobId,
layer: item.layer,
layerinfohash: {
copper_percent: item.copper_percent
}
})
})
drillRes.forEach(function(item){
save_layerinfo({
jobid: JobId,
layer: item.layer,
layerinfohash: {
drl_pad_top: item.drl_pad_top,
drl_pad_bot: item.drl_pad_bot,
}
})
})
})
// smd
var smdInfo = smdAnalysis({job:job,steplist:[pcs_step],layers:analysis_obj.matrixInfo.mOuters,attr:".smd"})
var save_info = [smdInfo, analysis_obj.jobInfo.laser_info]; // 保存 smd 和 bga数据
// 保存
console.log("===================================> save layer info")
save_info.forEach(function(item){
Object.keys(item).forEach(function(key){
var val = item[key]
save_layerinfo({
jobid: JobId,
layer: key,
layerinfohash: val
})
})
})
GUI.msg("Done")
return 'Done';
QDfm.updateRow({
table: "pdm_aimdfm_task",
data: {
progress: 33.33
},
where: { id: $.task_id }
});
if (GEN.hasError()) {
Status = 'error';
resultData.push({ type: "error", title: "GEN错误!", detail: [{ desc: _.join(GEN.STATUS, "\n") }] });
return {
status: Status,
result_data: resultData
};
} else {
resultData.push({ type: "info", title: "操作完成, 请注意检查!" });
return {
status: Status,
result_data: resultData
};
}
}
catch (error) {
GUI.msg(error);
return 'Error';
catch (e) {
Status = 'error';
console.log("====================================>error");
console.log(_.toString(e));
resultData.push({type: "error", title: "脚本执行出错!", detail: [{desc: _.toString(e)}]});
return {status: Status, result_data: resultData};
}
function UPLOAD_LAYER_MATRIX(props){
......@@ -273,9 +508,591 @@ function ANALYSIS_STACKUP(props){
})
return matrix;
}
function getMatrixInfo(props){ // 获取matrix各种信息
var job = props.job
var matrix = GEN.getMatrix({job:job})
var res = {
matrix: matrix, // matrix
matrixVal: [], // matrix 的 value数组
mSignal: {}, // board的signal层 {}
mSignals: [], // board的signal层 []
mDrill: {}, // board的drill层
mDrills: [], // board的drill层
mSolderMask: {}, // 防焊层
mSolderMasks: [], // 防焊层
mOuters: [], // 外层和对于的防旱
mBoardLayer: [] // board层
}
for (var key in matrix) {
var value = matrix[key]
res.matrixVal.push(value)
if(value.context == "board"){
res.mBoardLayer.push(key)
switch (value.layer_type) {
case "signal":
res.mSignal[key] = value
res.mSignals.push(value)
break;
case "drill":
res.mDrill[key] = value
res.mDrills.push(value)
break;
case "solder_mask":
res.mSolderMask[key] = value
res.mSolderMasks.push(value)
break;
}
}
}
res.matrixVal = res.matrixVal.sort(function(a,b){return Number(a.row) - Number(b.row)})
res.mSignals = res.mSignals.sort(function(a,b){return Number(a.row) - Number(b.row)})
res.mDrills = res.mDrills.sort(function(a,b){return Number(a.row) - Number(b.row)})
// 找出外层 以及外层对应的防焊层 [{signalL:"top", solderL:"smt"}]
res.mOuters = res.mSignals.reduce(function(a,b){
if(b.tl_type == "outer"){
var solderLayers = res.mSolderMasks.filter(function(v){
return v.side == b.side
})
a.push({
signalL: b.name,
solderL: solderLayers.length >0 ? solderLayers[0]["name"] : null
})
}
return a
},[])
return res
}
function selCopyLayer(props){ // 拷贝选择的到辅助层
var layer = props.layer
var job = props.job
if(GEN.isLayerExists({job:job,layer:layer})){
GEN.deleteLayer({job:job,layer:layer})
}
GEN.selCopyOther({dest:'layer_name',target_layer:layer})
}
function save_job_info(props){ // todo 保存料号信息
var jobid = props.jobid;
var jobinfohash = props.jobinfohash;
Object.keys(jobinfohash).forEach(function(key){
var val = jobinfohash[key];
db.query("",function(q){
return q.insertRow({
table:'sys_user', // todo
data:{jobid:jobid, todo:key, value:val}, // todo
return_field:'id',
})
});
})
}
function save_layerinfo(props){ // todo 保存层信息
var jobid = props.jobid;
var layer = props.layer;
var layerinfohash = props.layerinfohash;
Object.keys(layerinfohash).forEach(function(key){
var val = layerinfohash[key];
db.query("",function(q){
return q.insertRow({
table:'sys_user', // todo
data:{jobid:jobid, layer:layer,key:key , value:val}, // todo
return_field:'id',
})
});
})
}
function analysis(props){
var job = props.job || Job;
var jobId = props.jobId || JobId;
var pcs_step = props.pcs_step || false;
var array_step = props.array_step || false;
var matrix = props.matrix;
function T_m_p(props){
this.job = props.job;
this.jobInfo = {};
this.jobId = props.jobId;
if(props.pcs_step){ this.pcs_step = props.pcs_step; }
if(props.matrix){ this.matrix = props.matrix; }
if(props.array_step){ this.array_step = props.array_step; }
this.matrixInfo = getMatrixInfo({job:this.job})
this.init();
}
T_m_p.prototype.init = function(){
var init_checking = ["job", "jobId", "pcs_step", "matrix"];
var t = this;
init_checking.forEach(function(v){ if(!t[v]){t.e(v+" is undefined")} })
}
T_m_p.prototype.e = function(e){ // 处理error
console.log(e)
throw e
}
T_m_p.prototype.analysis_layer_count = function(props){ // 分析board属性的层数量 []string
var matrix = this.matrixInfo.matrixVal;
var res = matrix.filter(function(v){return v.context == "board" && props.indexOf(v.layer_type) >= 0 })
return res.length
}
T_m_p.prototype.analysis_vc_card_size = function(props){ // card短边尺寸 string
return GEN.getProfileLimits({job:this.job,step:this.pcs_step})[props].toFixed(3)
}
T_m_p.prototype.analysis_vc_array_size = function(props){ // array长边尺寸 string
if(!this.array_step){return "error"}
return GEN.getProfileLimits({job:this.job,step:this.array_step})[props].toFixed(3)
}
T_m_p.prototype.analysis_vc_pcs_count_on_panel = function(props){ //
return "_todo"
}
T_m_p.prototype.analysis_stack_vias_number = function(props){ // via孔连续叠加的层数
var t = this;
var res;
// 找出 镭射孔
var laser_layers = []
for (var key in t.matrix) {
var val = t.matrix[key]
if(val.type == "laser_drill"){
laser_layers.push(val)
}
}
if(laser_layers.length == 0){return "error"}
GEN.openStep({job:t.job,name:t.pcs_step})
laser_layers = laser_layers.sort(function(a,b){return Number(a.row)-Number(b.row)})
var laser_info = {}
for(var i = 0; i < laser_layers.length-1; i++){
var start_layer = laser_layers[i].name
var cover_layer = laser_layers[i+1].name
GEN.workLayer({name:start_layer,display_number:2,clear_before:'yes'})
GEN.selClearFeature()
GEN.selRefFeat({layers:cover_layer,use:'filter',mode:'cover'})
var count = GEN.getSelectCount()
if(count>0){
if(!laser_info[start_layer]){
laser_info[start_layer] = {}
}
laser_info[start_layer].drill_connect_layer = cover_layer
laser_info[start_layer].drill_connect_point = count
}
}
// via孔连续叠加的层数
var via_vias_info = []
function analysis_via_number(layers){
if(layers.length < 2){return}
var startlayer = layers[0].name + "_cover"
GEN.selClearFeature()
GEN.workLayer({name:layers[0].name,display_number:2,clear_before:'yes'})
GEN.selAllFeat()
selCopyLayer({job:t.job,layer:startlayer})
var end_index = start_cover_next(startlayer,layers,0)
via_vias_info.push(end_index+1)
analysis_via_number(layers.slice(end_index))
}
function start_cover_next(start, layers, end_index){
if(layers.length < 2){
GEN.deleteLayer({job:t.job,layer:start})
return end_index
}
layers = layers.slice(1)
GEN.workLayer({name:start,display_number:2,clear_before:'yes'})
GEN.selClearFeature()
GEN.selRefFeat({layers:layers[0].name,use:'filter',mode:'cover'})
var count = GEN.getSelectCount()
if (count < 1) {
GEN.deleteLayer({job:t.job,layer:start})
return ++end_index
}
var nextstartlayer = layers[0].name + "_cover"
selCopyLayer({job:t.job,layer:nextstartlayer})
GEN.deleteLayer({job:t.job,layer:start})
return start_cover_next(nextstartlayer,layers,++end_index)
}
analysis_via_number(laser_layers.slice())
if (via_vias_info.length == 1){
res = via_vias_info[0]
}else{
res = via_vias_info.reduce(function(a,b){return a-b>0?a :b})
}
t.jobInfo.stack_vias_more = "no"
if(GEN.getLayerCount({job:t.job}) > 14 && res >= 12){
t.jobInfo.stack_vias_more = "yes"
}
t.jobInfo.laser_info = laser_info;
return res
}
T_m_p.prototype.analysis_layer_exist = function(props){ // 存在某某层? string
return this.matrixInfo.matrix.hasOwnProperty(props) ? "yes" : "no"
}
T_m_p.prototype.analysis_laser_via_on_buried_hole = function(){ // todo
return "_todo"
}
T_m_p.prototype.analysis_milling_bit_size = function(){ // todo
return "_todo"
}
T_m_p.prototype.analysis_milling_length = function(){ // todo
return "_todo"
}
T_m_p.prototype.analysis_board_has_attr = function(props){ // board层中检查存在01005属性物件时
GEN.openStep({job:this.job,name:this.pcs_step})
GEN.clearLayers()
GEN.affectedLayer({affected:'yes',layer:this.matrixInfo.mBoardLayer,clear_before:'yes'});
GEN.selClearFeature()
GEN.selectByFilter({attribute:props})
var res = GEN.getSelectCount() > 0? "yes" : "no"
GEN.affectedLayer({affected:'no',mode:'all'});
GEN.selClearFeature()
GEN.closeStep()
return res
}
T_m_p.prototype.analysis_vc_src_EDGE_PLATING = function(props){ // ? 检查线路外形是否存在物件,存在则存yes
var res = "no"
var rout = this.matrixInfo.matrixVal.filter(function(v){return v.layer_type == "rout"}) // 找rout层
if(rout.length == 0){
return "error:cant find rout layer"
}
GEN.openStep({job:this.job, name:this.pcs_step})
GEN.affectedLayer({affected:'no',mode:'all'})
try {
this.matrixInfo.mSignals.forEach(function(v){ // 用线路层逐层与rout层touch 找得到说明存在
GEN.workLayer({name:v.name,display_number:2,clear_before:'yes'})
GEN.selClearFeature()
GEN.selRefFeat({layers:rout[0].name,mode:"touch",use:"filter"})
if( GEN.getSelectCount()>0){
throw "yes"
}
GEN.clearLayers()
})
} catch (msg) {
res = msg
GEN.affectedLayer({affected:'no',mode:'all'})
GEN.selClearFeature()
}
GEN.closeStep()
return res
}
T_m_p.prototype.analysis_edge_plating_length = function(){ // todo
return "_todo"
}
T_m_p.prototype.analysis_glod_finger = function(){ // todo
return "_todo"
}
T_m_p.prototype.analysis_glod_finger_area = function(){ // todo
return "_todo"
}
T_m_p.prototype.analysis_solder_mask_side = function(){ // 检查防焊层所在面次
var solder_paste_layers = this.matrixInfo.matrixVal.filter(function(v){return v.layer_type == "solder_paste"})
var solder_paste_info= solder_paste_layers.map(function(v){return v.side}).reduce(function(a,b){
if(a.indexOf(b)<0){ a.push(b) }
return a
},[])
var res = "no"
if(solder_paste_info.length == 0){
res = "no"
} else if (solder_paste_info.length == 1) {
res = /top/ig.test(solder_paste_info[0]) ? "top" : "bot"
} else {
res = "both"
}
return res
}
T_m_p.prototype.analysis_silk_screen_side = function(){ // 检查文字层所在面次
var solder_mask_layers = this.matrixInfo.matrixVal.filter(function(v){return v.layer_type == "solder_mask"})
var solder_mask_info= solder_mask_layers.map(function(v){return v.side}).reduce(function(a,b){
if(a.indexOf(b)<0){ a.push(b) }
return a
},[])
var res = "no"
if(solder_mask_info.length == 0){
res = "no"
} else if (solder_mask_info.length == 1) {
res = /top/ig.test(solder_mask_info[0]) ? "top" : "bot"
} else {
res = "both"
}
return res
}
T_m_p.prototype.analysis_min_drl_size = function(){ // todo
return "_todo"
}
T_m_p.prototype.analysis_max_pth_drl_size = function(){ // todo
return "_todo"
}
T_m_p.prototype.analysis_max_npth_drl_size = function(){ // todo
return "_todo"
}
T_m_p.prototype.analysis_min_slot_drl_size = function(){ // todo
return "_todo"
}
T_m_p.prototype.analysis_max_slot_drl_size = function(){ // todo
return "_todo"
}
T_m_p.prototype.analysis_max_slot_drl_length = function(){ // todo
return "_todo"
}
T_m_p.prototype.analysis_max_spec_slot_drl_size = function(){ // todo
return "_todo"
}
T_m_p.prototype.analysis_max_spec_slot_drl_length = function(){ // todo
return "_todo"
}
return new T_m_p({job:job, jobId:jobId, pcs_step:pcs_step, array_step:array_step,matrix:matrix})
}
function smdAnalysis(props){
var job = props.job
var steplist = props.steplist
var layers = props.layers
var res = {}
steplist.forEach(function(step){
GEN.openStep({job:job,step:step})
layers.forEach(function(layer){
// 计算开窗 数量
GEN.workLayer({name:layer.solderL,display_number:2,clear_before:'yes'})
if (!res.hasOwnProperty(layer.solderL)){
res[layer.solderL] = {}
}
GEN.selectByFilter({profile:'in'})
GEN.selAllFeat()
res[layer.solderL].sm_opening_count = GEN.getSelectCount()
GEN.selClearFeature()
// 分析最小smd宽高
GEN.workLayer({name:layer.signalL,display_number:2,clear_before:'yes'})
GEN.selClearFeature()
GEN.selectByFilter({attribute:props.attr})
var selCount = GEN.getSelectCount()
if(selCount>0){
var tmp_layer = layer.signalL + "_tmp"
selCopyLayer({job:job,layer:tmp_layer})
var symbols = GEN.getLayerSymsHist({job:job,layer:tmp_layer,step:step})
GEN.workLayer({name:tmp_layer,display_number:2,clear_before:'yes'})
var symbolInfo = symbolAnalysis({symbols:symbols,filterReg:/^rect/})
if (!res.hasOwnProperty(layer.signalL)){
res[layer.signalL] = {}
}
res[layer.signalL]["min_smd_width"] = symbolInfo["min_width"]
res[layer.signalL]["min_smd_length"] = symbolInfo["min_length"]
// 分析最小smd间距
// 创建一个checklist并且分析
var min_smd_pitch = smdPitch({job:job,step:step,layer:tmp_layer})
res[layer.signalL]["min_smd_pitch"] = min_smd_pitch
// 分析开窗宽高
GEN.workLayer({name:layer.solderL,display_number:2,clear_before:'yes'})
GEN.selClearFeature()
GEN.selRefFeat({layers:tmp_layer,use:'filter',mode:'include'})
GEN.selRefFeat({layers:tmp_layer,use:'filter',mode:'cover'})
var solderL_tmp = layer.solderL + "_tmp"
selCopyLayer({job:job,layer:solderL_tmp})
GEN.selClearFeature()
GEN.workLayer({name:solderL_tmp,display_number:2,clear_before:"yes"})
var symbols_solder = GEN.getLayerSymsHist({job:job,layer:solderL_tmp,step:step})
var symbolInfo_solder = symbolAnalysis({symbols:symbols_solder,filterReg:/^rect/})
res[layer.signalL].min_smd_opening_width = symbolInfo_solder["min_width"]
res[layer.signalL].min_smd_opening_length = symbolInfo_solder["min_length"]
GEN.deleteLayer({job:job,layer:solderL_tmp})
GEN.deleteLayer({job:job,layer:tmp_layer})
}
})
GEN.closeStep()
})
return res
}
function symbolAnalysis(props){
var symbols = Object.keys(props.symbols).reduce(function(a,b){
if(props.filterReg.test(b)){
var res = /^rect(\d+\.\d+|\d+)x(\d+\.\d+|\d+)/ig.exec(b).slice(1)
var num1 = res[0], num2 = res[1]
if(num1<=num2){
a.width.push(num1)
a.length.push(num2)
} else {
a.width.push(num2)
a.length.push(num1)
}
}
return a
},{width:[],length:[]})
return {
min_width:symbols.width.reduce(function(a,b){return b-a > 0 ? a : b}),
min_length:symbols.length.reduce(function(a,b){return b-a > 0 ? a : b})
}
}
function smdPitch(props){
var job = props.job
var step = props.step
var layer = props.layer
var ck = "tmp_chk"
if(GEN.isChklistExists({job:job,step:step,chklist:ck})){
GEN.COM("chklist_delete", { chklist: ck })
}
// 创建并运行
GEN.createChklist({ // 创建checklist
chklist: ck,
items: [{
name: "smdPitch",
nact: 1,
action: "valor_analysis_signal",
erf: "S2_conductor_Check",
params: {
pp_layer: ".affected",
pp_spacing: 20,
pp_selected: "All",
pp_r2c: 10,
pp_d2c: 15,
pp_sliver: 8,
pp_min_pad_overlap: 5,
pp_check_missing_pads_for_drills: "Yes",
pp_use_compensated_rout: "Skeleton",
pp_sm_spacing: "Yes",
pp_tests: "Spacing\\;SMD",
pp_check_missing_pads_for_drills:"Yes"
}
}]
})
GEN.chklistShow({ chklist: ck })
GEN.affectedLayer({ affected: "yes", layer: layer, clear_before: "yes" })
GEN.chklistRun({
chklist: ck,
nact: 1,
area: 'profile'
})
var tmp_layer1 = "mk_1_"+layer+"_pitch"
var tmp_layer2 = "ms_1_"+layer+"_pitch"
if(GEN.isLayerExists({job:job,layer:tmp_layer1})){
GEN.deleteLayer({job:job,layer:tmp_layer1})
}
if(GEN.isLayerExists({job:job,layer:tmp_layer2})){
GEN.deleteLayer({job:job,layer:tmp_layer2})
}
GEN.COM("chklist_create_lyrs,chklist="+ck+",severity=3,suffix=pitch");
GEN.workLayer({name:tmp_layer2,display_number:1,clear_before:'yes'});
GEN.selectByFilter({attribute:[{attribute:".string",text:"smd_pitch"}]})
var tmp_layer = tmp_layer2 + "_tmp"
selCopyLayer({job:job,layer:tmp_layer})
GEN.workLayer({name:tmp_layer,display_number:1,clear_before:'yes'});
var symbols = GEN.getLayerSymsHist({job:job,layer:tmp_layer,step:step})
// 获取最小smd间距
var res = _.values(symbols).sort(function(a,b){return Number(a.size)-Number(b.size)})[0].size
GEN.deleteLayer({job:job,layer:tmp_layer})
GEN.deleteLayer({job:job,layer:tmp_layer1})
GEN.deleteLayer({job:job,layer:tmp_layer2})
return res
}
function createChklistAndRun(par) {
var checkLayers = par.layers
var items = par.items
GEN.createChklist({ // 创建checklist
chklist: oChecklistName,
items: items
})
GEN.chklistShow({
chklist: oChecklistName
})
GEN.affectedLayer({
affected: "yes",
layer: checkLayers,
clear_before: "yes"
})
items.forEach(function(v){
GEN.chklistRun({
chklist: oChecklistName,
nact: v.nact,
area: 'profile'
})
})
}
function analysisChkAttr(par) {
var layers = par.layers;
var hash = {};
var info = par.info;
var job = par.job;
var oChecklistName = par.oChecklistName
layers.forEach(function (v) {
hash[v] = {}
Object.keys(info).forEach(function (key) {
var val = info[key]
hash[v][key] = val.reduce(function (a, type) {
var tmp = GEN.getCheckAttr({
job: job,
step: par.step,
checklist: oChecklistName,
nact: 1,
attr: v + "_min_" + type
})
if (a === "N/A" && /\d+/.test(tmp)) {
a = tmp
}
if (/\d+/.test(a) && /\d+/.test(tmp) && Number(tmp) < Number(a)) {
a = tmp
}
return a
}, "N/A")
})
})
return hash
}
function analysisDrill(par, step){
// {"layer":"d1-2","symbol":"r3.937","start":"top","end":"isl2"}
var res = par.map(function(drill){
GEN.affectedLayer({affected:"yes",layer:drill.layer,clear_before:"yes",mode:"all"})
GEN.selClearFeature()
GEN.selectByFilter({feat_types:"pad",include_syms:drill.symbol})
// 拷贝到_tmp
var tmplayer = drill.layer + "_tmp"
if(GEN.isLayerExists({job:Job,layer:tmplayer})){GEN.deleteLayer({job:Job,step:step,layer:tmplayer})}
GEN.selCopyOther({dest:"layer_name",target_layer:tmplayer,invert:'no',dx:0,dy:0,size:0})
GEN.affectedLayer({affected:"no",mode:"all"})
GEN.selClearFeature();
[drill.start,drill.end].forEach(function(item, i){
GEN.workLayer({name:item,display_number:1,clear_before:"yes"})
GEN.selRefFeat({
layers: tmplayer,
use: "filter",
mode: "include",
f_types: "pad",
pads_as:"shape",
polarity:"positive",
include_syms:drill.symbol,
filter: {
feat_types:'pad'
}
})
var res = ""
var pads = GEN.getFeatures({job:Job,step:step,layer:item,options:"select"})
if(pads && pads.length) {
pads = pads.filter(function(item){
return /^r\d+/.test(item.symbol)
})
pads = pads.sort(function(a,b){
return parseInt(a.symbol) - parseInt(b.symbol)
})
res = pads[0].symbol.slice(1)
}
if ( i == 0) {
drill.drl_pad_top = res
} else if (i==1){
drill.drl_pad_bot = res
}
})
GEN.deleteLayer({job:Job,step:step,layer:tmplayer})
return drill
})
return res
}
function tmp(){
return {
return {
"sst": {
"row": "1","type": "solder_paste","name": "sp_fr","context": "board","layer_type": "solder_paste","polarity": "positive","drl_start": "","drl_end": "","gdrl_start": "","gdrl_end": "",
"tl_num": -1000,"tl_name": "sp_fr","tl_type": "solder_paste","odb_name": "sst","odb_context": "board","odb_type": "solder_paste","odb_polarity": "positive","odb_side": "top",
......@@ -535,9 +1352,266 @@ return {
"tl_num": 110051,"odb_name": "top_assy_mate","odb_context": "misc","odb_type": "signal","odb_polarity": "positive","odb_side": "none",
"row_num": 110051,"odb_row_num": "52"
}
}
}
}
function tmp_2(){
return {
"cad": {
"d1-2": {
"1": {
"count": "06896",
"num": "1",
"type": "via",
"min_tol": "2.756",
"max_tol": "0.984",
"finish_size": "2.756",
"drill_size": "2.756",
"slot_len": "0",
"type2": "laser",
"shape": "hole",
"bit": 0
}
},
"d2-3": {
"1": {
"count": "07430",
"num": "1",
"type": "via",
"min_tol": "2.756",
"max_tol": "0.984",
"finish_size": "2.756",
"drill_size": "2.756",
"slot_len": "0",
"type2": "laser",
"shape": "hole",
"bit": 0
}
},
"d3-4": {
"1": {
"count": "06866",
"num": "1",
"type": "via",
"min_tol": "2.756",
"max_tol": "0.984",
"finish_size": "2.756",
"drill_size": "2.756",
"slot_len": "0",
"type2": "laser",
"shape": "hole",
"bit": 0
}
},
"d4-5": {
"1": {
"count": "06413",
"num": "1",
"type": "via",
"min_tol": "2.756",
"max_tol": "0.984",
"finish_size": "2.756",
"drill_size": "2.756",
"slot_len": "0",
"type2": "laser",
"shape": "hole",
"bit": 0
}
},
"d5-6": {
"1": {
"count": "08938",
"num": "1",
"type": "via",
"min_tol": "2.756",
"max_tol": "0.984",
"finish_size": "2.756",
"drill_size": "2.756",
"slot_len": "0",
"type2": "laser",
"shape": "hole",
"bit": 0
}
},
"d6-7": {
"1": {
"count": "09057",
"num": "1",
"type": "via",
"min_tol": "2.756",
"max_tol": "0.984",
"finish_size": "2.756",
"drill_size": "2.756",
"slot_len": "0",
"type2": "laser",
"shape": "hole",
"bit": 0
}
},
"d7-8": {
"1": {
"count": "07818",
"num": "1",
"type": "via",
"min_tol": "2.756",
"max_tol": "0.984",
"finish_size": "2.756",
"drill_size": "2.756",
"slot_len": "0",
"type2": "laser",
"shape": "hole",
"bit": 0
}
},
"d8-9": {
"1": {
"count": "09126",
"num": "1",
"type": "via",
"min_tol": "2.756",
"max_tol": "0.984",
"finish_size": "2.756",
"drill_size": "2.756",
"slot_len": "0",
"type2": "laser",
"shape": "hole",
"bit": 0
}
},
"d9-10": {
"1": {
"count": "08498",
"num": "1",
"type": "via",
"min_tol": "2.756",
"max_tol": "0.984",
"finish_size": "2.756",
"drill_size": "2.756",
"slot_len": "0",
"type2": "laser",
"shape": "hole",
"bit": 0
}
},
"drill": {
"1": {
"count": "05",
"num": "1",
"type": "non_plated",
"min_tol": "3.15",
"max_tol": "3.15",
"finish_size": "15.748",
"drill_size": "15.748",
"slot_len": "0",
"type2": "standard",
"shape": "hole",
"bit": 0
},
"2": {
"count": "01",
"num": "2",
"type": "non_plated",
"min_tol": "0",
"max_tol": "1.969",
"finish_size": "35.039",
"drill_size": "35.039",
"slot_len": "0",
"type2": "standard",
"shape": "hole",
"bit": 0
},
"3": {
"count": "01",
"num": "3",
"type": "non_plated",
"min_tol": "3.15",
"max_tol": "3.15",
"finish_size": "35.039",
"drill_size": "35.039",
"slot_len": "0",
"type2": "standard",
"shape": "hole",
"bit": 0
},
"4": {
"count": "01",
"num": "4",
"type": "non_plated",
"min_tol": "1.969",
"max_tol": "1.969",
"finish_size": "47.244",
"drill_size": "47.244",
"slot_len": "0",
"type2": "standard",
"shape": "hole",
"bit": 0
},
"5": {
"count": "05",
"num": "5",
"type": "non_plated",
"min_tol": "1.969",
"max_tol": "1.969",
"finish_size": "59.055",
"drill_size": "59.055",
"slot_len": "0",
"type2": "standard",
"shape": "hole",
"bit": 0
},
"6": {
"count": "01",
"num": "6",
"type": "non_plated",
"min_tol": "1.969",
"max_tol": "1.969",
"finish_size": "70.866",
"drill_size": "70.866",
"slot_len": "0",
"type2": "standard",
"shape": "hole",
"bit": 0
},
"7": {
"count": "01",
"num": "7",
"type": "non_plated",
"min_tol": "1.969",
"max_tol": "1.969",
"finish_size": "74.803",
"drill_size": "74.803",
"slot_len": "0",
"type2": "standard",
"shape": "hole",
"bit": 0
}
}
},
"stp": {
"d1-2": {},
"d2-3": {},
"d3-4": {},
"d4-5": {},
"d5-6": {},
"d6-7": {},
"d7-8": {},
"d8-9": {},
"d9-10": {},
"drill": {
"1": {
"count": "08",
"num": "1",
"type": "non_plated",
"min_tol": "0",
"max_tol": "1.969",
"finish_size": "118.11",
"drill_size": "118.11",
"slot_len": "0",
"type2": "standard",
"shape": "hole",
"bit": 0
}
}
}
}
}
\ No newline at end of file
......@@ -75,6 +75,7 @@ if ($.conf.product_type == "aimdfm") {
}
var GEN = $.gen;
var Job = $.job_name;
var JobId = $.job_id;
var db = $.db;
var Status = 'ok';
var resultData = [];
......@@ -95,6 +96,16 @@ try {
console.log("========================db");
par.db = "genesis"
};
var db_customer = db.query("",function(q){
return q.selectValue({
table:'pdm_job',
field:'customer_code',
where:{id : JobId}
})
});
if(db_customer && !(/^done$/ig.test(db_customer)) && db_customer != "" ){
par.customer = db_customer
}
par.customer = par.customer[0].toUpperCase()+par.customer.slice(1).toLowerCase()
var cfg = db.query("",function(q){
return q.selectValue({
......
......@@ -58,7 +58,8 @@ if ($.conf.product_type == "aimdfm") {
}
var GEN = $.gen;
var Job = $.job_name;
var db = $.db
var db = $.db;
var JobId = $.job_id;
var Status = 'ok';
var resultData = [];
var PAR = {};
......@@ -74,6 +75,16 @@ try {
console.log("========================cfg");
par.config_path = "cam/input_data"
};
var db_customer = db.query("",function(q){
return q.selectValue({
table:'pdm_job',
field:'customer_code',
where:{id : JobId}
})
});
if(db_customer && !(/^done$/ig.test(db_customer)) && db_customer != "" ){
par.customer = db_customer
}
par.customer = par.customer[0].toUpperCase()+par.customer.slice(1).toLowerCase()
var cfg = db.query("",function(q){
return q.selectValue({
......@@ -117,6 +128,23 @@ try {
// 改名
err = reName({job:job, matrix:after_sort_matrix, cfg:format_cfg})
if(err){throw err}
// 创建profile
var new_martix = GEN.getMatrix({job:job})
var profileLayer = Object.keys(new_martix).filter(function(v){
return new_martix[v].layer_type=="rout"
})
if(profileLayer.length){
var tmp = profileLayer[0]
if(profileLayer.indexOf("outline")>=0){tmp = "outline"}
var step = GEN.getStepList({job:job})[0];
GEN.openStep({job:job,name:step})
GEN.workLayer({name:tmp,display_number:2,clear_before:'yes'})
GEN.selCreateProfile()
GEN.closeStep()
}
// end
GEN.checkInout({job:job,mode:"out"}) // 结束保存料号 关闭料号
GEN.saveJob({ job: job });
......
......@@ -150,7 +150,6 @@
"customer": {
"Customer_1": {
"path": "/opt/resource/customer_1",
"db": "genesis",
"step": "cad",
"rules": [
{
......@@ -190,15 +189,16 @@
}
],
"tl_name": [
{"orig_name" : "^spt$", "tl_name" : "spt" },
{"orig_name" : "^smt$", "tl_name" : "smt" },
{"orig_name" : "^smb$", "tl_name" : "smb" },
{"orig_name" : "^spb$", "tl_name" : "spb" },
{"orig_name" : "^ssb$", "tl_name" : "ssb" },
{"orig_name" : "^sst$", "tl_name" : "sst" },
{"orig_name" : ["^sst$","^past_top$"], "tl_name" : "past_top" },
{"orig_name" : ["^ssb$","^past_botm$"], "tl_name" : "past_botm" },
{"orig_name" : ["^spt$","^silk_top$"], "tl_name" : "silk_top" },
{"orig_name" : ["^spb$","^silk_bot$"], "tl_name" : "silk_bot" },
{"orig_name" : ["^smt$","^sm_top$"], "tl_name" : "sm_top" },
{"orig_name" : ["^smb$","^sm_botm$"], "tl_name" : "sm_botm" },
{"orig_name" : "^top$", "tl_name" : "top" },
{"orig_name" : "^drill$", "tl_name" : "drill" },
{"orig_name" : "^rout$", "tl_name" : "rout" },
{"orig_name" : ["outline.art","^outline$"], "tl_name" : "outline" },
{"orig_name" : ["^rout$","\\.rou$"], "tl_name" : "rout" },
{"orig_name" : "^bottom$", "tl_name" : "bottom" },
{"orig_name" : ["^isl(\\d+)$","^layer_(\\d+)$"], "tl_name" : "l_($1)"},
{"orig_name" : ["_isl(\\d+)_isl(\\d+)","d(\\d+)-(\\d+)"], "tl_name" : "d_($1)-($2)"},
......@@ -208,7 +208,6 @@
},
"Customer_2": {
"path": "/opt/resource/customer_2",
"db": "genesis",
"step": "cad",
"rules": [
{
......@@ -337,7 +336,7 @@
{"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" : ["\\.rou$","^rout$"], "tl_name" : "rout" },
{"orig_name" : "fab.art", "tl_name" : "fab.art" },
{"orig_name" : ["multipack.art","^array$"], "tl_name" : "array" },
{"orig_name" : ["outline.art","^outline$"], "tl_name" : "outline" },
......@@ -348,7 +347,6 @@
},
"New_data": {
"path": "/opt/resource/new_data",
"db": "genesis",
"step": "cad",
"rules": [
{
......@@ -451,17 +449,18 @@
}
],
"tl_name": [
{"orig_name" : "pasttop.art", "tl_name" : "past_top" },
{"orig_name" : "pleg.art", "tl_name" : "silk_top" },
{"orig_name" : "soldtop.art", "tl_name" : "sm_top" },
{"orig_name" : ["pasttop.art","^past_top$","top_solderpaste"], "tl_name" : "past_top" },
{"orig_name" : ["pleg.art","^silk_top$","top_silkscreen"], "tl_name" : "silk_top" },
{"orig_name" : ["soldtop.art","^sm_top$","top_soldermask"], "tl_name" : "sm_top" },
{"orig_name" : ["top.art","^top$"], "tl_name" : "top" },
{"orig_name" : ["inner_(\\d+)\\.art","layer_(\\d+)"], "tl_name" : "l_($1)"},
{"orig_name" : ["bottom.art","^bottom$"], "tl_name" : "bottom" },
{"orig_name" : "soldbotm.art", "tl_name" : "sm_botm" },
{"orig_name" : "sleg.art", "tl_name" : "silk_bot" },
{"orig_name" : "pastbotm.art", "tl_name" : "past_botm" },
{"orig_name" : ["soldbotm.art","^sm_botm$","bot_soldermask"], "tl_name" : "sm_botm" },
{"orig_name" : ["sleg.art","^silk_bot$","bot_silkscreen"], "tl_name" : "silk_bot" },
{"orig_name" : ["pastbotm.art","^past_botm$","bot_solderpaste"], "tl_name" : "past_botm" },
{"orig_name" : "multipack.art", "tl_name" : "array" },
{"orig_name" : ["outline.art","outline"], "tl_name" : "outline" },
{"orig_name" : ["\\.rou$","^rout$"], "tl_name" : "rout" },
{"orig_name" : ["outline.art","^outline$"], "tl_name" : "outline" },
{"orig_name" : ["fab.art","fab"], "tl_name" : "fab" },
{"orig_name" : "top-enig", "tl_name" : "top-enig" },
{"orig_name" : "bot-enig", "tl_name" : "bot-enig" },
......@@ -483,8 +482,8 @@
{"tl_name":"d_(\\d+)-(\\d+)","new_name":"d($1)-($2)" ,"attr":{"context":"board","type":"drill"}},
{"tl_name":"drill","new_name":"drill" ,"attr":{"context":"board","type":"drill"}},
{"tl_name":"rout","new_name":"rout" ,"attr":{"context":"board","type":"rout"}},
{"tl_name":"outline","new_name":"outline" ,"attr":{"context":"board","type":"rout"}},
{"tl_name":"array","new_name":"array" ,"attr":{"context":"misc"}},
{"tl_name":"outline","new_name":"outline" ,"attr":{"context":"misc"}},
{"tl_name":"fab.art","new_name":"fab.art" ,"attr":{"context":"misc"}}
],
"delSameJob": "no"
......
/*
NAME:
DESCRIPTION: 客户数据分析
PARAMETER:
[
{
name : 'step_filter',
title : 'Step过滤',
type : 'LineEdit',
property : {tool_tip : '过滤step信息'}
},
{
name : 'erf',
title : 'erf名称',
type : 'LineEdit',
property : {tool_tip : ''}
},
{
name : 'auto_save',
title : '自动保存',
type : 'RadioBox',
property : {
item_list:[
{name:'yes',text:'YES'},
{name:'no',text:'NO'},
],
tool_tip:'是否自动保存料号开关'
}
}
]
VERSION_HISTORY:
V1.00 2020 3-30 Scott
HELP:
<html><body bgcolor="#DDECFE">
<font size="3" color="#003DB2"><p>功能简介</p></font>
<p> 客户数据分析</p>
<br>
<font size="3" color="#003DB2"><p>参数配置</p></font>
<p> 客户参数 </p>
<font size="3" color="#003DB2"><p>注意事项</p></font>
<p> ● 无 </p>
<br>
</body></html>
*/
// 引入模块 包
var $ = require('topcam.scriptfunc').argv();
var fs = require('fs');
var _ = require('lodash');
var IKM = $.ikm;
var GEN = $.gen;
var GUI = $.gui;
var Job = $.job;
var JobId = $.job_id;
var mode = "develop" // 运行模式 develop 开发模式 方便调试
try {
var job = "1"
var pcs_step = "cad", array_step = "stp";
var matrix = UPLOAD_LAYER_MATRIX({job:job}) // 分析matrix 获得分析后的matrix信息
var analysis_obj = analysis({job:job,jobId:JobId,pcs_step:pcs_step,array_step:array_step,matrix:matrix})
var config = {
jobInfo: {
layer_count: ["signal","power_ground"], // Board属性的signal或者power_ground层
vc_card_size_w: {api:"vc_card_size", props:"xsize"}, // card短边尺寸 // ? 保留小数
vc_card_size_l: {api:"vc_card_size", props:"ysize"}, // card长边尺寸 // ? 保留小数
vc_array_size_w: {api:"vc_array_size", props:"xsize"}, // ! array短边尺寸 需要arr_step // ? 保留小数
vc_array_size_l: {api:"vc_array_size", props:"ysize"}, // ! array长边尺寸 需要arr_step // ? 保留小数
vc_pcs_count_on_panel: true, // todo array中pcs的数量 ! 需要arr_step
stack_vias_number: true, // via孔连续叠加的层数
stack_vias_more: {only_value:true}, // yes|no : 14层板以上时,Stack Vias >=12时,存yes // ! 需要分析完via连续叠加层数
depth_drilling: {api:"layer_exist", props:"depth_drill"}, // yes|no :存在depth_drill 层时 ,存yes
depth_routing: {api:"layer_exist", props:"depth_routing"}, // tmp yes|no :存在depth_routing 层时,,存yes
laser_via_on_buried_hole: true, // todo via孔在埋孔上时,存yes
milling_bit_size: true, // todo 检查array中pcs的最小间距值
milling_length: true, // todo 检查array中铣切长度
vc_src_01005_pad_result: {api:"board_has_attr", props:".smd"}, // * yes|no:board 层中检查存在01005属性物件时,存yes 这里先拿.smd代替了
ATS_technology_25dc: {api:"layer_exist", props:"cavity"}, // yes|no:存在cavity层别时存yes
ATS_technology_25dr: {api:"layer_exist", props:"cavity"}, // yes|no:存在cavity层别时存yes
vc_src_EDGE_PLATING: true, // yes|no:检查线路外形是否存在物件,存在则存yes // !料号需要有rout层
edge_plating_length: true, // todo 检查线路外形处物件的长度
glod_finger: true, // todo yes|no:暂无逻辑
glod_finger_area: true, // todo 暂无逻辑
solder_mask_side: true, // top|bot|both:检查防焊层所在面次
silk_screen_side: true, // top|bot|both:检查文字层所在面次
min_drl_size: true, // todo 0.5mm 最小圆孔
max_pth_drl_size: true, // todo 3.5mm 最大pth圆孔
max_npth_drl_size: true, // todo 6.0mm 最大npth圆孔
min_slot_drl_size: true, // todo 0.8mm 最小槽孔
max_slot_drl_size: true, // todo 1.2mm 最大槽孔
max_slot_drl_length: true, // todo 2.0mm 最大槽孔
max_spec_slot_drl_size: true, // todo 2.1mm 最大异形槽孔
max_spec_slot_drl_length: true, // todo 3.0mm 最大异形槽孔
}
}
// 分析料号info
var jobInfo = {}
Object.keys(config.jobInfo).forEach(function(key){
var props = config.jobInfo[key];
if(props){
try {
if(props.hasOwnProperty("api") && props.hasOwnProperty("props")){
jobInfo[key] = analysis_obj["analysis_"+props.api](props.props)
} else if(props.only_value){
jobInfo[key] = analysis_obj[key]
} else {
jobInfo[key] = analysis_obj["analysis_"+key](props)
}
} catch (e) {
console.log(e);
jobInfo[key] = "_error"
}
}
})
// 过滤掉料号信息的 _todo 和 _error
for (var key in jobInfo) {
if(jobInfo[key] === "_todo" || jobInfo[key] === "_error"){
delete jobInfo[key]
}
}
// 上传jobInfo IKM版本
IKM.save_job_info({
jobid: JobId,
jobinfohash:jobInfo
})
// todo 上传jobInfo topjs3版本
// save_job_info({
// jobid: JobId,
// jobinfohash: jobInfo
// })
// todo 设置钻孔层孔属性,镭射孔via,无铜孔npth,其余孔pth
// todo 上传钻孔信息
// 获取pcs_step 和 array_step的钻孔信息
var drill_info = {};
var drillLayers = analysis_obj.matrixInfo.mDrills;
[pcs_step, array_step].forEach(function(step){
drill_info[step] = drill_info[step] || {};
drillLayers.forEach(function(layer){
var layer_tool_manager = GEN.getTool({job:job, step:step,layer:layer.name})
drill_info[step][layer.name] = layer_tool_manager
})
})
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){
var tool = pcs_tool_manager[layer][key];
var array_count;
if(array_tool_manager && array_tool_manager[layer] && array_tool_manager[layer][key]){array_count = array_tool_manager[layer][key].count}
var data = {
job_id: JobId,
layer_name: layer,
tool_num: key,
tool_flag: key,
tool_type: tool.shape,
drill_type:tool.type,
drill_size : tool.drill_size,
drill_slot_length: tool.slot_len,
finish_size : tool.finish_size,
finish_slot_length: tool.slot_len,
size_tol_lower: tool.min_tol,
size_tol_upper: tool.max_tol,
pcs_count: tool.count,
array_count: array_count, // todo
attr_data: {} // {"allowance": 2, "org_layer_name": "hhhh"}
}
if(!array_count){delete data.array_count}
var id = IKM.crud("selectValue",{
table:'pdm_job_cam_drill',
field:"id",
where:{job_id:JobId, layer_name: layer,tool_num: key}
})
if(/done/ig.test(id)){
IKM.crud("insertRow",{
table:'pdm_job_cam_drill',
data:data,
return_field:'id',
})
}else{
IKM.crud("updateRow",{
table:'pdm_job_cam_drill',
where: {id:id},
data:data,
update_policy:{tags:'array_append', attr_data:'json_merge'}
})
}
})
})
GUI.msg("Done")
return 'Done';
}
catch (error) {
GUI.msg(error);
return 'Error';
}
function UPLOAD_LAYER_MATRIX(props){
var job = props.job
props.jobcategory = props.jobcategory || "work"
var matrix = ANALYSIS_STACKUP({job:job, jobcategory:props.jobcategory});
var func = 'function(ARGV)\
{\
var jobId = ARGV["job_id"];\
var tableName = "pdm_job_" + ARGV["jobcategory"] + "_layer";\
//GUI.msgbox({text: TDataParse.variant2JsonStr(tableName)});\
var db = new TSqlQueryV2(T_SQLCNT_POOL.getSqlDatabase());\
db.begin();\
try{\
var oLayers = db.selectMapMap({table:tableName, field:["odb_name","release_status"], where:{job_id:jobId}, uniquefield:"odb_name"});\
if (db.lastError().isValid()) throw db.lastError();\
//GUI.msgbox({text: TDataParse.variant2JsonStr(oLayers)});\
\
db.deleteRow({table:tableName, where:{job_id:jobId}});\
if (db.lastError().isValid()) throw db.lastError();\
\
var fieldLst = ["name", "odb_context", "odb_type", "odb_polarity", "odb_side", "drl_start", "drl_end",\
"row_num", "type", "drl_start_num", "drl_end_num", "drl_from_num", "drl_to_num", "drl_connect_to", \
"odb_name", "side", "stackup_num", "customer_field", "input_file_name", "odb_row_num"];\
\
for (var i=0;i<ARGV["layers"].length;i++)\
{\
layerName = ARGV["layers"][i];\
var layerInfo = ARGV["matrix"][layerName];\
var tmpData = {"job_id":jobId, "name": layerInfo["name"]};\
if (ARGV["releasestatus"] != undefined && ARGV["releasestatus"] != null && ARGV["releasestatus"].length>0\
&& ARGV["releasestatus"][layerInfo["odb_name"]] != undefined && ARGV["releasestatus"][layerInfo["odb_name"]] != null )\
{\
tmpData["release_status"] = ARGV["releasestatus"];\
}\
else\
{\
tmpData["release_status"] = oLayers.hasOwnProperty(layerInfo["odb_name"]) ? oLayers[layerInfo["odb_name"]]["release_status"] : null;\
}\
for (n = 0; n < fieldLst.length; n++)\
{\
tmpData[fieldLst[n]] = layerInfo[fieldLst[n]];\
}\
//GUI.msgbox({text: TDataParse.variant2JsonStr(tmpData)});\
db.insertRow({table:tableName, data:tmpData});\
if (db.lastError().isValid()) throw db.lastError();\
}\
db.commit();\
return new TDataResponse();\
}\
catch (err)\
{\
print(err.text());\
db.rollback();\
return new TDataResponse(err, "");\
}\
}';
// var ret = IKM.command( func, // ?? =========================> tmp
// { job_id :JobId,
// matrix:matrix,
// layers: Object.keys(matrix).sort(function(a,b){return matrix[a]["row"] - matrix[b]["row"]}),
// jobcategory:props.jobcategory}, 1);
// if (ret.errText) {
// return {
// jobcategory:props.jobcategory,
// errText :ret.errText,
// errCode :ret.errCode,
// };
// }
return matrix
}
function ANALYSIS_STACKUP(props){
var job = props.job
if(!props.hasOwnProperty("jobcategory")){ props.jobcategory = 'work' }
var matrix = GEN.getMatrix({job:job})
var layer_count = IKM.get_jobinfo({jobname:JobId,jobcategory:props.jobcategory,jobinfo:'layer_count'});
if(!layer_count){
layer_count = GEN.getLayerCount({job:job})
}
IKM.save_job_info({jobid:JobId,jobcategory:props.jobcategory,jobinfohash:{TL_layer_count:layer_count}});
_.values(matrix).sort(function(a,b){return a.row-b.row}).forEach(function(layer){
layer.odb_name = layer.name;
layer.name = layer.tl_name;
layer.odb_context = layer.context;
layer.odb_type = layer.layer_type;
layer.odb_polarity = layer.polarity;
layer.odb_side = layer.side;
layer.row_num = layer.tl_num;
layer.type = layer.tl_type;
layer.side = layer.enum_tl_side;
layer.input_file_name = layer.file_name;
layer.odb_row_num = layer.row;
if (layer.odb_name == 'drill'){
layer.name = 'drill';
layer.drl_start_num = 1;
layer.drl_end_num = layer_count;
layer.drl_from_num = 1;
layer.drl_to_num = layer_count;
layer.type = 'main_drill';
}
else if (/^d_(\d+)\-(\d+)$/.test(layer.odb_name)){
var tmp = /^d(\d+)\-(\d+)$/.exec(layer.odb_name)
var drl_star = tmp[1];
var drl_end = tmp[2];
layer.name = 'drill' + drl_star + '-' + drl_end;
layer.drl_start_num = drl_star;
layer.drl_end_num = drl_end;
layer.drl_from_num = drl_star;
layer.drl_to_num = drl_end;
if( drl_star == 1 || drl_end == layer_count ){
layer.type = 'blind_drill'; // 埋孔
}
else{
layer.type = 'bury_drill'; // 盲孔
}
}
else if (/^d(\d+)\-(\d+)$/.test(layer.odb_name)){
var tmp = /^d(\d+)\-(\d+)$/.exec(layer.odb_name)
var drl_star = tmp[1];
var drl_end = tmp[2];
layer.name = 'd'+drl_star+'-'+drl_end;
layer.drl_start_num = drl_star;
layer.drl_end_num = drl_end;
layer.drl_from_num = drl_star;
layer.drl_to_num = drl_end;
layer.type = 'laser_drill'; // 镭射孔
}
else if (/\-a$/.test(layer.odb_name)){
layer.side = 'top';
if(!layer.name){
layer.name = '__'+layer.odb_name+'__'
}
if(!layer.type){
layer.type = 'other'
}
}
else if (/\-b$/.test(layer.odb_name)){
layer.side = 'bottom';
if(!layer.name){
layer.name = '__'+layer.odb_name+'__'
}
if(!layer.type){
layer.type = 'other'
}
}
else{
if(!layer.name){
layer.name = '__'+layer.odb_name+'__'
}
if(!layer.type){
layer.type = 'other'
}
}
})
return matrix;
}
function getMatrixInfo(props){ // 获取matrix各种信息
var job = props.job
var matrix = GEN.getMatrix({job:job})
var res = {
matrix: matrix, // matrix
matrixVal: [], // matrix 的 value数组
mSignal: {}, // board的signal层 {}
mSignals: [], // board的signal层 []
mDrill: {}, // board的drill层
mDrills: [], // board的drill层
mSolderMask: {}, // 防焊层
mSolderMasks: [], // 防焊层
mOuters: [], // 外层和对于的防旱
mBoardLayer: [] // board层
}
for (var key in matrix) {
var value = matrix[key]
res.matrixVal.push(value)
if(value.context == "board"){
res.mBoardLayer.push(key)
switch (value.layer_type) {
case "signal":
res.mSignal[key] = value
res.mSignals.push(value)
break;
case "drill":
res.mDrill[key] = value
res.mDrills.push(value)
break;
case "solder_mask":
res.mSolderMask[key] = value
res.mSolderMasks.push(value)
break;
}
}
}
res.matrixVal = res.matrixVal.sort(function(a,b){return Number(a.row) - Number(b.row)})
res.mSignals = res.mSignals.sort(function(a,b){return Number(a.row) - Number(b.row)})
res.mDrills = res.mDrills.sort(function(a,b){return Number(a.row) - Number(b.row)})
// 找出外层 以及外层对应的防焊层 [{signalL:"top", solderL:"smt"}]
res.mOuters = res.mSignals.reduce(function(a,b){
if(b.tl_type == "outer"){
var solderLayers = res.mSolderMasks.filter(function(v){
return v.side == b.side
})
a.push({
signalL: b.name,
solderL: solderLayers.length >0 ? solderLayers[0]["name"] : null
})
}
return a
},[])
return res
}
function selCopyLayer(props){ // 拷贝选择的到辅助层
var layer = props.layer
var job = props.job
if(GEN.isLayerExists({job:job,layer:layer})){
GEN.deleteLayer({job:job,layer:layer})
}
GEN.selCopyOther({dest:'layer_name',target_layer:layer})
}
function save_job_info(props){ // todo 保存料号信息
}
function analysis(props){
var job = props.job || Job;
var jobId = props.jobId || JobId;
var pcs_step = props.pcs_step || false;
var array_step = props.array_step || false;
var matrix = props.matrix;
function T_m_p(props){
this.job = props.job;
this.jobInfo = {};
this.jobId = props.jobId;
if(props.pcs_step){ this.pcs_step = props.pcs_step; }
if(props.matrix){ this.matrix = props.matrix; }
if(props.array_step){ this.array_step = props.array_step; }
this.matrixInfo = getMatrixInfo({job:this.job})
this.init();
}
T_m_p.prototype.init = function(){
var init_checking = ["job", "jobId", "pcs_step", "matrix"];
var t = this;
init_checking.forEach(function(v){ if(!t[v]){t.e(v+" is undefined")} })
}
T_m_p.prototype.e = function(e){ // 处理error
console.log(e)
throw e
}
T_m_p.prototype.analysis_layer_count = function(props){ // 分析board属性的层数量 []string
var matrix = this.matrixInfo.matrixVal;
var res = matrix.filter(function(v){return v.context == "board" && props.indexOf(v.layer_type) >= 0 })
return res.length
}
T_m_p.prototype.analysis_vc_card_size = function(props){ // card短边尺寸 string
return GEN.getProfileLimits({job:this.job,step:this.pcs_step})[props].toFixed(3)
}
T_m_p.prototype.analysis_vc_array_size = function(props){ // array长边尺寸 string
if(!this.array_step){return "error"}
return GEN.getProfileLimits({job:this.job,step:this.array_step})[props].toFixed(3)
}
T_m_p.prototype.analysis_vc_pcs_count_on_panel = function(props){ //
return "_todo"
}
T_m_p.prototype.analysis_stack_vias_number = function(props){ // via孔连续叠加的层数
var t = this;
var res;
// 找出 镭射孔
var laser_layers = []
for (var key in t.matrix) {
var val = t.matrix[key]
if(val.type == "laser_drill"){
laser_layers.push(val)
}
}
if(laser_layers.length == 0){return "error"}
GEN.openStep({job:t.job,name:t.pcs_step})
laser_layers = laser_layers.sort(function(a,b){return Number(a.row)-Number(b.row)})
var laser_info = {}
for(var i = 0; i < laser_layers.length-1; i++){
var start_layer = laser_layers[i].name
var cover_layer = laser_layers[i+1].name
GEN.workLayer({name:start_layer,display_number:2,clear_before:'yes'})
GEN.selClearFeature()
GEN.selRefFeat({layers:cover_layer,use:'filter',mode:'cover'})
var count = GEN.getSelectCount()
if(count>0){
if(!laser_info[start_layer]){
laser_info[start_layer] = {}
}
laser_info[start_layer].drill_connect_layer = cover_layer
laser_info[start_layer].drill_connect_point = count
}
}
// via孔连续叠加的层数
var via_vias_info = []
function analysis_via_number(layers){
if(layers.length < 2){return}
var startlayer = layers[0].name + "_cover"
GEN.selClearFeature()
GEN.workLayer({name:layers[0].name,display_number:2,clear_before:'yes'})
GEN.selAllFeat()
selCopyLayer({job:t.job,layer:startlayer})
var end_index = start_cover_next(startlayer,layers,0)
via_vias_info.push(end_index+1)
analysis_via_number(layers.slice(end_index))
}
function start_cover_next(start, layers, end_index){
if(layers.length < 2){
GEN.deleteLayer({job:t.job,layer:start})
return end_index
}
layers = layers.slice(1)
GEN.workLayer({name:start,display_number:2,clear_before:'yes'})
GEN.selClearFeature()
GEN.selRefFeat({layers:layers[0].name,use:'filter',mode:'cover'})
var count = GEN.getSelectCount()
if (count < 1) {
GEN.deleteLayer({job:t.job,layer:start})
return ++end_index
}
var nextstartlayer = layers[0].name + "_cover"
selCopyLayer({job:t.job,layer:nextstartlayer})
GEN.deleteLayer({job:t.job,layer:start})
return start_cover_next(nextstartlayer,layers,++end_index)
}
analysis_via_number(laser_layers.slice())
if (via_vias_info.length == 1){
res = via_vias_info[0]
}else{
res = via_vias_info.reduce(function(a,b){return a-b>0?a :b})
}
t.jobInfo.stack_vias_more = "no"
if(GEN.getLayerCount({job:t.job}) > 14 && res >= 12){
t.jobInfo.stack_vias_more = "yes"
}
t.jobInfo.laser_info = laser_info;
return res
}
T_m_p.prototype.analysis_layer_exist = function(props){ // 存在某某层? string
return this.matrixInfo.matrix.hasOwnProperty(props) ? "yes" : "no"
}
T_m_p.prototype.analysis_laser_via_on_buried_hole = function(){ // todo
return "_todo"
}
T_m_p.prototype.analysis_milling_bit_size = function(){ // todo
return "_todo"
}
T_m_p.prototype.analysis_milling_length = function(){ // todo
return "_todo"
}
T_m_p.prototype.analysis_board_has_attr = function(props){ // board层中检查存在01005属性物件时
GEN.openStep({job:this.job,name:this.pcs_step})
GEN.clearLayers()
GEN.affectedLayer({affected:'yes',layer:this.matrixInfo.mBoardLayer,clear_before:'yes'});
GEN.selClearFeature()
GEN.selectByFilter({attribute:props})
var res = GEN.getSelectCount() > 0? "yes" : "no"
GEN.affectedLayer({affected:'no',mode:'all'});
GEN.selClearFeature()
GEN.closeStep()
return res
}
T_m_p.prototype.analysis_vc_src_EDGE_PLATING = function(props){ // ? 检查线路外形是否存在物件,存在则存yes
var res = "no"
var rout = this.matrixInfo.matrixVal.filter(function(v){return v.layer_type == "rout"}) // 找rout层
if(rout.length == 0){
return "error:cant find rout layer"
}
GEN.openStep({job:this.job, name:this.pcs_step})
GEN.affectedLayer({affected:'no',mode:'all'})
try {
this.matrixInfo.mSignals.forEach(function(v){ // 用线路层逐层与rout层touch 找得到说明存在
GEN.workLayer({name:v.name,display_number:2,clear_before:'yes'})
GEN.selClearFeature()
GEN.selRefFeat({layers:rout[0].name,mode:"touch",use:"filter"})
if( GEN.getSelectCount()>0){
throw "yes"
}
GEN.clearLayers()
})
} catch (msg) {
res = msg
GEN.affectedLayer({affected:'no',mode:'all'})
GEN.selClearFeature()
}
GEN.closeStep()
return res
}
T_m_p.prototype.analysis_edge_plating_length = function(){ // todo
return "_todo"
}
T_m_p.prototype.analysis_glod_finger = function(){ // todo
return "_todo"
}
T_m_p.prototype.analysis_glod_finger_area = function(){ // todo
return "_todo"
}
T_m_p.prototype.analysis_solder_mask_side = function(){ // 检查防焊层所在面次
var solder_paste_layers = this.matrixInfo.matrixVal.filter(function(v){return v.layer_type == "solder_paste"})
var solder_paste_info= solder_paste_layers.map(function(v){return v.side}).reduce(function(a,b){
if(a.indexOf(b)<0){ a.push(b) }
return a
},[])
var res = "no"
if(solder_paste_info.length == 0){
res = "no"
} else if (solder_paste_info.length == 1) {
res = /top/ig.test(solder_paste_info[0]) ? "top" : "bot"
} else {
res = "both"
}
return res
}
T_m_p.prototype.analysis_silk_screen_side = function(){ // 检查文字层所在面次
var solder_mask_layers = this.matrixInfo.matrixVal.filter(function(v){return v.layer_type == "solder_mask"})
var solder_mask_info= solder_mask_layers.map(function(v){return v.side}).reduce(function(a,b){
if(a.indexOf(b)<0){ a.push(b) }
return a
},[])
var res = "no"
if(solder_mask_info.length == 0){
res = "no"
} else if (solder_mask_info.length == 1) {
res = /top/ig.test(solder_mask_info[0]) ? "top" : "bot"
} else {
res = "both"
}
return res
}
T_m_p.prototype.analysis_min_drl_size = function(){ // todo
return "_todo"
}
T_m_p.prototype.analysis_max_pth_drl_size = function(){ // todo
return "_todo"
}
T_m_p.prototype.analysis_max_npth_drl_size = function(){ // todo
return "_todo"
}
T_m_p.prototype.analysis_min_slot_drl_size = function(){ // todo
return "_todo"
}
T_m_p.prototype.analysis_max_slot_drl_size = function(){ // todo
return "_todo"
}
T_m_p.prototype.analysis_max_slot_drl_length = function(){ // todo
return "_todo"
}
T_m_p.prototype.analysis_max_spec_slot_drl_size = function(){ // todo
return "_todo"
}
T_m_p.prototype.analysis_max_spec_slot_drl_length = function(){ // todo
return "_todo"
}
return new T_m_p({job:job, jobId:jobId, pcs_step:pcs_step, array_step:array_step,matrix:matrix})
}
function tmp(){
return {
"sst": {
"row": "1","type": "solder_paste","name": "sp_fr","context": "board","layer_type": "solder_paste","polarity": "positive","drl_start": "","drl_end": "","gdrl_start": "","gdrl_end": "",
"tl_num": -1000,"tl_name": "sp_fr","tl_type": "solder_paste","odb_name": "sst","odb_context": "board","odb_type": "solder_paste","odb_polarity": "positive","odb_side": "top",
"row_num": -1000,"odb_row_num": "1"
},
"spt": {
"row": "2","type": "solder_paste","name": "sp_fr(2)","context": "board","layer_type": "solder_paste","polarity": "positive","drl_start": "","drl_end": "","gdrl_start": "","gdrl_end": "",
"tl_num": -999,"tl_name": "sp_fr(2)","tl_type": "solder_paste","odb_name": "spt","odb_context": "board","odb_type": "solder_paste","odb_polarity": "positive","odb_side": "top",
"row_num": -999,"odb_row_num": "2"
},
"smt": {
"row": "3","type": "solder_mask","name": "sm_fr","context": "board","layer_type": "solder_mask","polarity": "positive","drl_start": "","drl_end": "","gdrl_start": "","gdrl_end": "",
"tl_num": -998,"tl_name": "sm_fr","tl_type": "solder_mask","odb_name": "smt","odb_context": "board","odb_type": "solder_mask","odb_polarity": "positive","odb_side": "top",
"row_num": -998,"odb_row_num": "3"
},
"top": {
"row": "4","type": "outer","name": "top","context": "board","layer_type": "signal","polarity": "positive","drl_start": "","drl_end": "","gdrl_start": "","gdrl_end": "",
"tl_num": 1,"tl_name": "top","tl_type": "outer","odb_name": "top","odb_context": "board","odb_type": "signal","odb_polarity": "positive","odb_side": "top",
"row_num": 1,"odb_row_num": "4"
},
"isl2": {
"row": "5","type": "inner","name": "l2","context": "board","layer_type": "signal","polarity": "positive","drl_start": "","drl_end": "","gdrl_start": "","gdrl_end": "",
"tl_num": 2,"tl_name": "l2","tl_type": "inner","odb_name": "isl2","odb_context": "board","odb_type": "signal","odb_polarity": "positive","odb_side": "inner",
"row_num": 2,"odb_row_num": "5"
},
"isl3": {
"row": "6","type": "inner","name": "l3","context": "board","layer_type": "signal","polarity": "positive","drl_start": "","drl_end": "","gdrl_start": "","gdrl_end": "",
"tl_num": 3,"tl_name": "l3","tl_type": "inner","odb_name": "isl3","odb_context": "board","odb_type": "signal","odb_polarity": "positive","odb_side": "inner",
"row_num": 3,"odb_row_num": "6"
},
"isl4": {
"row": "7","type": "inner","name": "l4","context": "board","layer_type": "signal","polarity": "positive","drl_start": "","drl_end": "","gdrl_start": "","gdrl_end": "",
"tl_num": 4,"tl_name": "l4","tl_type": "inner","odb_name": "isl4","odb_context": "board","odb_type": "signal","odb_polarity": "positive","odb_side": "inner",
"row_num": 4,"odb_row_num": "7"
},
"isl5": {
"row": "8","type": "inner","name": "l5","context": "board","layer_type": "signal","polarity": "positive","drl_start": "","drl_end": "","gdrl_start": "","gdrl_end": "",
"tl_num": 5,"tl_name": "l5","tl_type": "inner","odb_name": "isl5","odb_context": "board","odb_type": "signal","odb_polarity": "positive","odb_side": "inner",
"row_num": 5,"odb_row_num": "8"
},
"isl6": {
"row": "9","type": "inner","name": "l6","context": "board","layer_type": "signal","polarity": "positive","drl_start": "","drl_end": "","gdrl_start": "","gdrl_end": "",
"tl_num": 6,"tl_name": "l6","tl_type": "inner","odb_name": "isl6","odb_context": "board","odb_type": "signal","odb_polarity": "positive","odb_side": "inner",
"row_num": 6,"odb_row_num": "9"
},
"isl7": {
"row": "10","type": "inner","name": "l7","context": "board","layer_type": "signal","polarity": "positive","drl_start": "","drl_end": "","gdrl_start": "","gdrl_end": "",
"tl_num": 7,"tl_name": "l7","tl_type": "inner","odb_name": "isl7","odb_context": "board","odb_type": "signal","odb_polarity": "positive","odb_side": "inner",
"row_num": 7,"odb_row_num": "10"
},
"isl8": {
"row": "11","type": "inner","name": "l8","context": "board","layer_type": "signal","polarity": "positive","drl_start": "","drl_end": "","gdrl_start": "","gdrl_end": "",
"tl_num": 8,"tl_name": "l8","tl_type": "inner","odb_name": "isl8","odb_context": "board","odb_type": "signal","odb_polarity": "positive","odb_side": "inner",
"row_num": 8,"odb_row_num": "11"
},
"isl9": {
"row": "12","type": "inner","name": "l9","context": "board","layer_type": "signal","polarity": "positive","drl_start": "","drl_end": "","gdrl_start": "","gdrl_end": "",
"tl_num": 9,"tl_name": "l9","tl_type": "inner","odb_name": "isl9","odb_context": "board","odb_type": "signal","odb_polarity": "positive","odb_side": "inner",
"row_num": 9,"odb_row_num": "12"
},
"bottom": {
"row": "13","type": "outer","name": "bottom","context": "board","layer_type": "signal","polarity": "positive","drl_start": "","drl_end": "","gdrl_start": "","gdrl_end": "",
"tl_num": 10,"tl_name": "bottom","tl_type": "outer","odb_name": "bottom","odb_context": "board","odb_type": "signal","odb_polarity": "positive","odb_side": "bottom",
"row_num": 10,"odb_row_num": "13"
},
"smb": {
"row": "14","type": "solder_mask","name": "sm_ba","context": "board","layer_type": "solder_mask","polarity": "positive","drl_start": "","drl_end": "","gdrl_start": "","gdrl_end": "",
"tl_num": 1013,"tl_name": "sm_ba","tl_type": "solder_mask","odb_name": "smb","odb_context": "board","odb_type": "solder_mask","odb_polarity": "positive","odb_side": "bottom",
"row_num": 1013,"odb_row_num": "14"
},
"spb": {
"row": "15","type": "solder_paste","name": "sp_ba","context": "board","layer_type": "solder_paste","polarity": "positive","drl_start": "","drl_end": "","gdrl_start": "","gdrl_end": "",
"tl_num": 1014,"tl_name": "sp_ba","tl_type": "solder_paste","odb_name": "spb","odb_context": "board","odb_type": "solder_paste","odb_polarity": "positive","odb_side": "bottom",
"row_num": 1014,"odb_row_num": "15"
},
"ssb": {
"row": "16","type": "solder_paste","name": "sp_ba(2)","context": "board","layer_type": "solder_paste","polarity": "positive","drl_start": "","drl_end": "","gdrl_start": "","gdrl_end": "",
"tl_num": 1015,"tl_name": "sp_ba(2)","tl_type": "solder_paste","odb_name": "ssb","odb_context": "board","odb_type": "solder_paste","odb_polarity": "positive","odb_side": "bottom",
"row_num": 1015,"odb_row_num": "16"
},
"d1-2": {
"row": "17","type": "laser_drill","name": "d1-2","context": "board","layer_type": "drill","polarity": "positive","drl_start": "top",
"drl_end": "isl2","gdrl_start": "top","gdrl_end": "isl2","drl_start_num": "1","drl_end_num": "2","tl_name": "drill1-2","tl_type": "drill",
"tl_num": 10016,"odb_name": "d1-2","odb_context": "board","odb_type": "drill","odb_polarity": "positive","odb_side": "none",
"row_num": 10016,"odb_row_num": "17","drl_from_num": "1","drl_to_num": "2"
},
"d2-3": {
"row": "18","type": "laser_drill","name": "d2-3","context": "board","layer_type": "drill","polarity": "positive","drl_start": "isl2","drl_end": "isl3","gdrl_start": "isl2","gdrl_end": "isl3","drl_start_num": "2","drl_end_num": "3","tl_name": "drill2-3","tl_type": "drill",
"tl_num": 10017,"odb_name": "d2-3","odb_context": "board","odb_type": "drill","odb_polarity": "positive","odb_side": "none",
"row_num": 10017,"odb_row_num": "18","drl_from_num": "2","drl_to_num": "3"
},
"d3-4": {
"row": "19","type": "laser_drill","name": "d3-4","context": "board","layer_type": "drill","polarity": "positive","drl_start": "isl3","drl_end": "isl4","gdrl_start": "isl3","gdrl_end": "isl4","drl_start_num": "3","drl_end_num": "4","tl_name": "drill3-4","tl_type": "drill",
"tl_num": 10018,"odb_name": "d3-4","odb_context": "board","odb_type": "drill","odb_polarity": "positive","odb_side": "none",
"row_num": 10018,"odb_row_num": "19","drl_from_num": "3","drl_to_num": "4"
},
"d4-5": {
"row": "20","type": "laser_drill","name": "d4-5","context": "board","layer_type": "drill","polarity": "positive","drl_start": "isl4","drl_end": "isl5","gdrl_start": "isl4","gdrl_end": "isl5","drl_start_num": "4","drl_end_num": "5","tl_name": "drill4-5","tl_type": "drill",
"tl_num": 10019,"odb_name": "d4-5","odb_context": "board","odb_type": "drill","odb_polarity": "positive","odb_side": "none",
"row_num": 10019,"odb_row_num": "20","drl_from_num": "4","drl_to_num": "5"
},
"d5-6": {
"row": "21","type": "laser_drill","name": "d5-6","context": "board","layer_type": "drill","polarity": "positive","drl_start": "isl5","drl_end": "isl6","gdrl_start": "isl5","gdrl_end": "isl6","drl_start_num": "5","drl_end_num": "6","tl_name": "drill5-6","tl_type": "drill",
"tl_num": 10020,"odb_name": "d5-6","odb_context": "board","odb_type": "drill","odb_polarity": "positive","odb_side": "none",
"row_num": 10020,"odb_row_num": "21","drl_from_num": "5","drl_to_num": "6"
},
"d6-7": {
"row": "22","type": "laser_drill","name": "d6-7","context": "board","layer_type": "drill","polarity": "positive","drl_start": "isl6","drl_end": "isl7","gdrl_start": "isl6","gdrl_end": "isl7","drl_start_num": "6","drl_end_num": "7","tl_name": "drill6-7","tl_type": "drill",
"tl_num": 10021,"odb_name": "d6-7","odb_context": "board","odb_type": "drill","odb_polarity": "positive","odb_side": "none",
"row_num": 10021,"odb_row_num": "22","drl_from_num": "6","drl_to_num": "7"
},
"d7-8": {
"row": "23","type": "laser_drill","name": "d7-8","context": "board","layer_type": "drill","polarity": "positive","drl_start": "isl7","drl_end": "isl8","gdrl_start": "isl7","gdrl_end": "isl8","drl_start_num": "7","drl_end_num": "8","tl_name": "drill7-8","tl_type": "drill",
"tl_num": 10022,"odb_name": "d7-8","odb_context": "board","odb_type": "drill","odb_polarity": "positive","odb_side": "none",
"row_num": 10022,"odb_row_num": "23","drl_from_num": "7","drl_to_num": "8"
},
"d8-9": {
"row": "24","type": "laser_drill","name": "d8-9","context": "board","layer_type": "drill","polarity": "positive","drl_start": "isl8","drl_end": "isl9","gdrl_start": "isl8","gdrl_end": "isl9","drl_start_num": "8","drl_end_num": "9","tl_name": "drill8-9","tl_type": "drill",
"tl_num": 10023,"odb_name": "d8-9","odb_context": "board","odb_type": "drill","odb_polarity": "positive","odb_side": "none",
"row_num": 10023,"odb_row_num": "24","drl_from_num": "8","drl_to_num": "9"
},
"d9-10": {
"row": "25","type": "laser_drill","name": "d9-10","context": "board","layer_type": "drill","polarity": "positive","drl_start": "isl9","drl_end": "bottom","gdrl_start": "isl9","gdrl_end": "bottom","drl_start_num": "9","drl_end_num": "10","tl_name": "drill9-10","tl_type": "drill",
"tl_num": 10024,"odb_name": "d9-10","odb_context": "board","odb_type": "drill","odb_polarity": "positive","odb_side": "none",
"row_num": 10024,"odb_row_num": "25","drl_from_num": "9","drl_to_num": "10"
},
"drill": {
"row": "26","type": "main_drill","name": "drill","context": "board","layer_type": "drill","polarity": "positive","drl_start": "top","drl_end": "bottom","gdrl_start": "top","gdrl_end": "bottom","drl_start_num": 1,"drl_end_num": 10,"tl_name": "drill","tl_type": "drill",
"tl_num": 10025,"odb_name": "drill","odb_context": "board","odb_type": "drill","odb_polarity": "positive","odb_side": "none",
"row_num": 10025,"odb_row_num": "26","drl_from_num": 1,"drl_to_num": 10
},
"rout": {
"row": "27","type": "other","name": "__rout__","context": "board","layer_type": "rout","polarity": "positive","drl_start": "top","drl_end": "bottom","gdrl_start": "top","gdrl_end": "bottom","odb_name": "rout","odb_context": "board","odb_type": "rout","odb_polarity": "positive","odb_side": "none","odb_row_num": "27"
},
"nclegend-1-2": {
"row": "28","type": "other","name": "__nclegend-1-2__","context": "misc","layer_type": "document","polarity": "positive","drl_start": "","drl_end": "","gdrl_start": "","gdrl_end": "",
"tl_num": 110027,"odb_name": "nclegend-1-2","odb_context": "misc","odb_type": "document","odb_polarity": "positive","odb_side": "none",
"row_num": 110027,"odb_row_num": "28"
},
"nclegend-2-3": {
"row": "29","type": "other","name": "__nclegend-2-3__","context": "misc","layer_type": "document","polarity": "positive","drl_start": "","drl_end": "","gdrl_start": "","gdrl_end": "",
"tl_num": 110028,"odb_name": "nclegend-2-3","odb_context": "misc","odb_type": "document","odb_polarity": "positive","odb_side": "none",
"row_num": 110028,"odb_row_num": "29"
},
"nclegend-3-4": {
"row": "30","type": "other","name": "__nclegend-3-4__","context": "misc","layer_type": "document","polarity": "positive","drl_start": "","drl_end": "","gdrl_start": "","gdrl_end": "",
"tl_num": 110029,"odb_name": "nclegend-3-4","odb_context": "misc","odb_type": "document","odb_polarity": "positive","odb_side": "none",
"row_num": 110029,"odb_row_num": "30"
},
"nclegend-4-5": {
"row": "31","type": "other","name": "__nclegend-4-5__","context": "misc","layer_type": "document","polarity": "positive","drl_start": "","drl_end": "","gdrl_start": "","gdrl_end": "",
"tl_num": 110030,"odb_name": "nclegend-4-5","odb_context": "misc","odb_type": "document","odb_polarity": "positive","odb_side": "none",
"row_num": 110030,"odb_row_num": "31"
},
"nclegend-5-6": {
"row": "32","type": "other","name": "__nclegend-5-6__","context": "misc","layer_type": "document","polarity": "positive","drl_start": "","drl_end": "","gdrl_start": "","gdrl_end": "",
"tl_num": 110031,"odb_name": "nclegend-5-6","odb_context": "misc","odb_type": "document","odb_polarity": "positive","odb_side": "none",
"row_num": 110031,"odb_row_num": "32"
},
"nclegend-6-7": {
"row": "33","type": "other","name": "__nclegend-6-7__","context": "misc","layer_type": "document","polarity": "positive","drl_start": "","drl_end": "","gdrl_start": "","gdrl_end": "",
"tl_num": 110032,"odb_name": "nclegend-6-7","odb_context": "misc","odb_type": "document","odb_polarity": "positive","odb_side": "none",
"row_num": 110032,"odb_row_num": "33"
},
"nclegend-7-8": {
"row": "34","type": "other","name": "__nclegend-7-8__","context": "misc","layer_type": "document","polarity": "positive","drl_start": "","drl_end": "","gdrl_start": "","gdrl_end": "",
"tl_num": 110033,"odb_name": "nclegend-7-8","odb_context": "misc","odb_type": "document","odb_polarity": "positive","odb_side": "none",
"row_num": 110033,"odb_row_num": "34"
},
"nclegend-8-9": {
"row": "35","type": "other","name": "__nclegend-8-9__","context": "misc","layer_type": "document","polarity": "positive","drl_start": "","drl_end": "","gdrl_start": "","gdrl_end": "",
"tl_num": 110034,"odb_name": "nclegend-8-9","odb_context": "misc","odb_type": "document","odb_polarity": "positive","odb_side": "none",
"row_num": 110034,"odb_row_num": "35"
},
"nclegend-9-10": {
"row": "36","type": "other","name": "__nclegend-9-10__","context": "misc","layer_type": "document","polarity": "positive","drl_start": "","drl_end": "","gdrl_start": "","gdrl_end": "",
"tl_num": 110035,"odb_name": "nclegend-9-10","odb_context": "misc","odb_type": "document","odb_polarity": "positive","odb_side": "none",
"row_num": 110035,"odb_row_num": "36"
},
"nclegend-1-10": {
"row": "37","type": "other","name": "__nclegend-1-10__","context": "misc","layer_type": "document","polarity": "positive","drl_start": "","drl_end": "","gdrl_start": "","gdrl_end": "",
"tl_num": 110036,"odb_name": "nclegend-1-10","odb_context": "misc","odb_type": "document","odb_polarity": "positive","odb_side": "none",
"row_num": 110036,"odb_row_num": "37"
},
"outline": {
"row": "38","type": "other","name": "__outline__","context": "misc","layer_type": "document","polarity": "positive","drl_start": "","drl_end": "","gdrl_start": "","gdrl_end": "",
"tl_num": 110037,"odb_name": "outline","odb_context": "misc","odb_type": "document","odb_polarity": "positive","odb_side": "none",
"row_num": 110037,"odb_row_num": "38"
},
"top_assem": {
"row": "39","type": "other","name": "__top_assem__","context": "misc","layer_type": "document","polarity": "positive","drl_start": "","drl_end": "","gdrl_start": "","gdrl_end": "",
"tl_num": 110038,"odb_name": "top_assem","odb_context": "misc","odb_type": "document","odb_polarity": "positive","odb_side": "none",
"row_num": 110038,"odb_row_num": "39"
},
"bot_assem": {
"row": "40","type": "other","name": "__bot_assem__","context": "misc","layer_type": "document","polarity": "positive","drl_start": "","drl_end": "","gdrl_start": "","gdrl_end": "",
"tl_num": 110039,"odb_name": "bot_assem","odb_context": "misc","odb_type": "document","odb_polarity": "positive","odb_side": "none",
"row_num": 110039,"odb_row_num": "40"
},
"top_testpoint": {
"row": "41","type": "other","name": "__top_testpoint__","context": "misc","layer_type": "document","polarity": "positive","drl_start": "","drl_end": "","gdrl_start": "","gdrl_end": "",
"tl_num": 110040,"odb_name": "top_testpoint","odb_context": "misc","odb_type": "document","odb_polarity": "positive","odb_side": "none",
"row_num": 110040,"odb_row_num": "41"
},
"bot_testpoint": {
"row": "42","type": "other","name": "__bot_testpoint__","context": "misc","layer_type": "document","polarity": "positive","drl_start": "","drl_end": "","gdrl_start": "","gdrl_end": "",
"tl_num": 110041,"odb_name": "bot_testpoint","odb_context": "misc","odb_type": "document","odb_polarity": "positive","odb_side": "none",
"row_num": 110041,"odb_row_num": "42"
},
"top_osp": {
"row": "43","type": "other","name": "__top_osp__","context": "misc","layer_type": "document","polarity": "positive","drl_start": "","drl_end": "","gdrl_start": "","gdrl_end": "",
"tl_num": 110042,"odb_name": "top_osp","odb_context": "misc","odb_type": "document","odb_polarity": "positive","odb_side": "none",
"row_num": 110042,"odb_row_num": "43"
},
"bot_osp": {
"row": "44","type": "other","name": "__bot_osp__","context": "misc","layer_type": "document","polarity": "positive","drl_start": "","drl_end": "","gdrl_start": "","gdrl_end": "",
"tl_num": 110043,"odb_name": "bot_osp","odb_context": "misc","odb_type": "document","odb_polarity": "positive","odb_side": "none",
"row_num": 110043,"odb_row_num": "44"
},
"top_enig": {
"row": "45","type": "other","name": "__top_enig__","context": "misc","layer_type": "document","polarity": "positive","drl_start": "","drl_end": "","gdrl_start": "","gdrl_end": "",
"tl_num": 110044,"odb_name": "top_enig","odb_context": "misc","odb_type": "document","odb_polarity": "positive","odb_side": "none",
"row_num": 110044,"odb_row_num": "45"
},
"bot_enig": {
"row": "46","type": "other","name": "__bot_enig__","context": "misc","layer_type": "document","polarity": "positive","drl_start": "","drl_end": "","gdrl_start": "","gdrl_end": "",
"tl_num": 110045,"odb_name": "bot_enig","odb_context": "misc","odb_type": "document","odb_polarity": "positive","odb_side": "none",
"row_num": 110045,"odb_row_num": "46"
},
"fab_page2": {
"row": "47","type": "other","name": "__fab_page2__","context": "misc","layer_type": "document","polarity": "positive","drl_start": "","drl_end": "","gdrl_start": "","gdrl_end": "",
"tl_num": 110046,"odb_name": "fab_page2","odb_context": "misc","odb_type": "document","odb_polarity": "positive","odb_side": "none",
"row_num": 110046,"odb_row_num": "47"
},
"tmp_top_shorts": {
"row": "48","type": "other","name": "__tmp_top_shorts__","context": "misc","layer_type": "signal","polarity": "positive","drl_start": "","drl_end": "","gdrl_start": "","gdrl_end": "",
"tl_num": 110047,"odb_name": "tmp_top_shorts","odb_context": "misc","odb_type": "signal","odb_polarity": "positive","odb_side": "none",
"row_num": 110047,"odb_row_num": "48"
},
"tmp_bot_shorts": {
"row": "49","type": "other","name": "__tmp_bot_shorts__","context": "misc","layer_type": "signal","polarity": "positive","drl_start": "","drl_end": "","gdrl_start": "","gdrl_end": "",
"tl_num": 110048,"odb_name": "tmp_bot_shorts","odb_context": "misc","odb_type": "signal","odb_polarity": "positive","odb_side": "none",
"row_num": 110048,"odb_row_num": "49"
},
"bot_assy_mate": {
"row": "50","type": "other","name": "__bot_assy_mate__","context": "misc","layer_type": "signal","polarity": "positive","drl_start": "","drl_end": "","gdrl_start": "","gdrl_end": "",
"tl_num": 110049,"odb_name": "bot_assy_mate","odb_context": "misc","odb_type": "signal","odb_polarity": "positive","odb_side": "none",
"row_num": 110049,"odb_row_num": "50"
},
"outline+1": {
"row": "51","type": "other","name": "__outline+1__","context": "misc","layer_type": "signal","polarity": "positive","drl_start": "","drl_end": "","gdrl_start": "","gdrl_end": "",
"tl_num": 110050,"odb_name": "outline+1","odb_context": "misc","odb_type": "signal","odb_polarity": "positive","odb_side": "none",
"row_num": 110050,"odb_row_num": "51"
},
"top_assy_mate": {
"row": "52","type": "other","name": "__top_assy_mate__","context": "misc","layer_type": "signal","polarity": "positive","drl_start": "","drl_end": "","gdrl_start": "","gdrl_end": "",
"tl_num": 110051,"odb_name": "top_assy_mate","odb_context": "misc","odb_type": "signal","odb_polarity": "positive","odb_side": "none",
"row_num": 110051,"odb_row_num": "52"
}
}
}
function tmp_2(){
return {
"cad": {
"d1-2": {
"1": {
"count": "06896",
"num": "1",
"type": "via",
"min_tol": "2.756",
"max_tol": "0.984",
"finish_size": "2.756",
"drill_size": "2.756",
"slot_len": "0",
"type2": "laser",
"shape": "hole",
"bit": 0
}
},
"d2-3": {
"1": {
"count": "07430",
"num": "1",
"type": "via",
"min_tol": "2.756",
"max_tol": "0.984",
"finish_size": "2.756",
"drill_size": "2.756",
"slot_len": "0",
"type2": "laser",
"shape": "hole",
"bit": 0
}
},
"d3-4": {
"1": {
"count": "06866",
"num": "1",
"type": "via",
"min_tol": "2.756",
"max_tol": "0.984",
"finish_size": "2.756",
"drill_size": "2.756",
"slot_len": "0",
"type2": "laser",
"shape": "hole",
"bit": 0
}
},
"d4-5": {
"1": {
"count": "06413",
"num": "1",
"type": "via",
"min_tol": "2.756",
"max_tol": "0.984",
"finish_size": "2.756",
"drill_size": "2.756",
"slot_len": "0",
"type2": "laser",
"shape": "hole",
"bit": 0
}
},
"d5-6": {
"1": {
"count": "08938",
"num": "1",
"type": "via",
"min_tol": "2.756",
"max_tol": "0.984",
"finish_size": "2.756",
"drill_size": "2.756",
"slot_len": "0",
"type2": "laser",
"shape": "hole",
"bit": 0
}
},
"d6-7": {
"1": {
"count": "09057",
"num": "1",
"type": "via",
"min_tol": "2.756",
"max_tol": "0.984",
"finish_size": "2.756",
"drill_size": "2.756",
"slot_len": "0",
"type2": "laser",
"shape": "hole",
"bit": 0
}
},
"d7-8": {
"1": {
"count": "07818",
"num": "1",
"type": "via",
"min_tol": "2.756",
"max_tol": "0.984",
"finish_size": "2.756",
"drill_size": "2.756",
"slot_len": "0",
"type2": "laser",
"shape": "hole",
"bit": 0
}
},
"d8-9": {
"1": {
"count": "09126",
"num": "1",
"type": "via",
"min_tol": "2.756",
"max_tol": "0.984",
"finish_size": "2.756",
"drill_size": "2.756",
"slot_len": "0",
"type2": "laser",
"shape": "hole",
"bit": 0
}
},
"d9-10": {
"1": {
"count": "08498",
"num": "1",
"type": "via",
"min_tol": "2.756",
"max_tol": "0.984",
"finish_size": "2.756",
"drill_size": "2.756",
"slot_len": "0",
"type2": "laser",
"shape": "hole",
"bit": 0
}
},
"drill": {
"1": {
"count": "05",
"num": "1",
"type": "non_plated",
"min_tol": "3.15",
"max_tol": "3.15",
"finish_size": "15.748",
"drill_size": "15.748",
"slot_len": "0",
"type2": "standard",
"shape": "hole",
"bit": 0
},
"2": {
"count": "01",
"num": "2",
"type": "non_plated",
"min_tol": "0",
"max_tol": "1.969",
"finish_size": "35.039",
"drill_size": "35.039",
"slot_len": "0",
"type2": "standard",
"shape": "hole",
"bit": 0
},
"3": {
"count": "01",
"num": "3",
"type": "non_plated",
"min_tol": "3.15",
"max_tol": "3.15",
"finish_size": "35.039",
"drill_size": "35.039",
"slot_len": "0",
"type2": "standard",
"shape": "hole",
"bit": 0
},
"4": {
"count": "01",
"num": "4",
"type": "non_plated",
"min_tol": "1.969",
"max_tol": "1.969",
"finish_size": "47.244",
"drill_size": "47.244",
"slot_len": "0",
"type2": "standard",
"shape": "hole",
"bit": 0
},
"5": {
"count": "05",
"num": "5",
"type": "non_plated",
"min_tol": "1.969",
"max_tol": "1.969",
"finish_size": "59.055",
"drill_size": "59.055",
"slot_len": "0",
"type2": "standard",
"shape": "hole",
"bit": 0
},
"6": {
"count": "01",
"num": "6",
"type": "non_plated",
"min_tol": "1.969",
"max_tol": "1.969",
"finish_size": "70.866",
"drill_size": "70.866",
"slot_len": "0",
"type2": "standard",
"shape": "hole",
"bit": 0
},
"7": {
"count": "01",
"num": "7",
"type": "non_plated",
"min_tol": "1.969",
"max_tol": "1.969",
"finish_size": "74.803",
"drill_size": "74.803",
"slot_len": "0",
"type2": "standard",
"shape": "hole",
"bit": 0
}
}
},
"stp": {
"d1-2": {},
"d2-3": {},
"d3-4": {},
"d4-5": {},
"d5-6": {},
"d6-7": {},
"d7-8": {},
"d8-9": {},
"d9-10": {},
"drill": {
"1": {
"count": "08",
"num": "1",
"type": "non_plated",
"min_tol": "0",
"max_tol": "1.969",
"finish_size": "118.11",
"drill_size": "118.11",
"slot_len": "0",
"type2": "standard",
"shape": "hole",
"bit": 0
}
}
}
}
}
\ No newline at end of file
......@@ -45,23 +45,38 @@
</body></html>
*/
console.log("=============================================>anaysis_start");
// 引入模块 包
var $ = require('topcam.scriptfunc').argv();
var fs = require('fs');
var _ = require('lodash');
var IKM = $.ikm;
var GEN = $.gen;
var GUI = $.gui;
var Job = $.job;
var JobId = $.job_id;
var mode = "develop" // 运行模式 develop 开发模式 方便调试
var database = require("topsin.database");
database.addConnection($.conf.database_conf, "DFM");
var QDfm = database.query("DFM");
if ($.conf.product_type == "aimdfm") {
QDfm.updateRow({
table: "pdm_aimdfm_task",
data: {
current_process_title: $.process_title
},
where: { id: $.task_id }
});
}
var GEN = $.gen;
var Job = $.job_name;
var db = $.db;
var Status = 'ok';
var resultData = [];
var PAR = {};
if ($.hasOwnProperty('script_parameter')){
PAR = JSON.parse($.script_parameter);
}
try {
var job = "1"
var job = Job;
var pcs_step = "cad", array_step = "stp";
var matrix = UPLOAD_LAYER_MATRIX({job:job}) // 分析matrix 获得分析后的matrix信息
console.log("===================================> 1matrix")
var analysis_obj = analysis({job:job,jobId:JobId,pcs_step:pcs_step,array_step:array_step,matrix:matrix})
var config = {
jobInfo: {
......@@ -95,8 +110,12 @@ try {
max_slot_drl_length: true, // todo 2.0mm 最大槽孔
max_spec_slot_drl_size: true, // todo 2.1mm 最大异形槽孔
max_spec_slot_drl_length: true, // todo 3.0mm 最大异形槽孔
},
layerInfo: {
}
}
console.log("===================================> 2analysis_obj")
// 分析料号info
var jobInfo = {}
......@@ -107,7 +126,7 @@ try {
if(props.hasOwnProperty("api") && props.hasOwnProperty("props")){
jobInfo[key] = analysis_obj["analysis_"+props.api](props.props)
} else if(props.only_value){
jobInfo[key] = analysis_obj[key]
jobInfo[key] = analysis_obj.jobInfo[key]
} else {
jobInfo[key] = analysis_obj["analysis_"+key](props)
}
......@@ -117,22 +136,27 @@ try {
}
}
})
console.log("===================================> 3 jobinfo")
// 过滤掉料号信息的 _todo 和 _error
for (var key in jobInfo) {
if(jobInfo[key] === "_todo" || jobInfo[key] === "_error"){
delete jobInfo[key]
}
}
console.log("===================================> 4 save job info")
// 上传jobInfo IKM版本
IKM.save_job_info({
jobid: JobId,
jobinfohash:jobInfo
})
// todo 上传jobInfo topjs3版本
// save_job_info({
// IKM.save_job_info({
// jobid: JobId,
// jobinfohash: jobInfo
// jobinfohash:jobInfo
// })
// 上传jobInfo topjs3版本
save_job_info({
jobid: JobId,
jobinfohash: jobInfo
})
console.log("===================================> 5 save drill info")
// todo 设置钻孔层孔属性,镭射孔via,无铜孔npth,其余孔pth
......@@ -172,34 +196,175 @@ try {
attr_data: {} // {"allowance": 2, "org_layer_name": "hhhh"}
}
if(!array_count){delete data.array_count}
var id = IKM.crud("selectValue",{
var id = db.query("",function(q){
return q.selectValue({
table:'pdm_job_cam_drill',
field:"id",
where:{job_id:JobId, layer_name: layer,tool_num: key}
})
});
if(/done/ig.test(id)){
IKM.crud("insertRow",{
db.query("",function(q){
return q.insertRow({
table:'pdm_job_cam_drill',
data:data,
return_field:'id',
})
});
}else{
IKM.crud("updateRow",{
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'}
})
});
}
})
})
console.log("===================================> 6 layer info")
// 分析layer info
var stepList = [pcs_step];
var oChecklistName = "mychecklist"
var signalLayers = analysis_obj.matrixInfo.mSignal.map(function(v){return v.name})
var drillLayers = analysis_obj.matrixInfo.mDrill.map(function(v){return v.name})
var info = {
min_line_width: ["line"],
min_line_spacing: ["l2l"],
min_line2pad: ["p2line"],
min_pad2pad: ["p2p", "smd2smd", "smd2pad"],
min_ar: ["ar","pth_ar"]
}
stepList.forEach(function(step){
GEN.openStep({ job: job, name: step })
GEN.clearLayers()
GEN.affectedLayer({ affected: 'no', mode: 'all' })
// 创建chklist并运行 如果chklist存在先删除
if (GEN.isChklistExists({ job: job, step: step, chklist: oChecklistName })) {
GEN.COM("chklist_delete", { chklist: oChecklistName })
}
createChklistAndRun({ // 创建checklist并运行
layers: signalLayers,
items: [{
name: "signal_layer_checks",
nact: 1,
action: "valor_analysis_signal",
erf: "S2_conductor_Check",
params: { // ?
pp_layer: ".affected",
pp_spacing: 20,
pp_selected: "All",
pp_r2c: 10,
pp_d2c: 15,
pp_sliver: 8,
pp_min_pad_overlap: 5,
pp_check_missing_pads_for_drills: "Yes",
pp_use_compensated_rout: "Skeleton",
pp_sm_spacing: "Yes"
}
}]
})
// signal层分析结果
var res = analysisChkAttr({layers:signalLayers, info:info, step:step, job:job, oChecklistName:oChecklistName})
// 铜面积
var copper_percent_pcs = signalLayers.map(function(v){
var tmp = {layer:v}
tmp.copper_percent = GEN.copperArea({layer1:v}).percent + "%"
return tmp
})
// 钻孔
var drillToSignals = drillLayers.map(function(v){ // 获取到钻孔层对应的顶层和底层
var simbols = GEN.getLayerSymsHist({job:job,step:step,layer:v})
var symbol = _.values(simbols).sort(function(a,b){return Number(a.size)-Number(b.size)})
.reduce(function(a,b){
if(b.pad!="0"){
a.push(b.symbol)
}
return a
},[])[0]
return {layer:v,symbol:symbol,start:matrix[v]["drl_start"],end:matrix[v]["drl_end"]}
})
var drillRes = analysisDrill(drillToSignals,step) // 钻孔分析结果
// 数据入库
Object.keys(res).forEach(function(key){
var val = res[key]
save_layerinfo({
jobid: JobId,
layer: key,
layerinfohash: val
})
})
copper_percent_pcs.forEach(function(item){
save_layerinfo({
jobid: JobId,
layer: item.layer,
layerinfohash: {
copper_percent: item.copper_percent
}
})
})
drillRes.forEach(function(item){
save_layerinfo({
jobid: JobId,
layer: item.layer,
layerinfohash: {
drl_pad_top: item.drl_pad_top,
drl_pad_bot: item.drl_pad_bot,
}
})
})
})
// smd
var smdInfo = smdAnalysis({job:job,steplist:[pcs_step],layers:analysis_obj.matrixInfo.mOuters,attr:".smd"})
var save_info = [smdInfo, analysis_obj.jobInfo.laser_info]; // 保存 smd 和 bga数据
// 保存
console.log("===================================> save layer info")
save_info.forEach(function(item){
Object.keys(item).forEach(function(key){
var val = item[key]
save_layerinfo({
jobid: JobId,
layer: key,
layerinfohash: val
})
})
})
GUI.msg("Done")
return 'Done';
QDfm.updateRow({
table: "pdm_aimdfm_task",
data: {
progress: 33.33
},
where: { id: $.task_id }
});
if (GEN.hasError()) {
Status = 'error';
resultData.push({ type: "error", title: "GEN错误!", detail: [{ desc: _.join(GEN.STATUS, "\n") }] });
return {
status: Status,
result_data: resultData
};
} else {
resultData.push({ type: "info", title: "操作完成, 请注意检查!" });
return {
status: Status,
result_data: resultData
};
}
}
catch (error) {
GUI.msg(error);
return 'Error';
catch (e) {
Status = 'error';
console.log("====================================>error");
console.log(_.toString(e));
resultData.push({type: "error", title: "脚本执行出错!", detail: [{desc: _.toString(e)}]});
return {status: Status, result_data: resultData};
}
function UPLOAD_LAYER_MATRIX(props){
......@@ -419,6 +584,34 @@ function selCopyLayer(props){ // 拷贝选择的到辅助层
GEN.selCopyOther({dest:'layer_name',target_layer:layer})
}
function save_job_info(props){ // todo 保存料号信息
var jobid = props.jobid;
var jobinfohash = props.jobinfohash;
Object.keys(jobinfohash).forEach(function(key){
var val = jobinfohash[key];
db.query("",function(q){
return q.insertRow({
table:'sys_user', // todo
data:{jobid:jobid, todo:key, value:val}, // todo
return_field:'id',
})
});
})
}
function save_layerinfo(props){ // todo 保存层信息
var jobid = props.jobid;
var layer = props.layer;
var layerinfohash = props.layerinfohash;
Object.keys(layerinfohash).forEach(function(key){
var val = layerinfohash[key];
db.query("",function(q){
return q.insertRow({
table:'sys_user', // todo
data:{jobid:jobid, layer:layer,key:key , value:val}, // todo
return_field:'id',
})
});
})
}
function analysis(props){
......@@ -653,6 +846,263 @@ function analysis(props){
}
return new T_m_p({job:job, jobId:jobId, pcs_step:pcs_step, array_step:array_step,matrix:matrix})
}
function smdAnalysis(props){
var job = props.job
var steplist = props.steplist
var layers = props.layers
var res = {}
steplist.forEach(function(step){
GEN.openStep({job:job,step:step})
layers.forEach(function(layer){
// 计算开窗 数量
GEN.workLayer({name:layer.solderL,display_number:2,clear_before:'yes'})
if (!res.hasOwnProperty(layer.solderL)){
res[layer.solderL] = {}
}
GEN.selectByFilter({profile:'in'})
GEN.selAllFeat()
res[layer.solderL].sm_opening_count = GEN.getSelectCount()
GEN.selClearFeature()
// 分析最小smd宽高
GEN.workLayer({name:layer.signalL,display_number:2,clear_before:'yes'})
GEN.selClearFeature()
GEN.selectByFilter({attribute:props.attr})
var selCount = GEN.getSelectCount()
if(selCount>0){
var tmp_layer = layer.signalL + "_tmp"
selCopyLayer({job:job,layer:tmp_layer})
var symbols = GEN.getLayerSymsHist({job:job,layer:tmp_layer,step:step})
GEN.workLayer({name:tmp_layer,display_number:2,clear_before:'yes'})
var symbolInfo = symbolAnalysis({symbols:symbols,filterReg:/^rect/})
if (!res.hasOwnProperty(layer.signalL)){
res[layer.signalL] = {}
}
res[layer.signalL]["min_smd_width"] = symbolInfo["min_width"]
res[layer.signalL]["min_smd_length"] = symbolInfo["min_length"]
// 分析最小smd间距
// 创建一个checklist并且分析
var min_smd_pitch = smdPitch({job:job,step:step,layer:tmp_layer})
res[layer.signalL]["min_smd_pitch"] = min_smd_pitch
// 分析开窗宽高
GEN.workLayer({name:layer.solderL,display_number:2,clear_before:'yes'})
GEN.selClearFeature()
GEN.selRefFeat({layers:tmp_layer,use:'filter',mode:'include'})
GEN.selRefFeat({layers:tmp_layer,use:'filter',mode:'cover'})
var solderL_tmp = layer.solderL + "_tmp"
selCopyLayer({job:job,layer:solderL_tmp})
GEN.selClearFeature()
GEN.workLayer({name:solderL_tmp,display_number:2,clear_before:"yes"})
var symbols_solder = GEN.getLayerSymsHist({job:job,layer:solderL_tmp,step:step})
var symbolInfo_solder = symbolAnalysis({symbols:symbols_solder,filterReg:/^rect/})
res[layer.signalL].min_smd_opening_width = symbolInfo_solder["min_width"]
res[layer.signalL].min_smd_opening_length = symbolInfo_solder["min_length"]
GEN.deleteLayer({job:job,layer:solderL_tmp})
GEN.deleteLayer({job:job,layer:tmp_layer})
}
})
GEN.closeStep()
})
return res
}
function symbolAnalysis(props){
var symbols = Object.keys(props.symbols).reduce(function(a,b){
if(props.filterReg.test(b)){
var res = /^rect(\d+\.\d+|\d+)x(\d+\.\d+|\d+)/ig.exec(b).slice(1)
var num1 = res[0], num2 = res[1]
if(num1<=num2){
a.width.push(num1)
a.length.push(num2)
} else {
a.width.push(num2)
a.length.push(num1)
}
}
return a
},{width:[],length:[]})
return {
min_width:symbols.width.reduce(function(a,b){return b-a > 0 ? a : b}),
min_length:symbols.length.reduce(function(a,b){return b-a > 0 ? a : b})
}
}
function smdPitch(props){
var job = props.job
var step = props.step
var layer = props.layer
var ck = "tmp_chk"
if(GEN.isChklistExists({job:job,step:step,chklist:ck})){
GEN.COM("chklist_delete", { chklist: ck })
}
// 创建并运行
GEN.createChklist({ // 创建checklist
chklist: ck,
items: [{
name: "smdPitch",
nact: 1,
action: "valor_analysis_signal",
erf: "S2_conductor_Check",
params: {
pp_layer: ".affected",
pp_spacing: 20,
pp_selected: "All",
pp_r2c: 10,
pp_d2c: 15,
pp_sliver: 8,
pp_min_pad_overlap: 5,
pp_check_missing_pads_for_drills: "Yes",
pp_use_compensated_rout: "Skeleton",
pp_sm_spacing: "Yes",
pp_tests: "Spacing\\;SMD",
pp_check_missing_pads_for_drills:"Yes"
}
}]
})
GEN.chklistShow({ chklist: ck })
GEN.affectedLayer({ affected: "yes", layer: layer, clear_before: "yes" })
GEN.chklistRun({
chklist: ck,
nact: 1,
area: 'profile'
})
var tmp_layer1 = "mk_1_"+layer+"_pitch"
var tmp_layer2 = "ms_1_"+layer+"_pitch"
if(GEN.isLayerExists({job:job,layer:tmp_layer1})){
GEN.deleteLayer({job:job,layer:tmp_layer1})
}
if(GEN.isLayerExists({job:job,layer:tmp_layer2})){
GEN.deleteLayer({job:job,layer:tmp_layer2})
}
GEN.COM("chklist_create_lyrs,chklist="+ck+",severity=3,suffix=pitch");
GEN.workLayer({name:tmp_layer2,display_number:1,clear_before:'yes'});
GEN.selectByFilter({attribute:[{attribute:".string",text:"smd_pitch"}]})
var tmp_layer = tmp_layer2 + "_tmp"
selCopyLayer({job:job,layer:tmp_layer})
GEN.workLayer({name:tmp_layer,display_number:1,clear_before:'yes'});
var symbols = GEN.getLayerSymsHist({job:job,layer:tmp_layer,step:step})
// 获取最小smd间距
var res = _.values(symbols).sort(function(a,b){return Number(a.size)-Number(b.size)})[0].size
GEN.deleteLayer({job:job,layer:tmp_layer})
GEN.deleteLayer({job:job,layer:tmp_layer1})
GEN.deleteLayer({job:job,layer:tmp_layer2})
return res
}
function createChklistAndRun(par) {
var checkLayers = par.layers
var items = par.items
GEN.createChklist({ // 创建checklist
chklist: oChecklistName,
items: items
})
GEN.chklistShow({
chklist: oChecklistName
})
GEN.affectedLayer({
affected: "yes",
layer: checkLayers,
clear_before: "yes"
})
items.forEach(function(v){
GEN.chklistRun({
chklist: oChecklistName,
nact: v.nact,
area: 'profile'
})
})
}
function analysisChkAttr(par) {
var layers = par.layers;
var hash = {};
var info = par.info;
var job = par.job;
var oChecklistName = par.oChecklistName
layers.forEach(function (v) {
hash[v] = {}
Object.keys(info).forEach(function (key) {
var val = info[key]
hash[v][key] = val.reduce(function (a, type) {
var tmp = GEN.getCheckAttr({
job: job,
step: par.step,
checklist: oChecklistName,
nact: 1,
attr: v + "_min_" + type
})
if (a === "N/A" && /\d+/.test(tmp)) {
a = tmp
}
if (/\d+/.test(a) && /\d+/.test(tmp) && Number(tmp) < Number(a)) {
a = tmp
}
return a
}, "N/A")
})
})
return hash
}
function analysisDrill(par, step){
// {"layer":"d1-2","symbol":"r3.937","start":"top","end":"isl2"}
var res = par.map(function(drill){
GEN.affectedLayer({affected:"yes",layer:drill.layer,clear_before:"yes",mode:"all"})
GEN.selClearFeature()
GEN.selectByFilter({feat_types:"pad",include_syms:drill.symbol})
// 拷贝到_tmp
var tmplayer = drill.layer + "_tmp"
if(GEN.isLayerExists({job:Job,layer:tmplayer})){GEN.deleteLayer({job:Job,step:step,layer:tmplayer})}
GEN.selCopyOther({dest:"layer_name",target_layer:tmplayer,invert:'no',dx:0,dy:0,size:0})
GEN.affectedLayer({affected:"no",mode:"all"})
GEN.selClearFeature();
[drill.start,drill.end].forEach(function(item, i){
GEN.workLayer({name:item,display_number:1,clear_before:"yes"})
GEN.selRefFeat({
layers: tmplayer,
use: "filter",
mode: "include",
f_types: "pad",
pads_as:"shape",
polarity:"positive",
include_syms:drill.symbol,
filter: {
feat_types:'pad'
}
})
var res = ""
var pads = GEN.getFeatures({job:Job,step:step,layer:item,options:"select"})
if(pads && pads.length) {
pads = pads.filter(function(item){
return /^r\d+/.test(item.symbol)
})
pads = pads.sort(function(a,b){
return parseInt(a.symbol) - parseInt(b.symbol)
})
res = pads[0].symbol.slice(1)
}
if ( i == 0) {
drill.drl_pad_top = res
} else if (i==1){
drill.drl_pad_bot = res
}
})
GEN.deleteLayer({job:Job,step:step,layer:tmplayer})
return drill
})
return res
}
function tmp(){
return {
......
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