Commit e3e4041f7862400ca7c66b3e1b943de944b869de

Authored by Tássia Camões Araújo
1 parent dabda648
Exists in master and in 1 other branch add_vagrant

Last modifications before releasing survey.

src/web/static/css/survey.css
@@ -97,6 +97,7 @@ margin-bottom: 10px; @@ -97,6 +97,7 @@ margin-bottom: 10px;
97 } 97 }
98 98
99 .radioButton, 99 .radioButton,
  100 +#start-button,
100 #next-button, 101 #next-button,
101 #restart-button, 102 #restart-button,
102 #continue-button, 103 #continue-button,
@@ -148,7 +149,7 @@ cursor: pointer; @@ -148,7 +149,7 @@ cursor: pointer;
148 #panel-controls { 149 #panel-controls {
149 position: relative; 150 position: relative;
150 width: 200px; 151 width: 200px;
151 -height: 60px; 152 +height: 80px;
152 padding: 5px; 153 padding: 5px;
153 margin: 5px; 154 margin: 5px;
154 border-radius: 5px; 155 border-radius: 5px;
src/web/survey.py
@@ -12,6 +12,7 @@ import urllib @@ -12,6 +12,7 @@ import urllib
12 import socket 12 import socket
13 import csv 13 import csv
14 import datetime 14 import datetime
  15 +import stat
15 16
16 sys.path.insert(0,"/var/www/AppRecommender/src/") 17 sys.path.insert(0,"/var/www/AppRecommender/src/")
17 18
@@ -38,15 +39,16 @@ class Thanks: @@ -38,15 +39,16 @@ class Thanks:
38 user_id = web_input['user_id'].encode('utf8') 39 user_id = web_input['user_id'].encode('utf8')
39 personal_file = open("/var/www/AppRecommender/src/web/submissions/%s/personal" % user_id,'w') 40 personal_file = open("/var/www/AppRecommender/src/web/submissions/%s/personal" % user_id,'w')
40 personal = {} 41 personal = {}
41 - for key in ["name","email","comments"]: 42 + for key in ["name","email","user_habits","comments"]:
42 if web_input.has_key(key): 43 if web_input.has_key(key):
43 personal[key] = web_input[key].encode("utf-8") 44 personal[key] = web_input[key].encode("utf-8")
44 else: 45 else:
45 personal[key] = "" 46 personal[key] = ""
46 try: 47 try:
47 writer = csv.writer(personal_file) 48 writer = csv.writer(personal_file)
48 - writer.writerow(("user","name","email","comments"))  
49 - writer.writerow((user_id,personal["name"],personal["email"],personal["comments"])) 49 + writer.writerow(("user","name","email","habits_id","comments"))
  50 + writer.writerow((user_id,personal["name"],personal["email"],
  51 + personal["user_habits"],personal["comments"]))
50 except: 52 except:
51 error_msg = "Could not save optional information." 53 error_msg = "Could not save optional information."
52 logging.critical("Could not save optional information.") 54 logging.critical("Could not save optional information.")
@@ -72,7 +74,8 @@ class Save: @@ -72,7 +74,8 @@ class Save:
72 % (user_id,strategy)) 74 % (user_id,strategy))
73 summary = {} 75 summary = {}
74 summary["poor"] = 0 76 summary["poor"] = 0
75 - summary["good"] = 0 77 + summary["redundant"] = 0
  78 + summary["useful"] = 0
76 summary["surprising"] = 0 79 summary["surprising"] = 0
77 80
78 # Save evaluation 81 # Save evaluation
@@ -94,44 +97,42 @@ class Save: @@ -94,44 +97,42 @@ class Save:
94 summary[evaluation] += 1 97 summary[evaluation] += 1
95 break 98 break
96 prediction_file.seek(0) 99 prediction_file.seek(0)
  100 + prediction_file.close()
  101 + evaluation_file.close()
97 except: 102 except:
98 error_msg = "Could not write evaluation to file." 103 error_msg = "Could not write evaluation to file."
99 logging.critical(error_msg) 104 logging.critical(error_msg)
100 return render.error([error_msg], "/survey/","START") 105 return render.error([error_msg], "/survey/","START")
101 finally: 106 finally:
102 - prediction_file.close()  
103 - evaluation_file.close()  
104 os.remove(os.path.join(strategy_dir,"prediction")) 107 os.remove(os.path.join(strategy_dir,"prediction"))
105 with open(os.path.join(strategy_dir,"end"),'w') as end: 108 with open(os.path.join(strategy_dir,"end"),'w') as end:
106 end_time = datetime.datetime.now().strftime("%Y%m%d%H%M%S") 109 end_time = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
107 end.write(end_time) 110 end.write(end_time)
108 111
109 # Save report 112 # Save report
110 - try:  
111 - report = os.path.join(user_dir,"report")  
112 - report_file = open(os.path.join(user_dir,"report"),'a')  
113 - writer = csv.writer(report_file)  
114 - if os.path.getsize(report) == 0:  
115 - fieldnames = ('user','strategy',"start","end",'truepositive',  
116 - 'falsepositive','surprise','comments')  
117 - writer.writerow(fieldnames)  
118 - with open(os.path.join(strategy_dir,"start"),'r') as start:  
119 - start_time = start.readline().strip()  
120 - if web_input.has_key("comments"):  
121 - comments = web_input['comments'].encode("utf-8")  
122 - else:  
123 - comments = ""  
124 - writer.writerow((user_id,strategy,start_time,end_time,  
125 - summary["good"]+summary["surprising"],  
126 - summary["poor"],summary["surprising"],comments))  
127 - except:  
128 - if comments:  
129 - error_msg = "Could not save comments."  
130 - logging.critical(error_msg)  
131 - return render.error([error_msg], "/survey/","START")  
132 - logging.critical("Could not save evaluation report.")  
133 - finally:  
134 - report_file.close() 113 + #try:
  114 + report = os.path.join(user_dir,"report")
  115 + report_file = open(os.path.join(user_dir,"report"),'a')
  116 + writer = csv.writer(report_file)
  117 + if os.path.getsize(report) == 0:
  118 + fieldnames = ('user','strategy','start','end','poor',
  119 + 'redundant','useful','surprising','comments')
  120 + writer.writerow(fieldnames)
  121 + with open(os.path.join(strategy_dir,"start"),'r') as start:
  122 + start_time = start.readline().strip()
  123 + if web_input.has_key("comments"):
  124 + comments = web_input['comments'].encode("utf-8")
  125 + else:
  126 + comments = ""
  127 + writer.writerow((user_id,strategy,start_time,end_time,summary["poor"],
  128 + summary["redundant"],summary["useful"],
  129 + summary["surprising"],comments))
  130 + #except:
  131 + # error_msg = "Could not save evaluation report."
  132 + # logging.critical(error_msg)
  133 + # return render.error([error_msg], "/survey/","START")
  134 + #finally:
  135 + # report_file.close()
135 136
136 if web_input.has_key('continue_button'): 137 if web_input.has_key('continue_button'):
137 return Survey().POST() 138 return Survey().POST()
@@ -140,42 +141,26 @@ class Save: @@ -140,42 +141,26 @@ class Save:
140 else: 141 else:
141 return render.index_survey() 142 return render.index_survey()
142 143
143 -class Request:  
144 - def __init__(self,web_input,submissions_dir):  
145 - self.strategy = ""  
146 - # Check if it is first round  
147 - if web_input.has_key('user_id'):  
148 - self.user_id = web_input['user_id'].encode('utf8')  
149 - self.user_dir = os.path.join(submissions_dir, self.user_id)  
150 - logging.info("New round for user %s" % self.user_id)  
151 - else:  
152 - self.user_dir = tempfile.mkdtemp(prefix='',dir=submissions_dir)  
153 - self.user_id = self.user_dir.split("/")[-1]  
154 - logging.info("Request from user %s" % self.user_id)  
155 - logging.debug("Created dir %s" % self.user_dir)  
156 - uploaded_file = os.path.join(self.user_dir,"uploaded_file") 144 +class Instruction:
  145 + def POST(self):
  146 + web_input = web.input(pkgs_file={})
  147 + submissions_dir = "/var/www/AppRecommender/src/web/submissions/"
  148 + user_dir = tempfile.mkdtemp(prefix='',dir=submissions_dir)
  149 + os.chmod(user_dir,stat.S_IRWXU|stat.S_IXOTH|stat.S_IROTH)
  150 + user_id = user_dir.split("/")[-1]
  151 + logging.info("Request from user %s" % user_id)
  152 + logging.debug("Created dir %s" % user_dir)
  153 + uploaded_file = os.path.join(user_dir,"uploaded_file")
157 if not os.path.exists(uploaded_file): 154 if not os.path.exists(uploaded_file):
158 if web_input['pkgs_file'].value: 155 if web_input['pkgs_file'].value:
159 lines = web_input['pkgs_file'].file.readlines() 156 lines = web_input['pkgs_file'].file.readlines()
160 with open(uploaded_file, "w") as uploaded: 157 with open(uploaded_file, "w") as uploaded:
161 uploaded.writelines(lines) 158 uploaded.writelines(lines)
162 - with open(uploaded_file) as uploaded:  
163 - if uploaded.readline().startswith('POPULARITY-CONTEST'):  
164 - self.user = PopconSystem(uploaded_file,self.user_id)  
165 else: 159 else:
166 - self.user = PkgsListSystem(uploaded_file,self.user_id)  
167 -  
168 - def __str__(self):  
169 - return "Request %s:\n %s" % (self.user.user_id,  
170 - str(self.user.pkg_profile))  
171 -  
172 - def validates(self):  
173 - self.errors = []  
174 - if not self.user.pkg_profile:  
175 - self.errors.append("No packages list provided.")  
176 - if self.errors:  
177 - return False  
178 - return True 160 + # saving empty files
  161 + with open(uploaded_file, "w") as uploaded:
  162 + pass
  163 + return render.intro(user_id)
179 164
180 class Survey: 165 class Survey:
181 def __init__(self): 166 def __init__(self):
@@ -185,24 +170,46 @@ class Survey: @@ -185,24 +170,46 @@ class Survey:
185 self.submissions_dir = "/var/www/AppRecommender/src/web/submissions/" 170 self.submissions_dir = "/var/www/AppRecommender/src/web/submissions/"
186 if not os.path.exists(self.submissions_dir): 171 if not os.path.exists(self.submissions_dir):
187 os.makedirs(self.submissions_dir) 172 os.makedirs(self.submissions_dir)
188 - 173 + self.strategies = ["cbh","cbh_eset",
  174 + "knn","knn_eset","knn_plus",
  175 + "knnco"]
189 def POST(self): 176 def POST(self):
190 web_input = web.input(pkgs_file={}) 177 web_input = web.input(pkgs_file={})
191 - logging.debug("Survey web_input %s" % str(web_input))  
192 - self.strategies = ["cb","cbh","cb_eset","cbh_eset",  
193 - "knn","knn_eset","knn_plus",  
194 - "knnco","knnco_eset"]  
195 - request = Request(web_input,self.submissions_dir)  
196 - if len(request.user.pkg_profile)<10: 178 + if web_input.has_key('user_id'):
  179 + user_id = web_input['user_id'].encode('utf8')
  180 + user_dir = os.path.join(self.submissions_dir, user_id)
  181 + logging.info("New recommendation for user %s" % user_id)
  182 +
  183 + uploaded_file = os.path.join(user_dir,"uploaded_file")
  184 + with open(uploaded_file) as uploaded:
  185 + if uploaded.readline().startswith('POPULARITY-CONTEST'):
  186 + user = PopconSystem(uploaded_file,user_id)
  187 + else:
  188 + user = PkgsListSystem(uploaded_file,user_id)
  189 + user.maximal_pkg_profile()
  190 + if len(user.pkg_profile)<10:
197 error_msg = "Could not extract profile from uploaded file. It must have at least 10 applications." 191 error_msg = "Could not extract profile from uploaded file. It must have at least 10 applications."
198 logging.critical(error_msg) 192 logging.critical(error_msg)
199 return render.error([error_msg], "/survey/","START") 193 return render.error([error_msg], "/survey/","START")
200 else: 194 else:
201 - request.strategy = self.set_rec_strategy(request.user_id)  
202 - prediction = self.rec.get_recommendation(request.user,10).get_prediction()  
203 - logging.info("Prediction for user %s" % request.user_id) 195 + # Check the remaining strategies and select a new one
  196 + old_strategies = [dirs for root, dirs, files in
  197 + os.walk(os.path.join(self.submissions_dir,
  198 + user_id))]
  199 + if old_strategies:
  200 + strategies = [s for s in self.strategies if s not in old_strategies[0]]
  201 + logging.info("Already used strategies %s" % old_strategies[0])
  202 + else:
  203 + strategies = self.strategies
  204 + if not strategies:
  205 + return render.thanks(user_id)
  206 + selected_strategy = random.choice(strategies)
  207 + logging.info("Selected \'%s\' from %s" % (selected_strategy,strategies))
  208 + self.set_rec_strategy(selected_strategy)
  209 + prediction = self.rec.get_recommendation(user,10).get_prediction()
  210 + logging.info("Prediction for user %s" % user_id)
204 logging.info(str(prediction)) 211 logging.info(str(prediction))
205 - self.save_prediction(request,prediction) 212 + self.save_prediction(user_id,selected_strategy,prediction)
206 213
207 # Load packages details 214 # Load packages details
208 recommendation = [result[0] for result in prediction] 215 recommendation = [result[0] for result in prediction]
@@ -215,32 +222,15 @@ class Survey: @@ -215,32 +222,15 @@ class Survey:
215 222
216 if pkgs_details: 223 if pkgs_details:
217 logging.info("Rendering survey slide...") 224 logging.info("Rendering survey slide...")
218 - return render.survey(pkgs_details, request) 225 + return render.survey(pkgs_details, user_id, selected_strategy, len(strategies))
219 else: 226 else:
220 return render.error(["No recommendation produced for the uploaded file."],"/survey/","START") 227 return render.error(["No recommendation produced for the uploaded file."],"/survey/","START")
221 228
222 - def set_rec_strategy(self,user_id):  
223 - # Check the remaining strategies and select a new one  
224 - old_strategies = [dirs for root, dirs, files in  
225 - os.walk(os.path.join(self.submissions_dir,  
226 - user_id))]  
227 - if old_strategies:  
228 - strategies = [s for s in self.strategies if s not in old_strategies[0]]  
229 - logging.info("Already used strategies %s" % old_strategies[0])  
230 - else:  
231 - strategies = self.strategies  
232 - if not strategies:  
233 - return render.thanks(request.user_id)  
234 - selected_strategy = random.choice(strategies)  
235 - logging.info("Selected \'%s\' from %s" % (selected_strategy,strategies))  
236 - k=50  
237 - n=50  
238 - if selected_strategy == "cb":  
239 - pass 229 + def set_rec_strategy(self,selected_strategy):
  230 + k=10
  231 + n=20
240 if selected_strategy == "cbh": 232 if selected_strategy == "cbh":
241 pass 233 pass
242 - if selected_strategy == "cb_eset":  
243 - pass  
244 if selected_strategy == "cbh_eset": 234 if selected_strategy == "cbh_eset":
245 pass 235 pass
246 if selected_strategy == "knn": 236 if selected_strategy == "knn":
@@ -251,13 +241,11 @@ class Survey: @@ -251,13 +241,11 @@ class Survey:
251 pass 241 pass
252 if selected_strategy == "knnco": 242 if selected_strategy == "knnco":
253 pass 243 pass
254 - if selected_strategy == "knnco_eset":  
255 - pass  
256 self.rec.set_strategy(selected_strategy,k,n) 244 self.rec.set_strategy(selected_strategy,k,n)
257 return selected_strategy 245 return selected_strategy
258 246
259 - def save_prediction(self,request,prediction):  
260 - strategy_dir = os.path.join(request.user_dir,request.strategy) 247 + def save_prediction(self,user_id,strategy,prediction):
  248 + strategy_dir = os.path.join(self.submissions_dir,user_id,strategy)
261 if not os.path.exists(strategy_dir): 249 if not os.path.exists(strategy_dir):
262 os.makedirs(strategy_dir) 250 os.makedirs(strategy_dir)
263 ranking = 0 251 ranking = 0
@@ -279,7 +267,7 @@ class Survey: @@ -279,7 +267,7 @@ class Survey:
279 now = datetime.datetime.now() 267 now = datetime.datetime.now()
280 start.write(now.strftime("%Y%m%d%H%M%S")) 268 start.write(now.strftime("%Y%m%d%H%M%S"))
281 logging.debug("Saved prediction to file at %s/%s" % 269 logging.debug("Saved prediction to file at %s/%s" %
282 - (request.user_id,request.strategy)) 270 + (user_id,strategy))
283 #def add_global_hook(): 271 #def add_global_hook():
284 # g = web.storage({"counter": "1"}) 272 # g = web.storage({"counter": "1"})
285 # def _wrapper(handler): 273 # def _wrapper(handler):
@@ -290,7 +278,8 @@ class Survey: @@ -290,7 +278,8 @@ class Survey:
290 render = web.template.render('/var/www/AppRecommender/src/web/templates/', base='layout', globals={'hasattr':hasattr}) 278 render = web.template.render('/var/www/AppRecommender/src/web/templates/', base='layout', globals={'hasattr':hasattr})
291 render_plain = web.template.render('/var/www/AppRecommender/src/web/templates/', globals={'hasattr':hasattr}) 279 render_plain = web.template.render('/var/www/AppRecommender/src/web/templates/', globals={'hasattr':hasattr})
292 280
293 -urls = ('/apprec', 'Survey', 281 +urls = ('/apprec', 'Instruction',
  282 + '/evaluation', 'Survey',
294 '/thanks', 'Thanks', 283 '/thanks', 'Thanks',
295 '/save', 'Save', 284 '/save', 'Save',
296 '/about', 'About', 285 '/about', 'About',
src/web/templates/index_survey.html
@@ -23,7 +23,7 @@ window.onload = function() { @@ -23,7 +23,7 @@ window.onload = function() {
23 <a href="http://github.com/tassia/AppRecommender">AppRecommender</a>, 23 <a href="http://github.com/tassia/AppRecommender">AppRecommender</a>,
24 a recommender system for GNU/Linux applications.</p><br /> 24 a recommender system for GNU/Linux applications.</p><br />
25 <p align="justify"> Given a list of packages installed in a real 25 <p align="justify"> Given a list of packages installed in a real
26 - running system and a set of applications will be suggested for it. 26 + running system, a set of applications will be suggested for it.
27 Upload a popularity-contest submission file (usually located at 27 Upload a popularity-contest submission file (usually located at
28 '/var/log/popularity-contest') or run the following command and 28 '/var/log/popularity-contest') or run the following command and
29 upload the generated 'packages.list' file.</p><br /> 29 upload the generated 'packages.list' file.</p><br />
src/web/templates/layout.html
@@ -80,7 +80,7 @@ function validateForm() @@ -80,7 +80,7 @@ function validateForm()
80 <div id="upload-slide"> 80 <div id="upload-slide">
81 <fieldset> 81 <fieldset>
82 <p> 82 <p>
83 - <label title="Upload file">Installed packages file: <input type="file" name="pkgs_file" size="20" /></label> 83 + <label title="Upload file">Installed packages: <input type="file" name="pkgs_file" size="20" /></label>
84 </p> 84 </p>
85 <div id="tip-upload" class="tip important"> 85 <div id="tip-upload" class="tip important">
86 <p> 86 <p>
src/web/templates/survey.html
1 -$def with (pkgs_details, request) 1 +$def with (pkgs_details, user_id, strategy, remaining)
2 $var title: Survey 2 $var title: Survey
3 $var url_base: /survey/ 3 $var url_base: /survey/
4 $var action: START 4 $var action: START
@@ -28,16 +28,20 @@ $var jsfiles: /static/coda-slider-2.0/javascripts/jquery-1.3.2.min.js /static/co @@ -28,16 +28,20 @@ $var jsfiles: /static/coda-slider-2.0/javascripts/jquery-1.3.2.min.js /static/co
28 28
29 <div class="show-end" style="display: none;"> 29 <div class="show-end" style="display: none;">
30 30
31 -<p>  
32 -If you have any comment regarding this set of suggestions, please write in the form below. Choose <i>Continue</i> if you can perform another round of evaluations, or <i>Finish</i> to conclude your participation. 31 +<p align="justify">
  32 +If you have any comments regarding this set of suggestions, please write in the
  33 +form below. There are <b>$(remaining-1) remaining</b> recommendation strategies to be evaluated.
  34 +Choose <i>Continue</i> if you can perform one more round of evaluations, or
  35 +<i>Finish</i> to conclude your participation.
33 </p> 36 </p>
34 37
35 </div> 38 </div>
36 39
37 <form action="save" method="post" enctype="multipart/form-data" name="surveyform"> 40 <form action="save" method="post" enctype="multipart/form-data" name="surveyform">
38 41
39 -<input type="hidden" name="user_id" value=$request.user.user_id>  
40 -<input type="hidden" name="strategy" value=$request.strategy> 42 +<input type="hidden" name="user_id" value=$user_id>
  43 +<input type="hidden" name="strategy" value=$strategy>
  44 +<input type="hidden" name="remaining" value=$remaining>
41 45
42 <div style="display: none; width: 400px; margin-left: 150px; margin-top: 10px;" class="show-end"><!-- display show in the end form --> 46 <div style="display: none; width: 400px; margin-left: 150px; margin-top: 10px;" class="show-end"><!-- display show in the end form -->
43 <p align="center"> 47 <p align="center">
@@ -62,16 +66,20 @@ $for pkg in pkgs_details: @@ -62,16 +66,20 @@ $for pkg in pkgs_details:
62 <div id="panel-controls" class="glass"> 66 <div id="panel-controls" class="glass">
63 <fieldset> 67 <fieldset>
64 <label class="radioButton"> 68 <label class="radioButton">
65 - <input class="radio" type="radio" name="evaluation-$pkgs_details.index(pkg)" value="surprising" />  
66 - Pleasantly surprising 69 + <input class="radio" type="radio" name="evaluation-$(pkgs_details.index(pkg))" value="poor" />
  70 + Poor
  71 + </label><br />
  72 + <label class="radioButton">
  73 + <input class="radio" type="radio" name="evaluation-$(pkgs_details.index(pkg))" value="redundant" />
  74 + Redundant
67 </label><br /> 75 </label><br />
68 <label class="radioButton"> 76 <label class="radioButton">
69 - <input class="radio yesb" type="radio" name="evaluation-$pkgs_details.index(pkg)" value="good" /> 77 + <input class="radio" type="radio" name="evaluation-$pkgs_details.index(pkg)" value="useful" />
70 Useful 78 Useful
71 </label><br /> 79 </label><br />
72 <label class="radioButton"> 80 <label class="radioButton">
73 - <input class="radio" type="radio" name="evaluation-$(pkgs_details.index(pkg))" value="poor" />  
74 - Poor 81 + <input class="radio" type="radio" name="evaluation-$pkgs_details.index(pkg)" value="surprising" />
  82 + Pleasantly surprising
75 </label> 83 </label>
76 </fieldset> 84 </fieldset>
77 <br style="clear: both;" /> 85 <br style="clear: both;" />
src/web/templates/thanks.html
@@ -14,14 +14,25 @@ $var cssfiles: static/css/survey.css @@ -14,14 +14,25 @@ $var cssfiles: static/css/survey.css
14 <div class="innertube"> 14 <div class="innertube">
15 15
16 <h1>AppRecommender Survey</h1> 16 <h1>AppRecommender Survey</h1>
17 -<p>Thank you very much for participating in this survey, you help is very much  
18 -appreciated! Identify yourself if you want to be mentioned in our thanks page  
19 -and final report.  
20 -</p><br /> 17 +<p>Thank you very much for participating in this survey!</p>
  18 +<p>Last but not least, we'd like to have your personal identification to mention
  19 +your name in our thanks page. The awareness of your installation habits would
  20 +make our report more informative and, finally, we appreciate general comments
  21 +regarding this survey and/or the recommendations you got.</p>
21 22
22 <div style="margin-left:150px;" id="optionalform"> 23 <div style="margin-left:150px;" id="optionalform">
23 <center> 24 <center>
24 <form action="thanks" method="post" enctype="multipart/form-data" name="identification_form"> 25 <form action="thanks" method="post" enctype="multipart/form-data" name="identification_form">
  26 +<div style="text-align: left;">
  27 + <p><label style="margin-left: 7px">Admin's habit</label>
  28 + <fieldset style="margin-left: 20px">
  29 + <input type=radio class=radio name="user_habits" value="1">I rarely install new applications.<br />
  30 + <input type=radio class=radio name="user_habits" value="2">I only install when I get a trusted recommendation.<br />
  31 + <input type=radio class=radio name="user_habits" value="3">I actively seek for new applications.<br />
  32 + <input type=radio class=radio name="user_habits" value="0">I would rather not comment on that.<br />
  33 + </fieldset>
  34 + </p>
  35 +</div>
25 <p> 36 <p>
26 <label> 37 <label>
27 <input type="hidden" name="user_id" value=$user_id> 38 <input type="hidden" name="user_id" value=$user_id>
src/web/templates/thanks_id.html
@@ -10,7 +10,7 @@ $var cssfiles: static/css/survey.css @@ -10,7 +10,7 @@ $var cssfiles: static/css/survey.css
10 10
11 <center> 11 <center>
12 <h1>Thanks!</h1> 12 <h1>Thanks!</h1>
13 -<p>Thank you once again and stay tuned for the survey report.</p><br /> 13 +<p>Thank you once again, your help is very much appreciated!</p><br />
14 </center> 14 </center>
15 15
16 </div><!-- class="innertube" --> 16 </div><!-- class="innertube" -->