.

Project management

We plan your precision landing

AGILE, FLEXIBLE, TRANSPARENT

THE GOAL IN MIND - YOU CAN RELY ON US

A carefully thought-out and executed plan forms the foundation for the successful implementation of a project. Communication, schedule and budget control, and the organization of all resources using the appropriate tools and methods enable all stakeholders to work together harmoniously and ensure that the project proceeds toward its goals. For us, the key to successful project planning lies in constant communication, flexible and transparent action, consistent follow-up, and an eye for the big picture.

the magic triangle as a "magic formula"

Whether agile or classic – one of the best-known tools for a successful project is the “magic triangle”.
Time, costs, scope. The challenge? Maintaining balance! If one thing tips over, the success of the project suffers. But what do you do if new requirements arise or the deadline is brought forward? Don’t panic – with the help of the magic triangle and Sustainable Risk Management, we show you all the adjustment options. Together, we keep control of the project goal.

time, costs, scope

WE think three-dimensionally

BALANCED, SAFE, PURPOSEFUL

.magisches-dreieck-app { background-color: #ffffff; /* Background color for the application */ padding: 20px; border-radius: 8px; display: flex; flex-direction: column; align-items: center; width: 100%; } .triangle-canvas { background-color: #ffffff; /* Background color for the triangle */ border: 1px solid #cccccc; width: 100%; max-width: 600px; /* Maximum width */ height: auto; aspect-ratio: 1 / 1; /* Square aspect ratio for responsive behavior */ } .slider-container { display: flex; justify-content: space-around; flex-wrap: wrap; width: 100%; max-width: 800px; margin: 10px auto; /* Reduced margin around the triangle */ background-color: #f9f9f9; padding: 20px; border-radius: 8px; } .slider-container div { margin: 10px; text-align: center; } .input-group { display: flex; flex-direction: column; align-items: center; width: 100%; max-width: 200px; } .input-field, .slider { background-color: #ffffff; border: 1px solid #cccccc; padding: 8px; border-radius: 4px; } .button-group { display: flex; gap: 10px; margin-top: 10px; } .button-group button { cursor: pointer; padding: 10px 20px; } .chatgpt-elements { display: none; /* Hidden by default, shown only if triangleAdvanced is set */ flex-direction: column; align-items: center; width: 100%; max-width: 800px; margin-bottom: 10px; } .chatgpt-input { width: 100%; padding: 10px; margin-bottom: 10px; } .debug-output { display: none; /* Hidden by default, shown only if triangleAdvanced is set */ margin-top: 10px; padding: 10px; background-color: #f9f9f9; border: 1px solid #ccc; border-radius: 4px; width: 100%; max-width: 800px; }
API Response:
document.addEventListener("DOMContentLoaded", function() { // Function to get query parameters from URL function getQueryParam(param) { const urlParams = new URLSearchParams(window.location.search); return urlParams.get(param); } // Check URL parameter "triangleAdvanced" to set advanced mode, default to hidden if not set const advancedMode = parseInt(getQueryParam('triangleAdvanced'), 10) || 0; document.querySelectorAll(".magisches-dreieck-app").forEach(function(instance) { const canvas = instance.querySelector('.triangle-canvas'); const ctx = canvas.getContext('2d'); const scopeInput = instance.querySelector('.scope'); const scopeSlider = instance.querySelector('.scope-slider'); const costInput = instance.querySelector('.cost'); const costSlider = instance.querySelector('.cost-slider'); const timeInput = instance.querySelector('.time'); const timeSlider = instance.querySelector('.time-slider'); const chatGPTElements = instance.querySelector('.chatgpt-elements'); const chatGPTInput = instance.querySelector('.chatgpt-input'); const chatGPTButton = instance.querySelector('.chatgpt-button'); const shareLink = instance.querySelector('.share-link'); const resetButton = instance.querySelector('.reset-button'); const debugOutput = instance.querySelector('.debug-output'); const debugContent = instance.querySelector('.debug-content'); // Show ChatGPT elements if triangleAdvanced is 1 or 2 if (advancedMode >= 1) { chatGPTElements.style.display = 'flex'; } // Show Debug output if triangleAdvanced is 2 if (advancedMode === 2) { debugOutput.style.display = 'block'; } function resizeCanvas() { const maxCanvasSize = 600; // Maximum canvas size reduced to 600px canvas.width = Math.min(instance.clientWidth, maxCanvasSize); canvas.height = canvas.width; updateTriangle(); } window.addEventListener('resize', resizeCanvas); resizeCanvas(); function drawTriangle(scope, cost, time) { const centerX = canvas.width / 2; const centerY = canvas.height / 2; const size = canvas.width / 3.5; const points = [ { x: centerX, y: centerY - size * (scope / 100) }, { x: centerX - size * Math.sin(Math.PI / 3) * (cost / 100), y: centerY + size * Math.cos(Math.PI / 3) * (cost / 100) }, { x: centerX + size * Math.sin(Math.PI / 3) * (time / 100), y: centerY + size * Math.cos(Math.PI / 3) * (time / 100) } ]; ctx.clearRect(0, 0, canvas.width, canvas.height); const imbalanceScope = Math.abs(scope - cost); const imbalanceCost = Math.abs(cost - time); const imbalanceTime = Math.abs(time - scope); // Set color based on balance let color = imbalanceScope > 5 || imbalanceCost > 5 || imbalanceTime > 5 ? '#E67F64' : '#61CE70'; // Red for unbalanced, Green for balanced ctx.beginPath(); ctx.moveTo(points[0].x, points[0].y); ctx.lineTo(points[1].x, points[1].y); ctx.lineTo(points[2].x, points[2].y); ctx.closePath(); ctx.fillStyle = color; ctx.fill(); ctx.stroke(); ctx.font = '16px Arial'; ctx.fillStyle = '#000'; ctx.fillText(`A: ${scope}%`, points[0].x - 20, points[0].y - 10); ctx.fillText(`B: ${cost}%`, points[1].x - 40, points[1].y + 20); ctx.fillText(`C: ${time}%`, points[2].x + 10, points[2].y + 20); } function updateTriangle() { const scope = parseInt(scopeInput.value); const cost = parseInt(costInput.value); const time = parseInt(timeInput.value); drawTriangle(scope, cost, time); } function resetValues() { scopeInput.value = 100; scopeSlider.value = 100; costInput.value = 100; costSlider.value = 100; timeInput.value = 100; timeSlider.value = 100; updateTriangle(); } // Sync inputs and sliders scopeInput.addEventListener('input', () => { scopeSlider.value = scopeInput.value; updateTriangle(); }); scopeSlider.addEventListener('input', () => { scopeInput.value = scopeSlider.value; updateTriangle(); }); costInput.addEventListener('input', () => { costSlider.value = costInput.value; updateTriangle(); }); costSlider.addEventListener('input', () => { costInput.value = costSlider.value; updateTriangle(); }); timeInput.addEventListener('input', () => { timeSlider.value = timeInput.value; updateTriangle(); }); timeSlider.addEventListener('input', () => { timeInput.value = timeSlider.value; updateTriangle(); }); // Create shareable link shareLink.addEventListener('click', () => { const scope = scopeInput.value; const cost = costInput.value; const time = timeInput.value; const url = `${window.location.origin}?scope=${scope}&cost=${cost}&time=${time}`; prompt('Share this link:', url); }); // Run ChatGPT analysis if enabled by triangleAdvanced parameter if (advancedMode >= 1 && chatGPTButton && chatGPTInput) { chatGPTButton.addEventListener('click', function() { const scenario = chatGPTInput.value; fetch(magischesDreieckAjax.ajaxurl, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' }, body: `action=chatgpt_analyse&input_text=${encodeURIComponent(scenario)}` }) .then(response => response.json()) .then(data => { if (advancedMode === 2) { debugContent.textContent = JSON.stringify(data, null, 2); // Display API response in debug mode } const responseText = data.data || ''; if (responseText.includes('Kosten erhöhen sich um')) { const costIncrease = responseText.match(/Kosten.*um (\d+)%/); if (costIncrease) { costInput.value = Math.min(150, parseInt(costInput.value) + parseInt(costIncrease[1])); costSlider.value = costInput.value; updateTriangle(); } } }) .catch(error => console.error('Error:', error)); }); } // Reset button event listener resetButton.addEventListener('click', resetValues); updateTriangle(); }); });

What does it mean when the scope increases?
- we need new features
- we have requests for changes after the fact
New requirements take more time and also increase the cost of implementation.

What does it mean when the budget is cut?
- We've had our budget cut
- We can't pay
A smaller budget leads to service cuts (e.g., removing features) and also reduces the amount of time that can be spent on the project.

What does it mean if I have less time?
- the deadline is moved up
Less time means either a reduced scope of work or higher costs (e.g., due to the use of more staff or overtime).

Quality assurance

WE PLAY IT SAFE

THOROUGH, CONSISTENT, COMPREHENSIVE

QUALITY IS VERY IMPORTANT TO US

Implementing online projects requires consistent quality management. This begins in the design phase and is essential throughout the development process. Continuous optimization is an integral part of agile web development, and each milestone includes testing functionality and usability in the interplay between design and technology. By continuously reviewing and evaluating the quality of our work and its compliance with requirements, we can identify defects early on and implement optimization measures. This results in sustainable development that delivers significant added value for the user.

Web development

From interface connections in TYPO3 to database applications with Python and Django to special tools for marketing and calculation – we offer all-round technical support.