MatchExtractsWithReference.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. <template>
  2. <ExperimentBlock
  3. :run-expe="runExpe"
  4. :calibration-check="calibrationCheck"
  5. :experiment-name="experimentName"
  6. :scene-name="sceneName"
  7. :loading-message="loadingMessage"
  8. :loading-error-message="loadingErrorMessage"
  9. >
  10. <template v-slot:header>
  11. <!-- Extract configuration -->
  12. <extract-configuration
  13. v-if="lockConfig === false"
  14. @setExtractConfig="setExtractConfig($event, $refs.configurator)"
  15. :loading-error-message="loadingErrorMessage"
  16. ref="configurator"
  17. />
  18. <!--/ Extract configuration -->
  19. </template>
  20. <template v-slot:content>
  21. <div class="text-center">
  22. <v-dialog
  23. v-model="dialogLess"
  24. v-if="explanation === false"
  25. width="500"
  26. >
  27. <v-card>
  28. <v-card-title
  29. class="headline lighten-2"
  30. primary-title
  31. >
  32. <p style="font-size:0.8em;">La qualité de cette zone est déjà à son <strong>minimum</strong></p>
  33. </v-card-title>
  34. <v-divider />
  35. <v-card-actions>
  36. <v-spacer />
  37. <v-btn
  38. color="primary"
  39. text
  40. @click="dialogLess = false"
  41. >
  42. Fermer
  43. </v-btn>
  44. </v-card-actions>
  45. </v-card>
  46. </v-dialog>
  47. </div>
  48. <div class="text-center">
  49. <v-dialog
  50. v-model="dialogMore"
  51. v-if="explanation === false"
  52. width="500"
  53. >
  54. <v-card>
  55. <v-card-title
  56. class="headline lighten-2"
  57. primary-title
  58. >
  59. <p style="font-size:0.8em;">La qualité de cette zone est déjà à son <strong>maximum</strong></p>
  60. </v-card-title>
  61. <v-divider />
  62. <v-card-actions>
  63. <v-spacer />
  64. <v-btn
  65. color="primary"
  66. text
  67. @click="dialogMore = false"
  68. >
  69. Fermer
  70. </v-btn>
  71. </v-card-actions>
  72. </v-card>
  73. </v-dialog>
  74. </div>
  75. <div class="text-center">
  76. <v-dialog
  77. v-model="dialogRefError"
  78. v-if="explanation === false"
  79. width="600"
  80. >
  81. <v-card>
  82. <v-card-title
  83. class="headline lighten-2"
  84. primary-title
  85. >
  86. <p style="font-size:0.8em;">
  87. Vous venez de cliquer sur l'image de référence. Celle-ci ne sera pas modifiée par cette action. <br /><br />
  88. L'expérience a pour objectif de régler la qualité de l'image de gauche pour qu'elle soit la plus proche de l'image de droite.
  89. </p>
  90. </v-card-title>
  91. <v-divider />
  92. <v-card-actions>
  93. <v-spacer />
  94. <v-btn
  95. color="primary"
  96. text
  97. @click="dialogRefError = false"
  98. >
  99. Fermer
  100. </v-btn>
  101. </v-card-actions>
  102. </v-card>
  103. </v-dialog>
  104. </div>
  105. <div class="text-center">
  106. <v-dialog
  107. v-model="calibrationCheck"
  108. width="600"
  109. >
  110. <v-card>
  111. <v-card-title
  112. class="headline lighten-2"
  113. primary-title
  114. >
  115. <p style="font-size:0.8em;">
  116. La scène de calibration vous est proposée de nouveau dans le but de vérifier que l'image de gauche correspond toujours à celle de droite sur votre écran actuel.
  117. <br /><br />
  118. Vous pouvez la régler de nouveau si cela est nécessaire.
  119. </p>
  120. </v-card-title>
  121. <v-divider />
  122. <v-card-actions>
  123. <v-spacer />
  124. <v-btn
  125. color="primary"
  126. text
  127. @click="calibrationCheck = false"
  128. >
  129. Fermer
  130. </v-btn>
  131. </v-card-actions>
  132. </v-card>
  133. </v-dialog>
  134. </div>
  135. <v-flex v-if="explanation === true || disableStart === true" xs12 sm12>
  136. <div style="margin-top:10%">
  137. <p v-if="disableStart === false && calibrationScene === true" style="font-size: 1.4em;">
  138. Vous allez voir des images, l'image de droite constitue toujours l'image de référence. Vous devez régler la qualité de l'image de gauche pour qu'elle soit la plus proche de l'image de droite.
  139. La première image est constituée de carré gris, c'est une partie de calibration. Si vous souhaitez régler votre écran (contraste, luminosité) vous pouvez le faire maintenant mais il vous est demandé de ne plus changer ce réglage au cours de l'expérience.
  140. Vous allez ensuite voir des scènes d'image de synthèse. Vous pouvez arrêter l'expérience quand vous souhaitez (ou faire une pause).
  141. </p>
  142. <p v-if="disableStart === true" style="margin-top:2%; color:orange; font-size: 1.4em;">
  143. <strong>Attention !</strong> L'expérience requiert un écran de résolution minimale de <strong>1920 x 1080</strong> pixels.
  144. <br />
  145. <br />
  146. Vous pouvez redimensionner la fenêtre de votre navigateur pour poursuivre l'expérience.
  147. </p>
  148. <p v-if="disableStart === false" style="margin-top:2%; color:#007acc; font-size: 1.4em;">
  149. <strong>La résolution de votre fenêtre de navigateur vous permet d'accéder à l'expérience</strong>.
  150. </p>
  151. <v-btn v-if="disableStart === true" @click="startExperiment" color="#007acc" large disabled>Poursuivre l'expérience</v-btn>
  152. <v-btn v-if="disableStart === false" @click="startExperiment" color="#007acc" large>Poursuivre l'expérience</v-btn>
  153. </div>
  154. </v-flex>
  155. <v-flex v-if="haveHelp === true" xs12 sm12>
  156. <div style="margin-top:10%">
  157. <p style="font-size: 1.4em;">
  158. Cette expérience vous propose le visuel deux images, celle de gauche considérée comme dégradée et celle de gauche, sa référence (image sans dégradation visible).
  159. <br />
  160. Vous devez régler la qualité de l'image de gauche pour qu'elle soit la plus proche de l'image de droite.
  161. </p>
  162. <br />
  163. <br />
  164. <p style="font-size: 1.4em;text-align:left">
  165. Pour cela, deux actions vous sont proposées :
  166. <br />
  167. <ul>
  168. <li> <strong>clic gauche de la souris :</strong> permet d'améliorer la qualité de l'image à l'endroit où de la dégradation vous est encore visible.</li>
  169. <li> <strong>clic droit de la souris :</strong> permet de revenir à une qualité inférieure de l'image si l'amélioration apportée n'était pas nécessaire (aucune amélioration visible apportée après clic droit).</li>
  170. </ul>
  171. </p>
  172. <v-btn @click="startExperiment" color="#007acc" large>Continuer l'expérience</v-btn>
  173. </div>
  174. </v-flex>
  175. <v-flex v-if="haveBreak === true" xs12 sm12>
  176. <div style="margin-top:10%">
  177. <p style="font-size: 1.4em;">
  178. Nous vous remercions d'avoir participé à cette expérience.
  179. Elle va nous permettre d'améliorer les calculs d'images. Si vous le souhaitez, vous pouvez revenir sur l'expérience via le <a :href="launcherURI" target="_blank">launcher</a> pour revoir de nouvelles images.
  180. </p>
  181. <v-btn @click="startExperiment" color="#007acc" large>Continuer l'expérience</v-btn>
  182. </div>
  183. <!-- Add of newsletter component -->
  184. <Newsletter />
  185. </v-flex>
  186. <v-flex v-if="runExpe === true" xs12 sm6 :style="{ 'max-width': maxWidth + 'px', 'min-width': maxWidth + 'px', 'margin-right': 20 + 'px' }">
  187. <v-card dark color="primary" :max-width="maxWidth" :min-width="maxWidth">
  188. <!-- <v-card-text class="px-0">Experiment image</v-card-text> -->
  189. <v-container class="pa-1">
  190. <template v-for="i in extractConfig.y">
  191. <v-layout row wrap :key="`row-${i}`">
  192. <v-flex
  193. v-for="(anExtract, index) in extracts.slice(extractConfig.x * (i - 1), (extractConfig.x * i))"
  194. :key="`extract-${i}-${extractConfig.x}-${extractConfig.y}-${index}-${anExtract.quality}`"
  195. class="pa-0"
  196. >
  197. <v-card flat tile class="d-flex height100">
  198. <div
  199. v-if="anExtract.loading"
  200. class="img-extract-loader"
  201. @click.right.prevent
  202. >
  203. <v-progress-circular
  204. :indeterminate="true"
  205. />
  206. </div>
  207. <v-img
  208. v-else
  209. :src="anExtract.link"
  210. @click.left.prevent="extractAction($event, anExtract)"
  211. @click.right.prevent="extractAction($event, anExtract)"
  212. class="cursor"
  213. :class="{ 'extract-hover-border': showHoverBorder === true }"
  214. @error="extractsRemovedFromServerFallback"
  215. >
  216. <template v-slot:placeholder>
  217. <v-layout fill-height align-center justify-center ma-0>
  218. <v-progress-circular indeterminate color="grey lighten-5" />
  219. </v-layout>
  220. </template>
  221. </v-img>
  222. </v-card>
  223. </v-flex>
  224. </v-layout>
  225. </template>
  226. </v-container>
  227. </v-card>
  228. </v-flex>
  229. <v-flex @click="dialogRefError = true" v-if="runExpe === true" sm6 xs12 :style="{ 'max-width': maxWidth + 'px', 'min-width': maxWidth + 'px' }">
  230. <v-card dark color="primary" :max-width="maxWidth" :min-width="maxWidth">
  231. <!-- <v-card-text>Reference image</v-card-text> -->
  232. <v-img v-if="referenceImage" :src="referenceImage" :max-height="maxHeight" :max-width="maxWidth" :min-width="maxWidth" />
  233. </v-card>
  234. </v-flex>
  235. <!-- Experiment validation button -->
  236. <v-layout v-if="runExpe === true" justify-end align-content-end>
  237. <v-text-field
  238. v-model="comment"
  239. label="Ajouter un commentaire ici"
  240. />
  241. <v-btn @click="userHelp" color="#737373" large right>Besoin d'aide ?</v-btn>
  242. <v-btn @click="userBreak" color="#cc7a00" large right>Arrêter ou faire une pause</v-btn>
  243. <v-btn @click="finishExperiment" color="#008000" large right>Valider & passer à l'image suivante</v-btn>
  244. </v-layout>
  245. <!--/ Experiment validation button -->
  246. </template>
  247. </ExperimentBlock>
  248. </template>
  249. <script>
  250. import { mapGetters } from 'vuex'
  251. import ExperimentBlock from '@/components/ExperimentBlock.vue'
  252. import ExperimentBaseExtracts from '@/mixins/ExperimentBaseExtracts'
  253. import ExtractConfiguration from '@/components/ExperimentsComponents/ExtractConfiguration.vue'
  254. import Newsletter from '@/components/ExperimentsComponents/Newsletter.vue'
  255. export default {
  256. components: {
  257. ExperimentBlock,
  258. ExtractConfiguration,
  259. Newsletter
  260. },
  261. mixins: [ExperimentBaseExtracts],
  262. data() {
  263. return {
  264. referenceImage: null,
  265. maxWidth: null,
  266. maxHeight: null,
  267. launcherURI: null,
  268. explanation: false,
  269. haveBreak: false,
  270. haveHelp: false,
  271. calibrationScene: false,
  272. runExpe: false,
  273. calibrationCheck: false,
  274. disableStart: false,
  275. dialogRefError: false
  276. }
  277. },
  278. computed: {
  279. ...mapGetters(['getHostURI', 'getAllExperimentProgress'])
  280. },
  281. async mounted() {
  282. // redirect by default to calibration scene
  283. let nScenes = Number(window.sessionStorage.getItem('sin3d-nb-scenes'))
  284. if (nScenes === 0) {
  285. console.log('number of scene is', nScenes)
  286. window.sessionStorage.setItem('sin3d-nb-scenes', nScenes + 1)
  287. this.$router.push(`/experiments/${this.experimentName}/50_shades_of_grey`)
  288. }
  289. else {
  290. // Load config for this scene to local state
  291. this.loadConfig()
  292. // Load progress from store into local state
  293. this.loadProgress()
  294. this.launcherURI = this.getHostURI + '/launcher/'
  295. let reference = null
  296. // Load scene data from the API
  297. await Promise.all([
  298. this.getImage('max').then(res => (reference = res)),
  299. this.getQualitiesList()
  300. ])
  301. this.referenceImage = reference.link
  302. this.maxWidth = reference.metadata.width
  303. this.maxHeight = reference.metadata.height
  304. // Load the cached configuration in the configurator component
  305. if (this.lockConfig === false) this.$refs.configurator.setDefaultConfig(this.extractConfig)
  306. // Load extracts if none were cached
  307. // if (this.extracts.length === 0)
  308. await this.setExtractConfig(this.extractConfig, this.$refs.configurator)
  309. this.saveProgress()
  310. this.loadExperimentState()
  311. // check window size
  312. this.checkWindow()
  313. window.addEventListener('resize', this.checkWindow)
  314. // check if calibration is already done
  315. if (this.sceneName === '50_shades_of_grey') {
  316. // load current user progression
  317. this.progression = this.getAllExperimentProgress()
  318. let done = this.progression[this.experimentName][this.sceneName].done
  319. console.log('Calibration scene is done', done)
  320. if (done === true) {
  321. console.log('Change of state for calibration')
  322. this.calibrationCheck = true
  323. this.runExpe = true
  324. this.explanation = false
  325. this.calibrationScene = true
  326. }
  327. }
  328. }
  329. },
  330. methods: {
  331. startExperiment() {
  332. this.runExpe = true
  333. this.explanation = false
  334. this.haveBreak = false
  335. this.haveHelp = false
  336. },
  337. userBreak() {
  338. this.haveBreak = true
  339. this.explanation = false
  340. this.runExpe = false
  341. this.haveHelp = false
  342. },
  343. userHelp() {
  344. this.haveHelp = true
  345. this.haveBreak = false
  346. this.explanation = false
  347. this.runExpe = false
  348. },
  349. loadExperimentState() {
  350. this.haveHelp = false
  351. this.explanation = false
  352. this.haveBreak = false
  353. this.runExpe = false
  354. if (this.sceneName === '50_shades_of_grey') {
  355. this.explanation = true
  356. this.calibrationScene = true
  357. }
  358. else {
  359. this.runExpe = true
  360. }
  361. },
  362. checkWindow() {
  363. // check window screen size
  364. if (window.innerWidth < 1920 || window.innerHeight < 900) {
  365. this.disableStart = true
  366. this.explanation = true
  367. this.runExpe = false
  368. this.haveBreak = false
  369. this.haveHelp = false
  370. }
  371. else {
  372. this.disableStart = false
  373. }
  374. }
  375. }
  376. }
  377. </script>