<commit_before>
'use strict';

const _ = require('lodash');
const Script = require('smooch-bot').Script;

const scriptRules = require('./script.json');

var myDate = new Date();
var groet = '';

/* hour is before noon */
if ( myDate.getHours() < 12 )
{
groet = "Goeiemorgen 🌝";
}
else  /* Hour is from noon to 5pm (actually to 5:59 pm) */
if ( myDate.getHours() >= 12 && myDate.getHours() <= 17 )
{
groet = "Goedendag 🌞";
}
else  /* the hour is after 5pm, so it is between 6pm and midnight */
if ( myDate.getHours() > 17 && myDate.getHours() <= 24 )
{
groet = "Goedenavond 🌙";
}
else
if (myDate.getHours() > 20  || myDate.getHours() <= 8 )
{
  groet = "Goedenavond 🌙  Bedankt voor je bezoek maar op dit moment is Independer echter gesloten. 🕘 Uiteraard kun je met onze IndyBot verder praten maar er is helaas niemand die jouw vraag specifiek kan beantwoorden. Je kan je vraag ook doormailen 📩 naar info@independer. Dan komt het altijd goed.";
}
else  /* the hour is not between 0 and 24, so something is wrong */
{
groet = "Welkom. ";
}

function wait(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}

module.exports = new Script({

 processing: {
//prompt: (bot) => bot.say('...'),
 receive: () => 'processing'
 },

start: {
    receive: (bot,message) => {
        const opening = message.text.trim().toUpperCase();
        return bot.say(`${groet}... Wat voor soort hypotheek zoek je? `)
        .then(() => bot.say(`![](http://www.bieg.nl/beeld/woningen.jpg)`))
        .then(() => bot.say(`%[Starters Hypotheek](postback:hypotheektype_starter) %[Nieuwe hypotheek](postback:hypotheektype_nieuw) %[Hypotheek oversluiten](postback:hypotheektype_oversluiten)`))
        .then(() => 'selecteerHypotheek');
    }
},

selecteerHypotheek: {
    receive: (bot, message) => {
      switch(message.text) {
      case 'Hoi':
            return bot.say(`${groet} waar ben je naar op zoek? %[Starters hypotheek](postback:hypotheektype_starter) %[Nieuwe hypotheek](postback:hypotheektype_nieuw) %[Hypotheek oversluiten](postback:hypotheektype_oversluiten)`)
            .then(() => 'askName')
          break;
      case 'Starters Hypotheek':
          return bot.say(`Wat voor type woning zoek je? `)
          .then(() => bot.say(`%[🏬 Appartement](postback:hypotheekkeuze_appartement) %[🏠 Huis](postback:hypotheekkeuze_huis) %[📭 Vakantiewoning](postback:hypotheekkeuze_vakantiewoning)`))
          .then(() => 'woningType')
              break;
        case 'Nieuwe hypotheek':
          return bot.say(`😞 Helaas biedt Independer momenteel alleen Starters een hypotheek aan.`)
          .then(() => bot.say(`Via onderstaande link kun je de beste hypotheekadviseur voor jou vinden. %[💼 Zoek Hypotheek Adviseur](https://www.independer.nl/hypotheekadviseur/jelocatie.aspx)`))
            .then(() => 'finish')
          break;
        case 'Hypotheek oversluiten':
          return bot.say(`😟 Het spijt me maar op dit moment biedt Independer alleen  Starters een hypotheek.`)
          .then(()=> bot.say(`Als het allemaal wel zo ver is, wil je dan een update ontvangen? %[Ja, dat wil ik wel](postback:update_ja) %[Nee, dat hoeft niet](postback:update_nee)`))
            .then(() => 'updateOntvangen')
          break;
        default:
          return bot.say(`![](http://www.bieg.nl/beeld/speechbubble.gif)`)
            .then(() => 'processing')
          break;
      }
    }
},

updateOntvangen: {
    receive: (bot, message) => {
      switch(message.text) {
        case 'Ja, dat wil ik wel':
            return bot.say(`👍 Leuk, dan houd ik  je op de hoogte zodra er weer nieuws is.`)
            .then(() => 'update_ja');
          break;
          case 'Nee, dat hoeft niet':
              receive: () => 'bye'
              break;
          default:
            return bot.say('![](http://www.bieg.nl/beeld/speechbubble.gif)')
              .then(() => 'processing')
            break;
}
}
},

update_ja: {
  prompt: (bot) => bot.say('Wat is je email adres?'),
      receive: (bot, message) => {
          const emailVisitor=message.text.trim();
          return bot.setProp('emailVisitor', emailVisitor)
              .then(()  => bot.say(`Ok - dan hou ik je via ✉ ${emailVisitor} op de hoogte.`))
              .then(()  =>'lastCheck')
    }
},
update_nee: {
  receive: () => 'bye'
},

hypotheekkeuze_appartement: {
receive: (bot,message)  => {
    //  prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`)
    receive: () => 'askName'
}
},
hypotheekkeuze_huis: {
//    prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`)
  receive: () => 'askName'
},
hypotheekkeuze_vakantiewoning: {
//    prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`)
    receive: () => 'askName'
},
hypotheekStarter: {
    receive: () => 'askName'
},
hypotheektype_nieuw: {
    prompt: (bot) => bot.say('Independer biedt momenteel alleen voor Starters een hypotheek. Onderstaande link bied je meer informatie %[Hypotheek Adviseur](https://www.independer.nl/hypotheekadviseur/intro.aspx)'),
    receive: () => 'processing'
},

woningType: {
  receive: (bot, message) => {
    switch(message.text) {
        case '🏬 Appartement':
          return bot.say(`Nice!`)
          .then(() => 'vervolgVragen')
          break;
      case '🏠 Huis':
          return bot.say(`Leuk`)
          .then(() => 'vervolgVragen')
          break;
    case '📭 Vakantiewoning':
          return bot.say(`Gezellig`)
          .then(() => 'vervolgVragen')
          break;
      default:
        return bot.say('![](http://www.bieg.nl/beeld/speechbubble.gif)')
          .then(() => 'processing')
        break;
        }
    }
},

vervolgVragen: {
  prompt: (bot) => bot.say('Hoe heet je eigelijk? Dat maakt het praten een stuk makkelijker...'),
  receive: (bot, message) => {
      const name = message.text;
      return bot.setProp('name', name)
          .then(() => bot.say(`Hoi ${name}. 📋 Ik heb nog wat vragen voor je om verder te kunnen.`))
          .then(() => 'lastCheck');
    }
},

lastCheck: {
    prompt: (bot) => bot.say(' Is er nog iets waar ik  je bij kan helpen?  🚦  %[Ja, nou je het zegt ](postback:speak) %[Nee hoor](postback:bye)'),
          receive: (bot, message) => {
            switch(message.text) {
              case 'Nee hoor':
                  receive: ()  => 'bye'
                  break;
             case 'Ja':
                  receive: () => 'speak'
                  break;
            case 'Nee':
                  receive: () => 'bye'
                  break;
            default:
              return bot.say('![](http://www.bieg.nl/beeld/speechbubble.gif)')
                .then(() => 'processing')
              break;
            }
        }
},

bye: {
    prompt: (bot) => bot.say('Fijn je gesproken te hebben. Bedankt voor je tijd ⏲'),
    receive: ()  => 'finish'
},

// error: {
// prompt: (bot) => bot.say('Sorry - kun je dat nog eens zeggen?  Er ging iets mis...'),
// receive: () => ''
// },

finish: {
receive: () => 'finish'
},

  speak: {
          receive: (bot, message) => {

              let upperText = message.text.trim().toUpperCase();

              function updateSilent() {
                  switch (upperText) {
                      case "CONNECT ME":
                          return bot.setProp("silent", true);
                      case "DISCONNECT":
                          return bot.setProp("silent", false);
                      default:
                          return Promise.resolve();
                  }
              }

              function getSilent() {
                  return bot.getProp("silent");
              }

              function processMessage(isSilent) {
                  if (isSilent) {
                      return Promise.resolve("speak");
                  }

                  if (!_.has(scriptRules, upperText)) {
                      return bot.say(`So, I'm good at structured conversations but stickers, emoji and sentences still confuse me. Say 'more' to chat about something else.`).then(() => 'speak');
                  }

                  var response = scriptRules[upperText];
                  var lines = response.split('\n');

                  var p = Promise.resolve();
                  _.each(lines, function(line) {
                      line = line.trim();
                      p = p.then(function() {
                          console.log(line);
                          return wait(50).then(function() {
                              return bot.say(line);
                          });
                      });
                  });

                  return p.then(() => 'speak');
              }

              return updateSilent()
                  .then(getSilent)
                  .then(processMessage);
          }
      }
});
<commit_msg>script<commit_after>
'use strict';

const _ = require('lodash');
const Script = require('smooch-bot').Script;

const scriptRules = require('./script.json');

var myDate = new Date();
var groet = '';

/* hour is before noon */
if ( myDate.getHours() < 12 )
{
groet = "Goeiemorgen 🌝";
}
else  /* Hour is from noon to 5pm (actually to 5:59 pm) */
if ( myDate.getHours() >= 12 && myDate.getHours() <= 17 )
{
groet = "Goedendag 🌞";
}
else  /* the hour is after 5pm, so it is between 6pm and midnight */
if ( myDate.getHours() > 17 && myDate.getHours() <= 24 )
{
groet = "Goedenavond 🌙";
}
else
if (myDate.getHours() > 20  || myDate.getHours() <= 8 )
{
  groet = "Goedenavond 🌙  Bedankt voor je bezoek maar op dit moment is Independer echter gesloten. 🕘 Uiteraard kun je met onze IndyBot verder praten maar er is helaas niemand die jouw vraag specifiek kan beantwoorden. Je kan je vraag ook doormailen 📩 naar info@independer. Dan komt het altijd goed.";
}
else  /* the hour is not between 0 and 24, so something is wrong */
{
groet = "Welkom. ";
}

function wait(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}

module.exports = new Script({

 processing: {
//prompt: (bot) => bot.say('...'),
 receive: () => 'processing'
 },

start: {
    receive: (bot,message) => {
        const opening = message.text.trim().toUpperCase();
        return bot.say(`${groet}... Wat voor soort hypotheek zoek je? `)
        .then(() => bot.say(`![](http://www.bieg.nl/beeld/woningen.jpg)`))
        .then(() => bot.say(`%[Starters Hypotheek](postback:hypotheektype_starter) %[Nieuwe hypotheek](postback:hypotheektype_nieuw) %[Hypotheek oversluiten](postback:hypotheektype_oversluiten)`))
        .then(() => 'selecteerHypotheek');
    }
},

selecteerHypotheek: {
    receive: (bot, message) => {
      switch(message.text) {
      case 'Hoi':
            return bot.say(`${groet} waar ben je naar op zoek? %[Starters hypotheek](postback:hypotheektype_starter) %[Nieuwe hypotheek](postback:hypotheektype_nieuw) %[Hypotheek oversluiten](postback:hypotheektype_oversluiten)`)
            .then(() => 'askName')
          break;
      case 'Starters Hypotheek':
          return bot.say(`Wat voor type woning zoek je? `)
          .then(() => bot.say(`%[🏬 Appartement](postback:hypotheekkeuze_appartement) %[🏠 Huis](postback:hypotheekkeuze_huis) %[📭 Vakantiewoning](postback:hypotheekkeuze_vakantiewoning)`))
          .then(() => 'woningType')
              break;
        case 'Nieuwe hypotheek':
          return bot.say(`😞 Helaas biedt Independer momenteel alleen Starters een hypotheek aan.`)
          .then(() => bot.say(`Via onderstaande link kun je de beste hypotheekadviseur voor jou vinden. %[💼 Zoek Hypotheek Adviseur](https://www.independer.nl/hypotheekadviseur/jelocatie.aspx)`))
            .then(() => 'finish')
          break;
        case 'Hypotheek oversluiten':
          return bot.say(`😟 Het spijt me maar op dit moment biedt Independer alleen  Starters een hypotheek.`)
          .then(()=> bot.say(`Als het allemaal wel zo ver is, wil je dan een update ontvangen? %[Ja, dat wil ik wel](postback:update_ja) %[Nee, dat hoeft niet](postback:update_nee)`))
            .then(() => 'updateOntvangen')
          break;
        default:
          return bot.say(`![](http://www.bieg.nl/beeld/speechbubble.gif)`)
            .then(() => 'processing')
          break;
      }
    }
},

updateOntvangen: {
    receive: (bot, message) => {
      switch(message.text) {
        case 'Ja, dat wil ik wel':
            return bot.say(`👍 Leuk, dan houd ik  je op de hoogte zodra er weer nieuws is.`)
            .then(() => 'update_ja');
          break;
          case 'Nee, dat hoeft niet':
              receive: () => 'bye'
              break;
          default:
            return bot.say('![](http://www.bieg.nl/beeld/speechbubble.gif)')
              .then(() => 'processing')
            break;
}
}
},

update_ja: {
  prompt: (bot) => bot.say('Wat is je email adres?'),
      receive: (bot, message) => {
          const emailVisitor=message.text.trim();
          return bot.setProp('emailVisitor', emailVisitor)
              .then(()  => bot.say(`Ok - dan hou ik je via ✉ ${emailVisitor} op de hoogte.`))
              .then(()  =>'lastCheck')
    }
},
update_nee: {
  receive: () => 'bye'
},

hypotheekkeuze_appartement: {
receive: (bot,message)  => {
    //  prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`)
    receive: () => 'askName'
}
},
hypotheekkeuze_huis: {
//    prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`)
  receive: () => 'askName'
},
hypotheekkeuze_vakantiewoning: {
//    prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`)
    receive: () => 'askName'
},
hypotheekStarter: {
    receive: () => 'askName'
},
hypotheektype_nieuw: {
    prompt: (bot) => bot.say('Independer biedt momenteel alleen voor Starters een hypotheek. Onderstaande link bied je meer informatie %[Hypotheek Adviseur](https://www.independer.nl/hypotheekadviseur/intro.aspx)'),
    receive: () => 'processing'
},

woningType: {
  receive: (bot, message) => {
    switch(message.text) {
        case '🏬 Appartement':
          return bot.say(`Nice!`)
          .then(() => 'vervolgVragen')
          break;
      case '🏠 Huis':
          return bot.say(`Leuk`)
          .then(() => 'vervolgVragen')
          break;
    case '📭 Vakantiewoning':
          return bot.say(`Gezellig`)
          .then(() => 'vervolgVragen')
          break;
      default:
        return bot.say('![](http://www.bieg.nl/beeld/speechbubble.gif)')
          .then(() => 'processing')
        break;
        }
    }
},

vervolgVragen: {
  prompt: (bot) => bot.say('Hoe heet je eigelijk? Dat maakt het praten een stuk makkelijker...'),
  receive: (bot, message) => {
      const name = message.text;
      return bot.setProp('name', name)
          .then(() => bot.say(`Hoi ${name}. 📋 Ik heb nog wat vragen voor je om verder te kunnen.`))
          .then(() => 'speak');
    }
},

lastCheck: {
    prompt: (bot) => bot.say(' Is er nog iets waar ik  je bij kan helpen?  🚦  %[Ja, nou je het zegt ](postback:speak) %[Nee hoor](postback:bye)'),
          receive: (bot, message) => {
            switch(message.text) {
              case 'Nee hoor':
                  receive: ()  => 'bye'
                  break;
             case 'Ja':
                  receive: () => 'speak'
                  break;
            case 'Nee':
                  receive: () => 'bye'
                  break;
            default:
              return bot.say('![](http://www.bieg.nl/beeld/speechbubble.gif)')
                .then(() => 'processing')
              break;
            }
        }
},

bye: {
    prompt: (bot) => bot.say('Fijn je gesproken te hebben. Bedankt voor je tijd ⏲'),
    receive: ()  => 'finish'
},

// error: {
// prompt: (bot) => bot.say('Sorry - kun je dat nog eens zeggen?  Er ging iets mis...'),
// receive: () => ''
// },

finish: {
receive: () => 'finish'
},

  speak: {
          receive: (bot, message) => {

              let upperText = message.text.trim().toUpperCase();

              function updateSilent() {
                  switch (upperText) {
                      case "CONNECT ME":
                          return bot.setProp("silent", true);
                      case "DISCONNECT":
                          return bot.setProp("silent", false);
                      default:
                          return Promise.resolve();
                  }
              }

              function getSilent() {
                  return bot.getProp("silent");
              }

              function processMessage(isSilent) {
                  if (isSilent) {
                      return Promise.resolve("speak");
                  }

                  if (!_.has(scriptRules, upperText)) {
                      return bot.say(`So, I'm good at structured conversations but stickers, emoji and sentences still confuse me. Say 'more' to chat about something else.`).then(() => 'speak');
                  }

                  var response = scriptRules[upperText];
                  var lines = response.split('\n');

                  var p = Promise.resolve();
                  _.each(lines, function(line) {
                      line = line.trim();
                      p = p.then(function() {
                          console.log(line);
                          return wait(50).then(function() {
                              return bot.say(line);
                          });
                      });
                  });

                  return p.then(() => 'speak');
              }

              return updateSilent()
                  .then(getSilent)
                  .then(processMessage);
          }
      }
});
<|endoftext|>


<commit_before>/**
 * Every converter need to supply the following methods:
 * addPart(orig, gloss) - Called everytime a new glossing entry should be added.
 *     orig contains the word in the original language, split into parts
 *     gloss contains the glossed version, split into parts
 * endLine(meaning) - Called once an entire sentence has been added.
 *     meaning contains the free translation of the sentence
 * finish() - Called once everything has been added. The time to display the result to the user.
 */

// Converts to reddit friendly markdown
var RedditConverter = function (output, smallCaps) {
	// Empty header row to sopport left alignment
	this.header = "|"
	// Markdown needs a middle row to seperate heading from content
	this.centerLine = "|";
	this.orig = "|";
	this.gloss    = "|";

	this.lines = "-----\n\n";

	this.useSmallCaps = smallCaps;
	this.output = output;
};
RedditConverter.prototype.addPart = function(orig, gloss) {
	this.orig += "***" + orig.join("") + "***";
	for (var i = 0; i < gloss.length; i += 1) {
		if (gloss[i].length > 1 && gloss[i] === gloss[i].toUpperCase()) {
			if (this.useSmallCaps) {
				this.gloss += "*_" + gloss[i].toLowerCase() + "_*";
			} else {
				this.gloss += gloss[i];
			}
		} else {
			this.gloss += gloss[i];
		}
	}

	this.header += "|";
	this.orig += "|";
	this.centerLine += ":-|";
	this.gloss += "|";
};
RedditConverter.prototype.endLine = function(meaning) {
	this.lines += this.header + "\n";
	this.lines += this.centerLine + "\n";
	this.lines += this.orig + "\n";
	this.lines += this.gloss + "\n";
	this.lines += "*" + meaning + "*" + "\n";
	this.lines += "\n-----\n\n";

	this.header = "|"
	this.centerLine = "|";
	this.orig = "|";
	this.gloss    = "|";
};
RedditConverter.prototype.finish = function() {
	this.output.html(this.lines);
};

var PlaintextConverter = function (output, smallCaps) {
	this.orig = "";
	this.gloss = "";

	this.lines = "";

	this.useSmallCaps = smallCaps;
	this.output = output;
};
PlaintextConverter.prototype.addPart = function(orig, gloss) {
	this.orig += orig.join("") + " ";
	for (var i = 0; i < gloss.length; i += 1) {
		if (gloss[i].length > 1 && gloss[i] === gloss[i].toUpperCase()) {
			if (this.useSmallCaps) {
				this.gloss += toUnicodeSmallCaps(gloss[i]);
			} else {
				this.gloss += gloss[i];
			}
		} else {
			this.gloss += gloss[i];
		}
	}
	this.gloss += " ";

	while (this.orig.length < this.gloss.length) {
		this.orig += " ";
	}
	while (this.gloss.length < this.orig.length) {
		this.gloss += " ";
	}
};
PlaintextConverter.prototype.endLine = function(meaning) {
	this.lines += this.orig + "\n";
	this.lines += this.gloss + "\n";
	this.lines += meaning + "\n";
	this.lines += "\n";

	this.orig = "";
	this.gloss    = "";
};
PlaintextConverter.prototype.finish = function() {
	this.output.html(this.lines);
};

function toUnicodeSmallCaps(input) {
	var table = [];
	table["A"] = "ᴀ";
	table["B"] = "ʙ";
	table["C"] = "ᴄ";
	table["D"] = "ᴅ";
	table["E"] = "ᴇ";
	table["F"] = "ꜰ";
	table["G"] = "ɢ";
	table["H"] = "ʜ";
	table["I"] = "ɪ";
	table["J"] = "ᴊ";
	table["K"] = "ᴋ";
	table["L"] = "ʟ";
	table["M"] = "ᴍ";
	table["N"] = "ɴ";
	table["O"] = "ᴏ";
	table["P"] = "ᴘ";
	// table["Q"] = "Q";
	table["R"] = "ʀ";
	table["S"] = "ꜱ";
	table["T"] = "ᴛ";
	table["U"] = "ᴜ";
	table["V"] = "ᴠ";
	table["W"] = "ᴡ";
	// table["X"] = "X";
	table["Y"] = "ʏ";
	table["Z"] = "ᴢ";

	var result = "";

	for (var i = 0; i < input.length; i++) {
		var c = input[i];
		if (c in table) {
			result += table[c];
		} else {
			result += c;
		}
	}

	return result;
}

function convertToReddit() {
	var output = $("<textarea id=\"output\" readonly></textarea>");
	var conv = new RedditConverter(output, $("#smallcaps").is(":checked"));
	convert(conv);
	$("#out").html("");
	output.appendTo("#out");
}
function convertToPlain() {
	var output = $("<textarea id=\"output\" readonly></textarea>");
	var conv = new PlaintextConverter(output, $("#smallcaps").is(":checked"));
	convert(conv);
	$("#out").html("");
	output.appendTo("#out");
}

// Splits a single glossing entry into it's parts
// "dog-ACC-PL" -> ["dog", "-", "ACC", "-", "PL"]
function splitEntry(entry) {
	var result = [];
	var word = "";
	for (var i = 0; i < entry.length; i++) {
		if (["-", "=", "."].indexOf(entry[i]) != -1) {
			result.push(word);
			word = "";
			result.push(entry[i]);
		} else {
			word += entry[i];
		}
	}
	if (!(word === "")) {
		result.push(word);
	}

	return result;
}

// Converts the text in the input field using a specified converter
function convert(converter) {
	var lines = $("#input").val().split("\n").map($.trim).filter(function(x) { return !(x === ""); });

	var i = 0;
	while (i < lines.length) {
		var orig = lines[i];
		i++; if (i >= lines.length) { alert("Uneven number of non-quoted lines"); break; }

		var gloss = lines[i];
		i++;

		var meaning = "";
		if (i < lines.length && ["'", "\""].indexOf(lines[i][0]) != -1) {
			meaning = lines[i];
			i++;
		}

		var origEntries = orig.split(" ").map($.trim).filter(function(x) { return !(x === ""); });
		var glossEntries = gloss.split(" ").map($.trim).filter(function(x) { return !(x === ""); });
		if (origEntries.length != glossEntries.length) {
			alert("Text and gloss have unequal number of parts!");
		}
		for (var a = 0; a < origEntries.length; a++) {
			converter.addPart(splitEntry(origEntries[a]), splitEntry(glossEntries[a]));
		}
		converter.endLine(meaning);
	}
	converter.finish();
}

$( window ).load(function() {
	$("#reddit").click(convertToReddit);
	$("#plain").click(convertToPlain);
});<commit_msg>Fixed some formatting issues<commit_after>/**
 * Every converter need to supply the following methods:
 * addPart(orig, gloss) - Called everytime a new glossing entry should be added.
 *     orig contains the word in the original language, split into parts
 *     gloss contains the glossed version, split into parts
 * endLine(meaning) - Called once an entire sentence has been added.
 *     meaning contains the free translation of the sentence
 * finish() - Called once everything has been added. The time to display the result to the user.
 */

var delimiters = ["-", "=", "."];

// Converts to reddit friendly markdown
var RedditConverter = function (output, smallCaps) {
	// Empty header row to sopport left alignment
	this.header = "|"
	// Markdown needs a middle row to seperate heading from content
	this.centerLine = "|";
	this.orig = "|";
	this.gloss    = "|";

	this.lines = "-----\n\n";

	this.useSmallCaps = smallCaps;
	this.output = output;
};
RedditConverter.prototype.addPart = function(orig, gloss) {
	this.orig += "***" + orig.join("") + "***";
	for (var i = 0; i < gloss.length; i += 1) {
		if (delimiters.indexOf(gloss[i]) == -1 && gloss[i] === gloss[i].toUpperCase()) {
			if (this.useSmallCaps) {
				this.gloss += "*_" + gloss[i].toLowerCase() + "_*";
			} else {
				this.gloss += gloss[i];
			}
		} else {
			this.gloss += gloss[i];
		}
	}

	this.header += "|";
	this.orig += "|";
	this.centerLine += ":-|";
	this.gloss += "|";
};
RedditConverter.prototype.endLine = function(meaning) {
	this.lines += this.header + "\n";
	this.lines += this.centerLine + "\n";
	this.lines += this.orig + "\n";
	this.lines += this.gloss + "\n";
	if (!(meaning === "")) {
		this.lines += "*" + meaning + "*" + "\n";
	}
	this.lines += "\n-----\n\n";

	this.header = "|"
	this.centerLine = "|";
	this.orig = "|";
	this.gloss    = "|";
};
RedditConverter.prototype.finish = function() {
	this.output.html(this.lines);
};

var PlaintextConverter = function (output, smallCaps) {
	this.orig = "";
	this.gloss = "";

	this.lines = "";

	this.useSmallCaps = smallCaps;
	this.output = output;
};
PlaintextConverter.prototype.addPart = function(orig, gloss) {
	this.orig += orig.join("") + " ";
	for (var i = 0; i < gloss.length; i += 1) {
		if (delimiters.indexOf(gloss[i]) == -1 && gloss[i] === gloss[i].toUpperCase()) {
			if (this.useSmallCaps) {
				this.gloss += toUnicodeSmallCaps(gloss[i]);
			} else {
				this.gloss += gloss[i];
			}
		} else {
			this.gloss += gloss[i];
		}
	}
	this.gloss += " ";

	while (this.orig.length < this.gloss.length) {
		this.orig += " ";
	}
	while (this.gloss.length < this.orig.length) {
		this.gloss += " ";
	}
};
PlaintextConverter.prototype.endLine = function(meaning) {
	this.lines += this.orig + "\n";
	this.lines += this.gloss + "\n";
	this.lines += meaning + "\n";
	this.lines += "\n";

	this.orig = "";
	this.gloss    = "";
};
PlaintextConverter.prototype.finish = function() {
	this.output.html(this.lines);
};

function toUnicodeSmallCaps(input) {
	var table = [];
	table["A"] = "ᴀ";
	table["B"] = "ʙ";
	table["C"] = "ᴄ";
	table["D"] = "ᴅ";
	table["E"] = "ᴇ";
	table["F"] = "ꜰ";
	table["G"] = "ɢ";
	table["H"] = "ʜ";
	table["I"] = "ɪ";
	table["J"] = "ᴊ";
	table["K"] = "ᴋ";
	table["L"] = "ʟ";
	table["M"] = "ᴍ";
	table["N"] = "ɴ";
	table["O"] = "ᴏ";
	table["P"] = "ᴘ";
	// table["Q"] = "Q";
	table["R"] = "ʀ";
	table["S"] = "ꜱ";
	table["T"] = "ᴛ";
	table["U"] = "ᴜ";
	table["V"] = "ᴠ";
	table["W"] = "ᴡ";
	// table["X"] = "X";
	table["Y"] = "ʏ";
	table["Z"] = "ᴢ";

	var result = "";

	for (var i = 0; i < input.length; i++) {
		var c = input[i];
		if (c in table) {
			result += table[c];
		} else {
			result += c;
		}
	}

	return result;
}

function convertToReddit() {
	var output = $("<textarea id=\"output\" readonly></textarea>");
	var conv = new RedditConverter(output, $("#smallcaps").is(":checked"));
	convert(conv);
	$("#out").html("");
	output.appendTo("#out");
}
function convertToPlain() {
	var output = $("<textarea id=\"output\" readonly></textarea>");
	var conv = new PlaintextConverter(output, $("#smallcaps").is(":checked"));
	convert(conv);
	$("#out").html("");
	output.appendTo("#out");
}

// Splits a single glossing entry into it's parts
// "dog-ACC-PL" -> ["dog", "-", "ACC", "-", "PL"]
function splitEntry(entry) {
	var result = [];
	var word = "";
	for (var i = 0; i < entry.length; i++) {
		if (delimiters.indexOf(entry[i]) != -1) {
			result.push(word);
			word = "";
			result.push(entry[i]);
		} else {
			word += entry[i];
		}
	}
	if (!(word === "")) {
		result.push(word);
	}

	return result;
}

// Converts the text in the input field using a specified converter
function convert(converter) {
	var lines = $("#input").val().split("\n").map($.trim).filter(function(x) { return !(x === ""); });

	var i = 0;
	while (i < lines.length) {
		var orig = lines[i];
		i++; if (i >= lines.length) { alert("Uneven number of non-quoted lines"); break; }

		var gloss = lines[i];
		i++;

		var meaning = "";
		if (i < lines.length && ["'", "\""].indexOf(lines[i][0]) != -1) {
			meaning = lines[i];
			i++;
		}

		var origEntries = orig.split(" ").map($.trim).filter(function(x) { return !(x === ""); });
		var glossEntries = gloss.split(" ").map($.trim).filter(function(x) { return !(x === ""); });
		if (origEntries.length != glossEntries.length) {
			alert("Text and gloss have unequal number of parts!");
		}
		for (var a = 0; a < origEntries.length; a++) {
			converter.addPart(splitEntry(origEntries[a]), splitEntry(glossEntries[a]));
		}
		converter.endLine(meaning);
	}
	converter.finish();
}

$( window ).load(function() {
	$("#reddit").click(convertToReddit);
	$("#plain").click(convertToPlain);
});<|endoftext|>


<commit_before>'use strict';

const Script = require('smooch-bot').Script;
const SefzigBot = "[SefzigBot] ";
const LinkBot = "[LinkBot] ";

module.exports = new Script({
    processing: {
        prompt: (bot) => bot.say(SefzigBot+'Nicht so schnell bitte...'),
        receive: () => 'processing'
    },

    start: {
        receive: (bot) => {
            return bot.say(SefzigBot+'Wenn Andreas gerade online ist, sieht er dieses Gespräch und kann beitreten.')
                .then(() => 'vorname'); /* <-- register */
        }
    },

    vorname: {
        prompt: (bot) => bot.say(SefzigBot+'Wie heissen Sie mit Vornamen?'),
        receive: (bot, message) => {
            var vorname = message.text;
            return bot.setProp('vorname', vorname)
                .then(() => bot.say(SefzigBot+`${vorname}, prima.`))
                .then(() => 'nachname');
        }
    },

    nachname: {
        prompt: (bot) => bot.say(SefzigBot+'Und mit Nachnamen?'),
        receive: (bot, message) => {
            var nachname = message.text;
            return bot.setProp('nachname', nachname)
                .then(() => bot.say(SefzigBot+`${nachname}, danke.`))
                .then(() => bot.say(SefzigBot+'Sie können hier jederzeit eine Nachricht an Andreas eingeben.'))
                .then(() => bot.say(SefzigBot+'Unterhalten Sie sich solange mit mir! Bitte schreiben Sie --bot:'))
                .then(() => 'register');
        }
    },

    register: {
        receive: (bot, message) => {

            var wollen = message.text;
            var befehl = wollen;
            befehl = befehl.trim();
            befehl = befehl.toUpperCase();

         // -----------------
         // System
         // -----------------

            if (befehl == "--BOT")            { bot.say(SefzigBot+'Ich weiß eine Menge über Andreas - und bin sein Ersatz für eine klassische Webseite. Rufen Sie mein Wissen durch Schreiben der mit -- beginnenden Wörter ab!');
                                                bot.say(SefzigBot+'Wollen Sie etwas über seine --Person oder --Neues von ihm erfahren? Oder auf anderem Wege --Kontakt  aufnehmen?'); }
            if (befehl == "--ABBRECHEN")      { bot.say(SefzigBot+'Text: Abbruch.'); }
            if (befehl == "--QRCODE")         { bot.say(SefzigBot+'Diesen Chat mobil öffnen: [Bild:https://zxing.org/w/chart?cht=qr&chs=200x200&chld=L&choe=UTF-8&chl=http%3A%2F%2Fsefzigbot.herokuapp.com%2F]'); }
            if (befehl == "--JAVASCRIPT")     { bot.say(SefzigBot+'[Javascript:test_alert]'); }

         // -----------------
         // Über mich
         // -----------------

            if (befehl == "--PERSON")         { bot.say(SefzigBot+'Andreas ist 38 Jahre alt und lebt in Hamburg. Hier sein --Lebenslauf und ein --Foto.'); }
            if (befehl == "--LEBENSLAUF")     { bot.say(SefzigBot+'Sein Lebenslauf als druckbares PDF-Dokument: %[Lebenslauf.pdf](http://sefzig.net/text/seiten/Lebenslauf/dateien/Andreas_Sefzig_Lebenslauf.pdf)');
                                                bot.say(SefzigBot+'Tabellarisches und ausformuliertes CV: %[Lebenslauf öffnen](http://sefzig.net/link/Lebenslauf/)'); }
            if (befehl == "--FOTO")           { bot.say(SefzigBot+'[Bild:http://sefzig.net/text/seiten/SefzignetStartseite/dateien/SefzignetStartseiteFotoLogos.png] Andreas Sefzig mit Logo'); }
            if (befehl == "--NEUES")          { bot.say(SefzigBot+'Text: Neues.'); }
            if (befehl == "--VIDEO")          { bot.say(SefzigBot+'[Youtube:u07XONlDwX8]'); }

         // -----------------
         // Links
         // -----------------

            if (befehl == "--LINKS")          { bot.say(LinkBot+'Andreas speichert interessante Links für sich und andere: %[Linkliste öffnen](http://sefzig.net/link/liste/)');
                                                bot.say(LinkBot+'URLs der Link-Verwaltung: --LinkEingabe, --LinkListe, --LinkEinrichten, --LinkAdmin, --LinkUber.'); }
            if (befehl == "--LINKEINGABE")    { bot.say(LinkBot+'Link: Eingabe.'); }
            if (befehl == "--LINKLISTE")      { bot.say(LinkBot+'Link: Liste.'); }
            if (befehl == "--LINKEINRICHTEN") { bot.say(LinkBot+'Link: Einrichten.'); }
            if (befehl == "--LINKADMIN")      { bot.say(LinkBot+'Link: Administration.'); }
            if (befehl == "--LINKUBER")       { bot.say(LinkBot+'Link: Über.'); }

         // -----------------
         // Kontakt
         // -----------------

            if (befehl == "--KONTAKT")        { bot.say(SefzigBot+'Sie erreichen Andreas über andreas@sefzig.net, in seinem --Slackteam, auf --Twitter und auf --Xing. %[Kontakt-Seite öffnen](http://sefzig.net/link/Kontakt/)'); }
            if (befehl == "--SLACKTEAM")      { bot.say(SefzigBot+'Andreas betreibt ein offenes Slack-Team, in dem man sich über Marketing-Technologie unterhält. %[Slack-Team öffnen](http://sefzig.net/link/Slack/)'); }
            if (befehl == "--XING")           { bot.say(SefzigBot+'Andreas ist bei Xing: Er ist seit 2004 angemeldet und gehört mit über 500 Kontakten zu den 5% der bestvernetzten Mitglieder. %[Xing-Profil öffnen](http://sefzig.net/link/XingProfil/)');
                                                bot.say(SefzigBot+'[Bild:http://sefzig.net/text/seiten/SefzigBot/dateien/xing_vernetzt.png]'); }
            if (befehl == "--TWITTER")        { bot.say(SefzigBot+'Andreas ist auf Twitter: Er ist seit 2008 angemeldet, hat beinahe 500 Follower und sah sich kürzlich gezwungen, alle Tweets zu löschen: Neustart 2016. %[Twitter-Profil öffnen](http://sefzig.net/link/TwitterProfil/)');
                                                bot.say(SefzigBot+'Schreiben Sie einen Tweet über @sefzig: %[@sefzig twittern](http://sefzig.net/link/TwitterTweet/)'); }

         // -----------------
         // Vorlage
         // -----------------

            if (befehl == "--VORLAGE")        { bot.say(SefzigBot+'Text: Vorlage.'); }

         // .then(function(){ bot.say(''); })
            return bot.setProp('wollen', wollen)
                .then(() => 'register');
        }
    },

    finish: {
        receive: (bot, message) => {
            return bot.getProp('name')
                .then(() => 'finish');
        }
    }
});
<commit_msg>Linklisten<commit_after>'use strict';

const Script = require('smooch-bot').Script;
const SefzigBot = "[SefzigBot] ";
const LinkBot = "[LinkBot] ";

module.exports = new Script({
    processing: {
        prompt: (bot) => bot.say(SefzigBot+'Nicht so schnell bitte...'),
        receive: () => 'processing'
    },

    start: {
        receive: (bot) => {
            return bot.say(SefzigBot+'Wenn Andreas gerade online ist, sieht er dieses Gespräch und kann beitreten.')
                .then(() => 'vorname'); /* <-- register */
        }
    },

    vorname: {
        prompt: (bot) => bot.say(SefzigBot+'Wie heissen Sie mit Vornamen?'),
        receive: (bot, message) => {
            var vorname = message.text;
            return bot.setProp('vorname', vorname)
                .then(() => bot.say(SefzigBot+`${vorname}, prima.`))
                .then(() => 'nachname');
        }
    },

    nachname: {
        prompt: (bot) => bot.say(SefzigBot+'Und mit Nachnamen?'),
        receive: (bot, message) => {
            var nachname = message.text;
            return bot.setProp('nachname', nachname)
                .then(() => bot.say(SefzigBot+`${nachname}, danke.`))
                .then(() => bot.say(SefzigBot+'Sie können hier jederzeit eine Nachricht an Andreas eingeben.'))
                .then(() => bot.say(SefzigBot+'Unterhalten Sie sich solange mit mir! Bitte schreiben Sie --bot:'))
                .then(() => 'register');
        }
    },

    register: {
        receive: (bot, message) => {

            var wollen = message.text;
            var befehl = wollen;
            befehl = befehl.trim();
            befehl = befehl.toUpperCase();

         // -----------------
         // System
         // -----------------

            if (befehl == "--BOT")            { bot.say(SefzigBot+'Ich weiß eine Menge über Andreas - und bin sein Ersatz für eine klassische Webseite. Rufen Sie mein Wissen durch Schreiben der mit -- beginnenden Wörter ab!');
                                                bot.say(SefzigBot+'Wollen Sie etwas über seine --Person oder --Neues von ihm erfahren? Oder auf anderem Wege --Kontakt  aufnehmen?'); }
            if (befehl == "--ABBRECHEN")      { bot.say(SefzigBot+'Text: Abbruch.'); }
            if (befehl == "--QRCODE")         { bot.say(SefzigBot+'Diesen Chat mobil öffnen: [Bild:https://zxing.org/w/chart?cht=qr&chs=200x200&chld=L&choe=UTF-8&chl=http%3A%2F%2Fsefzigbot.herokuapp.com%2F]'); }
            if (befehl == "--JAVASCRIPT")     { bot.say(SefzigBot+'[Javascript:test_alert]'); }

         // -----------------
         // Über mich
         // -----------------

            if (befehl == "--PERSON")         { bot.say(SefzigBot+'Andreas ist 38 Jahre alt und lebt in Hamburg. Hier sein --Lebenslauf und ein --Foto.'); }
            if (befehl == "--LEBENSLAUF")     { bot.say(SefzigBot+'Sein Lebenslauf als druckbares PDF-Dokument: %[Lebenslauf.pdf](http://sefzig.net/text/seiten/Lebenslauf/dateien/Andreas_Sefzig_Lebenslauf.pdf)');
                                                bot.say(SefzigBot+'Tabellarisches und ausformuliertes CV: %[Lebenslauf öffnen](http://sefzig.net/link/Lebenslauf/)'); }
            if (befehl == "--FOTO")           { bot.say(SefzigBot+'[Bild:http://sefzig.net/text/seiten/SefzignetStartseite/dateien/SefzignetStartseiteFotoLogos.png] Andreas Sefzig mit Logo'); }
            if (befehl == "--NEUES")          { bot.say(SefzigBot+'Text: Neues.'); }
            if (befehl == "--VIDEO")          { bot.say(SefzigBot+'[Youtube:u07XONlDwX8]'); }

         // -----------------
         // Links
         // -----------------

            if (befehl == "--LINKS")          { bot.say(LinkBot+'Andreas speichert interessante Links für sich und andere: %[Linkliste öffnen](http://sefzig.net/link/liste/)');
                                                bot.say(LinkBot+'URLs der Link-Verwaltung: --LinkEingabe, --LinkListe, --LinkEinrichten, --LinkAdmin, --LinkUber.'); }
            if (befehl == "--LINKEINGABE")    { bot.say(LinkBot+'Eingabemaske für einen neuen Link: %[Link eigeben](http://sefzig.net/link/)'); }
            if (befehl == "--LINKLISTE")      { bot.say(LinkBot+'Andreas allgemeine Linkliste: %[Link eigeben](http://sefzig.net/link/)');
                                                bot.say(LinkBot+'Empfohlene Linklisten: --LinksWerkzeuge, --LinksDemo, --LinksInnovation, --LinksRtm, --LinksAnhang'); }
            if (befehl == "--LINKEINRICHTEN") { bot.say(LinkBot+'Link: Einrichten.'); }
            if (befehl == "--LINKADMIN")      { bot.say(LinkBot+'Link: Administration.'); }
            if (befehl == "--LINKUBER")       { bot.say(LinkBot+'Link: Über.'); }

         // -----------------
         // Kontakt
         // -----------------

            if (befehl == "--KONTAKT")        { bot.say(SefzigBot+'Sie erreichen Andreas über andreas@sefzig.net, in seinem --Slackteam, auf --Twitter und auf --Xing. %[Kontakt-Seite öffnen](http://sefzig.net/link/Kontakt/)'); }
            if (befehl == "--SLACKTEAM")      { bot.say(SefzigBot+'Andreas betreibt ein offenes Slack-Team, in dem man sich über Marketing-Technologie unterhält. %[Slack-Team öffnen](http://sefzig.net/link/Slack/)'); }
            if (befehl == "--XING")           { bot.say(SefzigBot+'Andreas ist bei Xing: Er ist seit 2004 angemeldet und gehört mit über 500 Kontakten zu den 5% der bestvernetzten Mitglieder. %[Xing-Profil öffnen](http://sefzig.net/link/XingProfil/)');
                                                bot.say(SefzigBot+'[Bild:http://sefzig.net/text/seiten/SefzigBot/dateien/xing_vernetzt.png]'); }
            if (befehl == "--TWITTER")        { bot.say(SefzigBot+'Andreas ist auf Twitter: Er ist seit 2008 angemeldet, hat beinahe 500 Follower und sah sich kürzlich gezwungen, alle Tweets zu löschen: Neustart 2016. %[Twitter-Profil öffnen](http://sefzig.net/link/TwitterProfil/)');
                                                bot.say(SefzigBot+'Schreiben Sie einen Tweet über @sefzig: %[@sefzig twittern](http://sefzig.net/link/TwitterTweet/)'); }

         // -----------------
         // Vorlage
         // -----------------

            if (befehl == "--VORLAGE")        { bot.say(SefzigBot+'Text: Vorlage.'); }

         // .then(function(){ bot.say(''); })
            return bot.setProp('wollen', wollen)
                .then(() => 'register');
        }
    },

    finish: {
        receive: (bot, message) => {
            return bot.getProp('name')
                .then(() => 'finish');
        }
    }
});
<|endoftext|>


<commit_before>var username;
$(document).on('ready', function(){
  usernameInputInit()

})

function usernameInputInit(){
  var $input = $('.js-username-input')
  $input.focus();
  $input.on('keydown', function(e){
    if(e.which == 13) {
      username = $(this).val();
      $('.UserSelect').addClass('s-hidden');
      $('.js-search').focus();
      getGists();
    }
  })
}

function getGists(){
  $.ajax({
    url: `https://api.github.com/users/${username}/gists`
  })
  .done(function(data){
    generateLinks(data)

    var options = {
      valueNames: [ 'Gist-link']
    };
    var userList = new List('gists', options);
  })
}

function generateLinks(gists){
  $.each(gists, function(i, gist){
    var gistObj = gist.files[Object.keys(gist.files)[0]]
    // console.log(gistObj);
    generateLink(gistObj.filename, gistObj.raw_url)
  })
}

function generateLink(name, url){
  var $li = $('
');
  var $a = $('' + name + '')
    .attr('href', url)
    .attr('target', '_blank')
    .addClass('Gist-link');
  $li.append($a);
  $('.list').append($li);
}
<commit_msg>Skip username if got localstorage<commit_after>var username;
$(document).on('ready', function(){
  usernameInit()
})

function usernameInit(){
  if(localStorage.username){
    showGistPage();
    return;
  }
  var $input = $('.js-username-input')
  $input.focus();
  $input.on('keydown', function(e){
    if(e.which == 13) {
      username = $(this).val();
      localStorage.username = username;
      showGistPage();
    }
  })
}

function showGistPage(){
  $('.UserSelect').addClass('s-hidden');
  $('.js-search').focus();
  getGists();
}

function getGists(){
  $.ajax({
    url: `https://api.github.com/users/${localStorage.username}/gists`
  })
  .done(function(data){
    generateLinks(data)

    var options = {
      valueNames: [ 'Gist-link']
    };
    var userList = new List('gists', options);
  })
}

function generateLinks(gists){
  $.each(gists, function(i, gist){
    var gistObj = gist.files[Object.keys(gist.files)[0]]
    // console.log(gistObj);
    generateLink(gistObj.filename, gistObj.raw_url)
  })
}

function generateLink(name, url){
  var $li = $('
');
  var $a = $('' + name + '')
    .attr('href', url)
    .attr('target', '_blank')
    .addClass('Gist-link');
  $li.append($a);
  $('.list').append($li);
}
<|endoftext|>


<commit_before>$(document).ready(function() {

});<commit_msg>Delete script.js<commit_after><|endoftext|>


<commit_before>'use strict';

const Script = require('smooch-bot').Script;

module.exports = new Script({
    processing: {
        prompt: (bot) => bot.say('Beep boop...'),
        receive: () => 'processing'
    },

    start: {
        receive: (bot) => {
            return bot.say('Hallo! ich bin Andreas Sefzigs Bot.')
                .then(() => bot.say('Wenn Andreas online ist, sieht er, was Sie schreiben und kann diesem Gespräch beitreten.'))
                .then(() => 'vorname');
        }
    },

    vorname: {
        prompt: (bot) => bot.say('Vielleicht darf ich Sie erstmal begrüßen: Wie heissen Sie mit Vornamen?'),
        receive: (bot, message) => {
            const vorname = message.text;
            return bot.setProp('vorname', vorname)
                .then(() => bot.say(`${vorname}, prima.`))
                .then(() => 'nachname');
        }
    },

    nachname: {
        prompt: (bot) => bot.say('Und mit Nachnamen?'),
        receive: (bot, message) => {
            const nachname = message.text;
            return bot.setProp('nachname', nachname)
                .then(() => bot.say(`${nachname}, danke.`))
                .then(() => 'register');
        }
    },

    register: {
        prompt: (bot) => bot.say('Schreiben Sie Andreas eine Nachricht oder unterhalten Sie sich mit mir über ihn, indem Sie --bot schreiben.'),
        receive: (bot, message) => {

            const wollen = message.text;
            var befehl = wollen;
            befehl = befehl.trim();
            befehl = befehl.toUpperCase();

            if (befehl == "--BOT")       { bot.say('Die Hilfe usw.'); }
            if (befehl == "--HALLO")     { bot.say('Begrussung und alles.'); }
            if (befehl == "--ABBRECHEN") { bot.say('Text zum Abbruch.'); }

            return bot.setProp('wollen', wollen)
                .then(() => 'register');
        }
    },

    finish: {
        receive: (bot, message) => {
            return bot.getProp('name')
                .then(() => 'finish');
        }
    }
});
<commit_msg>Tests<commit_after>'use strict';

const Script = require('smooch-bot').Script;

module.exports = new Script({
    processing: {
        prompt: (bot) => bot.say('Beep boop...'),
        receive: () => 'processing'
    },

    start: {
        receive: (bot) => {
            return bot.say('Hallo! ich bin Andreas Sefzigs Bot.')
                .then(() => bot.say('Wenn Andreas online ist, sieht er, was Sie schreiben und kann diesem Gespräch beitreten.'))
                .then(() => 'vorname');
        }
    },

    vorname: {
        prompt: (bot) => bot.say('Vielleicht darf ich Sie erstmal begrüßen: Wie heissen Sie mit Vornamen?'),
        receive: (bot, message) => {
            const vorname = message.text;
            return bot.setProp('vorname', vorname)
                .then(() => bot.say(`${vorname}, prima.`))
                .then(() => 'nachname');
        }
    },

    nachname: {
        prompt: (bot) => bot.say('Und mit Nachnamen?'),
        receive: (bot, message) => {
            const nachname = message.text;
            return bot.setProp('nachname', nachname)
                .then(() => bot.say(`${vorname} ${nachname}, danke.`))
                .then(() => 'register');
        }
    },

    register: {
        prompt: (bot) => bot.say('Schreiben Sie Andreas eine Nachricht oder unterhalten Sie sich mit mir über ihn, indem Sie --bot schreiben.'),
        receive: (bot, message) => {

            const wollen = message.text;
            var befehl = wollen;
            befehl = befehl.trim();
            befehl = befehl.toUpperCase();

            if (befehl == "--BOT")       { bot.say('Die Hilfe usw.'); }
            if (befehl == "--HALLO")     { bot.say('Begrussung und alles.'); }
            if (befehl == "--ABBRECHEN") { bot.say('Text zum Abbruch.'); }

            return bot.setProp('wollen', wollen)
                .then(() => 'register');
        }
    },

    finish: {
        receive: (bot, message) => {
            return bot.getProp('name')
                .then(() => 'finish');
        }
    }
});
<|endoftext|>


<commit_before>(function() {

	function run()
	{
		var current = AStarSearch.run(source, target, coord);

		// path not found
		if (!current) return;

		var path = findPath(current.path);
		var visited = findVisited(current.visited);

		for (let i = 0; i < visited.length; i++)
			coord[visited[i].x][visited[i].y] = 5;

		// traveling through the path
		for (let i = 1; i < path.length - 1; i++)
			coord[path[i].x][path[i].y] = 3;

		draw();
	}

	function findPath(node)
	{
		var path = [];
		while (node)
		{
			path.push({ "x": node.gridX, "y": node.gridY });
			node = node.parent;
		}
		console.log("path length: " + path.length);
		return path;
	}

	function findVisited(nodes)
	{
		var visited = [];
		for (let i = 0; i < nodes.length; i++)
		{
			let x = nodes[i].gridX;
			let y = nodes[i].gridY;
			if ( (x != target.x || y != target.y) &&
				 (x != source.x || y != source.y) )
				visited.push({ "x": x, "y": y });
		}
		return visited;
	}

	// fills map acoording to map array contents
	function draw()
	{
		drawSquare(1, 1, "red");
		for (let i = 0; i < 20; i++)
		{
			for (let j = 0; j < 20; j++)
			{
				let color = getColor(coord[i][j]);
				drawSquare(i, j, color);
			}
		}
	}

	function getColor(number)
	{
		switch (number)
		{
			// character - green
			case 1: return "#4caf50";
			// wall - red
			case 2: return "#f44336";
			// path
			case 3: return "lightgreen";
			// target - blue
			case 4: return "#2196F3";
			// visited squares
			case 5: return "#cdffcc";
			// empty square
			default: return "white";
		}
	}

	// fills a square at specified coordinate
	function drawSquare(x, y, color)
	{
		map.fillStyle = color;
		map.fillRect(2 + 15 * x, 2 + 15 * y, 13, 13);
	}

	// clears all squares of specific color
	function clearSquare(number)
	{
		for (let i = 0; i < 20; i++)
		{
			for (let j = 0; j < 20; j++)
			{
				if (coord[i][j] == number)
					coord[i][j] = 0;
			}
		}
	}

	// places a square on mouse location
	function placeSquare(e)
	{
		if (!mousedown)
			return;

		// obtaining coordinates
		var x = Math.ceil((e.clientX - mapElm.offsetLeft) / 15) - 1;
		var y = Math.ceil((e.clientY - mapElm.offsetTop) / 15) - 1;

		// preventing coordinates from going
		// out of bounds
		x = x > 19 ? 19 : x < 0 ? 0 : x;
		y = y > 19 ? 19 : y < 0 ? 0 : y;

		// can't erase source/target
		// can only have it's location changed
		if (target.x == x && target.y == y &&
			selected != 4 || selected != 1 &&
			source.x == x && source.y == y)
			return;

		// deleting old source/target
		// and changing to a new one
		if (selected == 4)
		{
			clearSquare(selected);
			target.x = x;
			target.y = y;
		}
		else if (selected == 1)
		{
			clearSquare(selected);
			source.x = x;
			source.y = y;
		}

		coord[x][y] = selected;
		draw();
	}

	function selectSquare(n)
	{
		var btn;
		switch(n)
		{
			case 0: btn = emptyBtn; break;
			case 1: btn = sourceBtn; break;
			case 2: btn = wallBtn; break;
			case 4: btn = targetBtn; break;
		}

		emptyBtn.style.borderColor = "#c3c3c3";
		sourceBtn.style.borderColor = "#c3c3c3";
		wallBtn.style.borderColor = "#c3c3c3";
		targetBtn.style.borderColor = "#c3c3c3";

		btn.style.borderColor = "#F57F17";
		selected = n;
	}

	// buttons
	var sourceBtn = document.getElementById("source");
	var targetBtn = document.getElementById("target");
	var wallBtn = document.getElementById("wall");
	var emptyBtn = document.getElementById("empty");
	var runBtn = document.getElementById("run");
	var clearBtn = document.getElementById("clear");
	var controlBtn = document.getElementById("controls");

	var selected = 0;
	var mousedown = false;

	// generating empty coordinates for the grid
	var coord = [];
	for (let i = 0; i < 20; i++)
	{
		coord[i] = [];
		for (let j = 0; j < 20; j++)
			coord[i][j] = 0;
	}

	var mapElm = document.getElementById("map");
	var map = mapElm.getContext("2d");

	// character
	var source = { "x": 0, "y": 0 };
	coord[source.x][source.y] = 1;
	// target
	var target = { "x": 19, "y": 19 };
	coord[target.x][target.y] = 4;

	draw();

	sourceBtn.onclick = () => {
		selectSquare(1);
	};
	targetBtn.onclick = () => {
		selectSquare(4);
	};
	wallBtn.onclick = () => {
		selectSquare(2);
	};
	emptyBtn.onclick = () => {
		selectSquare(0);
	};

	// runs the algorithm
	runBtn.onclick = () => {

		// cleans old path
		clearSquare(3);
		clearSquare(5);

		// searching a new one
		run();

	};

	// clears the map
	clearBtn.onclick = () => {
		clearSquare(2);
		clearSquare(3);
		draw();
	};

	controlBtn.onclick = () => {
		alert("1,2,3,4 - Select a Square \n" +
			  "Esc/Del - Clear all \n" +
			  "Enter/Space - Run");
	};

	// turns off square placement
	mapElm.onmouseup = e => { mousedown = false; };
	mapElm.onmouseout = e => { mousedown = false; };

	// turns on square placement
	mapElm.onmousedown = e => {
		mousedown = true;
		placeSquare(e);
	};

	mapElm.onmousemove = placeSquare;

	// controls
	document.onkeydown = e => {

		switch (e.keyCode)
		{
			// 1
			case 49:
				selectSquare(1);
				break;
			// 2
			case 50:
				selectSquare(4);
				break;
			// 3
			case 51:
				selectSquare(2);
				break;
			// 4
			case 52:
				selectSquare(0);
				break;
			// space
			case 32:
			// enter
			case 13:
				runBtn.click();
				break;
			// esc
			case 27:
			// del
			case 46:
				clearBtn.click();
				break;
		}
	}

})();
<commit_msg>added visited square removal on map clear<commit_after>(function() {

	function run()
	{
		var current = AStarSearch.run(source, target, coord);

		// path not found
		if (!current) return;

		var path = findPath(current.path);
		var visited = findVisited(current.visited);

		for (let i = 0; i < visited.length; i++)
			coord[visited[i].x][visited[i].y] = 5;

		// traveling through the path
		for (let i = 1; i < path.length - 1; i++)
			coord[path[i].x][path[i].y] = 3;

		draw();
	}

	function findPath(node)
	{
		var path = [];
		while (node)
		{
			path.push({ "x": node.gridX, "y": node.gridY });
			node = node.parent;
		}
		console.log("path length: " + path.length);
		return path;
	}

	function findVisited(nodes)
	{
		var visited = [];
		for (let i = 0; i < nodes.length; i++)
		{
			let x = nodes[i].gridX;
			let y = nodes[i].gridY;
			if ( (x != target.x || y != target.y) &&
				 (x != source.x || y != source.y) )
				visited.push({ "x": x, "y": y });
		}
		return visited;
	}

	// fills map acoording to map array contents
	function draw()
	{
		drawSquare(1, 1, "red");
		for (let i = 0; i < 20; i++)
		{
			for (let j = 0; j < 20; j++)
			{
				let color = getColor(coord[i][j]);
				drawSquare(i, j, color);
			}
		}
	}

	function getColor(number)
	{
		switch (number)
		{
			// character - green
			case 1: return "#4caf50";
			// wall - red
			case 2: return "#f44336";
			// path
			case 3: return "lightgreen";
			// target - blue
			case 4: return "#2196F3";
			// visited squares
			case 5: return "#cdffcc";
			// empty square
			default: return "white";
		}
	}

	// fills a square at specified coordinate
	function drawSquare(x, y, color)
	{
		map.fillStyle = color;
		map.fillRect(2 + 15 * x, 2 + 15 * y, 13, 13);
	}

	// clears all squares of specific color
	function clearSquare(number)
	{
		for (let i = 0; i < 20; i++)
		{
			for (let j = 0; j < 20; j++)
			{
				if (coord[i][j] == number)
					coord[i][j] = 0;
			}
		}
	}

	// places a square on mouse location
	function placeSquare(e)
	{
		if (!mousedown)
			return;

		// obtaining coordinates
		var x = Math.ceil((e.clientX - mapElm.offsetLeft) / 15) - 1;
		var y = Math.ceil((e.clientY - mapElm.offsetTop) / 15) - 1;

		// preventing coordinates from going
		// out of bounds
		x = x > 19 ? 19 : x < 0 ? 0 : x;
		y = y > 19 ? 19 : y < 0 ? 0 : y;

		// can't erase source/target
		// can only have it's location changed
		if (target.x == x && target.y == y &&
			selected != 4 || selected != 1 &&
			source.x == x && source.y == y)
			return;

		// deleting old source/target
		// and changing to a new one
		if (selected == 4)
		{
			clearSquare(selected);
			target.x = x;
			target.y = y;
		}
		else if (selected == 1)
		{
			clearSquare(selected);
			source.x = x;
			source.y = y;
		}

		coord[x][y] = selected;
		draw();
	}

	function selectSquare(n)
	{
		var btn;
		switch(n)
		{
			case 0: btn = emptyBtn; break;
			case 1: btn = sourceBtn; break;
			case 2: btn = wallBtn; break;
			case 4: btn = targetBtn; break;
		}

		emptyBtn.style.borderColor = "#c3c3c3";
		sourceBtn.style.borderColor = "#c3c3c3";
		wallBtn.style.borderColor = "#c3c3c3";
		targetBtn.style.borderColor = "#c3c3c3";

		btn.style.borderColor = "#F57F17";
		selected = n;
	}

	// buttons
	var sourceBtn = document.getElementById("source");
	var targetBtn = document.getElementById("target");
	var wallBtn = document.getElementById("wall");
	var emptyBtn = document.getElementById("empty");
	var runBtn = document.getElementById("run");
	var clearBtn = document.getElementById("clear");
	var controlBtn = document.getElementById("controls");

	var selected = 0;
	var mousedown = false;

	// generating empty coordinates for the grid
	var coord = [];
	for (let i = 0; i < 20; i++)
	{
		coord[i] = [];
		for (let j = 0; j < 20; j++)
			coord[i][j] = 0;
	}

	var mapElm = document.getElementById("map");
	var map = mapElm.getContext("2d");

	// character
	var source = { "x": 0, "y": 0 };
	coord[source.x][source.y] = 1;
	// target
	var target = { "x": 19, "y": 19 };
	coord[target.x][target.y] = 4;

	draw();

	sourceBtn.onclick = () => {
		selectSquare(1);
	};
	targetBtn.onclick = () => {
		selectSquare(4);
	};
	wallBtn.onclick = () => {
		selectSquare(2);
	};
	emptyBtn.onclick = () => {
		selectSquare(0);
	};

	// runs the algorithm
	runBtn.onclick = () => {

		// cleans old path
		clearSquare(3);
		clearSquare(5);

		// searching a new one
		run();

	};

	// clears the map
	clearBtn.onclick = () => {
		clearSquare(2);
		clearSquare(3);
		clearSquare(5);
		draw();
	};

	controlBtn.onclick = () => {
		alert("1,2,3,4 - Select a Square \n" +
			  "Esc/Del - Clear all \n" +
			  "Enter/Space - Run");
	};

	// turns off square placement
	mapElm.onmouseup = e => { mousedown = false; };
	mapElm.onmouseout = e => { mousedown = false; };

	// turns on square placement
	mapElm.onmousedown = e => {
		mousedown = true;
		placeSquare(e);
	};

	mapElm.onmousemove = placeSquare;

	// controls
	document.onkeydown = e => {

		switch (e.keyCode)
		{
			// 1
			case 49:
				selectSquare(1);
				break;
			// 2
			case 50:
				selectSquare(4);
				break;
			// 3
			case 51:
				selectSquare(2);
				break;
			// 4
			case 52:
				selectSquare(0);
				break;
			// space
			case 32:
			// enter
			case 13:
				runBtn.click();
				break;
			// esc
			case 27:
			// del
			case 46:
				clearBtn.click();
				break;
		}
	}

})();
<|endoftext|>


<commit_before>/*
 * Websensor video stabilization project
 * https://github.com/jessenie-intel/websensor-video
 *
 * Copyright (c) 2017 Jesse Nieminen
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
*/

'use strict';

var constraints = {audio: true,video: {  width: { min: 640, ideal: 640, max: 640 },  height: { min: 480, ideal: 480, max: 480 }}};
var mediaRecorder = null;
var chunks = [];
var videoData = null;

var videoElement = document.querySelector('video');
videoElement.controls = false;

function errorCallback(error){
	console.log("error: ", error);
}

function startDemo () {
		navigator.getUserMedia(constraints, startRecording, errorCallback);
}

function startRecording(stream) {

                try {
                //Initialize sensors
                accel_sensor = new Accelerometer();
                accel_sensor.onchange = () => {
                };
                accel_sensor.onactivate = () => {
                };
                accel_sensor.start();
                orientation_sensor = new AbsOriSensor();
                orientation_sensor.onchange = () => {
                        this.roll = orientation_sensor.roll;
                        this.pitch = orientation_sensor.pitch;
                        this.yaw = orientation_sensor.yaw;
                        if(!this.initialoriobtained) //obtain initial longitude
                        {
                                let yawInitial = orientation_sensor.yaw;
                                this.longitudeInitial = -yawInitial * 180 / Math.PI;
                                longitudeOffset = this.longitudeInitial;
                                this.initialoriobtained = true;
                        }
                };
                orientation_sensor.onactivate = () => {
                };
                orientation_sensor.start();
                }
                catch(err) {
                        console.log(err.message);
                        console.log("Your browser doesn't seem to support generic sensors. If you are running Chrome, please enable it in about:flags.");
                        //this.innerHTML = "Your browser doesn't seem to support generic sensors. If you are running Chrome, please enable it in about:flags";
                }
	        //var options = {mimeType: 'video/webm;codecs=vp9'};
		//mediaRecorder = new MediaRecorder(stream, options);
		mediaRecorder = new MediaRecorder(stream);

	        mediaRecorder.start(10);

	        var url = window.URL;
	        videoElement.src = url ? url.createObjectURL(stream) : stream;
	        videoElement.play();

	        mediaRecorder.ondataavailable = function(e) {
                        //console.log("Data available", e);
		        chunks.push(e.data);
	        };

	        mediaRecorder.onerror = function(e){
		        console.log('Error: ', e);
	        };

	        mediaRecorder.onstart = function(){
                        console.log("Recording started", mediaRecorder.state);
	        };

	        mediaRecorder.onstop = function(){
		        var blob = new Blob(chunks, {type: "video/webm"});
		        chunks = [];

		        var videoURL = window.URL.createObjectURL(blob);

		        videoElement.src = videoURL;

                        //Read blob data so we can stabilize the video
                        var reader = new FileReader();
                          reader.onload = function(event){
                                let text = reader.result;
                            console.log(text);
                          };
                        reader.readAsText(blob);
                        stabilize(blob);
	        };

	        mediaRecorder.onpause = function(){
	        }

	        mediaRecorder.onresume = function(){
	        }

	        mediaRecorder.onwarning = function(e){
	        };
}

function stopRecording(){
	mediaRecorder.stop();
        //Now stabilize
        //stabilize(blob);
	videoElement.controls = true;
}

function stabilize(video) {     //Idea: copy video to canvas, operate on the video, and then use the canvas with the stabilized video as source for the video element
        var canvas = document.querySelector('canvas');
        var ctx = canvas.getContext('2d');
        ctx.drawImage(video, 0, 0);
        let imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
        //console.log(video);
}
<commit_msg>Work on accessing raw video data<commit_after>/*
 * Websensor video stabilization project
 * https://github.com/jessenie-intel/websensor-video
 *
 * Copyright (c) 2017 Jesse Nieminen
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
*/

'use strict';

var constraints = {audio: true,video: {  width: { min: 640, ideal: 640, max: 640 },  height: { min: 480, ideal: 480, max: 480 }}};
var mediaRecorder = null;
var chunks = [];
var videoData = null;

var videoElement = document.querySelector('video');
videoElement.controls = false;

function errorCallback(error){
	console.log("error: ", error);
}

function startDemo () {
		navigator.getUserMedia(constraints, startRecording, errorCallback);
}

function startRecording(stream) {

                try {
                //Initialize sensors
                accel_sensor = new Accelerometer();
                accel_sensor.onchange = () => {
                };
                accel_sensor.onactivate = () => {
                };
                accel_sensor.start();
                orientation_sensor = new AbsOriSensor();
                orientation_sensor.onchange = () => {
                        this.roll = orientation_sensor.roll;
                        this.pitch = orientation_sensor.pitch;
                        this.yaw = orientation_sensor.yaw;
                        if(!this.initialoriobtained) //obtain initial longitude
                        {
                                let yawInitial = orientation_sensor.yaw;
                                this.longitudeInitial = -yawInitial * 180 / Math.PI;
                                longitudeOffset = this.longitudeInitial;
                                this.initialoriobtained = true;
                        }
                };
                orientation_sensor.onactivate = () => {
                };
                orientation_sensor.start();
                }
                catch(err) {
                        console.log(err.message);
                        console.log("Your browser doesn't seem to support generic sensors. If you are running Chrome, please enable it in about:flags.");
                        //this.innerHTML = "Your browser doesn't seem to support generic sensors. If you are running Chrome, please enable it in about:flags";
                }
	        //var options = {mimeType: 'video/webm;codecs=vp9'};
		//mediaRecorder = new MediaRecorder(stream, options);
		mediaRecorder = new MediaRecorder(stream);

	        mediaRecorder.start(10);

	        var url = window.URL;
	        videoElement.src = url ? url.createObjectURL(stream) : stream;
	        videoElement.play();

	        mediaRecorder.ondataavailable = function(e) {
                        //console.log("Data available", e);
		        chunks.push(e.data);
	        };

	        mediaRecorder.onerror = function(e){
		        console.log('Error: ', e);
	        };

	        mediaRecorder.onstart = function(){
                        console.log("Recording started", mediaRecorder.state);
	        };

	        mediaRecorder.onstop = function(){
		        var blob = new Blob(chunks, {type: "video/webm"});
		        chunks = [];

		        var videoURL = window.URL.createObjectURL(blob);

		        videoElement.src = videoURL;

                        //Read blob data so we can stabilize the video
                        var reader = new FileReader();
                          reader.onload = function(event){
                                let text = reader.result;
                            console.log(text);
                          };
                        reader.readAsText(blob);
                        stabilize(blob);
	        };

	        mediaRecorder.onpause = function(){
	        }

	        mediaRecorder.onresume = function(){
	        }

	        mediaRecorder.onwarning = function(e){
	        };
}

function stopRecording(){
	mediaRecorder.stop();
        //Now stabilize
        //stabilize(blob);
	videoElement.controls = true;
}

function stabilize(video) {     //Idea: copy video to canvas, operate on the video, and then use the canvas with the stabilized video as source for the video element
        var canvas = document.querySelector('canvas');
        var ctx = canvas.getContext('2d');
        ctx.drawImage(videoElement, 0, 0);
        let imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
        //console.log(video);
}
<|endoftext|>


<commit_before>// ==UserScript==
// @name         AutoJoin IndieGala Giveaways (improved)
// @version      0.4
// @date         18/Feb/2017
// @description  AutoJoin for IndieGala Giveaways!
// @author       George Dorn (@GDorn), Sergio Susa (http://sergiosusa.com) and pagep (http://pagep.net)
// @homepage     https://github.com/petrvecera/indiegala-giveaways
// @match        https://www.indiegala.com/giveaways*
// @grant        none
// ==/UserScript==

var reloading = 3 * 60 * 1000; // 3 minutes; delay encountered when out of points with enabled inifinte run
var trying = 40 * 1000; // 10 seconds; delay before loading next page
var min_coins = 5; // number of points to save
var coins_per_page = 10; // number of extra points to save per page, to avoid wasting points on contests hours in the future; cycles to page one after exceeding
var timeBetweenClicks = 4 * 1000; // 2 seconds; delay between clicking on ticket stubs
var max_page = 20; // maximum page number; cycles to page 1 after this or stops script
var start_delay = 5 * 1000; // wait this long on page load, for 'match_games_in_steam_library' to finish.
var max_level = 0; // maximum contest level to try to enter; set to higher if you are a higher level.
var max_participants = 800; // skip contests with more participants than this
var skip_already_owned = true; // skip contests for games you already own (according to indiegala)
var infinite_run = false; // will not stop when you run out of coins or when you reach max page

if (!skip_already_owned) {
    start_delay = 50; //if we don't care about winning games we own, we can run a little faster
}

var autoEnter = function () {
    'use strict';

    console.log("Starting auto-entry.");

    if (skip_already_owned) {
        removeAlreadyHave();
    }

    var coins = parseInt($("#silver-coins-menu").html());
    console.log("Have this many coins: ", coins);
    if (coins < min_coins) {
        if (!infinite_run) {
            console.log('Not enought coints, stopping the script');
            return;
        }
        console.log("Not enough coins, reloading...");
        reloadPage(randomize(reloading));
        return;
    }

    // add more delay for every stub we need to wait to click on
    var next_page_delay = trying;

    var contests = $('div.tickets-col');

    console.log("Got ", contests.length, " contests: ", contests);

    // iterate through contests on the page, scheduling clicks on stubs if they meet our criteria
    for (var i = 0; i < contests.length; i++) {
        // if we spent all our coins, bail
        if (coins < min_coins) {
            console.log("Not enough coins to continue");
            break;
        }

        var contest = contests[i];
        console.log("Considering contest:", contest);

        var name = $(contest).find('div.ticket-right').find('h2').text().trim();
        var price = parseInt($(contest).find('div.ticket-price')[0].textContent);
        var level = get_level(contest);
        var participants = get_participants(contest);
        console.log("Name: ", name, " Price: ", price, " Level: ", level, " Participants: ", participants);

        var stub = contest.getElementsByTagName("aside")[0];
        if (!stub) {
            console.log("Skipping ", name, " because can't find stub?  Maybe already entered?");
            continue;
        }
        if (price > coins) {
            console.log("Skipping ", name, " because price (", price, ") exceeds coins (", coins, ")");
            continue;
        }

        if (level > max_level) {
            console.log("Skipping ", name, " because required level (", level, ") is greater than max_level,", max_level);
            continue;
        }

        if (participants > max_participants) {
            console.log("Skipping ", name, " because ", participants, " users participating, greater than the allowed ", max_participants);
            continue;
        }

        // if we're here, all checks passed, go ahead and click on it.
        var delay = randomize(timeBetweenClicks);

        var newUrl = "https://www.indiegala.com" + stub.querySelector("a.giv-coupon-link").getAttribute('href');
        window.open(newUrl, '_blank');

        console.log("Opening new window on: ", name, stub);
        console.log("New url: ", newUrl);
        next_page_delay += delay; // add the delay to the next page delay so we don't load next page before the click happens
        coins -= price; // deduct cost of contest
    }

    console.log("###### Done with this page, moving on to next. ######");

    var next_page = calculateNextPage();

    // get updated coins now in case our coin tracking broke
    coins = parseInt($(".coins-amount strong").html());

    // avoid spending too many coins on later pages, save them for short-running giveaways with fewer entries
    var needed_coins = min_coins + coins_per_page * (next_page - 1);
    if (coins < needed_coins) {
        console.log("Going back to page 1; we have ", coins, " but want at least ", needed_coins, " to continue.");
        next_page = 1;
        next_page_delay += trying; //some extra delay before loading first page again
    }

    if (next_page > max_page) {
        if (!infinite_run) {
            console.log('Too many pages, exceeded ' + max_page + ' - stoppnig the script!');
            return;
        }
        console.log('Too many pages, starting from 1');
        next_page = 1;
    }

    next_page_delay = randomize(next_page_delay);

    console.log("Going to load page ", next_page, " in about ", next_page_delay, 'ms');

    setTimeout(function () {

        window.location = "https://www.indiegala.com/giveaways/[NUM_PAGE]/expiry/asc".replace("[NUM_PAGE]", next_page);

    }, next_page_delay);

};

$(document).ready(function () {
    var pageUrl = window.location.href;
    if (pageUrl.indexOf("https://www.indiegala.com/giveaways/detail/") > -1) {
        console.log("I am on detail page, going to enter giveaway");
        var ticket = document.querySelector("aside.giv-coupon.relative.animated-coupon ");
        if (ticket) {
            ticket.click();
            console.log("Giveaway probably entered...");
        }
        setTimeout(function () {
            window.close();
        }, 1200);
    } else {
        console.log("I am on the main page, will start autojoin script");
        setTimeout(autoEnter, start_delay);
    }
});

/***********************************************************
 *  Utility Functions
 **********************************************************/

function randomize(number) {
    // returns a random number somewhere between 3/4 and 5/4 of the given value.
    // maybe helps bust bot detection.
    var base = Math.floor(number * 0.75);
    var max_add = Math.floor(number * 0.5);
    return result = base + Math.floor(Math.random() * max_add);
}

function removeAlreadyHave() {
    var count = 0;
    var nodes = $('.on-steam-library-corner');
    for (var i = 0; i < nodes.length; i++) {
        var node = nodes[i];
        if ($(node).is(':visible')) {
            $(node).parents('.tickets-col').remove();
            count += 1;
        }
    }
    console.log("Removed ", count, " offers already in steam library.");
}

function get_level(contest) {
    // returns the numeric level requirement for a chunk of text extracted from a ticket
    var text = contest.textContent.trim();
    var position = text.indexOf('LEVEL ') + 6;
    return parseInt(text.slice(position));
}

function get_participants(contest) {
    var text = $(contest).find('.ticket-info-cont div.info-row:nth-of-type(4)').text();
    return parseInt(text);
}

function calculateNextPage() {
    var page = window.location.href.replace("https://www.indiegala.com/giveaways/", "").replace("/expiry/asc", "");
    return parseInt(page) + 1;
}

function reloadPage(miliseconds) {
    console.log("Reloading page in ", miliseconds, " ms");
    setTimeout(function () {
        window.location.reload();
    }, miliseconds);
}

/***********************************************************
 *  Override Functions
 **********************************************************/
window.confirm = function (message, callback, caption) {
    return true;
};<commit_msg>Add auto-update urls<commit_after>// ==UserScript==
// @name         AutoJoin IndieGala Giveaways (improved)
// @version      0.4.1
// @date         18/Feb/2017
// @description  AutoJoin for IndieGala Giveaways!
// @author       George Dorn (@GDorn), Sergio Susa (http://sergiosusa.com) and pagep (http://pagep.net)
// @homepage     https://github.com/petrvecera/indiegala-giveaways
// @updateURL    https://raw.githubusercontent.com/petrvecera/indiegala-giveaways/master/script.js
// @downloadURL  https://raw.githubusercontent.com/petrvecera/indiegala-giveaways/master/script.js
// @match        https://www.indiegala.com/giveaways*
// @grant        none
// ==/UserScript==

var reloading = 3 * 60 * 1000; // 3 minutes; delay encountered when out of points with enabled inifinte run
var trying = 40 * 1000; // 10 seconds; delay before loading next page
var min_coins = 5; // number of points to save
var coins_per_page = 10; // number of extra points to save per page, to avoid wasting points on contests hours in the future; cycles to page one after exceeding
var timeBetweenClicks = 4 * 1000; // 2 seconds; delay between clicking on ticket stubs
var max_page = 20; // maximum page number; cycles to page 1 after this or stops script
var start_delay = 5 * 1000; // wait this long on page load, for 'match_games_in_steam_library' to finish.
var max_level = 0; // maximum contest level to try to enter; set to higher if you are a higher level.
var max_participants = 800; // skip contests with more participants than this
var skip_already_owned = true; // skip contests for games you already own (according to indiegala)
var infinite_run = false; // will not stop when you run out of coins or when you reach max page

if (!skip_already_owned) {
    start_delay = 50; //if we don't care about winning games we own, we can run a little faster
}

var autoEnter = function () {
    'use strict';

    console.log("Starting auto-entry.");

    if (skip_already_owned) {
        removeAlreadyHave();
    }

    var coins = parseInt($("#silver-coins-menu").html());
    console.log("Have this many coins: ", coins);
    if (coins < min_coins) {
        if (!infinite_run) {
            console.log('Not enought coints, stopping the script');
            return;
        }
        console.log("Not enough coins, reloading...");
        reloadPage(randomize(reloading));
        return;
    }

    // add more delay for every stub we need to wait to click on
    var next_page_delay = trying;

    var contests = $('div.tickets-col');

    console.log("Got ", contests.length, " contests: ", contests);

    // iterate through contests on the page, scheduling clicks on stubs if they meet our criteria
    for (var i = 0; i < contests.length; i++) {
        // if we spent all our coins, bail
        if (coins < min_coins) {
            console.log("Not enough coins to continue");
            break;
        }

        var contest = contests[i];
        console.log("Considering contest:", contest);

        var name = $(contest).find('div.ticket-right').find('h2').text().trim();
        var price = parseInt($(contest).find('div.ticket-price')[0].textContent);
        var level = get_level(contest);
        var participants = get_participants(contest);
        console.log("Name: ", name, " Price: ", price, " Level: ", level, " Participants: ", participants);

        var stub = contest.getElementsByTagName("aside")[0];
        if (!stub) {
            console.log("Skipping ", name, " because can't find stub?  Maybe already entered?");
            continue;
        }
        if (price > coins) {
            console.log("Skipping ", name, " because price (", price, ") exceeds coins (", coins, ")");
            continue;
        }

        if (level > max_level) {
            console.log("Skipping ", name, " because required level (", level, ") is greater than max_level,", max_level);
            continue;
        }

        if (participants > max_participants) {
            console.log("Skipping ", name, " because ", participants, " users participating, greater than the allowed ", max_participants);
            continue;
        }

        // if we're here, all checks passed, go ahead and click on it.
        var delay = randomize(timeBetweenClicks);

        var newUrl = "https://www.indiegala.com" + stub.querySelector("a.giv-coupon-link").getAttribute('href');
        window.open(newUrl, '_blank');

        console.log("Opening new window on: ", name, stub);
        console.log("New url: ", newUrl);
        next_page_delay += delay; // add the delay to the next page delay so we don't load next page before the click happens
        coins -= price; // deduct cost of contest
    }

    console.log("###### Done with this page, moving on to next. ######");

    var next_page = calculateNextPage();

    // get updated coins now in case our coin tracking broke
    coins = parseInt($(".coins-amount strong").html());

    // avoid spending too many coins on later pages, save them for short-running giveaways with fewer entries
    var needed_coins = min_coins + coins_per_page * (next_page - 1);
    if (coins < needed_coins) {
        console.log("Going back to page 1; we have ", coins, " but want at least ", needed_coins, " to continue.");
        next_page = 1;
        next_page_delay += trying; //some extra delay before loading first page again
    }

    if (next_page > max_page) {
        if (!infinite_run) {
            console.log('Too many pages, exceeded ' + max_page + ' - stoppnig the script!');
            return;
        }
        console.log('Too many pages, starting from 1');
        next_page = 1;
    }

    next_page_delay = randomize(next_page_delay);

    console.log("Going to load page ", next_page, " in about ", next_page_delay, 'ms');

    setTimeout(function () {

        window.location = "https://www.indiegala.com/giveaways/[NUM_PAGE]/expiry/asc".replace("[NUM_PAGE]", next_page);

    }, next_page_delay);

};

$(document).ready(function () {
    var pageUrl = window.location.href;
    if (pageUrl.indexOf("https://www.indiegala.com/giveaways/detail/") > -1) {
        console.log("I am on detail page, going to enter giveaway");
        var ticket = document.querySelector("aside.giv-coupon.relative.animated-coupon ");
        if (ticket) {
            ticket.click();
            console.log("Giveaway probably entered...");
        }
        setTimeout(function () {
            window.close();
        }, 1200);
    } else {
        console.log("I am on the main page, will start autojoin script");
        setTimeout(autoEnter, start_delay);
    }
});

/***********************************************************
 *  Utility Functions
 **********************************************************/

function randomize(number) {
    // returns a random number somewhere between 3/4 and 5/4 of the given value.
    // maybe helps bust bot detection.
    var base = Math.floor(number * 0.75);
    var max_add = Math.floor(number * 0.5);
    return result = base + Math.floor(Math.random() * max_add);
}

function removeAlreadyHave() {
    var count = 0;
    var nodes = $('.on-steam-library-corner');
    for (var i = 0; i < nodes.length; i++) {
        var node = nodes[i];
        if ($(node).is(':visible')) {
            $(node).parents('.tickets-col').remove();
            count += 1;
        }
    }
    console.log("Removed ", count, " offers already in steam library.");
}

function get_level(contest) {
    // returns the numeric level requirement for a chunk of text extracted from a ticket
    var text = contest.textContent.trim();
    var position = text.indexOf('LEVEL ') + 6;
    return parseInt(text.slice(position));
}

function get_participants(contest) {
    var text = $(contest).find('.ticket-info-cont div.info-row:nth-of-type(4)').text();
    return parseInt(text);
}

function calculateNextPage() {
    var page = window.location.href.replace("https://www.indiegala.com/giveaways/", "").replace("/expiry/asc", "");
    return parseInt(page) + 1;
}

function reloadPage(miliseconds) {
    console.log("Reloading page in ", miliseconds, " ms");
    setTimeout(function () {
        window.location.reload();
    }, miliseconds);
}

/***********************************************************
 *  Override Functions
 **********************************************************/
window.confirm = function (message, callback, caption) {
    return true;
};
<|endoftext|>


<commit_before>'use strict';

const Script = require('smooch-bot').Script;

module.exports = new Script({
    processing: {
        prompt: (bot) => bot.say('Beep boop...'),
        receive: () => 'processing'
    },

    start: {
        receive: (bot) => {
            return bot.say('Hallo! ich bin Andreas Sefzigs Bot.')
                .then(() => bot.say('Wenn Andreas online ist, sieht er, was Sie schreiben und kann diesem Gespräch beitreten.'))
                .then(() => 'vorname');
        }
    },

    vorname: {
        prompt: (bot) => bot.say('Vielleicht darf ich Sie erstmal begrüßen: Wie heissen Sie mit Vornamen?'),
        receive: (bot, message) => {
            const vorname = message.text;
            return bot.setProp('vorname', vorname)
                .then(() => bot.say(`${vorname}, prima.`))
                .then(() => 'nachname');
        }
    },

    nachname: {
        prompt: (bot) => bot.say('Und mit Nachnamen?'),
        receive: (bot, message) => {
            var vorname = bot.getProp('vorname');
            vorname = vorname.toSource();

            const nachname = message.text;
            return bot.setProp('nachname', nachname)
                .then(() => bot.say(vorname+` ${nachname}, danke.`))
                .then(() => bot.say('Schreiben Sie eine Nachricht an Andreas - oder unterhalten Sie sich mit mir, indem Sie --bot schreiben.'))
                .then(() => 'register');
        }
    },

    register: {
        receive: (bot, message) => {

            const wollen = message.text;
            var befehl = wollen;
            befehl = befehl.trim();
            befehl = befehl.toUpperCase();

         // Über mich
            if (befehl == "--PERSON")       { bot.say('Person.'); }
            if (befehl == "--LEBENSLAUF")   { bot.say('Lebenslauf.'); }

         // System
            if (befehl == "--BOT")       { bot.say('Bot.'); }
            if (befehl == "--ABBRECHEN") { bot.say('Abbruch.'); }

            return bot.setProp('wollen', wollen)
                .then(() => 'register');
        }
    },

    finish: {
        receive: (bot, message) => {
            return bot.getProp('name')
                .then(() => 'finish');
        }
    }
});
<commit_msg>Tests<commit_after>'use strict';

const Script = require('smooch-bot').Script;

module.exports = new Script({
    processing: {
        prompt: (bot) => bot.say('Beep boop...'),
        receive: () => 'processing'
    },

    start: {
        receive: (bot) => {
            return bot.say('Hallo! ich bin Andreas Sefzigs Bot.')
                .then(() => bot.say('Wenn Andreas online ist, sieht er, was Sie schreiben und kann diesem Gespräch beitreten.'))
                .then(() => 'vorname');
        }
    },

    vorname: {
        prompt: (bot) => bot.say('Vielleicht darf ich Sie erstmal begrüßen: Wie heissen Sie mit Vornamen?'),
        receive: (bot, message) => {
            const vorname = message.text;
            return bot.setProp('vorname', vorname)
                .then(() => bot.say(`${vorname}, prima.`))
                .then(() => 'nachname');
        }
    },

    nachname: {
        prompt: (bot) => bot.say('Und mit Nachnamen?'),
        receive: (bot, message) => {
            var vorname = bot.getProp('vorname');
            vorname = vorname.toSource();

            const nachname = message.text;
            return bot.setProp('nachname', nachname)
                .getProp('vorname')
                .then((vorname) => bot.say(`${vorname} ${nachname}, danke.`))
                .then(() => bot.say('Schreiben Sie eine Nachricht an Andreas - oder unterhalten Sie sich mit mir, indem Sie --bot schreiben.'))
                .then(() => 'register');
        }
    },

    register: {
        receive: (bot, message) => {

            const wollen = message.text;
            var befehl = wollen;
            befehl = befehl.trim();
            befehl = befehl.toUpperCase();

         // Über mich
            if (befehl == "--PERSON")       { bot.say('Person.'); }
            if (befehl == "--LEBENSLAUF")   { bot.say('Lebenslauf.'); }

         // System
            if (befehl == "--BOT")       { bot.say('Bot.'); }
            if (befehl == "--ABBRECHEN") { bot.say('Abbruch.'); }

            return bot.setProp('wollen', wollen)
                .then(() => 'register');
        }
    },

    finish: {
        receive: (bot, message) => {
            return bot.getProp('name')
                .then(() => 'finish');
        }
    }
});
<|endoftext|>