*/
Script("utils.js")
Script("pre.js")
Script("killring.js")
Script("history.js")
Script("readline.js")
Script("shell.js")
Script("pathhandler.js")
websh=Require("main.js")
console.log("websh library loaded.");
};
BundleModuleCode['main.js']=function (module,exports,global,process){
function websh(index,config,prompt,callback) {
var shell_panel_id="shell-panel-"+index,
shell_view_id="shell-view-"+index,
input_id="shell-cli-"+index,
parameter=config;
$(document).ready(function() {
var history = new Josh.History({ key : 'josh.websh', volatile : false });
var shell = Josh.Shell({
shell_panel_id:shell_panel_id,
shell_view_id:shell_view_id,
input_id:input_id,
prompt:prompt,
history:history
});
shell.index=index;
shell.fontSize = 16
var promptCounter = 0;
Object.keys(config).forEach ( p => {
switch (p) {
case 'WORK':
case 'WORKDIR':
shell.workdir=parameter[p]
break;
case 'PORT':
shell.port=Number(parameter[p]);
break;
default:
shell.setCommandHandler(p,{
exec : function(cmd, args, callback, output) {
console.log(cmd,args,parameter[p])
if (parameter[p][0]=='$') {
// internal JS command
var argv = parameter[p].split(' ')
argv[0]=argv[0].slice(1)
if (typeof window[argv[0]] == 'function') {
window[argv[0]](output,shell.workdir,argv.slice(1).concat(args));
callback('');
return;
} else return callback('Unknown internal command '+argv[0]);
}
var exec = parameter[p]+' '+args.join(',')
callback(exec);
shell.socket.send(exec+'\n');
}
});
}
})
Utils.POST('localhost:11111',{command:'session'},function (reply) {
if (reply.status==0) {
try {
var socket = Utils.connectShell(reply.reply,shell.outputString)
shell.socket=socket
setTimeout(function () { shell.socket.send('cd '+shell.workdir+'\n') },200);
} catch (e) {
alert(e)
}
} else alert(reply.status)
})
shell.onNewPrompt(function(callback) {
promptCounter++;
callback("[" + promptCounter + "] $");
});
shell.setCommandHandler("size", {
exec : function(cmd, args, callback) {
if (args[0]=='+') shell.fontSize++;
else if (args[0]=='-') shell.fontSize--;
else if (!isNaN(Number(args[0]))) shell.fontSize=Number(args[0])
Utils.addCSS('body { font-size:'+shell.fontSize+'px; }');
callback('')
}
});
['*'].forEach(cmd => {
shell.setCommandHandler(cmd, {
exec : function(cmd, args, callback, output) {
callback('')
shell.socket.send(cmd+' '+args.join(' ')+'\n')
}
});
})
shell.onCancel(function () {
shell.socket.signal('SIGTERM')
});
shell.activate();
shell.setActive(false);
if (!shell.workdir) shell.workdir=PATH.dirname(document.URL.replace(/\?.+$/,'').replace('file://',''))
shell.outputLine('Ready ['+shell.workdir+']')
shell.outputLine(Object.keys(parameter).join(' '))
$('#'+shell_panel_id).on( "mouseenter", function() {
console.log('main.shell.activate',shell.index,shell_panel_id)
shell.setActive(true)
}).on( "mouseleave", function() {
console.log('main.shell.deactivate',shell.index,shell_panel_id)
shell.setActive(false)
})
});
}
if (typeof module == 'object') module.exports=websh
};
Utils = {
addCSS : function (styles) {
var styleSheet = document.createElement("style")
styleSheet.type = "text/css"
styleSheet.innerText = styles
document.head.appendChild(styleSheet)
},
blobToText : function (data, callback) {
var textDecoder = new TextDecoder();
var fileReader = new FileReader();
fileReader.addEventListener('load', function () {
var str = textDecoder.decode(fileReader.result);
callback(str);
});
fileReader.readAsArrayBuffer(data);
},
connectShell : function (port,outputString) {
var hostname = 'localhost'
var protocol = (location.protocol === 'https:') ? 'wss://' : 'ws://';
var socketURL = protocol + hostname + ':' + port;
console.log('connectShell',socketURL)
var socket = new WebSocket(socketURL);
socket.addEventListener('message', function (ev) {
// console.log(ev)
var message = JSON.parse(ev.data)
if (message.stdout) outputString(message.stdout);
if (message.stderr) outputString(message.stderr);
});
// oninput handler function
return {
socket : socket,
signal : function (data) {
socket.send(JSON.stringify({signal:data}));
},
send : function (data) {
socket.send(JSON.stringify({stdin:data}));
}
}
},
parseUrl : function (url) {
if (!url) return {};
url = url.replace(/#[^$]+$/,'');
var queryString = url.substring( url.indexOf('?') + 1 );
if (queryString == url) return {};
var params = {}, queries, temp, i, l;
// Split into key/value pairs
queries = queryString.split("&");
// Convert the array of strings into an object
for ( i = 0, l = queries.length; i < l; i++ ) {
temp = queries[i].split('=');
if (temp[1]==undefined) temp[1]='true';
params[temp[0]] = temp[1].replace('%20',' ');
}
return params;
},
textToBlob : function (str) {
return new Blob([str]);
},
GET: function (url,params,cb,sync) {
var result;
// if (sync && !cb) cb=function (_result) { result=_result };
// promise?
if (!cb && !sync) {
return new Promise(function (resolve,reject){
Utils.GET(url,params,function (result) {
resolve(result);
})
})
}
if (url.indexOf('http')!=0) url = 'http://'+url;
try {
if (params) {
var o=params,sep='';
params='/?';
for(var p in o) {
params = params + sep + p + '='+o[p];
sep='&';
}
} else params='';
// print(url+params)
var request = new XMLHttpRequest();
request.open("GET",url+params, !sync);
request.onreadystatechange = function () {
if(request.readyState === 4)
{
if(request.status === 200 || request.status == 0)
{
var allText = request.responseText;
if (allText!='') result=JSON.parse(allText);
else result = new Error('GET data error (empty data)');
if (cb) cb(result);
} else {
result=new Error('GET from '+url+params+' failed (status '+request.status+')'+
(request.responseText?' '+request.responseText:''));
if (cb) cb(result)
}
}
}
request.onerror = function (error) {
if (result) return;
result='Error: GET from '+url+params+' failed: '+error;
if (cb) cb(result);
}
request.send(null);
} catch (error) {
result=new Error('GET from '+url+params+' failed: '+error.toString());
if (cb) cb(result);
}
return result;
},
Get: function (url,params,mimetype,cb,sync) {
if (typeof mimetype=='function') { sync=cb; cb=mimetype; mimetype=undefined };
var result;
// console.log(url,params,mimetype);
// if (sync && !cb) cb=function (_result) { result=_result };
// promise?
if (!cb && !sync) {
return new Promise(function (resolve,reject){
Utils.Get(url,params,mimetype,function (result) {
resolve(result);
})
})
}
if (url.indexOf('http')!=0) url = 'http://'+url;
try {
if (params) {
var o=params,params='',sep='';
for(var p in o) {
params = params + sep + p + '='+o[p];
sep='&';
}
if (params) params = '?'+params;
} else params='';
// print(url+params)
var request = new XMLHttpRequest();
request.open("GET",url+params, !sync);
if (mimetype=='binary') request.overrideMimeType("text/plain; charset=x-user-defined");
request.onreadystatechange = function () {
if(request.readyState === 4)
{
if(request.status === 200 || request.status == 0)
{
var allText = mimetype=='binary'?request.response:request.responseText;
// console.log(request.response.length);
result=allText;
if (cb) cb(result);
} else {
result=new Error('Get from '+url+params+' failed (status '+request.status+')'+
(request.responseText?' '+request.responseText:''));
if (cb) cb(result)
}
}
}
request.onerror = function (error) {
if (result) return;
result='Error: Get from '+url+params+' failed: '+error;
if (cb) cb(result);
}
request.send(null);
} catch (error) {
result=new Error('Get from '+url+params+' failed: '+error.toString());
if (cb) cb(result);
}
return result;
},
// JSON POST
POST: function (url,data,cb,sync){
var result;
// if (sync && !cb) cb=function (_result) { result=_result };
// console.log(url,data);
// promise?
if (!cb && !sync) {
return new Promise(function (resolve,reject){
Utils.POST(url,data,function (result) {
resolve(result);
})
})
}
if (url.indexOf('http')!=0) url = 'http://'+url;
try {
var request = new XMLHttpRequest();
request.open("POST", url, !sync);
request.onreadystatechange = function () {
if(request.readyState === 4)
{
if(request.status === 200 || request.status == 0)
{ /*console.log(request);*/
var allText = request.responseText;
try {
if (allText!='') result=JSON.parse(allText)
else result=new Error('POST data error (empty data)');
} catch (e) {
result = new Error(e.toString());
}
if (cb) cb(result);
} else {
result = new Error('POST to '+url+' failed (status '+request.status+')'+
(request.responseText?' '+request.responseText:''));
if (cb) cb(result);
}
}
}
request.onerror = function (error) {
if (result) return;
result = new Error('POST to '+url+' failed: '+error);
if (cb) cb(result)
}
request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
request.send(JSON.stringify(data));
} catch (error) {
result=new Error('POST to '+url+' failed: '+error.toString());
if (cb) cb(result)
}
return result;
},
// Formdata POST, data:{} => attr1=val&attr2=val2...
Post: function (url,data,cb,sync){
var result;
// if (sync && !cb) cb=function (_result) { result=_result };
// promise?
if (!cb && !sync) {
return new Promise(function (resolve,reject){
Utils.Post(url,data,function (result) {
resolve(result);
})
})
}
if (url.indexOf('http')!=0) url = 'http://'+url;
try {
var request = new XMLHttpRequest();
request.open("POST", url, !sync);
request.onreadystatechange = function () {
if(request.readyState === 4)
{
if(request.status === 200 || request.status == 0)
{ /*console.log(request);*/
var allText = request.responseText;
try {
if (allText!='') result=JSONfn.parse(allText)
else result=new Error('POST data error (empty data)');
} catch (e) {
result = new Error(e.toString());
}
if (cb) cb(result);
} else {
result = new Error('POST to '+url+' failed (status '+request.status+')'+
(request.responseText?' '+request.responseText:''));
if (cb) cb(result);
}
}
}
request.onerror = function (error) {
if (result) return;
result = new Error('POST to '+url+' failed: '+error);
if (cb) cb(result)
}
request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
var text=[];
for(var p in data) {
text.push(p+'='+escape(data[p]));
}
request.send(text.join('&'));
} catch (error) {
result=new Error('POST to '+url+' failed: '+error.toString());
if (cb) cb(result)
}
return result;
},
}
PATH = {
basename : function (path,extension) {
if (path[path.length-1]=='/') return '/';
return extension?
path.split('/').reverse()[0].replace(RegExp(extension.replace(/\./,'\\.')+'$'),'')
:
path.split('/').reverse()[0];
},
dirname : function (path) {
var el=path.split('/');
el.pop();
return el.join('/');
},
extension : function (file) {
return file.replace(/^[^\.]+\./,'');
}
}
if (typeof hljs != 'undefined') hljs.initHighlightingOnLoad();
Josh = {Debug: false };
/* ------------------------------------------------------------------------*
* Copyright 2013 Arne F. Claassen
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------*/
var Josh = Josh || {};
(function(root) {
Josh.KillRing = function(config) {
config = config || {};
var _console = Josh.Debug && root.console ? root.console : {log: function() {
}};
var _ring = config.ring || [];
var _cursor = config.cursor || 0;
var _uncommitted = false;
var _yanking = false;
if(_ring.length == 0) {
_cursor = -1;
} else if(_cursor >= _ring.length) {
_cursor = _ring.length - 1;
}
var self = {
isinkill: function() {
return _uncommitted;
},
lastyanklength: function() {
if(!_yanking) {
return 0;
}
return _ring[_cursor].length;
},
append: function(value) {
_yanking = false;
if(!value) {
return;
}
if(_ring.length == 0 || !_uncommitted) {
_ring.push('');
}
_cursor = _ring.length - 1;
_console.log("appending: " + value);
_uncommitted = true;
_ring[_cursor] += value;
},
prepend: function(value) {
_yanking = false;
if(!value) {
return;
}
if(_ring.length == 0 || !_uncommitted) {
_ring.push('');
}
_cursor = _ring.length - 1;
_console.log("prepending: " + value);
_uncommitted = true;
_ring[_cursor] = value + _ring[_cursor];
},
commit: function() {
_console.log("committing");
_yanking = false;
_uncommitted = false;
},
yank: function() {
self.commit();
if(_ring.length == 0) {
return null;
}
_yanking = true;
return _ring[_cursor];
},
rotate: function() {
if(!_yanking || _ring.length == 0) {
return null;
}
--_cursor;
if(_cursor < 0) {
_cursor = _ring.length - 1;
}
return self.yank();
},
items: function() {
return _ring.slice(0);
},
clear: function() {
_ring = [];
_cursor = -1;
_yanking = false;
_uncommited = false;
}
};
return self;
}
})(this);
/* ------------------------------------------------------------------------*
* Copyright 2013 Arne F. Claassen
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------*/
var Josh = Josh || {};
(function (root) {
Josh.History = function (config) {
config = config || {};
var _console = Josh.Debug && root.console ? root.console : {log: function() {}};
var _history = config.history || [''];
var _cursor = config.cursor || 0;
var _searchCursor = _cursor;
var _lastSearchTerm = '';
var _storage = config.storage || root.localStorage;
var _key = config.key || 'josh.history';
console.log('History',config)
if (!config.volatile && _storage) {
var data = _storage.getItem(_key);
if (data) {
_history = JSON.parse(data);
_searchCursor = _cursor = _history.length - 1;
} else {
save();
}
}
function save() {
if (!config.volatile && _storage) {
_storage.setItem(_key, JSON.stringify(_history));
}
}
function setHistory() {
_searchCursor = _cursor;
_lastSearchTerm = '';
return _history[_cursor];
}
return {
update:function (text) {
_console.log("updating history to " + text);
_history[_cursor] = text;
save();
},
accept:function (text) {
_console.log("accepting history " + text);
var last = _history.length - 1;
if (text) {
if (_cursor == last) {
_console.log("we're at the end already, update last position");
_history[_cursor] = text;
} else if (!_history[last]) {
_console.log("we're not at the end, but the end was blank, so update last position");
_history[last] = text;
} else {
_console.log("appending to end");
_history.push(text);
}
_history.push('');
}
_searchCursor = _cursor = _history.length - 1;
save();
},
items:function () {
return _history.slice(0, _history.length - 1);
},
clear:function () {
_history = [_history[_history.length - 1]];
save();
},
hasNext:function () {
return _cursor < (_history.length - 1);
},
hasPrev:function () {
return _cursor > 0;
},
prev:function () {
--_cursor;
return setHistory();
},
next:function () {
++_cursor;
return setHistory();
},
top:function () {
_cursor = 0;
return setHistory();
},
end:function () {
_cursor = _history.length - 1;
return setHistory();
},
search:function (term) {
if (!term && !_lastSearchTerm) {
return null;
}
var iterations = _history.length;
if (term == _lastSearchTerm) {
_searchCursor--;
iterations--;
}
if (!term) {
term = _lastSearchTerm;
}
_lastSearchTerm = term;
for (var i = 0; i < iterations; i++) {
if (_searchCursor < 0) {
_searchCursor = _history.length - 1;
}
var idx = _history[_searchCursor].indexOf(term);
if (idx != -1) {
return {
text:_history[_searchCursor],
cursoridx:idx,
term:term
};
}
_searchCursor--;
}
return null;
},
applySearch:function () {
if (_lastSearchTerm) {
_console.log("setting history to position" + _searchCursor + "(" + _cursor + "): " + _history[_searchCursor]);
_cursor = _searchCursor;
return _history[_cursor];
}
return null;
}
};
};
})(this);
/* ------------------------------------------------------------------------*
* Copyright 2013 Arne F. Claassen
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------*/
// HACK
var Josh = Josh || {};
Josh.readlines = []
var root = this
Josh.Version = "0.2.9";
Josh.Keys = {
Special: {
Backspace: 8,
Tab: 9,
Enter: 13,
Pause: 19,
CapsLock: 20,
Escape: 27,
Space: 32,
PageUp: 33,
PageDown: 34,
End: 35,
Home: 36,
Left: 37,
Up: 38,
Right: 39,
Down: 40,
Insert: 45,
Delete: 46
}
};
Josh.ReadLine = function(config) {
config = config || {};
// instance fields
var _console = config.console || (Josh.Debug && root.console ? root.console : {
log: function() {
}
});
var _history = config.history || new Josh.History();
var _killring = config.killring || new Josh.KillRing();
var _boundToElement = config.element ? true : false;
var _element = config.element || root;
var _active = false;
var _onActivate;
var _onDeactivate;
var _onCompletion;
var _onEnter;
var _onChange;
var _onCancel;
var _onEOT;
var _onClear;
var _onSearchStart;
var _onSearchEnd;
var _onSearchChange;
var _inSearch = false;
var _searchMatch;
var _lastSearchText = '';
var _text = '';
var _cursor = 0;
var _lastCmd;
var _completionActive;
var _cmdQueue = [];
var _suspended = false;
var _cmdMap = {
complete: cmdComplete,
done: cmdDone,
noop: cmdNoOp,
history_top: cmdHistoryTop,
history_end: cmdHistoryEnd,
history_next: cmdHistoryNext,
history_previous: cmdHistoryPrev,
end: cmdEnd,
home: cmdHome,
left: cmdLeft,
right: cmdRight,
cancel: cmdCancel,
delete: cmdDeleteChar,
backspace: cmdBackspace,
kill_eof: cmdKillToEOF,
kill_wordback: cmdKillWordBackward,
kill_wordforward: cmdKillWordForward,
yank: cmdYank,
clear: cmdClear,
search: cmdReverseSearch,
wordback: cmdBackwardWord,
wordforward: cmdForwardWord,
yank_rotate: cmdRotate
}
var _keyMap = {
default: {
8: cmdBackspace, // Backspace
9: cmdComplete, // Tab
13: cmdDone, // Enter
27: cmdEsc, // Esc
33: cmdHistoryTop, // Page Up
34: cmdHistoryEnd, // Page Down
35: cmdEnd, // End
36: cmdHome, // Home
37: cmdLeft, // Left
38: cmdHistoryPrev, // Up
39: cmdRight, // Right
40: cmdHistoryNext, // Down
46: cmdDeleteChar, // Delete
10: cmdNoOp, // Pause
19: cmdNoOp, // Caps Lock
45: cmdNoOp // Insert
},
control: {
65: cmdHome, // A
66: cmdLeft, // B
67: cmdCancel, // C
68: cmdDeleteChar, // D
69: cmdEnd, // E
70: cmdRight, // F
80: cmdHistoryPrev, // P
78: cmdHistoryNext, // N
75: cmdKillToEOF, // K
89: cmdYank, // Y
76: cmdClear, // L
82: cmdReverseSearch // R
},
meta: {
8: cmdKillWordBackward, // Backspace
66: cmdBackwardWord, // B
68: cmdKillWordForward, // D
70: cmdForwardWord, // F
89: cmdRotate // Y
}
};
// public methods
var self = {
isActive: function() {
return _active;
},
setActive : function (on) {
console.log('readline.setActive',on)
_active=on
return on
},
activate: function() {
console.log('readline.activate')
_active = true;
if(_onActivate) {
_onActivate();
}
},
deactivate: function() {
console.log('readline.deactivate')
_active = false;
if(_onDeactivate) {
_onDeactivate();
}
},
bind: function(key, action) {
var k = getKey(key);
var cmd = _cmdMap[action];
if(!cmd) {
return;
}
_keyMap[k.modifier][k.code];
},
unbind: function(key) {
var k = getKey(key);
delete _keyMap[k.modifier][k.code];
},
attach: function(el) {
if(_element) {
self.detach();
}
_console.log("attaching");
_console.log(el);
_element = el;
_boundToElement = true;
addEvent(_element, "focus", self.activate);
addEvent(_element, "blur", self.deactivate);
subscribeToKeys();
},
detach: function() {
removeEvent(_element, "focus", self.activate);
removeEvent(_element, "blur", self.deactivate);
_element = null;
_boundToElement = false;
},
onActivate: function(completionHandler) {
_onActivate = completionHandler;
},
onDeactivate: function(completionHandler) {
_onDeactivate = completionHandler;
},
onChange: function(changeHandler) {
_onChange = changeHandler;
},
onClear: function(completionHandler) {
_onClear = completionHandler;
},
onEnter: function(enterHandler) {
_onEnter = enterHandler;
},
onCompletion: function(completionHandler) {
_onCompletion = completionHandler;
},
onCancel: function(completionHandler) {
_onCancel = completionHandler;
},
onEOT: function(completionHandler) {
_onEOT = completionHandler;
},
onSearchStart: function(completionHandler) {
_onSearchStart = completionHandler;
},
onSearchEnd: function(completionHandler) {
_onSearchEnd = completionHandler;
},
onSearchChange: function(completionHandler) {
_onSearchChange = completionHandler;
},
getLine: function() {
return {
text: _text,
cursor: _cursor
};
},
setLine: function(line) {
_text = line.text;
_cursor = line.cursor;
refresh();
},
// Hacks to propagate key events from inactive to active readline
// if there is more than one shell
handleKeyEvent:handleKeyEvent,
handleKeyPress:handleKeyPress
};
// private methods
function addEvent(element, name, callback) {
if(element.addEventListener) {
element.addEventListener(name, callback, false);
} else if(element.attachEvent) {
element.attachEvent('on' + name, callback);
}
}
function removeEvent(element, name, callback) {
if(element.removeEventListener) {
element.removeEventListener(name, callback, false);
} else if(element.detachEvent) {
element.detachEvent('on' + name, callback);
}
}
function getKeyInfo(e) {
var code = e.keyCode || e.charCode;
var c = String.fromCharCode(code);
return {
code: code,
character: c,
shift: e.shiftKey,
control: e.controlKey,
alt: e.altKey,
isChar: true
};
}
function getKey(key) {
var k = {
modifier: 'default',
code: key.keyCode
};
if(key.metaKey || key.altKey) {
k.modifier = 'meta';
} else if(key.ctrlKey) {
k.modifier = 'control';
}
if(key.char) {
k.code = key.char.charCodeAt(0);
}
return k;
}
function queue(cmd) {
if(_suspended) {
_cmdQueue.push(cmd);
return;
}
call(cmd);
}
function call(cmd) {
_console.log('calling: ' + cmd.name + ', previous: ' + _lastCmd);
if(_inSearch && cmd.name != "cmdKeyPress" && cmd.name != "cmdReverseSearch") {
_inSearch = false;
if(cmd.name == 'cmdEsc') {
_searchMatch = null;
}
if(_searchMatch) {
if(_searchMatch.text) {
_cursor = _searchMatch.cursoridx;
_text = _searchMatch.text;
_history.applySearch();
}
_searchMatch = null;
}
if(_onSearchEnd) {
_onSearchEnd();
}
}
if(!_inSearch && _killring.isinkill() && cmd.name.substr(0, 7) != 'cmdKill') {
_killring.commit();
}
_lastCmd = cmd.name;
cmd();
}
function suspend(asyncCall) {
_suspended = true;
asyncCall(resume);
}
function resume() {
var cmd = _cmdQueue.shift();
if(!cmd) {
_suspended = false;
return;
}
call(cmd);
resume();
}
function cmdNoOp() {
// no-op, used for keys we capture and ignore
}
function cmdEsc() {
// no-op, only has an effect on reverse search and that action was taken in call()
}
function cmdBackspace() {
if(_cursor == 0) {
return;
}
--_cursor;
_text = remove(_text, _cursor, _cursor + 1);
refresh();
}
function cmdComplete() {
if(!_onCompletion) {
return;
}
suspend(function(resumeCallback) {
_onCompletion(self.getLine(), function(completion) {
if(completion) {
_text = insert(_text, _cursor, completion);
updateCursor(_cursor + completion.length);
}
_completionActive = true;
resumeCallback();
});
});
}
function cmdDone() {
if(!_text) {
return;
}
var text = _text;
_history.accept(text);
_text = '';
_cursor = 0;
if(!_onEnter) {
return;
}
suspend(function(resumeCallback) {
_onEnter(text, function(text) {
if(text) {
_text = text;
_cursor = _text.length;
}
if(_onChange) {
_onChange(self.getLine());
}
resumeCallback();
});
});
}
function cmdEnd() {
updateCursor(_text.length);
}
function cmdHome() {
updateCursor(0);
}
function cmdLeft() {
if(_cursor == 0) {
return;
}
updateCursor(_cursor - 1);
}
function cmdRight() {
if(_cursor == _text.length) {
return;
}
updateCursor(_cursor + 1);
}
function cmdBackwardWord() {
if(_cursor == 0) {
return;
}
updateCursor(findBeginningOfPreviousWord());
}
function cmdForwardWord() {
if(_cursor == _text.length) {
return;
}
updateCursor(findEndOfCurrentWord());
}
function cmdHistoryPrev() {
if(!_history.hasPrev()) {
return;
}
getHistory(_history.prev);
}
function cmdHistoryNext() {
if(!_history.hasNext()) {
return;
}
getHistory(_history.next);
}
function cmdHistoryTop() {
getHistory(_history.top);
}
function cmdHistoryEnd() {
getHistory(_history.end);
}
function cmdDeleteChar() {
if(_text.length == 0) {
if(_onEOT) {
_onEOT();
return;
}
}
if(_cursor == _text.length) {
return;
}
_text = remove(_text, _cursor, _cursor + 1);
refresh();
}
function cmdCancel() {
if(_onCancel) {
_onCancel();
}
}
function cmdKillToEOF() {
_killring.append(_text.substr(_cursor));
_text = _text.substr(0, _cursor);
refresh();
}
function cmdKillWordForward() {
if(_text.length == 0) {
return;
}
if(_cursor == _text.length) {
return;
}
var end = findEndOfCurrentWord();
if(end == _text.length - 1) {
return cmdKillToEOF();
}
_killring.append(_text.substring(_cursor, end))
_text = remove(_text, _cursor, end);
refresh();
}
function cmdKillWordBackward() {
if(_cursor == 0) {
return;
}
var oldCursor = _cursor;
_cursor = findBeginningOfPreviousWord();
_killring.prepend(_text.substring(_cursor, oldCursor));
_text = remove(_text, _cursor, oldCursor);
refresh();
}
function cmdYank() {
var yank = _killring.yank();
if(!yank) {
return;
}
_text = insert(_text, _cursor, yank);
updateCursor(_cursor + yank.length);
}
function cmdRotate() {
var lastyanklength = _killring.lastyanklength();
if(!lastyanklength) {
return;
}
var yank = _killring.rotate();
if(!yank) {
return;
}
var oldCursor = _cursor;
_cursor = _cursor - lastyanklength;
_text = remove(_text, _cursor, oldCursor);
_text = insert(_text, _cursor, yank);
updateCursor(_cursor + yank.length);
}
function cmdClear() {
if(_onClear) {
_onClear();
} else {
refresh();
}
}
function cmdReverseSearch() {
if(!_inSearch) {
_inSearch = true;
if(_onSearchStart) {
_onSearchStart();
}
if(_onSearchChange) {
_onSearchChange({});
}
} else {
if(!_searchMatch) {
_searchMatch = {term: ''};
}
search();
}
}
function updateCursor(position) {
_cursor = position;
refresh();
}
function addText(c) {
_text = insert(_text, _cursor, c);
++_cursor;
refresh();
}
function addSearchText(c) {
if(!_searchMatch) {
_searchMatch = {term: ''};
}
_searchMatch.term += c;
search();
}
function search() {
_console.log("searchtext: " + _searchMatch.term);
var match = _history.search(_searchMatch.term);
if(match != null) {
_searchMatch = match;
_console.log("match: " + match);
if(_onSearchChange) {
_onSearchChange(match);
}
}
}
function refresh() {
if(_onChange) {
_onChange(self.getLine());
}
}
function getHistory(historyCall) {
_history.update(_text);
_text = historyCall();
updateCursor(_text.length);
}
function findBeginningOfPreviousWord() {
var position = _cursor - 1;
if(position < 0) {
return 0;
}
var word = false;
for(var i = position; i > 0; i--) {
var word2 = isWordChar(_text[i]);
if(word && !word2) {
return i + 1;
}
word = word2;
}
return 0;
}
function findEndOfCurrentWord() {
if(_text.length == 0) {
return 0;
}
var position = _cursor + 1;
if(position >= _text.length) {
return _text.length - 1;
}
var word = false;
for(var i = position; i < _text.length; i++) {
var word2 = isWordChar(_text[i]);
if(word && !word2) {
return i;
}
word = word2;
}
return _text.length - 1;
}
function isWordChar(c) {
if(c == undefined) {
return false;
}
var code = c.charCodeAt(0);
return (code >= 48 && code <= 57)
|| (code >= 65 && code <= 90)
|| (code >= 97 && code <= 122);
}
function remove(text, from, to) {
if(text.length <= 1 || text.length <= to - from) {
return '';
}
if(from == 0) {
// delete leading characters
return text.substr(to);
}
var left = text.substr(0, from);
var right = text.substr(to);
return left + right;
}
function insert(text, idx, ins) {
if(idx == 0) {
return ins + text;
}
if(idx >= text.length) {
return text + ins;
}
var left = text.substr(0, idx);
var right = text.substr(idx);
return left + ins + right;
}
function handleKeyEvent(e) {
_console.log('websh.readline.handleKeyEvent',_active,"key: " + e.keyCode);
// return as unhandled if we're not active or the key is just a modifier key
if(e.keyCode == 16 || e.keyCode == 17 || e.keyCode == 18 || e.keyCode == 91) {
return true;
}
// check for some special first keys, regardless of modifiers
var cmd = _keyMap.default[e.keyCode];
// intercept ctrl- and meta- sequences (may override the non-modifier cmd captured above
var mod;
if(e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey) {
mod = _keyMap.control[e.keyCode];
if(mod) {
cmd = mod;
}
} else if((e.altKey || e.metaKey) && !e.ctrlKey && !e.shiftKey) {
mod = _keyMap.meta[e.keyCode];
if(mod) {
cmd = mod;
}
}
if(!cmd) {
return true;
}
queue(cmd);
e.preventDefault();
e.stopPropagation();
e.cancelBubble = true;
return false;
}
function handleKeyPress(e) {
_console.log('websh.readline.handleKeyPress',_active);
var key = getKeyInfo(e);
if(key.code == 0 || e.defaultPrevented || e.metaKey || e.altKey || e.ctrlKey) {
return false;
}
queue(function cmdKeyPress() {
if(_inSearch) {
addSearchText(key.character);
} else {
addText(key.character);
}
});
e.preventDefault();
e.stopPropagation();
e.cancelBubble = true;
return false;
}
Josh.readlines.push(self)
function subscribeToKeys() {
// set up key capture
_element.onkeydown = function(e) {
e = e || window.event;
_console.log('websh.readline.onkeydown',_active,"key: " + e.keyCode);
if (!_active) {
for(var i=0;i
Ausgabe: 16.1.2026
Abgabe: 24.1.2026
Es dürfen keine Standard Java Packages verwendet werden mit Ausnahme von System und String.
In dieser Übung soll die Erzeugung, der Zugriff und die Manipulation von Daten mit Baumstrukturen erfolgen und untersucht werden.
Aufgabe 1. Welche Eigenschaften haben Binärbäume? Aufgabe 2. Es wird von geordneten Binärbäumen ausgegenagen. Was muss beachtet werden wenn neue Knoten eingefügt und bestehende gelöscht werden? Wie ist die Ordnungsrelation?
Nachfolgend sind die aus der Vorlesung bekannten Algorithmen in Pseudonotation zusammengefasst.
searchNode liefert den Knoten zum Schlüssel k, seachParentNode sucht dann den Vorgänger zu diesem Knoten. Beide Suchfunktionen sollten kombiniert werden in dem die Suche zustandsbasiert den letzten Elternknoten speichert und seachParentNode dann auf das letzte Ergebnis zurückgreift (ein Cache).
Aufgabe 3. Erstelle die Knotenklasse Node und füge den Programmkode unten ein. Neben der Konstruktionsmethode soll es noch eine print Methode geben die den aktuellen Inhalt eines Knotens formattiert ausgibt.
Aufgabe 4. Erstelle die Baumklasse Tree und füge den Programmkode unten ein. Diese Klasse muss alle oben eingeführten Funktionen und Hilfsfunktionen enthalten um Knoten einfügen, entfernen und suchen zu können. Weiterhin soll eine Methode print geben die den Baum im ASCII Format ausgibt (s.u.).
Aufgabe 5. Erstelle eine Tabelle mit allen Nobelpreisträgern wo die Jahreszahl (letze beiden Jahreszahlen) eine Primzahl darstellen, also z.B. 1907, 2013. Die Daten finden sich unter https://de.wikipedia.org/wiki/Liste_der_Nobelpreistr%C3%A4ger.
Aufgabe 6. Teste nun die Implementierung mit nachfolgenden Beispielen. Da die Datentabellen vermutlich aufsteigend nach dem Schlüssel sortiert sind sollen die Datensätze randomisiert eingeführt werden. Dazu soll randomisiert ein Index der Datentabelle (names,years) ausgewählt werden. Das Problem: Ein Datensatz darf nicht zweimal eingefügt werden. Suche nach einer Lösung! Teste den Baum indem alle Datensätze gesucht werden und der Schlüssel und der ermittelte Knoten verglichen werden. Anschliessend werden die Knoten mit den Jahren 1903, 1913, 2003 und 2013 entfernt. Teste nochamls auf Korrektheit des Baums.
Aufgabe 7. Untersuche die Laufzeit für das Einfügen (in VM Ops) und das Suchen nach einem zufällig ausgewählten Schlüssel. Füge die Knoten in randomisierter Reihenfolge eine und teste (und messe) für N=10 Versuche. Wie groß ist die Streuung? Korreliert die VM Ops Zahl mit der theoretischen Kompliextätskalsse für das Suchen? Gebe diese an.
')))+'
');
}
self.scrollToBottom(true);
}
function outputString(output) {
if(output) {
if (output[0]=='<')
$(id(_input_id)).before(output);
else
$(id(_input_id)).before(expandSpaces(expandTabs(output.replace(/\n/g,'
'))));
}
self.scrollToBottom(true);
}
function activate() {
_console.log("activating shell");
if(!_view) {
_view = $(id(_shell_view_id));
}
if(!_panel) {
_panel = $(id(_shell_panel_id));
}
if($(id(_input_id)).length == 0) {
_view.append(self.templates.input_cmd({id:_input_id,class:"shell-cli"}));
}
self.refresh();
_active = true;
blinkCursor();
if(_promptHandler) {
_promptHandler(function(prompt) {
self.setPrompt(prompt);
})
}
if(_activationHandler) {
_activationHandler();
}
}
// init
_readline.onActivate(function() {
if(!_initialized) {
_initialized = true;
if(_initializationHandler) {
return _initializationHandler(activate);
}
}
return activate();
});
_readline.onDeactivate(function() {
if(_deactivationHandler) {
_deactivationHandler();
}
});
_readline.onChange(function(line) {
_line = line;
self.render();
});
_readline.onClear(function() {
_cmdHandlers.clear.exec(null, null, function() {
renderOutput(null, function() {
});
});
});
_readline.onSearchStart(function() {
$(id(_input_id)).replaceWith(self.templates.input_search({id:_input_id}));
_console.log('started search');
});
_readline.onSearchEnd(function() {
$(id(_input_id)).replaceWith(self.templates.input_cmd({id:_input_id}));
_searchMatch = null;
self.render();
_console.log("ended search");
});
_readline.onSearchChange(function(match) {
_searchMatch = match;
self.render();
});
_readline.onEnter(function(cmdtext, callback) {
_console.log("got command: " + cmdtext);
var parts = split(cmdtext);
var cmd = parts[0];
var args = parts.slice(1);
var handler = getHandler(cmd);
return handler.exec(cmd, args, function(output, cmdtext) {
renderOutput(output, function() {
callback(cmdtext)
});
},outputLine);
});
_readline.onCompletion(function(line, callback) {
if(!line) {
return callback();
}
var text = line.text.substr(0, line.cursor);
var parts = split(text);
var cmd = parts.shift() || '';
var arg = parts.pop() || '';
_console.log("getting completion handler for " + cmd);
var handler = getHandler(cmd);
if(handler != _cmdHandlers._default && cmd && cmd == text) {
_console.log("valid cmd, no args: append space");
// the text to complete is just a valid command, append a space
return callback(' ');
}
if(!handler.completion) {
// handler has no completion function, so we can't complete
return callback();
}
_console.log("calling completion handler for " + cmd);
return handler.completion(cmd, arg, line, function(match) {
_console.log("completion: " + JSON.stringify(match));
if(!match) {
return callback();
}
if(match.suggestions && match.suggestions.length > 1) {
return renderOutput(self.templates.suggest({suggestions: match.suggestions}), function() {
callback(match.completion);
});
}
return callback(match.completion);
});
});
return self;
}
/* ------------------------------------------------------------------------*
* Copyright 2013 Arne F. Claassen
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------*/
var Josh = Josh || {};
var root = this
Josh.PathHandler = function(shell, config) {
config = config || {};
var _console = config.console || (Josh.Debug && root.console ? root.console : {
log: function() {
}
});
var _shell = shell;
_shell.templates.not_found = _.template("
")}return q}function m(r,u,p){var v=h(r,p);var t=a(r);if(t=="no-highlight"){return}var w=t?d(t,v,true):g(v);t=w.language;var o=c(r);if(o.length){var q=document.createElementNS("http://www.w3.org/1999/xhtml","pre");q.innerHTML=w.value;w.value=j(o,c(q),v)}w.value=i(w.value,u,p);var s=r.className;if(!s.match("(\\s|^)(language-)?"+t+"(\\s|$)")){s=s?(s+" "+t):t}r.innerHTML=w.value;r.className=s;r.result={language:t,kw:w.keyword_count,re:w.r};if(w.second_best){r.second_best={language:w.second_best.language,kw:w.second_best.keyword_count,re:w.second_best.r}}}function n(){if(n.called){return}n.called=true;Array.prototype.map.call(document.getElementsByTagNameNS("http://www.w3.org/1999/xhtml","pre"),b).filter(Boolean).forEach(function(o){m(o,hljs.tabReplace)})}function k(){window.addEventListener("DOMContentLoaded",n,false);window.addEventListener("load",n,false)}var e={};this.LANGUAGES=e;this.highlight=d;this.highlightAuto=g;this.fixMarkup=i;this.highlightBlock=m;this.initHighlighting=n;this.initHighlightingOnLoad=k;this.IR="[a-zA-Z][a-zA-Z0-9_]*";this.UIR="[a-zA-Z_][a-zA-Z0-9_]*";this.NR="\\b\\d+(\\.\\d+)?";this.CNR="(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)";this.BNR="\\b(0b[01]+)";this.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|\\.|-|-=|/|/=|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~";this.BE={b:"\\\\[\\s\\S]",r:0};this.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[this.BE],r:0};this.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[this.BE],r:0};this.CLCM={cN:"comment",b:"//",e:"$"};this.CBLCLM={cN:"comment",b:"/\\*",e:"\\*/"};this.HCM={cN:"comment",b:"#",e:"$"};this.NM={cN:"number",b:this.NR,r:0};this.CNM={cN:"number",b:this.CNR,r:0};this.BNM={cN:"number",b:this.BNR,r:0};this.REGEXP_MODE={cN:"regexp",b:/\//,e:/\/[gim]*/,i:/\n/,c:[this.BE,{b:/\[/,e:/\]/,r:0,c:[this.BE]}]};this.inherit=function(q,r){var o={};for(var p in q){o[p]=q[p]}if(r){for(var p in r){o[p]=r[p]}}return o}}();hljs.LANGUAGES.ruleslanguage=function(a){return{k:{keyword:"BILL_PERIOD BILL_START BILL_STOP RS_EFFECTIVE_START RS_EFFECTIVE_STOP RS_JURIS_CODE RS_OPCO_CODE INTDADDATTRIBUTE|5 INTDADDVMSG|5 INTDBLOCKOP|5 INTDBLOCKOPNA|5 INTDCLOSE|5 INTDCOUNT|5 INTDCOUNTSTATUSCODE|5 INTDCREATEMASK|5 INTDCREATEDAYMASK|5 INTDCREATEFACTORMASK|5 INTDCREATEHANDLE|5 INTDCREATEMASK|5 INTDCREATEOVERRIDEDAYMASK|5 INTDCREATEOVERRIDEMASK|5 INTDCREATESTATUSCODEMASK|5 INTDCREATETOUPERIOD|5 INTDDELETE|5 INTDDIPTEST|5 INTDEXPORT|5 INTDGETERRORCODE|5 INTDGETERRORMESSAGE|5 INTDISEQUAL|5 INTDJOIN|5 INTDLOAD|5 INTDLOADACTUALCUT|5 INTDLOADDATES|5 INTDLOADHIST|5 INTDLOADLIST|5 INTDLOADLISTDATES|5 INTDLOADLISTENERGY|5 INTDLOADLISTHIST|5 INTDLOADRELATEDCHANNEL|5 INTDLOADSP|5 INTDLOADSTAGING|5 INTDLOADUOM|5 INTDLOADUOMDATES|5 INTDLOADUOMHIST|5 INTDLOADVERSION|5 INTDOPEN|5 INTDREADFIRST|5 INTDREADNEXT|5 INTDRECCOUNT|5 INTDRELEASE|5 INTDREPLACE|5 INTDROLLAVG|5 INTDROLLPEAK|5 INTDSCALAROP|5 INTDSCALE|5 INTDSETATTRIBUTE|5 INTDSETDSTPARTICIPANT|5 INTDSETSTRING|5 INTDSETVALUE|5 INTDSETVALUESTATUS|5 INTDSHIFTSTARTTIME|5 INTDSMOOTH|5 INTDSORT|5 INTDSPIKETEST|5 INTDSUBSET|5 INTDTOU|5 INTDTOURELEASE|5 INTDTOUVALUE|5 INTDUPDATESTATS|5 INTDVALUE|5 STDEV INTDDELETEEX|5 INTDLOADEXACTUAL|5 INTDLOADEXCUT|5 INTDLOADEXDATES|5 INTDLOADEX|5 INTDLOADEXRELATEDCHANNEL|5 INTDSAVEEX|5 MVLOAD|5 MVLOADACCT|5 MVLOADACCTDATES|5 MVLOADACCTHIST|5 MVLOADDATES|5 MVLOADHIST|5 MVLOADLIST|5 MVLOADLISTDATES|5 MVLOADLISTHIST|5 IF FOR NEXT DONE SELECT END CALL ABORT CLEAR CHANNEL FACTOR LIST NUMBER OVERRIDE SET WEEK DISTRIBUTIONNODE ELSE WHEN THEN OTHERWISE IENUM CSV INCLUDE LEAVE RIDER SAVE DELETE NOVALUE SECTION WARN DELETE SAVE SAVE_UPDATE CLEAR DETERMINANT LABEL REPORT REVENUE ABORT CALL DONE LEAVE EACH IN LIST NOVALUE FROM TOTAL CHARGE BLOCK AND OR CSV_FILE BILL_PERIOD RATE_CODE AUXILIARY_DEMAND UIDACCOUNT RS BILL_PERIOD_SELECT HOURS_PER_MONTH INTD_ERROR_STOP SEASON_SCHEDULE_NAME ACCOUNTFACTOR ARRAYUPPERBOUND CALLSTOREDPROC GETADOCONNECTION GETCONNECT GETDATASOURCE GETQUALIFIER GETUSERID HASVALUE LISTCOUNT LISTOP LISTUPDATE LISTVALUE PRORATEFACTOR RSPRORATE SETBINPATH SETDBMONITOR WQ_OPEN BILLINGHOURS DATE DATEFROMFLOAT DATETIMEFROMSTRING DATETIMETOSTRING DATETOFLOAT DAY DAYDIFF DAYNAME DBDATETIME HOUR MINUTE MONTH MONTHDIFF MONTHHOURS MONTHNAME ROUNDDATE SAMEWEEKDAYLASTYEAR SECOND WEEKDAY WEEKDIFF YEAR YEARDAY YEARSTR COMPSUM HISTCOUNT HISTMAX HISTMIN HISTMINNZ HISTVALUE MAXNRANGE MAXRANGE MINRANGE COMPIKVA COMPKVA COMPKVARFROMKQKW COMPLF IDATTR FLAG LF2KW LF2KWH MAXKW POWERFACTOR READING2USAGE AVGSEASON MAXSEASON MONTHLYMERGE SEASONVALUE SUMSEASON ACCTREADDATES ACCTTABLELOAD CONFIGADD CONFIGGET CREATEOBJECT CREATEREPORT EMAILCLIENT EXPBLKMDMUSAGE EXPMDMUSAGE EXPORT_USAGE FACTORINEFFECT GETUSERSPECIFIEDSTOP INEFFECT ISHOLIDAY RUNRATE SAVE_PROFILE SETREPORTTITLE USEREXIT WATFORRUNRATE TO TABLE ACOS ASIN ATAN ATAN2 BITAND CEIL COS COSECANT COSH COTANGENT DIVQUOT DIVREM EXP FABS FLOOR FMOD FREPM FREXPN LOG LOG10 MAX MAXN MIN MINNZ MODF POW ROUND ROUND2VALUE ROUNDINT SECANT SIN SINH SQROOT TAN TANH FLOAT2STRING FLOAT2STRINGNC INSTR LEFT LEN LTRIM MID RIGHT RTRIM STRING STRINGNC TOLOWER TOUPPER TRIM ABORT WARN NUMDAYS RATE_CODE READ_DATE STAGING",built_in:"IDENTIFIER OPTIONS XML_ELEMENT XML_OP XML_ELEMENT_OF DOMDOCCREATE DOMDOCLOADFILE DOMDOCLOADXML DOMDOCSAVEFILE DOMDOCGETROOT DOMDOCADDPI DOMNODEGETNAME DOMNODEGETTYPE DOMNODEGETVALUE DOMNODEGETCHILDCT DOMNODEGETFIRSTCHILD DOMNODEGETSIBLING DOMNODECREATECHILDELEMENT DOMNODESETATTRIBUTE DOMNODEGETCHILDELEMENTCT DOMNODEGETFIRSTCHILDELEMENT DOMNODEGETSIBLINGELEMENT DOMNODEGETATTRIBUTECT DOMNODEGETATTRIBUTEI DOMNODEGETATTRIBUTEBYNAME DOMNODEGETBYNAME"},c:[a.CLCM,a.CBLCLM,a.ASM,a.QSM,a.CNM,{cN:"array",b:"#[a-zA-Z .]+"}]}}(hljs);hljs.LANGUAGES.ruby=function(e){var a="[a-zA-Z_][a-zA-Z0-9_]*(\\!|\\?)?";var j="[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?";var g={keyword:"and false then defined module in return redo if BEGIN retry end for true self when next until do begin unless END rescue nil else break undef not super class case require yield alias while ensure elsif or include"};var c={cN:"yardoctag",b:"@[A-Za-z]+"};var k=[{cN:"comment",b:"#",e:"$",c:[c]},{cN:"comment",b:"^\\=begin",e:"^\\=end",c:[c],r:10},{cN:"comment",b:"^__END__",e:"\\n$"}];var d={cN:"subst",b:"#\\{",e:"}",l:a,k:g};var i=[e.BE,d];var b=[{cN:"string",b:"'",e:"'",c:i,r:0},{cN:"string",b:'"',e:'"',c:i,r:0},{cN:"string",b:"%[qw]?\\(",e:"\\)",c:i},{cN:"string",b:"%[qw]?\\[",e:"\\]",c:i},{cN:"string",b:"%[qw]?{",e:"}",c:i},{cN:"string",b:"%[qw]?<",e:">",c:i,r:10},{cN:"string",b:"%[qw]?/",e:"/",c:i,r:10},{cN:"string",b:"%[qw]?%",e:"%",c:i,r:10},{cN:"string",b:"%[qw]?-",e:"-",c:i,r:10},{cN:"string",b:"%[qw]?\\|",e:"\\|",c:i,r:10},{cN:"string",b:/\B\?(\\\d{1,3}|\\x[A-Fa-f0-9]{1,2}|\\u[A-Fa-f0-9]{4}|\\?\S)\b/}];var h={cN:"function",bWK:true,e:" |$|;",k:"def",c:[{cN:"title",b:j,l:a,k:g},{cN:"params",b:"\\(",e:"\\)",l:a,k:g}].concat(k)};var f=k.concat(b.concat([{cN:"class",bWK:true,e:"$|;",k:"class module",c:[{cN:"title",b:"[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?",r:0},{cN:"inheritance",b:"<\\s*",c:[{cN:"parent",b:"("+e.IR+"::)?"+e.IR}]}].concat(k)},h,{cN:"constant",b:"(::)?(\\b[A-Z]\\w*(::)?)+",r:0},{cN:"symbol",b:":",c:b.concat([{b:j}]),r:0},{cN:"symbol",b:a+":",r:0},{cN:"number",b:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",r:0},{cN:"variable",b:"(\\$\\W)|((\\$|\\@\\@?)(\\w+))"},{b:"("+e.RSR+")\\s*",c:k.concat([{cN:"regexp",b:"/",e:"/[a-z]*",i:"\\n",c:[e.BE,d]},{cN:"regexp",b:"%r{",e:"}[a-z]*",i:"\\n",c:[e.BE,d]},{cN:"regexp",b:"%r\\(",e:"\\)[a-z]*",i:"\\n",c:[e.BE,d]},{cN:"regexp",b:"%r!",e:"![a-z]*",i:"\\n",c:[e.BE,d]},{cN:"regexp",b:"%r\\[",e:"\\][a-z]*",i:"\\n",c:[e.BE,d]}]),r:0}]));d.c=f;h.c[1].c=f;return{l:a,k:g,c:f}}(hljs);hljs.LANGUAGES.haml=function(a){return{cI:true,c:[{cN:"doctype",b:"^!!!( (5|1\\.1|Strict|Frameset|Basic|Mobile|RDFa|XML\\b.*))?$",r:10},{cN:"comment",b:"^\\s*(-#|/).*$",r:0},{b:"^\\s*-(?!#)",starts:{e:"\\n",sL:"ruby"},r:0},{cN:"tag",b:"^\\s*%",c:[{cN:"title",b:"\\w+",r:0},{cN:"value",b:"[#\\.]\\w+",r:0},{b:"{\\s*",e:"\\s*}",eE:true,c:[{b:":\\w+\\s*=>",e:",\\s+",rB:true,eW:true,r:0,c:[{cN:"symbol",b:":\\w+",r:0},{cN:"string",b:'"',e:'"',r:0},{cN:"string",b:"'",e:"'",r:0},{b:"\\w+",r:0}]},],r:0},{b:"\\(\\s*",e:"\\s*\\)",eE:true,c:[{b:"\\w+\\s*=",e:"\\s+",rB:true,eW:true,r:0,c:[{cN:"attribute",b:"\\w+",r:0},{cN:"string",b:'"',e:'"',r:0},{cN:"string",b:"'",e:"'",r:0},{b:"\\w+",r:0}]},],r:0}],r:10},{cN:"bullet",b:"^\\s*[=~]\\s*",r:0},{b:"#{",starts:{e:"}",sL:"ruby"},r:0}]}}(hljs);hljs.LANGUAGES.haskell=function(f){var h={cN:"comment",b:"--",e:"$"};var g={cN:"comment",c:["self"],b:"{-",e:"-}"};var e={cN:"pragma",b:"{-#",e:"#-}"};var b={cN:"preprocessor",b:"^#",e:"$"};var d={cN:"type",b:"\\b[A-Z][\\w']*",r:0};var c={cN:"container",b:"\\(",e:"\\)",i:'"',c:[e,h,g,b,{cN:"type",b:"\\b[A-Z][\\w]*(\\((\\.\\.|,|\\w+)\\))?"},{cN:"title",b:"[_a-z][\\w']*"}]};var a={cN:"container",b:"{",e:"}",c:c.c};return{k:"let in if then else case of where do module import hiding qualified type data newtype deriving class instance as default infix infixl infixr foreign export ccall stdcall cplusplus jvm dotnet safe unsafe family forall mdo proc rec",c:[{cN:"module",b:"\\bmodule ",e:"where",k:"module where",c:[c,g],i:"\\W\\.|;"},{cN:"import",b:"\\bimport ",e:"$",k:"import qualified as hiding",c:[c,h,g],i:"\\W\\.|;"},{cN:"class",b:"\\b(class |instance )",e:"where",k:"class family instance where",c:[d,c,g]},{cN:"typedef",b:"\\b(data |(new)?type )",e:"$",k:"data family type newtype deriving",c:[e,h,g,d,c,a]},{cN:"default",b:"\\bdefault ",e:"$",k:"default",c:[d,c,h,g]},{cN:"infix",b:"\\b(infix |infixl |infixr )",e:"$",k:"infix infixl infixr",c:[f.CNM,h,g]},{cN:"foreign",b:"\\bforeign ",e:"$",k:"foreign import export ccall stdcall cplusplus jvm dotnet safe unsafe",c:[d,f.QSM,h,g]},{cN:"shebang",b:"#!\\/usr\\/bin\\/env runhaskell",e:"$"},e,h,g,b,f.QSM,f.CNM,d,{cN:"title",b:"^[_a-z][\\w']*"},{b:"->|<-"}]}}(hljs);hljs.LANGUAGES.xml=function(a){var c="[A-Za-z0-9\\._:-]+";var b={eW:true,r:0,c:[{cN:"attribute",b:c,r:0},{b:'="',rB:true,e:'"',c:[{cN:"value",b:'"',eW:true}]},{b:"='",rB:true,e:"'",c:[{cN:"value",b:"'",eW:true}]},{b:"=",c:[{cN:"value",b:"[^\\s/>]+"}]}]};return{cI:true,c:[{cN:"pi",b:"<\\?",e:"\\?>",r:10},{cN:"doctype",b:"",r:10,c:[{b:"\\[",e:"\\]"}]},{cN:"comment",b:"",r:10},{cN:"cdata",b:"<\\!\\[CDATA\\[",e:"\\]\\]>",r:10},{cN:"tag",b:"",rE:true,sL:"css"}},{cN:"tag",b:"
AuD Übung 08 Bäume (Stefan Bosse) [22.1.2026]
AuD Übung Bäume (08)
Gruppennummer und Namen der Gruppenmitglieder (Zeilenformat!)
Punkte: Total /2 1. /2 2. /2 3. /2 4. /2 5. /2 6. /2 7. /2
Bäume - Grundlagen
Bäume - Programmierung
Datenstrukturen
type node = {
left : node|null,
right : node|null,
data : string,
key : number
}
type tree = node|null
Algorithmen
function insert(node,data,key) {
if (node.key==key) error(Error);
if (k>node.key) {
if (!node.right) node.right=Node(data,key)
else insert(node.right,data,key)
} else {
if (!node.left) node.left=Node(data,key)
else insert(node.left,data,key)
}
}
function removeNode(root,k) {
// Eingabe: Wurzel vom Suchbaum T, Schlüssel k des zu löschenden Elementes
node = searchNode (root, k)
if (node = null) error(Error)
parent = searchParentofNode(root, node) // Sollte mit Search kombiniert werden
/* 1. Fall */
if (!node.left && !node.right) { // node ist Blattknoten
if (parent.left===node) // node ist linkes Kind
parent.left = null
else
parent.right = null
/* 2. Fall */
} else if (!node.left) {
if (parent.left===node) // node ist linkes Kind
parent.left = node.right
else
parent.right = node.right
} else if (!node.right) {
if (parent.left===node) // node ist linkes Kind
parent.left = node.left
else
parent.right = node.left
} else /* 3. Fall */
child = searchMinimalElement (node.right)
replaceNode(node,child) // Ersetze node durch child
}
}
function search (node,k) {
if (node.key==k) return node
if (node.left && node.left.key<k) return search(node.left,k)
if (node.right && node.right.key<k) return search(node.right,k)
error(NOTFOUND)
}
Programm
PGI+aW1wb3J0PC9iPiBqYXZhLmxhbmcuKjsKPGI+aW1wb3J0PC9iPiB1ai5sYW5nLio7CnB1YmxpYyA8Yj5jbGFzczwvYj4gTm9kZSB7CiAgcHVibGljIFN0cmluZyBkYXRhOwogIHB1YmxpYyBpbnQga2V5OwogIHB1YmxpYyBOb2RlIGxlZnQ7CiAgcHVibGljIE5vZGUgcmlnaHQ7CgogIHB1YmxpYyBOb2RlIChTdHJpbmcgZGF0YSwgaW50IGtleSkgewogICAgdGhpcy5kYXRhPWRhdGE7CiAgICB0aGlzLmtleT1rZXk7CiAgICB0aGlzLmxlZnQ9bnVsbDsKICAgIHRoaXMucmlnaHQ9bnVsbDsKICB9CgogIHB1YmxpYyB2b2lkIHByaW50ICgpIHsKICAJU3lzdGVtLm91dC5wcmludGxuKCJLZXk6ICIrdGhpcy5rZXkrIiwgRGF0YTogIit0aGlzLmRhdGEpOwogIH0KCn0=
bXBvcnQgamF2YS5sYW5nLio7CjxiPmltcG9ydDwvYj4gdWoubGFuZy4qOwoKcHVibGljIDxiPmNsYXNzPC9iPiBUcmVlIHsKICAgIHB1YmxpYyBOb2RlIHJvb3Q7CgoJcHVibGljIFRyZWUgKCkgewogICAgCXRoaXMucm9vdD1udWxsOwogICAgfQogICAgcHVibGljIE5vZGUgaW5zZXJ0KFN0cmluZyBkYXRhLCBpbnQga2V5KSB7CiAgICAgICAgcm9vdCA9IGluc2VydChyb290LCBkYXRhLCBrZXkpOwogICAgICAgIDxiPnJldHVybjwvYj4gcm9vdDsKICAgIH0KCiAgICBwcml2YXRlIE5vZGUgaW5zZXJ0KE5vZGUgbm9kZSwgU3RyaW5nIGRhdGEsIGludCBrZXkpIHsKICAgICAgICA8Yj5pZjwvYj4gKG5vZGUgPT0gbnVsbCkgPGI+cmV0dXJuPC9iPiA8Yj5uZXc8L2I+IE5vZGUoZGF0YSwga2V5KTsKICAgICAgICA8Yj5pZjwvYj4gKGtleSA9PSBub2RlLmtleSkgdGhyb3cgPGI+bmV3PC9iPiBSdW50aW1lRXhjZXB0aW9uKCJLZXkgYWxyZWFkeSBleGlzdHMhIik7CiAgICAgICAgPGI+aWY8L2I+IChrZXkgJmx0OyBub2RlLmtleSkgbm9kZS5sZWZ0ID0gaW5zZXJ0KG5vZGUubGVmdCwgZGF0YSwga2V5KTsKICAgICAgICA8Yj5lbHNlPC9iPiBub2RlLnJpZ2h0ID0gaW5zZXJ0KG5vZGUucmlnaHQsIGRhdGEsIGtleSk7CiAgICAgICAgPGI+cmV0dXJuPC9iPiBub2RlOwogICAgfQoKICAgIHB1YmxpYyBOb2RlIHJlbW92ZShpbnQga2V5KSB7CiAgICAgICAgcm9vdCA9IHJlbW92ZShyb290LCBrZXkpOwogICAgICAgIDxiPnJldHVybjwvYj4gcm9vdDsKICAgIH0KCiAgICBwcml2YXRlIE5vZGUgcmVtb3ZlKE5vZGUgbm9kZSwgaW50IGtleSkgewogICAgICAgIDxiPmlmPC9iPiAobm9kZSA9PSBudWxsKSB0aHJvdyA8Yj5uZXc8L2I+IFJ1bnRpbWVFeGNlcHRpb24oIk5PVEZPVU5EIik7CiAgICAgICAgPGI+aWY8L2I+IChrZXkgJmx0OyBub2RlLmtleSkgewogICAgICAgICAgICBub2RlLmxlZnQgPSByZW1vdmUobm9kZS5sZWZ0LCBrZXkpOwogICAgICAgIH0gPGI+ZWxzZTwvYj4gPGI+aWY8L2I+IChrZXkgJmd0OyBub2RlLmtleSkgewogICAgICAgICAgICBub2RlLnJpZ2h0ID0gcmVtb3ZlKG5vZGUucmlnaHQsIGtleSk7CiAgICAgICAgfSA8Yj5lbHNlPC9iPiB7CiAgICAgICAgICAgIDxiPmlmPC9iPiAobm9kZS5sZWZ0ID09IG51bGwpIDxiPnJldHVybjwvYj4gbm9kZS5yaWdodDsKICAgICAgICAgICAgPGI+aWY8L2I+IChub2RlLnJpZ2h0ID09IG51bGwpIDxiPnJldHVybjwvYj4gbm9kZS5sZWZ0OwogICAgICAgICAgICBOb2RlIG1pbk5vZGUgPSBub2RlLnJpZ2h0OwogICAgICAgICAgICA8Yj53aGlsZTwvYj4gKG1pbk5vZGUubGVmdCAhPSBudWxsKSBtaW5Ob2RlID0gbWluTm9kZS5sZWZ0OwoKICAgICAgICAgICAgbm9kZS5rZXkgPSBtaW5Ob2RlLmtleTsKICAgICAgICAgICAgbm9kZS5kYXRhID0gbWluTm9kZS5kYXRhOwogICAgICAgICAgICBub2RlLnJpZ2h0ID0gcmVtb3ZlKG5vZGUucmlnaHQsIG1pbk5vZGUua2V5KTsKICAgICAgICB9CiAgICAgICAgPGI+cmV0dXJuPC9iPiBub2RlOwogICAgfQoKICAgIHB1YmxpYyBOb2RlIHNlYXJjaChpbnQga2V5KSB7CiAgICAgICAgTm9kZSBub2RlID0gcm9vdDsKICAgICAgICA8Yj53aGlsZTwvYj4gKG5vZGUgIT0gbnVsbCkgewogICAgICAgICAgICA8Yj5pZjwvYj4gKGtleSA9PSBub2RlLmtleSkgPGI+cmV0dXJuPC9iPiBub2RlOwogICAgICAgICAgICA8Yj5lbHNlPC9iPiA8Yj5pZjwvYj4gKGtleSAmbHQ7IG5vZGUua2V5KSBub2RlID0gbm9kZS5sZWZ0OwogICAgICAgICAgICA8Yj5lbHNlPC9iPiBub2RlID0gbm9kZS5yaWdodDsKICAgICAgICB9CiAgICAgICAgdGhyb3cgPGI+bmV3PC9iPiBSdW50aW1lRXhjZXB0aW9uKCJOT1RGT1VORCIpOwogICAgfQoKICBwdWJsaWMgdm9pZCBwcmludCgpIHsKICAgICAgPGI+aWY8L2I+ICh0aGlzLnJvb3QgPT0gbnVsbCkgPGI+cmV0dXJuPC9iPjsKICAgICAgTm9kZVtdIHF1ZXVlID0gPGI+bmV3PC9iPiBOb2RlWzI1Nl07CiAgICAgIGludCBxcyA9IDAsIHFlID0gMDsKICAgICAgcXVldWVbcWUrK10gPSByb290OwogICAgICBpbnQgaGVpZ2h0ID0gMDsKICAgICAgPGI+d2hpbGU8L2I+IChxcyAmbHQ7IHFlKSB7CiAgICAgICAgICBpbnQgc2l6ZSA9IHFlIC0gcXM7CiAgICAgICAgICBoZWlnaHQrKzsKICAgICAgICAgIDxiPmZvcjwvYj4gKGludCBpID0gMDsgaSAmbHQ7IHNpemU7IGkrKykgewogICAgICAgICAgICAgIE5vZGUgbiA9IHF1ZXVlW3FzKytdOwogICAgICAgICAgICAgIDxiPmlmPC9iPiAobiAhPSBudWxsKSB7CiAgICAgICAgICAgICAgICAgIDxiPmlmPC9iPiAobi5sZWZ0ICE9IG51bGwpIHF1ZXVlW3FlKytdID0gbi5sZWZ0OwogICAgICAgICAgICAgICAgICA8Yj5pZjwvYj4gKG4ucmlnaHQgIT0gbnVsbCkgcXVldWVbcWUrK10gPSBuLnJpZ2h0OwogICAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgfQogICAgICBOb2RlW10gbGV2ZWwgPSA8Yj5uZXc8L2I+IE5vZGVbXSB7IHJvb3QgfTsKICAgICAgaW50IG5vZGVXaWR0aCA9IDY7CiAgICAgIDxiPmZvcjwvYj4gKGludCBsID0gMDsgbCAmbHQ7IGhlaWdodDsgbCsrKSB7CiAgICAgICAgICBpbnQgc3BhY2VzID0gKGludCkgTWF0aC5wb3coMiwgaGVpZ2h0IC0gbCAtIDEpIC0gMTsKICAgICAgICAgIGludCBsZWFkaW5nID0gc3BhY2VzICogbm9kZVdpZHRoOwogICAgICAgICAgaW50IGJldHdlZW4gPSAoc3BhY2VzICogMiArIDEpICogbm9kZVdpZHRoOwogICAgICAgICAgPGI+Zm9yPC9iPiAoaW50IGkgPSAwOyBpICZsdDsgbGVhZGluZzsgaSsrKSBTeXN0ZW0ub3V0LnByaW50KCIgIik7CiAgICAgICAgICBOb2RlW10gbmV4dCA9IDxiPm5ldzwvYj4gTm9kZVtsZXZlbC5sZW5ndGggKiAyXTsKICAgICAgICAgIDxiPmZvcjwvYj4gKGludCBpID0gMDsgaSAmbHQ7IGxldmVsLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgICAgTm9kZSBuID0gbGV2ZWxbaV07CiAgICAgICAgICAgICAgPGI+aWY8L2I+IChuID09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgPGI+Zm9yPC9iPiAoaW50IHMgPSAwOyBzICZsdDsgbm9kZVdpZHRoOyBzKyspIFN5c3RlbS5vdXQucHJpbnQoIiAiKTsKICAgICAgICAgICAgICAgICAgbmV4dFsyICogaV0gPSBudWxsOwogICAgICAgICAgICAgICAgICBuZXh0WzIgKiBpICsgMV0gPSBudWxsOwogICAgICAgICAgICAgIH0gPGI+ZWxzZTwvYj4gewogICAgICAgICAgICAgICAgICBTeXN0ZW0ub3V0LnByaW50KCJbIiArIG4ua2V5ICsgIl0iKTsKICAgICAgICAgICAgICAgICAgbmV4dFsyICogaV0gPSBuLmxlZnQ7CiAgICAgICAgICAgICAgICAgIG5leHRbMiAqIGkgKyAxXSA9IG4ucmlnaHQ7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIDxiPmZvcjwvYj4gKGludCBzID0gMDsgcyAmbHQ7IGJldHdlZW47IHMrKykgU3lzdGVtLm91dC5wcmludCgiICIpOwogICAgICAgICAgfQogICAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKCk7CiAgICAgICAgICBsZXZlbCA9IG5leHQ7CiAgICAgIH0KICB9Cgp9Cg==
[10]
[2] [11]
[1] [5] [20] [30]
PGI+aW1wb3J0PC9iPiBqYXZhLmxhbmcuKjsKPGI+aW1wb3J0PC9iPiB1ai5sYW5nLio7CnB1YmxpYyA8Yj5jbGFzczwvYj4gRGF0YVRhYmxlcyB7CiAgc3RhdGljIFN0cmluZ1tdIG5hbWVzID0gewogICAgIlJvZW50Z2VuIiwKICAgICJCZWNxdWVyZWwiLAogICAgIk1pY2hlbHNvbiIsCiAgICAiV2llbiIsCiAgICAiT25uZXMiLAogICAgIkJhcmtsYSIsCiAgICAiU3RhcmsiLAogICAgIk1pbGxpa2FuIiwKICAgICJkZUJyb2dsaWUiLAogICAgIkRhdmlzc29uIiwKICAgICJTdGVybiIsCiAgICAiQXBwbGV0b24iLAogICAgIlplcm5pa2UiLAogICAgIlNlZ3JlIiwKICAgICJIb2ZzdGFkdGVyIiwKICAgICJCZXRoZSIsCiAgICAiR2Fib3IiLAogICAgIkVzYWtpIiwKICAgICJDcm9uaW4iLAogICAgIkNoYW5kcmFzZWtoYXIiLAogICAgIkxlZGVybWFuIiwKICAgICJDaHUiLAogICAgIkFicmlrb3NvdiIsCiAgICAiUGVybG11dHRlciIsCiAgICAiU3RyaWNrbGFuZCIsCiAgICAiUGVlYmxlcyIsCiAgICAiQWdvc3RpbmkiCiAgfTsKCiAgc3RhdGljIGludFtdIHllYXJzID0gewogICAgMTkwMSwKICAgIDE5MDMsCiAgICAxOTA3LAogICAgMTkxMSwKICAgIDE5MTMsCiAgICAxOTE3LAogICAgMTkxOSwKICAgIDE5MjMsCiAgICAxOTI5LAogICAgMTkzNywKICAgIDE5NDMsCiAgICAxOTQ3LAogICAgMTk1MywKICAgIDE5NTksCiAgICAxOTYxLAogICAgMTk2NywKICAgIDE5NzEsCiAgICAxOTczLAogICAgMTk3OSwKICAgIDE5ODMsCiAgICAxOTg5LAogICAgMTk5NywKICAgIDIwMDMsCiAgICAyMDExLAogICAgMjAxNywKICAgIDIwMTksCiAgICAyMDIzCiAgfTsKCn0=
Test der Klasse Baumstruktur Tree. Ausführung von make (Linux, Mac) oder makew (Windows) und run. (websh0) help or hit TAB for a list of commands.
PGI+aW1wb3J0PC9iPiBqYXZhLmxhbmcuKjsKPGI+aW1wb3J0PC9iPiB1ai5sYW5nLio7CgpwdWJsaWMgPGI+Y2xhc3M8L2I+IFRlc3QgewogICAgcHVibGljIHN0YXRpYyB2b2lkIG1haW4oKSB7CiAgICAgICAgVHJlZSB0ID0gPGI+bmV3PC9iPiBUcmVlKCk7CiAgICAgICAgaW50IG4gPSBEYXRhVGFibGVzLm5hbWVzLmxlbmd0aDsKCiAgICAgICAgaW50W10gaW5kaWNlcyA9IDxiPm5ldzwvYj4gaW50W25dOwogICAgICAgIDxiPmZvcjwvYj4gKGludCBpID0gMDsgaSAmbHQ7IG47IGkrKykgaW5kaWNlc1tpXSA9IGk7CgogICAgICAgIDxiPmZvcjwvYj4gKGludCBpID0gbiAtIDE7IGkgJmd0OyAwOyBpLS0pIHsKICAgICAgICAgICAgaW50IGogPSAoaW50KShNYXRoLnJhbmRvbSgpICogKGkgKyAxKSk7IAogICAgICAgICAgICBpbnQgdGVtcCA9IGluZGljZXNbaV07CiAgICAgICAgICAgIGluZGljZXNbaV0gPSBpbmRpY2VzW2pdOwogICAgICAgICAgICBpbmRpY2VzW2pdID0gdGVtcDsKICAgICAgICB9CgogICAgICAgIDxiPmZvcjwvYj4gKGludCBpID0gMDsgaSAmbHQ7IG47IGkrKykgewogICAgICAgICAgICBpbnQgaWR4ID0gaW5kaWNlc1tpXTsKICAgICAgICAgICAgdC5pbnNlcnQoRGF0YVRhYmxlcy5uYW1lc1tpZHhdLCBEYXRhVGFibGVzLnllYXJzW2lkeF0pOwogICAgICAgIH0KCiAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKCJCYXVtIG5hY2ggenVmYWVsbGlnZW0gRWluZnVlZ2VuOiIpOwogICAgICAgIC8vPGk+dC5wcmludCgpOzwvaT4KCgogICAgICAgIFN5c3RlbS5vdXQucHJpbnRsbigiVWViZXJwcnVlZnVuZyBhbGxlciBEYXRlbnNhZXR6ZToiKTsKICAgICAgICA8Yj5mb3I8L2I+IChpbnQgaSA9IDA7IGkgJmx0OyBuOyBpKyspIHsKICAgICAgICAgICAgTm9kZSBub2RlID0gdC5zZWFyY2goRGF0YVRhYmxlcy55ZWFyc1tpXSk7CiAgICAgICAgICAgIFN5c3RlbS5vdXQucHJpbnRsbigiR2VmdW5kZW46ICIgKyBub2RlLmtleSArICIgLSZndDsgIiArIG5vZGUuZGF0YSk7CiAgICAgICAgfQoKICAgICAgICBpbnRbXSB5ZWFyc1RvUmVtb3ZlID0gezE5MDMsIDE5MTMsIDIwMDMsIDIwMTN9OwogICAgICAgIDxiPmZvcjwvYj4gKGludCB5ZWFyIDogeWVhcnNUb1JlbW92ZSkgewogICAgICAgICAgICB0LnJlbW92ZSh5ZWFyKTsKICAgICAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKCJFbnRmZXJudDogIiArIHllYXIpOwogICAgICAgIH0KCiAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKCJCYXVtIG5hY2ggRW50ZmVybmVuIGJlc3RpbW10ZXIgSmFocmU6Iik7CiAgICAgICAgLy88aT50LnByaW50KCk7PC9pPgoKCiAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKCJVZWJlcnBydWVmdW5nIGFsbGVyIERhdGVuc2FldHplIG5hY2ggRW50ZmVybmVuOiIpOwogICAgICAgIDxiPmZvcjwvYj4gKGludCBpID0gMDsgaSAmbHQ7IG47IGkrKykgewogICAgICAgICAgICBOb2RlIG5vZGUgPSB0LnNlYXJjaChEYXRhVGFibGVzLnllYXJzW2ldKTsKICAgICAgICAgICAgPGI+aWY8L2I+IChub2RlPT1udWxsKSB7CiAgICAgICAgICAgIAlTeXN0ZW0ub3V0LnByaW50bG4oIkZlaGx0OiAiICsgRGF0YVRhYmxlcy55ZWFyc1tpXSk7CiAgICAgICAgICAgICAgICA8Yj5jb250aW51ZTwvYj47CiAgICAgICAgICAgIH0KICAgICAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKCJHZWZ1bmRlbjogIiArIG5vZGUua2V5ICsgIiAtJmd0OyAiICsgbm9kZS5kYXRhKTsKICAgICAgICB9CiAgICB9Cgp9
Hilfe