<commit_before>const Discord = require('discord.js');
const client = new Discord.Client();
const figlet = require('figlet');
const fs = require('fs');
const irc = require('irc');

//process.argv.forEach((t) => console.log(t));

token = process.argv[2];
//console.log('Using token: ' + token);

client.on('ready', () => {
        console.log("BOT IS READY");
});

serverText = fs.readFileSync('servers.json');
var servers = JSON.parse(serverText);

const ircClient = new irc.Client(servers.irc.hostname, servers.irc.nick, {
        channels: servers.irc.channels,
        secure: servers.irc.secure,
        port: servers.irc.port
});

executorsText = fs.readFileSync('executors.json');
const executors = JSON.parse(executorsText).list;

function getChannelFromID(server, id) {
        return server.channels.resolve(id);
}

client.on('message', (msg) => {

        const re = /\?(?<command>\w*)(?<args> (\w*)*)?( ?```(?<code>.*)```)?/gms;
        input = re.exec(msg.content);

        if(input) {

                command = input.groups.command;
                args = input.groups.args;
                code = input.groups.code;

                //console.dir(input);

                if (command == "fig") {
                        if (input.groups.args == undefined) {
                                msg.channel.send("You need to give some text to figlet");
                                return;
                        }

                        figlet(args, (err, data) => {
                                if (err) {
                                        console.log("figlet broke?");
                                }
                                msg.channel.send("```" + data + "```")
                        });
                }

                if (command == "setdel") {
                        var channel = args;
                        if (!servers[msg.guild.id]) {
                                servers[msg.guild.id] = {}
                        }
                        servers[msg.guild.id]["deletes"] = channel;

                        let newServer = JSON.stringify(servers);

                        fs.writeFile('servers.json', newServer, (err) => {
                                if (err) throw err;
                                console.log("delete prefs updated for " + msg.guild.name);
                        });

                        msg.channel.send("Delete channel preference set.")
                }

                if (command == "execute") {
                        if (executors.includes(""+msg.author.id)) {
                                if(code != undefined) {
                                        try {
                                                msg.channel.send(eval(code.trim(/(javascript)|(js)/gm)));
                                        } catch (e) {
                                                msg.channel.send("Your code caused an error");
                                        }
                                } else {
                                        msg.channel.send("You have to send some code using ```[code]```");
                                }
                        } else {
                                msg.channel.send("You are not an approved executor");
                        }
                }

        }

        if (msg.channel.id == servers.irc.cid && msg.author.id != client.user.id) {

                console.dir(msg);

                if (msg.content != "")
                        ircClient.say(servers.irc.channels[0], "<" + msg.member.displayName + ">: " + msg.content);

                msg.embeds.forEach((e) => {
                        console.log("relayed an embed");
                        ircClient.say(servers.irc.channels[0], "<" + msg.member.displayName + "> " + e.url);
                });
        }

});

client.on('messageDelete', (msg) => {
        if (servers[msg.guild.id]) {
                if (servers[msg.guild.id]["deletes"]) {
                        chan = getChannelFromID(msg.guild, servers[msg.guild.id]["deletes"]);

                        let delEmbed = new Discord.MessageEmbed()
                                .setColor('#992020')
                                .setTitle("Deleted Message from " + msg.author.tag)
                                .addFields(
                                        {name: "Message", value: msg.content},
                                        {name: "Channel", value: msg.channel.name},
                                        {name: "Timestamp", value: msg.createdAt}
                                );
                        try {
                                chan.send(delEmbed);
                        } catch (e) {
                                console.log("error sending deleted message log");
                        }

                        console.log("sent deleted message log to " + msg.guild.name);

                }
        }

});

ircClient.addListener('message', (from, to, message) => {
        if (servers.irc.channels.includes(to) && !from.includes(servers.irc.nick)) {
                client.guilds.resolve(servers.irc.sid).channels.resolve(servers.irc.cid).send("<" + from + "> " + message);
        }
});

ircClient.addListener('registered', (msg) => {
        console.log("IRC Bridge Connected");
});

ircClient.addListener('error', (msg) => {
        console.log("IRC Error: " + msg);
});

client.login(token);
<commit_msg>fixed(?) image bridging<commit_after>const Discord = require('discord.js');
const client = new Discord.Client();
const figlet = require('figlet');
const fs = require('fs');
const irc = require('irc');

//process.argv.forEach((t) => console.log(t));

token = process.argv[2];
//console.log('Using token: ' + token);

client.on('ready', () => {
        console.log("BOT IS READY");
});

serverText = fs.readFileSync('servers.json');
var servers = JSON.parse(serverText);

const ircClient = new irc.Client(servers.irc.hostname, servers.irc.nick, {
        channels: servers.irc.channels,
        secure: servers.irc.secure,
        port: servers.irc.port
});

executorsText = fs.readFileSync('executors.json');
const executors = JSON.parse(executorsText).list;

function getChannelFromID(server, id) {
        return server.channels.resolve(id);
}

client.on('message', (msg) => {

        const re = /\?(?<command>\w*)(?<args> (\w*)*)?( ?```(?<code>.*)```)?/gms;
        input = re.exec(msg.content);

        if(input) {

                command = input.groups.command;
                args = input.groups.args;
                code = input.groups.code;

                //console.dir(input);

                if (command == "fig") {
                        if (input.groups.args == undefined) {
                                msg.channel.send("You need to give some text to figlet");
                                return;
                        }

                        figlet(args, (err, data) => {
                                if (err) {
                                        console.log("figlet broke?");
                                }
                                msg.channel.send("```" + data + "```")
                        });
                }

                if (command == "setdel") {
                        var channel = args;
                        if (!servers[msg.guild.id]) {
                                servers[msg.guild.id] = {}
                        }
                        servers[msg.guild.id]["deletes"] = channel;

                        let newServer = JSON.stringify(servers);

                        fs.writeFile('servers.json', newServer, (err) => {
                                if (err) throw err;
                                console.log("delete prefs updated for " + msg.guild.name);
                        });

                        msg.channel.send("Delete channel preference set.")
                }

                if (command == "execute") {
                        if (executors.includes(""+msg.author.id)) {
                                if(code != undefined) {
                                        try {
                                                msg.channel.send(eval(code.trim(/(javascript)|(js)/gm)));
                                        } catch (e) {
                                                msg.channel.send("Your code caused an error");
                                        }
                                } else {
                                        msg.channel.send("You have to send some code using ```[code]```");
                                }
                        } else {
                                msg.channel.send("You are not an approved executor");
                        }
                }

        }

        if (msg.channel.id == servers.irc.cid && msg.author.id != client.user.id) {

                //console.dir(msg);

                if (msg.content != "")
                        ircClient.say(servers.irc.channels[0], "<" + msg.member.displayName + ">: " + msg.content);

                msg.attachments.forEach((e) => {
                        //console.log("relayed an embed");
                        ircClient.say(servers.irc.channels[0], "<" + msg.member.displayName + "> " + e.url);
                });
        }

});

client.on('messageDelete', (msg) => {
        if (servers[msg.guild.id]) {
                if (servers[msg.guild.id]["deletes"]) {
                        chan = getChannelFromID(msg.guild, servers[msg.guild.id]["deletes"]);

                        let delEmbed = new Discord.MessageEmbed()
                                .setColor('#992020')
                                .setTitle("Deleted Message from " + msg.author.tag)
                                .addFields(
                                        {name: "Message", value: msg.content},
                                        {name: "Channel", value: msg.channel.name},
                                        {name: "Timestamp", value: msg.createdAt}
                                );
                        try {
                                chan.send(delEmbed);
                        } catch (e) {
                                console.log("error sending deleted message log");
                        }

                        console.log("sent deleted message log to " + msg.guild.name);

                }
        }

});

ircClient.addListener('message', (from, to, message) => {
        if (servers.irc.channels.includes(to) && !from.includes(servers.irc.nick)) {
                client.guilds.resolve(servers.irc.sid).channels.resolve(servers.irc.cid).send("<" + from + "> " + message);
        }
});

ircClient.addListener('registered', (msg) => {
        console.log("IRC Bridge Connected");
});

ircClient.addListener('error', (msg) => {
        console.log("IRC Error: " + msg);
});

client.login(token);
<|endoftext|>


<commit_before>const Discord = require('discord.js');
const request = require('request');
const sql = require('sqlite');
sql.open('./streamers.sqlite');
let Config;

//look for config
try {
    Config = require('./config.json');
} catch(e) {
    console.log('Please create an config.json file in the main directory based off of the config.json.example file!\n' + e.stack);
	process.exit();
}

console.log('I am ready for work :)')

const bot = new Discord.Client()

function check() {
    for(let i = 0; Config.streamers.length > i; i++) {
         sql.get(`SELECT * FROM streamers WHERE streamer ='${Config.streamers[i]}'`).then(row => {
            if (!row) {
                sql.run('INSERT INTO streamers (streamer, status) VALUES (?, ?)', [Config.streamers[i], 0]);
             } else {
                 request('https://beam.pro/api/v1/channels/'+Config.streamers[i],
                    function(err,res,body){
                        const data = JSON.parse(body);
                        if(!data) console.log(`The channel, ${Config.streamers[i]}, is not a valid beam.pro channel!`);
                        if(data.online === false && row.status === 0) console.log(`${row.streamer} is already saved as offline!`);
                        if(data.online === false && row.status == 1) {
                            sql.run(`UPDATE streamers SET status = 0 WHERE streamer = '${Config.streamers[i]}'`);
                            console.log(`${Config.streamers[i]} is offline!`)
                        };
                        if(row.status === 1 && data.online == true) return;
                        if(data.online === true && row.status == 0) {
                            sql.run(`UPDATE streamers SET status = 1 WHERE streamer = '${Config.streamers[i]}'`);
                            console.log(`${row.streamer} is now Online!`)
                            for(let j = 0; j < Config.channelID.length; j++){
                                const embed = new Discord.RichEmbed()
                                    .setTitle('Beam Alerts')
                                    .setDescription(`${Config.streamers[i]} is now live!`)
                                    .addField(`Playing For:`, `${data.numFollowers} followers`,true)
                                    .addField(`${Config.streamers[i]} is Playing:`, `${data.type.name}`,true)
                                    .setFooter('BaconHawk - NITEHAWK')
                                    .setColor([0,45,255])
                                    .setTimestamp()
                                bot.channels.get(Config.channelID[j]).sendEmbed(embed);
                            }
                        }
                    });
    }
}).catch(() => {
    console.error;
    sql.run('CREATE TABLE IF NOT EXISTS streamers (streamer TEXT, status INTEGER)').then(() => {
      sql.run('INSERT INTO streamers (streamer, status) VALUES (?, ?)', [Config.streamers[i], 0]);
      console.log(`Table created!`);
    });
  });
    }

}

bot.on('ready', () =>{check(); setInterval(check, 60*5*1000)});
bot.login(Config.bot_token)<commit_msg>added bhlog<commit_after>const Discord = require('discord.js');
const request = require('request');
const sql = require('sqlite');
sql.open('./streamers.sqlite');
let bhlog = console.log
let Config;

//look for config
try {
    Config = require('./config.json');
} catch(e) {
    bhlog('Please create an config.json file in the main directory based off of the config.json.example file!\n' + e.stack);
	process.exit();
}

bhlog('I am ready for work :)')

const bot = new Discord.Client()

function check() {
    for(let i = 0; Config.streamers.length > i; i++) {
         sql.get(`SELECT * FROM streamers WHERE streamer ='${Config.streamers[i]}'`).then(row => {
            if (!row) {
                sql.run('INSERT INTO streamers (streamer, status) VALUES (?, ?)', [Config.streamers[i], 0]);
             } else {
                 request('https://beam.pro/api/v1/channels/'+Config.streamers[i],
                    function(err,res,body){
                        const data = JSON.parse(body);
                        if(!data) console.log(`The channel, ${Config.streamers[i]}, is not a valid beam.pro channel!`);
                        if(data.online === false && row.status === 0) console.log(`${row.streamer} is already saved as offline!`);
                        if(data.online === false && row.status == 1) {
                            sql.run(`UPDATE streamers SET status = 0 WHERE streamer = '${Config.streamers[i]}'`);
                            console.log(`${Config.streamers[i]} is offline!`)
                        };
                        if(row.status === 1 && data.online == true) return;
                        if(data.online === true && row.status == 0) {
                            sql.run(`UPDATE streamers SET status = 1 WHERE streamer = '${Config.streamers[i]}'`);
                            console.log(`${row.streamer} is now Online!`)
                            for(let j = 0; j < Config.channelID.length; j++){
                                const embed = new Discord.RichEmbed()
                                    .setTitle('Beam Alerts')
                                    .setDescription(`${Config.streamers[i]} is now live!`)
                                    .addField(`Playing For:`, `${data.numFollowers} followers`,true)
                                    .addField(`${Config.streamers[i]} is Playing:`, `${data.type.name}`,true)
                                    .setFooter('BaconHawk - NITEHAWK')
                                    .setColor([0,45,255])
                                    .setTimestamp()
                                bot.channels.get(Config.channelID[j]).sendEmbed(embed);
                            }
                        }
                    });
    }
}).catch(() => {
    console.error;
    sql.run('CREATE TABLE IF NOT EXISTS streamers (streamer TEXT, status INTEGER)').then(() => {
      sql.run('INSERT INTO streamers (streamer, status) VALUES (?, ?)', [Config.streamers[i], 0]);
      console.log(`Table created!`);
    });
  });
    }

}

bot.on('ready', () =>{check(); setInterval(check, 60*5*1000)});
bot.login(Config.bot_token)
<|endoftext|>


<commit_before>client.login("")

var prefix = "px;"

client.on("message", function(message) {

    if (message.author.equals(client.user)) return;

    if (!message.content.startsWith(prefix)) return;

    var args = message.content.substring(prefix.length).split(" ");

    switch (args[0]) {
        //ping command
        case "ping":
             const embed1 = new Discord.RichEmbed()
           	.setColor("#940000")
           	.setTitle(":ping_pong: Pong!", "Response time: " + client.ping + "ms")
           	.setFooter("Requested by " + message.author.tag, message.author.displayAvatarURL)
           	.setTimestamp()
            message.channel.send({embed});
            break;
        // about command
        case "about":
            const embed2 = new Discord.RichEmbed()
	        .setColor("#940000")
            	.setTitle("About PixaBot", "PixaBot is a Discord bot that features games, image manipulation, moderation and music commands written in JavaScript.")
           	.setFooter("Requested by " + message.author.tag, message.author.displayAvatarURL)
           	.setTimestamp()
            message.channel.send({embed});
            break;
        // version command
        case "version":
            message.channel.send("The current version of PixaBot is " + 0.2  + " beta 1")
            break;
        // kick command
        case "kick":
		    message.channel.send("Coming Soon!")
		break;
        // ban command
	case "ban":
		message.channel.send("Coming Soon!")
		break;
	case "help":
            const embed3 = new Discord.RichEmbed()
	        .setColor("#940000")
            	.setTitle("PixaBot Help Guide", "Here are my available commands. To execute one of my commands, my prefix is `px;`.")
            	.addField("General Commands", "Coming soon!")
            	.setFooter("Requested by " + message.author.tag, message.author.displayAvatarURL)
           	.setTimestamp()
            	message.channel.send({embed});
		break;
	    case "coming soon":
		    message.channel.send("kick: px;kick ban: px;ban and help command")
            break;
        case "CanIbeMod?":
		    message.channel.send("no but you can be jailed if you want (from kaiss)")
            break;
}
<commit_msg>numbering<commit_after>client.login("")

var prefix = "px;"

client.on("message", function(message) {

    if (message.author.equals(client.user)) return;

    if (!message.content.startsWith(prefix)) return;

    var args = message.content.substring(prefix.length).split(" ");

    switch (args[0]) {
        //ping command
        case "ping":
             const embed1 = new Discord.RichEmbed()
           	.setColor("#940000")
           	.setTitle(":ping_pong: Pong!", "Response time: " + client.ping + "ms")
           	.setFooter("Requested by " + message.author.tag, message.author.displayAvatarURL)
           	.setTimestamp()
            message.channel.send({embed1});
            break;
        // about command
        case "about":
            const embed2 = new Discord.RichEmbed()
	        .setColor("#940000")
            	.setTitle("About PixaBot", "PixaBot is a Discord bot that features games, image manipulation, moderation and music commands written in JavaScript.")
           	.setFooter("Requested by " + message.author.tag, message.author.displayAvatarURL)
           	.setTimestamp()
            message.channel.send({embed2});
            break;
        // version command
        case "version":
            message.channel.send("The current version of PixaBot is " + 0.2  + " beta 1")
            break;
        // kick command
        case "kick":
		    message.channel.send("Coming Soon!")
		break;
        // ban command
	case "ban":
		message.channel.send("Coming Soon!")
		break;
	case "help":
            const embed3 = new Discord.RichEmbed()
	        .setColor("#940000")
            	.setTitle("PixaBot Help Guide", "Here are my available commands. To execute one of my commands, my prefix is `px;`.")
            	.addField("General Commands", "Coming soon!")
            	.setFooter("Requested by " + message.author.tag, message.author.displayAvatarURL)
           	.setTimestamp()
            	message.channel.send({embed3});
		break;
	    case "coming soon":
		    message.channel.send("kick: px;kick ban: px;ban and help command")
            break;
        case "CanIbeMod?":
		    message.channel.send("no but you can be jailed if you want (from kaiss)")
            break;
}
<|endoftext|>


<commit_before>const Discord = require('discord.js');
const client = new Discord.Client();
const weather = require('weather-js');
const sql = require("sqlite");
const palavroes = require('./profanity/palavroes.js');
const await = require('await');
const ytdl = require('ytdl-core');
//const streamOptions = { seek: 0, volume: 1 };
//const mysql = require('mysql');

var servers = {};

//----------------------------------------------------------------------------------------------------------------------------------

sql.open("./score.sqlite");

//----------------------------------------------------------------------------------------------------------------------------------

client.config = require('./config.json');
client.log = require('./functions/log.js');
client.commands = new Discord.Collection();

//----------------------------------------------------------------------------------------------------------------------------------

//COMANDOS
client.commands.set('ping', require('./commands/ping.js'));
client.commands.set('falar', require('./commands/falar.js'));
client.commands.set('ajuda', require('./commands/ajuda.js'));
client.commands.set('limpar', require('./commands/limpar.js'));
client.commands.set('ban', require('./commands/ban.js'));
client.commands.set('kick', require('./commands/kick.js'));
client.commands.set('unban', require('./commands/unban.js'));
client.commands.set('roll6', require('./commands/roll6.js'));
client.commands.set('bot', require('./commands/conversaBot.js'));
client.commands.set('morra', require('./commands/conversaMorra.js'));
client.commands.set('soma', require('./commands/calcularSoma.js'));
client.commands.set('sub', require('./commands/calcularSub.js'));
client.commands.set('mult', require('./commands/calcularMult.js'));
client.commands.set('div', require('./commands/calcularDiv.js'));
client.commands.set('fsalvos', require('./commands/canalSalvos.js'));
client.commands.set('feventos', require('./commands/canalEventos.js'));
client.commands.set('fprincipal', require('./commands/canalPrincipal.js'));
client.commands.set('resp', require('./commands/resp.js'));
client.commands.set('play', require('./commands/radioPlayYoutube.js'));
client.commands.set('playinitiald', require('./commands/radioPlayInitialD.js'));
client.commands.set('playmoe', require('./commands/radioPlayMoe.js'));
client.commands.set('playanimenfo', require('./commands/radioPlayAnimeNfo.js'));
client.commands.set('playhrh', require('./commands/radioHardRockHeaven.js'));
client.commands.set('playmh', require('./commands/radioMetalHardcore.js'));
client.commands.set('stop', require('./commands/radioStop.js'));
client.commands.set('userinfo', require('./commands/userinfo.js'));
client.commands.set('serverinfo', require('./commands/serverinfo.js'));
client.commands.set('tempo', require('./commands/tempo.js'));
client.commands.set('afk', require('./commands/joinAway.js'));
client.commands.set('level', require('./commands/levelXp.js'));
client.commands.set('pontos', require('./commands/levelPoints.js'));
client.commands.set('votar', require('./commands/votar.js'));
client.commands.set('invite', require('./commands/invite.js'));
client.commands.set('up', require('./commands/botUpdate.js'));
//client.commands.set('teste', require('./commands/teste.js'));

//----------------------------------------------------------------------------------------------------------------------------------

//MENSAGEM
client.on('messageReactionAdd', (reaction, user) => require('./events/messageReactionAdd.js')(client, reaction, user));
//----------------------------------------------------------------------------------------------------------------------------------
client.on('message', message => {
  //BANCO DE DADOS
  sql.get(`SELECT * FROM scores WHERE userId ="${message.author.id}"`).then(row =>
  { if (!row) { sql.run("INSERT INTO scores (userId, points, level) VALUES (?, ?, ?)", [message.author.id, 1, 0]);
  } else {  let curLevel = Math.floor(0.1 * Math.sqrt(row.points + 1));
    if (curLevel > row.level) { row.level = curLevel;  sql.run(`UPDATE scores SET points = ${row.points + 1}, level = ${row.level} WHERE userId = ${message.author.id}`);  message.reply(`Ding! Parabéns! Você subiu de level. O seu level atual é **${curLevel}**!`);    }
  sql.run(`UPDATE scores SET points = ${row.points + 1} WHERE userId = ${message.author.id}`);  }
  }).catch(() => { console.error;
  sql.run("CREATE TABLE IF NOT EXISTS scores (userId TEXT, points INTEGER, level INTEGER)").then(() => {
  sql.run("INSERT INTO scores (userId, points, level) VALUES (?, ?, ?)", [message.author.id, 1, 0]);   });  });
  //FILTRO DE PALAVRÃO
    if( palavroes.some(palavra => message.content.toUpperCase().includes(palavra)) ) {
  message.delete();
  message.reply(':warning: **Atenção** :warning: ... A sua mensagem foi apagada. Por favor não diga palavrões!!! Rhrumnn!!! :anger:').then(msg => {msg.delete(60000)}); }
  //MENSAGEM TEMPO EM TEMPO
  if (message.content === "$loop") {
    var channel = client.channels.get('167715230082662401');
    var interval = setInterval (function () {
      channel.sendMessage('**Mensagem automática**: Olá! Eu sou a **BoT** @Waifu! \nSou programada e hosteada pelo @Giulianno para cuidar deste servidor! \n● Use o comando **!bot** para chamar a minha atenção! \n● Use o comando **!ajuda** para listar os comandos usados no servidor! \n● Use o comando **!invite** para criar um link e invitar alguém para o servidor. \n( Mande o link para a pessoa desejada ) ( Pessoas novas no servidor começam com o status de **@everyone**! Status de **@everyone** ou **@Sub** não podem usar o comando **!invite**. Por favor, peça para algum admin mudar o seu status para **@Membro** )').then(msg => {msg.delete(300000)})
    }, 30 * 1000);}
  //MENSAGEM REQUIRE
  require('./events/message.js')(client, message, sql) });
//----------------------------------------------------------------------------------------------------------------------------------

//READY
client.on('ready', () => { var channel = client.channels.get('377272159770247170'); channel.sendMessage(":black_square_button: **O BoT está online!**").then(msg => {msg.delete(60000)}); require('./events/ready.js')(client) });

//GUILD
client.on('guildCreate', guild => require('./events/guildCreate.js')(client, guild));
client.on('guildMemberAdd', (member, message, channel) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('Olá, seja bem vindo(a) **'+member.user.username+'**!').then(msg => {msg.delete(60000)}) } );
client.on('guildMemberRemove', (member, message, channel) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('Adeus **'+member.user.username+'**!').then(msg => {msg.delete(60000)}) } );
client.on('guildMemberUpdate', (oldMember, newMember) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('Os dados do usuário **'+oldMember+'** foram **atualizados**! (Cargo | Nickname)').then(msg => {msg.delete(60000)}) } );
client.on('guildUpdate', (guild, oldGuild, newGuild) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('O servidor **'+oldGuild+'** foi **atualizado**!').then(msg => {msg.delete(60000)}) } );
client.on('guildBanAdd', (guild, user) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage(':warning: **Atenção** :warning: ... O usuário **'+user+'** foi **banido**!').then(msg => {msg.delete(60000)}) } );
client.on('guildBanRemove', (guild, user) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage(':warning: **Atenção** :warning: ... O usuário **'+user+'** foi **desbanido**!').then(msg => {msg.delete(60000)}) } );

//USER
//client.on('userNoteUpdate', (user, oldNote, newNote) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('O usuário **'+user+'** atualizou a sua **descrição** no perfil!').then(msg => {msg.delete(60000)}) } );
client.on('userUpdate', (oldUser, newUser) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('O usuário **'+oldUser+'** atualizou o seu **nome de cadastro**!').then(msg => {msg.delete(60000)}) } );

//EMOJI
client.on('emojiCreate', (emoji) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('O **Emoji** '+emoji+' foi adicionado!').then(msg => {msg.delete(60000)}) } );
client.on('emojiDelete', (emoji) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('O **Emoji** '+emoji+' foi deletado!!').then(msg => {msg.delete(60000)}) } );
client.on('emojiUpdate', (emoji, oldEmoji, newEmoji) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('O **Emoji** '+oldEmoji+' foi **atualizado**!').then(msg => {msg.delete(60000)}) } );

//ROLES
client.on('roleCreate', (role) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('O novo **Cargo** '+role+' foi adicionado!').then(msg => {msg.delete(60000)}) } );
client.on('roleDelete', (role) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('O **Cargo** '+role+' foi deletado!!').then(msg => {msg.delete(60000)}) } );
client.on('roleUpdate', (role, oldRole, newRole) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('O **Cargo** '+oldRole+' foi **atualizado**!').then(msg => {msg.delete(60000)}) } );

//CANAL
client.on('channelCreate', (channel) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('Uma nova **sala de conversa** foi **criada**!').then(msg => {msg.delete(60000)}) } );
client.on('channelDelete', (channel, guild) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('Uma **sala de conversa** foi **deletada**!').then(msg => {msg.delete(60000)}) } );
client.on('channelPinsUpdate', (channel, time) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('Uma nova mensagem foi **fixada** em **'+time+'**!').then(msg => {msg.delete(60000)}) } );
client.on('channelUpdate', (channel, oldChannel, newChannel) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('A sala de conversa **'+oldChannel+'** foi atualizada!').then(msg => {msg.delete(60000)}) } );

//----------------------------------------------------------------------------------------------------------------------------------
//-----Nao usado por causa de spam
/*client.on('voiceStateUpdate', (oldMember, newMember) => { let newUserChannel = newMember.voiceChannel; let oldUserChannel = oldMember.voiceChannel;
if(oldUserChannel === undefined && newUserChannel !== undefined) { entra no canal --- CODIGO de msg aqui } else if(newUserChannel === undefined){ sai no canal --- CODIGO de msg aqui }}); */
//----------------------------------------------------------------------------------------------------------------------------------
//-----mysql Heroku connect database
/*var con;
if(process.env.DATABASE_URL) { con = mysql.createConnection(process.env.DATABASE_URL); } */
//----------------------------------------------------------------------------------------------------------------------------------

//client.login(config.token)
client.login(process.env.BOT_TOKEN);<commit_msg><commit_after>const Discord = require('discord.js');
const client = new Discord.Client();
const weather = require('weather-js');
const sql = require("sqlite");
const palavroes = require('./profanity/palavroes.js');
const await = require('await');
const ytdl = require('ytdl-core');
//const streamOptions = { seek: 0, volume: 1 };
//const mysql = require('mysql');

var servers = {};

//----------------------------------------------------------------------------------------------------------------------------------

sql.open("./score.sqlite");

//----------------------------------------------------------------------------------------------------------------------------------

client.config = require('./config.json');
client.log = require('./functions/log.js');
client.commands = new Discord.Collection();

//----------------------------------------------------------------------------------------------------------------------------------

//COMANDOS
client.commands.set('ping', require('./commands/ping.js'));
client.commands.set('falar', require('./commands/falar.js'));
client.commands.set('ajuda', require('./commands/ajuda.js'));
client.commands.set('limpar', require('./commands/limpar.js'));
client.commands.set('ban', require('./commands/ban.js'));
client.commands.set('kick', require('./commands/kick.js'));
client.commands.set('unban', require('./commands/unban.js'));
client.commands.set('roll6', require('./commands/roll6.js'));
client.commands.set('bot', require('./commands/conversaBot.js'));
client.commands.set('morra', require('./commands/conversaMorra.js'));
client.commands.set('soma', require('./commands/calcularSoma.js'));
client.commands.set('sub', require('./commands/calcularSub.js'));
client.commands.set('mult', require('./commands/calcularMult.js'));
client.commands.set('div', require('./commands/calcularDiv.js'));
client.commands.set('fsalvos', require('./commands/canalSalvos.js'));
client.commands.set('feventos', require('./commands/canalEventos.js'));
client.commands.set('fprincipal', require('./commands/canalPrincipal.js'));
client.commands.set('resp', require('./commands/resp.js'));
client.commands.set('play', require('./commands/radioPlayYoutube.js'));
client.commands.set('playinitiald', require('./commands/radioPlayInitialD.js'));
client.commands.set('playmoe', require('./commands/radioPlayMoe.js'));
client.commands.set('playanimenfo', require('./commands/radioPlayAnimeNfo.js'));
client.commands.set('playhrh', require('./commands/radioHardRockHeaven.js'));
client.commands.set('playmh', require('./commands/radioMetalHardcore.js'));
client.commands.set('stop', require('./commands/radioStop.js'));
client.commands.set('userinfo', require('./commands/userinfo.js'));
client.commands.set('serverinfo', require('./commands/serverinfo.js'));
client.commands.set('tempo', require('./commands/tempo.js'));
client.commands.set('afk', require('./commands/joinAway.js'));
client.commands.set('level', require('./commands/levelXp.js'));
client.commands.set('pontos', require('./commands/levelPoints.js'));
client.commands.set('votar', require('./commands/votar.js'));
client.commands.set('invite', require('./commands/invite.js'));
client.commands.set('up', require('./commands/botUpdate.js'));
//client.commands.set('teste', require('./commands/teste.js'));

//----------------------------------------------------------------------------------------------------------------------------------

//MENSAGEM
client.on('messageReactionAdd', (reaction, user) => require('./events/messageReactionAdd.js')(client, reaction, user));
//----------------------------------------------------------------------------------------------------------------------------------
client.on('message', message => {
  //BANCO DE DADOS
  sql.get(`SELECT * FROM scores WHERE userId ="${message.author.id}"`).then(row =>
  { if (!row) { sql.run("INSERT INTO scores (userId, points, level) VALUES (?, ?, ?)", [message.author.id, 1, 0]);
  } else {  let curLevel = Math.floor(0.1 * Math.sqrt(row.points + 1));
    if (curLevel > row.level) { row.level = curLevel;  sql.run(`UPDATE scores SET points = ${row.points + 1}, level = ${row.level} WHERE userId = ${message.author.id}`);  message.reply(`Ding! Parabéns! Você subiu de level. O seu level atual é **${curLevel}**!`);    }
  sql.run(`UPDATE scores SET points = ${row.points + 1} WHERE userId = ${message.author.id}`);  }
  }).catch(() => { console.error;
  sql.run("CREATE TABLE IF NOT EXISTS scores (userId TEXT, points INTEGER, level INTEGER)").then(() => {
  sql.run("INSERT INTO scores (userId, points, level) VALUES (?, ?, ?)", [message.author.id, 1, 0]);   });  });
  //FILTRO DE PALAVRÃO
    if( palavroes.some(palavra => message.content.toUpperCase().includes(palavra)) ) {
  message.delete();
  message.reply(':warning: **Atenção** :warning: ... A sua mensagem foi apagada. Por favor não diga palavrões!!! Rhrumnn!!! :anger:').then(msg => {msg.delete(60000)}); }
  //MENSAGEM TEMPO EM TEMPO
  if (message.content === "$loop") {
    var channel = client.channels.get('167715230082662401');
    var interval = setInterval (function () {
      channel.sendMessage('**Mensagem automática**: Olá! Eu sou a **BoT** @Waifu! \nSou programada e hosteada pelo @Giulianno para cuidar deste servidor! \n● Use o comando **!bot** para chamar a minha atenção! \n● Use o comando **!ajuda** para listar os comandos usados no servidor! \n● Use o comando **!invite** para criar um link e invitar alguém para o servidor. \n( Mande o link para a pessoa desejada ) ( Pessoas novas no servidor começam com o status de **@everyone**! Status de **@everyone** ou **@Sub** não podem usar o comando **!invite**. Por favor, peça para algum admin mudar o seu status para **@Membro** )')
    }, 1 * 1000).then(msg => {msg.delete(300000)});}
  //MENSAGEM REQUIRE
  require('./events/message.js')(client, message, sql) });
//----------------------------------------------------------------------------------------------------------------------------------

//READY
client.on('ready', () => { var channel = client.channels.get('377272159770247170'); channel.sendMessage(":black_square_button: **O BoT está online!**").then(msg => {msg.delete(60000)}); require('./events/ready.js')(client) });

//GUILD
client.on('guildCreate', guild => require('./events/guildCreate.js')(client, guild));
client.on('guildMemberAdd', (member, message, channel) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('Olá, seja bem vindo(a) **'+member.user.username+'**!').then(msg => {msg.delete(60000)}) } );
client.on('guildMemberRemove', (member, message, channel) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('Adeus **'+member.user.username+'**!').then(msg => {msg.delete(60000)}) } );
client.on('guildMemberUpdate', (oldMember, newMember) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('Os dados do usuário **'+oldMember+'** foram **atualizados**! (Cargo | Nickname)').then(msg => {msg.delete(60000)}) } );
client.on('guildUpdate', (guild, oldGuild, newGuild) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('O servidor **'+oldGuild+'** foi **atualizado**!').then(msg => {msg.delete(60000)}) } );
client.on('guildBanAdd', (guild, user) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage(':warning: **Atenção** :warning: ... O usuário **'+user+'** foi **banido**!').then(msg => {msg.delete(60000)}) } );
client.on('guildBanRemove', (guild, user) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage(':warning: **Atenção** :warning: ... O usuário **'+user+'** foi **desbanido**!').then(msg => {msg.delete(60000)}) } );

//USER
//client.on('userNoteUpdate', (user, oldNote, newNote) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('O usuário **'+user+'** atualizou a sua **descrição** no perfil!').then(msg => {msg.delete(60000)}) } );
client.on('userUpdate', (oldUser, newUser) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('O usuário **'+oldUser+'** atualizou o seu **nome de cadastro**!').then(msg => {msg.delete(60000)}) } );

//EMOJI
client.on('emojiCreate', (emoji) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('O **Emoji** '+emoji+' foi adicionado!').then(msg => {msg.delete(60000)}) } );
client.on('emojiDelete', (emoji) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('O **Emoji** '+emoji+' foi deletado!!').then(msg => {msg.delete(60000)}) } );
client.on('emojiUpdate', (emoji, oldEmoji, newEmoji) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('O **Emoji** '+oldEmoji+' foi **atualizado**!').then(msg => {msg.delete(60000)}) } );

//ROLES
client.on('roleCreate', (role) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('O novo **Cargo** '+role+' foi adicionado!').then(msg => {msg.delete(60000)}) } );
client.on('roleDelete', (role) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('O **Cargo** '+role+' foi deletado!!').then(msg => {msg.delete(60000)}) } );
client.on('roleUpdate', (role, oldRole, newRole) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('O **Cargo** '+oldRole+' foi **atualizado**!').then(msg => {msg.delete(60000)}) } );

//CANAL
client.on('channelCreate', (channel) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('Uma nova **sala de conversa** foi **criada**!').then(msg => {msg.delete(60000)}) } );
client.on('channelDelete', (channel, guild) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('Uma **sala de conversa** foi **deletada**!').then(msg => {msg.delete(60000)}) } );
client.on('channelPinsUpdate', (channel, time) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('Uma nova mensagem foi **fixada** em **'+time+'**!').then(msg => {msg.delete(60000)}) } );
client.on('channelUpdate', (channel, oldChannel, newChannel) => { var channel = client.channels.get('167715230082662401'); channel.sendMessage('A sala de conversa **'+oldChannel+'** foi atualizada!').then(msg => {msg.delete(60000)}) } );

//----------------------------------------------------------------------------------------------------------------------------------
//-----Nao usado por causa de spam
/*client.on('voiceStateUpdate', (oldMember, newMember) => { let newUserChannel = newMember.voiceChannel; let oldUserChannel = oldMember.voiceChannel;
if(oldUserChannel === undefined && newUserChannel !== undefined) { entra no canal --- CODIGO de msg aqui } else if(newUserChannel === undefined){ sai no canal --- CODIGO de msg aqui }}); */
//----------------------------------------------------------------------------------------------------------------------------------
//-----mysql Heroku connect database
/*var con;
if(process.env.DATABASE_URL) { con = mysql.createConnection(process.env.DATABASE_URL); } */
//----------------------------------------------------------------------------------------------------------------------------------

//client.login(config.token)
client.login(process.env.BOT_TOKEN);<|endoftext|>


<commit_before>'use latest';
import bodyParser from 'body-parser';
import express from 'express';
import Webtask from 'webtask-tools';
import { MongoClient } from 'mongodb';
import { ObjectID } from 'mongodb';

const collection = 'chatbot.terms';
const server = express();

function Term(key, value) {
  this.key = key;
  this.value = value;
}

var insertTerm = function(key, value, db, cb) {
    db.collection(collection).insertOne(new Term(key.toLowerCase(),value), (err, result) => {
      if (err) cb(err);
      cb(null, `Added \'${key}\' with response \'${value}\'`);
    });
};

var readTerms = function(db, cb) {
    db.collection(collection).find().toArray((err, terms) =>  {
      if (err) cb(err);
      else cb(null, terms);
    });
};

var updateTerm = function(term, value, db, cb) {
  db.collection(collection).find().toArray((err, terms) =>  {
    if (err) cb(err);
    else {
      var existing = terms.find(o => o.key === term.toLowerCase());
        if (existing && existing._id !== null) {
        db.collection(collection).updateOne({_id: existing._id}, {key: term.toLowerCase(), value: value}, (err, result) => {
          if (err) cb(err);
          else { cb(null, `Updated \'${term}\' with value \'${value}\'`); }
        });
        } else { cb(null, `${term} not found`); }
    }
  });
};

var deleteTerm = function(term, db, cb) {
  db.collection(collection).find().toArray((err, terms) =>  {
      if (err) cb(err);
      else {
        var doomed = terms.find(o => o.key === term.toLowerCase());
        if (doomed) {
          db.collection(collection).remove({_id : doomed._id}, (err, result) => {
            if (err) cb(err);
            else { cb(null, `Term \'${term}\' successfully deleted`); }
          });
        } else { cb(null, `${term} not found`); }
      }
  });
};

server.use(bodyParser.json());
server.get('/', (req, res, next) => {
    res.status(200).send('Hello there!');
});

// Receives callback POSTS from GroupMe service
server.post('/', (req, res, next) => {
  const { MONGO_URL } = req.webtaskContext.data;
  MongoClient.connect(MONGO_URL, (err, db) => {
    if (err) return next(err);
    // Expects GroupMe payload
    var message = req.body.text;
    var parts = message.split(' ');
    if (parts[0].toLowerCase() == '/bot') {
      switch(parts[1]) {
        case 'add':
        case 'new':
        case 'insert':
          insertTerm(parts[2], parts.slice(3, parts.length).join(' '), db, (err, result) => {
            res.status(200).send(result);
          });
          break;
        case 'update':
        case 'change':
          updateTerm(parts[2], parts.slice(3, parts.length).join(' '), db, (err, result) => {
            res.status(200).send(result);
          });
          break;
        case 'delete':
        case 'remove':
        case 'rm':
          deleteTerm(parts[2], db, (err, result) => {
            res.status(200).send(result);
          });
        default:
          res.status(200).send('Command not found');
      }
    } else {
      readTerms(db, (err, terms) => {
        if (err) res.status(500).send(err);
        else {
          var matches = [];
          for(var i = 0; i < terms.length; i++) {
            if (message.indexOf(terms[i].key) > -1) matches.push(terms[i].value);
          }
          if (matches.length > 0) res.status(200).send(`Matches: ${matches.join(", ")}`);
          else res.status(200).send('');
        }
      });
    }
  });

});

module.exports = Webtask.fromExpress(server);
<commit_msg>Added missing break in delete switch<commit_after>'use latest';
import bodyParser from 'body-parser';
import express from 'express';
import Webtask from 'webtask-tools';
import { MongoClient } from 'mongodb';
import { ObjectID } from 'mongodb';

const collection = 'chatbot.terms';
const server = express();

function Term(key, value) {
  this.key = key;
  this.value = value;
}

var insertTerm = function(key, value, db, cb) {
    db.collection(collection).insertOne(new Term(key.toLowerCase(),value), (err, result) => {
      if (err) cb(err);
      cb(null, `Added \'${key}\' with response \'${value}\'`);
    });
};

var readTerms = function(db, cb) {
    db.collection(collection).find().toArray((err, terms) =>  {
      if (err) cb(err);
      else cb(null, terms);
    });
};

var updateTerm = function(term, value, db, cb) {
  db.collection(collection).find().toArray((err, terms) =>  {
    if (err) cb(err);
    else {
      var existing = terms.find(o => o.key === term.toLowerCase());
        if (existing && existing._id !== null) {
        db.collection(collection).updateOne({_id: existing._id}, {key: term.toLowerCase(), value: value}, (err, result) => {
          if (err) cb(err);
          else { cb(null, `Updated \'${term}\' with value \'${value}\'`); }
        });
        } else { cb(null, `${term} not found`); }
    }
  });
};

var deleteTerm = function(term, db, cb) {
  db.collection(collection).find().toArray((err, terms) =>  {
      if (err) cb(err);
      else {
        var doomed = terms.find(o => o.key === term.toLowerCase());
        if (doomed) {
          db.collection(collection).remove({_id : doomed._id}, (err, result) => {
            if (err) cb(err);
            else { cb(null, `Term \'${term}\' successfully deleted`); }
          });
        } else { cb(null, `${term} not found`); }
      }
  });
};

server.use(bodyParser.json());
server.get('/', (req, res, next) => {
    res.status(200).send('Hello there!');
});

// Receives callback POSTS from GroupMe service
server.post('/', (req, res, next) => {
  const { MONGO_URL } = req.webtaskContext.data;
  MongoClient.connect(MONGO_URL, (err, db) => {
    if (err) return next(err);
    // Expects GroupMe payload
    var message = req.body.text;
    var parts = message.split(' ');
    if (parts[0].toLowerCase() == '/bot') {
      switch(parts[1]) {
        case 'add':
        case 'new':
        case 'insert':
          insertTerm(parts[2], parts.slice(3, parts.length).join(' '), db, (err, result) => {
            res.status(200).send(result);
          });
          break;
        case 'update':
        case 'change':
          updateTerm(parts[2], parts.slice(3, parts.length).join(' '), db, (err, result) => {
            res.status(200).send(result);
          });
          break;
        case 'delete':
        case 'remove':
        case 'rm':
          deleteTerm(parts[2], db, (err, result) => {
            res.status(200).send(result);
          });
          break;
        default:
          res.status(200).send('Command not found');
      }
    } else {
      readTerms(db, (err, terms) => {
        if (err) res.status(500).send(err);
        else {
          var matches = [];
          for(var i = 0; i < terms.length; i++) {
            if (message.indexOf(terms[i].key) > -1) matches.push(terms[i].value);
          }
          if (matches.length > 0) res.status(200).send(`Matches: ${matches.join(", ")}`);
          else res.status(200).send('');
        }
      });
    }
  });

});

module.exports = Webtask.fromExpress(server);
<|endoftext|>


<commit_before>// defaultCompareFn: The default compare function.
// Returns:
//   0   if node1.val and node2.val are equal
//   < 0 if node1.val < node2.val
//   > 0 if node1.val > node2.val
function defaultCompareFn (node1, node2) {
    return node1.val - node2.val;
}

// This is the sentinel for Red-Black trees. It's not used in
// constructing BSTs but allows sharing of functions more easily
var NIL = {val:'NIL',
           color:'b',
           left:null,
           right:null,
           p:null};

// treeTuple: Return a tuple hierarchy in the form: [val,left,right]
// (or [val,color,left,right] in the case of Red-Black tree)
// Note: an empty tree will return null
function treeTuple (tree) {
    if (tree === null || !('val' in tree)) {
        return null;
    }
    if (tree === NIL) {
        return 'NIL';
    }

    var res = [];
    res.push(tree.val);
    if ('color' in tree) {
        res.push(tree.color);
    }
    res.push(treeTuple(tree.left));
    res.push(treeTuple(tree.right));
    return res;
}

// treeReduce:
// Returns the final reduced result
function treeReduce (result, node, action, order) {
    order = order||"in";  // pre, in, or post

    if (node !== null && node !== NIL && 'val' in node) {
        if (order === 'pre') { result = action(result, node); }
        result = treeReduce(result, node.left, action, order);
        if (order === 'in') { result = action(result, node); }
        result = treeReduce(result, node.right, action, order);
        if (order === 'post') { result = action(result, node); }
    }
    return result;
}

// treeWalk: Walk the tree and return an array of all the values. The
// walk order depends on order (a string) which may be:
//   'in'   -> in-order walk
//   'pre'  -> pre-order walk
//   'post' -> post-order walk
// Based on INORDER-TREE-WALK definition in CLRS 12.1
function treeWalk (tree, order) {
    return treeReduce([], tree, function(res, node) {
        return res.concat([node.val]);
    }, order);
}

// treeLinks: Return a list of links: [[a, b], [b, c]]
// Note: an empty tree will return null
function treeLinks (tree) {
    return treeReduce([], tree, function(res, node) {
        var links = [];
        if (node.left && node.left !== NIL) {
            links.push([node.val, node.left.val]);
        }
        if (node.right && node.right !== NIL) {
            links.push([node.val, node.right.val]);
        }
        return res.concat(links);
    }, 'pre');
}

// treeDOT: Return DOT graph description
// This can be fed to GraphViz to generate a rendering of the graph.
function treeDOT(tree) {
    var links = treeLinks(tree),
        dot;
    if (tree.p === NIL) {
        dot = "digraph Red_Black_Tree {\n";
    } else {
        dot = "digraph Binary_Search_Tree {\n";
    }
    treeReduce(null, tree, function(_, n) {
        if (n.color === 'r') {
            dot += '  ' + n.val + " [color=red];\n";
        }
        if (n.left && n.left !== NIL) {
            dot += "  " + n.val + " -> " + n.left.val + ";\n";
        }
        if (n.right && n.right !== NIL) {
            dot += "  " + n.val + " -> " + n.right.val + ";\n";
        }
    }, 'pre');
    dot += "}";
    return dot;
}

// treeSearch: Search the tree for value using compareFn.
// Returns the matching node.
// Based on TREE-SEARCH defintion in CLRS 12.2
function treeSearch (tree, value, compareFn) {
    if (typeof compareFn === 'undefined') {
        compareFn = defaultCompareFn;
    }

    if (tree === null || tree.val === undefined
        || compareFn(tree, {val:value}) === 0) {
        return tree;
    } else if (compareFn({val:value}, tree) < 0) {
        return treeSearch(tree.left, value);
    } else {
        return treeSearch(tree.right, value);
    }
}

// treeMin: Return the minimum (left-most) node.
// Based on TREE-MINIMUM definition in CLRS 12.2
function treeMin(tree) {
    while (tree.left !== null && tree.left !== NIL) {
        tree = tree.left;
    }
    return tree;
}

// treeMin: Return the maximum (right-most) node.
// Based on TREE-MAXIMUM definition in CLRS 12.2
function treeMax(tree) {
    while (tree.right !== null && tree.right !== NIL) {
        tree = tree.right;
    }
    return tree;
}

// treeInsert: Add the value to the tree using compareFn to determin
// the placement. Returns new tree (root node could have changed)
// Based on TREE-INSERT definition in CLRS 12.3
function treeInsert (tree, node, compareFn) {
    if (typeof compareFn === 'undefined') {
        compareFn = defaultCompareFn;
    }

    var x = ('val' in tree) ? tree : null,
        y = null,
        z = node;

    while (x !== null) {
        y = x;
        if (compareFn(z, x) < 0) {
            x = x.left;
        } else {
            x = x.right;
        }
    }

    z.p = y;
    if (y === null) {
        // tree was empty
        tree = z;
    } else if (compareFn(z, y) < 0) {
        y.left = z;
    } else {
        y.right = z;
    }
    return tree;
}

// treeTransplant
// Based on TRANSPLANT definition in CLRS 12.3
function treeTransplant(tree, dst, src) {
    var u = dst, v = src;
    if (u.p === null) {
        tree = v;
    } else if (u === u.p.left) {
        u.p.left = v;
    } else {
        u.p.right = v;
    }
    if (v !== null) {
        v.p = u.p;
    }
    return tree;
}

// treeRemove
// Based on TREE-DELETE definition in CLRS 12.3
function treeRemove (tree, node) {
    var z = node,
        y;
    if (z.left === null) {
        tree = treeTransplant(tree,z,z.right);
    } else if (z.right === null) {
        tree = treeTransplant(tree,z,z.left);
    } else {
        y = treeMin(z.right);
        if (y.p !== z) {
            tree = treeTransplant(tree,y,y.right);
            y.right = z.right;
            y.right.p = y;
        }
        tree = treeTransplant(tree,z,y);
        y.left = z.left;
        y.left.p = y;
    }
    return tree;
}

// BST: Binary Search Tree Object
//   - Constructor: new BST(cmpFn) - create/construct a new BST object
//       using cmpFn.  If cmpFn is not provided then a numeric comparison
//       is done on nodeX.val
//   - API/Methods: walk, search, min, max, remove, insert. For
//       debugging: root, tuples.
function BST (cmpFn) {
    if (typeof cmpFn === 'undefined') {
        cmpFn = defaultCompareFn;
    }

    var self = this,
        api = {};
    self.tree = {p:null,left:null,right:null};
    self.insertFn = treeInsert;
    self.removeFn = treeRemove;

    api.walk   = function(order) { return treeWalk(self.tree, order); };
    api.search = function(val)   { return treeSearch(self.tree, val, cmpFn); };
    api.min    = function()      { return treeMin(self.tree); };
    api.max    = function()      { return treeMax(self.tree); };
    api.root   = function()      { return self.tree; };
    api.tuples = function()      { return treeTuple(self.tree); };
    api.links  = function()      { return treeLinks(self.tree); };
    api.DOT    = function()      { return treeDOT(self.tree); };
    api.remove = function(node)  { self.tree = self.removeFn(self.tree,node); };
    api.insert = function() {
        // Allow one or more values to be inserted
        if (arguments.length === 1) {
            var node = {val:arguments[0],
                        left:null,
                        right:null,
                        p:null};
            self.tree = self.insertFn(self.tree, node, cmpFn);
        } else {
            for (var i = 0; i < arguments.length; i++) {
                var node = {val:arguments[i],
                            left:null,
                            right:null,
                            p:null};
                self.tree = self.insertFn(self.tree, node, cmpFn);
            }
        }
    };

    // Return the API functions (public interface)
    return api;
}

exports.NIL = NIL;
exports.defaultCompareFn = defaultCompareFn;
exports.treeTuple = treeTuple;
exports.treeReduce = treeReduce;
exports.treeWalk = treeWalk;
exports.treeLinks = treeLinks;
exports.treeDOT = treeDOT;
exports.treeSearch = treeSearch;
exports.treeMin = treeMin;
exports.treeMax = treeMax;
exports.treeInsert = treeInsert;
exports.treeTransplant = treeTransplant;
exports.treeRemove = treeRemove;
exports.BST = BST;
<commit_msg>Always add invidual nodes for DOT output not just red ones.<commit_after>// defaultCompareFn: The default compare function.
// Returns:
//   0   if node1.val and node2.val are equal
//   < 0 if node1.val < node2.val
//   > 0 if node1.val > node2.val
function defaultCompareFn (node1, node2) {
    return node1.val - node2.val;
}

// This is the sentinel for Red-Black trees. It's not used in
// constructing BSTs but allows sharing of functions more easily
var NIL = {val:'NIL',
           color:'b',
           left:null,
           right:null,
           p:null};

// treeTuple: Return a tuple hierarchy in the form: [val,left,right]
// (or [val,color,left,right] in the case of Red-Black tree)
// Note: an empty tree will return null
function treeTuple (tree) {
    if (tree === null || !('val' in tree)) {
        return null;
    }
    if (tree === NIL) {
        return 'NIL';
    }

    var res = [];
    res.push(tree.val);
    if ('color' in tree) {
        res.push(tree.color);
    }
    res.push(treeTuple(tree.left));
    res.push(treeTuple(tree.right));
    return res;
}

// treeReduce:
// Returns the final reduced result
function treeReduce (result, node, action, order) {
    order = order||"in";  // pre, in, or post

    if (node !== null && node !== NIL && 'val' in node) {
        if (order === 'pre') { result = action(result, node); }
        result = treeReduce(result, node.left, action, order);
        if (order === 'in') { result = action(result, node); }
        result = treeReduce(result, node.right, action, order);
        if (order === 'post') { result = action(result, node); }
    }
    return result;
}

// treeWalk: Walk the tree and return an array of all the values. The
// walk order depends on order (a string) which may be:
//   'in'   -> in-order walk
//   'pre'  -> pre-order walk
//   'post' -> post-order walk
// Based on INORDER-TREE-WALK definition in CLRS 12.1
function treeWalk (tree, order) {
    return treeReduce([], tree, function(res, node) {
        return res.concat([node.val]);
    }, order);
}

// treeLinks: Return a list of links: [[a, b], [b, c]]
// Note: an empty tree will return null
function treeLinks (tree) {
    return treeReduce([], tree, function(res, node) {
        var links = [];
        if (node.left && node.left !== NIL) {
            links.push([node.val, node.left.val]);
        }
        if (node.right && node.right !== NIL) {
            links.push([node.val, node.right.val]);
        }
        return res.concat(links);
    }, 'pre');
}

// treeDOT: Return DOT graph description
// This can be fed to GraphViz to generate a rendering of the graph.
function treeDOT(tree) {
    var links = treeLinks(tree),
        dot;
    if (tree.p === NIL) {
        dot = "digraph Red_Black_Tree {\n";
    } else {
        dot = "digraph Binary_Search_Tree {\n";
    }
    treeReduce(null, tree, function(_, n) {
        if (n.color === 'r') {
            dot += '  ' + n.val + " [color=red];\n";
        } else {
            dot += '  ' + n.val + " [color=black];\n";
        }
        if (n.left && n.left !== NIL) {
            dot += "  " + n.val + " -> " + n.left.val + ";\n";
        }
        if (n.right && n.right !== NIL) {
            dot += "  " + n.val + " -> " + n.right.val + ";\n";
        }
    }, 'pre');
    dot += "}";
    return dot;
}

// treeSearch: Search the tree for value using compareFn.
// Returns the matching node.
// Based on TREE-SEARCH defintion in CLRS 12.2
function treeSearch (tree, value, compareFn) {
    if (typeof compareFn === 'undefined') {
        compareFn = defaultCompareFn;
    }

    if (tree === null || tree.val === undefined
        || compareFn(tree, {val:value}) === 0) {
        return tree;
    } else if (compareFn({val:value}, tree) < 0) {
        return treeSearch(tree.left, value);
    } else {
        return treeSearch(tree.right, value);
    }
}

// treeMin: Return the minimum (left-most) node.
// Based on TREE-MINIMUM definition in CLRS 12.2
function treeMin(tree) {
    while (tree.left !== null && tree.left !== NIL) {
        tree = tree.left;
    }
    return tree;
}

// treeMin: Return the maximum (right-most) node.
// Based on TREE-MAXIMUM definition in CLRS 12.2
function treeMax(tree) {
    while (tree.right !== null && tree.right !== NIL) {
        tree = tree.right;
    }
    return tree;
}

// treeInsert: Add the value to the tree using compareFn to determin
// the placement. Returns new tree (root node could have changed)
// Based on TREE-INSERT definition in CLRS 12.3
function treeInsert (tree, node, compareFn) {
    if (typeof compareFn === 'undefined') {
        compareFn = defaultCompareFn;
    }

    var x = ('val' in tree) ? tree : null,
        y = null,
        z = node;

    while (x !== null) {
        y = x;
        if (compareFn(z, x) < 0) {
            x = x.left;
        } else {
            x = x.right;
        }
    }

    z.p = y;
    if (y === null) {
        // tree was empty
        tree = z;
    } else if (compareFn(z, y) < 0) {
        y.left = z;
    } else {
        y.right = z;
    }
    return tree;
}

// treeTransplant
// Based on TRANSPLANT definition in CLRS 12.3
function treeTransplant(tree, dst, src) {
    var u = dst, v = src;
    if (u.p === null) {
        tree = v;
    } else if (u === u.p.left) {
        u.p.left = v;
    } else {
        u.p.right = v;
    }
    if (v !== null) {
        v.p = u.p;
    }
    return tree;
}

// treeRemove
// Based on TREE-DELETE definition in CLRS 12.3
function treeRemove (tree, node) {
    var z = node,
        y;
    if (z.left === null) {
        tree = treeTransplant(tree,z,z.right);
    } else if (z.right === null) {
        tree = treeTransplant(tree,z,z.left);
    } else {
        y = treeMin(z.right);
        if (y.p !== z) {
            tree = treeTransplant(tree,y,y.right);
            y.right = z.right;
            y.right.p = y;
        }
        tree = treeTransplant(tree,z,y);
        y.left = z.left;
        y.left.p = y;
    }
    return tree;
}

// BST: Binary Search Tree Object
//   - Constructor: new BST(cmpFn) - create/construct a new BST object
//       using cmpFn.  If cmpFn is not provided then a numeric comparison
//       is done on nodeX.val
//   - API/Methods: walk, search, min, max, remove, insert. For
//       debugging: root, tuples.
function BST (cmpFn) {
    if (typeof cmpFn === 'undefined') {
        cmpFn = defaultCompareFn;
    }

    var self = this,
        api = {};
    self.tree = {p:null,left:null,right:null};
    self.insertFn = treeInsert;
    self.removeFn = treeRemove;

    api.walk   = function(order) { return treeWalk(self.tree, order); };
    api.search = function(val)   { return treeSearch(self.tree, val, cmpFn); };
    api.min    = function()      { return treeMin(self.tree); };
    api.max    = function()      { return treeMax(self.tree); };
    api.root   = function()      { return self.tree; };
    api.tuples = function()      { return treeTuple(self.tree); };
    api.links  = function()      { return treeLinks(self.tree); };
    api.DOT    = function()      { return treeDOT(self.tree); };
    api.remove = function(node)  { self.tree = self.removeFn(self.tree,node); };
    api.insert = function() {
        // Allow one or more values to be inserted
        if (arguments.length === 1) {
            var node = {val:arguments[0],
                        left:null,
                        right:null,
                        p:null};
            self.tree = self.insertFn(self.tree, node, cmpFn);
        } else {
            for (var i = 0; i < arguments.length; i++) {
                var node = {val:arguments[i],
                            left:null,
                            right:null,
                            p:null};
                self.tree = self.insertFn(self.tree, node, cmpFn);
            }
        }
    };

    // Return the API functions (public interface)
    return api;
}

exports.NIL = NIL;
exports.defaultCompareFn = defaultCompareFn;
exports.treeTuple = treeTuple;
exports.treeReduce = treeReduce;
exports.treeWalk = treeWalk;
exports.treeLinks = treeLinks;
exports.treeDOT = treeDOT;
exports.treeSearch = treeSearch;
exports.treeMin = treeMin;
exports.treeMax = treeMax;
exports.treeInsert = treeInsert;
exports.treeTransplant = treeTransplant;
exports.treeRemove = treeRemove;
exports.BST = BST;
<|endoftext|>


<commit_before>"use strict";

function CCD(gl){
  this.gl = gl;
  this.joints = [];
  this.mesh = new Mesh(gl);
  this.material = new Material(gl);
  this.transform = new Transform();
  this.setupMaterial();

  this.effectorPosition = new Vector3(0,0,0);
  this.setupJoints();
  this.calculateMesh();
}

CCD.prototype.setupJoints = function() {
  var j1 = new Joint();
  var j2 = new Joint();
  var j3 = new Joint();
  var j4 = new Joint();

  this.joints.push(j1,j2,j3,j4);

  j1.id = 0;
  j1.children.push(j2);
  j1.childCount = 1;
  j1.refPoseTranslation.set(0.0,0.0,0.0);

  j2.id = 1;
  j2.parentID = 0;
  j2.children.push(j3);
  j2.childCount = 1;
  j2.refPoseTranslation.set(0,0,8);

  j3.id = 2;
  j3.parentID = 1;
  j3.children.push(j4);
  j3.childCount = 1;
  j3.refPoseTranslation.set(0,0,8);

  j4.id = 3;
  j4.parentID = 2;
  j4.refPoseTranslation.set(0,0,8);

  for(var i = 0; i < this.joints.length; i++){
    var joint = this.joints[i];
    joint.animationWorldBases.push(new Matrix44());
    joint.animationTranslations.push(joint.refPoseTranslation.clone());
    joint.animationRotations.push(new Vector3(0,0,0));
    joint.currentMatrices = joint.animationWorldBases;
  }

  for(var i = 0; i < this.joints.length; i++){
    var joint = this.joints[i];
    var rot = new Quaternion();
    rot.fromEulerAngles(joint.animationRotations[0]);
    this.calculateJoint(
                        0,
                        joint,
                        joint.animationTranslations[0],
                        rot
                        );

  }

};

CCD.prototype.calculateMesh = function() {
  var positions = [];
  this.mesh.clear();

  //calculate positions
  //positions.push(new Vector3(0,0,0));
  for(var i = 0; i < this.joints.length; i++){
    var joint = this.joints[i];

    var mat0 = joint.animationWorldBases[0];
    //var p = new Vector3(0,0,0);
    //p.transform(mat0);
    var p = new Vector3(mat0.m[12], mat0.m[13], mat0.m[14]);

    positions.push(p);
  }

  for(var i = 0; i < positions.length-1; i++) {
    var p0 = positions[i];
    var p1 = positions[i+1];
    this.mesh.positions.push(p0);
    this.mesh.positions.push(p1);

    var rb = i/this.joints.length;
    //var c = new Vector4(rb * 0.5, 0.0, rb, 1.0);
    var c = new Vector4(0, rb, 0, 1.0);

    this.mesh.colors.push(c);
    this.mesh.colors.push(c);
  }

  //add effector!
  this.mesh.positions.push(this.effectorPosition.clone().add(new Vector3(0,-1,0)));
  this.mesh.positions.push(this.effectorPosition.clone().add(new Vector3(0,1,0)));
  this.mesh.positions.push(this.effectorPosition.clone().add(new Vector3(0,0,-1)));
  this.mesh.positions.push(this.effectorPosition.clone().add(new Vector3(0,0,1)));
  this.mesh.positions.push(this.effectorPosition.clone().add(new Vector3(-1,0,0)));
  this.mesh.positions.push(this.effectorPosition.clone().add(new Vector3(1,0,0)));
  this.mesh.colors.push(new Vector4(1.0, 0.0, 0.0, 1.0));
  this.mesh.colors.push(new Vector4(1.0, 0.0, 0.0, 1.0));
  this.mesh.colors.push(new Vector4(1.0, 0.0, 0.0, 1.0));
  this.mesh.colors.push(new Vector4(1.0, 0.0, 0.0, 1.0));
  this.mesh.colors.push(new Vector4(1.0, 0.0, 0.0, 1.0));
  this.mesh.colors.push(new Vector4(1.0, 0.0, 0.0, 1.0));

  this.mesh.primitiveType = this.gl.LINES;

  if(this.mesh.vertexBuffer instanceof WebGLBuffer){
    this.mesh.updateBuffers();
  } else {
    this.mesh.constructBuffers();
  }

};

CCD.prototype.animateEffector = function(time){
  this.effectorPosition = new Vector3(0,15,8);
  var radius = 20.0;
  var horizOffset =  Math.sin(time);
  var vertOffset = Math.cos(time);
  var depthOffset = Math.cos(time);
  this.effectorPosition.x += horizOffset * radius;
  //this.effectorPosition.y += vertOffset * radius;
  //this.effectorPosition.z += depthOffset * radius;
}

CCD.prototype.animate = function(time){
  this.animateEffector(time);

  for( var i = 0; i < this.joints.length; i++ ) {
    var joint = this.joints[i];
    var trans = joint.animationTranslations[0].clone();
    var rotEuler = joint.animationRotations[0].clone();
    var rot = new Quaternion();
    rot.fromEulerAngles(rotEuler);
    rot.normalize();

    if(i == 0){
      var pos0 = new Vector3(0,0,0);
      /*
      var pm = new Matrix44();
      if(joint.parentID > -1){
        pm = this.joints[joint.parentID].animationWorldBases[0];
        pos0 = new Vector3(pm.m[12], pm.m[13], pm.m[14]);
      }
      var mtx = joint.animationWorldBases[0];
      var pos1 = new Vector3(mtx.m[12], mtx.m[13], mtx.m[14]);
      var dir = pos1.subtract(pos0).normalize();
      */
      var mtx = joint.animationWorldBases[0];
      //var translation = new Vector3(mtx.m[12], mtx.m[13], mtx.m[14]);
      var dir = new Vector3(0,0,1);
      dir.transformDirection(mtx).normalize();
      pos0.transform(mtx);

      var localEffPos = this.effectorPosition.clone();//.transform(pm.clone().invert());
      var dirToEffector = localEffPos.subtract(pos0).normalize();
      //var axisAngle = dir.getRotationToAlign(dirToEffector);
      rot.rotationTo(dir,dirToEffector);

      //THis is stable so the above code has an instability!
      rot.identity();
      rot.rotateX(Math.PI*0.5);
      rot.rotateY(Math.sin(-time) + 1*Math.PI);
      //console.debug(rot);
    }
    this.calculateJoint(0, joint, trans, rot);

  }
  this.calculateMesh();
};

CCD.prototype.calculateJoint = function(frame, joint, translation, rotation){
  var jointID = joint.id;
  //var mat = joint.animationCombinedBases[frame];

  var targetMatrix = joint.currentMatrices[frame];
  var animPose = joint.animationWorldBases[frame];
  if( joint.parentID != -1 ) {
    this.joints[joint.parentID].animationWorldBases[frame].copyInto(animPose);
  } else {
    animPose.identity();
  }

  animPose.translate(translation.x, translation.y, translation.z);
  animPose.rotate(rotation);

  /*
  animPose.copyInto(mat);
  mat.preMultiply(this.referencePose[jointID].referencePoseWorldToLocal.m);

  joint.currentMatrices[frame] = mat.clone();
  */
};

CCD.prototype.drawDebug = function(projMat, time){

  if(this.mesh.vertexBuffer instanceof WebGLBuffer){

    this.material.bind(this.mesh);
    //this.mesh.bind(this.material.shader);
    this.material.setUniforms(
        this.transform.matrix.m,
        this.transform.inverse.m,
        this.transform.inverseTranspose.m,
        projMat.m,
        time
        );
    this.gl.drawArrays(
        this.mesh.primitiveType,
        0,
        this.mesh.numItems
        );
  }
}

CCD.prototype.setupMaterial = function(gl){
  var fsSource="  precision mediump float;\n";
  fsSource +="\n";
  fsSource +="    varying vec4 vPosition;\n";
  fsSource +="    varying vec2 vUV;\n";
  fsSource +="    varying vec3 vNormal;\n";
  fsSource +="    varying vec3 vTangent;\n";
  fsSource +="    varying vec3 vBitangent;\n";
  fsSource +="    varying vec4 vVertColor;\n";
  fsSource +="\n";
  fsSource +="    uniform float uTime;\n";
  fsSource +="    uniform mat4 uMVMatrix;\n";
  fsSource +="\n";
  fsSource +="    void main(void) {\n";
  fsSource +="      gl_FragColor = vVertColor;\n";
  fsSource +="    }\n";

  var vsSource="  precision mediump float;\n";
  vsSource +="    attribute vec3 aVertexPosition;\n";
  vsSource +="    attribute vec3 aVertexNormal;\n";
  vsSource +="    attribute vec2 aVertexUV;\n";
  vsSource +="    attribute vec4 aVertexTangent;\n";
  vsSource +="    attribute vec4 aVertexColor;\n";
  vsSource +="\n";
  vsSource +="    uniform mat4 uMVMatrix;\n";
  vsSource +="    uniform mat4 uInverse;\n";
  vsSource +="    uniform mat4 uInverseTranspose;\n";
  vsSource +="    uniform mat4 uPMatrix;\n";
  vsSource +="    uniform float uTime;\n";
  vsSource +="\n";
  vsSource +="    varying vec4 vPosition;\n";
  vsSource +="    varying vec2 vUV;\n";
  vsSource +="    varying vec3 vNormal;\n";
  vsSource +="    varying vec3 vTangent;\n";
  vsSource +="    varying vec3 vBitangent;\n";
  vsSource +="    varying vec4 vVertColor;\n";
  vsSource +="\n";
  vsSource +="    void main(void) {\n";
  vsSource +="        vPosition = uMVMatrix * vec4(aVertexPosition,1.0);\n";
  //vsSource +="        vPosition = vec4(aVertexPosition,1.0);\n";
  vsSource +="        vVertColor = aVertexColor;\n";
  vsSource +="        vUV = aVertexUV.xy;\n";
  vsSource +="        vNormal = aVertexNormal.xyz;\n";
  vsSource +="        vTangent = aVertexTangent.xyz;\n";
  vsSource +="        gl_Position = uPMatrix * vPosition;\n";
  vsSource +="    }\n";

  this.material.shader.initShaderWithSource(fsSource,vsSource);
  this.material.zTest = false;
  this.material.zWrite = false;
  this.material.lineWidth = 3.0;

};

<commit_msg>Isolating instability<commit_after>"use strict";

function CCD(gl){
  this.gl = gl;
  this.joints = [];
  this.mesh = new Mesh(gl);
  this.material = new Material(gl);
  this.transform = new Transform();
  this.setupMaterial();

  this.effectorPosition = new Vector3(0,0,0);
  this.setupJoints();
  this.calculateMesh();
}

CCD.prototype.setupJoints = function() {
  var j1 = new Joint();
  var j2 = new Joint();
  var j3 = new Joint();
  var j4 = new Joint();

  this.joints.push(j1,j2,j3,j4);

  j1.id = 0;
  j1.children.push(j2);
  j1.childCount = 1;
  j1.refPoseTranslation.set(0.0,0.0,0.0);

  j2.id = 1;
  j2.parentID = 0;
  j2.children.push(j3);
  j2.childCount = 1;
  j2.refPoseTranslation.set(0,0,8);

  j3.id = 2;
  j3.parentID = 1;
  j3.children.push(j4);
  j3.childCount = 1;
  j3.refPoseTranslation.set(0,0,8);

  j4.id = 3;
  j4.parentID = 2;
  j4.refPoseTranslation.set(0,0,8);

  for(var i = 0; i < this.joints.length; i++){
    var joint = this.joints[i];
    joint.animationWorldBases.push(new Matrix44());
    joint.animationTranslations.push(joint.refPoseTranslation.clone());
    joint.animationRotations.push(new Vector3(0,0,0));
    joint.currentMatrices = joint.animationWorldBases;
  }

  for(var i = 0; i < this.joints.length; i++){
    var joint = this.joints[i];
    var rot = new Quaternion();
    rot.fromEulerAngles(joint.animationRotations[0]);
    this.calculateJoint(
                        0,
                        joint,
                        joint.animationTranslations[0],
                        rot
                        );

  }

};

CCD.prototype.calculateMesh = function() {
  var positions = [];
  this.mesh.clear();

  //calculate positions
  //positions.push(new Vector3(0,0,0));
  for(var i = 0; i < this.joints.length; i++){
    var joint = this.joints[i];

    var mat0 = joint.animationWorldBases[0];
    //var p = new Vector3(0,0,0);
    //p.transform(mat0);
    var p = new Vector3(mat0.m[12], mat0.m[13], mat0.m[14]);

    positions.push(p);
  }

  for(var i = 0; i < positions.length-1; i++) {
    var p0 = positions[i];
    var p1 = positions[i+1];
    this.mesh.positions.push(p0);
    this.mesh.positions.push(p1);

    var rb = i/this.joints.length;
    //var c = new Vector4(rb * 0.5, 0.0, rb, 1.0);
    var c = new Vector4(0, rb, 0, 1.0);

    this.mesh.colors.push(c);
    this.mesh.colors.push(c);
  }

  //add effector!
  this.mesh.positions.push(this.effectorPosition.clone().add(new Vector3(0,-1,0)));
  this.mesh.positions.push(this.effectorPosition.clone().add(new Vector3(0,1,0)));
  this.mesh.positions.push(this.effectorPosition.clone().add(new Vector3(0,0,-1)));
  this.mesh.positions.push(this.effectorPosition.clone().add(new Vector3(0,0,1)));
  this.mesh.positions.push(this.effectorPosition.clone().add(new Vector3(-1,0,0)));
  this.mesh.positions.push(this.effectorPosition.clone().add(new Vector3(1,0,0)));
  this.mesh.colors.push(new Vector4(1.0, 0.0, 0.0, 1.0));
  this.mesh.colors.push(new Vector4(1.0, 0.0, 0.0, 1.0));
  this.mesh.colors.push(new Vector4(1.0, 0.0, 0.0, 1.0));
  this.mesh.colors.push(new Vector4(1.0, 0.0, 0.0, 1.0));
  this.mesh.colors.push(new Vector4(1.0, 0.0, 0.0, 1.0));
  this.mesh.colors.push(new Vector4(1.0, 0.0, 0.0, 1.0));

  this.mesh.primitiveType = this.gl.LINES;

  if(this.mesh.vertexBuffer instanceof WebGLBuffer){
    this.mesh.updateBuffers();
  } else {
    this.mesh.constructBuffers();
  }

};

CCD.prototype.animateEffector = function(time){
  this.effectorPosition = new Vector3(0,15,8);
  var radius = 20.0;
  var horizOffset =  Math.sin(time);
  var vertOffset = Math.cos(time);
  var depthOffset = Math.cos(time);
  this.effectorPosition.x += horizOffset * radius;
  //this.effectorPosition.y += vertOffset * radius;
  //this.effectorPosition.z += depthOffset * radius;
}

CCD.prototype.animate = function(time){
  this.animateEffector(time);

  for( var i = 0; i < this.joints.length; i++ ) {
    var joint = this.joints[i];
    var trans = joint.animationTranslations[0].clone();
    var rotEuler = joint.animationRotations[0].clone();
    var rot = new Quaternion();
    rot.fromEulerAngles(rotEuler);
    rot.normalize();

    if(i == 0){
      var pos0 = new Vector3(0,0,0);
      /*
      var pm = new Matrix44();
      if(joint.parentID > -1){
        pm = this.joints[joint.parentID].animationWorldBases[0];
        pos0 = new Vector3(pm.m[12], pm.m[13], pm.m[14]);
      }
      var mtx = joint.animationWorldBases[0];
      var pos1 = new Vector3(mtx.m[12], mtx.m[13], mtx.m[14]);
      var dir = pos1.subtract(pos0).normalize();
      */
      var mtx = joint.animationWorldBases[0];
      //var translation = new Vector3(mtx.m[12], mtx.m[13], mtx.m[14]);
      var dir = new Vector3(0,0,1);
      dir.transformDirection(mtx).normalize();
      pos0.transform(mtx);

      var localEffPos = this.effectorPosition.clone();//.transform(pm.clone().invert());
      var dirToEffector = localEffPos.subtract(pos0).normalize();
      //var axisAngle = dir.getRotationToAlign(dirToEffector);
      rot.rotationTo(dir,dirToEffector);

      //TODO: FIND INSTABILITY
      //THis is stable so the above code has an instability!
      rot.identity();
      rot.rotateX(Math.PI*0.5);
      rot.rotateY(Math.sin(-time) + 1*Math.PI);
      //console.debug(rot);
    }
    this.calculateJoint(0, joint, trans, rot);

  }
  this.calculateMesh();
};

CCD.prototype.calculateJoint = function(frame, joint, translation, rotation){
  var jointID = joint.id;
  //var mat = joint.animationCombinedBases[frame];

  var targetMatrix = joint.currentMatrices[frame];
  var animPose = joint.animationWorldBases[frame];
  if( joint.parentID != -1 ) {
    this.joints[joint.parentID].animationWorldBases[frame].copyInto(animPose);
  } else {
    animPose.identity();
  }

  animPose.translate(translation.x, translation.y, translation.z);
  animPose.rotate(rotation);

  /*
  animPose.copyInto(mat);
  mat.preMultiply(this.referencePose[jointID].referencePoseWorldToLocal.m);

  joint.currentMatrices[frame] = mat.clone();
  */
};

CCD.prototype.drawDebug = function(projMat, time){

  if(this.mesh.vertexBuffer instanceof WebGLBuffer){

    this.material.bind(this.mesh);
    //this.mesh.bind(this.material.shader);
    this.material.setUniforms(
        this.transform.matrix.m,
        this.transform.inverse.m,
        this.transform.inverseTranspose.m,
        projMat.m,
        time
        );
    this.gl.drawArrays(
        this.mesh.primitiveType,
        0,
        this.mesh.numItems
        );
  }
}

CCD.prototype.setupMaterial = function(gl){
  var fsSource="  precision mediump float;\n";
  fsSource +="\n";
  fsSource +="    varying vec4 vPosition;\n";
  fsSource +="    varying vec2 vUV;\n";
  fsSource +="    varying vec3 vNormal;\n";
  fsSource +="    varying vec3 vTangent;\n";
  fsSource +="    varying vec3 vBitangent;\n";
  fsSource +="    varying vec4 vVertColor;\n";
  fsSource +="\n";
  fsSource +="    uniform float uTime;\n";
  fsSource +="    uniform mat4 uMVMatrix;\n";
  fsSource +="\n";
  fsSource +="    void main(void) {\n";
  fsSource +="      gl_FragColor = vVertColor;\n";
  fsSource +="    }\n";

  var vsSource="  precision mediump float;\n";
  vsSource +="    attribute vec3 aVertexPosition;\n";
  vsSource +="    attribute vec3 aVertexNormal;\n";
  vsSource +="    attribute vec2 aVertexUV;\n";
  vsSource +="    attribute vec4 aVertexTangent;\n";
  vsSource +="    attribute vec4 aVertexColor;\n";
  vsSource +="\n";
  vsSource +="    uniform mat4 uMVMatrix;\n";
  vsSource +="    uniform mat4 uInverse;\n";
  vsSource +="    uniform mat4 uInverseTranspose;\n";
  vsSource +="    uniform mat4 uPMatrix;\n";
  vsSource +="    uniform float uTime;\n";
  vsSource +="\n";
  vsSource +="    varying vec4 vPosition;\n";
  vsSource +="    varying vec2 vUV;\n";
  vsSource +="    varying vec3 vNormal;\n";
  vsSource +="    varying vec3 vTangent;\n";
  vsSource +="    varying vec3 vBitangent;\n";
  vsSource +="    varying vec4 vVertColor;\n";
  vsSource +="\n";
  vsSource +="    void main(void) {\n";
  vsSource +="        vPosition = uMVMatrix * vec4(aVertexPosition,1.0);\n";
  //vsSource +="        vPosition = vec4(aVertexPosition,1.0);\n";
  vsSource +="        vVertColor = aVertexColor;\n";
  vsSource +="        vUV = aVertexUV.xy;\n";
  vsSource +="        vNormal = aVertexNormal.xyz;\n";
  vsSource +="        vTangent = aVertexTangent.xyz;\n";
  vsSource +="        gl_Position = uPMatrix * vPosition;\n";
  vsSource +="    }\n";

  this.material.shader.initShaderWithSource(fsSource,vsSource);
  this.material.zTest = false;
  this.material.zWrite = false;
  this.material.lineWidth = 3.0;

};

<|endoftext|>