Skip to content

Commit be97323

Browse files
committed
Languages list customization
1 parent e124a98 commit be97323

File tree

6 files changed

+57
-164
lines changed

6 files changed

+57
-164
lines changed

README.md

+28-15
Original file line numberDiff line numberDiff line change
@@ -46,21 +46,34 @@ by certain points (branches) in repository, as more and more functionality are a
4646
- [Step 12 - customization-2](https://github.com/CodeAbbey/src/tree/v0.12-cust2) more configuration, and mess-hall working
4747
- [Step 13 - forum](https://github.com/CodeAbbey/src/tree/v0.13-forum) well, forum files and tables are added here
4848
- [Step 14 - profile](https://github.com/CodeAbbey/src/tree/v0.14-profile) files for user profile settings added
49-
50-
### Step 14 - User profile settings
51-
52-
We show user profile page already but we hadn't controls to change data there - password, email, personal
53-
info and username. With this update all this comes. You may note that there is a single configuration
54-
page but its various buttons lead to several endpoints, each of them do not provide separate page, but
55-
updates data, shows flash message and redirects to user profile.
56-
57-
**Exercises**
58-
59-
Try to update name, personal info, password and email. You'll notice you need to change "levels" which
60-
allow changing name and personal info. Find them in `conf.php`.
61-
62-
When changing name you may see queer message that name is already taken (though name is changed). Investigate
63-
it and propose some fix. (for now it's a small bug)
49+
- [Step 15 - langs](https://github.com/CodeAbbey/src/tree/v0.15-langs) languages list customization
50+
51+
### Step 15 - Languages list customization
52+
53+
This is a small but somewhat painful piece :) During the lifetime of CodeAbbey the list of languages (used to mark solutions, primarily) have grown - some languages there are pretty specific
54+
to the site (e.g. `Asm4004` and `SQLite`), others may be so rare you won't like to include them
55+
in your site.
56+
57+
Now the list lives also in `conf.php` under the name of `$ctx->elems->conf->languages` - it is
58+
a "key-value" list (or associative array) where values are how the language is named in user
59+
interface, while keys - how they are called in the database etc. For many languages these match
60+
but sometimes it's preferable that the key doesn't use special characters etc.
61+
62+
There is another use for these languages, almost absent (yet) in opensource version - it is about
63+
running the code in the chosen language in user's interface. For most of languages this requires
64+
sending the code from browser to server and then either executing them here (e.g. it is a situation
65+
with `BASIC` or `RegExp` which are actually executed by `PHP` interpreter), or sending further
66+
to "sandbox" server. Some could be instead executed in-browser. Of such the only one is present
67+
for now - javascript. As a exercise (somewhat advanced and not 5-minutes work) you may try to
68+
attach some python interpreter implemented in javascript (perhaps, brython) - or other more
69+
lightweight language - and create here button for it.
70+
71+
Functionality to run sources in sandbox is absent now mainly for the reason that setting up a
72+
sandbox server is a separate matter (and unlike main site it couldn't run on free hosting) - but
73+
if you inspect code on main CodeAbbey website you'll see how requests are sent to dedicated
74+
controller. You can either implement something here yourself or ask me for further guidance about
75+
creating sandbox. But I recommend not doing this until you feel the most of main functionality is
76+
sturdy enough and your site is steaming well :)
6477

6578
## How to run
6679

conf.php

+3
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@
3939

4040
$ctx->elems->conf->logging = array('activity' => false);
4141

42+
$ctx->elems->conf->languages = array("c/c++" => "C/C++", "python" => "Python", "go" => "Go",
43+
"java" => "Java", "c#" => "C#", "javascript" => "JavaScript", "other" => "Other");
44+
4245
$ctx->elems->conf->passwordSalt = 'salt#cadabraabra';
4346
$ctx->elems->conf->emailSalt = 'salt#racadabraab';
4447

fragments/taskview/runtools.html

+3-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
</td></tr>
77
<tr>
88
<td>
9-
<input type="button" id="run-javascript" value="JavaScript" title="Read from 'input()', write to 'output(...)'"/><br/>
9+
<input type="button" id="run-javascript" value="JavaScript"
10+
onclick="runJavaScript()"
11+
title="Read from 'input()', write to 'output(...)'"/><br/>
1012
<br/><br/>
1113
<span class="strong">Web Compilers</span><br/>
1214
<a href="http://ideone.com" target="_blank">IdeOne.com</a><br/>

fragments/taskview/solcaption.html

+6
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,11 @@
1616
<option value="<?= $langKey ?>"><?= $langVal ?></option>
1717
<?php endforeach; ?>
1818
</select>
19+
<button class="btn btn-success form-control" id="run-any" type="button">Run</button>
1920
</div>
21+
<script>
22+
var executorsForRunButton ={
23+
'javascript': '#',
24+
};
25+
</script>
2026
</div>

js/task/_view.js

+7-128
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ $(function() {
182182
return {"code": src, "input": input, "lang": lang};
183183
}
184184

185-
function localRun(lang, sel) {
185+
window.localRun = function(lang, sel) {
186186
if (sel) selectLanguage(sel);
187187
var data = inputSrcData(lang);
188188
var toolsLocalRun = tools + '_localrun';
@@ -194,9 +194,9 @@ $(function() {
194194
} catch (e) {
195195
alert(e.message);
196196
}
197-
}
197+
};
198198

199-
function remoteRun(lang, sel) {
199+
window.remoteRun = function(lang, sel) {
200200
if (sel) selectLanguage(sel);
201201
var data = inputSrcData(lang);
202202
var sandboxPath = tools + '_sandbox';
@@ -219,27 +219,10 @@ $(function() {
219219
} catch (e) {
220220
alert(e.message);
221221
}
222-
}
222+
};
223223

224224
$("#run-any").click(function() {
225-
var opts = {
226-
'c/c++': 'cpp',
227-
'python': 'py',
228-
'java': 'java',
229-
'c#': 'cs',
230-
'perl': 'pl',
231-
'lua': 'lua',
232-
'scheme': 'scm',
233-
'forth': 'fth',
234-
'php': 'php',
235-
'regex': '!re',
236-
'brainfuck': '!bf',
237-
'turing': '!turing',
238-
'basic': '!basic',
239-
'asm4004': '!i4004',
240-
'javascript': '#',
241-
'sql': '#',
242-
};
225+
var opts = executorsForRunButton;
243226
var lang = langSelect.val();
244227
var runner = opts[lang];
245228
if (typeof(runner) == 'undefined') {
@@ -255,75 +238,7 @@ $(function() {
255238
}
256239
});
257240

258-
$("#run-python").click(function() {
259-
remoteRun('py', "python");
260-
});
261-
262-
$("#run-cpp").click(function() {
263-
remoteRun('cpp', "c/c++");
264-
});
265-
266-
$("#run-c").click(function() {
267-
remoteRun('c', "c/c++");
268-
});
269-
270-
$("#run-java").click(function() {
271-
remoteRun('java', "java");
272-
});
273-
274-
$("#run-cs").click(function() {
275-
remoteRun('cs', "c#");
276-
});
277-
278-
$("#run-perl").click(function() {
279-
remoteRun('pl', "perl");
280-
});
281-
282-
$("#run-lua").click(function() {
283-
remoteRun('lua', "lua");
284-
});
285-
286-
$("#run-scheme").click(function() {
287-
remoteRun('scm', "scheme");
288-
});
289-
290-
$("#run-forth").click(function() {
291-
remoteRun('fth', "forth");
292-
});
293-
294-
$("#run-scala").click(function() {
295-
remoteRun(15, "scala");
296-
});
297-
298-
$("#run-php").click(function() {
299-
remoteRun(7, "php");
300-
});
301-
302-
$("#run-go").click(function() {
303-
remoteRun(21, "go");
304-
});
305-
306-
$("#run-regexp").click(function() {
307-
localRun('re', "regexp");
308-
});
309-
310-
$("#run-brainfuck").click(function() {
311-
localRun('bf', "brainfuck");
312-
});
313-
314-
$("#run-turing").click(function() {
315-
localRun('turing', "turing");
316-
});
317-
318-
$("#run-basic").click(function() {
319-
localRun('basic', "basic");
320-
});
321-
322-
$("#run-i4004").click(function() {
323-
localRun('i4004', "asm4004");
324-
});
325-
326-
$("#run-javascript").click(function() {
241+
window.runJavaScript = function() {
327242
selectLanguage("javascript");
328243
var src = prepareRun();
329244
try {
@@ -334,44 +249,8 @@ $(function() {
334249
alert(e.message);
335250
}
336251
inputHolder = null;
337-
});
252+
};
338253

339-
$("#run-sql").click(function() {
340-
selectLanguage("sql");
341-
ans = $('#answer');
342-
var sqlRun = () => {
343-
ans.val('');
344-
var db = new sqlite.Database();
345-
var text = $('#test-data').val() + ';' + solutionArea.getValue()
346-
var stmts = text.split(';');
347-
for (var i = 0; i < stmts.length; i++) {
348-
var line = stmts[i].replace(/^\s+/, '');
349-
try {
350-
if (line.substr(0, 6).toLowerCase() != 'select') {
351-
db.run(line);
352-
} else {
353-
var st = db.prepare(line);
354-
while (st.step()) {
355-
var row = st.get();
356-
ans.val(ans.val() + row.join(',') + ' ');
357-
}
358-
}
359-
} catch (e) {
360-
ans.val('Probably syntax error');
361-
}
362-
}
363-
};
364-
if (typeof(sqlite) == 'undefined') {
365-
ans.val('initializing...');
366-
initSqlJs({locateFile: (x) => '/js/_sql/' + x})
367-
.then((s) => {
368-
window.sqlite = s;
369-
sqlRun();
370-
});
371-
} else {
372-
sqlRun();
373-
}
374-
});
375254
});
376255

377256
var inputHolder = null;

module/service/LangService.php

+10-20
Original file line numberDiff line numberDiff line change
@@ -55,19 +55,9 @@ function detectLanguage($s) {
5555
}
5656

5757
function languagesArray() {
58-
return ["c/c++" => "C/C++", "python" => "Python", "java" => "Java",
59-
"c#" => "C#", "ruby" => "Ruby", "php" => "PHP",
60-
"javascript" => "JavaScript", "perl" => "Perl", "lisp" => "LISP",
61-
"vb" => "VB", "lua" => "Lua", "brainfuck" => "Brainfuck",
62-
"scala" => "Scala", "f#" => "F#", "d" => "D", "go" => "Go",
63-
"haskell" => "Haskell", "ocaml" => "Ocaml", "julia" => "Julia",
64-
"ada" => "Ada", "rust" => "Rust", "swift" => "Swift", "shell" => "Shell",
65-
"pascal" => "Pascal", "r" => "R", "matlab" => "Matlab", "vala" => "Vala",
66-
"fortran" => "Fortran", "scheme" => "Scheme", "basic" => "BASIC",
67-
"forth" => "Forth", "turing" => "Turing Machine", "regexp" => "RegExp",
68-
"asm4004" => "Asm4004", "sql" => "SQL", "other" => "Other"];
58+
return $this->ctx->elems->conf->languages;
6959
}
70-
60+
7161
function preferredLanguage($userid) {
7262
$table = $this->ctx->userTasksDao->languagesCount($userid);
7363
$res = '';
@@ -80,15 +70,15 @@ function preferredLanguage($userid) {
8070
}
8171
return $res;
8272
}
83-
73+
8474
function preferredLanguageUpdate($userid) {
8575
$lang = $this->preferredLanguage($userid);
8676
$data = $this->ctx->userDataDao->findFirst("userid = $userid");
8777
$data->language = $lang;
8878
$this->ctx->userDataDao->save($data);
8979
return $lang;
9080
}
91-
81+
9282
function checkAndFixLanguage($language) {
9383
$languages = $this->languagesArray();
9484
if (isset($languages[$language])) {
@@ -98,20 +88,20 @@ function checkAndFixLanguage($language) {
9888
}
9989
return null;
10090
}
101-
91+
10292
function changeLanguage($task, $user, &$oldLang, &$language, $confirm, $model) {
10393
$language = $this->checkAndFixLanguage($language);
10494
$oldLang = $this->checkAndFixLanguage($oldLang);
10595
if ($oldLang === null || $language === null) {
10696
return array(0, "Unknown error");
10797
}
108-
98+
10999
$userTaskOld = $this->ctx->userTasksDao->findFirst("taskid = {$task->id} and userid = {$user->id} and language = '$oldLang'");
110100
$userTaskNew = $this->ctx->userTasksDao->findFirst("taskid = {$task->id} and userid = {$user->id} and language = '$language'");
111101
if (!is_object($userTaskOld)) {
112102
return array(0, 'Solution missed');
113103
}
114-
104+
115105
if ($confirm) {
116106
$this->doChangeLanguage($userTaskOld, $userTaskNew, $task->url, $user->url, $language);
117107
return array(2, 'Language successfully changed');
@@ -120,7 +110,7 @@ function changeLanguage($task, $user, &$oldLang, &$language, $confirm, $model) {
120110
return array(1);
121111
}
122112
}
123-
113+
124114
private function doChangeLanguage($userTaskOld, $userTaskNew, $taskurl, $userurl, $language) {
125115
$ctx = $this->ctx;
126116
if (is_object($userTaskNew)) {
@@ -133,7 +123,7 @@ private function doChangeLanguage($userTaskOld, $userTaskNew, $taskurl, $userurl
133123
$this->deleteDuplicateSolution($userTaskOld, $userTaskNew);
134124
}
135125
}
136-
126+
137127
private function deleteDuplicateSolution($userTaskOld, $userTaskNew) {
138128
$ctx = $this->ctx;
139129
$votes = $ctx->codelikesDao->find("codeid = {$userTaskNew->id}");
@@ -143,7 +133,7 @@ private function deleteDuplicateSolution($userTaskOld, $userTaskNew) {
143133
}
144134
$ctx->userTasksDao->delete($userTaskNew->id);
145135
}
146-
136+
147137
private function prepareConfirmation($task, $user, $oldlang, $language, $overwrite, $model) {
148138
$model->task = $task;
149139
$model->username = $user->username;

0 commit comments

Comments
 (0)