Parcourir la source

Merge branch 'release/v0.1.6'

Jérôme BUISINE il y a 4 ans
Parent
commit
062143bd28

+ 5 - 7
DOCUMENTATION.md

@@ -31,12 +31,10 @@ An example for the `quest_one_image` key experience:
     'params':{
         'iterations': 10
     },
+
+    # if others custom session param are directly set for experience
     'session_params': [
-        'expe_percentage',
-        'expe_orientation',
-        'expe_position',
-        'expe_stim',
-        'expe_previous_iteration'
+        'expe_data',
     ],
 
     # template file used in django `expe` route
@@ -118,7 +116,7 @@ line += ";" + str(previous_percentage)
 line += ";" + str(previous_orientation) 
 line += ";" + str(previous_position) 
 line += ";" + str(answer) 
-line += ";" + str(answer_time) 
+line += ";" + str(expe_answer_time) 
 line += ";" + str(entropy) 
 line += '\n'
 
@@ -143,5 +141,5 @@ If you want to create your own template, specify your template path into configu
 
 Example of way to use your experience data into template:
 ```python
-{{expe_data|get_value_from_dict:'image_path'}}
+{{request.session.expe_data|get_value_from_dict:'image_path'}}
 ```

+ 1 - 1
Dockerfile

@@ -1,4 +1,4 @@
-from python
+FROM python
 
 COPY . /usr/src/app
 WORKDIR /usr/src/app

+ 12 - 6
README.md

@@ -13,21 +13,27 @@ Web site which contains experiences on synthesis images (perception of noise).
 You need to have python, pip
 
 ```
-pip install -r requirementst.txt
+pip install -r requirements.txt
+```
+
+Initialize the database with the following command :
+
+```
+python manage.py migrate
 ```
 
 #### Run server
 
-And then, run the server :
+Run the server :
 
 ```
-python project/manage.py runserver
+python manage.py runserver
 ```
 
-or if you want to precise a specific port number :
+or if you want to make it listen on a specific port number :
 
 ```
-python project/manage.py runserver 8080
+python manage.py runserver 8080
 ```
 
 ### 2. Using docker (recommended)
@@ -94,7 +100,7 @@ WEBEXPE_PREFIX_URL=experience/ WEB_API_PREFIX_URL=expe/api make deploy
 
 ## Create your experiences
 
-Documentation is available [here](DOCUMENTATION.md). This documentation explains how you can create your own experience.
+See [DOCUMENTATION.md](DOCUMENTATION.md). This documentation explains how to create your own experience.
 
 ## How to contribute ?
 

+ 4 - 6
expe/config.py

@@ -34,19 +34,17 @@ expes_configuration         = {
         'params':{
             'iterations': 10
         },
+       
+        # if others custom session param are directly set for experience
         'session_params': [
-            'expe_percentage',
-            'expe_orientation',
-            'expe_position',
-            'expe_stim',
-            'expe_previous_iteration'
+            'expe_data',
         ],
 
         # template file used in django `expe` route
         'template': 'expe/expe.html',
 
         # javascript file used
-        'js':[
+        'javascript':[
             'loadImg.js',
             'keyEvents.js'
         ],

+ 22 - 20
expe/expes/run.py

@@ -43,18 +43,21 @@ def run_quest_one_image(request, model_filepath, output_file):
         if request.session['expe_previous_iteration'] == iteration:
             return None
         else:
+            current_expe_data = request.session['expe_data']
             answer = int(request.GET.get('answer'))
-            answer_time = time.time() - request.session['answer_time']
-            print("Answer time is ", answer_time)
-            previous_percentage = request.session.get('expe_percentage')
-            previous_orientation = request.session.get('expe_orientation')
-            previous_position = request.session.get('expe_position')
-            previous_stim = request.session.get('expe_stim')
+            expe_answer_time = time.time() - current_expe_data['expe_answer_time']
+            previous_percentage = current_expe_data['expe_percentage']
+            previous_orientation = current_expe_data['expe_orientation']
+            previous_position = current_expe_data['expe_position']
+            previous_stim = current_expe_data['expe_stim']
+
+            print("Answer time is ", expe_answer_time)
 
     # 3. Load or create Quest instance
     # default params
+    # TODO : add specific thresholds information for scene
     thresholds = np.arange(50, 10000, 50)
-    stim_space=np.asarray(qualities)
+    stim_space = np.asarray(qualities)
     slopes = np.arange(0.0001, 0.001, 0.00003)
 
     # check if necessary to construct `quest` object
@@ -81,7 +84,7 @@ def run_quest_one_image(request, model_filepath, output_file):
         line += ";" + str(previous_orientation) 
         line += ";" + str(previous_position) 
         line += ";" + str(answer) 
-        line += ";" + str(answer_time) 
+        line += ";" + str(expe_answer_time) 
         line += ";" + str(entropy) 
         line += '\n'
 
@@ -123,21 +126,20 @@ def run_quest_one_image(request, model_filepath, output_file):
     if img_merge is not None:
         img_merge.save(filepath_img)
 
-    # 6. Prepare session data for current iteration and data for view
-    # set current step data
-    request.session['expe_percentage'] = percentage
-    request.session['expe_orientation'] = orientation
-    request.session['expe_position'] = position
-    request.session['answer_time'] = time.time()
-    request.session['expe_previous_iteration'] = iteration
-    request.session['expe_stim'] = str(next_stim)
+    # 6. Prepare experience data for current iteration and data for view
     
-    # expe is now started
-    request.session['expe_started'] = True
-
     # here you can save whatever you need for you experience
     data_expe = {
-        'image_path': filepath_img
+        'image_path': filepath_img,
+        'expe_percentage': percentage,
+        'expe_orientation': orientation,
+        'expe_position': position,
+        'expe_answer_time': time.time(),
+        'expe_previous_iteration': iteration,
+        'expe_stim': str(next_stim)
     }
+    
+    # expe is now started
+    request.session['expe_started'] = True
 
     return data_expe

+ 4 - 6
expe/templates/base.html

@@ -34,16 +34,14 @@
         const host     = window.location.host
         var baseUrl    = location.protocol + '//' + host + '/'
 
-        if (BASE != ''){
-            baseUrl += BASE + '/'
-        }
+        if (BASE !== '') baseUrl += BASE + '/'
 
         const expeUrl  = baseUrl + 'expe'  
 
         // EXPE variables parts
         // get access to django variables
-        var BEGIN_EXPE = "{{request.session.expe_started}}"
-        var END_EXPE   = "{{request.session.expe_finished}}"
+        var BEGIN_EXPE = "{{request.session.expe_started}}" === 'True'
+        var END_EXPE   = "{{request.session.expe_finished}}" === 'True'
     </script>
 
     <!-- Custom Javascript file for experience template is placed here -->
@@ -52,7 +50,7 @@
     {% endblock %}
 
     <!-- Dynamically load JS file of experience -->
-    {% for file in js %}
+    {% for file in javascript %}
         {% with 'js/'|add:file as js_static %}
             <script src="{% static js_static %}"></script>
         {% endwith %}

+ 1 - 1
expe/templates/expe/expe.html

@@ -18,7 +18,7 @@
 
     <!-- TODO : Load    img from bitmap with javascript `loadImg.js` -->
     {% if not request.session.expe_finished %}
-        <img id="expeImg" src="{{expe_data|get_value_from_dict:'image_path'}}" data-img="{{request.session.img_merged}}"/>
+        <img id="expeImg" src="{{request.session.expe_data|get_value_from_dict:'image_path'}}" data-img="{{request.session.img_merged}}"/>
     {% endif %}
 
     {% block javascripts %}

+ 5 - 4
expe/templates/expe/expe_indications.html

@@ -13,8 +13,9 @@
     <h5>{{indication}}</h5>
 
     <p id="expeIndication"><strong>Press enter to begin experience</strong></p>
-    
-    {% block javascripts %}
-        <script src="{% static "js/indications.js" %}"></script>
-    {% endblock %}
+
+{% endblock %}
+
+{% block javascripts %}
+    <script src="{% static "js/indications.js" %}"></script>
 {% endblock %}

+ 8 - 8
expe/templates/expe/expe_results.html

@@ -73,13 +73,13 @@
             {% endfor %}
         {% endif %}
     </div>
+{% endblock %}
 
-    {% block javascripts %}
-        <script type="text/javascript"> 
-            // Utils informations
-            var expe_name = "{{expe}}"
-        </script>
-        <script src="{% static "js/results.js" %}"></script>
-        <script src="{% static "js/FileSaver.js" %}"></script>
-    {% endblock %}
+{% block javascripts %}
+    <script type="text/javascript"> 
+        // Utils informations
+        var expe_name = "{{expe}}"
+    </script>
+    <script src="{% static "js/results.js" %}"></script>
+    <script src="{% static "js/FileSaver.js" %}"></script>
 {% endblock %}

+ 9 - 6
expe/views.py

@@ -148,18 +148,21 @@ def expe(request):
         del request.session['scene']
         del request.session['qualities']
         del request.session['timestamp']
-        del request.session['answer_time']
 
         # specific current expe session params (see `config.py`)
         for key in cfg.expes_configuration[expe_name]['session_params']:
             del request.session[key]
 
-    # get base data
+    # set expe current data into session (replace only if experience data changed)
+    if expe_data is not None:
+        request.session['expe_data'] = expe_data
+
+        # get base data
     data = get_base_data(expe_name)
-    # expe parameters
-    data['expe_name']       = expe_name
-    data['expe_data']       = expe_data
-    data['end_text']        = cfg.expes_configuration[expe_name]['text']['end_text']
+
+    # other experiences information
+    data['expe_name']            = expe_name
+    data['end_text']             = cfg.expes_configuration[expe_name]['text']['end_text']
 
     return render(request, cfg.expes_configuration[expe_name]['template'], data)
 

+ 20 - 24
static/js/indications.js

@@ -1,29 +1,25 @@
-// implement `key` events
-document.onkeydown = checkKey;
-
 // Utils informations
-var KEYCODE_Q           = '81'
-var KEYCODE_ENTER       = '13'
-
-urlParams = new URLSearchParams(window.location.search);
+const KEYCODE_Q     = 81
+const KEYCODE_ENTER = 13
 
-var scene = urlParams.get('scene')
-var expe  = urlParams.get('expe')
+urlParams = new URLSearchParams(window.location.search)
 
-function checkKey(e) {
+const scene = urlParams.get('scene')
+const expe  = urlParams.get('expe')
 
-   e = e || window.event;
+const checkKey = e => {
+     if (e.keyCode === KEYCODE_Q) {
+          // `q` to quit expe
+          console.log('`q` key is pressed')
+          window.location = ''
+     }
+     else if (e.keyCode === KEYCODE_ENTER) {
+          // right arrow
+          const params = `?scene=${scene}&expe=${expe}&iteration=0`
+          console.log(expeUrl + params)
+          window.location = expeUrl + params
+     }
+}
 
-   if (e.keyCode == KEYCODE_Q) {
-        // `q` for quit expe
-        console.log('`q` key is pressed')
-        window.location = ''
-   }
-   else if (e.keyCode == KEYCODE_ENTER) {
-
-        // right arrow
-        var params = "?scene=" + scene + "&expe=" + expe + "&iteration=0"
-        console.log(expeUrl + params)
-        window.location = expeUrl + params
-   }
-}
+// implement `key` events
+document.addEventListener('keydown', checkKey)

+ 27 - 38
static/js/keyEvents.js

@@ -1,71 +1,60 @@
-// implement `key` events
-document.onkeydown = checkKey;
-
-urlParams = new URLSearchParams(window.location.search);
-
 // Utils informations
-var KEYCODE_Q           = '81'
-var KEYCODE_ENTER       = '13'
-var KEYCODE_LEFT_ARROW  = '37'
-var KEYCODE_RIGHT_ARROW = '39'
-
-// get params if exists
-if (urlParams.has('scene')){
-
-   var scene = urlParams.get('scene')
-   var expe  = urlParams.get('expe')
-}
+const KEYCODE_Q           = 81
+const KEYCODE_ENTER       = 13
+const KEYCODE_LEFT_ARROW  = 37
+const KEYCODE_RIGHT_ARROW = 39
 
-function checkKey(e) {
+urlParams = new URLSearchParams(window.location.search)
 
-   e = e || window.event;
+const scene = urlParams.get('scene')
+const expe  = urlParams.get('expe')
 
-   if (e.keyCode == '81') {
-      // `q` for quit expe
+const checkKey = e => {
+   if (e.keyCode === KEYCODE_Q) {
+      // `q` to quit expe
       console.log('`q` key is pressed')
       window.location = baseUrl
    }
-   else if (e.keyCode == '13') {
-
+   else if (e.keyCode === KEYCODE_ENTER) {
       // check if experience is begin
-      if (!BEGIN_EXPE){
-
-         console.log(window.location.href + "&begin=true")
+      if (!BEGIN_EXPE) {
          // right arrow
-         window.location = window.location.href + "&begin=true"
+         window.location = window.location.href + '&begin=true'
       } 
    }
-   else if (e.keyCode == '37' || e.keyCode == '39'){
-
-      // only do something is experience is begin
-      if (BEGIN_EXPE){
-         var answer;
+   else if (e.keyCode === KEYCODE_LEFT_ARROW || e.keyCode === KEYCODE_RIGHT_ARROW) {
+      // only do something is experience has begun
+      if (BEGIN_EXPE) {
+         let answer
 
          // left arrow key
-         if (e.keyCode == '37'){
+         if (e.keyCode === KEYCODE_LEFT_ARROW) {
             console.log('left arrow is pressed')
             answer = '1'
          }
 
          // right arrow key
-         if (e.keyCode == '39'){
+         if (e.keyCode === KEYCODE_RIGHT_ARROW) {
             console.log('right arrow is pressed')
             answer = '0'
          }
 
-         var iteration = 0;
+         let iteration = 0
 
          // update of iteration if exists
-         if (urlParams.has('iteration')){
+         if (urlParams.has('iteration')) {
             iteration = urlParams.get('iteration')
 
             // increment step
-            iteration++;
+            iteration++
          }
          
          // construct url with params for experience
-         var params = "?scene=" + scene + "&expe=" + expe + "&iteration=" + iteration + "&answer=" + answer
+         const params = `?scene=${scene}&expe=${expe}&iteration=${iteration}&answer=${answer}`
          window.location = expeUrl + params
       }
    }
-}
+}
+
+// implement `key` events
+document.addEventListener('keydown', checkKey)

+ 15 - 24
static/js/loadImg.js

@@ -1,28 +1,19 @@
-window.onload = function () {
-
-    console.log("End expe " + END_EXPE)
+const delay = ms => new Promise(res => setTimeout(res, ms))
 
+window.addEventListener('DOMContentLoaded', async () => {
+    console.log('End expe ' + END_EXPE)
+    
     // only if not end of expe
-    if (END_EXPE == "False"){
-        setTimeout(function(){ 
-            document.getElementById("expeImg").style.display = "inline";
-        }, 500);
+    if (!END_EXPE) {
+        await delay(500)
+        document.getElementById('expeImg').style.display = 'inline'
     }
-
-    // redirect if end of expe after 5 sec
-    if (END_EXPE == "True"){
-        
-        for(var i=0; i<6; i++){
-            ((x)=>{
-                setTimeout(()=> 
-                    document.getElementById("refreshTime").textContent = 5 - x
-                ,1000 * i)
-            })(i);
-        } 
-
-        setTimeout(function(){ 
-            // TODO : refresh to home app
-            window.location = baseUrl
-        }, 5000);
+    // redirect after 5s if end of expe
+    else if (END_EXPE) {
+        for (let i = 0; i <= 5; i++) {
+            document.getElementById('refreshTime').textContent = 5 - i
+            if (i <= 4) await delay(1000)
+        }
+        window.location = baseUrl
     }
-}
+})

+ 4 - 11
static/js/results.js

@@ -1,18 +1,12 @@
-// create
 const toggleVisible = ele => ele.style.display = ele.style.display === 'none' ? 'block' : 'none'
-const toggleClass = (elem, class1, class2) => elem.className = elem.className === class1 ? class2 : class1
+const toggleClass = (ele, class1, class2) => ele.className = ele.className === class1 ? class2 : class1
 
 // Download endpoint response as a file using a POST request
 const downloadContent = path => {
     const csrfToken = document.querySelector('[name=csrfmiddlewaretoken]').value
+    const downloadUrl = BASE === '' ? `/admin/download` : `/${BASE}/admin/download`
 
-    if (BASE == ''){
-        var downloadUrl = '/admin/download'
-    }else{
-        var downloadUrl = '/' + BASE + '/admin/download'
-    }
-
-    fetch(downloadUrl, {
+    return fetch(downloadUrl, {
         method: 'POST',
         body: `path=${path}`,
         headers: {
@@ -28,13 +22,12 @@ const downloadContent = path => {
             const filename = `${expe_name}_${disposition.split('=')[1]}`
 
             const blob = await res.blob()
-            // use of `FileSaver`
+            // use of `FileSaver.js` library
             saveAs(blob, filename)
         }
     })
 }
 
-
 window.addEventListener('DOMContentLoaded', () => {
     // Display list of files from day folder
     // need to parse as `Array`