Framework

Von $1

    Inhaltsverzeichnis
    keine Gliederung

    Version seit 19:05, 11 Aug 2026

    zu dieser Version.

    Zurück zu Versionshistorie.

    Zeige aktuelle Version

     
    LLM:
     
     
     
     
    (function() {
    
        var fontLink = document.createElement('link');
        fontLink.rel = 'stylesheet';
        fontLink.href = 'https://fonts.googleapis.com/css2?family=Press+Start+2P';
        document.head.appendChild(fontLink);
    
        var PF = '"Press Start 2P","Courier New",Courier,monospace';
        var CRISP = '-webkit-font-smoothing:none; -moz-osx-font-smoothing:unset; font-smooth:never; text-rendering:optimizeSpeed;';
    
        var css = ''
        + '#serverBuddy { display: none !important; }'
        + '#buddySpeech { display: none !important; }'
        + '#buddyChat { display:flex; gap:24px; align-items:flex-start; width:100%; font-family:' + PF + '; color:#333; ' + CRISP + ' }'
        + '#buddyChatMain { flex:1; min-width:0; }'
        + '#buddyChatSide { width:280px; flex-shrink:0; display:flex; flex-direction:column; align-items:center; position:sticky; top:40px; }'
        + '#buddyChatSide img { width:280px; height:280px; image-rendering:pixelated; image-rendering:crisp-edges; display:block; border:none; cursor:pointer; transition:transform 0.15s ease; }'
        + '#buddyChatSide img:hover { transform:rotate(-5deg) scale(1.05); }'
        + '#buddyBubble { transform:scale(0); background:#fff; color:#333; padding:12px 18px; border-radius:14px; border:2px solid #ccc; font-family:' + PF + '; font-size:16px; line-height:1.8; max-width:280px; text-align:center; white-space:pre-wrap; word-wrap:break-word; opacity:0; transition:opacity 0.3s ease,transform 0.3s ease; box-shadow:0 2px 8px rgba(0,0,0,0.1); margin-bottom:12px; ' + CRISP + ' }'
        + '#buddyBubble.visible { opacity:1; transform:scale(1); }'
        + '#buddyBubble::after { content:""; position:absolute; bottom:-10px; left:50%; transform:translateX(-50%); width:0; height:0; border-left:10px solid transparent; border-right:10px solid transparent; border-top:10px solid #ccc; }'
        + '#chatLog { min-height:400px; max-height:600px; overflow-y:auto; padding:20px; margin-bottom:16px; border:2px solid #ccc; background:#f8f8f8; }'
        + '.chatMsg { margin-bottom:14px; padding:12px 16px; border-radius:8px; font-size:16px; line-height:1.8; max-width:90%; word-wrap:break-word; }'
        + '.chatMsg.user { background:#e8e8e8; color:#555; margin-left:auto; text-align:right; border:1px solid #ddd; }'
        + '.chatMsg.buddy { background:#fff; color:#333; margin-right:auto; border:1px solid #ccc; }'
        + '.chatMsg.buddy::before { content:"> "; color:#0077aa; margin-right:4px; opacity:0.6; }'
        + '.chatMsg.buddy.claude { border-left:3px solid #d97706; }'
        + '.chatMsg.system { color:#999; font-size:16px; text-align:center; margin:8px auto; max-width:100%; }'
        + '.chatMsg.typing { color:#999; opacity:0.6; }'
        + '.chatMsg.fact { color:#0077aa; font-size:14px; text-align:left; margin:6px 0; max-width:100%; border-left:3px solid #0077aa; padding:8px 12px; background:#f0f8ff; opacity:0.9; }'
        + '.chatMsg.fact::before { content:"// "; opacity:0.5; }'
        + '.chatMsg a { color:#0077aa; text-decoration:underline; }'
        + '.chatMsg a:hover { color:#005580; }'
        + '.chatMsg pre { background:#1e1e1e; color:#d4d4d4; padding:12px; border-radius:6px; overflow-x:auto; font-family:"Courier New",monospace; font-size:13px; line-height:1.6; margin:8px 0; white-space:pre-wrap; word-wrap:break-word; }'
        + '.chatMsg code { background:#e8e8e8; color:#c7254e; padding:2px 5px; border-radius:3px; font-family:"Courier New",monospace; font-size:13px; }'
        + '.chatMsg pre code { background:none; color:inherit; padding:0; }'
        + '.chatMsg ul, .chatMsg ol { margin:6px 0 6px 20px; padding:0; }'
        + '.chatMsg li { margin:4px 0; }'
        + '.chatMsg .mdH { font-size:15px; color:#0077aa; margin:10px 0 4px 0; display:block; }'
        + '#chatInputWrap { display:flex; gap:8px; border:2px solid #ccc; background:#f8f8f8; padding:10px; }'
        + '#chatInput { flex:1; background:#fff; border:1px solid #ccc; color:#333; font-family:' + PF + '; font-size:16px; padding:12px 14px; outline:none; ' + CRISP + ' }'
        + '#chatInput::placeholder { color:#aaa; }'
        + '#chatInput:focus { border-color:#0077aa; }'
        + '#chatSend { background:#fff; color:#0077aa; border:1px solid #0077aa; padding:12px 24px; font-family:' + PF + '; font-size:16px; cursor:pointer; ' + CRISP + ' }'
        + '#chatSend:hover { background:#0077aa; color:#fff; }'
        + '#chatSend:disabled { opacity:0.3; cursor:default; }'
        + '#llmSwitch { display:flex; gap:6px; margin-top:10px; align-items:center; flex-wrap:wrap; }'
        + '#llmLabel { font-size:14px; color:#999; margin-right:4px; }'
        + '.llmBtn { background:#fff; border:1px solid #ccc; color:#666; padding:6px 14px; font-family:' + PF + '; font-size:14px; cursor:pointer; border-radius:4px; ' + CRISP + ' }'
        + '.llmBtn:hover { border-color:#0077aa; color:#0077aa; }'
        + '.llmBtn.active { background:#0077aa; color:#fff; border-color:#0077aa; }'
        + '.llmBtn.active-dual { background:#d97706; color:#fff; border-color:#d97706; }'
        + '.llmBtn:disabled { opacity:0.3; cursor:default; }'
        + '#chatFooter { display:flex; justify-content:space-between; align-items:center; margin-top:8px; }'
        + '#chatStatus { font-size:16px; color:#999; }'
        + '#chatBtns { display:flex; gap:6px; }'
        + '#chatStats, #chatExport { background:none; border:1px solid #ccc; color:#888; padding:6px 14px; font-family:' + PF + '; font-size:14px; cursor:pointer; border-radius:4px; ' + CRISP + ' }'
        + '#chatStats:hover, #chatExport:hover { background:#f0f0f0; color:#333; border-color:#999; }'
        + '#chatStats.active { background:#0077aa; color:#fff; border-color:#0077aa; }'
        + '#aiStats { display:none; margin-top:12px; padding:16px; border:2px solid #0077aa; background:#f0f8ff; border-radius:8px; font-size:14px; line-height:2.2; color:#333; }'
        + '#aiStats.visible { display:block; }'
        + '.statsTitle { font-size:14px; color:#0077aa; margin:0 0 8px 0; padding-bottom:6px; border-bottom:1px solid #ccc; }'
        + '.statRow { display:flex; justify-content:space-between; padding:3px 0; }'
        + '.statLabel { color:#666; }'
        + '.statValue { color:#333; text-align:right; }'
        + '.statSection { margin-top:10px; padding-top:6px; border-top:1px solid #e0e0e0; }'
        + '.energyBar { display:inline-block; height:6px; background:#4caf50; margin-left:6px; vertical-align:middle; border-radius:3px; }'
        + '.scoreBox { text-align:center; padding:14px; margin-bottom:10px; border:2px solid #0077aa; border-radius:8px; background:#e8f4ff; }'
        + '.scoreNum { font-size:24px; color:#0077aa; display:block; margin:6px 0; }'
        + '.scoreLabel { font-size:14px; color:#666; }'
        + '.scoreGrade { font-size:14px; margin-top:4px; }'
        + '.statIcon { display:inline-block; width:16px; text-align:center; margin-right:4px; font-style:normal; }'
        + '#mtTribute { display:none; margin-top:16px; padding:16px; border:2px solid #d97706; background:#fffbf0; border-radius:8px; font-size:14px; line-height:2; color:#333; max-width:280px; text-align:left; }'
        + '#mtTribute.visible { display:block; }'
        + '#mtTribute .mtTitle { font-size:14px; color:#d97706; margin-bottom:8px; padding-bottom:6px; border-bottom:1px solid #e0d0b0; }'
        + '#mtTribute .mtBody { color:#555; font-size:13px; line-height:1.9; }'
        + '@media (max-width:768px) { #buddyChat { flex-direction:column-reverse; } #buddyChatSide { width:100%; flex-direction:row; justify-content:center; position:static; } #buddyChatSide img { width:120px; height:120px; } #mtTribute { max-width:100%; } }';
    
        var styleEl = document.createElement('style');
        styleEl.type = 'text/css';
        styleEl.appendChild(document.createTextNode(css));
        document.head.appendChild(styleEl);
    
        /* === CONFIG === */
        var SHORT_LEN    = 100;
        var SEARCH_LIMIT = 5;
        var ENERGY_PER_TOKEN = 0.000000015;
    
        /* === PROVIDER STATE === */
        var providers = new Object();
        providers.p1 = new Object();
        providers.p1.url = ''; providers.p1.key = ''; providers.p1.model = 'default';
        providers.p1.name = 'Local'; providers.p1.type = 'openai'; providers.p1.ready = false;
        providers.p2 = new Object();
        providers.p2.url = ''; providers.p2.key = ''; providers.p2.model = 'claude-sonnet-4-20250514';
        providers.p2.name = 'Claude'; providers.p2.type = 'anthropic'; providers.p2.ready = false;
    
        var activeProvider = 'p1';
        var dualMode = false;
    
        /* === SESSION STATS === */
        var ss = new Object();
        ss.start = Date.now(); ss.reqs = 0; ss.errors = 0;
        ss.tokIn = 0; ss.tokOut = 0; ss.chIn = 0; ss.chOut = 0;
        ss.timeMs = 0; ss.lastMs = 0; ss.provider = ''; ss.model = '';
    
        /* === DOM === */
        var log        = document.getElementById('chatLog');
        var input      = document.getElementById('chatInput');
        var btn        = document.getElementById('chatSend');
        var status     = document.getElementById('chatStatus');
        var avatar     = document.getElementById('buddyChatImg');
        var bubble     = document.getElementById('buddyBubble');
        var exportBtn  = document.getElementById('chatExport');
        var statsBtn   = document.getElementById('chatStats');
        var statsDiv   = document.getElementById('aiStats');
        var llmBtn1    = document.getElementById('llmBtn1');
        var llmBtn2    = document.getElementById('llmBtn2');
        var llmBtnDual = document.getElementById('llmBtnDual');
        var tributeDiv = document.getElementById('mtTribute');
        if (!log || !input || !btn) return;
    
        log.innerHTML = '';
    
        var GIFS = new Object();
        GIFS.idle    = '/@api/deki/files/403/=buddy_idle.gif';
        GIFS.sleep   = '/@api/deki/files/402/=buddy_sleeping.gif';
        GIFS.happy   = '/@api/deki/files/401/=buddy_happy.gif';
        GIFS.error   = '/@api/deki/files/400/=buddy_error.gif';
        GIFS.loading = '/@api/deki/files/399/=buddy_loading.gif';
    
        var history = [];
        var busy = false;
        var sysMsg = '';
        var staticInfo = '';
        var statsVisible = false;
        var tributeVisible = false;
        var bubbleTimer = null;
    
        var pageId = 0;
        var userName = 'Anonymous User';
        var pagePath = '/';
        if (typeof Deki !== 'undefined') {
            if (Deki.PageId) pageId = Deki.PageId;
            if (Deki.UserName) userName = Deki.UserName;
            if (Deki.PageTitle) pagePath = Deki.PageTitle;
        }
        if (typeof YAHOO !== 'undefined' && YAHOO.Deki && YAHOO.Deki.PagePath) {
            pagePath = YAHOO.Deki.PagePath;
        }
    
        /* === LOGGING === */
        function logToServer(type, extra) {
            try {
                var payload = new Object();
                payload.type = type;
                payload.user = userName;
                payload.page = pagePath;
                payload.provider = (extra && extra.provider) ? extra.provider : '-';
                payload.model = (extra && extra.model) ? extra.model : '-';
                payload.tokens = (extra && extra.tokens) ? extra.tokens : 0;
                payload.latency = (extra && extra.latency) ? extra.latency : 0;
                payload.message = (extra && extra.message) ? extra.message : '';
                var xhr = new XMLHttpRequest();
                xhr.open('POST', '/helikon-logger.php', true);
                xhr.setRequestHeader('Content-Type', 'application/json');
                xhr.send(JSON.stringify(payload));
            } catch (e) {}
        }
    
        /* === HTML TAG HELPERS === */
        var T = String.fromCharCode(60);
        var TC = String.fromCharCode(60) + '/';
        var G = String.fromCharCode(62);
    
        function tag(el, cls, inner) {
            return T + el + ' class="' + cls + '"' + G + inner + TC + el + G;
        }
        function tagS(el, cls, style, inner) {
            return T + el + ' class="' + cls + '" style="' + style + '"' + G + inner + TC + el + G;
        }
        function makeMsg(role, content) {
            var m = new Object(); m.role = role; m.content = content; return m;
        }
        function estimateTokens(text) { return Math.ceil(text.length / 4); }
    
        /* === UTILITIES === */
        function fetchText(url, callback) {
            var xhr = new XMLHttpRequest();
            xhr.open('GET', url, true);
            xhr.onload = function() {
                callback(xhr.status === 200 ? xhr.responseText.replace(/^\s+|\s+$/g, '') : '');
            };
            xhr.onerror = function() { callback(''); };
            xhr.send();
        }
    
        function fetchAllProperties(callback) {
            if (!pageId) { callback(new Object()); return; }
            var url = '/@api/deki/pages/' + pageId + '/properties';
            var xhr = new XMLHttpRequest();
            xhr.open('GET', url, true);
            xhr.onload = function() {
                var props = new Object();
                if (xhr.status === 200) {
                    try {
                        var parser = new DOMParser();
                        var xml = parser.parseFromString(xhr.responseText, 'text/xml');
                        var nodes = xml.getElementsByTagName('property');
                        var i;
                        for (i = 0; i < nodes.length; i++) {
                            var nameAttr = nodes[i].getAttribute('name') || '';
                            var contents = nodes[i].getElementsByTagName('contents');
                            var val = '';
                            if (contents.length > 0 && contents[0].textContent) {
                                val = contents[0].textContent.replace(/^\s+|\s+$/g, '');
                            }
                            props[nameAttr.replace('urn:custom.mindtouch.com#', '')] = val;
                        }
                    } catch (e) {}
                }
                callback(props);
            };
            xhr.onerror = function() { callback(new Object()); };
            xhr.send();
        }
    
        /* === MINDTOUCH API LAYER === */
        var mtConfig = new Object();
        mtConfig.base = '/@api/deki';
        mtConfig.key = '';
        mtConfig.ready = false;
    
        function mtApi(endpoint, callback) {
            var url = mtConfig.base + endpoint;
            var xhr = new XMLHttpRequest();
            xhr.open('GET', url, true);
            if (mtConfig.key) {
                xhr.setRequestHeader('Authorization', 'Bearer ' + mtConfig.key);
            }
            xhr.onload = function() {
                if (xhr.status === 200 || xhr.status === 304) {
                    try {
                        var parser = new DOMParser();
                        var xml = parser.parseFromString(xhr.responseText, 'text/xml');
                        callback(null, xml);
                    } catch (e) { callback('Parse-Fehler', null); }
                } else { callback('HTTP ' + xhr.status, null); }
            };
            xhr.onerror = function() { callback('Nicht erreichbar', null); };
            xhr.send();
        }
    
        function mtSubpages(pagePath, callback) {
            var encoded = encodeURIComponent(pagePath.replace(/\//g, '%2F'));
            mtApi('/pages/=' + encoded + '/subpages', function(err, xml) {
                if (err) { callback(err, []); return; }
                var results = [];
                try {
                    var pages = xml.getElementsByTagName('page.subpage');
                    if (pages.length === 0) pages = xml.getElementsByTagName('page');
                    var i;
                    for (i = 0; i < pages.length; i++) {
                        var entry = new Object();
                        entry.id = pages[i].getAttribute('id') || '';
                        var titleEl = pages[i].getElementsByTagName('title');
                        var pathEl = pages[i].getElementsByTagName('path');
                        entry.title = titleEl.length > 0 ? titleEl[0].textContent : '';
                        entry.path = pathEl.length > 0 ? pathEl[0].textContent : '';
                        if (entry.title) results.push(entry);
                    }
                } catch (e) {}
                callback(null, results);
            });
        }
    
        function mtPageContent(pageIdArg, callback) {
            mtApi('/pages/' + pageIdArg + '/contents', callback);
        }
    
        function mtPageProps(pageIdArg, callback) {
            mtApi('/pages/' + pageIdArg + '/properties', function(err, xml) {
                if (err) { callback(err, new Object()); return; }
                var props = new Object();
                try {
                    var nodes = xml.getElementsByTagName('property');
                    var i;
                    for (i = 0; i < nodes.length; i++) {
                        var name = nodes[i].getAttribute('name') || '';
                        var contents = nodes[i].getElementsByTagName('contents');
                        var val = '';
                        if (contents.length > 0 && contents[0].textContent) {
                            val = contents[0].textContent.replace(/^\s+|\s+$/g, '');
                        }
                        props[name.replace('urn:custom.mindtouch.com#', '')] = val;
                    }
                } catch (e) {}
                callback(null, props);
            });
        }
    
        /* Global API fuer Features-Panel und zukuenftige Module */
        window.helikonApi = new Object();
        window.helikonApi.mt = mtApi;
        window.helikonApi.mtSubpages = mtSubpages;
        window.helikonApi.mtPageContent = mtPageContent;
        window.helikonApi.mtPageProps = mtPageProps;
        window.helikonApi.mtConfig = mtConfig;
        window.helikonApi.providers = providers;
    
        /* === WIKI SEARCH === */
        function searchWiki(query, callback) {
            var url = '/@api/deki/site/search?q=' + encodeURIComponent(query) + '&limit=' + SEARCH_LIMIT + '&format=xml';
            var xhr = new XMLHttpRequest();
            xhr.open('GET', url, true);
            xhr.onload = function() {
                var results = [];
                if (xhr.status === 200) {
                    try {
                        var parser = new DOMParser();
                        var xml = parser.parseFromString(xhr.responseText, 'text/xml');
                        var pages = xml.getElementsByTagName('page');
                        if (pages.length === 0) pages = xml.getElementsByTagName('search-result');
                        var i;
                        for (i = 0; i < Math.min(pages.length, SEARCH_LIMIT); i++) {
                            var titleEl = pages[i].getElementsByTagName('title');
                            var pathEl = pages[i].getElementsByTagName('path');
                            var snippetEl = pages[i].getElementsByTagName('preview');
                            if (snippetEl.length === 0) snippetEl = pages[i].getElementsByTagName('content.snippet');
                            var title = titleEl.length > 0 ? titleEl[0].textContent : '';
                            var path = pathEl.length > 0 ? pathEl[0].textContent : '';
                            var snippet = snippetEl.length > 0 ? snippetEl[0].textContent : '';
                            if (title || path) {
                                var entry = new Object();
                                entry.title = title; entry.path = path;
                                entry.snippet = snippet.replace(/^\s+|\s+$/g, '').substring(0, 150);
                                results.push(entry);
                            }
                        }
                    } catch (e) {}
                }
                callback(results);
            };
            xhr.onerror = function() { callback([]); };
            xhr.send();
        }
    
    function buildSearchContext(results) {
            var filtered = [];
            var fi;
            for (fi = 0; fi < results.length; fi++) {
                var p = '' + (results[fi].path || '');
                if (p.indexOf('Template:') === 0) continue;
                if (p.indexOf('[object') !== -1) continue;
                filtered.push(results[fi]);
            }
            if (filtered.length === 0) return '';
            var ctx = '\n\n[Interne Dokumentation - nicht woertlich zitieren]\n';
            var i;
            for (i = 0; i < filtered.length; i++) {
                var r = filtered[i];
                ctx += (i + 1) + '. ' + r.title + ' (/' + r.path + ')';
                if (r.snippet) ctx += ' - ' + r.snippet;
                ctx += '\n';
            }
            return ctx;
        }
    
        function isGreeting(msg) {
            var lower = msg.toLowerCase();
            var greetings = new Array('hi','hallo','hey','moin','servus','gr\u00FCezi','gr\u00FCzi','sal\u00FC','yo','guten tag','guten morgen','guten abend','hoi');
            var i;
            for (i = 0; i < greetings.length; i++) {
                if (lower === greetings[i] || lower === greetings[i] + '!' || lower === greetings[i] + '.') return true;
            }
            return false;
        }
    
        /* === UI === */
        function setGif(name) { if (avatar) avatar.src = GIFS[name] || GIFS.idle; }
    
        function showBubble(txt, duration) {
            if (!bubble) return;
            if (bubbleTimer) clearTimeout(bubbleTimer);
            bubble.textContent = txt;
            bubble.className = 'visible';
            bubbleTimer = setTimeout(function() { bubble.className = ''; }, duration || 5000);
        }
    
        var HASH = String.fromCharCode(35);
        var rxInParen = new RegExp('\\(\\/([\\w\\/:.\\.\\-_%?=+' + HASH + ']+)\\)', 'g');
        var rxStandalone = new RegExp('(?:^|[\\s,])(\\/[\\w][\\w\\/:.\\.\\-_%?=+' + HASH + ']*)', 'g');
    
        function cleanPath(p) {
            var trail = '';
            while (p.length > 1 && '.!?,;:'.indexOf(p.charAt(p.length - 1)) !== -1) {
                trail = p.charAt(p.length - 1) + trail;
                p = p.substring(0, p.length - 1);
            }
            var r = new Object(); r.path = p; r.tail = trail; return r;
        }
        function makeLink(p) { return T + 'a href="' + p + '" target="_blank"' + G + p + TC + 'a' + G; }
    
        function formatReply(text) {
            /* Code-Bloecke schuetzen */
            var codeBlocks = [];
            text = text.replace(/```[\w]*\n?([\s\S]*?)```/g, function(m, code) {
                var idx = codeBlocks.length;
                codeBlocks.push(T + 'pre' + G + T + 'code' + G + code.replace(/&/g,'&').replace(/g,'>') + TC + 'code' + G + TC + 'pre' + G);
                return '%%CODE' + idx + '%%';
            });
            /* Inline code */
            text = text.replace(/`([^`]+)`/g, T + 'code' + G + '$1' + TC + 'code' + G);
            /* Headings: **Text** am Zeilenanfang */
            text = text.replace(/(?:^|\n)\*\*([^*]+)\*\*(?:\n|$)/g, '\n' + T + 'span class="mdH"' + G + '$1' + TC + 'span' + G + '\n');
            /* Bold */
            text = text.replace(/\*\*([^*]+)\*\*/g, T + 'strong' + G + '$1' + TC + 'strong' + G);
            /* List items: * text */
            text = text.replace(/(?:^|\n)\* ([^\n]+)/g, '\n' + T + 'li' + G + '$1' + TC + 'li' + G);
            /* Aufeinanderfolgende li in ul wrappen */
            text = text.replace(/((?:\s*
  • [\s\S]*?<\/li>\s*)+)/g, T + 'ul' + G + '$1' + TC + 'ul' + G); /* Newlines zu br */ text = text.replace(/\n/g, T + 'br /' + G); /* Code-Bloecke zurueck */ var ci; for (ci = 0; ci < codeBlocks.length; ci++) { text = text.replace('%%CODE' + ci + '%%', codeBlocks[ci]); } return text; } function linkifyReply(text) { /* Externe URLs (https://...) klickbar machen */ var urlRx = new RegExp('(https?:\\/\\/[\\w][\\w\\/:.\\-_%?=+' + HASH + '&@!~]*[\\w\\/])', 'g'); var linked = text.replace(urlRx, function(match, url) { return T + 'a href="' + url + '" target="_blank"' + G + url + TC + 'a' + G; }); linked = linked.replace(rxInParen, function(match, raw) { var c = cleanPath(raw); return '(' + makeLink('/' + c.path) + c.tail + ')'; }); linked = linked.replace(rxStandalone, function(match, raw) { var prefix = match.charAt(0) === '/' ? '' : match.charAt(0); var c = cleanPath(raw); return prefix + makeLink(c.path) + c.tail; }); return linked; } function addMsg(text, cls) { var div = document.createElement('div'); div.className = 'chatMsg ' + cls; if (cls.indexOf('buddy') !== -1) { div.innerHTML = linkifyReply(text); } else { div.textContent = text; } log.appendChild(div); log.scrollTop = log.scrollHeight; return div; } function setStatus(txt) { if (status) status.textContent = txt || ''; } /* === PDF EXPORT === */ function exportPdf() { var msgs = log.getElementsByClassName('chatMsg'); if (msgs.length === 0) { showBubble('Nix zum Exportieren!', 3000); return; } var now = new Date(); var dateStr = now.getFullYear() + '-' + ('0' + (now.getMonth() + 1)).slice(-2) + '-' + ('0' + now.getDate()).slice(-2); var timeStr = ('0' + now.getHours()).slice(-2) + ':' + ('0' + now.getMinutes()).slice(-2); var html = T + '!DOCTYPE html' + G + T + 'html' + G + T + 'head' + G; html += T + 'meta charset="utf-8" /' + G; html += T + 'title' + G + 'Helikon Chat Export ' + dateStr + TC + 'title' + G; html += T + 'style' + G; html += 'body{font-family:"Courier New",monospace;font-size:14px;color:#333;max-width:800px;margin:0 auto;padding:40px 20px}'; html += 'h1{font-size:20px;border-bottom:2px solid #0077aa;padding-bottom:10px;color:#0077aa}'; html += '.meta{color:#999;font-size:12px;margin-bottom:30px}'; html += '.msg{margin-bottom:16px;padding:12px 16px;border-radius:6px;line-height:1.6}'; html += '.msg-user{background:#e8e8e8;text-align:right;border:1px solid #ddd}'; html += '.msg-buddy{background:#f8f8f8;border:1px solid #ccc}'; html += 'a{color:#0077aa}'; html += TC + 'style' + G + TC + 'head' + G + T + 'body' + G; html += T + 'h1' + G + 'Helikon Chat Export' + TC + 'h1' + G; html += T + 'div class="meta"' + G + dateStr + ' ' + timeStr + TC + 'div' + G; var i; for (i = 0; i < msgs.length; i++) { var el = msgs[i]; if (el.className.indexOf('system') > -1 || el.className.indexOf('typing') > -1 || el.className.indexOf('fact') > -1) continue; var mcls = el.className.indexOf('user') > -1 ? 'msg-user' : 'msg-buddy'; html += T + 'div class="msg ' + mcls + '"' + G + el.innerHTML + TC + 'div' + G; } html += TC + 'body' + G + TC + 'html' + G; var printWin = window.open('', '_blank'); printWin.document.write(html); printWin.document.close(); printWin.onload = function() { printWin.print(); }; showBubble('PDF wird erstellt...', 3000); } if (exportBtn) exportBtn.addEventListener('click', exportPdf); /* === SCORE === */ function calcScore() { if (ss.reqs === 0) { var r0 = new Object(); r0.score = 0; r0.grade = 'Noch keine Daten'; r0.color = '#999'; return r0; } var avgMs = Math.round(ss.timeMs / ss.reqs); var avgTok = Math.round((ss.tokIn + ss.tokOut) / ss.reqs); var raw = 100; if (avgMs > 500) raw -= Math.min((avgMs - 500) / 50, 30); if (avgTok > 200) raw -= Math.min((avgTok - 200) / 20, 20); raw -= (ss.errors / ss.reqs) * 50; raw = Math.max(0, Math.min(100, Math.round(raw))); var grade = ''; var color = '#999'; if (raw >= 90) { grade = '\u2B50 Prompt-Meister'; color = '#4caf50'; } else if (raw >= 75) { grade = '\u26A1 Speed-Runner'; color = '#8bc34a'; } else if (raw >= 60) { grade = '\u2705 Effizient'; color = '#ffc107'; } else if (raw >= 40) { grade = '\u23F3 Gemuetlich'; color = '#ff9800'; } else { grade = '\u2618 Energie-Verschwender'; color = '#f44336'; } var res = new Object(); res.score = raw; res.grade = grade; res.color = color; return res; } function sr(label, value) { return tag('div', 'statRow', tag('span', 'statLabel', label) + tag('span', 'statValue', value)); } function updateStats() { if (!statsDiv) return; var elapsed = Math.floor((Date.now() - ss.start) / 1000); var mins = Math.floor(elapsed / 60); var secs = elapsed % 60; var totTok = ss.tokIn + ss.tokOut; var kwh = totTok * ENERGY_PER_TOKEN; var avgMs = ss.reqs > 0 ? Math.round(ss.timeMs / ss.reqs) : 0; var sc = calcScore(); var ico = function(i) { return tagS('em', 'statIcon', '', i); }; var h = tag('div', 'scoreBox', tag('span', 'scoreLabel', 'EFFIZIENZ-SCORE') + tagS('span', 'scoreNum', 'color:' + sc.color, '' + sc.score) + tagS('span', 'scoreGrade', 'color:' + sc.color, sc.grade)); h += tag('div', 'statsTitle', ico('\u2699') + 'Session'); h += sr(ico('\u26A1') + 'Provider', ss.provider || '-'); h += sr(ico('\u23F1') + 'Dauer', mins + 'm ' + secs + 's'); h += tag('div', 'statsTitle', ico('\u2709') + 'Anfragen'); h += sr(ico('\u2197') + 'Gesendet', '' + ss.reqs); h += sr(ico('\u23F3') + 'Avg Antwort', avgMs + ' ms'); h += tag('div', 'statsTitle', ico('\u2B50') + 'Tokens'); h += sr(ico('\u25B2') + 'Rein', '' + ss.tokIn); h += sr(ico('\u25BC') + 'Raus', '' + ss.tokOut); h += sr(ico('\u2211') + 'Total', totTok + ' ' + tagS('span', 'energyBar', 'width:' + Math.min(totTok / 50, 150) + 'px', '')); h += tag('div', 'statsTitle', ico('\u2618') + 'Energie'); h += sr(ico('\u26A1') + 'Verbrauch', kwh.toFixed(6) + ' kWh'); var comp = ''; if (kwh > 0) { var ledH = kwh / 0.01; if (ledH < 0.01) comp = 'weniger als 1 Sek LED'; else if (ledH < 1) comp = (ledH * 60).toFixed(0) + ' Min LED'; else comp = ledH.toFixed(1) + ' Std LED'; } else { comp = 'noch nix verbraucht'; } h += sr(ico('\u2600') + 'Vergleich', comp); statsDiv.innerHTML = h; } /* === STATS BUTTON === */ if (statsBtn) { statsBtn.addEventListener('click', function() { statsVisible = !statsVisible; if (statsVisible) { updateStats(); statsDiv.className = 'visible'; statsBtn.className = 'active'; showBubble('Nerd-Modus!', 3000); } else { statsDiv.className = ''; statsBtn.className = ''; } }); } /* === MINDTOUCH TRIBUTE (Avatar Click) === */ if (avatar) { avatar.addEventListener('click', function() { tributeVisible = !tributeVisible; if (tributeVisible) { var h = ''; h += tag('div', 'mtTitle', '\u2764 MindTouch Core (2006\u20132013)'); h += T + 'div class="mtBody"' + G; h += 'Am 9. April 2013 schrieb Aaron Fulkerson:'; h += T + 'br /' + G + T + 'br /' + G; h += T + 'em' + G + '"This is the End, Beautiful Friend"' + TC + 'em' + G; h += T + 'br /' + G + T + 'br /' + G; h += 'MindTouch Core und Platform wurden eingestellt. Was als Fork von MediaWiki begann (2005), wurde zu einem der Top-5 Open-Source-Projekte weltweit.'; h += T + 'br /' + G + T + 'br /' + G; h += 'DekiWiki brachte XHTML statt Wikitext, WYSIWYG-Editing und DekiScript \u2013 eine eigene Skriptsprache direkt in Wiki-Seiten. Die REST-API auf C#/Mono war ihrer Zeit voraus.'; h += T + 'br /' + G + T + 'br /' + G; h += 'Danke an Aaron Fulkerson, Steve Bjorg und alle Community-Contributors.'; h += T + 'br /' + G + T + 'br /' + G; h += T + 'em' + G + 'Diese Seite laeuft noch immer auf MindTouch Core 2013.' + TC + 'em' + G; h += T + 'br /' + G; h += T + 'em' + G + 'Manche Software stirbt nie wirklich.' + TC + 'em' + G; h += TC + 'div' + G; tributeDiv.innerHTML = h; tributeDiv.className = 'visible'; setGif('happy'); showBubble('Danke, MindTouch!', 5000); setTimeout(function() { setGif('idle'); }, 5000); } else { tributeDiv.className = ''; } }); } /* === HANDLE REPLY === */ function handleReply(reply, providerName, providerType) { history.push(makeMsg('assistant', reply)); var cls = 'buddy'; if (providerType === 'anthropic') cls += ' claude'; if (dualMode) { addMsg('[' + providerName + '] ' + reply, cls); } else { addMsg(reply, cls); } var logData = new Object(); logData.provider = providerName; logData.model = ss.model; logData.tokens = ss.tokOut; logData.latency = ss.lastMs; logData.message = reply; logToServer('bot_reply', logData); if (reply.length <= SHORT_LEN && !dualMode) { showBubble(reply, 6000); } else { var dot = reply.indexOf('. '); var summary; if (dot > 0 && dot < 80) { summary = reply.substring(0, dot + 1); } else if (reply.length > 60) { summary = reply.substring(0, 57) + '...'; } else { summary = reply; } showBubble(dualMode ? providerName + ': OK' : summary, 6000); } setGif('happy'); setTimeout(function() { setGif('idle'); }, 3000); if (statsVisible) updateStats(); } /* === LLM CALLS === */ function callOpenAI(prov, searchContext, callback) { var fullSys = sysMsg; if (staticInfo) fullSys += '\n\n' + staticInfo; if (searchContext) fullSys += searchContext; var messages = []; messages.push(makeMsg('system', fullSys)); var i; for (i = 0; i < history.length; i++) { messages.push(history[i]); } var bodyObj = new Object(); bodyObj.model = prov.model; bodyObj.messages = messages; bodyObj.max_tokens = 1000; var xhr = new XMLHttpRequest(); xhr.open('POST', prov.url, true); xhr.setRequestHeader('Content-Type', 'application/json'); if (prov.key) xhr.setRequestHeader('Authorization', 'Bearer ' + prov.key); xhr.onload = function() { if (xhr.status === 200) { try { var data = JSON.parse(xhr.responseText); callback(null, data.choices[0].message.content, data); } catch (e) { callback('Parse-Fehler'); } } else { callback('API-Fehler ' + xhr.status); } }; xhr.onerror = function() { callback('Nicht erreichbar'); }; xhr.send(JSON.stringify(bodyObj)); } function callAnthropic(prov, searchContext, callback) { var fullSys = sysMsg; if (staticInfo) fullSys += '\n\n' + staticInfo; if (searchContext) fullSys += searchContext; var msgs = []; var i; for (i = 0; i < history.length; i++) { if (history[i].role !== 'system') { msgs.push(makeMsg(history[i].role, history[i].content)); } } var bodyObj = new Object(); bodyObj.model = prov.model; bodyObj.max_tokens = 1000; bodyObj.system = fullSys; bodyObj.messages = msgs; var xhr = new XMLHttpRequest(); xhr.open('POST', prov.url, true); xhr.setRequestHeader('Content-Type', 'application/json'); xhr.setRequestHeader('x-api-key', prov.key); xhr.setRequestHeader('anthropic-version', '2023-06-01'); xhr.setRequestHeader('anthropic-dangerous-direct-browser-access', 'true'); xhr.onload = function() { if (xhr.status === 200) { try { var data = JSON.parse(xhr.responseText); var reply = ''; var ci; for (ci = 0; ci < data.content.length; ci++) { if (data.content[ci].type === 'text') reply += data.content[ci].text; } callback(null, reply, data); } catch (e) { callback('Parse-Fehler'); } } else { callback('API-Fehler ' + xhr.status); } }; xhr.onerror = function() { callback('Nicht erreichbar'); }; xhr.send(JSON.stringify(bodyObj)); } function callProvider(providerKey, searchContext, callback) { var prov = providers[providerKey]; if (!prov || !prov.ready) { callback('Provider nicht konfiguriert'); return; } var startTime = Date.now(); ss.provider = prov.name; ss.model = prov.model; var wrapCb = function(err, reply, data) { var latency = Date.now() - startTime; ss.lastMs = latency; ss.timeMs += latency; ss.reqs++; if (err) { ss.errors++; callback(err); } else { ss.chOut += reply.length; if (data && data.usage) { ss.tokIn += data.usage.prompt_tokens || data.usage.input_tokens || 0; ss.tokOut += data.usage.completion_tokens || data.usage.output_tokens || 0; } else { ss.tokIn += estimateTokens(reply); ss.tokOut += estimateTokens(reply); } callback(null, reply); } }; if (prov.type === 'anthropic') { callAnthropic(prov, searchContext, wrapCb); } else { callOpenAI(prov, searchContext, wrapCb); } } /* === SEND === */ function send() { var msg = input.value.replace(/^\s+|\s+$/g, ''); if (!msg || busy) return; if (!providers.p1.ready && !providers.p2.ready) { addMsg('Kein LLM konfiguriert.', 'system'); showBubble('Keine API!', 3000); setGif('error'); setTimeout(function() { setGif('idle'); }, 4000); return; } addMsg(msg, 'user'); input.value = ''; history.push(makeMsg('user', msg)); ss.chIn += msg.length; logToServer('user_msg', {message: msg}); busy = true; btn.disabled = true; setGif('loading'); showBubble('...', 30000); var typing = addMsg('...', 'buddy typing'); var doCall = function(searchCtx) { if (dualMode) { if (typing.parentNode) log.removeChild(typing); var pending = 0; if (providers.p1.ready) pending++; if (providers.p2.ready) pending++; var dualDone = function() { pending--; if (pending <= 0) { busy = false; btn.disabled = false; input.focus(); setStatus('Dual Mode | bereit'); } }; var keys = new Array('p1', 'p2'); var ki; for (ki = 0; ki < keys.length; ki++) { (function(pk) { if (!providers[pk].ready) return; var dt = addMsg('[' + providers[pk].name + '] ...', 'buddy typing'); callProvider(pk, searchCtx, function(err, reply) { if (dt.parentNode) log.removeChild(dt); if (err) { addMsg('[' + providers[pk].name + '] Fehler: ' + err, 'system'); logToServer('error', {provider: providers[pk].name, message: err}); } else { handleReply(reply, providers[pk].name, providers[pk].type); } dualDone(); }); })(keys[ki]); } } else { callProvider(activeProvider, searchCtx, function(err, reply) { if (typing.parentNode) log.removeChild(typing); if (err) { addMsg('Fehler: ' + err, 'system'); showBubble('Fehler!', 3000); setGif('error'); setTimeout(function() { setGif('idle'); }, 4000); setStatus(err); logToServer('error', {provider: providers[activeProvider].name, message: err}); } else { handleReply(reply, providers[activeProvider].name, providers[activeProvider].type); setStatus(providers[activeProvider].name + ' | bereit'); } busy = false; btn.disabled = false; input.focus(); }); } }; if (isGreeting(msg)) { setStatus('antworte...'); doCall(''); } else { setStatus('durchsuche Doku...'); searchWiki(msg, function(results) { var ctx = buildSearchContext(results); setStatus(results.length > 0 ? 'denkt nach... (' + results.length + ' Treffer)' : 'denkt nach...'); doCall(ctx); }); } } /* === LLM SWITCH === */ function updateSwitchUI() { llmBtn1.className = 'llmBtn'; llmBtn2.className = 'llmBtn'; llmBtnDual.className = 'llmBtn'; llmBtn1.disabled = !providers.p1.ready; llmBtn2.disabled = !providers.p2.ready; llmBtnDual.disabled = (!providers.p1.ready || !providers.p2.ready); if (dualMode) { llmBtnDual.className = 'llmBtn active-dual'; } else if (activeProvider === 'p1') { llmBtn1.className = 'llmBtn active'; } else { llmBtn2.className = 'llmBtn active'; } if (!dualMode && providers[activeProvider]) { setStatus(providers[activeProvider].name + ' | bereit'); } else if (dualMode) { setStatus('Dual Mode | bereit'); } } llmBtn1.addEventListener('click', function() { if (!providers.p1.ready) return; dualMode = false; activeProvider = 'p1'; updateSwitchUI(); showBubble(providers.p1.name + ' aktiv', 2000); logToServer('provider_switch', {message: providers.p1.name + ' | ' + providers.p1.model + ' | ' + providers.p1.type}); }); llmBtn2.addEventListener('click', function() { if (!providers.p2.ready) return; dualMode = false; activeProvider = 'p2'; updateSwitchUI(); showBubble(providers.p2.name + ' aktiv', 2000); logToServer('provider_switch', {message: providers.p2.name + ' | ' + providers.p2.model + ' | ' + providers.p2.type}); }); llmBtnDual.addEventListener('click', function() { if (!providers.p1.ready || !providers.p2.ready) return; dualMode = !dualMode; updateSwitchUI(); showBubble(dualMode ? 'Dual-Modus!' : providers[activeProvider].name + ' aktiv', 2000); logToServer('provider_switch', {message: dualMode ? 'Dual Mode' : providers[activeProvider].name}); }); btn.addEventListener('click', send); input.addEventListener('keydown', function(e) { if (e.keyCode === 13) send(); }); /* === INIT === */ setGif('loading'); setStatus('lade konfiguration...'); input.disabled = true; btn.disabled = true; fetchAllProperties(function(props) { providers.p1.url = props['buddy.apiurl'] || ''; providers.p1.key = props['buddy.apikey'] || ''; if (props['buddy.model']) providers.p1.model = props['buddy.model']; if (props['buddy.name1']) providers.p1.name = props['buddy.name1']; providers.p1.ready = !!providers.p1.url; providers.p2.url = props['buddy.apiurl2'] || ''; providers.p2.key = props['buddy.apikey2'] || ''; if (props['buddy.model2']) providers.p2.model = props['buddy.model2']; if (props['buddy.name2']) providers.p2.name = props['buddy.name2']; providers.p2.ready = !!providers.p2.url; /* MindTouch API config */ mtConfig.base = props['buddy.mtapi'] || '/@api/deki'; mtConfig.key = props['buddy.mtapikey'] || ''; mtConfig.ready = true; if (llmBtn1) llmBtn1.textContent = providers.p1.name; if (llmBtn2) llmBtn2.textContent = providers.p2.name; if (!providers.p1.ready && providers.p2.ready) activeProvider = 'p2'; var sysPromptUrl = props['buddy.systemprompt'] || '/@api/deki/files/404/=system-prompt.txt'; var staticInfoUrl = props['buddy.staticinfo'] || ''; function ready() { var loaded = []; loaded.push('Prompt: ' + (sysMsg.length > 20 ? 'OK (' + sysMsg.length + ' Zeichen)' : 'FALLBACK')); loaded.push('Static: ' + (staticInfo ? 'OK (' + staticInfo.length + ' Zeichen)' : 'LEER')); setGif('idle'); input.disabled = false; btn.disabled = false; updateSwitchUI(); var startProv = providers[activeProvider]; if (startProv && startProv.ready) { logToServer('session_start', {provider: startProv.name, model: startProv.model}); } if (providers.p1.ready || providers.p2.ready) { showBubble('Hallo! Wie kann ich helfen?', 5000); setStatus(loaded.join(' | ')); } else { showBubble('Kein LLM konfiguriert!', 5000); setGif('error'); setStatus('buddy.apiurl / buddy.apiurl2 fehlt'); } } function loadStatic(callback) { if (staticInfoUrl) { fetchText(staticInfoUrl, function(val) { if (val) staticInfo = val; callback(); }); } else { callback(); } } if (sysPromptUrl) { fetchText(sysPromptUrl, function(val) { sysMsg = val || 'Du bist Helikon, ein freundlicher Dokumentations-Assistent.'; loadStatic(ready); }); } else { sysMsg = 'Du bist Helikon, ein freundlicher Dokumentations-Assistent.'; loadStatic(ready); } }); /* === HEADER HOVER FACTS === */ var headerFacts = new Object(); var hf = headerFacts; hf['Charles Babbage'] = new Array('Der Urvater aller Computer! Hat die Analytical Engine nie fertig gebaut. Kennen wir das nicht alle?','Babbage hasste Strassenmusikanten. Haette er Slack-Notifications erlebt...','Fun fact: Die britische Regierung gab ihm 17000 Pfund. Das waere heute ueber 3 Millionen!'); hf['Ada Lovelace'] = new Array('Die erste Programmiererin der Welt! Und das ohne Stack Overflow.','Ada schrieb den ersten Algorithmus bevor es Computer gab. Talk about early adopter!','Tochter von Lord Byron. Poesie und Code liegen naeher als man denkt.'); hf['Konrad Zuse'] = new Array('Z3: Der erste funktionierende Computer der Welt. Made in Germany!','Zuse hat nebenbei auch die erste hoehere Programmiersprache erfunden: Plankalkuel.','Er baute den Z1 im Wohnzimmer seiner Eltern. Der erste Nerd-Keller war ein Wohnzimmer.'); hf['Howard Aiken'] = new Array('Harvard Mark I: 16 Meter lang, 5 Tonnen schwer. Und weniger Rechenpower als deine Smartwatch.','Aiken sagte: Die Welt braucht vielleicht 5 Computer. Ups.','Der Mark I klang wie eine Naehfabrik. Noise-Cancelling gabs noch nicht.'); hf['Alan Turing'] = new Array('Hat den Enigma-Code geknackt und den Krieg verkuerzt. Nicht schlecht fuer einen Mathematiker.','Der Turing-Test: Kann eine Maschine denken? Frag mich nochmal in 10 Jahren.','Turing liebte Langstreckenlaeufe. Debug-Methode: Rennen bis die Loesung kommt.'); hf['John von Neumann'] = new Array('Die Von-Neumann-Architektur: Jeder Computer den du je benutzt hast basiert darauf.','Er konnte ganze Buecher auswendig zitieren. Menschliches RAM auf Maximum.','Von Neumann rechnete schneller im Kopf als fruehere Computer. Kein Witz.'); hf['Steve Jobs bis 1976'] = new Array('Apple wurde in einer Garage gegruendet. Jedes Startup braucht eine Origin-Story.','Jobs war barfuss bei wichtigen Meetings. Der erste Casual Friday.','Er ging nach Indien um sich selbst zu finden. Kam zurueck und erfand Apple.'); hf['IBM PC 5150'] = new Array('Der IBM PC: 4.77 MHz, 16 KB RAM. Dein Browser-Tab braucht heute mehr.','1981 kostete er 1565 Dollar. Inflation-bereinigt ca. 5000 Dollar. Fuer 16 KB RAM!','IBM dachte PCs waeren ein Nischenprodukt. Klassischer Management-Move.'); hf['Apple II'] = new Array('Der Apple II: Erster Computer mit Farbgrafik fuer zuhause. Revolution!','Wozniak hat den Apple II quasi alleine designed. Jobs hat ihn verkauft.','VisiCalc auf dem Apple II war die erste Killer-App. Excel-Urahn!'); hf['Steve Jobs bis 1985'] = new Array('Von Apple gefeuert. Von der eigenen Firma. Das muss man erstmal schaffen.','Jobs Reality Distortion Field: Er konnte dich ueberzeugen dass schwarz weiss ist.','Nach Apple gruendete er NeXT. Spoiler: Er kommt zurueck.'); hf['Diskette'] = new Array('Speichern-Icon bis heute! Kinder fragen: Was ist dieses 3D-gedruckte Save-Symbol?','1.44 MB. Da passt nicht mal ein Handyfoto drauf.','Das befriedigende Klick-Geraeusch beim Einschieben. ASMR der 90er.'); hf['Game Boy'] = new Array('Tetris auf dem Game Boy: Produktivitaetskiller seit 1989.','Der Game Boy ueberlebte einen Bombenangriff im Golfkrieg. Nokia-Level Haerte.','118 Millionen Stueck verkauft. Und alle spielten Tetris.'); hf['NeXTstation'] = new Array('Tim Berners-Lee erfand das Web auf einem NeXT. Danke, Steve!','Der NeXT-Wuerfel kostete 6500 Dollar. Design hat seinen Preis.','NeXTSTEP wurde zu macOS. Die beste Rache ist Erfolg.'); hf['CD-ROM'] = new Array('700 MB! Das war mal unvorstellbar viel Speicher.','Bitte nicht die glaenzende Seite anfassen. BITTE!','AOL-CDs als Untersetzer. Recycling der 90er.'); hf['Netscape Navigator'] = new Array('Netscape: Der Browser der das Internet populaer machte. RIP.','Der Browserkrieg hat begonnen! Netscape vs. Microsoft, Runde 1.','Aus Netscape wurde Mozilla Firefox. Der Phoenix aus der Asche!'); hf['Internet Explorer'] = new Array('Internet Explorer: Nur genutzt um einen anderen Browser runterzuladen.','IE6 hat eine ganze Generation von Webentwicklern traumatisiert.','Ruhe in Frieden, IE. Du warst... ein Browser. Irgendwie.'); hf['Bill Gates'] = new Array('640 KB sollten fuer jeden reichen. Legendaeres Fehlzitat!','Von Harvard abgebrochen. Eltern hassen diesen Trick.','Ctrl+Alt+Delete war ein Fehler, sagt er selbst. Wenigstens ehrlich.'); hf['DVD und Blu-ray'] = new Array('DVD: Rewind war gestern! Aber Regionalcodes waren die neue Nerverei.','Blu-ray vs HD-DVD: Der letzte grosse Formatkrieg.','Wer hat noch eine DVD-Sammlung im Regal? Sei ehrlich.'); hf['Geschichte von Linux'] = new Array('Linus Torvalds: "Ich mache ein freies Betriebssystem. Wird wohl nichts Grosses."','Linux laeuft auf Supercomputern, Handys, Kuehlschraenken und dem Mars-Rover!','BTW, I use Arch. Der Veganer-Spruch der IT.'); hf['List of Linux distributions'] = new Array('Es gibt ueber 600 Linux-Distros. Fuer jedes Problem eine eigene Distribution.','Ubuntu, Debian, Arch, Fedora, Mint... Die Qual der Wahl.','Jeder Linux-User hat schon 3x die Distro gewechselt. Mindestens.'); hf['Handheld'] = new Array('Von Handhelds zu Smartphones. Die Evolution der Ablenkung.','Palm Pilot! Wer erinnert sich an Graffiti-Schrifterkennung?','Handhelds: Als Taschencomputer noch eine eigene Kategorie waren.'); hf['Personal Digital Assistant'] = new Array('PDA: Personal Digital Assistant. Heute sagt man einfach Handy.','Mit dem Stylus auf dem PDA tippen. Das war Premium-UX!','Newton MessagePad: Apples erster Flop. Oder seiner Zeit voraus?'); hf['Google'] = new Array('Googles erster Server war in Lego-Steinen eingebaut. Kein Witz!','Googles erstes Buero: Eine Garage. Schon wieder eine Garage.','"Don\'t be evil" hiess es mal. Heute heisst es... naja.'); hf['Notebook'] = new Array('Vom 10-Kilo-Laptop zum Ultrabook. Unsere Rucksaecke danken es.','Erster Laptop: Osborne 1, 1981. 11 Kilo. Armtraining inklusive.','Laptop im Bett: Modernes Lagerfeuer fuer digitale Nomaden.'); hf['USB-Stick'] = new Array('USB: Braucht immer 3 Versuche zum Einstecken. Immer.','USB-C: Endlich egal welche Seite! Nur 20 Jahre hat es gedauert.','Wer hat nicht mindestens 5 USB-Sticks in der Schublade liegen?'); hf['Youtube'] = new Array('Erstes Youtube-Video: "Me at the zoo". 19 Sekunden die alles aenderten.','Youtube frisst mehr Bandbreite als TV. Die Zukunft ist hier.','Katzenvideos: Der wahre Grund warum das Internet erfunden wurde.'); hf['Tim Berners-Lee'] = new Array('Hat das World Wide Web erfunden. Und nie Milliarden damit verdient. Respekt!','Erster Webserver lief auf einem NeXT-Wuerfel. Mit einem Zettel: "Nicht ausschalten!"','Ohne ihn waerst du jetzt nicht hier. Danke, Tim!'); hf['Containervirtualisierung'] = new Array('Docker: Funktioniert auf meinem Computer! Endlich auch auf deinem.','Container sind wie Schiffscontainer: Alles drin, ueberall einsetzbar.','kubectl get pods: Der Befehl der DevOps-Engineers nicht schlafen laesst.'); hf['Smartphone OS'] = new Array('Android vs iOS: Der ewige Glaubenskrieg. Schlimmer als Tabs vs Spaces.','Es gab mal Windows Phone. Moment der Stille bitte.','Dein Smartphone hat mehr Power als die Apollo-11-Rakete. Und du spielst Candy Crush.'); hf['SaaS'] = new Array('Software as a Service: Frueher kaufte man Software. Heute mietet man sie. Fuer immer.','SaaS: Wo jede App ein monatliches Abo ist. Dein Konto weint leise.','Die Cloud ist nur der Computer von jemand anderem. Romantisch, oder?'); hf['Cloud Computing'] = new Array('Die Cloud: Klingt fluffy, ist ein riesiges Rechenzentrum irgendwo in Irland.','Cloud Computing: Weil "anderer-Leute-Computer" nicht so cool klingt.','Frueher hatte man Server im Keller. Jetzt hat Amazon sie. Fortschritt?'); var factBubbles = new Array('Schon gewusst?', 'Fun Fact!', 'Wusstest du?', 'Ach ja...', 'Apropos!', 'Hey, check das!'); function pick(arr) { return arr[Math.floor(Math.random() * arr.length)]; } var factCooldown = false; var areas = document.querySelectorAll('area[title]'); var ai; for (ai = 0; ai < areas.length; ai++) { (function(area) { area.addEventListener('mouseenter', function() { if (factCooldown || busy) return; var title = area.getAttribute('title') || ''; var facts = headerFacts[title]; if (!facts) return; factCooldown = true; addMsg(title + ': ' + pick(facts), 'fact'); setGif('happy'); showBubble(pick(factBubbles), 3000); setTimeout(function() { setGif('idle'); }, 3000); setTimeout(function() { factCooldown = false; }, 5000); }); })(areas[ai]); } })();
  • template('firncore/AI/Framework/Suche')

     
    Use the language selection below for English Utilise le sélecteur de langue ci-dessous pour français Per l'italiano, utilizzare la selezione della lingua qui sotto Schön sprichst du deutsch :-)