diff --git a/README.md b/README.md index 5987f8b..e053966 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,9 @@ Data source from : https://github.com/pomber/covid19 ## Features : +- Maths functions : Exp, pow, Logistic - sync X axis at a value -- reset (broken, need reload page too) +- reset - set a limit for y axis - select first and last day - select data source (confirmed, deaths, recovered) diff --git a/brain.md b/brain.md index 5f00766..51f8173 100644 --- a/brain.md +++ b/brain.md @@ -3,14 +3,7 @@ ## First production : -OK load data source -OK git clean -vuejs prod -hosting - - -Save user config to local -reset mode +User Local Presets (N) Charts modes: - Country day decal diff --git a/doc.md b/doc.md index 51cd3b1..f7122a5 100644 --- a/doc.md +++ b/doc.md @@ -3,6 +3,8 @@ # Changelog +v0.04 Fix reset +v0.03 maths functions v0.02 sync x axis v0.01 repack, data auto loading diff --git a/src/App.vue b/src/App.vue index 446abcb..ec9b7d7 100644 --- a/src/App.vue +++ b/src/App.vue @@ -106,9 +106,26 @@ ymax: 0, syncSince: 0, resetConfig: false, + math: { + exp: { + display: false, + factor: 6.5, + dayPrev: 26 + }, + pow: { + display: false, + factor: 3, + dayPrev: 5 + }, + logi: { + display: false, + factor:0.15, + dayPrev: 42 + }, + }, }, countriesConfig: { - selected: [{name: "France"}, {name: "Italy"}], + selected: [{name: "France"}, {name: "Italy"},{name:"Spain"},{name:"United Kingdom"}], basePalette: "tolRainbowColor" }, } @@ -120,13 +137,13 @@ props: { source: String, }, - data: () => ({ + data () { return { drawer: true, title: 'Cov Charts', allData: {}, chartWidth: 500, - chartConfig: defaultUserConfig.chartConfig, - countriesConfig: defaultUserConfig.countriesConfig, + chartConfig: Object.assign({},defaultUserConfig.chartConfig), + countriesConfig:Object.assign({}, defaultUserConfig.countriesConfig), configLists: { scaleList: ['log', 'linear'], typesList: ['confirmed', 'deaths', 'recovered'], @@ -137,7 +154,7 @@ //all: Object.keys(AllData).sort(), }, debug: false, - }), + }}, watch: { drawer() { console.log('dd', this.drawer) @@ -172,26 +189,108 @@ uc = JSON.parse(uc) this.countriesConfig = uc.countriesConfig this.chartConfig = uc.chartConfig - this.ccc("loadConfig storage") } else { - this.countriesConfig = defaultUserConfig.countriesConfig - this.chartConfig = defaultUserConfig.chartConfig - this.ccc("loadConfig default") + this.countriesConfig = Object.assign({},defaultUserConfig.countriesConfig) + this.chartConfig = Object.assign({},defaultUserConfig.chartConfig) } }, saveConfig() { - this.ccc("saveConfig") let userConfig = {countriesConfig: this.countriesConfig, chartConfig: this.chartConfig} localStorage.setItem('userConfig', JSON.stringify(userConfig)) }, resetConfig() { localStorage.setItem('userConfig', 'null') - this.ccc("resetConfig") this.loadConfig() }, ccc(a, b) { - if (this.debug) console.log(a, b) + if (this.debug) console.log(a, b?b:'') }, + + addMathFunctions(cdata, ymax) { + let cc = this.chartConfig.math + // Pow + if (cc.pow.display) { + cdata.push(this.calcFunction(cdata, + 'pow3', + '#ffc500', + i => limit(Math.pow(i - parseInt(cc.pow.dayPrev), parseFloat(cc.pow.factor)), 1, ymax) + )) + } + + // Exp + if (cc.exp.display) { + cdata.push(this.calcFunction(cdata, + 'exp', + '#fd1e00', + i => limit(Math.exp((i + parseInt(cc.exp.dayPrev)) / parseFloat(cc.exp.factor)), 1, ymax) + )) + } + + + if (cc.logi.display) { + // Logistic function + let L = ymax + let k = parseFloat(cc.logi.factor) + let xo = parseInt(cc.logi.dayPrev) + cdata.push(this.calcFunction(cdata, + 'logistic', + 'rgb(253,130,0)', + //i => limit(L / (1 + Math.exp(Math.E, -k*(i - xo))), 1, 60000) + i => limit(L / (1 + Math.exp(-k * (i - xo))), 0, ymax) + )) + } + + return cdata + + }, + calcFunction(cdata, name, color, callback) { + return { + country: name, + color: color, + isMaths: true, + list: cdata[0].list.map((day, id) => { + return { + confirmed: callback(id), + date: day.date + } + }) + } + + }, + calculateLog(cdata, ymax) { + + console.log(' calculateLog',) + let max = ymax + let dayDecal = 2 + + let pointsCount = cdata[0].list.length + let e = Math.log(max) + let step = e / pointsCount + + step , dayDecal; + let getY = i => { + i = i === 0 ? 0.5 : i + let value = Math.exp((i + dayDecal) * step) + //let value = Math.pow((i), 3) + + return value < max ? value : undefined + } + let pointList = cdata[0].list.map((d, i) => { + return { + confirmed: getY(i), + date: d.date + } + }) + let log = { + country: "log", + color: '#FFCC00', + list: pointList + } + cdata.push(log) + + return cdata + }, + }, computed: { syncSinceInt() { @@ -205,6 +304,7 @@ let formatedData = [] const addSomeDays = false + let ymax = 0 this.countriesConfig.selected.map((country) => { @@ -246,14 +346,19 @@ } } - // // Get ymax - // filtered.map(d => { - // ymax = d[this.dataSelected] > ymax ? d[this.dataSelected] : ymax - // }) + // Get ymax + + filtered.map(d => { + ymax = d[this.chartConfig.typeSelected] > ymax ? d[this.chartConfig.typeSelected] : ymax + }) country.list = filtered formatedData.push(country) }) + + + formatedData = this.addMathFunctions(formatedData, ymax) + return formatedData } } @@ -267,9 +372,23 @@ font-size: 12px; } - input, select, .v-input { - font-size: 12px; + input, select, .v-input, .v-label { + font-size: 13px; } + .v-list--dense .v-list-item { + min-height: 20px; + } + + .v-list--dense .v-list-item .v-list-item__content { + padding: 2px 0; + } + + .v-list-item__action{ + margin: 8px 0; + } + .v-text-field.v-text-field--solo .v-input__control { + min-height: 20px; + } diff --git a/src/components/ChartConfig.vue b/src/components/ChartConfig.vue index 45922e3..ba8f534 100644 --- a/src/components/ChartConfig.vue +++ b/src/components/ChartConfig.vue @@ -1,7 +1,7 @@ @@ -109,12 +209,11 @@ props: ['configs', 'configLists'], components: {Counter}, data() { - return { - } + return {} }, - watch:{ - 'configs.syncSince': function(value){ - if ( ! (value > 0 ) ){ + watch: { + 'configs.syncSince': function (value) { + if (!(value > 0)) { this.configs.syncSince = 0 } } @@ -124,7 +223,7 @@ this.configs.resetConfig = true } }, - computed: { } + computed: {} } @@ -139,4 +238,9 @@ max-width: 50%; } + .numFieldsm { + max-width: 50px; + } + + \ No newline at end of file diff --git a/src/components/MultiBarChartSingle.vue b/src/components/MultiBarChartSingle.vue index 5c29cc9..8998803 100644 --- a/src/components/MultiBarChartSingle.vue +++ b/src/components/MultiBarChartSingle.vue @@ -18,7 +18,7 @@
-
+
- {{value}} + {{input}}
@@ -17,18 +17,16 @@ classname: {type: String, default: 'themeGreen'}, }, data() { - return { - value: this.input, - } + return {} }, methods: { click(dirfactor) { - this.value = this.value + (dirfactor * this.inc) - if (this.value > this.max) this.value = this.max - if (this.value < this.min) this.value = this.min - this.$emit('input', this.value) + let input = this.input + (dirfactor * this.inc) + if (input > this.max) input = this.max + if (input < this.min) input = this.min + this.$emit('input', input) } - } + }, } @@ -44,16 +42,18 @@ padding: 0; width: 15px; line-height: 15px; - /*/margin: 0 px 3 px 0 px 3 px;*/ + /*/margin: 0 px 3 px 0 px 3 px;*/ } .bleft, .bright { border: 0px solid red; border-radius: 5px; } + .bleft { margin-right: 3px; } + .bright { margin-left: 3px; } @@ -61,14 +61,17 @@ .themeGreen.counter { border: 1px solid #2c3e50; background: #d3e3e0; - color:white; + color: white; } + .themeGreen.counter button { background: #d3e3e0; } + .themeGreen .bleft { border-right: 1px solid #2c3e50; } + .themeGreen .bright { border-left: 1px solid #2c3e50; } @@ -76,16 +79,19 @@ .themeGrey.counter { border: 0px solid #8ecaf9; background: inherit; - color:white; + color: white; } + .themeGrey.counter button { background: #767676; width: 18px; line-height: 18px; } + .themeGrey .bleft { border-right: 0px solid #8ecaf9; } + .themeGrey .bright { border-left: 0px solid #8ecaf9; }