492 lines
30 KiB
Ruby
492 lines
30 KiB
Ruby
class HncCancerPredictfields
|
||
require "pathname"
|
||
require 'json'
|
||
include Mongoid::Document
|
||
include Mongoid::Timestamps
|
||
Field_relations = {"number_field"=>"Fixnum","text_area"=>"String"}
|
||
FIELDINFO = {"variable"=>"String","name"=>"String","is_num"=>"Fixnum","hint"=>"String","comment_text"=>"String","choice_fields"=>"Array","range"=>"Array","right"=>"Fixnum","is_float"=>"Fixnum","revert_value"=>"Fixnum","map_values"=>"Array","hnc_cancer_predict_mapping_file"=>"String","lpv_impact"=>"Float","active_choice"=>"number_field","disable_condition"=>"text_area"}
|
||
NonLoclaized = ["variable","is_num","range","right","is_float","revert_value","map_values","hnc_cancer_predict_mapping_file","lpv_impact","active_choice","disable_condition"]
|
||
AdvanceFields = ["revert_value","map_values","hnc_cancer_predict_mapping_file"]
|
||
TherapyFields = ["variable","name","hint","comment_text","choice_fields","lpv_impact","active_choice","disable_condition"]
|
||
TherapyOnly = ["lpv_impact","active_choice","disable_condition"]
|
||
ModuleAppPath = Pathname.new(File.expand_path(__dir__)).dirname.dirname.to_s.freeze
|
||
JS = "hnc_cancer_predict.js"
|
||
JSFileName = "public/hnc_tool_js_filename.txt".freeze
|
||
ToolTableMap = I18n.available_locales.map do |locale|
|
||
[locale, "public/hnc_tool_table_tmp_#{locale}.txt".freeze]
|
||
end.to_h
|
||
field :title ,type:String ,default:""
|
||
field :advance_mode, type: Boolean, default: false
|
||
field :form_show , :type=> Hash ,default:{
|
||
"0"=>{"variable"=>"age", "name"=>{"zh_tw"=>"年齡<br/>(Age)", "en"=>"Age"}, "is_num"=>1, "hint"=>{"zh_tw"=>"從 20 歲(含)開始至 80 歲", "en"=>"Age must be between 20 and 80"}, "comment_text"=>{"zh_tw"=>"年齡為該病人於確診罹患頭頸癌時之年齡", "en"=>"Age at diagnosis"}, "choice_fields"=>{"zh_tw"=>[], "en"=>[]}, "range"=>[20, 80], "right"=>0, "is_float"=>0, "need_map_values"=>0, "revert_value"=>0, "map_values"=>[]},
|
||
"1"=>{"variable"=>"size", "name"=>{"zh_tw"=>"腫瘤大小(單位:mm)<br/>(Tumor size)", "en"=>"Tumor size"}, "is_num"=>1, "hint"=>{"zh_tw"=>"", "en"=>"The unit of tumor size is millimeter (mm)"}, "comment_text"=>{"zh_tw"=>"若有多個原發腫瘤,請輸入最大尺寸之原發腫瘤、上限為 100mm", "en"=>"If there was more than one primary tumor, please enter the size of the largest one."}, "choice_fields"=>{"zh_tw"=>[], "en"=>[]}, "range"=>[1, 100], "right"=>0, "is_float"=>0, "need_map_values"=>0, "revert_value"=>0, "map_values"=>[]},
|
||
"2"=>{"variable"=>"height", "name"=>{"zh_tw"=>"身高(單位:公分)<br/>(Height)", "en"=>"Height(cm)"}, "is_num"=>1, "hint"=>{"zh_tw"=>"", "en"=>""}, "comment_text"=>{"zh_tw"=>"", "en"=>""}, "choice_fields"=>{"zh_tw"=>[], "en"=>[]}, "range"=>[140, 200], "right"=>0, "is_float"=>0, "need_map_values"=>0, "revert_value"=>0, "map_values"=>[]},
|
||
"3"=>{"variable"=>"weight", "name"=>{"zh_tw"=>"體重(單位:公斤)<br/>(Weight)", "en"=>"Weight(kg)"}, "is_num"=>1, "hint"=>{"zh_tw"=>"", "en"=>""}, "comment_text"=>{"zh_tw"=>"", "en"=>""}, "choice_fields"=>{"zh_tw"=>[], "en"=>[]}, "range"=>[40, 130], "right"=>0, "is_float"=>0, "need_map_values"=>0, "revert_value"=>0, "map_values"=>[]},
|
||
"4"=>{"variable"=>"pstage", "name"=>{"zh_tw"=>"病理分期<br/>(Pathological stage)", "en"=>"Pathological stage"}, "is_num"=>0, "hint"=>{"zh_tw"=>"", "en"=>""}, "comment_text"=>{"zh_tw"=>"若無分期資訊,請選擇“未知”選項,將以分期第 1 期進行預測。", "en"=>"Please select “unknown” if there is no information about “Pathological stage”. The prediction model would use “1th stage” as the alternative variable."}, "choice_fields"=>{"zh_tw"=>["1", "2", "3", "4", "未知"], "en"=>["1", "2", "3", "4", "unknown"]}, "range"=>[], "right"=>0, "is_float"=>0, "need_map_values"=>0, "revert_value"=>0, "map_values"=>[]},
|
||
"5"=>{"variable"=>"sex", "name"=>{"zh_tw"=>"性別<br/>(Sex)", "en"=>"Sex"}, "is_num"=>0, "hint"=>{"zh_tw"=>"", "en"=>""}, "comment_text"=>{"zh_tw"=>"", "en"=>""}, "choice_fields"=>{"zh_tw"=>["男", "女"], "en"=>["Male", "Female"]}, "range"=>[], "right"=>1, "is_float"=>0, "need_map_values"=>0, "revert_value"=>0, "map_values"=>[]},
|
||
"6"=>{"variable"=>"site", "name"=>{"zh_tw"=>"腫瘤部位<br/>(Tumor site)", "en"=>"Tsumor site"}, "is_num"=>0, "hint"=>{"zh_tw"=>"", "en"=>""}, "comment_text"=>{"zh_tw"=>"", "en"=>""}, "choice_fields"=>{"zh_tw"=>["口腔", "口咽", "下咽", "唾液腺", "喉"], "en"=>["Oral cavity", "Oropharynx", "Hypopharynx", "Salivary glands", "Larynx"]}, "range"=>[], "right"=>1, "is_float"=>0, "need_map_values"=>0, "revert_value"=>0, "map_values"=>[]},
|
||
"7"=>{"variable"=>"lymph", "name"=>{"zh_tw"=>"被侵犯頸部淋巴結之最大直徑<br/>(Maximum lymph node diameter)", "en"=>"Maximum lymph node diameter"}, "is_num"=>0, "hint"=>{"zh_tw"=>"", "en"=>""}, "comment_text"=>{"zh_tw"=>"此請填入被侵犯頸部淋巴結紀錄中之最大徑,若無頸部淋巴結被侵犯資訊,請選擇“未知”選項,將以無侵犯類別進行預測。", "en"=>"Please fill in the maximum lymph node diameter here. If there is no information about this, please select the “Unknown” option, and prediction will be made as no metastasis."}, "choice_fields"=>{"zh_tw"=>["無侵犯", "1-9 mm", "10-19 mm", "20-29 mm", "30-39 mm", "40-49 mm", "50-59 mm", ">= 60 mm", "未知"], "en"=>["No metastasis", "1-9 mm", "10-19 mm", "20-29 mm", "30-39 mm", "40-49 mm", "50-59 mm", ">= 60 mm", "unknown"]}, "range"=>[], "right"=>1, "is_float"=>0, "need_map_values"=>0, "revert_value"=>0, "map_values"=>[]},
|
||
"8"=>{"variable"=>"drinking", "name"=>{"zh_tw"=>"喝酒行為<br/>(Alcohol consumption)", "en"=>"Alcohol consumption"}, "is_num"=>0, "hint"=>{"zh_tw"=>"", "en"=>""}, "comment_text"=>{"zh_tw"=>"請依據診斷日前一年內喝酒行為填入。", "en"=>"Please fill in the information based on your drinking behavior within one year before this diagnosis."}, "choice_fields"=>{"zh_tw"=>["從未喝酒", "偶爾喝", "習慣性喝酒"], "en"=>["Never", "Sometime", "Usually"]}, "range"=>[], "right"=>1, "is_float"=>0, "need_map_values"=>0, "revert_value"=>0, "map_values"=>[]},
|
||
"9"=>{"variable"=>"smoking", "name"=>{"zh_tw"=>"吸菸行為<br/>(Tobacco smoking)", "en"=>"Tobacco smoking"}, "is_num"=>0, "hint"=>{"zh_tw"=>"", "en"=>""}, "comment_text"=>{"zh_tw"=>"請依據診斷日前一年內吸菸行為填入。", "en"=>"Please fill in the information based on your smoking behavior within one year before this diagnosis."}, "choice_fields"=>{"zh_tw"=>["沒有", "有"], "en"=>["No", "Yes"]}, "range"=>[], "right"=>1, "is_float"=>0, "need_map_values"=>0, "revert_value"=>0, "map_values"=>[]}
|
||
}
|
||
field :form_show_in_result , :type=> Hash ,default: {
|
||
"1"=>{"variable"=>"Chemotherapy", "name"=>{"zh_tw"=>"化學治療", "en"=>"Chemotherapy"}, "is_num"=>0, "hint"=>{"zh_tw"=>"", "en"=>""}, "comment_text"=>{"zh_tw"=>"", "en"=>""}, "choice_fields"=>{"zh_tw"=>["否", "是"], "en"=>["No", "Yes"]}, "range"=>[], "right"=>0, "is_float"=>0, "revert_value"=>0, "map_values"=>"", "active_choice"=>2, "disable_condition"=>"", "lpv_impact"=>0.15613},
|
||
"2"=>{"variable"=>"Radiotherapy", "name"=>{"zh_tw"=>"放射治療", "en"=>"Radiotherapy"}, "is_num"=>0, "hint"=>{"zh_tw"=>"", "en"=>""}, "comment_text"=>{"zh_tw"=>"", "en"=>""}, "choice_fields"=>{"zh_tw"=>["否", "是"], "en"=>["No", "Yes"]}, "range"=>[], "right"=>0, "is_float"=>0, "revert_value"=>0, "map_values"=>"", "active_choice"=>2, "disable_condition"=>"", "lpv_impact"=>-0.34129}
|
||
}
|
||
field :form_result_is_right , :type=> Integer ,default: 0
|
||
field :text_descibe ,type:Hash ,default: {
|
||
"zh_tw"=>"歡迎使用台灣準備頭頸癌預後系統!<br />\r\n本預測系統由台灣癌症登記資料庫2013至2018年間共49,137位頭頸癌病人所建立。<br />\r\n若要開始 請在下方選擇相關資訊",
|
||
"en"=>"Welcome to the Taiwan Head and Neck Cancer Prediction System!<br />\r\nThe prediction system is constructed using clinical data from 49,137 head and neck cancer patients in the Taiwan Cancer Registry database between 2013 to 2018.<br />\r\nTo start, please select the information below."
|
||
}
|
||
field :small ,type:Hash ,default:{'font_size'=>"0.825em",'active'=>0}
|
||
field :medium ,type:Hash ,default:{'font_size'=>"1em",'active'=>1}
|
||
field :large ,type:Hash ,default:{'font_size'=>"1.25em",'active'=>0}
|
||
field :hnc_head_images_id ,type:Array , default: []
|
||
field :title_images_id ,type:Array , default: []
|
||
field :title_texts ,type:Hash ,default: {"zh_tw"=>"頭頸癌症線上預測工具", "en"=>"Predict Head and Neck Cancer Tool"}
|
||
field :table_above_texts ,type:Hash ,default: {"zh_tw"=>"下表之分析為針對手術後病人,根據選定的術後治療,分別估計在第1年、3 及5年的存活率。", "en"=>"The analysis is for women who had undergone surgery.The table shows the 1-, 3- and 5-year survival rates,based on the treatment you have selected."}
|
||
field :text_above_texts ,type:Hash ,default: {"zh_tw"=>"此研究分析來自已接受根除性手術後之婦女所得之結果,根據您所輸入的資訊以及治療方式,在術後<br/>第{{years}}年,", "en"=>"The analysis is for women who had undergone surgery. Base on the information and the treatment you have selected, the predictions of survival status<br/>{{years}}"}
|
||
field :surgery_only_texts ,type:Hash ,default: {"zh_tw"=>"100 位只接受根除性手術的婦女中,有{{Surgery_only}}位婦女,術後{{surgery_year}}年仍為存活", "en"=>"after surgery are as follows:<br/>{{Surgery_only}} out of 100 women treated with surgery only are alive at {{surgery_year}} years."}
|
||
field :extra_texts ,type:Hash ,default: {"zh_tw"=>",此外", "en"=>""}
|
||
field :extra_therapy_texts ,type:Hash ,default: {"zh_tw"=>"100 位在術後有接受{{extra_therapy}}的婦女中,有{{survival_num}}位婦女,術後{{surgery_year}}年仍為存活(多了{{Additional_Benefit}}位)", "en"=>"{{survival_num}} out of 100 women treated with {{extra_therapy}} are alive (an extra {{Additional_Benefit}})"}
|
||
field :danger_texts ,type:Hash ,default: {"zh_tw"=>"請注意紅框的輸入資料是否符合要求!", "en"=>"Please check whether input data in red blocks are correct!"}
|
||
field :years ,type:Array ,default:[1,3,5]
|
||
field :texts_between_Result_and_result_block ,type:Hash ,default: {"zh_tw"=>"如果欲將預測結果應用於臨床上,請務必與您的主治醫師討論後再做最後決定。化學治療為高期數頭頸癌常規治療,本係數估計會有失真現象,請謹慎使用並考慮干擾因子效應。", "en"=>"Please note that the patients need to consult with their medical doctors before making any decision.As chemotherapy is the standard treatment of high grade head and neck cancer patients, the estimation of the coefficient in chemotherapy may be biased. Please be careful about the interpretation of the results and seriouly consider the confounding factors."}
|
||
#field :image_uploader ,type:Object
|
||
field :prediction_formula , type: String ,default: "lpv = ((age-56.13649)*0.00542+(size-26.24087)*0.01555+(bmi-24.71561)*(-0.03777)+
|
||
pstage_2*0.22023+pstage_3*0.11253+pstage_4*0.74585+
|
||
sex_ind*(-0.29218)+site_oralph*0.15131+site_hyph*(-0.18040)+site_sal*(-0.32440)+site_lary*(-0.19674)+
|
||
lymph_1*0.69354+lymph_2*0.85665+lymph_3*0.92695+lymph_4*0.93122+lymph_5*0.72533+
|
||
lymph_6*1.12371+lymph_7*1.13236+drink_ind*0.12961+smoke_ind*(-0.17848)+chemo*(0.15613)+radio*(-0.34129)
|
||
)"
|
||
field :years_settings , type: Array , default: ["exp(-0.03639284)^( exp(lpv) )","exp(-0.08738490)^( exp(lpv) )","exp(-0.10683094)^( exp(lpv) )"]
|
||
field :tmp_years_settings , type: Array , default: []
|
||
field :tmp_years_settings_for_ruby , type: Array , default: []
|
||
field :hidden_variables, type: String, default: "bmi = weight / ((height / 100.0) ^ 2)
|
||
pstage_2 = (pstage == 2) ? 1 : 0
|
||
pstage_3 = (pstage == 3) ? 1 : 0
|
||
pstage_4 = (pstage == 4) ? 1 : 0
|
||
sex_ind = (sex == 2) ? 1 : 0
|
||
site_oralph = (site == 2) ? 1 : 0
|
||
site_hyph = (site == 3) ? 1 : 0
|
||
site_sal = (site == 4) ? 1 : 0
|
||
site_lary = (site == 5) ? 1 : 0
|
||
lymph_1 = (lymph == 2) ? 1 : 0
|
||
lymph_2 = (lymph == 3) ? 1 : 0
|
||
lymph_3 = (lymph == 4) ? 1 : 0
|
||
lymph_4 = (lymph == 5) ? 1 : 0
|
||
lymph_5 = (lymph == 6) ? 1 : 0
|
||
lymph_6 = (lymph == 7) ? 1 : 0
|
||
lymph_7 = (lymph == 8) ? 1 : 0
|
||
drink_ind = (drinking == 1) ? 0 : 1
|
||
smoke_ind = (smoking == 1) ? 0 : 1
|
||
chemo = (Chemotherapy == 2) ? 1 : 0
|
||
radio = (Radiotherapy == 2) ? 1 : 0
|
||
"
|
||
field :fix_hidden_variables, type: Array, default: []
|
||
field :tmp_hidden_variables_for_ruby, type: String, default: ""
|
||
field :tmp_hidden_variables_for_js, type: String, default: ""
|
||
field :lpv_calc, type: Hash, default: {} #for js code
|
||
field :tmp_lpv_ruby_code, type: String, default: ""
|
||
field :tmp_lpv_variables, type: Array, default: []
|
||
field :mapping_data_from_csv , type: String ,default: ""
|
||
field :all_variables, type: Array, default: []
|
||
field :treatment_method, type: Array, default: ['Surgery_only']
|
||
field :treatment_method_active_indices, type: Array, default: [1]
|
||
field :result_table, type: String, default: "", localize: true
|
||
field :result_text, type: String, default: "", localize: true
|
||
field :therapy_lpv, type: Array, default: [0]
|
||
#before_create :set_expire
|
||
before_save do
|
||
self.form_show.each do |num,property|
|
||
property[:need_map_values] = (property[:map_values].class == Array && property[:choice_fields].class == Array && property[:map_values].length == property[:choice_fields].length) ? 1 : 0
|
||
end
|
||
result_keys = []
|
||
self.form_show.each do |num,property|
|
||
variable_name = property[:variable]
|
||
if variable_name.present?
|
||
result_keys << variable_name
|
||
end
|
||
end
|
||
self.form_show_in_result.each do |num,property|
|
||
variable_name = property[:variable]
|
||
if variable_name.present?
|
||
result_keys << variable_name
|
||
end
|
||
end
|
||
mapping_data = JSON.parse(self.mapping_data_from_csv) rescue {}
|
||
if self.advance_mode && mapping_data.present?
|
||
mapping_data.each do |k,v|
|
||
result_keys += (v.keys rescue [])
|
||
end
|
||
end
|
||
result_keys = result_keys.uniq
|
||
self.all_variables = result_keys
|
||
formula = text_to_math(self.prediction_formula)
|
||
tmp_hidden_variables = text_to_math(self.hidden_variables)
|
||
result_keys.each do |k|
|
||
formula = formula.gsub(/(\A|[^\w])#{k}($|[^\w])/){|f| "#{$1}result[\"#{k.strip}\"]#{$2}" }
|
||
tmp_hidden_variables = tmp_hidden_variables.gsub(/(\A|[^\w])#{k}($|[^\w])/){|f| "#{$1}result[\"#{k.strip}\"]#{$2}" }
|
||
end
|
||
self.tmp_hidden_variables_for_js = tmp_hidden_variables.rstrip.gsub(/\n\s+/,"\n ").gsub("\n",";\n") + ";"
|
||
self.fix_hidden_variables = []
|
||
self.tmp_hidden_variables_for_ruby = tmp_hidden_variables.split(/^([^=!]+)=([^=!])/).select{|s| s.present?}.each_slice(2).map do |a,b|
|
||
a = a.strip
|
||
self.fix_hidden_variables << a
|
||
if b
|
||
("result[\"#{a}\"]=" + b.gsub("\n",""))
|
||
else
|
||
a
|
||
end
|
||
end.join("\n")
|
||
self.fix_hidden_variables = self.fix_hidden_variables.uniq
|
||
formula = formula.split(/^([^=!]+)=([^=!])/).select{|s| s.present?}.each_slice(2).map do |a,b|
|
||
a = a.strip
|
||
if b
|
||
("result[\"#{a}\"]=" + b.gsub("\n",""))
|
||
else
|
||
a
|
||
end
|
||
end.join("\n")
|
||
self.fix_hidden_variables.each do |v|
|
||
formula = formula.gsub(/(\A|[^\w\"])#{v}($|[^\w])/){|f| "#{$1}result[\"#{v.strip}\"]#{$2}"}
|
||
self.tmp_hidden_variables_for_ruby = self.tmp_hidden_variables_for_ruby.gsub(/(\A|[^\w\"])#{v}($|[^\w])/){|f| "#{$1}result[\"#{v.strip}\"]#{$2}"}
|
||
end
|
||
self.tmp_lpv_ruby_code = formula
|
||
formula_variables = formula.enum_for(:scan,/([^\=\(\)]+)?=[^=]/).map {|x| x[-1] }.compact.map{|s| s.strip[8..-3]}
|
||
self.tmp_lpv_variables = formula_variables
|
||
self.tmp_years_settings = self.years_settings.map do |s|
|
||
text_to_math(s)
|
||
end
|
||
self.tmp_years_settings_for_ruby = self.tmp_years_settings.clone
|
||
formula_variables.each do |variable_name|
|
||
self.tmp_years_settings_for_ruby = self.tmp_years_settings_for_ruby.map do |y|
|
||
y.gsub(variable_name,"result[\"#{variable_name}\"]")
|
||
end
|
||
end
|
||
self.treatment_method = ['Surgery_only']
|
||
self.form_show_in_result.values.each do |choice|
|
||
variable = choice["variable"]
|
||
if variable.present?
|
||
self.treatment_method << variable
|
||
end
|
||
end
|
||
tmp_table_translations = {}
|
||
tmp_text_translations = {}
|
||
@years = self.years
|
||
@head_name = ['Treatment','Additional_Benefit','Overall_Survival']
|
||
# @head_name = ['Treatment','Overall_Survival']
|
||
@therapy_names = self.treatment_method
|
||
I18n.available_locales.each do |locale|
|
||
I18n.with_locale(locale) do
|
||
@table_head = @head_name.map{|name| I18n.t('hnc_cancer_predict.table.'+name)}
|
||
@therapy_choices = [I18n.t('hnc_cancer_predict.table.Surgeryonly')]
|
||
self.form_show_in_result.values.each{|choice| @therapy_choices.push choice["name"][locale].to_s}
|
||
tmp_table = "<span class=\"result_title print_only\">#{I18n.t("hnc_cancer_predict.table.table")}</span><div style=\"clear: both\"></div>"
|
||
tmp_table += '<input id="current_year" type="hidden" value="'+@years[-1].to_s+'" index="0"/><p id="cancer_table_texts">'+self.table_above_texts[locale].to_s+'</p>'
|
||
tmp_table += ('<a style="display: inline-block;">'+(locale.to_s == 'zh_tw' ? '第' : '')+'</a><a style="display: inline-block;">')
|
||
@years.each{|year| tmp_table += ('<button class="cancer_years cancer_table_btn btn btn-default btn-sm">'+year.to_s+'</button>')}
|
||
tmp_table += ('</a><a style="display: inline-block;">'+(locale == 'zh_tw' ? '年' : '')+'</a>')
|
||
tmp_table += '<table><thead><tr>'
|
||
@table_head.each_with_index{|head,index| tmp_table += ('<th class="cancer_th '+@head_name[index]+'">' + head + '</th>')}
|
||
tmp_table += '</tr></thead><tbody>'
|
||
@therapy_choices.each_with_index do |choice,i|
|
||
tmp_table += '<tr class="'+@therapy_names[i].to_s+'">'
|
||
@table_head.each_with_index do |head,index|
|
||
tmp_table += ('<td class="cancer_td '+ @head_name[index]+'">' + ((index == 0) ? (((i==0)? '' : '+') + choice) : '-') + '</td>')
|
||
end
|
||
tmp_table += '</tr>'
|
||
end
|
||
tmp_table_translations[locale] = tmp_table
|
||
@texts = self.text_above_texts[locale].to_s.gsub('<br/>','</span><br/><span>').gsub('{{Surgery_only}}','<span class="'+@therapy_names[0]+' Overall_Survival"></span>')
|
||
@texts = @texts.split('{{years}}')
|
||
@texts.delete('')
|
||
tmp_text = "<span class=\"result_title print_only\">#{I18n.t("hnc_cancer_predict.table.text")}</span><div style=\"clear: both\"></div>"
|
||
tmp_text += ('<span>'+@texts[0].to_s)
|
||
@years.each{|year| tmp_text += ('<button class="cancer_years cancer_table_btn btn btn-default btn-sm" style="float:none;">'+year.to_s+'</button>')}
|
||
if @texts.count > 1
|
||
tmp_text += (@texts[1]+'</span>') if @texts.count > 1
|
||
else
|
||
tmp_text += '</span>'
|
||
end
|
||
if !self.surgery_only_texts[locale].blank?
|
||
@surgery_only_texts = self.surgery_only_texts[locale]
|
||
@surgery_only_texts.insert(0,'<p class="show"><span>')
|
||
@surgery_only_texts = @surgery_only_texts.gsub('{{Surgery_only}}','<span class="'+@therapy_names[0]+' Overall_Survival"></span><span>')
|
||
@surgery_only_texts = @surgery_only_texts.gsub('{{surgery_year}}','</span><span class="surgery_year">'+@years[-1].to_s+'</span><span>')
|
||
@surgery_only_texts += '</span>'
|
||
else
|
||
@surgery_only_texts = ''
|
||
end
|
||
tmp_text += @surgery_only_texts
|
||
tmp_text += '<span class="addition">'+(self.extra_texts[locale].to_s rescue '')+'</span><div class="extra-text" style="display:none;"><div class="texts_show" style="clear:both;"></div></div></p>'
|
||
tmp_text_translations[locale] = tmp_text
|
||
end
|
||
end
|
||
self.result_table_translations = tmp_table_translations
|
||
self.result_text_translations = tmp_text_translations
|
||
self.treatment_method_active_indices = [1]
|
||
self.form_show_in_result.each do |num, property|
|
||
v = property[:active_choice]
|
||
if v.present?
|
||
self.treatment_method_active_indices << (v - 1)
|
||
else
|
||
self.treatment_method_active_indices << 1
|
||
end
|
||
end
|
||
self.lpv_calc = get_years_settings_dict
|
||
self.generate_eval_formula
|
||
end
|
||
def reload_any_asset(path, type=nil, force_reload=false)
|
||
env = Rails.application.assets
|
||
new_env = Sprockets::Environment.new(Rails.root.to_s) do |env|
|
||
env.version = ::Rails.env
|
||
tmp_path = "#{Rails.application.config.root}/tmp/cache/assets/#{::Rails.env}"
|
||
env.cache = ::Sprockets::Cache::FileStore.new(tmp_path)
|
||
env.context_class.class_eval do
|
||
include ::Sprockets::Rails::Helper
|
||
end
|
||
end
|
||
new_env.config = env.config
|
||
stats = env.cached.instance_variable_get(:@stats)
|
||
new_path = path.sub(/\.erb$/,'')
|
||
if force_reload || (stats && stats[path]) #Need reload asset
|
||
if type.nil?
|
||
ext = File.extname(new_path)
|
||
env.mime_types.each do |t, h|
|
||
if h[:extensions].include?(ext)
|
||
type = t
|
||
break
|
||
end
|
||
end
|
||
end
|
||
if type
|
||
full_path = 'file://'+path+'?type='+type
|
||
uris = env.cached.instance_variable_get(:@uris)
|
||
keys = uris.keys.select{|k| k.include?(full_path)}
|
||
asset = new_env.load(full_path)
|
||
if keys.count != 0
|
||
keys.each do |k|
|
||
uris[k] = asset
|
||
end
|
||
end
|
||
new_path = new_path.sub(/\.[^.]+$/){|ext| '-' + asset.digest + ext}
|
||
File.binwrite(new_path, asset.to_s)
|
||
yield new_path if block_given?
|
||
end
|
||
end
|
||
end
|
||
def reload_js_asset(path, force_reload=false)
|
||
reload_any_asset(path, 'application/javascript', force_reload) do |new_path|
|
||
File.open(JSFileName, 'w+'){|f| f.write(new_path)}
|
||
end
|
||
end
|
||
def generate_eval_formula
|
||
eval_hidden_variables = "def eval_hidden_variables(result); #{self.tmp_hidden_variables_for_ruby}; end"
|
||
HncCancerPredictsController.module_eval(eval_hidden_variables)
|
||
eval_formula = "def eval_formula(result); #{self.tmp_lpv_ruby_code}; end"
|
||
HncCancerPredictsController.module_eval(eval_formula)
|
||
end
|
||
def generate_jscode
|
||
js_code = "var map_values , mapping_hash , temp_index ,temp_value , index , closest_value;\r\n"
|
||
mapping_data_from_csv = JSON.parse(self.mapping_data_from_csv) rescue {}
|
||
tmp_hash = self.form_show.values + self.form_show_in_result.values
|
||
tmp_hash.each do |property|
|
||
@variable = property[:variable]
|
||
if @variable.present?
|
||
if property[:is_num] == 1
|
||
js_code += " result['#{@variable}'] = Number(result_json['#{@variable}']);\r\n"
|
||
elsif property[:choice_fields].present?
|
||
if !(self.advance_mode)
|
||
js_code += " result['#{@variable}'] = Number(result_json['#{@variable}']);\r\n"
|
||
else
|
||
if property[:need_map_values] == 1
|
||
js_code += " map_values = #{property[:map_values]};\r\n"
|
||
js_code += " result['#{@variable}'] = map_values[Number(result_json['#{@variable}'']) - 1];\r\n"
|
||
else
|
||
if property[:revert_value] != 1
|
||
js_code += " result['#{@variable}'] = Number(result_json['#{@variable}']) - 1;\r\n"
|
||
else
|
||
js_code += " result['#{@variable}'] = (#{property[:choice_fields].length} - Number(result_json['#{@variable}']));\r\n"
|
||
end
|
||
end
|
||
end
|
||
end
|
||
if self.advance_mode && property[:hnc_cancer_predict_mapping_file].present?
|
||
if (mapping_data_from_csv != {} && !mapping_data_from_csv[@variable].blank?)
|
||
js_code += " mapping_hash = mapping_data_from_csv['#{@variable}'];\r\n"
|
||
js_code += " temp_index = 0;\r\n"
|
||
js_code += " temp_value = result['#{@variable}'];\r\n"
|
||
js_code += " index = 0;
|
||
$.each(mapping_hash,function(k,v){
|
||
if( index == 0 ){
|
||
var index_val = v.indexOf(temp_value);
|
||
if( index_val != -1 ){
|
||
temp_index = index_val;
|
||
}else{
|
||
closest_value = v.get_nearest_value(temp_value);
|
||
temp_index = v.indexOf(closest_value)
|
||
}
|
||
}
|
||
result[k] = v[temp_index];
|
||
index++;
|
||
});\r\n"
|
||
end
|
||
end
|
||
end
|
||
end
|
||
js_code += "\n Object.keys(result).forEach(function(k){
|
||
if(Number.isNaN(result[k])){
|
||
result[k] = 0;
|
||
}
|
||
})"
|
||
js_code += "\n #{self.tmp_hidden_variables_for_js}"
|
||
formula = text_to_math(self.prediction_formula)
|
||
self.all_variables.each do |k|
|
||
formula = formula.gsub(/(\A|[^\w])#{k}($|[^\w])/){|f| "#{$1}result[\"#{k.strip}\"]#{$2}" }
|
||
end
|
||
formula_variables = self.tmp_lpv_variables.map{|v| v}
|
||
js_code = "\n function calculate_first_lpv(result_json){
|
||
result = {};
|
||
#{js_code}
|
||
try{
|
||
#{formula.gsub(/\s{2,10}/," ").gsub("\n","\n ")}
|
||
}catch(e){console.log(e)};
|
||
result['lpv_variable'] = {};
|
||
#{formula_variables.map{|v| "result['lpv_variable']['#{v}'] = #{v};"}.join("\n ") }
|
||
result['lpv'] = #{formula_variables.count == 0 ? 0 : formula_variables.last};
|
||
result['lpv_variable']['lpv'] = result['lpv'];
|
||
return result;
|
||
};
|
||
function calculate_and_change_result_value(obj){
|
||
obj.servive_ratio_arr = [];
|
||
for(var i = 0;i<obj.active_treatment.length;i++){
|
||
var servive_ratio = round(calculate_servive_ratio(obj.year,obj.lpv_real[i])*100,2);
|
||
var benefit = servive_ratio - obj.servive_ratio_arr[obj.servive_ratio_arr.length-1];
|
||
obj.servive_ratio_arr.push(servive_ratio);
|
||
$('tr.'+obj.active_treatment[i]+' td.Overall_Survival').html(servive_ratio+'%');
|
||
$('.'+obj.active_treatment[i]+'.Overall_Survival').html(Math.round(servive_ratio));
|
||
if(i != 0){
|
||
$('tr.'+obj.active_treatment[i]+' td.Additional_Benefit').html(round(benefit,2)+'%');
|
||
$('.'+obj.active_treatment[i]+'.Additional_Benefit').html(Math.round(benefit));
|
||
}
|
||
}
|
||
//$('.'+obj.active_treatment[0]+'.Overall_Survival').html(Math.round(obj.servive_ratio_arr[0]));
|
||
};"
|
||
@years = self.years
|
||
switch_texts = "
|
||
#{formula_variables.map{|v| "var #{v} = obj['#{v}'];"}.join("\n ")}
|
||
switch(year) {"
|
||
@years.each do |year|
|
||
year_index = @years.index(year)
|
||
switch_texts +=
|
||
"
|
||
case '#{year}':
|
||
servive_ratio = #{text_to_math(self.years_settings[year_index])};
|
||
break;"
|
||
end
|
||
switch_texts += "
|
||
default:
|
||
console.log('not found year.');
|
||
}"
|
||
js_code = js_code +"
|
||
|
||
function calculate_servive_ratio(year,obj){
|
||
var servive_ratio;#{switch_texts}
|
||
return servive_ratio;
|
||
}
|
||
"
|
||
return js_code
|
||
end
|
||
def text_to_math(text)
|
||
text.gsub("\r\n","\n").gsub('^','**').gsub('exp','Math.exp').gsub('log','Math.log')
|
||
end
|
||
def replace_str_with_idx(org_str,st, ed, replace_str)
|
||
org_str.slice!(st, ed - st + 1)
|
||
org_str.insert(st, replace_str)
|
||
org_str
|
||
end
|
||
def auto_write_predict_js(force_reload=true)
|
||
js_codes = generate_jscode
|
||
save_path = "#{ModuleAppPath}/app/assets/javascripts/#{JS}"
|
||
file_texts = File.read(save_path)
|
||
need_write = false
|
||
str1 = "/* auto add start */"
|
||
index1 = file_texts.index(str1)
|
||
str2 = "/* auto add end */"
|
||
index2 = file_texts.index(str2)
|
||
if (!index1.nil? && !index2.nil?)
|
||
file_texts = replace_str_with_idx(file_texts, index1 + str1.length, index2 - 1, js_codes)
|
||
need_write = true
|
||
end
|
||
str3 = "/*lpv_calc_formula_start*/"
|
||
index3 = file_texts.index(str3)
|
||
str4 = "/*lpv_calc_formula_end*/"
|
||
index4 = file_texts.index(str4)
|
||
if (!index3.nil? && !index4.nil?)
|
||
file_texts = replace_str_with_idx(file_texts, index3 + str3.length, index4 - 1, self.lpv_calc.to_json.gsub("@",".") + ';')
|
||
need_write = true
|
||
end
|
||
tmp_disable_jscodes = ""
|
||
str5 = "/*disable_condition start*/"
|
||
index5 = file_texts.index(str5)
|
||
str6 = "/*disable_condition end*/"
|
||
index6 = file_texts.index(str6)
|
||
self.form_show_in_result.each do |num,property|
|
||
if property[:disable_condition].present?
|
||
tmp = property[:disable_condition].clone
|
||
self.all_variables.each do |k|
|
||
tmp = tmp.gsub(/(\A|[^\w])#{k}($|[^\w])/){|f| "#{$1}post_json[\"#{k}\"]#{$2}" }
|
||
end
|
||
variable = property[:variable]
|
||
tmp_disable_jscodes += "\n if(#{tmp}){
|
||
$('##{variable} .cancer_table_btn').attr('disabled','disabled');
|
||
$('[for=\"#{variable}\"]').css('color','rgb(204, 204, 204)');
|
||
}else{
|
||
$('##{variable} .cancer_table_btn').removeAttr('disabled');
|
||
$('[for=\"#{variable}\"]').css('color','');
|
||
}"
|
||
end
|
||
end
|
||
if (!index5.nil? && !index6.nil?)
|
||
tmp_disable_jscodes += "\n\t\t\t"
|
||
file_texts = replace_str_with_idx(file_texts, index5 + str5.length, index6 - 1, tmp_disable_jscodes)
|
||
need_write = true
|
||
end
|
||
str7 = "/*therapy_lpv start*/"
|
||
index7 = file_texts.index(str7)
|
||
str8 = "/*therapy_lpv end*/"
|
||
index8 = file_texts.index(str8)
|
||
self.therapy_lpv = [0]
|
||
self.form_show_in_result.each do |num,property|
|
||
if property[:lpv_impact].present?
|
||
self.therapy_lpv << property[:lpv_impact]
|
||
else
|
||
self.therapy_lpv << 0
|
||
end
|
||
end
|
||
if (!index7.nil? && !index8.nil?)
|
||
file_texts = replace_str_with_idx(file_texts, index7 + str7.length, index8 - 1, self.therapy_lpv.to_s + ';')
|
||
need_write = true
|
||
end
|
||
if need_write
|
||
File.write(save_path,file_texts)
|
||
reload_js_asset(save_path, force_reload)
|
||
elsif !(File.exist?(JSFileName))
|
||
File.open(JSFileName, 'w+'){|f| f.write(save_path)}
|
||
end
|
||
end
|
||
def get_years_settings_dict
|
||
lpv_variable_name = (prediction_formula.include?("=") ? prediction_formula.split("=")[0].strip : "" rescue "")
|
||
res = self.years.map.with_index do |y, i|
|
||
tmp_formula = self.tmp_years_settings[i]
|
||
if lpv_variable_name.present?
|
||
tmp_formula = tmp_formula.gsub(lpv_variable_name, "lpv_current")
|
||
else
|
||
tmp_formula = tmp_formula.gsub("lpv", "lpv_current")
|
||
end
|
||
[y.to_s.sub(".","@"), tmp_formula]
|
||
end
|
||
res.to_h
|
||
end
|
||
end |