From 214c84417dab0d3e45257669d79127688f1c15c4 Mon Sep 17 00:00:00 2001 From: Balhau Date: Wed, 12 Feb 2014 00:07:27 +0000 Subject: [PATCH] Sudoku initial commit --- corelib.js | 2379 +++++++++++++++++++++++++++++++++++++++++++++ css.css | 57 ++ index.html | 62 ++ js.js | 2702 ++++++++++++++++++++++++++++++++++++++++++++++++++++ sudoku.js | 258 +++++ test.html | 12 + 6 files changed, 5470 insertions(+) create mode 100644 corelib.js create mode 100644 css.css create mode 100644 index.html create mode 100644 js.js create mode 100644 sudoku.js create mode 100644 test.html diff --git a/corelib.js b/corelib.js new file mode 100644 index 0000000..dcce2c1 --- /dev/null +++ b/corelib.js @@ -0,0 +1,2379 @@ +/** + * Extensões a objectos de javascript + * Rotinas de encriptação + * Funções matemáticas + * @author Vítor Hugo Fernandes (a.k.a Balhau) + * @copyright Este documento está licenciado sob os direitos do MIT license + */ + +/** + * Objecto que representa propriedades comuns aos algoritmos + */ +var ALG={}; +/** + * Número de iteracções feitas pelo algoritmo + */ +ALG.ITER=0; +/** + * Variável que representa a chave secreta gerada pelo algoritmo de Vigénere. Isto ocorre sempre + * que a chave não é especificada à entrada da função + */ +ALG.VIGSECRETKEY=""; + +/** + * Método que troca dois elementos num array + * @param {int} i Indice da posicao + * @param {int} j Indice da posicao + */ +Array.prototype.troca=function(i,j){ + if((i=0) && (j=0)){ + var aux=this[i]; + this[i]=this[j]; + this[j]=aux; + } +}; + +Array.prototype.classpos=function(el){ + var p; + for(var i=0;i 0) { + par = xu[0]; + if (par[0] != par[1]) + grupos[grupos.length] = par; + else + grupos[grupos.length] = [par[0]]; + xu.remove(0); + volta=true; + while (volta) { + volta=false; + for (var i = 0; i < xu.length; i++) { + dif = xu[i].less(grupos[grupos.length - 1]); + if (dif.length == 1) { + grupos[grupos.length-1]=grupos[grupos.length - 1].concat(dif); + xu.remove(i); + i--; + volta=true; + }else if(dif.length==0){ + xu.remove(i); + i--; + } + } + } + } + return grupos; +}; + +/** + * Método que devolve um array com os elementos de arrA x arrB (produto de conjuntos) + * @param {Array} arrA Array de elementos + * @param {Array} arrB Array de elementos + * @return {Array} Array de elementos (a,b) onde a em arrA e b em arrB + */ +Array.produto=function(arrA,arrB){ + var out=[]; + for(var i=0;i=0;i--){ + maximo=i; + for(var j=0;jthis[maximo]) + maximo=j; + } + this.troca(i, maximo); + } +} + +Array.prototype.ShellSort=function(){ + var n=this.length; + var passo=Math.round(n/2); + var j=null; + var val=null; + while(passo>0){ + for(var i=passo;i=passo && this[j-passo]>val){ + this[j]=this[j-passo]; + j-=passo; + } + this[j]=val; + } + passo=Math.round(passo/2.1); + } +} + +/** + * Método que efectua a operação and sobre dois arrays. Devolve um array com os elementos + * que coincidentes para cada posição + * @param {Array} arrA Array + * @param {Array} arrB Array + * @return {Array} Array com os elementos que coincidem + */ +Array.and=function(arrA,arrB){ + var min=Object.min(arrA,arrB); + var max=Object.max(arrA,arrB); + var out=[]; + for(var i=0;i= this.length) { + return this; + } + this[i]=undefined; + for(var j=i;jthis[j+1]) + this.troca(j,j+1); + ALG.ITER++; + } + } + return this; +}; +/** + * Método que cria um array com valores aleatórios + * @param {int} dim Dimensão do array + * @param {int} low Valor minimo + * @param {int} sup Valor máximo + * @param {bool} intarray Valor booleano indicando se o array é composto por valores inteiros ou valores decimais + * @return {int} Array aleatório com dim elementos compreendidos entre low e sup + */ +Array.random=function(dim,low,sup,intarray){ + var arr=[]; + if(typeof(low)=='undefined') + low=0; + if(typeof(sup)=='undefined') + sup=100; + if(typeof(intarray)=='undefined') + intarray=true; + for(var i=0;i this.length-1) return this; + return this.substr(0,index) + chr + this.substr(index+1); +} +/** + * Método que baralha a string de modo a que esta continue legível para o ser humano + * @param {String} String para conversão + */ +String.shuffleText=function(str){ + var arr=str.split(" "); + var tmp=""; + var posA=0; + var posB=0; + for(var i=0;i0) + { + expmax=getexp(aux); + aux-=Math.pow(2,expmax); + expaux=getexp(aux); + strout+="1"; + if(aux==0 && expmax>=1){ + expmax++; + } + while(--expmax>expaux){ + strout+="0"; + } + } +return strout; +} + +/** + * Método que devolve um array contendo o código binário da string + * @return {Array} arr Array contendo strings com a representação binária de cada um dos caractéres da string + */ +String.prototype.toByteArray=function(){ + var arr=[]; + for(var i=0;i=97 && pos<=122){ + posA=this.charCodeAt(i)-97; + str+=String.fromCharCode(65+posA); + } + else if(pos>=65 && pos<=122){ + str+=this[i]; + } + //se for o espaço + else if(pos==32){ + str+=" "; + } + } + return str; +} + +/** + * Método que verifica se o caracter com determinada posição na string é uma letra maiuscula + * do alfabeto + * @param {Int} ind Posição na string + * @return {Bool} val Verdadeiro se o caracter for uma letra maiuscula, falso caso contrário + */ +String.prototype.maiuscula=function(ind){ + if(this.charCodeAt(ind)>=65 && this.charCodeAt(ind)<=90) + return true; + return false; +} + +/** + * Método que verifica se o caracter com determinada posição na string é uma letra minuscula + * do alfabeto + * @param {Int} ind Posição na string + * @return {Bool} val Verdadeiro se o caracter for uma letra minuscula, falso caso contrário + */ +String.prototype.minuscula=function(ind){ + if(this.charCodeAt(ind)>=65 && this.charCodeAt(ind)<=90) + return true; + return false; +}; + +/** + * @constructor Construtor da class + */ +var MathL=function(){}; + +/** + * Expansão do número segundo o problema de Collatz Syracuse Ulam (CSU) + * @param Numero inteiro + * @return Array Sequência de inteiros até encontrar o valor 1 + */ +MathL.CSUExpansion=function(n){ + var a=n; + var out=[a]; + while(a!=1){ + a=(a%2==0)?a/2:a*3+1; + out[out.length]=a; + } + return out; +}; + +/** + * @constructor Construtor do objecto CMarkov que representa uma cadeia de Markov + * @param {Array} lstats Lista com os labels dos estados associados à cadeia de markov + * @param {Array} pobj Representa a matriz de probabilidades da cadeia de markov + * @param {Array} inip Representa o vector de probabilidades inicial para a cadeia de markov + */ +MathL.CMarkov=function(lstats,pobj,inip){ + if(lstats.length*lstats.length!=pobj.length || lstats.length!=inip.length){ + throw "As dimensões do número de estados não corresponde à dimensão da matriz de probabilidades ou à dimensão do vector de probabilidades iniciais"; + } + this.lbels=lstats; + this.mp=MathL.Matriz.ArrayToMatriz(lstats.length,lstats.length,pobj); + this.auxmit=MathL.Matriz.ArrayToMatriz(1,lstats.length,inip); + this.initm=MathL.Matriz.ArrayToMatriz(1,lstats.length,inip); +}; + +MathL.CMarkov.prototype.iterate=function(){ + this.auxmit=MathL.Matriz.multMatriz(this.auxmit,this.mp); +}; + +MathL.CMarkov.prototype.restart=function(){ + this.auxmit=this.initm; +}; + +MathL.CMarkov.prototype.printIteration=function(){ + var std="["; + for(var i=0;ierr){ + xa=xi; + xi=xi-(Math.pow(xi,exp)-val)/(exp*xi); + ALG.ITER++; + } + return xi; +}; + +/** + * Método de Simpson para cálculo de integrais + * @param {Function} f Função que se pretende integrar + * @param {Number} min Minimo do intervalo de integração + * @param {Number} max Maximo do intervalo de integração + * @param {Number} n Número de intervalos + * @return {Number} Integral de Simpson + */ +MathL.SimpsonInt=function(f,min,max,n){ + n=n*2; + var sint=f(min); + var passo=(max-min)/n; + var fact=0; + var xi; + for(var i=1;i<=n;i++){ + //determina o factor para cada iteracção + fact=(i==n)?1:(i%2==0)?2:4; + xi=min+passo*i; + sint+=fact*f(xi); + } + return sint*(passo/3); +} +/** + * Determinação do integral da função f a partir do método do trapézio + * @param {Function} f Função a integrar + * @param {Number} min Intervalo minimo de integração + * @param {Number} max Intervalo máximo de integração + * @param {Number} n Número de intervalos para integração + * @return {Number} Integral de f entre min e max + */ +MathL.TrapzInt=function(f,min,max,n){ + var passo=(max-min)/n; + var strap=f(min); + var fact; + var xi; + for(var i=1;i<=n;i++){ + fact=(i==n)?1:2; + xi=min+passo*i; + strap+=fact*f(xi); + } + return strap*(passo/2); +} +/** + * Determina o integral de um intervalo de valores e respectivas imagens a partir do + * algoritmo do trapézio + * @param {Array} arrx array de coordenadas + * @param {Array} arry array das imagens das coordenadas + */ +MathL.TrapzCInt=function(arrx,arry){ + if(arrx.length!=arry.length) + return Number.NaN; + var soma=0; + for(var i=1;i=this._matriz.length){ + return this; + } + this._matriz.remove(ind); + return this; +}; + +/** + * Método que remove uma coluna da matriz + * @param {Int} ind Índice da matriz que pretendemos remover + * @return {MathL.Matriz} mat O próprio objecto matriz, para chaining + */ +MathL.Matriz.prototype.rmColuna=function(ind){ + if(ind<0 || ind >=this._matriz[0].length){ + return this; + } + for(var i=0;ithis._matriz.length){ + return null; + } + var ncol=this._matriz[0].length; + for(var i=0;ithis._matriz[0].length){ + return this; + } + var nlin=this._matriz.length; + for(var i=0;i=0;i--){ + if(ms._matriz[i][i]!=0){ + ms.MLinha(i,1/ms._matriz[i][i]); + for(j=i-1;j>=0;j--){ + aux=ms._matriz[j][i]; + for(k=i;kMath.sqrt(i)) + break; + if((i%primos[j])==0) + primo=false; + } + if(primo) + primos[primos.length]=i; + } + return primos; +}; + +/** + * Determina a média dos valores contidos no array, aqui assume-se que o array + * é preenchido com valores numéricos + */ +Array.prototype.media=function(){ + var cmp=this.length; + var m=0; + for(var i=0;i Math.sqrt(i)) + break; + if ((i % primos[j]) == 0) + primo = false; + ALG.ITER++; + } + if (primo) + primos[primos.length] = i; + i++; + } + return primos; +}; + +/** + * Método que devolve o valor de combinações (n,k) + * @param {int} n Inteiro (n k) --> n + * @param {int} k Inteiro (n k) --> k + * @return {int} com Inteiro número de combinações + */ +MathL.comb=function(n,k){ + var res=1; + for(var i=1;i<=k;i++){ + res*=(n+1-i)/i; + } + return res; +}; + + + +var COOkie={}; + +COOkie.setCookie=function(cookieName,cookieValue,minutos) { + var today = new Date(); + var expire = new Date(); + if (minutos==null || minutos==0) minutos=1; + expire.setTime(today.getTime() + 60000*minutos); + document.cookie = cookieName+"="+escape(cookieValue) + + ";expires="+expire.toGMTString(); +}; + + +var Crypto=function(){ +}; +/** + * Função que implementa a criptografia de Ceaser + * @param {string} str string a criptografar + * @param {int} shift Número de deslocamentos + * @return {string} strC String criptografada + */ +Crypto.cesar=function(str,shift){ + var i; + var strO=""; + var chcod; + for(i=0;i "+freq+"%"; + } + return strO; +}; + +/** + * Método que encripta uma string a partir da chave de Vigénere. Este método encripta somente + * strings que contenham caracteres do alfabeto + * @param {String} str String a encriptar + * @param {String} chave Chave encriptadora + * @return {String} enc Chave encriptada a partir do algoritmo de vigénere + * + */ +Crypto.VEncripta=function(str,chave){ + if(typeof(chave)=='undefined'){ + chave=Crypto.vigenereRandomKey(); + ALG.VIGSECRETKEY=chave; + } + else{ + chave=chave.toMaiuscula(); + ALG.VIGSECRETKEY=chave; + } + //Se a string a codificar não for válida sai com valor nulo + if(!String.isAlphaChar(str)){ + return null; + } + var chcomp=chave.length; + var chcod=0; + var deslocamentochave=0; + var strOut=""; + var offset=0; + var k=0; + str=str.toMaiuscula(); + for(var i=0;iarrA[ii]){ + k=ii; + } + } + return k; + }; + + //Criar os nós para cada um dos valores + for(var i=0;i1){ + indA1=getIndMinFreqObj(arrA); + noAux1=arrA[indA1]; + arrA.remove(indA1); + indA2=getIndMinFreqObj(arrA); + noAux2=arrA[indA2]; + arrA.remove(indA2); + noRaiz=new noarvore(noAux1.key+noAux2.key,null); + noRaiz.esq=noAux1; + noRaiz.dir=noAux2; + arrA[arrA.length]=noRaiz; + } + return noRaiz; +}; + +/** + * Método que devolve os códigos dos caracteres a partir da árvore de códigos + * @param {noarvore} arvore Árvore contendo a codificação dos caracteres a partir do algoritmo de Huffman + * @param {Object} obj Objecto do tipo dicionário que irá conter os códigos de cada um dos caracteres presentes na + * arvore de Huffman + * @param {Object} str String que será sempre inicializada a vazio, necessária para recorrencia + */ +Compressao.getTreeCodes = function(arvore,obj,str){ + if (arvore != null) { + Compressao.getTreeCodes(arvore.esq,obj,str+"1"); + Compressao.getTreeCodes(arvore.dir,obj,str+"0"); + if (arvore.val != null) { + obj[arvore.val] = str; + } + } + return obj; +} + +/** + * Algoritmo de Huffman para compressão de dados + * @param {Object} Obj Objecto representando a árvore de huffman necessária para a compressão e descompressão dos dados + */ +Compressao.HuffmanEncoding=function(str){ + var arv=Compressao.HuffmanEncodingTree(str); + var objC=Compressao.getTreeCodes(arv,new Object(),""); + var strO=""; + var cod=""; + for(var i=0;i final, false-> nao final + */ +Automato.prototype.sfinal=function(esta,bool){ + var b; + if(typeof(bool)!='undefined') + b=bool; + else + b=true; + if(b){ + if(this.finais.has(esta)) + return; + this.finais[this.finais.length]=esta; + } + else{ + if(!this.finais.has(esta)) + return; + this.finais.remove(this.finais.pos(esta)); + } +}; + +/*** + * Atribui final ou nao inicial a um estado + * @param {Number} esta Estado + * @param {Boolean} bool true-> inicial, false-> nao inicial + */ +Automato.prototype.sinicial=function(esta,bool){ + var b; + if(typeof(bool)!='undefined') + b=bool; + else + b=true; + if(b){ + if(this.iniciais.has(esta)) + return; + this.iniciais[this.iniciais.length]=esta; + } + else{ + if(!this.iniciais.has(esta)) + return; + this.iniciais.remove(this.iniciais.pos(esta)); + } +}; + +/** + * Método que devolve uma string com a descrição do autómato + * @return {String} descrição com as transições do autómato + */ +Automato.prototype.toString=function(){ + var out="Alfabeto: "+this.alfabeto.toString()+"\n"; + out+="Estados: "+this.estados.toString()+"\n"; + out+="Iniciais: "+this.iniciais.toString()+"\n"; + out+="Finais: "+this.finais.toString()+"\n"; + out+="Transições: "+this.transicoes.toString()+"\n"; + return out; +}; + +var noarvore=function(key,val){ + this.esq=null; + this.dir=null; + this.key=key; + this.val=val; +} + + + +var Tree=function(){ + this.raiz=new noarvore(null,null); +}; + +/** + * Método que insere + * @param {Número} key Chave numérica + * @param {Object} val Objecto que representa o valor que se encontra nos nós da árvore + */ +Tree.prototype.insertElement=function(key,val){ + //caso a árvore esteja vazia insere imediatamente no lado esquerdo da árvore + var elaux=this.dir; + if(this.esq==null){ + this.esq=new noarvore(key,val); + } + else{ + //Enquanto não estivermos numa folha da árvore + while(elaux.dir!=null){ + //Se a chave à direita for maior que a chave inserida então percorremos a árvore pela sua folha esquerda + if(elaux.key>key){ + elaux=elaux.esq; + } + else{ + elaux=elaux.dir; + } + } + } +} + + +COOkie.getCookie=function(c_name) +{ +if (document.cookie.length>0) + { + c_start=document.cookie.indexOf(c_name + "="); + if (c_start!=-1) + { + c_start=c_start + c_name.length+1; + c_end=document.cookie.indexOf(";",c_start); + if (c_end==-1) c_end=document.cookie.length; + return unescape(document.cookie.substring(c_start,c_end)); + } + } +return ""; +}; + +/** + * Método que devolve uma string contendo as propriedades deste objecto + * @return {string} str String contendo informação sobre as propriedades do objecto + */ +Object.prototype.inspect=function(){ + var str=""; + var filho; + for(filho in this){ + if(typeof(this[filho])=='function') + str+="Função: "+filho+"\n"; + else + str+="Variável: "+filho+"-->"+this[filho]+"\n"; + } + return str; +}; + +/** + * Método privado que devolve uma string com a representação JSON do objecto + * @param {Object} obj Objecto que se pretende exportar para JSON + * @private + */ +Object._toJSONString=function(obj){ + var str=""; + var e; + console.log(typeof(obj)); + if(obj==null) + return "null"; + if(typeof(obj)=='number'){ + str+=obj; + return str; + } + else if(typeof(obj)=='string'){ + str+="'"+obj+"'"; + return str; + } + else if (typeof(obj) == 'object') { + if (typeof(obj.length) == "undefined") { + str += "{"; + var k = 0; + for (e in obj) { + if (typeof(obj[e]) != "function") { + if (k != 0) { + str += ","; + } + str +='"'+e+'":'+ Object._toJSONString(obj[e]); + k++; + } + } + str += "}"; + } + else { + str += "["; + for (var i = 0; i < obj.length; i++) { + if (typeof(obj[i]) != "function") { + if (i != 0) { + str += ","; + } + str += Object._toJSONString(obj[i]); + } + } + str += "]"; + } + } + + return str; +} + +/** + * Método que devolve uma string representando o objecto + * @return {String} str string contendo a representação JSON do objecto + */ +Object.prototype.toJSONString=function(){ + return Object._toJSONString(this); +} +/** + * Método que transforma um objecto do tipo dicionário num array binário + * @return {Array} arr Array binário contendo os valores do objecto dicionário + */ +Object.prototype.toDicArray=function(){ + var arr=[]; + var i=0; + for(e in this){ + arr[i]=[]; + arr[i][0]=e; + arr[i][1]=this[e]; + i++; + } + return arr; +}; + +/** + * Método que devolve uma string contendo o nome de todos os métodos existentes no objecto + * @return {string} strm String com a descrição dos métodos + */ +Object.prototype.getMetodos=function(){ + var str=""; + for(var filho in this){ + if(typeof(this[filho])=='function') + str+="Função: "+filho+"\n"; + } + return str; +}; + + +/** + * Método que devolve uma string contendo o nome e valor de todas as propriedades existentes + * no objecto + * @return {string} strp String com a descrição dos valores do objecto + */ +Object.prototype.getPropriedades=function(){ + var str=""; + for(var filho in this){ + if(typeof(this[filho])!='function') + str="Variavel: "+this[filho]; + } + return str; +}; + +Object.min=function(strA,strB){ + return strB.length>strA.length?strA:strB; +}; + +Object.max=function(strA,strB){ + return strA.length>=strB.length?strA:strB; +}; + +/** + * Devolve um array com os caracteres que constituem a string + * @return {Array} + */ +String.prototype.alphabet=function(){ + var out=[]; + var ext={}; + for(var i=0;i + + + + Sudoku + + + + + +
+
+
+ + + + +
+ + + diff --git a/js.js b/js.js new file mode 100644 index 0000000..740ac89 --- /dev/null +++ b/js.js @@ -0,0 +1,2702 @@ +/************************************************* + * BaLHau LIB + * Esta biblioteca foi desenvolvida por Vítor Hugo Fernandes, a.k.a BaLHau + * @author Balhau + */ +/** + * Método que devolve os elementos que contém uma determinada className + * @param cls {@link String} nome da class + * @return {@link Array} contendo os elementos de uma determinada class + */ +var getByClassName=function(cls){ + var el=document.getElementsByTagName('*'); + var out=[]; + for(var i=0;i=10?vmin:"0"+vmin; + var hora=vhor>=10?vhor:"0"+vhor; + var seg=(totseg%60)>=10?totseg%60:"0"+totseg%60; + var rt=""; + rt=(hora>0)?hora+":":""; + rt+=min+":"+seg; + return rt; +}; + +/** + * Método que devolve os valores representados numa string URL no formato GET + * @return {Object} Variaveis e seus respectivos valores + */ +String.prototype.getVarsFromUrl=function(){ + var aux=this.split("?"); + if(aux.length==0) + return {}; + var vars=aux[1].split("&"); + var out={}; + var par=""; + for(var i=0;i"; + document.body.appendChild(dcont); + var frm=$(id); + if(callbackobject){ + if(typeof(callbackobject.onComplete)=="function") + frm.onComplete=callbackobject.onComplete; + } + return id; +} + +BLauLib.AIM.form=function(formE,name){ + formE.setAttribute('target',name); +} + +BLauLib.AIM.submit=function(formE,callbackobject){ + BLauLib.AIM.form(formE, BLauLib.AIM.criaFrame(callbackobject)); + if(callbackobject){ + if(typeof(callbackobject.onStart)=="function") + return callbackobject.onStart(); + return true; + }else{ + return true; + } +} + +BLauLib.AIM.onLoaded=function(id){ + var el=$(id); + if(el.contentDocument){ + var doc=el.contentDocument; + } + else if(el.contentWindow){ + var doc=el.contentWindow.document; + } + else{ + var doc=window.frames[id].document; + } + + if(doc.location.href=="about:blank"){ + return; + } + if(typeof(el.onComplete)=='function'){ + el.onComplete(doc.body.innerHTML); + } +} +/** + * Método que efectua uma ligação assíncrona ao servidor + * @param {String} metodo Tipo de ligação POST/GET + * @param {String} urlAja Endereço da ligação + */ +BLauLib.Ajax.prototype.open=function(metodo,urlAja) +{ + //Copia das estruturas devido à  não visibilidade do operador "this" dentro do método "onreadystatechange" + + var onLoading=this.onLoading; + var onLoaded=this.onLoaded; + var onError=this.onError; + var ajax=this.xmlHttp; + var estado=this.xmlHttp.readyState; + var pthis=this; + var ready=function() + { + if(ajax.readyState==4) + { + if(typeof(onLoaded)=="function"){ + pthis.text=ajax.responseText; + pthis.html=ajax.responseXML; + onLoaded(); + } + } + if(ajax.readyState==2){ + if(typeof(onLoading)=="function"){ + onLoading(); + } + } + if(ajax.readyState==3){ + if(typeof(onError)=="function"){ + onError(); + } + } + }; + this.xmlHttp.onreadystatechange=ready; + this.xmlHttp.open(metodo,urlAja); + if(metodo=="POST"|| metodo=="post"){ + this.xmlHttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded;charset=UTF-8"); + } +}; +/** + * Método que envia uma mensagem para o servidor + * @param {String} conteúdo para o servidor + */ +BLauLib.Ajax.prototype.send=function(conteudo) +{ + this.xmlHttp.send(conteudo); +}; + +/** + * Devolve o dia da semana para um determinado mes de um determinado ano + * @param mes Mes + * @param ano Ano + * @return Índice do dia da semana + */ +Date.getFirstDayMonth=function(mes,ano){ + var d=new Date(ano,mes); + d.setDate(1); + return d.getDay(); +}; + +/** + * Método que devolve o número de dias de um mês + * @param mes Mes que se pretende saber o numero de dias + * @param ano Ano que se pretende saber o numero de dias + * @return Dias 28-31 dias do mes + */ +Date.getNumDaysMonth=function(mes,ano){ + return 32-new Date(ano,mes,32).getDate(); +} + +BLauLib.UI={}; +/** + * Painel que apresenta os dados no ecran sob a forma paginada + * @param {String} Id do elemento contentor + * @param {Array} Array com os cabeçalhos + * @param {Array} Array com os dados tabelados + * @param {Number} Number com o número de elementos por página + */ +BLauLib.UI.NPaged=function(iddiv,aheaders,adata,nppag,css){ + this.headers=aheaders; + this.data=adata; + this.nppage=nppag; + this.divp=$(iddiv); + this.tblcon=null; + this.idpr=this.divp.id; + this.pagenumber=1; + if(typeof(css)=="undefined") + this.css="npage"; + else + this.css=css; + this.build(); +}; + +/** + * Objecto que representa um objecto calendário + */ +BLauLib.UI.DatePicker=function(id){ + this.id=id; + this.dinput=$$('input'); + this.dbox=BLauLib.UI.DatePicker.buildDataBox(dinput); + + this.dinput.id="data_"+this.id; + this.dbox.id="dataBox_"+this.id; +}; + +/** + * Método que efectua a construção do div de dados + */ +BLauLib.UI.DatePicker.buildDateBox=function(inputobj){ + var i_obj=$(inputobj); + var divbox=$$('div'); + +}; + + +/** + * Método que efectua a criação da tabela contentora das datas + * @param {obj} Elemento associado ao calendário + */ +BLauLib.UI.DatePicker._createTableDate=function(obj,id){ + var DS=7; + var id=id; + var tbody=$$('table'); //Criação do elemento table que servirá de contentor do calendário + var linhas=$$('tr',DS+1); //Numero de linhas da tabela + var cells=$$('td',46); //Numero de células 46, inclui dias do mes, semana, cabeçalho e rodapé + tbody.className="dpTB"; + tbody.id="dpTB_"+id; + //Configuração do cabeçalho + var btleft=$$('input'); + var btright=$$('input'); + var title=$$('div'); + title.id="dpHeader_"+id; + + btleft.type="button"; + btright.type="button"; + btright.value=">"; + btleft.value="<"; + + cells[1].colSpan=DS-2; + cells[1].className="dpTTD"; + + cells[0].add(btleft); + cells[1].add(title); + cells[2].add(btleft); + linhas[0].add(cells[0],cells[1],cells[2]); + //Configuração dos dias da semana + var dsem=cells.select(3,2+DS); + var dsm=["Do","Se","Te","Qu","Qu","Se","Sa"]; + for(var i=0;i=this.data.length) //caso o valor de n esteja fora do intervalo de dados + return; + if(n>=posmin && n1){ + for(var i=0;i"+this+""; +}; + +/** + * Efectua a remoção de caracteres vazios à direita da string + * @return {String} String sem espaços brancos à direita + */ +String.prototype.rtrim=function(){ + var i=this.length-1; + while(i>=0 && this.charAt(i)==' '){ + i--; + } + return this.substring(0,i+1); +} + +/** + * Verifica se uma string é vazia + * @return {Boolean} Valor verdadeiro caso a string seja vazia, falso caso contrário + */ +String.prototype.empty=function(){ + return (this.trim()==''); +} + +String.prototype.trim=function(){ + return this.ltrim().rtrim(); +} + +/** + * Método que devolve um array de elementos que devolvem valor true quando passados para a função callback + * @param {Function} callback Função callback que avalia o elemento + * @return {Array} Array com os elementos que retornam valor true na avaliação pela função callback + */ +Array.prototype.where=function(callback){ + var out=[]; + for(var i=0;i=0;i--){ + stou+=this.charAt(i); + } + return stou; +}; + +/** + * Método que transforma uma String num array com a sua codificação UNicode + * @param {String} car Caracter separador + * @return {String} Codificação Unicode separada através do caracter car + */ +String.prototype.toUnicodeArray=function(car){ + var sb=new StringBuilder(''); + for(var i=0;i b.l ? a.l <= b.r : b.l <= a.r)) + && (a.t == b.t || (a.t > b.t ? a.t <= b.b : b.t <= a.b)) && (r[r.length] = l[i])); + return j ? !!r.length : r; +}; + + + +/** + * Método que efectua a duplicação em profundidade de um determinado Elemento HTML. Quando invocado este método + * cria um elemento idêntico ao elemento instanciado assim como os Elementos filhos num processo recursivo. + * Os identificadores são diferentes de cópia para cópia para evitar colisões em posteriores invocações de objectos + * a partir de javascript partindo do seu ID; + * @param {Booleano} Variável boleana indicando o tipo de clonagem. Caso este parãmetro não seja inserido + * ou seja verdadeiro a cópia é feita em profundidade, caso o valor seja falso temos unicament a cópia do elemento + * sem efectuar profundidade. + * @return {HElement} Devolve um objecto do tipo HElement que consiste no presente objecto duplicado + */ +HElement.prototype.clone = function(prof){ + if(typeof(this.clones)=='undefined' || this.clones==null) + this.clones=0; + if(typeof(prof)=='undefined'){ + prof=true; + } + var cln = document.createElement(this.tagName); + for (i = 0; i < this.attributes.length; i++) { + if (this.attributes[i].name == "id") { + cln.setAttribute(this.attributes[i].name, this.attributes[i].nodeValue + "_clone_" + this.clones); + } + else { + //cln.attributes[i]=document.createAttribute(el.attributes[i].name); + cln.setAttribute(this.attributes[i].nodeName,this.attributes[i].nodeValue); + if(typeof(this.innerText)!='undefined') + cln.innerText=this.innerText; + } + } + if (prof) { + var filhos = this.childNodes; + for (i = 0; i < filhos.length; i++) { + //Elementos do tipo TEXTO + if (filhos[i].nodeType == 3) { + cln.appendChild(filhos[i]); + } + else { + elF = HElement.get(filhos[i]); + cln.appendChild(HElement.get(elF.clone(prof))); + } + } + } + else + cln.innerHTML = this.innerHTML; + return cln; +}; + +/** + * Método que coloca um elemento no centro da janela + */ +HElement.prototype.putAtCenter=function(){ + var wd=BLauLib.Window.width(); + var he=BLauLib.Window.height(); + var sx=BLauLib.Window.scrX(); + var sy=BLauLib.Window.scrY(); + var x=wd/2+sx-this.offsetWidth/2; + var y=he/2+sy-this.offsetHeight/2; + this.style.position="absolute"; + this.style.left=isNaN(x)?(wd/2+"px"):(x+"px"); + this.style.top=isNaN(y)?(he/2+"px"):(y+"px"); +} + +/** + * Método que aplica uma função de callback aos elementos em profundidade + * @param {Function} callback + */ +HElement.prototype.traverse=function(callback){ + callback(this); + for(var i=0;iminx) + this.style.width=xdiff+"px"; + if(ydiff>miny) + this.style.height=ydiff+"px"; +} + +/*** + * Objecto que representa uma contentor janela + * @classDescription Este objecto representa um contentor janela. O propósito consiste em simular um ambiente desktop + * a partir de construção de um conjunto de elementos e alguns métodos associados + * @param {String} nel Nome do elemento + * @param {String} titulo Titulo da janela + * @param {String} bdcontent Conteudo do contentor + * @param {Number} dimx Dimensão em X + * @param {Number} dimy Dimensão em Y + */ +BLauLib.Window=function(nel,titulo,bdcontent,dimx,dimy){ + var nel=nel; + this.dx=null; + this.drag=false; + this.dy=null; + if(dimx && dimy){ + dx=Math.max(dimx,BLauLib.Window.MIN_WIDTH); + dy=Math.max(dimy,BLauLib.Window.MIN_HEIGHT); + } + else{ + dx=300; + dy=100; + } + this.titulo=titulo; + if(!nel){ + nel=BLauLib.Window.COUNT; + BLauLib.Window.COUNT++; + } + + //contentor + this.contentor=$$("div"); + + //topbar + this.tbbar=$$("div"); + imgclose=$$("img"); + //tabelatop + var tbartable=$$("table"); + tbartable.className="tbwindow"; + //tbartable.setWidth(dx); + + //titulo + this.divT=$$("div"); + this.divT.innerHTML=this.titulo; + this.divT.className="titleheader"; + + //divImgClose + var divImgClose=$$("div"); + divImgClose.className="imgclose"; + + //corpo + this.bd=$$("div"); + this.bd.className="wcontent"; + + this.contentor.className="wmain"; + this.contentor.id="wd_"+nel; + this.contentor.setWidth(dx); + var obj=this.contentor; + var tbb=this.tbbar; + //top bar + this.tbbar.className="wheader"; + this.tbbar.id="tpbar_"+nel; + //this.tbbar.setHeight(BLauLib.Window.TBAR_HEIGHT); + + + imgclose.id="imgclose_"+nel; + imgclose.src=BLauLib.Window.IMGCLOSE; + var evimgclose=function(ev){ + var el=HElement.get(obj); + var onimgclose=function(){ + el.parentNode.removeChild(el); + } + el.desvanece(0.2,onimgclose); + } + + + this.bd.className="wcontent"; + this.bd.id="bd_"+nel; + this.bd.style.minHeight=dy+"px"; + this.bd.innerHTML=bdcontent; + + //adiciona os elementos ao top bar + this.tbbar.appendChild(this.divT); + divImgClose.appendChild(imgclose); + this.tbbar.appendChild(divImgClose); + + //eventos + var isto=this; + this.tbbar.onmousedown=function(e){ + e=e?e:window.event; + isto.drag=true; + var elH=HElement.get(obj); + var hD=HElement.get(tbb); + var pnt=elH.startDrag(e.clientX,e.clientY,null); + } + + this.tbbar.onmouseup=function(){ + document.onmousemove=null; + isto.drag=false; + } + + imgclose.onmouseup=evimgclose; + this.contentor.appendChild(this.tbbar); + this.contentor.appendChild(this.bd); +} + +/** + * Método que devolve o div contentor da janela + */ +BLauLib.Window.prototype.getContentor=function(){ + return this.contentor; +} + +/** + * Método que atribui uma determinada transparência à janela + * @param {Number} val Transparência, valor entre 0 e 100 + */ +BLauLib.Window.prototype.setAlpha=function(val){ + this.contentor.setAlpha(val); +} + +/** + * Método que permite especificar o conteúdo do contentor da janela + * @param {String} val String contendo o HTML que irá ficar interno ao contentor da janela + */ +BLauLib.Window.prototype.setBodyContent=function(val){ + this.bd.innerHTML=val; +} + +/** + * Método que permite especificar o conteúdo da barra de título da janela + * @param {String} titulo HTML com o conteúdo a passar para a janela de título + */ +BLauLib.Window.prototype.setTitle=function(titulo){ + this.divT.innerHTML=titulo; +} +/** + * Objecto Canvas que encapsular um conjunto de funcionalidades a operar sobre o objecto canvas + * @classDescription Neste objecto pretende-se encapsular um conjunto de funcionalidades que irão operar sob + * a tag canvas. Este objecto consiste numa pequena API para automatizar algumas ferramentas e funcionalidades de + * computação visual que se pode efectuar recorrendo à especificação HTML5 + * @param {String} id identificador do objecto canvas + */ +BLauLib.Canvas=function(id){ + this.canvas=$(id); + if(this.canvas && this.canvas.getContext){ + this.c=this.canvas.getContext("2d"); + } + else + throw "O browser não suporta o objecto canvas"; +} + +/** + * Método que especifica a função que será executada quando se efectua um varrimento da imagem pixel por pixel. + * A função enviada para o método será invocada para todos os valores de pixel. + * @see #inverte + * @see #noiseImage + * @see #blackWhiteNoise + * @see #Threshold + * @param {Function} func Função callback + * @param {Object} args Argumentos adicionais para a função callback + */ +BLauLib.Canvas.prototype._ppixelCallback=function(func,args){ + var imgd=this.c.getImageData(0,0,this.canvas.width,this.canvas.height); + var pixs=imgd.data; + var n=pixs.length; + var sm=0; + for(var i=0;i0.5) + return [255,255,255,100]; + return [0,0,0,100] + },null) +} + + +/*** + * Aplica threshold na imagem + * @param {Number} treshold Limite de threshold + */ +BLauLib.Canvas.prototype.Threshold=function(tresh){ + this._ppixelCallback(function(px1,px2,px3,alpha,tr){ + var arr=[]; + sm=(px1+px2+px3)/3; + if(sm xmax) { + sfac = xmax / img.width; + img.width = img.width * sfac; + img.height = img.height * sfac; + } + this.canvas.width = img.width; + this.canvas.height = img.height; + this.c.drawImage(img,0,0,img.width,img.height); + this.c.scale(sfac,sfac); +} + +/** + * Método que carrega uma imagem para o objecto canvas efectuando um redimensionamento + * a partir da sua altura máxima + * @param {String} src Endereço da imagem + * @param {Number} xmax Altura máxima da imagem + */ +BLauLib.Canvas.prototype.loadScaledYImage=function(src,ymax){ + var img=new Image(); + var sfac=1; + img.src=src; + if (xmax && img.width > ymax) { + sfac = ymax / img.height; + img.width = img.width * sfac; + img.height = img.height * sfac; + } + this.canvas.width = img.width; + this.canvas.height = img.height; + this.c.drawImage(img,0,0,img.width,img.height); + this.c.scale(sfac,sfac); +} + + +var HOSTNAME=""; +var DIR_IMAGENS=""; +BLauLib.Window.COUNT=0; +BLauLib.Window.TBAR_HEIGHT=25; +BLauLib.Window.BBAR_HEIGHT=25; +BLauLib.Window.MIN_HEIGHT=100; +BLauLib.Window.MIN_WIDTH=100; +BLauLib.Window.IMGCLOSE=HOSTNAME+DIR_IMAGENS+"close16.png"; +BLauLib.Window.IMGRESIZE=HOSTNAME+DIR_IMAGENS+"resze.png"; + +BLauLib.Window.width=function(){ + return $('$html')[0].clientWidth; +} + +BLauLib.Window.height=function(){ + return $('$html')[0].clientHeight; +} +BLauLib.Window.scrX=function(){ + return $('$html')[0].scrollLeft; +} + +BLauLib.Window.scrY=function(){ + return $('$html')[0].scrollTop; +} + +BLauLib.MsgBox=function(tipoMsg,msg,titulo){ + BLauLib.Window.apply(this, ["msg"+BLauLib.Window.COUNT,titulo,400,100]); + this.bd.innerHTML=msg; + return this.contentor; +} +/** + * Método que efectua a transicao entre dois niveis de transparencia + * @param {Number} alphaIni Percentagem de opacidade inicial + * @param {Number} alphaFin Percentagem de opacidade final + * @param {Number} seg Numero em segundos de duracao da transicao + * @see #desvanece + * @see #aparece + * @see #getAlpha + * @see #setAlpha + */ +HElement.prototype.transicaoAlpha=function(alphaIni,alphaFin,seg,callback){ + if(!this.ontransition){ + this.ontransition=true; + var cresc=true; + var transita=true; + if(alphaIni>alphaFin) + cresc=false; + var passo=(alphaFin-alphaIni)/(seg*24); + var alphaAct=alphaIni; + var obj=this; + var act=function(){ + if ((cresc === true && alphaAct > alphaFin) || (cresc === false && alphaAct < alphaFin)) { + transita=false; + if(alphaAct>100){ + obj.setAlpha(100) + } + if(alphaAct<0){ + obj.setAlpha(0); + } + obj.ontransition=false; + clearInterval(i); + if(callback!=null){ + callback(); + } + } + else{ + alphaAct+=passo; + obj.setAlpha(alphaAct); + + } + } + if(transita) + var i=setInterval(act,1000/30); + } +}; + +/** + * Método que remove um elemento filho a partir do seu identificador + * @param {String} id Identificador do elemento a remover + */ +HElement.prototype.removeChildById=function(id){ + var cnt=this.childElementCount; + var filho=null; + for(var i=0;i 127) && (c < 2048)) { + utftext += String.fromCharCode((c >> 6) | 192); + utftext += String.fromCharCode((c & 63) | 128); + } + else { + utftext += String.fromCharCode((c >> 12) | 224); + utftext += String.fromCharCode(((c >> 6) & 63) | 128); + utftext += String.fromCharCode((c & 63) | 128); + } + } + return utftext; +} + +/** + * Método que descodifica uma string do formato UTF-8 + * @return {String} String descodificada + */ +String.prototype.decodeUTF8=function(){ + var string = ""; + var i = 0; + var c = c1 = c2 = 0; + + while ( i < this.length ) { + + c = this.charCodeAt(i); + + if (c < 128) { + string += String.fromCharCode(c); + i++; + } + else if((c > 191) && (c < 224)) { + c2 = this.charCodeAt(i+1); + string += String.fromCharCode(((c & 31) << 6) | (c2 & 63)); + i += 2; + } + else { + c2 = this.charCodeAt(i+1); + c3 = this.charCodeAt(i+2); + string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); + i += 3; + } + } + return string; +} + +var Priberam=function(){ + this.descricao=""; + this.NDIV=32; + this.onLoaded=null; +} + +var DragHandler = { + + // private property. + _oElem : null, + + // public method. Attach drag handler to an element. + attach : function(oElem,dgEl) { + oElem.onmousedown = DragHandler._dragBegin; + _dgEl=dgEl; + // callbacks + oElem.dragBegin = new Function(); + oElem.drag = new Function(); + oElem.dragEnd = new Function(); + return oElem; + }, + + + // private method. Begin drag process. + _dragBegin : function(e) { + var oElem = DragHandler._oElem = this; + + if (isNaN(parseInt(oElem.style.left))) { oElem.style.left = '0px'; } + if (isNaN(parseInt(oElem.style.top))) { oElem.style.top = '0px'; } + + var x = parseInt(oElem.style.left); + var y = parseInt(oElem.style.top); + + e = e ? e : window.event; + oElem.mouseX = e.clientX; + oElem.mouseY = e.clientY; + + oElem.dragBegin(oElem, x, y); + + document.onmousemove = DragHandler._drag; + document.onmouseup = DragHandler._dragEnd; + return false; + }, + + + // private method. Drag (move) element. + _drag : function(e) { + var oElem = DragHandler._oElem; + + var x = parseInt(oElem.style.left); + var y = parseInt(oElem.style.top); + + e = e ? e : window.event; + oElem.style.left = x + (e.clientX - oElem.mouseX) + 'px'; + oElem.style.top = y + (e.clientY - oElem.mouseY) + 'px'; + + oElem.mouseX = e.clientX; + oElem.mouseY = e.clientY; + + oElem.drag(oElem, x, y); + + return false; + }, + + + // private method. Stop drag process. + _dragEnd : function() { + var oElem = DragHandler._oElem; + + var x = parseInt(oElem.style.left); + var y = parseInt(oElem.style.top); + + oElem.dragEnd(oElem, x, y); + + document.onmousemove = null; + document.onmouseup = null; + DragHandler._oElem = null; + alert("END"); + } + } + +Priberam.prototype.get=function(pal){ + var aj=new BLauLib.Ajax(); + var dc; + var obj=this; + aj.addVar("url","http://www.priberam.pt/dlpo/default.aspx?pal="+encodeURI(pal)); + aj.onLoaded=function(){ + var eltmp=document.createElement('hidden'); + eltmp.innerHTML=aj.text; + var dvs=eltmp.getElementsByTagName("div"); + obj.descricao=dvs[obj.NDIV].innerHTML.decodeUTF8(); + obj.onLoaded(); + }; + aj.open("POST","http://localhost/wbservices/wb_loadurl"); + aj.send(aj.encPostVars()); +}; + +/** + * Método que contém um conjunto de funcionalidades para o processamento de captchas + * @classDescription Este objecto pretende fornecer um conjunto de funcionalidades de manipulação de imagens gerados pelo + * sistema RECaptcha + * @param {String} pubkey Chave pública + * @param {String} privkey Chave privada + * @author Balhau + */ +var RECaptcha=function(pubkey,privkey){ + this.publickey=pubkey; + this.privatekey=privkey; + this.challenge=""; + this.challengeURL=RECaptcha.ServerName+"challenge?k="+this.publickey; +} + +/** + * Método que utiliza um script de servidor para guardar imagens geradas pelo serviço RECaptcha + * @param {String} imgname Nome da imagem que pretendemos guardar + */ +RECaptcha.prototype.saveImage=function(imgname){ + var aj=new BLauLib.Ajax(); + var obj=this; + aj.onLoaded = function(){ + var resp = aj.text; + resp=resp.split(";")[0]; + resp=resp.split(","); + resp=resp[1].split(":"); + resp=resp[1].replace(/'/gi,""); + obj.challenge=resp; + var naj=new BLauLib.Ajax(); + var urlImg=RECaptcha.ServerName+"image?c="+resp.trim(); + naj.addVar("url",urlImg); + naj.addVar("imgname",imgname); + naj.onLoaded=function(){ + } + naj.callPost(RECaptcha.PHPCallbackFile); + } + aj.open("GET",RECaptcha.PHPRedirectFile+"?url="+this.challengeURL); + aj.send(null); +} + +/** + * Nome do ficheiro que efectua o processamento das imagens geradas pelo mecanismo RECaptcha + */ +RECaptcha.PHPCallbackFile="save.php"; + +/** + * Nome do ficheiro que funciona como proxy para endereços externos. + */ +RECaptcha.PHPRedirectFile="redirect.php"; + +/** + * Endereço do serviço RECaptcha + */ +RECaptcha.ServerName="http://www.google.com/recaptcha/api/"; diff --git a/sudoku.js b/sudoku.js new file mode 100644 index 0000000..807eabe --- /dev/null +++ b/sudoku.js @@ -0,0 +1,258 @@ +/*** + * Classe que implementa o Sudoku + * @author Balhau + * @classDescription O objecto Sudoku contém funções para geração de sudokus e respectivas soluções + * @requires Este ficheiro necessita do ficheiro js.js como requisito devido a funções utilitárias + */ +var Sudoku=function(){ + var dx=Sudoku.DIMX; + var dy=Sudoku.DIMY; + this._mat=[]; + this.clear(); +}; + +Sudoku.getPosXY=function(pos){ + var x=pos%9; + var y=Math.floor(pos/9); + return {"x":x,"y":y}; +}; + +Sudoku.toPos=function(x,y){ + var dx=Sudoku.DIMX; + var dy=Sudoku.DIMY; + if(x>=dx) + x=dx-1; + if(y>=dy) + y=dy-1; + return y*9+x; +}; +/** + * Verifica se a coluna contem valores todos diferentes + * @param pos Posição no vector + * @param val Valor a colocar no vector + * @return Boolean + */ +Sudoku.prototype.checkColum=function(pos,val){ + var dx=Sudoku.DIMX; + var dy=Sudoku.DIMY; + var p=Sudoku.getPosXY(pos); + for(var i=0;i=3 && p.x<6)pi=1;else pi=2; + if(p.y<3)pj=0;else if(p.y>=3 && p.y<6)pj=1;else pj=2; + var ci=0; + var pii=pi*3; + var li=pj*9*3; + for(var i=0;i<9;i++){ + if(i%3==0 && i!=0){ + ci=0; + li+=9; + } + //var p=Sudoku.getPosXY(li+ci+pii); + //console.log("PosA: "+p.x+","+p.y); + if(this._mat[li+ci+pii]==val) + return false; + ci++; + } + return true; +}; + +/** + * Método que reinicia o vector com os valores do sudoku + * @return + */ +Sudoku.prototype.clear=function(){ + var dx=Sudoku.DIMX; + var dy=Sudoku.DIMY; + for(var i=0;imaxit){ + pos=Math.max(0,i-Sudoku.BACK_TRACK_STEP); + this.clearLastValues(i, pos); //backtrack + i=pos; //retorna atrás nas iteracções + it=0; //inicia o contador + itt++; + } + if(itt>maxitt){ + i=maxitt; + } + } + if(i==maxitt) + return false; + return true; +}; + +/** + * Método que devolve os blocos do sudoku sob a forma de HTML + * @param x Ponto x do bloco + * @param y Ponto y do bloco + * @return String com o código em HTML do bloco + */ +Sudoku.prototype.getHTMLBlock=function(x,y){ + var pi,pj;//variaveis que identificam o bloco + if(x<3)pi=0;else if(x>=3 && x<6)pi=1;else pi=2; + if(y<3)pj=0;else if(y>=3 && y<6)pj=1;else pj=2; + var ci=0; + var pii=pi*3; + var li=pj*9*3; + var ncl=((x+y)%2==0)?"par":"impar"; + var str="\n\t"; + for(var i=0;i<9;i++){ + if(i%3==0 && i!=0){ + ci=0; + li+=9; + str+="\n\t\n\t"; + } + str+="\n\t\t"; + ci++; + } + str+="\n\t\n
"+this._mat[li+ci+pii]+"
"; + return str; +}; + +/** + * Método que devolve uma instância do sudoku em função do seu nível de dificuldade + * @param level + * @return + */ +Sudoku.prototype.getSudoku=function(level){ + if(BLauLib.isUndefined(level)) + level=Sudoku.EASY; + var comp=this._mat.length; + var pb=0.5-level*0.12; + var ninst=new Sudoku(); + var mclone=this._mat.clone(); + for(var i=0;i"; + } + str+=""; + } + str+=""; + return str; +}; + +/** + * Método que devolve uma descrição do sudoku em forma de string + * @return String + */ +Sudoku.prototype.toString=function(){ + var st=""; + var cmp=this._mat.length; + var pl=1; + for(var i=0;i0?this._mat[i]:" "; + if((i+1)%9==0){ + pl++; + st+="|\n"; + } + if(pl%4==0){ + for(var j=0;j<9;j++){ + st+="___"; + } + st+="\n"; + pl=1; + } + } + return st; +}; + diff --git a/test.html b/test.html new file mode 100644 index 0000000..6a9c6be --- /dev/null +++ b/test.html @@ -0,0 +1,12 @@ + + + + + + Js Test + + + + + +