Skip to content
Snippets Groups Projects
Select Git revision
  • 8bbf429872aae6e2b5848e9d200ae646a936b771
  • master default protected
  • 0.1.3
  • 0.1.2
  • 0.1.1
  • 0.1.0
  • v0.1.0
7 results

setupbase.py

Blame
  • create-evaluation-files.py 37.06 KiB
    #!/usr/bin/python3
    # Create HTML files with Selection evaluation results for each participant
    #    in current directory. Creates evaluation.html and reviews/
    #
    # cd Selection
    # usage: python ../create-evaluation-files-multi.py \
    #    ../registrations.csv ../submissions-638.csv 
    #
    # Some --- columns needs to be renamed in evaluation-results.csv
    # First column --- to -o-
    # Column --- for each preference stating Does not meet requirements needs to be renamed to -n-
    #
    import sys
    import csv
    import os
    import re
    import string
    from posix import unlink
    from datetime import datetime
    from collections import Counter
    import glob
    
    
    # enter SoHPC year
    SoHPC_year = "2020" 
    
    #
    # Basic skeleton of html file (header, footer and content in the middle (parameter 3)
    # Also include place holders for file title (0) and date (1)
    skeleton = """
    <html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <meta http-equiv="CACHE-CONTROL" content="NO-CACHE">
        <meta http-equiv="EXPIRES" content="0">
        <title>{{TITLE}}</title>
        <script type="text/javascript">
            function goto_project(){
                var myselect = document.getElementById("project_id_list");
                window.location.href = '#project_'+myselect.options[myselect.selectedIndex].value;
            }
        </script>
    <style>
      body {background-color:white}
      .size {
      background-color: white;
      margin:0 auto;
      font-family: arial;
      font-size: 12px;
      }
      div.title { font-size: 16px; font-weight: bold;}
      div {margin-bottom: 2px;}
      table.list {
          width: 100%;
          padding: 0px;
          margin: 0px;
          -webkit-border-vertical-spacing: 0px;
      }
      table.list tr:nth-child(even) {
        background-color: #EFEFEF;
      }
      table.list tr.head, table.list tr.foot {
          background-color: #BBBBBB;
      }
          table.list tr.head th {
              border-bottom: 1px solid #aaaaaa;
          }
          table.list tr.foot th {
              border-top: 1px solid #aaaaaa;
          }
    
      table.list tr td.id {
          text-align: right;
          padding-right: 5px;
          border-left: 0px;
      }
      table.list tr:hover {
        background-color: LightGreen;
      }
      td.dataCaptionTD {
          width: 150px;
      }
      td.dataSubCaptionTD {
          width: 150px;
      }
      th.overall_comment, td.overall_comment {
          width: 15%;
          vertical-align: top;
      }
      table.list tr table.no_bg_coloring tr {
          background-color: transparent;
      }
      table.list tr.registrant_selected {
          text-decoration: line-through;
          background-color: #00EFEF;
          font-style: italic;
          color: #999999;
      }
          table.list tr.registrant_selected a {
              color: #999999;
          }
    </style>
    </head>
    <body>
    <div class=size>
    <br>
    <br>
    <div style="font-size: 16px; text-align: center; font-weight: bold;">Summer of HPC project evaluation results</div>
    <br><br>
    <div ><span style="float:right;"><b>Date</b>: {{DATE}}</span></div> 
    {{CONTENT}}
    </body>
    </html>
    """
    
    #
    # Main content of index.html file. It holds list of projects and particiants (sorted by score)
    #
    index_data = """
    <br>
    <a name="projects"></a>
    Content: [<a href="#projects">Project list</a>]&nbsp;&nbsp;[<a href="#registrants">Registrant list</a>]
    <br>
    <br>
    <h2>PROJECT LIST WITH REGISTRANTS</h2>
    
    <table>
    <tr valign="top">
        <td>
            Projects and selected registrants (students):
            <table class="list" style="width: auto;">
            <tr class="head">
                <td>Project: ID- - name</td>
                <td>Selected registrant (link to application)</td>
                <td>Country</td>
                <td>Gender</td>
                <td>Age</td>
                <td>E-mail</td>
                <td colspan="2">Evaluation<br>details</td>
            </tr>
            {{PROJECT_LIST_AND_SELECTED_PARTICIPANTS}}
            </table>
        </td>
        <td width="10%">&nbsp;</td>
        <td>
            Countries - all and selected.
            <table class="list">
            <tr class="head">
                <th>&nbsp;</th>
                <th colspan="3">Registrants</th>
            </tr>
            <tr class="head">
                <th>Country</th>
                <th width="60px">All</th>
                <th width="60px">Selected</th>
                <th width="60px">[%]</th>
            </tr>
            {{COUNTRY_PARTICIPANTS_LIST}}
            </table>
        </td>
    </tr>
    </table>
    <hr>
    {{CONTENT_PROJECTS}}
    
    <br>
    <br>
    <br>
    <hr>
    <br>
    <a name="registrants"></a>
    Content: [<a href="#projects">Project list</a>]&nbsp;&nbsp;[<a href="#registrants">Registrant list</a>]
    <br>
    <br>
    <h2>REGISTRANTS EVALUATIONS</h2>
    {{CONTENT_REGISTRANTS}}
    """
    
    # layout of project in TOC
    project_selected_participant_row = """
        <tr>
            <td rowspan="{{PROJECT_ROW_SPAN}}"><a href="#project_{{PROJECT_ID}}">{{PROJECT_ID}} - {{PROJECT_NAME}}</td>
            <td>{{PARTICIPANTS_LIST}}</td>
        </tr>
    """
    
    # layout of list of participants; value is added to "skeleton"
    project_html_data = """
    <br>
    <a name="project_{{PROJECT_ID}}"></a>
    <h3>{{PROJECT_ID}} - {{PROJECT_NAME}}</h3>
    On mouseover (put mouse cursor above mark) and additional explanation will be displayed. <div style="float: right;"><a href="#projects">[to top]</a></div>
    <table class="list">
    <head>
        <tr class="head">
            <th>&nbsp;</th>
            <th>&nbsp;</th>
            <th>&nbsp;</th>
            <th>&nbsp;</th>
            <th>&nbsp;</th>
            <th>&nbsp;</th>
            <th colspan="2">Comment</th>
            <th colspan="2">Pref.1</th>
            <th colspan="2">Pref.2</th>
            <th colspan="2">Pref.3</th>
            <th colspan="3">Motivation</th>
            <th colspan="3">Ambasador</th>
            <th colspan="3">Technical</th>
            <th>&nbsp;</th>
        </tr>
        <tr class="head">
            <th>No.</th>
            <th>Name (ID)</th>
            <th>Country</th>
            <th>Gender</th>
            <th>Age</th>
            <th>Choice</th>
            <th class="overall_comment">P1</th>
            <th class="overall_comment">P2</th>
            <th title="[X] = Student meet compulsory preferences.\n[  ] = Student DOES NOT meet compulsory preferences.">(?)</th>
            <th title="[X] = Student meet desirable prerequisites.\n[  ] = Student DOES NOT meet desirable preferences.">(?)</th>
            <th title="[X] = Student meet compulsory preferences.\n[  ] = Student DOES NOT meet compulsory preferences.">(?)</th>
            <th title="[X] = Student meet desirable prerequisites.\n[  ] = Student DOES NOT meet desirable preferences.">(?)</th>
            <th title="[X] = Student meet compulsory preferences.\n[  ] = Student DOES NOT meet compulsory preferences.">(?)</th>
            <th title="[X] = Student meet desirable prerequisites.\n[  ] = Student DOES NOT meet desirable preferences.">(?)</th>
            <th>P1</th>
            <th>P2</th>
            <th>Avg</th>
            <th>P1</th>
            <th>P2</th>
            <th>Avg</th>
            <th>P1</th>
            <th>P2</th>
            <th>Avg</th>
            <th>Average</th>
        </tr>
    </thead>
    <tbody>
    {{REGISTRANT_DATA}}
    </tbody>
    </table>
    """
    
    # row for 
    project_user_row = """
    <tr class="{{REGISTRANT_SELECTED}}">
        <td class="id">{{I}}</td>
        <td><a href="{{HTML_FILENAME}}">{{NAME}} ({{ID}})</a> <a href='{{EVALUATION_HTML_LINK_1}}'>[eval1]</a> <a href='{{EVALUATION_HTML_LINK_2}}'>[eval2]</a></td>
        <td>{{COUNTRY}}</td>
        <td align="center">{{GENDER}}</td>
        <td align="center">{{AGE}}</td>
        <td class="{{CHOICE}}" align="center">{{CHOICE}}</td>
        <td align="left" class="overall_comment"><i>{{REVIEWER_1}}:</i><br>{{OVERALL_COMMENT_1}}</td>
        <td align="left" class="overall_comment"><i>{{REVIEWER_2}}:</i><br>{{OVERALL_COMMENT_2}}</td>
        <td align="center" title="{{PREFERENCE_1_COMPULSORY}}">{{PREFERENCE_1_SHORT_COMPULSORY}}</td>
        <td align="center" title="{{PREFERENCE_1_DESIRABLE}}">{{PREFERENCE_1_SHORT_DESIRABLE}}</td>
        <td align="center" title="{{PREFERENCE_2_COMPULSORY}}">{{PREFERENCE_2_SHORT_COMPULSORY}}</td>
        <td align="center" title="{{PREFERENCE_2_DESIRABLE}}">{{PREFERENCE_2_SHORT_DESIRABLE}}</td>
        <td align="center" title="{{PREFERENCE_3_COMPULSORY}}">{{PREFERENCE_3_SHORT_COMPULSORY}}</td>
        <td align="center" title="{{PREFERENCE_3_DESIRABLE}}">{{PREFERENCE_3_SHORT_DESIRABLE}}</td>
        <td align="center" title="{{REVIEWER_1}}: {{MOTIVATION_COMMENT_P1}}">{{MOTIVATION_P1}}</td>
        <td align="center" title="{{REVIEWER_2}}: {{MOTIVATION_COMMENT_P2}}">{{MOTIVATION_P2}}</td>
        <td align="center">{{MOTIVATION_AVG}}</td>
        <td align="center" title="{{REVIEWER_1}}: {{AMBASADOR_COMMENT_P1}}">{{AMBASADOR_P1}}</td>
        <td align="center" title="{{REVIEWER_2}}: {{AMBASADOR_COMMENT_P2}}">{{AMBASADOR_P2}}</td>
        <td align="center">{{AMBASADOR_AVG}}</td>
        <td align="center" title="{{REVIEWER_1}}: {{TECHNICAL_COMMENT_P1}}">{{TECHNICAL_P1}}</td>
        <td align="center" title="{{REVIEWER_2}}: {{TECHNICAL_COMMENT_P2}}">{{TECHNICAL_P2}}</td>
        <td align="center">{{TECHNICAL_AVG}}</td>
        <td align="center">{{AVERAGE_P}}</td>
    </tr>
    """
    
    # layout of single row for each participant; content is added to "person_data"
    registrant_list = """
    On mouseover (put mouse cursor above mark) and additional explanation will be displayed. 
    <table class="list">
    <tr class="head">
        <th>&nbsp;</th>
        <th>&nbsp;</th>
        <th colspan="2">Comment</th>
        <th colspan="2">Pref.1</th>
        <th colspan="2">Pref.2</th>
        <th colspan="2">Pref.3</th>
        <th colspan="3">Motivation</th>
        <th colspan="3">Ambasador</th>
        <th colspan="3">Technical</th>
        <th>&nbsp;</th>
    </tr>
    <tr class="head">
        <th>No.</th>
        <th>Registrant</th>
        <th class="overall_comment">P1</th>
        <th class="overall_comment">P2</th>
        <th title="[X] = Student meet compulsory preferences.\n[  ] = Student DOES NOT meet compulsory preferences.">(?)</th>
        <th title="[X] = Student meet desirable prerequisites.\n[  ] = Student DOES NOT meet desirable preferences.">(?)</th>
        <th title="[X] = Student meet compulsory preferences.\n[  ] = Student DOES NOT meet compulsory preferences.">(?)</th>
        <th title="[X] = Student meet desirable prerequisites.\n[  ] = Student DOES NOT meet desirable preferences.">(?)</th>
        <th title="[X] = Student meet compulsory preferences.\n[  ] = Student DOES NOT meet compulsory preferences.">(?)</th>
        <th title="[X] = Student meet desirable prerequisites.\n[  ] = Student DOES NOT meet desirable preferences.">(?)</th>
        <th>P1</th>
        <th>P2</th>
        <th>Avg</th>
        <th>P1</th>
        <th>P2</th>
        <th>Avg</th>
        <th>P1</th>
        <th>P2</th>
        <th>Avg</th>
        <th>Average</th>
    </tr>
    {0}
    <tr class="foot">
        <th>No</th>
        <th>Registrant</th>
        <th colspan="2">Comment</th>
        <th colspan="2">Pref.1</th>
        <th colspan="2">Pref.2</th>
        <th colspan="2">Pref.3</th>
        <th colspan="3">Motivation</th>
        <th colspan="3">Ambasador</th>
        <th colspan="3">Technical</th>
        <th>Average</th>
    </tr>
    </table>
    """
    
    # layout of registrant daata + scores of evaluation + average scores
    person_row = """
    <tr class="{{REGISTRANT_SELECTED}}">
        <td class="id">{{I}}</td>
        <td><a href="{{HTML_FILENAME}}">{{REGISTRANT_NAME}}; {{COUNTRY}}, {{GENDER}}, {{AGE}} years (ID: {{REGISTRANT_ID}})</a><br>Preferred projects: {{PROJECT_ID_LIST}}</td>
        <td align="left" class="overall_comment"><i>{{REVIEWER_1}}:</i><br>{{OVERALL_COMMENT_1}}</td>
        <td align="left" class="overall_comment"><i>{{REVIEWER_2}}:</i><br>{{OVERALL_COMMENT_2}}</td>
        <td align="center" title="{{PREFERENCE_1_COMPULSORY}}">{{PREFERENCE_1_SHORT_COMPULSORY}}</td>
        <td align="center" title="{{PREFERENCE_1_DESIRABLE}}">{{PREFERENCE_1_SHORT_DESIRABLE}}</td>
        <td align="center" title="{{PREFERENCE_2_COMPULSORY}}">{{PREFERENCE_2_SHORT_COMPULSORY}}</td>
        <td align="center" title="{{PREFERENCE_2_DESIRABLE}}">{{PREFERENCE_2_SHORT_DESIRABLE}}</td>
        <td align="center" title="{{PREFERENCE_3_COMPULSORY}}">{{PREFERENCE_3_SHORT_COMPULSORY}}</td>
        <td align="center" title="{{PREFERENCE_3_DESIRABLE}}">{{PREFERENCE_3_SHORT_DESIRABLE}}</td>
        <td align="center" title="{{REVIEWER_1}}: {{MOTIVATION_COMMENT_P1}}">{{MOTIVATION_P1}}</td>
        <td align="center" title="{{REVIEWER_2}}: {{MOTIVATION_COMMENT_P2}}">{{MOTIVATION_P2}}</td>
        <td align="center">{{MOTIVATION_AVG}}</td>
        <td align="center" title="{{REVIEWER_1}}: {{AMBASADOR_COMMENT_P1}}">{{AMBASADOR_P1}}</td>
        <td align="center" title="{{REVIEWER_2}}: {{AMBASADOR_COMMENT_P2}}">{{AMBASADOR_P2}}</td>
        <td align="center">{{AMBASADOR_AVG}}</td>
        <td align="center" title="{{REVIEWER_1}}: {{TECHNICAL_COMMENT_P1}}">{{TECHNICAL_P1}}</td>
        <td align="center" title="{{REVIEWER_2}}: {{TECHNICAL_COMMENT_P2}}">{{TECHNICAL_P2}}</td>
        <td align="center">{{TECHNICAL_AVG}}</td>
        <td align="center">{{AVERAGE_P}}</td>
    </tr>
    """
    
    #
    # Save given title/date/content into given file
    #
    def save_content(filename, skeleton, title, date, content):
        skeleton = skeleton.replace("{{TITLE}}", title)
        skeleton = skeleton.replace("{{DATE}}",  date)
        skeleton = skeleton.replace("{{CONTENT}}", content)
        # open file and write content
        f = open(filename, "w")
        f.write(skeleton)
        f.close()
    
        return
    
    
    #
    # Read file and return header and data rows
    #
    def read_csv_file(filename):
        # Open the CSV file for reading -- evaluation data
        reader = csv.reader(open(filename))
        header_org = next(reader)
        header = []
        # correct names of fields (columns); remove all non-printable chars and "
        include = set(string.printable)
        
        for key in header_org:
            # check all header names/columns
            name = "".join(ch for ch in key if ch in include)
            name = name.replace('"', "")
            header.append(name)
        
        #print(header)
        # get header len = number of fields/columns
        header_len = len(header)
        
        data_rows = []
        # Read a single row from the CSV file
        for row in reader:
            if len(row) == 0:
                continue
            if len(row) != header_len:
                print("BAD DATA ROW ", ", ".join(row))
                continue
            data_rows.append(row)
    
        return { "header": header, "rows": data_rows } 
    
    #
    # Return number of points (score) for given evaluation part
    # 0 if not defined. Values are written as %d Points.
    #
    def get_points_from_evaluation(value):
        point = 0
        
        if value:
            # check 
            #print(value)
            tmp_point = value.split(" ")[0].strip()
            
            if tmp_point:
                point = int(tmp_point)
        
        return point
    
    
    #===========================================================
    #== MAIN 
    #===========================================================
    
    # read both files
    tmp_user_data = read_csv_file(sys.argv[1])
    eval_data = read_csv_file(sys.argv[2])
    
    #
    # create user_data dictionary with id as key and other data as dictionay 
    # for each row, keys are field names 
    user_data = {}
    
    for row in tmp_user_data['rows']:
        # process all rows
        dic=dict(zip(tmp_user_data['header'], row))
        #[print(key) for key in dic.keys()]
        if dic['ID'] == '':
            dic['ID'] = 0
        
        id = int(dic['ID'])
        link = glob.glob('../Application_Form/*_%d' % id)
        if len(link) == 0:
            print('Missing Application form for id %d' % id)
        link = link[0]
        dic.update({'link_application': "%s/index.html" % link})
        user_data.update({id:dic})
    
    
    #print(user_data)
    
    if not os.path.exists("reviews"):
        # if does not exist, create cubdir for storing HTML files
        os.makedirs("reviews")
        
    #get_file("cookies.txt", "54-0.pdf", "https://events.prace-ri.eu/event/367/manage/registration/users/54/attachments/0.pdf")
    print("Creating HTML files: ")
    
    # read registrant content template
    f = open("../evaluation-detail-format.html", "r")
    evaluation_content = f.read()
    f.close()
    
    n = datetime.now()
    generation_date = "{0}. {1}. {2} @ {3}:{4}".format(n.day, n.month, n.year, n.hour, n.minute)
    
    # data about projects and registrants sorted with project first, then all rgistrant data and scores...
    project_data = {}
    student_data = {}
    country_data = {}
    
    for id in user_data:
        # prepare array for student evaluation data
        student_data.update({id: {'motivation': {'p': ['', ''], 'comment': ['',''], 'avg': 0.}, 
                                  'ambasador': {'p': ['', ''], 'comment': ['',''], 'avg': 0.}, 
                                  'technical': {'p': ['', ''], 'comment': ['',''], 'avg': 0.}, 
                                  'average': 0.,
                                  'num_reviewers_done': 0,
                                  'evaluation_detail_file': ['',''],
                                  'reviewer': ['', ''], 
                                  'overall_comment': ['', ''],
                                  'preference': [[['',''], ['',''], ['','']], [['',''], ['',''], ['','']]]}
                             })
    
        # store countries into separate array
        ctryName = user_data[id]['Country']
        
        if not ctryName in country_data:
            # add country to array
            country_data.update({ctryName : {'all': 0, 'selected': 0, 'percent': 0.0 }})
            
        # add another student
        country_data[ctryName]['all'] += 1
    
    #print(student_data)
    #print(eval_data)
    for row in eval_data['rows']:
        # loop over all evaluations
        done_keys = {}
        dic=dict(zip(eval_data['header'], row))
    
    #    print(dic)
        userID=int(dic["Applicant number"])
        reviewerName=dic["Signature"].replace(" ","_")
        filename = "reviews/{0:03}_{1}.html".format(userID,reviewerName)
    
        #print("{0}: {1}".format(userID, user_data[userID]['Name']))
    #    print(" - evaluation defined")
    
        # store points form evaluation
        sum = 0
        numReviewer = student_data[userID]['num_reviewers_done']
        
        if numReviewer < 2:
            student_data[userID]['evaluation_detail_file'][numReviewer] = filename
            student_data[userID]['reviewer'][numReviewer] = dic["Signature"]
            student_data[userID]['overall_comment'][numReviewer] = dic["Overall recommendation and comment"]
            
        else:
            print("{0}: {1}".format(userID, user_data[userID]['Name']))
            print("   -->> ERROR: too many reviewers!! -- {0}; only first 2 reviewers used.".format(numReviewer+1))
            continue
        
        # 2019 remapping
        remap = {
        'motivation': 'Motivation & Enthusiasm',
        'ambasador': 'Ambassador Potential',
        'technical': 'Technical ability'
        }
        for part in ['motivation', 'ambasador', 'technical']:
            # parse all fields, store the points and compute the average
    
            point = get_points_from_evaluation(dic[remap[part]])
            #print("    - {0}: {1} -> {2} (reviever num: {3})".format(part, dic[remap[part]], point, numReviewer))
            #print(dic[remap[part] + " comment"])
    
            if numReviewer < 2:
                student_data[userID][part]['p'][numReviewer] = point
                student_data[userID][part]['comment'][numReviewer] = dic[remap[part] + " comment"]
                
            if numReviewer == 0:
                # average is current values 
                student_data[userID][part]['avg'] = student_data[userID][part]['p'][0]
                sum += student_data[userID][part]['avg']
                
            else:
                # compute average from both marks
                student_data[userID][part]['avg'] = 0.5*(student_data[userID][part]['p'][0]+student_data[userID][part]['p'][1])
                sum += student_data[userID][part]['avg']
    
        # compute the average
        student_data[userID]['average'] = sum/3.
        student_data[userID]['num_reviewers_done'] += 1
    
     #   print("    - avg: {0:.2f}".format(student_data[userID]['average']);)
        #
        # generate registrant presentation HTML
        #
        content = evaluation_content
        # current preference
        currentPreference = ''
    
        for i in range(0,len(eval_data['header'])):
            # loop over header to preserve key order
            key = eval_data['header'][i]
            value = row[i].strip()
            #print(key, "|" + value + "|")
            # replace value for all keys in row
            html_fld = key.replace(" ", "_").upper()
            
            #print("key: {0}".format(html_fld))
            
            if html_fld in done_keys:
                # current key was already used in current row; add number at the end
                #print("found: {0}".format(html_fld))
                done_keys[html_fld] += 1
                html_fld = "{0}__{1}".format(html_fld, done_keys[html_fld])
            else:
                # key not used; add it to array for checking later
                done_keys.update({html_fld: 1})
            
    #        print("key: " + key + ", html: " + html_fld + ", value=|" + value  + "|")
            #print(done_keys)
    
            content = content.replace("{{" + html_fld + "}}", value)
            
            if key == "Applicant number":
                # replace also add/replace participant full name and formated UID {0:03}
                userID = int(value)
                tmp_title = user_data[userID]['Name']
                formUID = value.strip().zfill(3)
                content = content.replace("{{REGISTRANT_NAME}}", tmp_title)
                content = content.replace("{{FORMATED_UID}}", formUID)
     
            elif key == "Submission Date":
                # 2019 format 
                # 2019-03-26 00:33:44.289498+00:00
                # display date + time in more nicer format
                #print(html_fld)
                if value != '':
                    # n = datetime.strptime(value, '%y-%m-%d %H:%M:%S.%f+%z')
                    # dateTime = "{0}. {1}. {2} @ {3}:{4}".format(n.day, n.month, n.year, n.hour, n.minute)
                    content = content.replace("{{" + html_fld +"_DISP}}", value)
                else:
                    content = content.replace("{{" + html_fld +"_DISP}}", "")
    
            elif key == 'Motivation & Enthusiasm':
                content = content.replace("{{%s}}" % "MOTIVATION", value)
    
            elif key == 'Motivation & Enthusiasm comment':
                content = content.replace("{{%s}}" % "MOTIVATION-COMMENT", value)
    
            elif key == 'Ambassador Potential':
                content = content.replace("{{%s}}" % "AMBASADOR", value)
    
            elif key == 'Ambassador Potential comment':
                content = content.replace("{{%s}}" % "AMBASADOR-COMMENT", value)
    
            elif key == 'Technical ability':
                content = content.replace("{{%s}}" % "TECHNICAL", value)
    
            elif key == 'Technical ability comment':
                content = content.replace("{{%s}}" % "TECHNICAL-COMMENT", value)
    
            elif key == 'Overall recommendation and comment':
                content = content.replace("{{%s}}" % "OVERALL", value)
    
            elif key.startswith("Project preference"):
                # process preference
                currentPreference = key[-1]
                #print('Current preference = ', currentPreference)
                currPrefIndex = int(currentPreference)-1
                # The string is in form:
                # Student meet compulsory preferences.; Student meet desirable prerequisites
                if 'meet compulsory' in value:
                    student_data[userID]['preference'][numReviewer][currPrefIndex][0] = "[X]"
                else:
                    student_data[userID]['preference'][numReviewer][currPrefIndex][0] = "[&nbsp;&nbsp;]"
    
                if 'meet desirable' in value:
                    student_data[userID]['preference'][numReviewer][currPrefIndex][1] = "[X]"
                else:
                    student_data[userID]['preference'][numReviewer][currPrefIndex][1] = "[&nbsp;&nbsp;]"
    
                if "not fit" in value:
                    #student_data[userID]['preference'][numReviewer][currPrefIndex][2] = "[X]"
                    content = content.replace("{{PREFERENCE_" + currentPreference +"_DOESNOTFIT}}", "[X]")
                else:
                    # student_data[userID]['preference'][numReviewer][currPrefIndex][2] = "[&nbsp;&nbsp;]";
                    content = content.replace("{{PREFERENCE_" + currentPreference +"_DOESNOTFIT}}", "[&nbsp;&nbsp;]")
    
                content = content.replace("{{PREFERENCE_" + currentPreference +"_COMPULSORY}}", student_data[userID]['preference'][numReviewer][currPrefIndex][0])
                content = content.replace("{{PREFERENCE_" + currentPreference +"_DESIRABLE}}", student_data[userID]['preference'][numReviewer][currPrefIndex][1])
                
        # add content into skeleton and write to file
        save_content(filename, skeleton, "Summer of HPC {0} - Registrant data".format(SoHPC_year), generation_date, content)
    
    # for fldName in ['First Choice', 'Second Choice', 'Third Choice']:
    #for fldName in ['1', '2', '3']:
    for fldName in ['Choice 1', 'Choice 2', 'Choice 3']:
        # get all three projects and first add all user's first choice, then second and then third choice
        for id in user_data:
            # loop over all users and extract projects and prepare arrays
            if user_data[id][fldName].strip():
                # project is defined
                proj = user_data[id][fldName].split(" ", 1)
    #            print(proj)
                projID = int(proj[0].strip())
                projName = proj[1].strip()
            
                if not projID in project_data:
                    # project does not exist; add an empty array for later addinf the data
                    initData = {'name': projName, 'students': [], 'selected_student': {}}
                    project_data.update({projID: initData})
    
                project_data[projID]['students'].append({'id': id, 'choice': fldName.split(" ")[0]})         
    
    
    for id in user_data:
        # loop over usr data and save selected students/registrants for each projct
        if user_data[id]['selected'].strip():
            # get project ID and order from selected number: 2001.1 (project ID.order of selection)
            _tmp = [el.strip() for el in user_data[id]['selected'].split(".")]
            projID = int(_tmp[0])
            projOrder = 0
    
            if len(_tmp) == 2:
                # get order from second part of 'selected' column
                if len(_tmp[1]) > 0:
                    projOrder = int(_tmp[1])
    
            project_data[projID]['selected_student'][projOrder] = id
            # get student country and change country stat data
            ctryName = user_data[id]['Country']
            country_data[ctryName]['selected'] += 1
            
    # now display project and student data into evaluation.html file
    content_projects = ""
    content_registrants = registrant_list
    
    # sort projects by projectID
    project_ids = sorted(project_data)
    
    #
    # layout project data + registrants for each project
    #
    proj_rows = ""
    proj_select = ""
    
    for projID in project_ids:
        # loop over all projects
        proj_row = project_html_data
        proj_row = proj_row.replace("{{PROJECT_NAME}}", project_data[projID]['name'])
        proj_row = proj_row.replace("{{PROJECT_ID}}", "{0}".format(projID))
    
        tmp_row = project_selected_participant_row.replace("{{PROJECT_ID}}", "{0}".format(projID))
        tmp_row = tmp_row.replace("{{PROJECT_NAME}}", project_data[projID]['name'])
        tmp_row = tmp_row.replace("{{PROJECT_ROW_SPAN}}", str(max(1, len(project_data[projID]['selected_student']))))
    
        if project_data[projID]['selected_student']:
            # add selected students in order defined in dict
            _cur_proj_students = ""
            _cur_proj_sep = ""
    
            for ordNum in sorted(project_data[projID]['selected_student'].keys()):
                # print students according to the order
                x = project_data[projID]['selected_student'][ordNum]
                _cur_proj_students += _cur_proj_sep+\
                    "<a href='{0}'>{1}</a> ({7})</td><td>{2}</td><td>{3}</td><td>{4}</td><td>{8}</td><td align='center'><a href='{5}'>[1]</a></td><td align='center'><a href='{6}'>[2]</a></td>"\
                    .format(user_data[x]['link_application'], user_data[x]['Name'],
                            user_data[x]['Country'], user_data[x]['Gender'],
                            user_data[x]['Age (years)'],
                            student_data[x]['evaluation_detail_file'][0],
                            student_data[x]['evaluation_detail_file'][1],
                            user_data[x]['ID'],
                            user_data[x]['Email'])
                _cur_proj_sep = "</tr><tr><td>"
            tmp_row = tmp_row.replace("{{PARTICIPANTS_LIST}}", _cur_proj_students)
        else:
            tmp_row = tmp_row.replace("{{PARTICIPANTS_LIST}}", "")
    
        proj_select += tmp_row
        
    #    proj_select += project_toc_row.format(projID, projID, project_data[projID]['name']);
        user_rows = ""
        no = 1
    
        # sort students by average value, not ID
        tmp_avg_list = []
    
        for student_row in project_data[projID]['students']:
            # create list of student IDs with their average value
            tmp_avg_list.append([max(0, student_data[student_row['id']]['average']), student_row['id'], student_row])
    
        for curr_row in sorted(tmp_avg_list, reverse=True):
            # display students according to their average value
            _, id, student_row = curr_row
            row = project_user_row
            row = row.replace("{{I}}", "{0}".format(no))
            row = row.replace("{{NAME}}", user_data[id]['Name'])
            row = row.replace("{{ID}}", user_data[id]['ID'])
            row = row.replace("{{COUNTRY}}", user_data[id]['Country'])
            row = row.replace("{{GENDER}}", user_data[id]['Gender'])
            row = row.replace("{{AGE}}", user_data[id]['Age (years)'])
            row = row.replace("{{CHOICE}}", student_row['choice'])
            row = row.replace("{{OVERALL}}", student_row['choice'])
            row = row.replace("{{HTML_FILENAME}}", user_data[id]['link_application'])
            row = row.replace("{{EVALUATION_HTML_LINK_1}}", student_data[id]['evaluation_detail_file'][0])
            row = row.replace("{{EVALUATION_HTML_LINK_2}}", student_data[id]['evaluation_detail_file'][1])
            row = row.replace("{{REVIEWER_1}}", student_data[id]['reviewer'][0])
            row = row.replace("{{REVIEWER_2}}", student_data[id]['reviewer'][1])
            row = row.replace("{{OVERALL_COMMENT_1}}", student_data[id]['overall_comment'][0])
            row = row.replace("{{OVERALL_COMMENT_2}}", student_data[id]['overall_comment'][1])
    
            if user_data[id]['selected']:
                # current student is selected for project; display it in special way
                row =  row.replace("{{REGISTRANT_SELECTED}}", "registrant_selected")
            else:
                # ordinary row
                row = row.replace("{{REGISTRANT_SELECTED}}", "")
    
            for part in ['motivation','ambasador','technical']:
                # add all parts
                html_fld = part.upper()
                #print(student_data[id].keys())
                #print(part in student_data[id])
                row = row.replace("{{"+ html_fld +"_P1}}", "{0}".format(student_data[id][part]['p'][0]))
                row = row.replace("{{"+ html_fld +"_P2}}", "{0}".format(student_data[id][part]['p'][1]))
                row = row.replace("{{"+ html_fld +"_COMMENT_P1}}", "{0}".format(student_data[id][part]['comment'][0]))
                row = row.replace("{{"+ html_fld +"_COMMENT_P2}}", "{0}".format(student_data[id][part]['comment'][1]))
        
                if student_data[id][part]['avg'] > 0:
                    row = row.replace("{{"+ html_fld +"_AVG}}", "{0:.2f}".format(student_data[id][part]['avg']))
                else:
                    row = row.replace("{{"+ html_fld +"_AVG}}", "")
                
            if student_data[id]['average'] > 0:
                row = row.replace("{{AVERAGE_P}}", "{0:.2f}".format(student_data[id]['average']))
            else:
                row = row.replace("{{AVERAGE_P}}", "")
    
            for prefNo in range(1,4):
                # display all preferences
                row = row.replace("{{PREFERENCE_" + "{0}".format(prefNo) +"_SHORT_COMPULSORY}}", 
                                  "{0}<br>{1}".format(student_data[id]['preference'][0][prefNo-1][0], student_data[id]['preference'][1][prefNo-1][0]))
                row = row.replace("{{PREFERENCE_" + "{0}".format(prefNo) +"_SHORT_DESIRABLE}}", 
                                  "{0}<br>{1}".format(student_data[id]['preference'][0][prefNo-1][1], student_data[id]['preference'][1][prefNo-1][1]))
                row = row.replace("{{PREFERENCE_" + "{0}".format(prefNo) +"_COMPULSORY}}", 
                                  "{0}: {1}\n{2}: {3}".format(student_data[id]['reviewer'][0], student_data[id]['preference'][0][prefNo-1][0], 
                                                                student_data[id]['reviewer'][1], student_data[id]['preference'][1][prefNo-1][0]))
                row = row.replace("{{PREFERENCE_" + "{0}".format(prefNo) +"_DESIRABLE}}", 
                                  "{0}: {1}\n{2}: {3}".format(student_data[id]['reviewer'][0], student_data[id]['preference'][0][prefNo-1][1], 
                                                                student_data[id]['reviewer'][1], student_data[id]['preference'][1][prefNo-1][1]))
    
            user_rows += row
            no += 1
    
        proj_row = proj_row.replace("{{REGISTRANT_DATA}}", user_rows)
        proj_rows += proj_row
    
    #print(project_data)
    #print(proj_select)
    #print(proj_rows)
    
    index_data = index_data.replace("{{PROJECT_LIST_AND_SELECTED_PARTICIPANTS}}", proj_select)
    content_projects = proj_rows
    
    
    #
    # display country statistics: all + selected registrants + percents
    country_rows = ""
    country_list_sorted = sorted(country_data)
    
    for ctryName in country_list_sorted:
        # loop over all countries
        row = ""
        perc = 100 * country_data[ctryName]['selected'] * 1.0 / country_data[ctryName]['all']
        country_rows += "<tr><td>{0}</td><td class='id'>{1}</td><td class='id'>{2}</td><td class='id'>{3:.1f}</td></tr>".format(
                                ctryName, country_data[ctryName]['all'], country_data[ctryName]['selected'], perc)
    
    index_data = index_data.replace("{{COUNTRY_PARTICIPANTS_LIST}}", country_rows)
    
    # layout of registrant data + scores of evaluation + average scores
    user_avg = {}
    
    for id in user_data:
        # loop over usr data and create {key: avg} for sorting
        user_avg.update({id: student_data[id]['average']})
        
    # now sort it
    user_sorted = Counter(user_avg)
    
    rows = ""
    no = 1
    for cell in user_sorted.most_common():
        # loop over usr data and create registrant data
        id = cell[0]
        row = person_row
        row = row.replace("{{I}}", "{0}".format(no))
        row = row.replace("{{REGISTRANT_NAME}}", user_data[id]['Name'])
        row = row.replace("{{COUNTRY}}", user_data[id]['Country'])
        row = row.replace("{{GENDER}}", user_data[id]['Gender'])
        row = row.replace("{{AGE}}", user_data[id]['Age (years)'])
        row = row.replace("{{REGISTRANT_ID}}", user_data[id]['ID'])
        row = row.replace("{{HTML_FILENAME}}", user_data[id]['link_application'])
        row = row.replace("{{REVIEWER_1}}", student_data[id]['reviewer'][0])
        row = row.replace("{{REVIEWER_2}}", student_data[id]['reviewer'][1])
        row = row.replace("{{OVERALL_COMMENT_1}}", student_data[id]['overall_comment'][0])
        row = row.replace("{{OVERALL_COMMENT_2}}", student_data[id]['overall_comment'][1])
        project_list_tmp = ""
        sep = ""
        
        if user_data[id]['selected']:
            # current student is selected for project; display it in special way
            row = row.replace("{{REGISTRANT_SELECTED}}", "registrant_selected")
        else:
            # ordinary row
            row = row.replace("{{REGISTRANT_SELECTED}}", "")
    
    #    for fldName in ['1', '2', '3']:
        for fldName in ['Choice 1', 'Choice 2', 'Choice 3']:        
            # get all three projects and first add all user's first choise, then second and then third choice
            if user_data[id][fldName].strip():
                # project is defined
                proj = user_data[id][fldName].split(" ", 1)
                projID = int(proj[0].strip())
                project_list_tmp += "{0} <a href='#project_{1}'>{2}</a>".format(sep,projID,projID)
                sep = ", "
    
        row = row.replace("{{PROJECT_ID_LIST}}", project_list_tmp)
    
        for part in ['motivation','ambasador','technical']:
            # add all parts
            html_fld = part.upper()
            row = row.replace("{{"+ html_fld +"_P1}}", "{0}".format(student_data[id][part]['p'][0]))
            row = row.replace("{{"+ html_fld +"_P2}}", "{0}".format(student_data[id][part]['p'][1]))
            row = row.replace("{{"+ html_fld +"_COMMENT_P1}}", "{0}".format(student_data[id][part]['comment'][0]))
            row = row.replace("{{"+ html_fld +"_COMMENT_P2}}", "{0}".format(student_data[id][part]['comment'][1]))
    
            if student_data[id][part]['avg'] > 0:
                row = row.replace("{{"+ html_fld +"_AVG}}", "{0:.2f}".format(student_data[id][part]['avg']))
            else:
                row = row.replace("{{"+ html_fld +"_AVG}}", "")
            
        if student_data[id]['average'] > 0:
            row = row.replace("{{AVERAGE_P}}", "{0:.2f}".format(student_data[id]['average']))
        else:
            row = row.replace("{{AVERAGE_P}}", "")
    
        for prefNo in range(1,4):
            # display all preferences
            row = row.replace("{{PREFERENCE_" + "{0}".format(prefNo) +"_SHORT_COMPULSORY}}", 
                              "{0}<br>{1}".format(student_data[id]['preference'][0][prefNo-1][0], student_data[id]['preference'][1][prefNo-1][0]))
            row = row.replace("{{PREFERENCE_" + "{0}".format(prefNo) +"_SHORT_DESIRABLE}}", 
                              "{0}<br>{1}".format(student_data[id]['preference'][0][prefNo-1][1], student_data[id]['preference'][1][prefNo-1][1]))
            row = row.replace("{{PREFERENCE_" + "{0}".format(prefNo) +"_COMPULSORY}}", 
                              "{0}: {1}\n{2}: {3}".format(student_data[id]['reviewer'][0], student_data[id]['preference'][0][prefNo-1][0], 
                                                            student_data[id]['reviewer'][1], student_data[id]['preference'][1][prefNo-1][0]))
            row = row.replace("{{PREFERENCE_" + "{0}".format(prefNo) +"_DESIRABLE}}", 
                              "{0}: {1}\n{2}: {3}".format(student_data[id]['reviewer'][0], student_data[id]['preference'][0][prefNo-1][1], 
                                                            student_data[id]['reviewer'][1], student_data[id]['preference'][1][prefNo-1][1]))
    
        rows += row
        no += 1
        
        
    content_registrants = registrant_list.format(rows)
    
    # add persons list into "index" file content
    content = index_data
    content = content.replace("{{CONTENT_PROJECTS}}", content_projects)
    content = content.replace("{{CONTENT_REGISTRANTS}}", content_registrants)
    save_content("evaluation.html", skeleton, "Summer of HPC {0} - Project evaluation results".format(SoHPC_year), generation_date, content)
    
    print("All done!")