Select Git revision
GeometryFactory.cpp
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>] [<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%"> </td>
<td>
Countries - all and selected.
<table class="list">
<tr class="head">
<th> </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>] [<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> </th>
<th> </th>
<th> </th>
<th> </th>
<th> </th>
<th> </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> </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> </th>
<th> </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> </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] = "[ ]"
if 'meet desirable' in value:
student_data[userID]['preference'][numReviewer][currPrefIndex][1] = "[X]"
else:
student_data[userID]['preference'][numReviewer][currPrefIndex][1] = "[ ]"
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] = "[ ]";
content = content.replace("{{PREFERENCE_" + currentPreference +"_DOESNOTFIT}}", "[ ]")
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!")