Parcourir la source

Segmented experiment in multiple components. Progression backup working

rigwild il y a 4 ans
Parent
commit
1db128ebad

+ 1 - 1
src/functions.js

@@ -23,7 +23,7 @@ export const delay = ms => new Promise(res => setTimeout(res, ms))
 export const buildURI = (ssl, host, port, route = '') => `${ssl ? 'https' : 'http'}://${host}:${port}${route}`
 export const buildWsURI = (ssl, host, port, uuid = '') => `${ssl ? 'wss' : 'ws'}://${host}:${port}?uuid=${uuid}`
 
-export const sortIntArray = intArray => intArray.sort((a, b) => a - b)
+export const sortIntArray = intArray => intArray ? intArray.sort((a, b) => a - b) : null
 
 export const findNearestUpper = (value, arrInt) => {
   const arr = sortIntArray(arrInt)

+ 56 - 0
src/mixins/ExperimentBase.vue

@@ -0,0 +1,56 @@
+<script>
+import { mapGetters, mapActions } from 'vuex'
+import { API_ROUTES } from '@/functions'
+
+export default {
+  props: {
+    sceneName: {
+      type: String,
+      required: true
+    }
+  },
+  data() {
+    return {
+      experimentName: null, // Must be redefined in parent component
+
+      loadingMessage: null,
+      loadingErrorMessage: null,
+      qualities: null
+    }
+  },
+  computed: {
+    ...mapGetters(['getHostURI', 'getExperimentProgress'])
+  },
+  methods: {
+    ...mapActions(['setExperimentProgress']),
+
+    // Load progress from store into local state
+    loadProgress() {
+      if (!this.experimentName || !this.sceneName)
+        console.warn('Could not load progress : experimentName and sceneName must be defined')
+
+      const progress = this.getExperimentProgress({ experimentName: this.experimentName, sceneName: this.sceneName })
+      Object.assign(this.$data, progress)
+      console.log('Loaded data from store to local state.', progress)
+    },
+
+    // Save progress from local state into store
+    saveProgress() {
+      if (!this.experimentName || !this.sceneName)
+        console.warn('Could not load progress : experimentName and sceneName must be defined')
+      this.setExperimentProgress({ experimentName: this.experimentName, sceneName: this.sceneName, data: this.$data })
+      console.log('Saved data from local state to store.', this.$data)
+    },
+
+    // Load qualities list from the API
+    async getQualitiesList() {
+      if (this.qualities) return
+
+      const URI = `${this.getHostURI}${API_ROUTES.listSceneQualities(this.sceneName)}`
+      const { data } = await fetch(URI).then(res => res.json())
+      this.qualities = data
+      this.saveProgress()
+    }
+  }
+}
+</script>

+ 112 - 0
src/mixins/ExperimentBaseExtracts.vue

@@ -0,0 +1,112 @@
+<script>
+import ExperimentBase from '@/mixins/ExperimentBase.vue'
+
+import { mapGetters } from 'vuex'
+import { API_ROUTES, findNearestUpper, findNearestLower } from '@/functions'
+
+export default {
+  mixins: [ExperimentBase],
+  data() {
+    return {
+      // Experiment config sliders
+      experimentConfig: {
+        x: 4,
+        y: 4
+      },
+      // Updated when `setConfig` is called
+      extractConfig: {
+        x: 4,
+        y: 4
+      },
+      extracts: []
+    }
+  },
+  computed: {
+    ...mapGetters(['getHostURI']),
+    isConfigNew() {
+      return this.extractConfig.x !== this.experimentConfig.x || this.extractConfig.y !== this.experimentConfig.y
+    }
+  },
+  methods: {
+    // Load extracts from the API
+    async getExtracts(quality = 'min') {
+      const URI = `${this.getHostURI}${API_ROUTES.getImageExtracts(this.sceneName, quality, this.extractConfig.x, this.extractConfig.y)}`
+      const { data } = await fetch(URI)
+        .then(async res => {
+          res.json = await res.json()
+          return res
+        })
+        .then(res => {
+          if (!res.ok) throw new Error(res.json.message + res.json.data ? `\n${res.json.data}` : '')
+          return res.json
+        })
+      return data
+    },
+
+    // Config was updated, load extracts and save progression
+    async setConfig() {
+      // Check if the config is the same
+      if (this.extracts.length > 0 && !this.isConfigNew) return
+
+      this.loadingMessage = 'Loading configuration extracts...'
+      this.loadingErrorMessage = null
+      try {
+        this.extractConfig.x = this.experimentConfig.x
+        this.extractConfig.y = this.experimentConfig.y
+        const data = await this.getExtracts()
+        const hostURI = this.getHostURI
+        this.extracts = data.extracts.map((url, i) => ({
+          link: hostURI + url,
+          quality: data.info.image.quality,
+          zone: i + 1,
+          index: i,
+          nextQuality: findNearestUpper(data.info.image.quality, this.qualities),
+          precQuality: findNearestLower(data.info.image.quality, this.qualities),
+          loading: false
+        }))
+      }
+      catch (err) {
+        console.error('Failed to load new configuration', err)
+        this.loadingErrorMessage = 'Failed to load new configuration. ' + err.message
+      }
+      finally {
+        this.loadingMessage = null
+        this.saveProgress()
+      }
+    },
+
+    // An action was triggered, load extracts and save progression
+    async extractAction(event, extractObj) {
+      console.log(event, extractObj)
+      const { index, nextQuality, precQuality, quality } = extractObj
+
+      let newQuality
+      if (event.button === 0) newQuality = precQuality // Left click
+      if (event.button === 2) newQuality = nextQuality // Right click
+
+      // Do not load a new extract if same quality
+      if (newQuality === quality) return
+
+      // Set loading state
+      this.extracts[index].loading = true
+      try {
+        // Loading new extract
+        const data = await this.getExtracts(newQuality)
+        this.extracts[index].link = this.getHostURI + data.extracts[index]
+        this.extracts[index].quality = data.info.image.quality
+        this.extracts[index].nextQuality = findNearestUpper(data.info.image.quality, this.qualities)
+        this.extracts[index].precQuality = findNearestLower(data.info.image.quality, this.qualities)
+        this.extracts[index].loading = false
+      }
+      catch (err) {
+        // TODO: toast message if fail
+        console.error('Failed to load extract', err)
+      }
+      finally {
+        this.extracts[index].loading = false
+        this.saveProgress()
+      }
+    }
+  }
+}
+</script>

+ 2 - 2
src/router/experiments.js

@@ -1,13 +1,13 @@
 export default [
   {
-    path: '/experiments/ExperimentNoReference/:sceneId',
+    path: '/experiments/ExperimentNoReference/:sceneName',
     name: 'ExperimentNoReference',
     fullName: 'No reference image',
     component: () => import('@/views/Experiments/NoReference.vue'),
     props: true
   },
   {
-    path: '/experiments/ExperimentWithReference/:sceneId',
+    path: '/experiments/ExperimentWithReference/:sceneName',
     name: 'ExperimentWithReference',
     fullName: 'With reference image',
     component: () => import('@/views/Experiments/WithReference.vue'),

+ 1 - 0
src/store/actions.js

@@ -9,6 +9,7 @@ export default {
   resetApp({ commit }, { hostConfig = false, progression = false }) {
     commit('resetApp', { hostConfig, progression })
   },
+
   async setHostConfig({ state, commit }, { ssl, host, port }) {
     // Timeout after 1s
     const controller = new AbortController()

+ 8 - 1
src/store/getters.js

@@ -20,10 +20,17 @@ export default {
   areScenesLoaded(state) {
     if (!state) return
     return state.scenesList !== null
-  }
+  },
 
   // TODO: Cache scene thumb URI
   // areScenesThumbsLoaded(state) {
   //   return state.scenesList !== null
   // }
+
+  getExperimentProgress: state => ({ experimentName, sceneName }) => {
+    if (!state) return
+    if (state.progression && state.progression[experimentName])
+      return state.progression[experimentName][sceneName].data
+  }
+
 }

+ 20 - 14
src/store/mutations.js

@@ -8,6 +8,20 @@ const checkProgression = (state, experimentName, sceneName) => {
   if (!state.progression[experimentName][sceneName])
     state.progression[experimentName][sceneName] = { done: false, data: {} }
 }
+const createProgressionObj = (state, scenes) => {
+  const progressionObj = Experiments.reduce((accExpe, expe) => {
+    const scenesProgressObj = scenes.reduce((accScene, scene) => {
+      // Do not overwrite current progression
+      if (state.progression[expe.name] && state.progression[expe.name][scene])
+        accScene[scene] = state.progression[expe.name][scene]
+      else accScene[scene] = { done: false, data: {} }
+      return accScene
+    }, {})
+    accExpe[expe.name] = scenesProgressObj
+    return accExpe
+  }, {})
+  state.progression = progressionObj
+}
 
 export default {
   setAppUniqueId(state) {
@@ -20,7 +34,11 @@ export default {
         this._vm.$disconnect()
       state.hostConfig = defaultState().hostConfig
     }
-    if (progression) state.progression = defaultState().progression
+    if (progression) {
+      // Reset progression and recreate the progression object
+      state.progression = defaultState().progression
+      createProgressionObj(state, state.scenesList)
+    }
   },
 
   setHostConfig(state, newConfig) {
@@ -29,19 +47,7 @@ export default {
 
   setListScenes(state, scenes) {
     state.scenesList = scenes
-    const progressionObj = Experiments.reduce((accExpe, expe) => {
-      const scenesProgressObj = scenes.reduce((accScene, scene) => {
-        // Do not overwrite current progression
-        if (state.progression[expe.name] && state.progression[expe.name][scene])
-          accScene[scene] = state.progression[expe.name][scene]
-        else accScene[scene] = { done: false, data: {} }
-        return accScene
-      }, {})
-      accExpe[expe.name] = scenesProgressObj
-      return accExpe
-    }, {})
-
-    state.progression = progressionObj
+    createProgressionObj(state, scenes)
   },
 
   setExperimentProgress(state, { experimentName, sceneName, data }) {

+ 17 - 109
src/views/Experiments/WithReference.vue

@@ -106,8 +106,8 @@
 </template>
 
 <script>
-import { mapGetters, mapActions } from 'vuex'
-import { API_ROUTES, findNearestUpper, findNearestLower } from '@/functions'
+import ExperimentBaseExtracts from '@/mixins/ExperimentBaseExtracts.vue'
+import { API_ROUTES } from '@/functions'
 import Loader from '@/components/Loader.vue'
 
 export default {
@@ -115,131 +115,39 @@ export default {
   components: {
     Loader
   },
-  props: {
-    sceneId: {
-      type: String,
-      required: true
-    }
-  },
+  mixins: [ExperimentBaseExtracts],
+
   data() {
     return {
-      referenceImage: null,
-      qualities: null,
-
-      experimentConfig: { // Experiment config sliders
-        x: 8,
-        y: 4,
-        error: null
-      },
-      extractConfig: { // Updated when `setConfig` is called
-        x: 8,
-        y: 4
-      },
-      loadingMessage: null,
-      loadingErrorMessage: null,
-      extracts: []
+      experimentName: 'ExperimentWithReference',
+      referenceImage: null
     }
   },
   computed: {
-    ...mapGetters(['getHostURI']),
-    isConfigNew() {
-      return this.extractConfig.x !== this.experimentConfig.x || this.extractConfig.y !== this.experimentConfig.y
-    }
+
   },
 
   async mounted() {
+    // Load progress from store into local state
+    this.loadProgress()
+
+    // Load scene data from the API
     await this.getReferenceImage()
     await this.getQualitiesList()
 
     // Get default extracts : min quality, cut config : x = 4, y = 4
     await this.setConfig()
+    this.saveProgress()
   },
   methods: {
-    ...mapActions([]),
-
+    // Load the reference image from the API
     async getReferenceImage() {
-      const URI = `${this.getHostURI}${API_ROUTES.getImage(this.sceneId, 'max')}`
-      const { data } = await fetch(URI).then(res => res.json())
-      this.referenceImage = this.getHostURI + data.link
-    },
+      if (this.referenceImage) return
 
-    async getQualitiesList() {
-      const URI = `${this.getHostURI}${API_ROUTES.listSceneQualities(this.sceneId)}`
+      const URI = `${this.getHostURI}${API_ROUTES.getImage(this.sceneName, 'max')}`
       const { data } = await fetch(URI).then(res => res.json())
-      this.qualities = data
-    },
-
-    async getExtracts(quality = 'max') {
-      const URI = `${this.getHostURI}${API_ROUTES.getImageExtracts(this.sceneId, quality, this.extractConfig.x, this.extractConfig.y)}`
-      const { data } = await fetch(URI)
-        .then(async res => {
-          res.json = await res.json()
-          return res
-        })
-        .then(res => {
-          if (!res.ok) throw new Error(res.json.message + res.json.data ? `\n${res.json.data}` : '')
-          return res.json
-        })
-      return data
-    },
-
-    async setConfig() {
-      // Check if the config is the same
-      if (this.extracts.length > 0 && !this.isConfigNew) return
-
-      this.loadingMessage = 'Loading configuration extracts...'
-      this.loadingErrorMessage = null
-      try {
-        this.extractConfig.x = this.experimentConfig.x
-        this.extractConfig.y = this.experimentConfig.y
-        const data = await this.getExtracts()
-        const hostURI = this.getHostURI
-        this.extracts = data.extracts.map((url, i) => ({
-          link: hostURI + url,
-          quality: data.info.image.quality,
-          zone: i + 1,
-          index: i,
-          nextQuality: findNearestUpper(data.info.image.quality, this.qualities),
-          precQuality: findNearestLower(data.info.image.quality, this.qualities),
-          loading: false
-        }))
-      }
-      catch (err) {
-        console.error('Failed to load new configuration', err)
-        this.loadingErrorMessage = 'Failed to load new configuration. ' + err.message
-      }
-      this.loadingMessage = null
-    },
-
-    async extractAction(event, extractObj) {
-      console.log(event, extractObj)
-      const { index, nextQuality, precQuality, quality } = extractObj
-
-      let newQuality
-      if (event.button === 0) newQuality = precQuality // Left click
-      if (event.button === 2) newQuality = nextQuality // Right click
-
-      // Do not load a new extract if same quality
-      if (newQuality === quality) return
-
-      // Set loading state
-      this.extracts[index].loading = true
-      try {
-        // Loading new extract
-        const data = await this.getExtracts(newQuality)
-        this.extracts[index].link = this.getHostURI + data.extracts[index]
-        this.extracts[index].quality = data.info.image.quality
-        this.extracts[index].nextQuality = findNearestUpper(data.info.image.quality, this.qualities)
-        this.extracts[index].precQuality = findNearestLower(data.info.image.quality, this.qualities)
-        this.extracts[index].loading = false
-      }
-      catch (err) {
-        // TODO: toast message if fail
-        console.error('Failed to load extract', err)
-      }
-      finally {
-        this.extracts[index].loading = false
-      }
+      this.referenceImage = this.getHostURI + data.link
+      this.saveProgress()
     }
   }
 }

+ 1 - 2
src/views/SelectExperimentScene.vue

@@ -80,8 +80,7 @@ export default {
       const { data: thumb } = await fetch(`${this.getHostURI}${API_ROUTES.getImage(aScene, 'max')}`)
         .then(res => res.json())
 
-      let sceneObj = {}
-      sceneObj = {
+      let sceneObj = {
         name: thumb.sceneName,
         thumbLink: `${this.getHostURI}${thumb.link}`,
         experimentLink: `/experiments/${this.experimentName}/${thumb.sceneName}`