Skip to content
Snippets Groups Projects
Commit 4be238b9 authored by jonschi's avatar jonschi
Browse files

allow for basic week switching

parent c251f84d
Branches
No related tags found
No related merge requests found
......@@ -11,6 +11,7 @@
"@tweenjs/tween.js": "^18.6.4",
"bulma": "^0.9.3",
"dat.gui": "^0.7.9",
"moment": "^2.29.1",
"three": "^0.124.0",
"vue": "^3.2.25",
"vue-datepicker-next": "^1.0.2"
......@@ -583,6 +584,14 @@
"sourcemap-codec": "^1.4.8"
}
},
"node_modules/moment": {
"version": "2.29.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
"integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==",
"engines": {
"node": "*"
}
},
"node_modules/nanoid": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz",
......@@ -1109,6 +1118,11 @@
"sourcemap-codec": "^1.4.8"
}
},
"moment": {
"version": "2.29.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
"integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ=="
},
"nanoid": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz",
......
......@@ -11,6 +11,7 @@
"@tweenjs/tween.js": "^18.6.4",
"bulma": "^0.9.3",
"dat.gui": "^0.7.9",
"moment": "^2.29.1",
"three": "^0.124.0",
"vue": "^3.2.25",
"vue-datepicker-next": "^1.0.2"
......
......@@ -4,14 +4,23 @@ import { loadJsonFile } from "./helpers/fileLoader";
import Globe from "./components/Globe.vue";
import Sidebar from "./components/Sidebar.vue";
import { ref } from "vue";
import { computed } from "@vue/reactivity";
import moment from 'moment'
let covidData = ref([]);
let selectedNutsCode = ref("") // TODO: start with ref to null?
moment.updateLocale("en", { week: {
dow: 1, // First day of week is Monday
doy: 4 // First week of year must contain 4 January (7 + 1 - 4)
}});
const covidData = ref({});
const selectedNutsCode = ref(null)
const selectedDate = ref(new Date()) // TODO: determine last date somehow?
const init = async function() {
covidData.value = await loadJsonFile(
"../src/assets/sample-covid-data-2022-10.json"
"../src/assets/sample-covid-data-2022-13.json"
);
selectedDate.value = new Date('2022-03-07T00:00:00.000Z')
}
const search = function() {
......@@ -23,13 +32,20 @@ const regionSelected = function(nuts) {
selectedNutsCode.value = nuts
}
const dateSelected = function(date) {
let momentDate = moment(date.toJSON())
momentDate.utc(true)
momentDate.startOf('week')
selectedDate.value = momentDate.toDate()
}
init();
</script>
<template>
<div>
<Sidebar :covid-data="covidData" :selectedNutsCode="selectedNutsCode" @search="search"/>
<Globe :covid-data=covidData @region-selected="regionSelected"/>
<Sidebar :covid-data="covidData" :selectedNutsCode="selectedNutsCode" :selected-date="selectedDate" @date-selected="dateSelected" @search="search"/>
<Globe :covid-data="covidData" :selected-date="selectedDate" @region-selected="regionSelected" />
</div>
</template>
......
This diff is collapsed.
......@@ -6,11 +6,17 @@ import { VueElement, ref } from "vue"
import { loadJsonFile } from "../helpers/fileLoader.js"
const props = defineProps({
covidData: Array
covidData: Object,
selectedDate: Date,
})
const emit = defineEmits(['regionSelected'])
watch(() => props.selectedDate, () => {
console.log("watch called")
addAllRegions()
})
// Create loaders and globally usable variables for data
const texLoader = new THREE.TextureLoader();
let geoData, covidData;
......@@ -162,7 +168,7 @@ function addRegion(shapePoints, covidDataWeek) {
// Draw all regions
function addAllRegions() {
console.log("adding all regions, length: ", props.covidData.length)
console.log("adding all regions")
if (rootObject) {
scene.remove(rootObject);
}
......@@ -172,9 +178,15 @@ function addAllRegions() {
geoData.features.forEach(function(region) {
const regionNutsCode = region.properties.NUTS_ID;
const covidDataWeek = props.covidData.find((element) => {
return element.nuts == regionNutsCode;
});
if (props.covidData == null || Object.keys(props.covidData) == 0) {
console.log("early return", props.covidData == null)
return;
}
const covidDataForDate = props.covidData[props.selectedDate.toJSON()]
if (!covidDataForDate) {
debugger
}
const covidDataWeek = covidDataForDate[regionNutsCode]
if (!covidDataWeek) {
// could not covid data but a region is available
......@@ -297,9 +309,7 @@ onMounted(async () => {
// update text, if it has a "name" field. This will contain the nuts code of the intersected region
const name = intersects[0].object.name;
if (name) {
var covidDataElement = props.covidData.find(
(element) => element.nuts == name
);
var covidDataElement = props.covidData[props.selectedDate.toJSON()][name]
tooltipString.value = `${covidDataElement.region}: ${covidDataElement.incidence}`;
}
} // else: it is the same object that is already intersected, so dont do anything
......@@ -319,10 +329,6 @@ onMounted(async () => {
geoData = await loadJsonFile("../src/assets/NUTS_RG_60M_2021_4326.geojson");
watch(props.covidData, () => {
console.log("watch called")
addAllRegions()
}, {immediate: true, deep: true})
tick();
});
</script>
......
......@@ -6,26 +6,28 @@ import DatePicker from 'vue-datepicker-next';
import 'vue-datepicker-next/index.css';
const props = defineProps({
covidData: Array,
covidData: Object,
selectedNutsCode: String,
selectedDate: Date,
});
const emit = defineEmits(['search', 'dateSelected']);
const selectedRegion = computed({
get() {
if (props.selectedNutsCode == "") return null;
if (props.covidData.length == 0) return null;
return props.covidData.find((element) => element.nuts == props.selectedNutsCode);
const covidDataForDate = props.covidData[props.selectedDate.toJSON()]
if (!covidDataForDate) {
return {}
}
const covidDataForDateAndNutsCode = covidDataForDate[props.selectedNutsCode];
if (!covidDataForDateAndNutsCode) {
return {}
}
return covidDataForDateAndNutsCode
},
});
const selectedDate = ref(new Date());
const setSelectedDate = function(date) {
const diff = date.getDate() - date.getDay() + (date.getDay() === 0 ? -6 : 1);
selectedDate.value = new Date(date.setDate(diff))
}
const emit = defineEmits(["search"]);
</script>
<template>
......@@ -43,7 +45,7 @@ const emit = defineEmits(["search"]);
</div>
</div>
<hr />
<date-picker :value="selectedDate" @change="setSelectedDate" type="week" format="DD/MM/YYYY" :clearable="false" :lang="{formatLocale: {firstDayOfWeek: 1}}"></date-picker>
<date-picker :value="selectedDate" @change="this.$emit('dateSelected', $event)" type="week" format="DD/MM/YYYY" :clearable="false" :lang="{formatLocale: {firstDayOfWeek: 1}}"></date-picker>
<hr />
<h1>selected region: {{selectedRegion == null ? "none" : selectedRegion.region}}</h1>
</div>
......
......@@ -4,13 +4,6 @@ const models = require('./models')
async function main() {
const [result, metadata] = await models.sequelize.query('select distinct date from caseweeks order by date')
const dates = result.map((element) => element.date)
console.log(JSON.stringify(dates))
// const firstDate = new Date(dates[0])
// console.log(firstDate)
// const firstCaseWeeks = await models.caseweek.findAll({where: {date: new Date(firstDate)}});
// console.log(firstCaseWeeks.length)
let output = {}
await Promise.all(dates.map(async (dateString) => {
......@@ -21,6 +14,7 @@ async function main() {
caseweeks.forEach((caseweek) => {
dateRootObject[caseweek.nuts] = caseweek
})
console.log(date, date.toJSON())
output[date.toJSON()] = dateRootObject
}))
......
......@@ -9,6 +9,7 @@
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"moment": "^2.29.1",
"pg": "^8.7.3",
"sequelize": "^6.17.0",
"sequelize-cli": "^6.4.1"
......
......@@ -11,6 +11,7 @@
"author": "jschiefner",
"license": "ISC",
"dependencies": {
"moment": "^2.29.1",
"pg": "^8.7.3",
"sequelize": "^6.17.0",
"sequelize-cli": "^6.4.1"
......
const fs = require('fs')
const { mainModule } = require('process')
const models = require('./models')
const moment = require('moment')
var file = process.env.DATA_FILE
......@@ -25,43 +27,12 @@ file.forEach(element => {
console.log("Total Objects: ", file.length)
console.log("Distribution of present data:", counter)
function firstDayOfWeek(year, week) {
// Jan 1 of 'year'
let date = new Date(year, 0, 1)
let offset = date.getTimezoneOffset()
// ISO: week 1 is the one with the year's first Thursday
// so nearest Thursday: current date + 4 - current day number
// Sunday is converted from 0 to 7
date.setDate(date.getDate() + 4 - (date.getDay() || 7))
// 7 days * (week - overlapping first week)
date.setTime(date.getTime() + 7 * 24 * 60 * 60 * 1000
* (week + (year == date.getFullYear() ? -1 : 0 )))
// daylight savings fix
date.setTime(date.getTime()
+ (date.getTimezoneOffset() - offset) * 60 * 1000)
// back to Monday (from Thursday)
date.setDate(date.getDate() - 3)
return date
}
function parseDate(dateString) {
let [year, week] = dateString.split('-')
year = parseInt(year)
week = parseInt(week)
if (year == NaN || week == NaN) {
throw new ArgumentError(`something wrong with this datestring: ${dateString}, year: ${year}, week: ${week}`)
}
return firstDayOfWeek(year, week)
const date = moment(dateString, 'YYYY-W')
date.utc(true)
return date.toDate()
}
// example from file
// {
// country: 'Sweden',
......@@ -74,15 +45,9 @@ function parseDate(dateString) {
// source: 'Epidemic intelligence subnational data'
// }
models.caseweek.findOne({order: [['date', 'DESC']]}).then((last) => {
let lastTime
if (last) {
lastTime = last.date.getTime()
} else {
lastTime = 0;
}
async function main() {
await models.caseweek.truncate()
let counter = 0;
file.forEach(element => {
const caseweek = models.caseweek.build({
......@@ -96,14 +61,14 @@ models.caseweek.findOne({order: [['date', 'DESC']]}).then((last) => {
source: element.source,
})
if (caseweek.date.getTime() > lastTime) {
caseweek.save()
counter++
}
})
console.log(`Saved ${counter} new entries`)
})
}
main()
// * To extract a specific week into a sample file:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment