Skip to content
Snippets Groups Projects
Select Git revision
  • 8a840bfa45926abedcaf9d7b9327c90749fef902
  • master default
  • dja
  • dja_fix_animations
  • dja_various_fixes
  • dja_differentiate_same_user_connections
  • dja_fix_bugs
  • dja_guest
  • dja_guests
  • dja_sign_out_without_race_conditions
  • dja_subgroups
  • dua_subgroups
  • dja_groups_2
  • dja_groups
  • dja_heroku_11_7_2024
  • dja_share_files
  • dja_execute_files_aux_2
  • dja_execute_files_aux
  • dja_execute_files
  • dja_files_page
  • dja-create-main-button
  • v2.0
  • v1.0
23 results

ghci.service.ts

Blame
  • ghci.service.ts 13.47 KiB
    import { Injectable,ViewChild,ElementRef } from '@angular/core';
    import { Observable, Subject } from 'rxjs/Rx';
    import { WebsocketService } from './websocket.service';
    import { AuthenticationService } from './authentication.service';
    import { GHCI_URL } from '../config';
    
    declare var $:any;
    declare var that :any ;
    const regex = /^color (errores|input|output|logs) (\d)$/g;
    
    import 'tippy.js/dist/tippy';
    
    @Injectable()
    export class GHCIService {
    	public messages: Subject<any> = new Subject<any>();
    	private connection = undefined;
    	private cons = undefined;
    	private modoAvanzado: boolean = false;     // indica si debe mostrarse todo lo que ocurre en el intérprete.
    	private clear:boolean = false;
    	private error :string ="";
    	private warnings: any = [];
    	private codemirrorRef :any = null;
    	private warningStepReaded :number = 0;
    	private waitingForError : boolean = false;
    	private waitingForWarning : boolean = false;
    	private waitingForWarning2 : boolean = false;
    	private warningText :string = "";
    	private lastError : number = -1;
    	private lastWarning :number = -1;
    
    	private console_error_class : string = "jqconsole-asd";
    
    	consoleBuffer = [];
    
    	constructor(private authService:AuthenticationService){
    		console.log("contructor ghci");
    		this.conectarWS(GHCI_URL, authService.getUser().cedula, authService.getToken());
    		setInterval( this.checkConnection.bind(this), 5000);	
    		setInterval( this.doPing.bind(this), 30000);	
    	}
    
    	setCodemirrorRef(instance){
    		this.codemirrorRef = instance;
    	}
    
    	clearWarnings(){
    		this.warnings = [];
    	}
    
    	getWarnings(){
    		return this.warnings;
    	}
    
    	loadFile(fileId, dependencias) {
    		this.waitingForWarning = true;
    		var message = {
    			'token': this.authService.getToken(),
    			'load': fileId,
    			'dependencias' :[]
    
    		};
    		for(var i in dependencias){
    			message.dependencias.push(dependencias[i]);
    		};
    		this.connection.send(JSON.stringify(message));
    	}
    	copyFile(fileId){
    		var message = {
    			'token': this.authService.getToken(),
    			'copy': fileId
    		};
    		this.connection.send(JSON.stringify(message));
    	}
    	reiniciarInterprete(){
    		var message = {
    			'token': this.authService.getToken(),
    			'restart': ''
    		};
    		console.log(message);
    		this.connection.send(JSON.stringify(message));
    	}
    
    	regex: string  = '/(<svg.*\s*.*<\/svg>)/g';
    	
    	consoleRef:any;
    
    	conectarWS(wsUrl, cedula, token){
    		if(cedula && token && (!this.connection || this.connection.readyState == WebSocket.CLOSED)){
    			this.connection = new WebSocket(wsUrl+"/"+cedula+"/"+token);
    
    			this.connection.onopen = function(){
    				console.log('Conexión con web socket exitosa');
    			}
    			this.connection.onclose = function(){
    				console.log('Conexión con web socket cerrada');
    			}
    			this.connection.onmessage = this.onMessage.bind(this);
    		}
    	}
    
    	desconectarWS(){
    		if(this.connection){
    			this.connection.close();
    		}
    	}
    
    	logConsole(text){
    		if(this.consoleRef){
    			this.consoleRef.Write(text, 'jqconsole-logs'); 
    		}else{
    			this.consoleBuffer.unshift({text: text, type:'jqconsole-logs'})
    			setTimeout(this.checkConsole.bind(this),100);
    		}
    	}
    
    	outputConsole(text){
    		if(this.consoleRef){
    			this.consoleRef.Write(text, 'jqconsole-output'); 
    		}else{
    			this.consoleBuffer.unshift({text: text, type:'jqconsole-output'})
    			setTimeout(this.checkConsole.bind(this),100);
    		}
    	}
    
    	errorConsole(text){
    		if(this.consoleRef){
    			this.consoleRef.Write(text, 'jqconsole-errors'); 
    		}else{
    			this.consoleBuffer.unshift({text: text, type:'jqconsole-errors'})
    			setTimeout(this.checkConsole.bind(this),100);
    		}
    	}
    hayError(text){
    		var line = -1;
    		if(this.waitingForError){
    			var line = this.lastError;
    			if(this.codemirrorRef!==null){
    		        var makeMarker = function() {
    	              var marker = document.createElement("div");
    	              marker.id = "error_" + line.toString();
    	              marker.style.width = "15px";
    	              marker.title = JSON.parse(text).resultado.split("OUT")[1].trim();
    	              marker.style.height = "15px";
    	              marker.style.marginLeft = "-5px";
    	              marker.style.cursor = "pointer";
    	              marker.style["background-image"] = "url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAHlBMVEW7AAC7AACxAAC7AAC7AAAAAAC4AAC5AAD///+7AAAUdclpAAAABnRSTlMXnORSiwCK0ZKSAAAATUlEQVR42mWPOQ7AQAgDuQLx/z8csYRmPRIFIwRGnosRrpamvkKi0FTIiMASR3hhKW+hAN6/tIWhu9PDWiTGNEkTtIOucA5Oyr9ckPgAWm0GPBog6v4AAAAASUVORK5CYII=')";
    	              marker.innerHTML = "<a href='@' title='cuidado , advertencia matefun'></a>";
    	              return marker;
    	            }
    	            this.codemirrorRef.setGutterMarker(line, "breakpoints", makeMarker());
    	           	this.waitingForError = false;
    	           	this.lastError = -1;
    			}
    		}else {
    			try{
    			var line = Number(JSON.parse(text).resultado.split("en línea")[1].split(",")[0].trim())-1;
    			this.waitingForError = true;	
    			this.lastError = line;
    			
    		}catch(err){
    		}
    		return false;
    
    		}
    
    	}
    	resetGutters(){
    		if(this.codemirrorRef!==null){
    			this.codemirrorRef.clearGutter("breakpoints");
    		}
    	}
    	hayWarnings(text){
    		
    		var line = -1;
    		var m = JSON.parse(text);
    		
    		if(this.warningStepReaded===1){
    			try{
    				var warningText2 = m.resultado.split("OUT")[1].trim();
    				this.warningStepReaded = 2;
    				this.warningText = this.warningText + '\n\n' +  warningText2;
    
    				var line = this.lastWarning;
    				var title = this.warningText;
    
    				var columna = title.split("columna:")[1].split("}")[0];
    				var warningTextToShow = title.split("}")[1];
    
    				var warningFinalText = "En columna " + columna + ": " + warningTextToShow;
    
    				if(this.codemirrorRef!==null){
    			        var makeMarker = function() {
    		              var marker = document.createElement("div");
    		              marker.style.width = "15px";
    		              marker.style.height = "15px";
    		              marker.style.marginLeft = "-5px";
    		              marker.style.cursor = "pointer";
    		              marker.innerHTML = "<a href='@' title='cuidado , advertencia matefun'></a>";
    		              marker.title = warningFinalText;
    		              marker.style["background-image"] = "url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAANlBMVEX/uwDvrwD/uwD/uwD/uwD/uwD/uwD/uwD/uwD6twD/uwAAAADurwD2tQD7uAD+ugAAAAD/uwDhmeTRAAAADHRSTlMJ8mN1EYcbmiixgACm7WbuAAAAVklEQVR42n3PUQqAIBBFUU1LLc3u/jdbOJoW1P08DA9Gba8+YWJ6gNJoNYIBzAA2chBth5kLmG9YUoG0NHAUwFXwO9LuBQL1giCQb8gC9Oro2vp5rncCIY8L8uEx5ZkAAAAASUVORK5CYII=')";
    		              marker.innerHTML = "";
    		              return marker;
    		            }
    		            this.codemirrorRef.setGutterMarker(line, "breakpoints", makeMarker());
    				}
    
    			}catch(err){
    
    			}
    		}
    
    		if(this.warningStepReaded===0){
    
    			try{
    
    				var line = m.resultado.split("OUTAdvertencia:")[1].trim().split("línea:")[1].split(" ")[1]-1;
    				this.lastWarning = line;
    				this.warnings.push(line);
    				var warningText = m.resultado.split("OUTAdvertencia:")[1].trim();
    				this.warningStepReaded = 1;
    				this.warningText = warningText;
    				debugger;
    				if(this.waitingForWarning){
    
    					this.outputConsole('El programa contiene advertencias\n');
    					this.waitingForWarning = false;	
    				}
    				
    
    			} catch(err){
    
    			}
    
    		}
    
    		
    	}
    
    	onMessage(e){
    		if(this.modoAvanzado){
    			this.logConsole('Respuesta: ' + e.data + '\n');
    		}
    		if(this.clear){
    			this.clearConsole();
    		}
    		var server_message = e.data;
    
    		if(this.hayError(server_message)){
    			this.error = "Error";
    		} else {
    			this.error = "";
    		}
    		
    		this.hayWarnings(server_message);
    
    		if(this.warningStepReaded==2){
    			this.warningStepReaded = 0;
    			return;
    		} else if(this.warningStepReaded==1){
    			return;
    		}
    
    		var json_server_message = JSON.parse(server_message);
    		if(json_server_message.tipo=='salida'){
    
    
    				var line = json_server_message.resultado.trim();
    				if(line.startsWith("OUT")){
    					this.outputConsole(line.substring(3) + '\n');     
    				}else if(line.startsWith("IN")){
    					var promptText = line.substring(3);
    					if(this.consoleRef===undefined){
    						this.renderConsole();
    					}
    					this.consoleRef.SetPromptLabel(promptText);
    					this.consoleRef.SetPromptText('');
    					this.startPrompt.bind(this);
    					this.startPrompt();
    				}
    				
    			
    
    		} else if (json_server_message.tipo=='error'){
    			if(this.modoAvanzado){
    				this.errorConsole(json_server_message.resultado  + '\n');	
    			}
    		} else if (json_server_message.tipo == 'prompt'){
    			// console.log(json_server_message.resultado);
    			// console.log(this.consoleRef);
    			// console.log(this.consoleRef.SetPromptLabel);
    			// this.consoleRef.SetPromptLabel.bind(this);
    			this.consoleRef.SetPromptLabel(json_server_message.resultado+'>');
    			this.consoleRef.SetPromptText('');
    			this.startPrompt.bind(this);
    			this.startPrompt();
    			// console.log(x);
    		}else if (json_server_message.tipo == 'canvas' || json_server_message.tipo == 'animacion' || json_server_message.tipo == 'graph'){
    			this.messages.next(json_server_message);
    		}
    
    	}
    
    	checkConsole(){
    		if(this.consoleRef){
    			while(this.consoleBuffer.length > 0){
    				var bufferedMessage = this.consoleBuffer.pop();
    				this.consoleRef.Write(bufferedMessage.text,bufferedMessage.type);
    			}
    		}else{
    			setTimeout(this.checkConsole.bind(this),500);
    		}
    	}
    
    	checkConnection(){
    		var usuario = this.authService.getUser();
    		var token = this.authService.getToken();
    		if(usuario && token && (!this.connection || this.connection.readyState == WebSocket.CLOSED)){
    			this.conectarWS(GHCI_URL, usuario.cedula, token);
    		}		
    	}
    
    	doPing(){
    		var token = this.authService.getToken();
    		if(this.connection && this.connection.readyState == WebSocket.OPEN && token){
    			var message = {
    				'token': token,
    				'ping': ''
    			};
    			this.connection.send(JSON.stringify(message));
    		}		
    	}
    
    	sendLine(line) {
    		if(line.trim()!==""){
    			var message = {
    				'token': this.authService.getToken(),
    				'comando': line
    			};
    			console.log(message);
    			if(this.connection && this.connection.readyState == WebSocket.OPEN){
    				this.connection.send(JSON.stringify(message));
    			}else{
    				this.errorConsole("Sin conexión al servidor...");
    			}
    		}
    	}
    
    	startPrompt() {
    		// Start the prompt with history enabled.
    		this.jqconsole.Prompt(true, this.callback.bind(this));
    	};
    
    	focusConsole(){
    		this.jqconsole.Focus();
    	};
    
    	clearConsole(){
    		this.consoleRef.Reset();
    		this.startPrompt.bind(this);
    		this.startPrompt();
    		this.clear = false;
    	};
    
    	callback(input){
    		// Output input with the class jqconsole-output. 
    		var ejecutar: boolean;
    		ejecutar = this.procesarInput(input);
    		if(ejecutar) {
    			if(this.modoAvanzado){
    				this.logConsole("Ejecutar: " + input + '\n');
    			}
    			this.sendLine.bind(this);
    			this.sendLine(input);
    		}
    		this.startPrompt.bind(this);
    		this.startPrompt();
    	}
    
    	procesarInput(input){
    		var _input: string;
    		var send: boolean = false;
    		_input = input.trim().toLocaleLowerCase();
    		if(_input==="limpiar"){
    			this.clearConsole();
    		} else if(_input==="modo avanzado") {
    			this.modoAvanzado= true;
    			this.logConsole("Modo avanzado activado\n");
    		} else if(_input==="modo normal"){
    			this.modoAvanzado= false;
    			this.logConsole("Modo avanzado desactivado\n");
    		} else if(_input==="listar colores"){
    			this.outputConsole("1 - Azul\n");
    			this.outputConsole("2 - Rojo\n");
    			this.outputConsole("3 - Verde\n");
    			this.outputConsole("4 - Verde oscuro\n");
    			this.outputConsole("5 - Blanco\n");
    			this.outputConsole("6 - Naranja\n");
    			this.outputConsole("7 - Gris\n");
    			this.outputConsole("8 - Gris oscuro\n");
    			this.outputConsole("9 - Marrón\n");
    		} else if(_input.match(regex)!==null) {
    			var _tipoTexto :string = _input.split(" ")[1];
    			var _color : string = input.split(" ")[2];
    			this.jqconsoleColor(_color,_tipoTexto);
    			if(this.modoAvanzado){
    				this.logConsole("Color " + _tipoTexto + " seleccionado\n");	
    			}
    		} else {
    			send = true;
    		}	
    		return send;
    	}
    
    	getCSSColorName(n){
    		if(n==="1"){
    			return "rgb(77, 77, 255)";
    		} else if(n==="2"){
    			return "rgb(255, 26, 26)";
    		} else if (n==="3"){
    			return "rgb(0, 179, 60)";
    		} else if(n==="4"){
    			return "rgb(0, 77, 0)";
    		} else if(n==="5"){
    			return "rgb(255, 255, 255)";
    		} else if(n==="6"){
    			return "rgb(255, 133, 51)";
    		} else if(n==="7"){
    			return "rgb(204, 204, 179)";
    		} else if(n==="8"){
    			return "rgb(102, 102, 102)";
    		} else if(n==="9"){
    			return "rgb(101, 27, 27)";
    		}
    	}
    
    	getJQConsoleClass(jqconsoletext){
    		if(jqconsoletext==="input"){
    			return '.jqconsole-prompt';
    		} else if(jqconsoletext==="error"){
    			return '.jqconsole-error';
    		} else if (jqconsoletext==="logs"){
    			return '.jqconsole-logs';
    		} else if(jqconsoletext==="output"){
    			return '.jqconsole-output';
    		}
    	}
    
    	jqconsoleColor(color, clase){
    		var cssColor:string = this.getCSSColorName(color);
    		var jqConsoleClass: string = this.getJQConsoleClass(clase);
    
    
    		var style = document.createElement('style');
    		style.type = 'text/css';
    		style.innerHTML = jqConsoleClass +' { color: ' + cssColor + '; }';
    		document.getElementsByTagName('head')[0].appendChild(style);
    
    		if(jqConsoleClass==='.jqconsole-prompt'){
    			var style2 = document.createElement('style');
    			style2.type = 'text/css';
    			style2.innerHTML = '.jqconsole-old-prompt { color: ' + cssColor + '; }';
    			document.getElementsByTagName('head')[0].appendChild(style2);
    		}
    
    	}
    
    	consola: any=undefined;
    	renderConsole(){
    		if(this.jqconsole){
    			$('#console').replaceWith(this.consola);
    		}else{
    			if ($("#console").jqconsole!=undefined){ // Check if element has been found
    				this.jqconsole = $('#console').jqconsole('');
    				this.consoleRef = this.jqconsole;
    				this.startPrompt.bind(this);
    				this.startPrompt();
    			} else {
    				this.rendered();
    			}
    			this.consola = $("#console");
    		}
    	}
    
    	jqconsole:any = undefined;
    	rendered(){
    		setTimeout(this.renderConsole.bind(this),1000);
    	}
    
    
    
    }