Software Entwicklung

Auf Ihre Bedürfnisse zugeschnitten
Weil Individualität uns allen innewohnt

Epcom Software-Entwickler

Kontaktieren Sie uns gerne!
Anfrage office@epcom.cc +43 (3612) 21269

Standardsoftware versus Individual-Programmierung

Standardsoftware gibt es für fast alle Anwendungsfälle und oft auch für jedes Budget. Allerdings hat diese auch oft ein oder mehrere entscheidende Probleme. Da die Software nicht für Ihre spezielle Anforderung entwickelt wurde ist die Wahrscheinlichkeit sehr groß, dass sie auch Funktionen enthält die sie niemals verwenden und benötigen werden.

Vielleicht fragen Sie sich: „Warum kann das ein Problem sein?“ Weil durch jede zur verfügung gestellte Funktion zwangsweise auch die Benutzeroberfläche umfangreicher werden muss. Und dies kann zu längeren Einarbeits- und Einschulungszeiten führen. Im Extremfall könnte dies sogar zu einer „Ablehnung“ der Software durch die Benutzer führen. Vielleicht haben Sie den Satz „Das ist zu kompliziert“ im Zusammenhang mit der Bedienung von Software auch selbst schon gesagt oder von Mitarbeitern bzw. Kollegen gehört. Bei Software, die speziell auf Ihre Anforderungen maßgeschneidert ist, wird auch die Benutzeroberfläche nur die Funktionen anbieten, die sie auch benötigen.

Ein weiteres Problem kann die Flexibilität sein. Was, wenn die Software zwar die meisten ihrer Anforderungen abdeckt, aber eben nicht alle? Hier gibt es oft nur die Möglichkeiten

  • Ihre eigene Arbeitsweise anzupassen um mit der Software „klarzukommen“
  • Eine weitere Software anzuschaffen um genau diese Anforderung abzudecken.
  • „Die Erfindung eines Workarounds“
Keine dieser Möglichkeiten ist ideal oder effizient. Genau hier schafft speziell für Sie entwickelte Software Abhilfe. Sie wird nach Ihren Anforderungen programmiert und kann jederzeit flexibel erweitert oder angepasst werden.

Warum das Rad neu erfinden?

Machen wir gar nicht :-) Natürlich verwenden wir bei der Entwicklung von Software ebenfalls bereits existierende Komponenten und Frameworks. Dies erhöht die Entwicklungsgeschwindigkeit, reduziert damit Entwicklungskosten und erhöht auch die Qualität der Software. Wir verwenden einfach diese Komponenten die schon gut für Ihre Anforderungen passen und erweitern sie entsprechend. Die Benutzerschnittstelle wird eigens entworfen um so effizientes und intuitives Arbeiten zu ermöglichen.

Sie behalten die Datenhoheit!

Zur Speicherung der Daten und für diverse Schnittstellen verwenden wir immer etablierte Standards und Systeme. Die Daten werden je nach Anforderung in einer (fast) beliebigen Datenbank oder einem offenen Dateiformat gespeichert. So können Sie auch sicher sein, aufgrund der erzeugten und verwalteten Daten in einem System „gefangen“ zu sein.

Open Source

Wir bekennen uns klar zur Verwendung von Open Source Software und setzen diese in allen Bereichen in denen es möglich und vernünftig ist seit über 20 Jahren ein. Profitieren Sie ebenfalls durch den Einsatz von Open Source Software indem Sie massiv Kosten für Lizenzgebühren sparen. Aber natürlich richtet sich die Verwendung der eingesetzten Software immer an Ihren Anforderungen!

Weiterentwicklung beziehungsweise Portierung „alter Anwendungen“

Sie haben eine Anwendung in Betrieb die speziell für Sie entwickelt wurde aber keine Anpassungsmöglichkeit der Software mehr? Gerne unterstützen wir Sie bei Analyse der Software und Daten um einen möglichen Migrationsweg zu erstellen oder auch eine Weiterentwicklung auszuführen, sofern dies durch die Lizenz und Verfügbarkeit der Quellcodes möglich ist.

Welche Art von Software dürfen wir Ihnen Anbieten?
Mehrfachnennung möglich ;-)

  • Desktop-Anwendung für Windows, macOS oder Linux
  • App für Android und / oder iOS
  • Web-Applikation für die Verwendung in einem beliebigen Browser
  • Serverseitiger Dienst

Für zwischendurch ...

Abwechslung gefällig? Ein kleines Browser-Game für zwischendurch. Zum Starten clicken Sie einfach auf "Ausprobieren!"

/**
 * @title Hit the Bricks
 * @version 1.0
 * @author epcom it-systeme GmbH 
 * @description
 * Ein in Javascript programmiertes Mini-Spiel für den Browser. Inspiriert durch das 
 * Mozilla Developer Network Tutorial "2D breakout game using pure JavaScript"
 * https://developer.mozilla.org/en-US/docs/Games/Tutorials/2D_Breakout_game_pure_JavaScript
 */

class HitTheBricks{
	constructor(containerID){
		this.container=document.getElementById(containerID);
		this.canvas=this.container.getElementsByTagName('canvas')[0];
		this.canvas.width=this.canvas.offsetWidth;
		this.canvas.height=this.canvas.offsetHeight;
		this.ctx=this.canvas.getContext('2d');
		this.data={};
		this.objects={};
		this.initData();
		if(!this.validateData()){ return; }
		this.addEvents();
		this.draw();
	}
	initData(){
		this.objects={
			'score':this.container.getElementsByClassName('score')[0],
			'lives':this.container.getElementsByClassName('lives')[0],
			'status':this.container.getElementsByClassName('status')[0],
			'range':this.container.getElementsByClassName('form-range')[0]
		};

		this.data.ballRadius = 10;
		this.data.x = this.getRandomInt(this.canvas.width - this.data.ballRadius*2);
		this.data.y = this.canvas.height-30;
		this.data.dx = this.speed();
		this.data.dy = -this.speed();
		this.data.paddleHeight = 10;
		this.data.paddleWidth = 75;
		this.data.paddleX = (this.canvas.width-this.data.paddleWidth)/2;
		this.data.rightPressed = false;
		this.data.leftPressed = false;
		this.data.brickRowCount = 5;
		this.data.brickColumnCount = 3;
		this.data.brickPadding = 10;
		this.data.brickHeight = 20;
		this.data.brickOffsetTop = 30;
		this.data.brickOffsetLeft = 30;
		this.data.brickWidth = (this.canvas.width - this.data.brickRowCount * this.data.brickPadding - this.data.brickOffsetLeft * 2) / this.data.brickRowCount;
		this.data.score = 0;
		this.data.lives = 3;
		
		this.data.bricks = [];
		for(var c=0; c < this.data.brickColumnCount; c++) {
		  this.data.bricks[c] = [];
		  for(var r=0; r < this.data.brickRowCount; r++) {
		    this.data.bricks[c][r] = { x: 0, y: 0, status: 1 };
		  }
		}		
		this.status('');

	}
	validateData(){
		if(this.container == undefined){
			console.error('container ist nicht vorhanden');
			return false;
		}
		if(this.canvas == undefined){
			console.error('canvas ist nicht vorhanden');
			return false;
		}
		if(this.objects.score == undefined){
			console.error('score container ist nicht vorhanden');
			return false;
		}
		if(this.objects.lives == undefined){
			console.error('lives container ist nicht vorhanden');
			return false;
		}
		if(this.objects.status == undefined){
			console.error('status container ist nicht vorhanden');
			return false;
		}
		if(this.objects.range == undefined){
			console.error('range ist nicht vorhanden');
			return false;
		}
		return true;

	}
	addEvents(){
		document.addEventListener("keydown", this.keyDownHandler.bind(this), false);
		document.addEventListener("keyup", this.keyUpHandler.bind(this), false);
		document.addEventListener("mousemove", this.mouseMoveHandler.bind(this), false);
	}
	keyDownHandler(e) {
	    if(e.key == "Right" || e.key == "ArrowRight") {
	        this.data.rightPressed = true;
	    }else if(e.key == "Left" || e.key == "ArrowLeft") {
	        this.data.leftPressed = true;
	    }
	}
	
	keyUpHandler(e) {
	    if(e.key == "Right" || e.key == "ArrowRight") {
	        this.data.rightPressed = false;
	    }else if(e.key == "Left" || e.key == "ArrowLeft") {
	        this.data.leftPressed = false;
	    }
	}
	
	mouseMoveHandler(e) {
		var relativeX = e.clientX - this.canvas.offsetLeft;
		if(relativeX > 0 && relativeX < this.canvas.width) {
	  		this.data.paddleX = relativeX - this.data.paddleWidth/2;
		}
	}
	
	collisionDetection() {
		for(var c=0; c < this.data.brickColumnCount; c++) {
		    for(var r=0; r < this.data.brickRowCount; r++) {
		    	var b = this.data.bricks[c][r];
		    	if(b.status == 1) {
		        	if(this.data.x > b.x && this.data.x < b.x+this.data.brickWidth && this.data.y > b.y && this.data.y < b.y+this.data.brickHeight) {
		          		this.data.dy = -this.data.dy;
		          		b.status = 0;
		          		this.data.score++;
		          		if(this.data.score == this.data.brickRowCount*this.data.brickColumnCount) {
		            		this.status("YOU WIN, CONGRATS!");
		          		}
		        	}
		      	}
		    }
		}
	}
	
	drawBall() {
		this.ctx.beginPath();
		this.ctx.arc(this.data.x, this.data.y, this.data.ballRadius, 0, Math.PI*2);
		this.ctx.fillStyle = "#0095DD";
		this.ctx.fill();
		this.ctx.closePath();
	}
	drawPaddle() {
		this.ctx.beginPath();
		this.ctx.rect(this.data.paddleX, this.canvas.height-this.data.paddleHeight, this.data.paddleWidth, this.data.paddleHeight);
		this.ctx.fillStyle = "#0095DD";
		this.ctx.fill();
		this.ctx.closePath();
	}
	drawBricks() {
		for(var c=0; c < this.data.brickColumnCount; c++) {
    		for(var r=0; r < this.data.brickRowCount; r++) {
		    	if(this.data.bricks[c][r].status == 1) {
        			var brickX = (r*(this.data.brickWidth+this.data.brickPadding))+this.data.brickOffsetLeft;
        			var brickY = (c*(this.data.brickHeight+this.data.brickPadding))+this.data.brickOffsetTop;
        			this.data.bricks[c][r].x = brickX;
        			this.data.bricks[c][r].y = brickY;
        			this.ctx.beginPath();
        			this.ctx.rect(brickX, brickY, this.data.brickWidth, this.data.brickHeight);
        			this.ctx.fillStyle = "#0095DD";
        			this.ctx.fill();
        			this.ctx.closePath();
      			}
    		}
  		}
	}
	drawScore() {
		this.objects.score.innerHTML='Score: ' + this.data.score;
	}
	drawLives() {
		this.objects.lives.innerHTML='Lives: ' + this.data.lives;
	}
	status(msg){
		this.objects.status.innerHTML=msg;
	}
	
	getRandomInt(max) {
		return Math.floor(Math.random() * max);
	}
	
	speed(){
		return this.objects.range.value.toInt();
	}
	
	/**
	 * Die Geschwindigkeit kann beliebig während des Spieles geändert werden
	 */
	validateSpeed(){
		var actualSpeed=this.speed();
		if(this.data.dx < 0 && this.data.dx !== -actualSpeed){
			this.data.dx = -actualSpeed;
		}else if(this.data.dx > 0 && this.data.dx !== actualSpeed){
			this.data.dx = actualSpeed;
		}
		if(this.data.dy < 0 && this.data.dy !== -actualSpeed){
			this.data.dy = -actualSpeed;
		}else if(this.data.dy > 0 && this.data.dy !== actualSpeed){
			this.data.dy = actualSpeed;
		}
	}
	
	draw() {
		this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
		this.drawBricks();
		this.drawBall();
		this.drawPaddle();
		this.drawScore();
		this.drawLives();
		this.collisionDetection();
		if(this.data.score == this.data.brickRowCount*this.data.brickColumnCount) {
			return;
  		}
		this.validateSpeed();		
		if(this.data.x + this.data.dx > this.canvas.width-this.data.ballRadius || this.data.x + this.data.dx < this.data.ballRadius) {
    		this.data.dx = -this.data.dx;
  		}
  		if(this.data.y + this.data.dy < this.data.ballRadius) {
    		this.data.dy = -this.data.dy;
  		}else if(this.data.y + this.data.dy > this.canvas.height-this.data.ballRadius) {
    		if(this.data.x > this.data.paddleX && this.data.x < this.data.paddleX + this.data.paddleWidth) {
      			this.data.dy = -this.data.dy;
	    	}else{
	      		this.data.lives--;
	      		if(!this.data.lives) {
	        		this.status("GAME OVER");
					return;
	      		}else{
			        this.data.x = this.getRandomInt(this.canvas.width - this.data.ballRadius*2);
			        this.data.y = this.canvas.height-30;
			        this.data.dx = this.speed();
			        this.data.dy = -this.speed();
			        this.data.paddleX = (this.canvas.width-this.data.paddleWidth)/2;
				}
			}
		}
	
		if(this.data.rightPressed && this.data.paddleX < this.canvas.width-this.data.paddleWidth) {
	    	this.data.paddleX += 7;
	  	}else if(this.data.leftPressed && this.data.paddleX > 0) {
	    	this.data.paddleX -= 7;
		}
		this.data.x += this.data.dx;
		this.data.y += this.data.dy;
		requestAnimationFrame(this.draw.bind(this));
	}
}

Hit the bricks

Spiel bereit!
APIs und

Schnittstellen

Daten sollten im Idealfall nur an einer Stelle gewartet werden müssen. Allerdings werden sie meist in verschiedenen Systemen benötigt. Um also eine automatische Kommunikation zwischen diesen zu realisieren werden Schnittstellen verwendet. Dies wird in der heutigen Zeit auch immer wichtiger. Selbst in Politik und Medien hat das Thema „Digitalisierung“ vermehrt Einzug gefunden.

Tatsächlich ist die Verwendung bzw. Programmierung von Schnittstellen unterschiedlichster Systeme eine unserer Haupttätigkeiten der letzten Jahre und so konnten wir schon erfolgreich Schnittstellen zu Zahlungsdienstleistern wie Qenta oder SIX, zu SAP Systemen, Ski-Data oder auch spezielle Abrechnungsschnittstellen für die Autoindustrie entwickeln (VDA).

Kontaktieren Sie uns für ein individuelles Angebot
Anfrage office@epcom.cc +43 (3612) 21269

Auch das ist eine Schnitt-Stelle Auch eine Schnitt-Stelle...