Select Git revision
FrameElement.cpp
create-evaluation-files.py 36.31 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.py \
# ../RegistrantsList.csv ../evaluation-results.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
#
# 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><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 2019 - Registrant data", 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 choise, 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(" ")[1]});
for id in user_data:
# loop over usr data and save selected students/registrants for each projct
if user_data[id]['selected'].strip():
projID = int(user_data[id]['selected'].strip());
project_data[projID]['selected_student'].append(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 projets
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']);
if project_data[projID]['selected_student']:
tmp_row = tmp_row.replace("{{PARTICIPANTS_LIST}}",
"<br>".join("<a href='{0}'>{1}</a> ({7})</td><td>{2}</td><td>{3}</td><td>{4}</td><td align='center'><a href='{5}'>[1]</a></td><td align='center'><a href='{6}'>[2]</a></td><td>{8}</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'])
for x in project_data[projID]['selected_student']));
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;
for student_row in sorted(project_data[projID]['students'], key=lambda student_row: (student_row['choice'], -student_data[student_row['id']]['average'], student_row['id'])):
# create list of students in current project
id = student_row['id'];
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(proj_select)
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 2018 - Project evaluation results", generation_date, content)
print("All done!")