diff --git a/app.js b/app.js index dae734c..1dd4e5a 100644 --- a/app.js +++ b/app.js @@ -6,58 +6,55 @@ const app = Vue.createApp({ return { cvssConfigData: cvssConfig, maxComposedData: maxComposed, - maxHammingData: maxHamming, + maxSeverityData: maxSeverity, expectedMetricOrder: expectedMetricOrder, cvssMacroVectorDetailsData: cvssMacroVectorDetails, cvssMacroVectorValuesData: cvssMacroVectorValues, showDetails: false, cvssSelected: null, header_height: 0, - enviro_default: "H", - currentLookup: cvssLookup_global, + lookup: cvssLookup_global, } }, methods: { - getvalueEqLookup(lookup,i){ - eq=parseInt(lookup[i]) - eq_val = maxComposed["eq"+String(i+1)][eq] - return eq_val + getEQMaxes(lookup, eq) { + return maxComposed["eq" + eq][lookup[eq - 1]] }, - extractValueMetric(metric,str){ - //indexOf gives first index of the metric, we then need to go over its size + extractValueMetric(metric, str) { + // indexOf gives first index of the metric, we then need to go over its size extracted = str.slice(str.indexOf(metric) + metric.length + 1) - //remove what follow - if(extracted.indexOf('/')>0) { + // remove what follow + if (extracted.indexOf('/') > 0) { metric_val = extracted.substring(0, extracted.indexOf('/')); } - else{ - //case where it is the last metric so no ending / + else { + // case where it is the last metric so no ending / metric_val = extracted } return metric_val }, - buttonClass(isPrimary, big=false) { + buttonClass(isPrimary, big = false) { result = "btn btn-m" - if(isPrimary) { + if (isPrimary) { result += " btn-primary" } - if(!big) { + if (!big) { result += " btn-sm" } return result }, - baseScoreClass(qualScore) { - if(qualScore == "Low") { + scoreClass(qualScore) { + if (qualScore == "Low") { return "c-hand text-success" } - else if(qualScore == "Medium") { + else if (qualScore == "Medium") { return "c-hand text-warning" } - else if(qualScore == "High") { + else if (qualScore == "High") { return "c-hand text-error" } - else if(qualScore == "Critical") { + else if (qualScore == "Critical") { return "c-hand text-error text-bold" } else { @@ -81,22 +78,22 @@ const app = Vue.createApp({ // Ensure compliance first toSelect = {} oi = 0 - for(index in metrics) { + for (index in metrics) { [key, value] = metrics[index].split(":") expected = Object.entries(this.expectedMetricOrder)[oi++] - while(true) { + while (true) { // If out of possible metrics ordering, it not a valid value thus // the vector is invalid - if(expected == undefined) { + if (expected == undefined) { console.log("Error invalid vector, too many metric values") return } - if(key != expected[0]) { + if (key != expected[0]) { // If not this metric but is mandatory, the vector is invalid // As the only mandatory ones are from the Base group, 11 is the // number of metrics part of it. - if(oi <= 11) { + if (oi <= 11) { console.log("Error invalid vector, missing mandatory metrics") return } @@ -107,57 +104,45 @@ const app = Vue.createApp({ break } // The value MUST be part of the metric's values, case insensitive - if(!expected[1].includes(value)) { - console.log("Error invalid vector, for key " + key + ", value " + value + " is not in " +expected[1]) + if (!expected[1].includes(value)) { + console.log("Error invalid vector, for key " + key + ", value " + value + " is not in " + expected[1]) return } - if(key in this.cvssSelected) { + if (key in this.cvssSelected) { toSelect[key] = value } } // Apply iff is compliant - for(key in toSelect) { + for (key in toSelect) { this.cvssSelected[key] = toSelect[key] } }, m(metric) { selected = this.cvssSelected[metric] - // E:X is the same as E:A - if(metric == "E" && selected == "X") { + // If E=X it will default to the worst case i.e. E=A + if (metric == "E" && selected == "X") { return "A" } - // The three security requirements metrics have X equivalent to H. - // CR:X is the same as CR:H - if(metric == "CR" && selected == "X") { - return this.enviro_default; + // If CR=X, IR=X or AR=X they will default to the worst case i.e. CR=H, IR=H and AR=H + if (metric == "CR" && selected == "X") { + return "H"; } // IR:X is the same as IR:H - if(metric == "IR" && selected == "X") { - return this.enviro_default; + if (metric == "IR" && selected == "X") { + return "H" } // AR:X is the same as AR:H - if(metric == "AR" && selected == "X") { - return this.enviro_default; - } - - // Sometimes the vector string just sets SI:S even though properly - // it should be MSI:S/ This is mostly a corner case of when people - // directly modify the string in the url. - if (metric=='MSI' && selected=='X' && this.cvssSelected['SI']=="S"){ - return "S" - } - - if (metric=='MSA' && selected=='X' && this.cvssSelected['SA']=="S"){ - return "S" + if (metric == "AR" && selected == "X") { + return "H" } // All other environmental metrics just overwrite base score values, // so if they’re not defined just use the base score value. - if(Object.keys(this.cvssSelected).includes("M" + metric)) { + if (Object.keys(this.cvssSelected).includes("M" + metric)) { modified_selected = this.cvssSelected["M" + metric] - if(modified_selected != "X") { + if (modified_selected != "X") { return modified_selected } } @@ -169,9 +154,9 @@ const app = Vue.createApp({ }, resetSelected() { this.cvssSelected = {} - for([metricType, metricTypeData] of Object.entries(this.cvssConfigData)) { - for([metricGroup, metricGroupData] of Object.entries(metricTypeData.metric_groups)) { - for([metric, metricData] of Object.entries(metricGroupData)) { + for ([metricType, metricTypeData] of Object.entries(this.cvssConfigData)) { + for ([metricGroup, metricGroupData] of Object.entries(metricTypeData.metric_groups)) { + for ([metric, metricData] of Object.entries(metricGroupData)) { this.cvssSelected[metricData.short] = metricData.selected } } @@ -180,7 +165,7 @@ const app = Vue.createApp({ splitObjectEntries(object, chunkSize) { arr = Object.entries(object) res = []; - for(let i = 0; i < arr.length; i += chunkSize) { + for (let i = 0; i < arr.length; i += chunkSize) { chunk = arr.slice(i, i + chunkSize) res.push(chunk) } @@ -190,9 +175,9 @@ const app = Vue.createApp({ computed: { vector() { value = "CVSS:4.0" - for(metric in this.expectedMetricOrder) { + for (metric in this.expectedMetricOrder) { selected = this.cvssSelected[metric] - if(selected != "X") { + if (selected != "X") { value = value.concat("/" + metric + ":" + selected) } } @@ -203,414 +188,350 @@ const app = Vue.createApp({ // 1-(AV:N or PR:N or UI:N) and not (AV:N and PR:N and UI:N) and not AV:P // 2-AV:P or not(AV:N or PR:N or UI:N) - if(this.m("AV") == "N" && this.m("PR") == "N" && this.m("UI") == "N") { + if (this.m("AV") == "N" && this.m("PR") == "N" && this.m("UI") == "N") { eq1 = "0" } - else if((this.m("AV") == "N" || this.m("PR") == "N" || this.m("UI") == "N") - && !(this.m("AV") == "N" && this.m("PR") == "N" && this.m("UI") == "N") - && !(this.m("AV") == "P")) { + else if ((this.m("AV") == "N" || this.m("PR") == "N" || this.m("UI") == "N") + && !(this.m("AV") == "N" && this.m("PR") == "N" && this.m("UI") == "N") + && !(this.m("AV") == "P")) { eq1 = "1" } - else if(this.m("AV") == "P" - || !(this.m("AV") == "N" || this.m("PR") == "N" || this.m("UI") == "N")) { + else if (this.m("AV") == "P" + || !(this.m("AV") == "N" || this.m("PR") == "N" || this.m("UI") == "N")) { eq1 = "2" } - else { - console.log("Error computing EQ1") - eq1 = 9 - } // EQ2: 0-(AC:L and AT:N) // 1-(not(AC:L and AT:N)) - if(this.m("AC") == "L" && this.m("AT") == "N") { + if (this.m("AC") == "L" && this.m("AT") == "N") { eq2 = "0" } - else if(!(this.m("AC") == "L" && this.m("AT") == "N")) { + else if (!(this.m("AC") == "L" && this.m("AT") == "N")) { eq2 = "1" } - else { - console.log("Error computing EQ2") - eq2 = 9 - } // EQ3: 0-(VC:H and VI:H) // 1-(not(VC:H and VI:H) and (VC:H or VI:H or VA:H)) // 2-not (VC:H or VI:H or VA:H) - if(this.m("VC") == "H" && this.m("VI") == "H") { + if (this.m("VC") == "H" && this.m("VI") == "H") { eq3 = 0 } - else if(!(this.m("VC") == "H" && this.m("VI") == "H") - && (this.m("VC") == "H" || this.m("VI") == "H" || this.m("VA") == "H")) { + else if (!(this.m("VC") == "H" && this.m("VI") == "H") + && (this.m("VC") == "H" || this.m("VI") == "H" || this.m("VA") == "H")) { eq3 = 1 } - else if(!(this.m("VC") == "H" || this.m("VI") == "H" || this.m("VA") == "H")) { + else if (!(this.m("VC") == "H" || this.m("VI") == "H" || this.m("VA") == "H")) { eq3 = 2 } - else { - console.log("Error computing EQ3") - eq3 = 9 - } // EQ4: 0-(MSI:S or MSA:S) - // 1-(SC:H or SI:H or SA:H and not(MSI:S or MSA:S)) - // 2-((SC:L or N) and (SI:L or N) and (SA:L or N)) + // 1-not (MSI:S or MSA:S) and (SC:H or SI:H or SA:H) + // 2-not (MSI:S or MSA:S) and not (SC:H or SI:H or SA:H) - if(this.m("MSI") == "S" || this.m("MSA") == "S") { + if (this.m("MSI") == "S" || this.m("MSA") == "S") { eq4 = 0 } - else if(this.m("SC") == "H" || this.m("SI") == "H" - || this.m("SA") == "H" && !(this.m("MSI") == "S" || this.m("MSA") == "S")) { + else if (!(this.m("MSI") == "S" || this.m("MSA") == "S") && + (this.m("SC") == "H" || this.m("SI") == "H" || this.m("SA") == "H")) { eq4 = 1 } - else if(((this.m("SC") == "L" || this.m("SC") == "N") - && (this.m("SI") == "L" || this.m("SI") == "N") - && (this.m("SA") == "L" || this.m("SA") == "N"))) { + else if (!(this.m("MSI") == "S" || this.m("MSA") == "S") && + !((this.m("SC") == "H" || this.m("SI") == "H" || this.m("SA") == "H"))) { eq4 = 2 } - else { - console.log("Error computing EQ4") - eq4 = 9 - } // EQ5: 0-E:A // 1-E:P // 2-E:U - if(this.m("E") == "A") { + if (this.m("E") == "A") { eq5 = 0 } - else if(this.m("E") == "P") { + else if (this.m("E") == "P") { eq5 = 1 } - else if(this.m("E") == "U") { + else if (this.m("E") == "U") { eq5 = 2 } - else { - console.log("Error computing EQ5") - eq5 = 9 - } // EQ6: 0-(CR:H and VC:H) or (IR:H and VI:H) or (AR:H and VA:H) // 1-not[(CR:H and VC:H) or (IR:H and VI:H) or (AR:H and VA:H)] - if((this.m("CR") == "H" && this.m("VC") == "H") - || (this.m("IR") == "H" && this.m("VI") == "H") - || (this.m("AR") == "H" && this.m("VA") == "H")) { - eq6 = 0 - } - else if(!((this.m("CR") == "H" && this.m("VC") == "H") - || (this.m("IR") == "H" && this.m("VI") == "H") - || (this.m("AR") == "H" && this.m("VA") == "H"))) { - eq6 = 1 + if ((this.m("CR") == "H" && this.m("VC") == "H") + || (this.m("IR") == "H" && this.m("VI") == "H") + || (this.m("AR") == "H" && this.m("VA") == "H")) { + eq6 = 0 } - else { - console.log("Error computing EQ6") - eq6 = 9 + else if (!((this.m("CR") == "H" && this.m("VC") == "H") + || (this.m("IR") == "H" && this.m("VI") == "H") + || (this.m("AR") == "H" && this.m("VA") == "H"))) { + eq6 = 1 } - return eq1 + eq2 + eq3 + eq4 + eq5 +eq6 + return eq1 + eq2 + eq3 + eq4 + eq5 + eq6 }, - baseScore() { - //define lookup table - lookuptable = this.currentLookup; + score() { + // The following defines the index of each metric's values. + // It is used when looking for the highest vector part of the + // combinations produced by the MacroVector respective highest vectors. + AV_levels = { "N": 0.0, "A": 0.1, "L": 0.2, "P": 0.3 } + PR_levels = { "N": 0.0, "L": 0.1, "H": 0.2 } + UI_levels = { "N": 0.0, "P": 0.1, "A": 0.2 } - AV_levels={"N": 0.0, "A": 0.1, "L": 0.2, "P": 0.3} - PR_levels={"N": 0.0, "L": 0.1, "H": 0.2} - UI_levels={"N": 0.0, "P": 0.1, "A": 0.2} + AC_levels = { 'L': 0.0, 'H': 0.1 } + AT_levels = { 'N': 0.0, 'P': 0.1 } - AC_levels={'L':0.0, 'H':0.1} - AT_levels={'N':0.0, 'P':0.1} - - VC_levels={'H':0.0, 'L':0.1, 'N':0.2} - VI_levels={'H':0.0, 'L':0.1, 'N':0.2} - VA_levels={'H':0.0, 'L':0.1, 'N':0.2} + VC_levels = { 'H': 0.0, 'L': 0.1, 'N': 0.2 } + VI_levels = { 'H': 0.0, 'L': 0.1, 'N': 0.2 } + VA_levels = { 'H': 0.0, 'L': 0.1, 'N': 0.2 } - SC_levels={'H':0.1, 'L':0.2, 'N':0.3} - SI_levels={'S':0.0, 'H':0.1, 'L':0.2, 'N':0.3} - SA_levels={'S':0.0, 'H':0.1, 'L':0.2, 'N':0.3} + SC_levels = { 'H': 0.1, 'L': 0.2, 'N': 0.3 } + SI_levels = { 'S': 0.0, 'H': 0.1, 'L': 0.2, 'N': 0.3 } + SA_levels = { 'S': 0.0, 'H': 0.1, 'L': 0.2, 'N': 0.3 } - CR_levels={'H':0.0, 'M':0.1, 'L':0.2} - IR_levels={'H':0.0, 'M':0.1, 'L':0.2} - AR_levels={'H':0.0, 'M':0.1, 'L':0.2} + CR_levels = { 'H': 0.0, 'M': 0.1, 'L': 0.2 } + IR_levels = { 'H': 0.0, 'M': 0.1, 'L': 0.2 } + AR_levels = { 'H': 0.0, 'M': 0.1, 'L': 0.2 } - E_levels={'U': 0.2, 'P': 0.1, 'A': 0} + E_levels = { 'U': 0.2, 'P': 0.1, 'A': 0 } - lookup = this.macroVector - // Exception for no impact on system - if(["VC", "VI", "VA", "SC", "SI", "SA"].every( (met) => this.m(met)=="N" )) { - return "0.0" + macroVector = this.macroVector + + // Exception for no impact on system (shortcut) + if (["VC", "VI", "VA", "SC", "SI", "SA"].every((metric) => this.m(metric) == "N")) { + return 0.0 } - value = lookuptable[lookup] + value = this.lookup[macroVector] + + // 1. For each of the EQs: + // a. The maximal scoring difference is determined as the difference + // between the current MacroVector and the lower MacroVector. + // i. If there is no lower MacroVector the available distance is + // set to NaN and then ignored in the further calculations. + eq1_val = parseInt(macroVector[0]) + eq2_val = parseInt(macroVector[1]) + eq3_val = parseInt(macroVector[2]) + eq4_val = parseInt(macroVector[3]) + eq5_val = parseInt(macroVector[4]) + eq6_val = parseInt(macroVector[5]) - eq1_val = parseInt(lookup[0]) - eq2_val = parseInt(lookup[1]) - eq3_val = parseInt(lookup[2]) - eq4_val = parseInt(lookup[3]) - eq5_val = parseInt(lookup[4]) - eq6_val = parseInt(lookup[5]) + // compute next lower macro, it can also not exist + eq1_next_lower_macro = "".concat(eq1_val + 1, eq2_val, eq3_val, eq4_val, eq5_val, eq6_val) + eq2_next_lower_macro = "".concat(eq1_val, eq2_val + 1, eq3_val, eq4_val, eq5_val, eq6_val) - //compute next lower macro, it can also not exist - eq1_next_lower_macro = "".concat(eq1_val+1,eq2_val,eq3_val,eq4_val,eq5_val,eq6_val) - eq2_next_lower_macro = "".concat(eq1_val,eq2_val+1,eq3_val,eq4_val,eq5_val,eq6_val) - - //eq3 and eq6 are related - if (eq3==1 && eq6==1){ - //11 --> 21 - eq3eq6_next_lower_macro = "".concat(eq1_val,eq2_val,eq3_val+1,eq4_val,eq5_val,eq6_val) + // eq3 and eq6 are related + if (eq3 == 1 && eq6 == 1) { + // 11 --> 21 + eq3eq6_next_lower_macro = "".concat(eq1_val, eq2_val, eq3_val + 1, eq4_val, eq5_val, eq6_val) } - else if (eq3==0 && eq6==1){ - //01 --> 11 - eq3eq6_next_lower_macro = "".concat(eq1_val,eq2_val,eq3_val+1,eq4_val,eq5_val,eq6_val) + else if (eq3 == 0 && eq6 == 1) { + // 01 --> 11 + eq3eq6_next_lower_macro = "".concat(eq1_val, eq2_val, eq3_val + 1, eq4_val, eq5_val, eq6_val) } - else if (eq3==1 && eq6==0){ - //10 --> 11 - eq3eq6_next_lower_macro = "".concat(eq1_val,eq2_val,eq3_val,eq4_val,eq5_val,eq6_val+1) + else if (eq3 == 1 && eq6 == 0) { + // 10 --> 11 + eq3eq6_next_lower_macro = "".concat(eq1_val, eq2_val, eq3_val, eq4_val, eq5_val, eq6_val + 1) } - else if (eq3==0 && eq6==0){ - //00 --> 01 - //00 --> 10 - eq3eq6_next_lower_macro_left = "".concat(eq1_val,eq2_val,eq3_val,eq4_val,eq5_val,eq6_val+1) - eq3eq6_next_lower_macro_right = "".concat(eq1_val,eq2_val,eq3_val+1,eq4_val,eq5_val,eq6_val) + else if (eq3 == 0 && eq6 == 0) { + // 00 --> 01 + // 00 --> 10 + eq3eq6_next_lower_macro_left = "".concat(eq1_val, eq2_val, eq3_val, eq4_val, eq5_val, eq6_val + 1) + eq3eq6_next_lower_macro_right = "".concat(eq1_val, eq2_val, eq3_val + 1, eq4_val, eq5_val, eq6_val) } - else{ - //21 --> 32 (do not exist) - eq3eq6_next_lower_macro = "".concat(eq1_val,eq2_val,eq3_val+1,eq4_val,eq5_val,eq6_val+1) + else { + // 21 --> 32 (do not exist) + eq3eq6_next_lower_macro = "".concat(eq1_val, eq2_val, eq3_val + 1, eq4_val, eq5_val, eq6_val + 1) } - eq4_next_lower_macro = "".concat(eq1_val,eq2_val,eq3_val,eq4_val+1,eq5_val,eq6_val) - eq5_next_lower_macro = "".concat(eq1_val,eq2_val,eq3_val,eq4_val,eq5_val+1,eq6_val) + eq4_next_lower_macro = "".concat(eq1_val, eq2_val, eq3_val, eq4_val + 1, eq5_val, eq6_val) + eq5_next_lower_macro = "".concat(eq1_val, eq2_val, eq3_val, eq4_val, eq5_val + 1, eq6_val) - //get their score, if the next lower macro score do not exist the result is NaN - score_eq1_next_lower_macro = lookuptable[eq1_next_lower_macro] - score_eq2_next_lower_macro = lookuptable[eq2_next_lower_macro] + // get their score, if the next lower macro score do not exist the result is NaN + score_eq1_next_lower_macro = this.lookup[eq1_next_lower_macro] + score_eq2_next_lower_macro = this.lookup[eq2_next_lower_macro] - if (eq3==0 && eq6==0){ - //multiple path take the one with higher score - score_eq3eq6_next_lower_macro_left = lookuptable[eq3eq6_next_lower_macro_left] - score_eq3eq6_next_lower_macro_right = lookuptable[eq3eq6_next_lower_macro_right] + if (eq3 == 0 && eq6 == 0) { + // multiple path take the one with higher score + score_eq3eq6_next_lower_macro_left = this.lookup[eq3eq6_next_lower_macro_left] + score_eq3eq6_next_lower_macro_right = this.lookup[eq3eq6_next_lower_macro_right] - if (score_eq3eq6_next_lower_macro_left>score_eq3eq6_next_lower_macro_right){ + if (score_eq3eq6_next_lower_macro_left > score_eq3eq6_next_lower_macro_right) { score_eq3eq6_next_lower_macro = score_eq3eq6_next_lower_macro_left } - else{ + else { score_eq3eq6_next_lower_macro = score_eq3eq6_next_lower_macro_right } } - else{ - score_eq3eq6_next_lower_macro = lookuptable[eq3eq6_next_lower_macro] + else { + score_eq3eq6_next_lower_macro = this.lookup[eq3eq6_next_lower_macro] } - score_eq4_next_lower_macro = lookuptable[eq4_next_lower_macro] - score_eq5_next_lower_macro = lookuptable[eq5_next_lower_macro] + score_eq4_next_lower_macro = this.lookup[eq4_next_lower_macro] + score_eq5_next_lower_macro = this.lookup[eq5_next_lower_macro] - //get all max vector for the eq - eq1_maxes = this.getvalueEqLookup(lookup,0) - eq2_maxes = this.getvalueEqLookup(lookup,1) - eq3_eq6_maxes = this.getvalueEqLookup(lookup,2)[lookup[5]] - eq4_maxes = this.getvalueEqLookup(lookup,3) - eq5_maxes = this.getvalueEqLookup(lookup,4) + // b. The severity distance of the to-be scored vector from a + // highest severity vector in the same MacroVector is determined. + eq1_maxes = this.getEQMaxes(macroVector, 1) + eq2_maxes = this.getEQMaxes(macroVector, 2) + eq3_eq6_maxes = this.getEQMaxes(macroVector, 3)[macroVector[5]] + eq4_maxes = this.getEQMaxes(macroVector, 4) + eq5_maxes = this.getEQMaxes(macroVector, 5) - //compose them + // compose them max_vectors = [] - for (eq1_max of eq1_maxes){ - for (eq2_max of eq2_maxes){ - for (eq3_eq6_max of eq3_eq6_maxes){ - for (eq4_max of eq4_maxes){ - for (eq5max of eq5_maxes){ - max_vectors.push(eq1_max+eq2_max+eq3_eq6_max+eq4_max+eq5max) + for (eq1_max of eq1_maxes) { + for (eq2_max of eq2_maxes) { + for (eq3_eq6_max of eq3_eq6_maxes) { + for (eq4_max of eq4_maxes) { + for (eq5max of eq5_maxes) { + max_vectors.push(eq1_max + eq2_max + eq3_eq6_max + eq4_max + eq5max) } } } } } - if (max_vectors==undefined){ - return "0.0" - } - - // compute hamming distance + // Find the max vector to use i.e. one in the combination of all the highests + // that is greater or equal (severity distance) than the to-be scored vector. for (let i = 0; i < max_vectors.length; i++) { - tmp_vector = max_vectors[i] - //cannot have a negative distance if less than max - hamming_distance_AV = AV_levels[this.m("AV")]-AV_levels[this.extractValueMetric("AV",tmp_vector)] - hamming_distance_PR = PR_levels[this.m("PR")]-PR_levels[this.extractValueMetric("PR",tmp_vector)] - hamming_distance_UI = UI_levels[this.m("UI")]-UI_levels[this.extractValueMetric("UI",tmp_vector)] + max_vector = max_vectors[i] + severity_distance_AV = AV_levels[this.m("AV")] - AV_levels[this.extractValueMetric("AV", max_vector)] + severity_distance_PR = PR_levels[this.m("PR")] - PR_levels[this.extractValueMetric("PR", max_vector)] + severity_distance_UI = UI_levels[this.m("UI")] - UI_levels[this.extractValueMetric("UI", max_vector)] - hamming_distance_AC = AC_levels[this.m("AC")]-AC_levels[this.extractValueMetric("AC",tmp_vector)] - hamming_distance_AT = AT_levels[this.m("AT")]-AT_levels[this.extractValueMetric("AT",tmp_vector)] + severity_distance_AC = AC_levels[this.m("AC")] - AC_levels[this.extractValueMetric("AC", max_vector)] + severity_distance_AT = AT_levels[this.m("AT")] - AT_levels[this.extractValueMetric("AT", max_vector)] - hamming_distance_VC = VC_levels[this.m("VC")]-VC_levels[this.extractValueMetric("VC",tmp_vector)] - hamming_distance_VI = VI_levels[this.m("VI")]-VI_levels[this.extractValueMetric("VI",tmp_vector)] - hamming_distance_VA = VA_levels[this.m("VA")]-VA_levels[this.extractValueMetric("VA",tmp_vector)] + severity_distance_VC = VC_levels[this.m("VC")] - VC_levels[this.extractValueMetric("VC", max_vector)] + severity_distance_VI = VI_levels[this.m("VI")] - VI_levels[this.extractValueMetric("VI", max_vector)] + severity_distance_VA = VA_levels[this.m("VA")] - VA_levels[this.extractValueMetric("VA", max_vector)] + severity_distance_SC = SC_levels[this.m("SC")] - SC_levels[this.extractValueMetric("SC", max_vector)] + severity_distance_SI = SI_levels[this.m("SI")] - SI_levels[this.extractValueMetric("SI", max_vector)] + severity_distance_SA = SA_levels[this.m("SA")] - SA_levels[this.extractValueMetric("SA", max_vector)] - if(this.m("MSI") == "S" && this.m("MSA")=="S"){ - //use MSI and MSA - hamming_distance_SI = SI_levels[this.m("MSI")]-SI_levels[this.extractValueMetric("SI",tmp_vector)] - hamming_distance_SA = SA_levels[this.m("MSA")]-SA_levels[this.extractValueMetric("SA",tmp_vector)] - } - else if (this.m("MSI") == "S"){ - //only MSI set to S - hamming_distance_SI = SI_levels[this.m("MSI")]-SI_levels[this.extractValueMetric("SI",tmp_vector)] - hamming_distance_SA = SA_levels[this.m("SA")]-SA_levels[this.extractValueMetric("SA",tmp_vector)] - } - else if(this.m("MSA") == "S"){ - //only MSA set to S - hamming_distance_SI = SI_levels[this.m("SI")]-SI_levels[this.extractValueMetric("SI",tmp_vector)] - hamming_distance_SA = SA_levels[this.m("MSA")]-SA_levels[this.extractValueMetric("SA",tmp_vector)] - } - else { - //none set to S - hamming_distance_SI = SI_levels[this.m("SI")]-SI_levels[this.extractValueMetric("SI",tmp_vector)] - hamming_distance_SA = SA_levels[this.m("SA")]-SA_levels[this.extractValueMetric("SA",tmp_vector)] - } - hamming_distance_SC = SC_levels[this.m("SC")]-SC_levels[this.extractValueMetric("SC",tmp_vector)] - - hamming_distance_CR = CR_levels[this.m("CR")]-CR_levels[this.extractValueMetric("CR",tmp_vector)] - hamming_distance_IR = IR_levels[this.m("IR")]-IR_levels[this.extractValueMetric("IR",tmp_vector)] - hamming_distance_AR = AR_levels[this.m("AR")]-AR_levels[this.extractValueMetric("AR",tmp_vector)] + severity_distance_CR = CR_levels[this.m("CR")] - CR_levels[this.extractValueMetric("CR", max_vector)] + severity_distance_IR = IR_levels[this.m("IR")] - IR_levels[this.extractValueMetric("IR", max_vector)] + severity_distance_AR = AR_levels[this.m("AR")] - AR_levels[this.extractValueMetric("AR", max_vector)] - //if any is less than zero this is not the right max - if (hamming_distance_AV<0 || hamming_distance_PR<0 || hamming_distance_UI<0 || hamming_distance_AC<0 || hamming_distance_AT<0 || hamming_distance_VC<0 || hamming_distance_VI<0 || hamming_distance_VA<0 || hamming_distance_SC<0 || hamming_distance_SI<0 || hamming_distance_SA<0 || hamming_distance_CR<0 || hamming_distance_IR<0 || hamming_distance_AR<0) { + // if any is less than zero this is not the right max + if ([severity_distance_AV, severity_distance_PR, severity_distance_UI, severity_distance_AC, severity_distance_AT, severity_distance_VC, severity_distance_VI, severity_distance_VA, severity_distance_SC, severity_distance_SI, severity_distance_SA, severity_distance_CR, severity_distance_IR, severity_distance_AR].some((met) => met < 0)) { continue } - else{ - //if multiple maxes exist to reach it it is enough the first one - break - } + // if multiple maxes exist to reach it it is enough the first one + break } - - - current_hamming_distance_eq1 = hamming_distance_AV + hamming_distance_PR + hamming_distance_UI - current_hamming_distance_eq2 = hamming_distance_AC + hamming_distance_AT - current_hamming_distance_eq3eq6 = hamming_distance_VC + hamming_distance_VI + hamming_distance_VA + hamming_distance_CR + hamming_distance_IR + hamming_distance_AR - current_hamming_distance_eq4 = hamming_distance_SC + hamming_distance_SI + hamming_distance_SA - current_hamming_distance_eq5 = 0 - + current_severity_distance_eq1 = severity_distance_AV + severity_distance_PR + severity_distance_UI + current_severity_distance_eq2 = severity_distance_AC + severity_distance_AT + current_severity_distance_eq3eq6 = severity_distance_VC + severity_distance_VI + severity_distance_VA + severity_distance_CR + severity_distance_IR + severity_distance_AR + current_severity_distance_eq4 = severity_distance_SC + severity_distance_SI + severity_distance_SA + current_severity_distance_eq5 = 0 step = 0.1 - //if the next lower macro score do not exist the result is Nan + // if the next lower macro score do not exist the result is Nan + // Rename to maximal scoring difference (aka MSD) available_distance_eq1 = value - score_eq1_next_lower_macro available_distance_eq2 = value - score_eq2_next_lower_macro available_distance_eq3eq6 = value - score_eq3eq6_next_lower_macro available_distance_eq4 = value - score_eq4_next_lower_macro available_distance_eq5 = value - score_eq5_next_lower_macro + percent_to_next_eq1_severity = 0 + percent_to_next_eq2_severity = 0 + percent_to_next_eq3eq6_severity = 0 + percent_to_next_eq4_severity = 0 + percent_to_next_eq5_severity = 0 - percent_to_next_eq1_hamming = 0 - percent_to_next_eq2_hamming = 0 - percent_to_next_eq3eq6_hamming = 0 - percent_to_next_eq4_hamming = 0 - percent_to_next_eq5_hamming = 0 - - - //some of them do not exist, we will find them by retrieving the score. If score null then do not exist + // some of them do not exist, we will find them by retrieving the score. If score null then do not exist n_existing_lower = 0 - normalized_hamming_eq1 = 0 - normalized_hamming_eq2 = 0 - normalized_hamming_eq3eq6 = 0 - normalized_hamming_eq4 = 0 - normalized_hamming_eq5 = 0 - - //multiply by step because distance is pure - maxHamming_eq1 = this.maxHammingData['eq1'][String(eq1_val)]*step - maxHamming_eq2 = this.maxHammingData['eq2'][String(eq2_val)]*step - maxHamming_eq3eq6 = this.maxHammingData['eq3'][String(eq3_val)][String(eq6_val)]*step - maxHamming_eq4 = this.maxHammingData['eq4'][String(eq4_val)]*step - - if (!isNaN(available_distance_eq1)){ - n_existing_lower=n_existing_lower+1 - percent_to_next_eq1_hamming = (current_hamming_distance_eq1)/maxHamming_eq1 - //can be nan if divided by zero - if(isNaN(percent_to_next_eq1_hamming)){ - percent_to_next_eq1_hamming=0 - } + normalized_severity_eq1 = 0 + normalized_severity_eq2 = 0 + normalized_severity_eq3eq6 = 0 + normalized_severity_eq4 = 0 + normalized_severity_eq5 = 0 - normalized_hamming_eq1 = available_distance_eq1*percent_to_next_eq1_hamming - + // multiply by step because distance is pure + maxSeverity_eq1 = this.maxSeverityData["eq1"][eq1_val] * step + maxSeverity_eq2 = this.maxSeverityData["eq2"][eq2_val] * step + maxSeverity_eq3eq6 = this.maxSeverityData["eq3eq6"][eq3_val][eq6_val] * step + maxSeverity_eq4 = this.maxSeverityData["eq4"][eq4_val] * step + + // c. The proportion of the distance is determined by dividing + // the severity distance of the to-be-scored vector by the depth + // of the MacroVector. + // d. The maximal scoring difference is multiplied by the proportion of + // distance. + if (!isNaN(available_distance_eq1)) { + n_existing_lower = n_existing_lower + 1 + percent_to_next_eq1_severity = (current_severity_distance_eq1) / maxSeverity_eq1 + normalized_severity_eq1 = available_distance_eq1 * percent_to_next_eq1_severity } - if (!isNaN(available_distance_eq2)){ - n_existing_lower=n_existing_lower+1 - percent_to_next_eq2_hamming = (current_hamming_distance_eq2)/maxHamming_eq2 - if(isNaN(percent_to_next_eq2_hamming)){ - percent_to_next_eq2_hamming=0 - } - - normalized_hamming_eq2 = available_distance_eq2*percent_to_next_eq2_hamming + if (!isNaN(available_distance_eq2)) { + n_existing_lower = n_existing_lower + 1 + percent_to_next_eq2_severity = (current_severity_distance_eq2) / maxSeverity_eq2 + normalized_severity_eq2 = available_distance_eq2 * percent_to_next_eq2_severity } - if (!isNaN(available_distance_eq3eq6)){ - n_existing_lower=n_existing_lower+1 - percent_to_next_eq3eq6_hamming = (current_hamming_distance_eq3eq6)/maxHamming_eq3eq6 - if(isNaN(percent_to_next_eq3eq6_hamming)){ - percent_to_next_eq3eq6_hamming=0 - } - - normalized_hamming_eq3eq6 = available_distance_eq3eq6*percent_to_next_eq3eq6_hamming + if (!isNaN(available_distance_eq3eq6)) { + n_existing_lower = n_existing_lower + 1 + percent_to_next_eq3eq6_severity = (current_severity_distance_eq3eq6) / maxSeverity_eq3eq6 + normalized_severity_eq3eq6 = available_distance_eq3eq6 * percent_to_next_eq3eq6_severity } - if (!isNaN(available_distance_eq4)){ - n_existing_lower=n_existing_lower+1 - percent_to_next_eq4_hamming = (current_hamming_distance_eq4)/maxHamming_eq4 - if(isNaN(percent_to_next_eq4_hamming)){ - percent_to_next_eq4_hamming=0 - } - - normalized_hamming_eq4 = available_distance_eq4*percent_to_next_eq4_hamming + if (!isNaN(available_distance_eq4)) { + n_existing_lower = n_existing_lower + 1 + percent_to_next_eq4_severity = (current_severity_distance_eq4) / maxSeverity_eq4 + normalized_severity_eq4 = available_distance_eq4 * percent_to_next_eq4_severity } - if (!isNaN(available_distance_eq5)){ - //for eq5 is always 0 the percentage - n_existing_lower=n_existing_lower+1 - percent_to_next_eq5_hamming = 0 - if(isNaN(percent_to_next_eq5_hamming)){ - percent_to_next_eq5_hamming=0 - } - - normalized_hamming_eq5 = available_distance_eq5*percent_to_next_eq5_hamming + if (!isNaN(available_distance_eq5)) { + // for eq5 is always 0 the percentage + n_existing_lower = n_existing_lower + 1 + percent_to_next_eq5_severity = 0 + normalized_severity_eq5 = available_distance_eq5 * percent_to_next_eq5_severity } - if (n_existing_lower==0) { + // 2. The mean of the above computed proportional distances is computed. + if (n_existing_lower == 0) { mean_distance = 0 - } else { //sometimes we need to go up but there is nothing there, or down but there is nothing there so it's a change of 0. - mean_distance = (normalized_hamming_eq1+normalized_hamming_eq2+normalized_hamming_eq3eq6+normalized_hamming_eq4+normalized_hamming_eq5)/n_existing_lower + } else { // sometimes we need to go up but there is nothing there, or down but there is nothing there so it's a change of 0. + mean_distance = (normalized_severity_eq1 + normalized_severity_eq2 + normalized_severity_eq3eq6 + normalized_severity_eq4 + normalized_severity_eq5) / n_existing_lower } - value = parseFloat(value) - parseFloat(mean_distance); - - - if(value<0){ + // 3. The score of the vector is the score of the MacroVector + // (i.e. the score of the highest severity vector) minus the mean + // distance so computed. This score is rounded to one decimal place. + value -= mean_distance; + if (value < 0) { value = 0.0 } - - if(value>10){ + if (value > 10) { value = 10.0 } - return value.toFixed(1) }, qualScore() { - if(this.baseScore == 0) { + if (this.score == 0) { return "None" } - else if(this.baseScore < 4.0) { + else if (this.score < 4.0) { return "Low" } - else if(this.baseScore < 7.0) { + else if (this.score < 7.0) { return "Medium" } - else if(this.baseScore < 9.0) { + else if (this.score < 9.0) { return "High" } else { @@ -628,7 +549,6 @@ const app = Vue.createApp({ }) const resizeObserver = new ResizeObserver(() => { - //console.log("Size changed") this.header_height = document.getElementById('header').clientHeight }) diff --git a/cvss_config.js b/cvss_config.js index f70468d..f98571f 100644 --- a/cvss_config.js +++ b/cvss_config.js @@ -731,4 +731,4 @@ cvssConfig = { } } } -} \ No newline at end of file +} diff --git a/cvss_lookup.js b/cvss_lookup.js index 4511064..aecacfc 100644 --- a/cvss_lookup.js +++ b/cvss_lookup.js @@ -2,274 +2,274 @@ // SPDX-License-Identifier: BSD-2-Clause cvssLookup_global = { - "000000": "10", - "000001": "9.9", - "000010": "9.8", - "000011": "9.5", - "000020": "9.5", - "000021": "9.2", - "000100": "10", - "000101": "9.6", - "000110": "9.3", - "000111": "8.7", - "000120": "9.1", - "000121": "8.1", - "000200": "9.3", - "000201": "9", - "000210": "8.9", - "000211": "8", - "000220": "8.1", - "000221": "6.8", - "001000": "9.8", - "001001": "9.5", - "001010": "9.5", - "001011": "9.2", - "001020": "9", - "001021": "8.4", - "001100": "9.3", - "001101": "9.2", - "001110": "8.9", - "001111": "8.1", - "001120": "8.1", - "001121": "6.5", - "001200": "8.8", - "001201": "8", - "001210": "7.8", - "001211": "7", - "001220": "6.9", - "001221": "4.8", - "002001": "9.2", - "002011": "8.2", - "002021": "7.2", - "002101": "7.9", - "002111": "6.9", - "002121": "5", - "002201": "6.9", - "002211": "5.5", - "002221": "2.7", - "010000": "9.9", - "010001": "9.7", - "010010": "9.5", - "010011": "9.2", - "010020": "9.2", - "010021": "8.5", - "010100": "9.5", - "010101": "9.1", - "010110": "9", - "010111": "8.3", - "010120": "8.4", - "010121": "7.1", - "010200": "9.2", - "010201": "8.1", - "010210": "8.2", - "010211": "7.1", - "010220": "7.2", - "010221": "5.3", - "011000": "9.5", - "011001": "9.3", - "011010": "9.2", - "011011": "8.5", - "011020": "8.5", - "011021": "7.3", - "011100": "9.2", - "011101": "8.2", - "011110": "8", - "011111": "7.2", - "011120": "7", - "011121": "5.9", - "011200": "8.4", - "011201": "7", - "011210": "7.1", - "011211": "5.2", - "011220": "5", - "011221": "3", - "012001": "8.6", - "012011": "7.5", - "012021": "5.2", - "012101": "7.1", - "012111": "5.2", - "012121": "2.9", - "012201": "6.3", - "012211": "2.9", - "012221": "1.7", - "100000": "9.8", - "100001": "9.5", - "100010": "9.4", - "100011": "8.7", - "100020": "9.1", - "100021": "8.1", - "100100": "9.4", - "100101": "8.9", - "100110": "8.6", - "100111": "7.4", - "100120": "7.7", - "100121": "6.4", - "100200": "8.7", - "100201": "7.5", - "100210": "7.4", - "100211": "6.3", - "100220": "6.3", - "100221": "4.9", - "101000": "9.4", - "101001": "8.9", - "101010": "8.8", - "101011": "7.7", - "101020": "7.6", - "101021": "6.7", - "101100": "8.6", - "101101": "7.6", - "101110": "7.4", - "101111": "5.8", - "101120": "5.9", - "101121": "5", - "101200": "7.2", - "101201": "5.7", - "101210": "5.7", - "101211": "5.2", - "101220": "5.2", - "101221": "2.5", - "102001": "8.3", - "102011": "7", - "102021": "5.4", - "102101": "6.5", - "102111": "5.8", - "102121": "2.6", - "102201": "5.3", - "102211": "2.1", - "102221": "1.3", - "110000": "9.5", - "110001": "9", - "110010": "8.8", - "110011": "7.6", - "110020": "7.6", - "110021": "7", - "110100": "9", - "110101": "7.7", - "110110": "7.5", - "110111": "6.2", - "110120": "6.1", - "110121": "5.3", - "110200": "7.7", - "110201": "6.6", - "110210": "6.8", - "110211": "5.9", - "110220": "5.2", - "110221": "3", - "111000": "8.9", - "111001": "7.8", - "111010": "7.6", - "111011": "6.7", - "111020": "6.2", - "111021": "5.8", - "111100": "7.4", - "111101": "5.9", - "111110": "5.7", - "111111": "5.7", - "111120": "4.7", - "111121": "2.3", - "111200": "6.1", - "111201": "5.2", - "111210": "5.7", - "111211": "2.9", - "111220": "2.4", - "111221": "1.6", - "112001": "7.1", - "112011": "5.9", - "112021": "3", - "112101": "5.8", - "112111": "2.6", - "112121": "1.5", - "112201": "2.3", - "112211": "1.3", - "112221": "0.6", - "200000": "9.3", - "200001": "8.7", - "200010": "8.6", - "200011": "7.2", - "200020": "7.5", - "200021": "5.8", - "200100": "8.6", - "200101": "7.4", - "200110": "7.4", - "200111": "6.1", - "200120": "5.6", - "200121": "3.4", - "200200": "7", - "200201": "5.4", - "200210": "5.2", - "200211": "4", - "200220": "4", - "200221": "2.2", - "201000": "8.5", - "201001": "7.5", - "201010": "7.4", - "201011": "5.5", - "201020": "6.2", - "201021": "5.1", - "201100": "7.2", - "201101": "5.7", - "201110": "5.5", - "201111": "4.1", - "201120": "4.6", - "201121": "1.9", - "201200": "5.3", - "201201": "3.6", - "201210": "3.4", - "201211": "1.9", - "201220": "1.9", - "201221": "0.8", - "202001": "6.4", - "202011": "5.1", - "202021": "2", - "202101": "4.7", - "202111": "2.1", - "202121": "1.1", - "202201": "2.4", - "202211": "0.9", - "202221": "0.4", - "210000": "8.8", - "210001": "7.5", - "210010": "7.3", - "210011": "5.3", - "210020": "6", - "210021": "5", - "210100": "7.3", - "210101": "5.5", - "210110": "5.9", - "210111": "4", - "210120": "4.1", - "210121": "2", - "210200": "5.4", - "210201": "4.3", - "210210": "4.5", - "210211": "2.2", - "210220": "2", - "210221": "1.1", - "211000": "7.5", - "211001": "5.5", - "211010": "5.8", - "211011": "4.5", - "211020": "4", - "211021": "2.1", - "211100": "6.1", - "211101": "5.1", - "211110": "4.8", - "211111": "1.8", - "211120": "2", - "211121": "0.9", - "211200": "4.6", - "211201": "1.8", - "211210": "1.7", - "211211": "0.7", - "211220": "0.8", - "211221": "0.2", - "212001": "5.3", - "212011": "2.4", - "212021": "1.4", - "212101": "2.4", - "212111": "1.2", - "212121": "0.5", - "212201": "1", - "212211": "0.3", - "212221": "0.1" -} \ No newline at end of file + "000000": 10, + "000001": 9.9, + "000010": 9.8, + "000011": 9.5, + "000020": 9.5, + "000021": 9.2, + "000100": 10, + "000101": 9.6, + "000110": 9.3, + "000111": 8.7, + "000120": 9.1, + "000121": 8.1, + "000200": 9.3, + "000201": 9, + "000210": 8.9, + "000211": 8, + "000220": 8.1, + "000221": 6.8, + "001000": 9.8, + "001001": 9.5, + "001010": 9.5, + "001011": 9.2, + "001020": 9, + "001021": 8.4, + "001100": 9.3, + "001101": 9.2, + "001110": 8.9, + "001111": 8.1, + "001120": 8.1, + "001121": 6.5, + "001200": 8.8, + "001201": 8, + "001210": 7.8, + "001211": 7, + "001220": 6.9, + "001221": 4.8, + "002001": 9.2, + "002011": 8.2, + "002021": 7.2, + "002101": 7.9, + "002111": 6.9, + "002121": 5, + "002201": 6.9, + "002211": 5.5, + "002221": 2.7, + "010000": 9.9, + "010001": 9.7, + "010010": 9.5, + "010011": 9.2, + "010020": 9.2, + "010021": 8.5, + "010100": 9.5, + "010101": 9.1, + "010110": 9, + "010111": 8.3, + "010120": 8.4, + "010121": 7.1, + "010200": 9.2, + "010201": 8.1, + "010210": 8.2, + "010211": 7.1, + "010220": 7.2, + "010221": 5.3, + "011000": 9.5, + "011001": 9.3, + "011010": 9.2, + "011011": 8.5, + "011020": 8.5, + "011021": 7.3, + "011100": 9.2, + "011101": 8.2, + "011110": 8, + "011111": 7.2, + "011120": 7, + "011121": 5.9, + "011200": 8.4, + "011201": 7, + "011210": 7.1, + "011211": 5.2, + "011220": 5, + "011221": 3, + "012001": 8.6, + "012011": 7.5, + "012021": 5.2, + "012101": 7.1, + "012111": 5.2, + "012121": 2.9, + "012201": 6.3, + "012211": 2.9, + "012221": 1.7, + "100000": 9.8, + "100001": 9.5, + "100010": 9.4, + "100011": 8.7, + "100020": 9.1, + "100021": 8.1, + "100100": 9.4, + "100101": 8.9, + "100110": 8.6, + "100111": 7.4, + "100120": 7.7, + "100121": 6.4, + "100200": 8.7, + "100201": 7.5, + "100210": 7.4, + "100211": 6.3, + "100220": 6.3, + "100221": 4.9, + "101000": 9.4, + "101001": 8.9, + "101010": 8.8, + "101011": 7.7, + "101020": 7.6, + "101021": 6.7, + "101100": 8.6, + "101101": 7.6, + "101110": 7.4, + "101111": 5.8, + "101120": 5.9, + "101121": 5, + "101200": 7.2, + "101201": 5.7, + "101210": 5.7, + "101211": 5.2, + "101220": 5.2, + "101221": 2.5, + "102001": 8.3, + "102011": 7, + "102021": 5.4, + "102101": 6.5, + "102111": 5.8, + "102121": 2.6, + "102201": 5.3, + "102211": 2.1, + "102221": 1.3, + "110000": 9.5, + "110001": 9, + "110010": 8.8, + "110011": 7.6, + "110020": 7.6, + "110021": 7, + "110100": 9, + "110101": 7.7, + "110110": 7.5, + "110111": 6.2, + "110120": 6.1, + "110121": 5.3, + "110200": 7.7, + "110201": 6.6, + "110210": 6.8, + "110211": 5.9, + "110220": 5.2, + "110221": 3, + "111000": 8.9, + "111001": 7.8, + "111010": 7.6, + "111011": 6.7, + "111020": 6.2, + "111021": 5.8, + "111100": 7.4, + "111101": 5.9, + "111110": 5.7, + "111111": 5.7, + "111120": 4.7, + "111121": 2.3, + "111200": 6.1, + "111201": 5.2, + "111210": 5.7, + "111211": 2.9, + "111220": 2.4, + "111221": 1.6, + "112001": 7.1, + "112011": 5.9, + "112021": 3, + "112101": 5.8, + "112111": 2.6, + "112121": 1.5, + "112201": 2.3, + "112211": 1.3, + "112221": 0.6, + "200000": 9.3, + "200001": 8.7, + "200010": 8.6, + "200011": 7.2, + "200020": 7.5, + "200021": 5.8, + "200100": 8.6, + "200101": 7.4, + "200110": 7.4, + "200111": 6.1, + "200120": 5.6, + "200121": 3.4, + "200200": 7, + "200201": 5.4, + "200210": 5.2, + "200211": 4, + "200220": 4, + "200221": 2.2, + "201000": 8.5, + "201001": 7.5, + "201010": 7.4, + "201011": 5.5, + "201020": 6.2, + "201021": 5.1, + "201100": 7.2, + "201101": 5.7, + "201110": 5.5, + "201111": 4.1, + "201120": 4.6, + "201121": 1.9, + "201200": 5.3, + "201201": 3.6, + "201210": 3.4, + "201211": 1.9, + "201220": 1.9, + "201221": 0.8, + "202001": 6.4, + "202011": 5.1, + "202021": 2, + "202101": 4.7, + "202111": 2.1, + "202121": 1.1, + "202201": 2.4, + "202211": 0.9, + "202221": 0.4, + "210000": 8.8, + "210001": 7.5, + "210010": 7.3, + "210011": 5.3, + "210020": 6, + "210021": 5, + "210100": 7.3, + "210101": 5.5, + "210110": 5.9, + "210111": 4, + "210120": 4.1, + "210121": 2, + "210200": 5.4, + "210201": 4.3, + "210210": 4.5, + "210211": 2.2, + "210220": 2, + "210221": 1.1, + "211000": 7.5, + "211001": 5.5, + "211010": 5.8, + "211011": 4.5, + "211020": 4, + "211021": 2.1, + "211100": 6.1, + "211101": 5.1, + "211110": 4.8, + "211111": 1.8, + "211120": 2, + "211121": 0.9, + "211200": 4.6, + "211201": 1.8, + "211210": 1.7, + "211211": 0.7, + "211220": 0.8, + "211221": 0.2, + "212001": 5.3, + "212011": 2.4, + "212021": 1.4, + "212101": 2.4, + "212111": 1.2, + "212121": 0.5, + "212201": 1, + "212211": 0.3, + "212221": 0.1, +} diff --git a/index.html b/index.html index 810d9a1..5d72b95 100644 --- a/index.html +++ b/index.html @@ -33,7 +33,7 @@ - + @@ -54,7 +54,7 @@