Best JavaScript code snippet using webdriverio-monorepo
main.js
Source:main.js  
...132    callback: (command) => {133      speak("Gotcha. Let me know if you need anything!", "Success");134      // reset commands135      annyang.removeCommands();136      annyang.addCommands(keywordCommand);137      annyang.addCommands(cancelCommand);138    },139  },140};141// test alarms142// const t1 = new Date(2021, 10, 17, 21, 48, 0);143// const label1 = "my alarm 1";144// setAlarm(t1, label1, true);145// const t2 = new Date(2021, 10, 17, 23, 48, 0);146// const label2 = "";147// setAlarm(t2, label2, true);148// setTimeout(() => editAlarmEnabled(t2, "", false), 5000);149// setTimeout(() => editAlarmLabel(t2, "my alarm 1", "my alarm 2"), 10000);150// const t3 = new Date(2021, 10, 17, 23, 48, 30);151// setTimeout(() => editAlarmTime(t1, "my alarm 2", t3), 15000);152// setTimeout(() => deleteAlarm(null, "my alarm 2"), 20000);153// setTimeout(() => console.log("done!"), 25000);154// test events155// const t1 = new Date(2021, 10, 17, 21, 48, 0);156// const label1 = "my event 1";157// const d1 = 120; // minutes158// setEvent(t1, label1, d1, true);159// const t2 = new Date(2021, 10, 17, 23, 48, 0);160// const label2 = "";161// const d2 = 240; // minutes162// setEvent(t2, label2, d2, true);163// setTimeout(() => editEventLabel(t2, "my event 1", "my event 2"), 5000);164// const t3 = new Date(2021, 10, 17, 23, 48, 30);165// const d3 = 180; // minutes166// setTimeout(() => editEventTime(t1, "my event 2", t3), 10000);167// setTimeout(() => deleteEvent(null, "my event 2"), 15000);168// setTimeout(() => editEventDuration(null, "my event 1", d3), 20000);169// setTimeout(() => console.log("done!"), 25000);170/** ========================== INITIALIZATION ============================== */171// attempt to start the system172if (annyang && nlp && compromiseNumbers && compromiseDates) {173  // all libraries available!174  // add various plugin to base compromise object175  nlp.extend(compromiseNumbers);176  nlp.extend(compromiseDates);177  // set up basic keyword command recognition for annyang178  var commands = {}; // commands object179  annyang.addCommands(keywordCommand); // add commands to recognition service180  annyang.addCommands(cancelCommand); // add commands to recognition service181  setCallbacks(); // set callbacks for speech recognition service182  // set speech synthesis parameters for Web Speech API183  var synth = window.speechSynthesis; // snyth API184  var voices = []; // list of voice options from the speech API185  var systemOutput = ""; // what the system will say186  var userOutput = ""; // what the user said187  populateVoiceList(); // add available voices to voice dropdown188  if (speechSynthesis.onvoiceschanged !== undefined) {189    speechSynthesis.onvoiceschanged = populateVoiceList;190  }191  pitchSlider.oninput = function () {192    pitchValue.textContent = pitchSlider.value;193  };194  rateSlider.oninput = function () {195    rateValue.textContent = rateSlider.value;196  };197  // add event listeners198  testBtn.addEventListener("click", () => speak("Hello! I'm going to be your partner for today.", "Test"));199  startBtn.addEventListener("click", listen);200  showhideBtn.addEventListener(201    "click",202    () => (outputText.style.display = outputText.style.display == "none" ? "block" : "none")203  );204} else {205  // not all libraries could be loaded206  testBtn.disabled = true;207  startBtn.disabled = true;208  showhideBtn.disabled = true;209  voiceSelect.disabled = true;210  pitchSlider.disabled = true;211  rateSlider.disabled = true;212  const d = new Date();213  const elem = `214    <div class="flex-row" style="color: red">215      <div class="flex-col col1">216        <span>${d.toLocaleTimeString()}</span>217      </div>218      <div class="flex-col col2">219        <span>System</span>220      </div>221      <div class="flex-col col3">222        <span>Error</span>223      </div>224      <div class="flex-col col4">225        <span>Speech Recognition not available in this browser. Supported browsers: Chrome, Edge, Safari</span>226      </div>227    </div>228  `;229  outputText.insertAdjacentHTML("beforeend", elem);230}231/**232 * Add all available synth voices in the current browser to the voice dropdown.233 */234function populateVoiceList() {235  voices = synth.getVoices().sort(function (a, b) {236    const an = a.name.toUpperCase();237    const bn = b.name.toUpperCase();238    if (an < bn) {239      return -1;240    } else if (an == bn) {241      return 0;242    } else {243      return +1;244    }245  });246  const selectedIndex = voiceSelect.selectedIndex < 0 ? 0 : voiceSelect.selectedIndex;247  voiceSelect.innerHTML = "";248  for (i = 0; i < voices.length; i++) {249    var option = document.createElement("option");250    option.textContent = voices[i].name + " (" + voices[i].lang + ")";251    if (voices[i].default) {252      option.textContent += " -- DEFAULT";253    }254    option.setAttribute("data-lang", voices[i].lang);255    option.setAttribute("data-name", voices[i].name);256    voiceSelect.appendChild(option);257  }258  voiceSelect.selectedIndex = selectedIndex;259}260/**261 * Set callbacks for speech recognition.262 */263function setCallbacks() {264  // when the recognition matches one or more of the commands265  annyang.addCallback("resultMatch", function (userSaid, commandText, phrases) {266    annyang.pause();267    testBtn.disabled = false;268    startBtn.disabled = false;269    startBtn.textContent = "Start recording";270    userOutput = userSaid;271    const d = new Date();272    const elem = `273      <div class="flex-row">274        <div class="flex-col col1">275          <span>${d.toLocaleTimeString()}</span>276        </div>277        <div class="flex-col col2">278          <span>User</span>279        </div>280        <div class="flex-col col3">281          <span>Keyword</span>282        </div>283        <div class="flex-col col4">284          <span>${userOutput}</span>285        </div>286      </div>287    `;288    outputText.insertAdjacentHTML("beforeend", elem);289  });290  // when the recognition does not match any of the commands291  annyang.addCallback("resultNoMatch", function (phrases) {292    annyang.pause();293    testBtn.disabled = false;294    startBtn.disabled = false;295    startBtn.textContent = "Start recording";296    userOutput = phrases[0];297    const d = new Date();298    const elem = `299      <div class="flex-row">300        <div class="flex-col col1">301          <span>${d.toLocaleTimeString()}</span>302        </div>303        <div class="flex-col col2">304          <span>User</span>305        </div>306        <div class="flex-col col3">307          <span>Guess</span>308        </div>309        <div class="flex-col col4">310          <span>${userOutput}</span>311        </div>312      </div>313    `;314    outputText.insertAdjacentHTML("beforeend", elem);315    speak(316      `I'm sorry. I heard ${userOutput}. I'm not currently programmed to respond to that. Try asking me to set a new alarm or event!`,317      "Failure"318    );319  });320  // when an error occurs321  annyang.addCallback("error", function (event) {322    annyang.pause();323    console.log(event);324    testBtn.disabled = false;325    startBtn.disabled = false;326    startBtn.textContent = "Start recording";327    speak("Error occurred in recognition. See console for details.", "Error");328  });329}330/** ============================== ALARMS ================================== */331function parseSetAlarmInput(userInput, d, t) {332  const userInputDoc = nlp(userInput); // parse input using compromise333  let dates, times;334  let nd = 0;335  let nt = 0;336  if (!d) {337    // only look for a date if one isn't provided338    dates = userInputDoc.dates().json();339    nd = dates.length; // number of dates found340  }341  if (d) nd += 1; // date is given342  if (!t) {343    // only look for a time if one isn't provided344    times = userInputDoc.times().json();345    nt = times.length; // number of times found346  }347  if (t) nt += 1; // time is given348  if (nd == 1 && nt == 1) {349    // one date, one time => try to set an alarm with the provided inputs350    if (!d) d = new Date(dates[0].start);351    if (!t) t = toTime(times[0].time);352    const target = new Date(d.getFullYear(), d.getMonth(), d.getDate(), t.hours, t.minutes, 0);353    setAlarm(target, null, true, false);354    // reset commands355    annyang.removeCommands();356    annyang.addCommands(keywordCommand);357    annyang.addCommands(cancelCommand);358  } else if (nd == 1 && nt > 1) {359    // one date, multiple times360    if (!d) d = new Date(dates[0].start);361    speak(362      "I heard multiple times to set that alarm for. Could you clarify which time you want to set your alarm for?",363      "Clarify"364    );365    annyang.removeCommands();366    annyang.addCommands(cancelCommand);367    annyang.addCommands({ "*response": (response) => parseSetAlarmInput(response, d, null) });368  } else if (nd == 1 && nt == 0) {369    // one date, no time370    if (!d) d = new Date(dates[0].start);371    speak("Certainly! And what time would you like to set the alarm for?", "Clarify");372    annyang.removeCommands();373    annyang.addCommands(cancelCommand);374    annyang.addCommands({ "*response": (response) => parseSetAlarmInput(response, d, null) });375  } else if (nd > 1 && nt == 1) {376    // multiple dates, one time377    if (!t) t = toTime(times[0].time);378    speak(379      "I heard multiple days to set that alarm for. Could you clarify which day you want to set your alarm for?",380      "Clarify"381    );382    annyang.removeCommands();383    annyang.addCommands(cancelCommand);384    annyang.addCommands({ "*response": (response) => parseSetAlarmInput(response, null, t) });385  } else if (nd > 1 && nt > 1) {386    // multiple dates, multiple times387    speak(388      "I heard multiple days and times to set that alarm for. Could you clarify a single date and time, please?",389      "Clarify"390    );391    annyang.removeCommands();392    annyang.addCommands(cancelCommand);393    annyang.addCommands({ "*response": (response) => parseSetAlarmInput(response, null, null) });394  } else if (nd > 1 && nt == 0) {395    // multiple dates, no time396    speak(397      "I heard multiple days and no time to set that alarm for. Could you clarify a single date and time, please?",398      "Clarify"399    );400    annyang.removeCommands();401    annyang.addCommands(cancelCommand);402    annyang.addCommands({ "*response": (response) => parseSetAlarmInput(response, null, null) });403  } else if (nd == 0 && nt == 1) {404    // no date, one time405    if (!t) t = toTime(times[0].time);406    speak("Absolutely! And what day would you like to set that alarm for?", "Clarify");407    annyang.removeCommands();408    annyang.addCommands(cancelCommand);409    annyang.addCommands({ "*response": (response) => parseSetAlarmInput(response, null, t) });410  } else if (nd == 0 && nt > 1) {411    // no date, multiple times412    speak(413      "I heard multiple times and no date to set that alarm for. Could you clarify a single date and time, please?",414      "Clarify"415    );416    annyang.removeCommands();417    annyang.addCommands(cancelCommand);418    annyang.addCommands({ "*response": (response) => parseSetAlarmInput(response, null, null) });419  } else if (nd == 0 && nt == 0) {420    // no date, no time421    speak("Of course. And when would you like that alarm scheduled for?", "Clarify");422    annyang.removeCommands();423    annyang.addCommands(cancelCommand);424    annyang.addCommands({ "*response": (response) => parseSetAlarmInput(response, null, null) });425  } else {426    // no idea427    speak("Sounds like you wanted to set an alarm. Could you give me a date and a time?", "Clarify");428    annyang.removeCommands();429    annyang.addCommands(cancelCommand);430    annyang.addCommands({ "*response": (response) => parseSetAlarmInput(response, null, null) });431  }432}433/**434 * Set an alarm for the time given with the given label and with the enabled435 * flag set to the given value.436 * @param {Date} time Time to set the alarm for.437 * @param {String} label (optional) A label for the alarm.438 * @param {Boolean} enabled A bool for whether alarm should be enabled.439 * @param {Boolean} mute Whether to mute the system responses.440 */441function setAlarm(time, label, enabled, mute) {442  if (time) {443    if (!Object.hasOwn(alarms, time.getTime())) {444      const ts = Math.floor(time.getTime() / 1000); // seconds445      function testAlarm() {446        const d = new Date();447        const ds = Math.floor(d.getTime() / 1000); // seconds448        if (ts == ds) {449          if (alarms[time.getTime()].enabled) alarmClockAudio.play(); // play the alarm!450          window.clearInterval(alarms[time.getTime()].id); // stop testing this alarm451        }452      }453      var testAlarmIntervalID = window.setInterval(testAlarm, 1000); // test alarm every second454      alarms[time.getTime()] = { id: testAlarmIntervalID, time: time, label: label, enabled: enabled }; // save alarm by time455      if (label && !Object.hasOwn(alarms, label)) {456        alarms[label] = { id: testAlarmIntervalID, time: time, label: label, enabled: enabled }; // save alarm by label457      }458      if (!mute) speak("Great! Your alarm is set.", "Success");459    } else {460      if (!mute) speak("I'm sorry, but there's already an alarm set for that date and time.", "Failure");461    }462  } else {463    console.log(`date and time given to setAlarm: ${time}`);464    if (!mute)465      speak(466        "I'm sorry, but something seems to be wrong with the provided date and time. Please check the console for details.",467        "Error"468      );469  }470  console.log("alarms:");471  console.log(alarms);472}473function parseDeleteAlarmInput(userInput, d, t) {474  const userInputDoc = nlp(userInput); // parse input using compromise475  let dates, times;476  let nd = 0;477  let nt = 0;478  if (!d) {479    // only look for a date if one isn't provided480    dates = userInputDoc.dates().json();481    nd = dates.length; // number of dates found482  }483  if (d) nd += 1; // date is given484  if (!t) {485    // only look for a time if one isn't provided486    times = userInputDoc.times().json();487    nt = times.length; // number of times found488  }489  if (t) nt += 1; // time is given490  if (nd == 1 && nt == 1) {491    // one date, one time => try to delete an alarm with the provided inputs492    if (!d) d = new Date(dates[0].start);493    if (!t) t = toTime(times[0].time);494    const target = new Date(d.getFullYear(), d.getMonth(), d.getDate(), t.hours, t.minutes, 0);495    deleteAlarm(target, null, false);496    // reset commands497    annyang.removeCommands();498    annyang.addCommands(keywordCommand);499    annyang.addCommands(cancelCommand);500  } else if (nd == 1 && nt > 1) {501    // one date, multiple times502    if (!d) d = new Date(dates[0].start);503    speak(504      "I heard multiple times just now. Could you clarify at which time the alarm you want to delete is?",505      "Clarify"506    );507    annyang.removeCommands();508    annyang.addCommands(cancelCommand);509    annyang.addCommands({ "*response": (response) => parseDeleteAlarmInput(response, d, null) });510  } else if (nd == 1 && nt == 0) {511    // one date, no time512    if (!d) d = new Date(dates[0].start);513    speak("Certainly! And at what time is the alarm you would like to delete?", "Clarify");514    annyang.removeCommands();515    annyang.addCommands(cancelCommand);516    annyang.addCommands({ "*response": (response) => parseDeleteAlarmInput(response, d, null) });517  } else if (nd > 1 && nt == 1) {518    // multiple dates, one time519    if (!t) t = toTime(times[0].time);520    speak("I heard multiple days just now. Could you clarify on which day the alarm you want to delete is?", "Clarify");521    annyang.removeCommands();522    annyang.addCommands(cancelCommand);523    annyang.addCommands({ "*response": (response) => parseDeleteAlarmInput(response, null, t) });524  } else if (nd > 1 && nt > 1) {525    // multiple dates, multiple times526    speak("I heard multiple days and times just now. Could you clarify a single date and time, please?", "Clarify");527    annyang.removeCommands();528    annyang.addCommands(cancelCommand);529    annyang.addCommands({ "*response": (response) => parseDeleteAlarmInput(response, null, null) });530  } else if (nd > 1 && nt == 0) {531    // multiple dates, no time532    speak("I heard multiple days and no time just now. Could you clarify a single date and time, please?", "Clarify");533    annyang.removeCommands();534    annyang.addCommands(cancelCommand);535    annyang.addCommands({ "*response": (response) => parseDeleteAlarmInput(response, null, null) });536  } else if (nd == 0 && nt == 1) {537    // no date, one time538    if (!t) t = toTime(times[0].time);539    speak("Absolutely! And on what day is the alarm you would like to delete?", "Clarify");540    annyang.removeCommands();541    annyang.addCommands(cancelCommand);542    annyang.addCommands({ "*response": (response) => parseDeleteAlarmInput(response, null, t) });543  } else if (nd == 0 && nt > 1) {544    // no date, multiple times545    speak("I heard multiple times and no date just now. Could you clarify a single date and time, please?", "Clarify");546    annyang.removeCommands();547    annyang.addCommands(cancelCommand);548    annyang.addCommands({ "*response": (response) => parseDeleteAlarmInput(response, null, null) });549  } else if (nd == 0 && nt == 0) {550    // no date, no time551    speak("Of course. And when is the alarm that you would like to delete set currently?", "Clarify");552    annyang.removeCommands();553    annyang.addCommands(cancelCommand);554    annyang.addCommands({ "*response": (response) => parseDeleteAlarmInput(response, null, null) });555  } else {556    // no idea557    speak("Sounds like you wanted to delete an existing alarm. Could you tell me when it's set currently?", "Clarify");558    annyang.removeCommands();559    annyang.addCommands(cancelCommand);560    annyang.addCommands({ "*response": (response) => parseDeleteAlarmInput(response, null, null) });561  }562}563/**564 * Deletes the alarm with the given time, or if time is not given, label.565 * @param {Date} time Time of the alarm to delete.566 * @param {String} label Label of the alarm to delete.567 * @param {Boolean} mute Whether to mute the system responses.568 */569function deleteAlarm(time, label, mute) {570  if (time) {571    // time is defined572    if (Object.hasOwn(alarms, time.getTime())) {573      // alarm exists574      window.clearInterval(alarms[time.getTime()].id); // stop testing this alarm575      const oldLabel = alarms[time.getTime()].label;576      if (oldLabel && Object.hasOwn(alarms, oldLabel)) {577        delete alarms[oldLabel]; // remove alarm by label578      }579      delete alarms[time.getTime()]; // remove alarm by time580      if (!mute) speak("Success! Your alarm was deleted.", "Success");581    } else {582      // alarm does not exist583      if (!mute) speak("I'm sorry, but there's no alarm set then currently to delete.", "Failure");584    }585  } else {586    // time is undefined587    if (label) {588      // label is defined589      if (Object.hasOwn(alarms, label)) {590        // alarm exists591        window.clearInterval(alarms[label].id); // stop testing this alarm592        const oldTime = alarms[label].time;593        if (oldTime && Object.hasOwn(alarms, oldTime.getTime())) {594          delete alarms[oldTime.getTime()]; // remove alarm by time595        }596        delete alarms[label]; // remove alarm by label597        if (!mute) speak("Success! Your alarm was deleted.", "Success");598      } else {599        // alarm does not exist600        if (!mute) speak("I'm sorry, but there's no alarm with that label currently to delete.", "Failure");601      }602    } else {603      // both time and label are undefined604      console.log(`date and time given to deleteAlarm: ${time}`);605      console.log(`label given to deleteAlarm: ${label}`);606      if (!mute)607        speak(608          "I'm sorry, but something seems to be wrong with either the provided date and time or label. Please check the console for details.",609          "Error"610        );611    }612  }613  console.log("alarms:");614  console.log(alarms);615}616function parseEditAlarmInput(userInput, d, t, newD, newT) {617  const parts = userInput.split(" to "); // use to determine what to edit618  if (parts.length == 1) {619    // no 'to' used as separator => look for subject date/time620    if (!d || !t) {621      // still looking for 'from' subject622      const userInputFromDoc = nlp(parts[0]); // parse input using compromise623      let dates, times;624      let nd = 0;625      let nt = 0;626      if (!d) {627        // only look for a date if one isn't provided628        dates = userInputFromDoc.dates().json();629        nd = dates.length; // number of dates found630      }631      if (d) nd += 1; // date is given632      if (!t) {633        // only look for a time if one isn't provided634        times = userInputFromDoc.times().json();635        nt = times.length; // number of times found636      }637      if (t) nt += 1; // time is given638      if (nd == 1 && nt == 1) {639        // one date, one time => 'from' subject found.640        if (!d) d = new Date(dates[0].start);641        if (!t) t = toTime(times[0].time);642        const target = new Date(d.getFullYear(), d.getMonth(), d.getDate(), t.hours, t.minutes, 0);643        if (Object.hasOwn(alarms, target.getTime())) {644          // found alarm to edit => ask for new date/time for that alarm645          speak("I found the alarm you want to edit! And to when do you want the alarm changed?", "Clarify");646          annyang.removeCommands();647          annyang.addCommands(cancelCommand);648          annyang.addCommands({ "*response": (response) => parseEditAlarmInput(response, d, t, null, null) });649        } else {650          // couldn't find alarm to edit => inform user651          speak("I'm sorry, I couldn't find the alarm you wanted to edit at time you gave me.", "Failure");652          // reset commands653          annyang.removeCommands();654          annyang.addCommands(keywordCommand);655          annyang.addCommands(cancelCommand);656        }657      } else if (nd == 1 && nt > 1) {658        // one date, multiple times659        if (!d) d = new Date(dates[0].start);660        speak(661          "I heard multiple times just now. Could you clarify at which time the alarm you want to edit is?",662          "Clarify"663        );664        annyang.removeCommands();665        annyang.addCommands(cancelCommand);666        annyang.addCommands({ "*response": (response) => parseEditAlarmInput(response, d, null, null, null) });667      } else if (nd == 1 && nt == 0) {668        // one date, no time669        if (!d) d = new Date(dates[0].start);670        speak("For sure. And at what time is the alarm you would like to edit?", "Clarify");671        annyang.removeCommands();672        annyang.addCommands(cancelCommand);673        annyang.addCommands({ "*response": (response) => parseEditAlarmInput(response, d, null, null, null) });674      } else if (nd > 1 && nt == 1) {675        // multiple dates, one time676        if (!t) t = toTime(times[0].time);677        speak(678          "I heard multiple days just now. Could you clarify on which day the alarm you want to edit is?",679          "Clarify"680        );681        annyang.removeCommands();682        annyang.addCommands(cancelCommand);683        annyang.addCommands({ "*response": (response) => parseEditAlarmInput(response, null, t, null, null) });684      } else if (nd > 1 && nt > 1) {685        // multiple dates, multiple times686        speak("I heard multiple days and times just now. Could you clarify a single date and time, please?", "Clarify");687        annyang.removeCommands();688        annyang.addCommands(cancelCommand);689        annyang.addCommands({ "*response": (response) => parseEditAlarmInput(response, null, null, null, null) });690      } else if (nd > 1 && nt == 0) {691        // multiple dates, no time692        speak(693          "I heard multiple days and no time just now. Could you clarify a single date and time, please?",694          "Clarify"695        );696        annyang.removeCommands();697        annyang.addCommands(cancelCommand);698        annyang.addCommands({ "*response": (response) => parseEditAlarmInput(response, null, null, null, null) });699      } else if (nd == 0 && nt == 1) {700        // no date, one time701        if (!t) t = toTime(times[0].time);702        speak("Without a doubt. And on what day is the alarm you would like to edit?", "Clarify");703        annyang.removeCommands();704        annyang.addCommands(cancelCommand);705        annyang.addCommands({ "*response": (response) => parseEditAlarmInput(response, null, t, null, null) });706      } else if (nd == 0 && nt > 1) {707        // no date, multiple times708        speak(709          "I heard multiple times and no date just now. Could you clarify a single date and time, please?",710          "Clarify"711        );712        annyang.removeCommands();713        annyang.addCommands(cancelCommand);714        annyang.addCommands({ "*response": (response) => parseEditAlarmInput(response, null, null, null, null) });715      } else if (nd == 0 && nt == 0) {716        // no date, no time717        speak("Ok. And when is the alarm that you would like to edit set currently?", "Clarify");718        annyang.removeCommands();719        annyang.addCommands(cancelCommand);720        annyang.addCommands({ "*response": (response) => parseEditAlarmInput(response, null, null, null, null) });721      } else {722        // no idea723        speak(724          "Sounds like you wanted to edit an existing alarm. Could you tell me when it's set currently?",725          "Clarify"726        );727        annyang.removeCommands();728        annyang.addCommands(cancelCommand);729        annyang.addCommands({ "*response": (response) => parseEditAlarmInput(response, null, null, null, null) });730      }731    } else {732      // now looking for 'to' subject733      const userInputToDoc = nlp(parts[0]); // parse input using compromise734      let dates, times;735      let nd = 0;736      let nt = 0;737      if (!newD) {738        // only look for a date if one isn't provided739        dates = userInputToDoc.dates().json();740        nd = dates.length; // number of dates found741      }742      if (newD) nd += 1; // date is given743      if (!newT) {744        // only look for a time if one isn't provided745        times = userInputToDoc.times().json();746        nt = times.length; // number of times found747      }748      if (newT) nt += 1; // time is given749      if (nd == 1 && nt == 1) {750        // one date, one time => 'to' subject found.751        if (!newD) newD = new Date(dates[0].start);752        if (!newT) newT = toTime(times[0].time);753        const target = new Date(d.getFullYear(), d.getMonth(), d.getDate(), t.hours, t.minutes, 0);754        const newTarget = new Date(newD.getFullYear(), newD.getMonth(), newD.getDate(), newT.hours, newT.minutes, 0);755        editAlarmTime(target, null, newTarget);756        // reset commands757        annyang.removeCommands();758        annyang.addCommands(keywordCommand);759        annyang.addCommands(cancelCommand);760      } else if (nd == 1 && nt > 1) {761        // one date, multiple times762        if (!newD) newD = new Date(dates[0].start);763        speak(764          "I heard multiple times just now. Could you clarify what time you want to change the alarm to?",765          "Clarify"766        );767        annyang.removeCommands();768        annyang.addCommands(cancelCommand);769        annyang.addCommands({ "*response": (response) => parseEditAlarmInput(response, d, t, newD, null) });770      } else if (nd == 1 && nt == 0) {771        // one date, no time772        if (!newD) newD = new Date(dates[0].start);773        speak("Of course. And what time do you want the alarm to be changed to?", "Clarify");774        annyang.removeCommands();775        annyang.addCommands(cancelCommand);776        annyang.addCommands({ "*response": (response) => parseEditAlarmInput(response, d, t, newD, null) });777      } else if (nd > 1 && nt == 1) {778        // multiple dates, one time779        if (!newT) newT = toTime(times[0].time);780        speak(781          "I heard multiple days just now. Could you clarify which day you want the alarm to be changed to?",782          "Clarify"783        );784        annyang.removeCommands();785        annyang.addCommands(cancelCommand);786        annyang.addCommands({ "*response": (response) => parseEditAlarmInput(response, d, t, null, newT) });787      } else if (nd > 1 && nt > 1) {788        // multiple dates, multiple times789        speak("I heard multiple days and times just now. Could you clarify a single date and time, please?", "Clarify");790        annyang.removeCommands();791        annyang.addCommands(cancelCommand);792        annyang.addCommands({ "*response": (response) => parseEditAlarmInput(response, d, t, null, null) });793      } else if (nd > 1 && nt == 0) {794        // multiple dates, no time795        speak(796          "I heard multiple days and no time just now. Could you clarify a single date and time, please?",797          "Clarify"798        );799        annyang.removeCommands();800        annyang.addCommands(cancelCommand);801        annyang.addCommands({ "*response": (response) => parseEditAlarmInput(response, d, t, null, null) });802      } else if (nd == 0 && nt == 1) {803        // no date, one time804        if (!newT) newT = toTime(times[0].time);805        speak("You got it. And what day do you want to change the alarm to?", "Clarify");806        annyang.removeCommands();807        annyang.addCommands(cancelCommand);808        annyang.addCommands({ "*response": (response) => parseEditAlarmInput(response, d, t, null, newT) });809      } else if (nd == 0 && nt > 1) {810        // no date, multiple times811        speak(812          "I heard multiple times and no date just now. Could you clarify a single date and time, please?",813          "Clarify"814        );815        annyang.removeCommands();816        annyang.addCommands(cancelCommand);817        annyang.addCommands({ "*response": (response) => parseEditAlarmInput(response, d, t, null, null) });818      } else if (nd == 0 && nt == 0) {819        // no date, no time820        speak("On it. And to when do you want the alarm changed?", "Clarify");821        annyang.removeCommands();822        annyang.addCommands(cancelCommand);823        annyang.addCommands({ "*response": (response) => parseEditAlarmInput(response, d, t, null, null) });824      } else {825        // no idea826        speak("I'm sorry, could you repeat to when you want the alarm changed?", "Clarify");827        annyang.removeCommands();828        annyang.addCommands(cancelCommand);829        annyang.addCommands({ "*response": (response) => parseEditAlarmInput(response, d, t, null, null) });830      }831    }832  } else if (parts.length == 2) {833    // assume 'from' and 'to' are in order => get subject for each834    const userInputFromDoc = nlp(parts[0]); // parse input using compromise835    const userInputToDoc = nlp(parts[1]); // parse input using compromise836    let dates, times;837    let nfd = 0; // number 'from' dates838    let ntd = 0; // number 'to' dates839    let nft = 0; // number 'from' times840    let ntt = 0; // number 'to' times841    if (!d) {842      // only look for a date if one isn't provided843      dates = userInputFromDoc.dates().json();844      nfd = dates.length; // number of dates found845    }846    if (d) nfd += 1; // date is given847    if (!t) {848      // only look for a time if one isn't provided849      times = userInputFromDoc.times().json();850      nft = times.length; // number of times found851    }852    if (t) nft += 1; // time is given853    if (!newD) {854      // only look for a date if one isn't provided855      dates = userInputToDoc.dates().json();856      ntd = dates.length; // number of dates found857    }858    if (newD) ntd += 1; // date is given859    if (!newT) {860      // only look for a time if one isn't provided861      times = userInputToDoc.times().json();862      ntt = times.length; // number of times found863    }864    if (newT) ntt += 1; // time is given865    if (nfd == 1 && ntd == 1 && nft == 1 && ntt == 1) {866      // one of each => 'from' and 'to' subject found.867      if (!d) d = new Date(dates[0].start);868      if (!t) t = toTime(times[0].time);869      if (!newD) newD = new Date(dates[0].start);870      if (!newT) newT = toTime(times[0].time);871      const target = new Date(d.getFullYear(), d.getMonth(), d.getDate(), t.hours, t.minutes, 0);872      const newTarget = new Date(newD.getFullYear(), newD.getMonth(), newD.getDate(), newT.hours, newT.minutes, 0);873      editAlarmTime(target, null, newTarget);874      // reset commands875      annyang.removeCommands();876      annyang.addCommands(keywordCommand);877      annyang.addCommands(cancelCommand);878    } else {879      // look for 'from' subject880      if (nfd == 1 && nft == 1) {881        // one date, one time => 'from' subject found.882        if (!d) d = new Date(dates[0].start);883        if (!t) t = toTime(times[0].time);884        const target = new Date(d.getFullYear(), d.getMonth(), d.getDate(), t.hours, t.minutes, 0);885        if (!Object.hasOwn(alarms, target.getTime())) {886          // couldn't find alarm to edit => inform user887          speak("I'm sorry, I couldn't find the alarm you wanted to edit at time you gave me.", "Failure");888          // reset commands889          annyang.removeCommands();890          annyang.addCommands(keywordCommand);891          annyang.addCommands(cancelCommand);892        } else {893          // look for 'to' subject894          if (ntd == 1 && ntt > 1) {895            // one date, multiple times896            if (!newD) newD = new Date(dates[0].start);897            speak(898              "I heard multiple times just now. Could you clarify what time you want to change the alarm to?",899              "Clarify"900            );901            annyang.removeCommands();902            annyang.addCommands(cancelCommand);903            annyang.addCommands({ "*response": (response) => parseEditAlarmInput(response, d, t, newD, null) });904          } else if (ntd == 1 && ntt == 0) {905            // one date, no time906            if (!newD) newD = new Date(dates[0].start);907            speak("Of course. And what time do you want the alarm to be changed to?", "Clarify");908            annyang.removeCommands();909            annyang.addCommands(cancelCommand);910            annyang.addCommands({ "*response": (response) => parseEditAlarmInput(response, d, t, newD, null) });911          } else if (ntd > 1 && ntt == 1) {912            // multiple dates, one time913            if (!newT) newT = toTime(times[0].time);914            speak(915              "I heard multiple days just now. Could you clarify which day you want the alarm to be changed to?",916              "Clarify"917            );918            annyang.removeCommands();919            annyang.addCommands(cancelCommand);920            annyang.addCommands({ "*response": (response) => parseEditAlarmInput(response, d, t, null, newT) });921          } else if (ntd > 1 && ntt > 1) {922            // multiple dates, multiple times923            speak(924              "I heard multiple days and times just now. Could you clarify a single date and time, please?",925              "Clarify"926            );927            annyang.removeCommands();928            annyang.addCommands(cancelCommand);929            annyang.addCommands({ "*response": (response) => parseEditAlarmInput(response, d, t, null, null) });930          } else if (ntd > 1 && ntt == 0) {931            // multiple dates, no time932            speak(933              "I heard multiple days and no time just now. Could you clarify a single date and time, please?",934              "Clarify"935            );936            annyang.removeCommands();937            annyang.addCommands(cancelCommand);938            annyang.addCommands({ "*response": (response) => parseEditAlarmInput(response, d, t, null, null) });939          } else if (ntd == 0 && ntt == 1) {940            // no date, one time941            if (!newT) newT = toTime(times[0].time);942            speak("You got it. And what day do you want to change the alarm to?", "Clarify");943            annyang.removeCommands();944            annyang.addCommands(cancelCommand);945            annyang.addCommands({ "*response": (response) => parseEditAlarmInput(response, d, t, null, newT) });946          } else if (ntd == 0 && ntt > 1) {947            // no date, multiple times948            speak(949              "I heard multiple times and no date just now. Could you clarify a single date and time, please?",950              "Clarify"951            );952            annyang.removeCommands();953            annyang.addCommands(cancelCommand);954            annyang.addCommands({ "*response": (response) => parseEditAlarmInput(response, d, t, null, null) });955          } else if (ntd == 0 && ntt == 0) {956            // no date, no time957            speak("On it. And to when do you want the alarm changed?", "Clarify");958            annyang.removeCommands();959            annyang.addCommands(cancelCommand);960            annyang.addCommands({ "*response": (response) => parseEditAlarmInput(response, d, t, null, null) });961          } else {962            // no idea963            speak("I'm sorry, could you repeat to when you want the alarm changed?", "Clarify");964            annyang.removeCommands();965            annyang.addCommands(cancelCommand);966            annyang.addCommands({ "*response": (response) => parseEditAlarmInput(response, d, t, null, null) });967          }968        }969      } else if (nfd == 1 && nft > 1) {970        // one date, multiple times971        if (!d) d = new Date(dates[0].start);972        speak(973          "I heard multiple times just now. Could you clarify at which time the alarm you want to edit is?",974          "Clarify"975        );976        annyang.removeCommands();977        annyang.addCommands(cancelCommand);978        annyang.addCommands({ "*response": (response) => parseEditAlarmInput(response, d, null, null, null) });979      } else if (nfd == 1 && nft == 0) {980        // one date, no time981        if (!d) d = new Date(dates[0].start);982        speak("For sure. And at what time is the alarm you would like to edit?", "Clarify");983        annyang.removeCommands();984        annyang.addCommands(cancelCommand);985        annyang.addCommands({ "*response": (response) => parseEditAlarmInput(response, d, null, null, null) });986      } else if (nfd > 1 && nft == 1) {987        // multiple dates, one time988        if (!t) t = toTime(times[0].time);989        speak(990          "I heard multiple days just now. Could you clarify on which day the alarm you want to edit is?",991          "Clarify"992        );993        annyang.removeCommands();994        annyang.addCommands(cancelCommand);995        annyang.addCommands({ "*response": (response) => parseEditAlarmInput(response, null, t, null, null) });996      } else if (nfd > 1 && nft > 1) {997        // multiple dates, multiple times998        speak("I heard multiple days and times just now. Could you clarify a single date and time, please?", "Clarify");999        annyang.removeCommands();1000        annyang.addCommands(cancelCommand);1001        annyang.addCommands({ "*response": (response) => parseEditAlarmInput(response, null, null, null, null) });1002      } else if (nfd > 1 && nft == 0) {1003        // multiple dates, no time1004        speak(1005          "I heard multiple days and no time just now. Could you clarify a single date and time, please?",1006          "Clarify"1007        );1008        annyang.removeCommands();1009        annyang.addCommands(cancelCommand);1010        annyang.addCommands({ "*response": (response) => parseEditAlarmInput(response, null, null, null, null) });1011      } else if (nfd == 0 && nft == 1) {1012        // no date, one time1013        if (!t) t = toTime(times[0].time);1014        speak("Without a doubt. And on what day is the alarm you would like to edit?", "Clarify");1015        annyang.removeCommands();1016        annyang.addCommands(cancelCommand);1017        annyang.addCommands({ "*response": (response) => parseEditAlarmInput(response, null, t, null, null) });1018      } else if (nfd == 0 && nft > 1) {1019        // no date, multiple times1020        speak(1021          "I heard multiple times and no date just now. Could you clarify a single date and time, please?",1022          "Clarify"1023        );1024        annyang.removeCommands();1025        annyang.addCommands(cancelCommand);1026        annyang.addCommands({ "*response": (response) => parseEditAlarmInput(response, null, null, null, null) });1027      } else if (nfd == 0 && nft == 0) {1028        // no date, no time1029        speak("Ok. And when is the alarm that you would like to edit set currently?", "Clarify");1030        annyang.removeCommands();1031        annyang.addCommands(cancelCommand);1032        annyang.addCommands({ "*response": (response) => parseEditAlarmInput(response, null, null, null, null) });1033      } else {1034        // no idea1035        speak(1036          "Sounds like you wanted to edit an existing alarm. Could you tell me when it's set currently?",1037          "Clarify"1038        );1039        annyang.removeCommands();1040        annyang.addCommands(cancelCommand);1041        annyang.addCommands({ "*response": (response) => parseEditAlarmInput(response, null, null, null, null) });1042      }1043    }1044  } else {1045    // no idea1046    speak(1047      "Sounds like you wanted to edit an existing alarm. Could you tell me which alarm you want to change and how you want to change it?",1048      "Clarify"1049    );1050    annyang.removeCommands();1051    annyang.addCommands(cancelCommand);1052    annyang.addCommands({ "*response": (response) => parseDeleteAlarmInput(response, null, null) });1053  }1054}1055/**1056 * Sets the `time` prop of an alarm with the given time, or if the time is not1057 * give, label, to the given value.1058 * @param {Date} time Time of the alarm to edit.1059 * @param {String} label Label of the alarm to edit.1060 * @param {Date} newTime New time to give to the alarm.1061 */1062function editAlarmTime(time, label, newTime) {1063  if (time) {1064    // time is defined1065    if (Object.hasOwn(alarms, time.getTime())) {1066      // alarm exists1067      const oldLabel = alarms[time.getTime()].label;1068      const oldEnabled = alarms[time.getTime()].enabled;1069      deleteAlarm(time, oldLabel, true); // mute system1070      setAlarm(newTime, oldLabel, oldEnabled, true); // mute system1071      speak("Success! Your alarm was changed.", "Success");1072    } else {1073      // alarm does not exist1074      speak("I'm sorry, but there's no alarm set then currently to edit.", "Failure");1075    }1076  } else {1077    // time is undefined1078    if (label) {1079      // label is defined1080      if (Object.hasOwn(alarms, label)) {1081        // alarm exists1082        const oldTime = alarms[label].time;1083        const oldEnabled = alarms[label].enabled;1084        deleteAlarm(oldTime, label, true); // mute system1085        setAlarm(newTime, label, oldEnabled, true); // mute system1086        speak("Success! Your alarm was changed.", "Success");1087      } else {1088        // alarm does not exist1089        speak("I'm sorry, but there's no alarm with that label currently to edit.", "Failure");1090      }1091    } else {1092      // both time and label are undefined1093      console.log(`date and time given to editAlarmTime: ${time}`);1094      console.log(`label given to editAlarmTime: ${label}`);1095      if (!mute)1096        speak(1097          "I'm sorry, but something seems to be wrong with either the provided date and time or label. Please check the console for details.",1098          "Error"1099        );1100    }1101  }1102  console.log("alarms:");1103  console.log(alarms);1104}1105/**1106 * Sets the `label` prop of an alarm with the given time, or if the time is not1107 * give, label, to the given value.1108 * @param {Date} time Time of the alarm to edit.1109 * @param {String} label Label of the alarm to edit.1110 * @param {String} newLabel New label to give to the alarm.1111 */1112function editAlarmLabel(time, label, newLabel) {1113  if (time && Object.hasOwn(alarms, time.getTime())) {1114    const oldLabel = alarms[time.getTime()].label;1115    const oldEnabled = alarms[time.getTime()].enabled;1116    deleteAlarm(time, oldLabel, true); // mute system1117    setAlarm(time, newLabel, oldEnabled, true); // mute system1118  } else if (label && Object.hasOwn(alarms, label)) {1119    const oldTime = alarms[label].time;1120    const oldEnabled = alarms[label].enabled;1121    deleteAlarm(oldTime, label, true); // mute system1122    setAlarm(oldTime, newLabel, oldEnabled, true); // mute system1123  }1124  console.log("alarms:");1125  console.log(alarms);1126}1127function parseEnableAlarmInput(userInput, d, t) {1128  const userInputDoc = nlp(userInput); // parse input using compromise1129  let dates, times;1130  let nd = 0;1131  let nt = 0;1132  if (!d) {1133    // only look for a date if one isn't provided1134    dates = userInputDoc.dates().json();1135    nd = dates.length; // number of dates found1136  }1137  if (d) nd += 1; // date is given1138  if (!t) {1139    // only look for a time if one isn't provided1140    times = userInputDoc.times().json();1141    nt = times.length; // number of times found1142  }1143  if (t) nt += 1; // time is given1144  if (nd == 1 && nt == 1) {1145    // one date, one time => try to enable an alarm with the provided inputs1146    if (!d) d = new Date(dates[0].start);1147    if (!t) t = toTime(times[0].time);1148    const target = new Date(d.getFullYear(), d.getMonth(), d.getDate(), t.hours, t.minutes, 0);1149    editAlarmEnabled(target, null, true);1150    // reset commands1151    annyang.removeCommands();1152    annyang.addCommands(keywordCommand);1153    annyang.addCommands(cancelCommand);1154  } else if (nd == 1 && nt > 1) {1155    // one date, multiple times1156    if (!d) d = new Date(dates[0].start);1157    speak(1158      "I heard multiple times just now. Could you clarify at which time the alarm you want to enable is?",1159      "Clarify"1160    );1161    annyang.removeCommands();1162    annyang.addCommands(cancelCommand);1163    annyang.addCommands({ "*response": (response) => parseEnableAlarmInput(response, d, null) });1164  } else if (nd == 1 && nt == 0) {1165    // one date, no time1166    if (!d) d = new Date(dates[0].start);1167    speak("For sure. And at what time is the alarm you would like to enable?", "Clarify");1168    annyang.removeCommands();1169    annyang.addCommands(cancelCommand);1170    annyang.addCommands({ "*response": (response) => parseEnableAlarmInput(response, d, null) });1171  } else if (nd > 1 && nt == 1) {1172    // multiple dates, one time1173    if (!t) t = toTime(times[0].time);1174    speak("I heard multiple days just now. Could you clarify on which day the alarm you want to enable is?", "Clarify");1175    annyang.removeCommands();1176    annyang.addCommands(cancelCommand);1177    annyang.addCommands({ "*response": (response) => parseEnableAlarmInput(response, null, t) });1178  } else if (nd > 1 && nt > 1) {1179    // multiple dates, multiple times1180    speak("I heard multiple days and times just now. Could you clarify a single date and time, please?", "Clarify");1181    annyang.removeCommands();1182    annyang.addCommands(cancelCommand);1183    annyang.addCommands({ "*response": (response) => parseEnableAlarmInput(response, null, null) });1184  } else if (nd > 1 && nt == 0) {1185    // multiple dates, no time1186    speak("I heard multiple days and no time just now. Could you clarify a single date and time, please?", "Clarify");1187    annyang.removeCommands();1188    annyang.addCommands(cancelCommand);1189    annyang.addCommands({ "*response": (response) => parseEnableAlarmInput(response, null, null) });1190  } else if (nd == 0 && nt == 1) {1191    // no date, one time1192    if (!t) t = toTime(times[0].time);1193    speak("Without a doubt. And on what day is the alarm you would like to enable?", "Clarify");1194    annyang.removeCommands();1195    annyang.addCommands(cancelCommand);1196    annyang.addCommands({ "*response": (response) => parseEnableAlarmInput(response, null, t) });1197  } else if (nd == 0 && nt > 1) {1198    // no date, multiple times1199    speak("I heard multiple times and no date just now. Could you clarify a single date and time, please?", "Clarify");1200    annyang.removeCommands();1201    annyang.addCommands(cancelCommand);1202    annyang.addCommands({ "*response": (response) => parseEnableAlarmInput(response, null, null) });1203  } else if (nd == 0 && nt == 0) {1204    // no date, no time1205    speak("Yes. And when is the alarm that you would like to enable set currently?", "Clarify");1206    annyang.removeCommands();1207    annyang.addCommands(cancelCommand);1208    annyang.addCommands({ "*response": (response) => parseEnableAlarmInput(response, null, null) });1209  } else {1210    // no idea1211    speak("Sounds like you wanted to enable an existing alarm. Could you tell me when it's set currently?", "Clarify");1212    annyang.removeCommands();1213    annyang.addCommands(cancelCommand);1214    annyang.addCommands({ "*response": (response) => parseEnableAlarmInput(response, null, null) });1215  }1216}1217function parseDisableAlarmInput(userInput, d, t) {1218  const userInputDoc = nlp(userInput); // parse input using compromise1219  let dates, times;1220  let nd = 0;1221  let nt = 0;1222  if (!d) {1223    // only look for a date if one isn't provided1224    dates = userInputDoc.dates().json();1225    nd = dates.length; // number of dates found1226  }1227  if (d) nd += 1; // date is given1228  if (!t) {1229    // only look for a time if one isn't provided1230    times = userInputDoc.times().json();1231    nt = times.length; // number of times found1232  }1233  if (t) nt += 1; // time is given1234  if (nd == 1 && nt == 1) {1235    // one date, one time => try to disable an alarm with the provided inputs1236    if (!d) d = new Date(dates[0].start);1237    if (!t) t = toTime(times[0].time);1238    const target = new Date(d.getFullYear(), d.getMonth(), d.getDate(), t.hours, t.minutes, 0);1239    editAlarmEnabled(target, null, false);1240    // reset commands1241    annyang.removeCommands();1242    annyang.addCommands(keywordCommand);1243    annyang.addCommands(cancelCommand);1244  } else if (nd == 1 && nt > 1) {1245    // one date, multiple times1246    if (!d) d = new Date(dates[0].start);1247    speak(1248      "I heard multiple times just now. Could you clarify at which time the alarm you want to disable is?",1249      "Clarify"1250    );1251    annyang.removeCommands();1252    annyang.addCommands(cancelCommand);1253    annyang.addCommands({ "*response": (response) => parseDisableAlarmInput(response, d, null) });1254  } else if (nd == 1 && nt == 0) {1255    // one date, no time1256    if (!d) d = new Date(dates[0].start);1257    speak("At what time is the alarm you would like to disable?", "Clarify");1258    annyang.removeCommands();1259    annyang.addCommands(cancelCommand);1260    annyang.addCommands({ "*response": (response) => parseDisableAlarmInput(response, d, null) });1261  } else if (nd > 1 && nt == 1) {1262    // multiple dates, one time1263    if (!t) t = toTime(times[0].time);1264    speak(1265      "I heard multiple days just now. Could you clarify on which day the alarm you want to disable is?",1266      "Clarify"1267    );1268    annyang.removeCommands();1269    annyang.addCommands(cancelCommand);1270    annyang.addCommands({ "*response": (response) => parseDisableAlarmInput(response, null, t) });1271  } else if (nd > 1 && nt > 1) {1272    // multiple dates, multiple times1273    speak("I heard multiple days and times just now. Could you clarify a single date and time, please?", "Clarify");1274    annyang.removeCommands();1275    annyang.addCommands(cancelCommand);1276    annyang.addCommands({ "*response": (response) => parseDisableAlarmInput(response, null, null) });1277  } else if (nd > 1 && nt == 0) {1278    // multiple dates, no time1279    speak("I heard multiple days and no time just now. Could you clarify a single date and time, please?", "Clarify");1280    annyang.removeCommands();1281    annyang.addCommands(cancelCommand);1282    annyang.addCommands({ "*response": (response) => parseDisableAlarmInput(response, null, null) });1283  } else if (nd == 0 && nt == 1) {1284    // no date, one time1285    if (!t) t = toTime(times[0].time);1286    speak("Sure. And on what day is the alarm you would like to disable?", "Clarify");1287    annyang.removeCommands();1288    annyang.addCommands(cancelCommand);1289    annyang.addCommands({ "*response": (response) => parseDisableAlarmInput(response, null, t) });1290  } else if (nd == 0 && nt > 1) {1291    // no date, multiple times1292    speak("I heard multiple times and no date just now. Could you clarify a single date and time, please?", "Clarify");1293    annyang.removeCommands();1294    annyang.addCommands(cancelCommand);1295    annyang.addCommands({ "*response": (response) => parseDisableAlarmInput(response, null, null) });1296  } else if (nd == 0 && nt == 0) {1297    // no date, no time1298    speak("And when is the alarm that you would like to disable set currently?", "Clarify");1299    annyang.removeCommands();1300    annyang.addCommands(cancelCommand);1301    annyang.addCommands({ "*response": (response) => parseDisableAlarmInput(response, null, null) });1302  } else {1303    // no idea1304    speak("Sounds like you wanted to disable an existing alarm. Could you tell me when it's set currently?", "Clarify");1305    annyang.removeCommands();1306    annyang.addCommands(cancelCommand);1307    annyang.addCommands({ "*response": (response) => parseDisableAlarmInput(response, null, null) });1308  }1309}1310/**1311 * Sets the `label` prop of an alarm with the given time, or if the time is not1312 * give, label, to the given value.1313 * @param {Date} time Time of the alarm to edit.1314 * @param {String} label Label of the alarm to edit.1315 * @param {String} newEnabled Whether to enable alarm or not.1316 */1317function editAlarmEnabled(time, label, newEnabled) {1318  if (time) {1319    // time is defined1320    if (Object.hasOwn(alarms, time.getTime())) {1321      // alarm exists1322      const oldLabel = alarms[time.getTime()].label;1323      deleteAlarm(time, oldLabel, true); // mute system1324      setAlarm(time, oldLabel, newEnabled, true); // mute system1325      speak(`Awesome! Your alarm was ${newEnabled ? "enabled" : "disabled"}.`, `Success`);1326    } else {1327      // alarm does not exist1328      speak(`I'm sorry, but there's no alarm set then currently to ${newEnabled ? "enable" : "disable"}.`, `Failure`);1329    }1330  } else {1331    // time is undefined1332    if (label) {1333      // label is defined1334      if (Object.hasOwn(alarms, label)) {1335        // alarm exists1336        const oldTime = alarms[label].time;1337        deleteAlarm(oldTime, label, true); // mute system1338        setAlarm(oldTime, label, newEnabled, true); // mute system1339        speak(`Awesome! Your alarm was ${newEnabled ? "enabled" : "disabled"}.`, `Success`);1340      } else {1341        // alarm does not exist1342        speak(1343          `I'm sorry, but there's no alarm with that label currently to ${newEnabled ? "enable" : "disable"}.`,1344          `Failure`1345        );1346      }1347    } else {1348      // both time and label are undefined1349      console.log(`date and time given to editAlarmEnabled: ${time}`);1350      console.log(`label given to editAlarmEnabled: ${label}`);1351      speak(1352        "I'm sorry, but something seems to be wrong with either the provided date and time or label. Please check the console for details.",1353        "Error"1354      );1355    }1356  }1357  console.log("alarms:");1358  console.log(alarms);1359}1360/** ============================== EVENTS ================================== */1361function parseSetEventInput(userInput, d, t, x) {1362  const userInputDoc = nlp(userInput); // parse input using compromise1363  let dates, times, durations;1364  let nd = 0; // number of dates found in the text1365  let nt = 0; // number of times found in the text1366  let nx = 0; // number of durations found in the text1367  if (d) nd += 1; // date is given1368  if (!d) {1369    // only look for a date if one isn't provided1370    dates = userInputDoc.dates().json();1371    nd = dates.length; // number of dates found1372  }1373  if (t) nt += 1; // time is given1374  if (!t) {1375    // only look for a time if one isn't provided1376    times = userInputDoc.times().json();1377    nt = times.length; // number of times found1378  }1379  if (x) nx += 1; // time is given1380  if (!x) {1381    // only look for a duration if one isn't provided1382    durations = userInput.match(/[0-9]+ (\bminutes?\b|\bhours?\b)/g);1383    if (durations == null) {1384      // no match1385      nx = 0;1386    } else {1387      // match1388      x = 0;1389      for (let i = 0; i < durations.length; i++) {1390        const num = parseInt(durations[i].split(" ")[0]);1391        const unit = durations[i].split(" ")[1];1392        if (unit == "minute" || unit == "minutes") {1393          x += num;1394        } else if (unit == "hour" || unit == "hours") {1395          x += num * 60;1396        }1397      }1398      nx = 1;1399    }1400  }1401  if (nd == 1 && nt == 1 && nx == 1) {1402    // one date, one time => try to set an event with the provided inputs1403    if (!d) d = new Date(dates[0].start);1404    if (!t) t = toTime(times[0].time);1405    const target = new Date(d.getFullYear(), d.getMonth(), d.getDate(), t.hours, t.minutes, 0);1406    setEvent(target, null, x, false);1407    // reset commands1408    annyang.removeCommands();1409    annyang.addCommands(keywordCommand);1410    annyang.addCommands(cancelCommand);1411  } else if (nd == 1 && nt == 1 && nx == 0) {1412    // one date, one time, no duration1413    if (!d) d = new Date(dates[0].start);1414    if (!t) t = toTime(times[0].time);1415    speak("And how long is your event for?", "Clarify");1416    annyang.removeCommands();1417    annyang.addCommands(cancelCommand);1418    annyang.addCommands({ "*response": (response) => parseSetEventInput(response, d, t, null) });1419  } else if (nd == 1 && nt > 1) {1420    // one date, multiple times1421    if (!d) d = new Date(dates[0].start);1422    speak(1423      "I heard multiple times to set that event for. Could you clarify which time you want to set your event for?",1424      "Clarify"1425    );1426    annyang.removeCommands();1427    annyang.addCommands(cancelCommand);1428    annyang.addCommands({ "*response": (response) => parseSetEventInput(response, d, null, x) });1429  } else if (nd == 1 && nt == 0) {1430    // one date, no time1431    if (!d) d = new Date(dates[0].start);1432    speak("Certainly! And what time would you like to set the event for?", "Clarify");1433    annyang.removeCommands();1434    annyang.addCommands(cancelCommand);1435    annyang.addCommands({ "*response": (response) => parseSetEventInput(response, d, null, x) });1436  } else if (nd > 1 && nt == 1) {1437    // multiple dates, one time1438    if (!t) t = toTime(times[0].time);1439    speak(1440      "I heard multiple days to set that event for. Could you clarify which day you want to set your event for?",1441      "Clarify"1442    );1443    annyang.removeCommands();1444    annyang.addCommands(cancelCommand);1445    annyang.addCommands({ "*response": (response) => parseSetEventInput(response, null, t, x) });1446  } else if (nd > 1 && nt > 1) {1447    // multiple dates, multiple times1448    speak(1449      "I heard multiple days and times to set that event for. Could you clarify a single date and time, please?",1450      "Clarify"1451    );1452    annyang.removeCommands();1453    annyang.addCommands(cancelCommand);1454    annyang.addCommands({ "*response": (response) => parseSetEventInput(response, null, null, x) });1455  } else if (nd > 1 && nt == 0) {1456    // multiple dates, no time1457    speak(1458      "I heard multiple days and no time to set that event for. Could you clarify a single date and time, please?",1459      "Clarify"1460    );1461    annyang.removeCommands();1462    annyang.addCommands(cancelCommand);1463    annyang.addCommands({ "*response": (response) => parseSetEventInput(response, null, null, x) });1464  } else if (nd == 0 && nt == 1) {1465    // no date, one time1466    if (!t) t = toTime(times[0].time);1467    speak("Absolutely! And what day would you like to set that event for?", "Clarify");1468    annyang.removeCommands();1469    annyang.addCommands(cancelCommand);1470    annyang.addCommands({ "*response": (response) => parseSetEventInput(response, null, t, x) });1471  } else if (nd == 0 && nt > 1) {1472    // no date, multiple times1473    speak(1474      "I heard multiple times and no date to set that event for. Could you clarify a single date and time, please?",1475      "Clarify"1476    );1477    annyang.removeCommands();1478    annyang.addCommands(cancelCommand);1479    annyang.addCommands({ "*response": (response) => parseSetEventInput(response, null, null, x) });1480  } else if (nd == 0 && nt == 0) {1481    // no date, no time1482    speak("Of course. And when would you like that event scheduled for?", "Clarify");1483    annyang.removeCommands();1484    annyang.addCommands(cancelCommand);1485    annyang.addCommands({ "*response": (response) => parseSetEventInput(response, null, null, x) });1486  } else {1487    // no idea1488    speak("Sounds like you wanted to set an event. Could you give me a date and a time?", "Clarify");1489    annyang.removeCommands();1490    annyang.addCommands(cancelCommand);1491    annyang.addCommands({ "*response": (response) => parseSetEventInput(response, null, null, x) });1492  }1493}1494/**1495 * Set an event for the time given with the given label.1496 * @param {Date} time Time to set the event for.1497 * @param {String} label (optional) A label for the event.1498 * @param {Number} duration How long the event runs, in minutes.1499 * @param {Boolean} mute Whether to mute the system responses.1500 */1501function setEvent(time, label, duration, mute) {1502  if (time) {1503    if (!Object.hasOwn(events, time.getTime())) {1504      eventID++; // get new event ID1505      events[time.getTime()] = { id: eventID, time: time, label: label, duration: duration }; // save event by time1506      if (label && !Object.hasOwn(events, label)) {1507        events[label] = { id: eventID, time: time, label: label, duration: duration }; // save event by label1508      }1509      if (!mute) speak("Great! Your event is set.", "Success");1510    } else {1511      if (!mute) speak("I'm sorry, but there's already an event set for that date and time.", "Failure");1512    }1513  } else {1514    console.log(`date and time given to setEvent: ${time}`);1515    if (!mute)1516      speak(1517        "I'm sorry, but something seems to be wrong with the provided date and time. Please check the console for details.",1518        "Error"1519      );1520  }1521  console.log("events:");1522  console.log(events);1523}1524function parseDeleteEventInput(userInput, d, t) {1525  const userInputDoc = nlp(userInput); // parse input using compromise1526  let dates, times;1527  let nd = 0;1528  let nt = 0;1529  if (!d) {1530    // only look for a date if one isn't provided1531    dates = userInputDoc.dates().json();1532    nd = dates.length; // number of dates found1533  }1534  if (d) nd += 1; // date is given1535  if (!t) {1536    // only look for a time if one isn't provided1537    times = userInputDoc.times().json();1538    nt = times.length; // number of times found1539  }1540  if (t) nt += 1; // time is given1541  if (nd == 1 && nt == 1) {1542    // one date, one time => try to delete an event with the provided inputs1543    if (!d) d = new Date(dates[0].start);1544    if (!t) t = toTime(times[0].time);1545    const target = new Date(d.getFullYear(), d.getMonth(), d.getDate(), t.hours, t.minutes, 0);1546    deleteEvent(target, null, false);1547    // reset commands1548    annyang.removeCommands();1549    annyang.addCommands(keywordCommand);1550    annyang.addCommands(cancelCommand);1551  } else if (nd == 1 && nt > 1) {1552    // one date, multiple times1553    if (!d) d = new Date(dates[0].start);1554    speak(1555      "I heard multiple times just now. Could you clarify at which time the event you want to delete is?",1556      "Clarify"1557    );1558    annyang.removeCommands();1559    annyang.addCommands(cancelCommand);1560    annyang.addCommands({ "*response": (response) => parseDeleteEventInput(response, d, null) });1561  } else if (nd == 1 && nt == 0) {1562    // one date, no time1563    if (!d) d = new Date(dates[0].start);1564    speak("Certainly! And at what time is the event you would like to delete?", "Clarify");1565    annyang.removeCommands();1566    annyang.addCommands(cancelCommand);1567    annyang.addCommands({ "*response": (response) => parseDeleteEventInput(response, d, null) });1568  } else if (nd > 1 && nt == 1) {1569    // multiple dates, one time1570    if (!t) t = toTime(times[0].time);1571    speak("I heard multiple days just now. Could you clarify on which day the event you want to delete is?", "Clarify");1572    annyang.removeCommands();1573    annyang.addCommands(cancelCommand);1574    annyang.addCommands({ "*response": (response) => parseDeleteEventInput(response, null, t) });1575  } else if (nd > 1 && nt > 1) {1576    // multiple dates, multiple times1577    speak("I heard multiple days and times just now. Could you clarify a single date and time, please?", "Clarify");1578    annyang.removeCommands();1579    annyang.addCommands(cancelCommand);1580    annyang.addCommands({ "*response": (response) => parseDeleteEventInput(response, null, null) });1581  } else if (nd > 1 && nt == 0) {1582    // multiple dates, no time1583    speak("I heard multiple days and no time just now. Could you clarify a single date and time, please?", "Clarify");1584    annyang.removeCommands();1585    annyang.addCommands(cancelCommand);1586    annyang.addCommands({ "*response": (response) => parseDeleteEventInput(response, null, null) });1587  } else if (nd == 0 && nt == 1) {1588    // no date, one time1589    if (!t) t = toTime(times[0].time);1590    speak("Absolutely! And on what day is the event you would like to delete?", "Clarify");1591    annyang.removeCommands();1592    annyang.addCommands(cancelCommand);1593    annyang.addCommands({ "*response": (response) => parseDeleteEventInput(response, null, t) });1594  } else if (nd == 0 && nt > 1) {1595    // no date, multiple times1596    speak("I heard multiple times and no date just now. Could you clarify a single date and time, please?", "Clarify");1597    annyang.removeCommands();1598    annyang.addCommands(cancelCommand);1599    annyang.addCommands({ "*response": (response) => parseDeleteEventInput(response, null, null) });1600  } else if (nd == 0 && nt == 0) {1601    // no date, no time1602    speak("Of course. And when is the event that you would like to delete set currently?", "Clarify");1603    annyang.removeCommands();1604    annyang.addCommands(cancelCommand);1605    annyang.addCommands({ "*response": (response) => parseDeleteEventInput(response, null, null) });1606  } else {1607    // no idea1608    speak("Sounds like you wanted to delete an existing event. Could you tell me when it's set currently?", "Clarify");1609    annyang.removeCommands();1610    annyang.addCommands(cancelCommand);1611    annyang.addCommands({ "*response": (response) => parseDeleteEventInput(response, null, null) });1612  }1613}1614/**1615 * Deletes the event with the given time, or if time is not given, label.1616 * @param {Date} time Time of the event to delete.1617 * @param {String} label Label of the event to delete.1618 * @param {Boolean} mute Whether to mute the system responses.1619 */1620function deleteEvent(time, label, mute) {1621  if (time) {1622    // time is defined1623    if (Object.hasOwn(events, time.getTime())) {1624      // event exists1625      const oldLabel = events[time.getTime()].label;1626      if (oldLabel && Object.hasOwn(events, oldLabel)) {1627        delete events[oldLabel]; // remove event by label1628      }1629      delete events[time.getTime()]; // remove event by time1630      if (!mute) speak("Success! Your event was deleted.", "Success");1631    } else {1632      // event does not exist1633      if (!mute) speak("I'm sorry, but there's no event set then currently to delete.", "Failure");1634    }1635  } else {1636    // time is undefined1637    if (label) {1638      // label is defined1639      if (Object.hasOwn(events, label)) {1640        // event exists1641        const oldTime = events[label].time;1642        if (oldTime && Object.hasOwn(events, oldTime.getTime())) {1643          delete events[oldTime.getTime()]; // remove event by time1644        }1645        delete events[label]; // remove event by label1646        if (!mute) speak("Success! Your event was deleted.", "Success");1647      } else {1648        // event does not exist1649        if (!mute) speak("I'm sorry, but there's no event with that label currently to delete.", "Failure");1650      }1651    } else {1652      // both time and label are undefined1653      console.log(`date and time given to deleteEvent: ${time}`);1654      console.log(`label given to deleteEvent: ${label}`);1655      if (!mute)1656        speak(1657          "I'm sorry, but something seems to be wrong with either the provided date and time or label. Please check the console for details.",1658          "Error"1659        );1660    }1661  }1662  console.log("events:");1663  console.log(events);1664}1665function parseEditEventInput(userInput, d, t, newD, newT) {1666  const parts = userInput.split(" to "); // use to determine what to edit1667  if (parts.length == 1) {1668    // no 'to' used as separator => look for subject date/time1669    if (!d || !t) {1670      // still looking for 'from' subject1671      const userInputFromDoc = nlp(parts[0]); // parse input using compromise1672      let dates, times;1673      let nd = 0;1674      let nt = 0;1675      if (!d) {1676        // only look for a date if one isn't provided1677        dates = userInputFromDoc.dates().json();1678        nd = dates.length; // number of dates found1679      }1680      if (d) nd += 1; // date is given1681      if (!t) {1682        // only look for a time if one isn't provided1683        times = userInputFromDoc.times().json();1684        nt = times.length; // number of times found1685      }1686      if (t) nt += 1; // time is given1687      if (nd == 1 && nt == 1) {1688        // one date, one time => 'from' subject found.1689        if (!d) d = new Date(dates[0].start);1690        if (!t) t = toTime(times[0].time);1691        const target = new Date(d.getFullYear(), d.getMonth(), d.getDate(), t.hours, t.minutes, 0);1692        if (Object.hasOwn(events, target.getTime())) {1693          // found event to edit => ask for new date/time for that event1694          speak("I found the event you want to edit! And to when do you want the event changed?", "Clarify");1695          annyang.removeCommands();1696          annyang.addCommands(cancelCommand);1697          annyang.addCommands({ "*response": (response) => parseEditEventInput(response, d, t, null, null) });1698        } else {1699          // couldn't find event to edit => inform user1700          speak("I'm sorry, I couldn't find the event you wanted to edit at time you gave me.", "Failure");1701          // reset commands1702          annyang.removeCommands();1703          annyang.addCommands(keywordCommand);1704          annyang.addCommands(cancelCommand);1705        }1706      } else if (nd == 1 && nt > 1) {1707        // one date, multiple times1708        if (!d) d = new Date(dates[0].start);1709        speak(1710          "I heard multiple times just now. Could you clarify at which time the event you want to edit is?",1711          "Clarify"1712        );1713        annyang.removeCommands();1714        annyang.addCommands(cancelCommand);1715        annyang.addCommands({ "*response": (response) => parseEditEventInput(response, d, null, null, null) });1716      } else if (nd == 1 && nt == 0) {1717        // one date, no time1718        if (!d) d = new Date(dates[0].start);1719        speak("For sure. And at what time is the event you would like to edit?", "Clarify");1720        annyang.removeCommands();1721        annyang.addCommands(cancelCommand);1722        annyang.addCommands({ "*response": (response) => parseEditEventInput(response, d, null, null, null) });1723      } else if (nd > 1 && nt == 1) {1724        // multiple dates, one time1725        if (!t) t = toTime(times[0].time);1726        speak(1727          "I heard multiple days just now. Could you clarify on which day the event you want to edit is?",1728          "Clarify"1729        );1730        annyang.removeCommands();1731        annyang.addCommands(cancelCommand);1732        annyang.addCommands({ "*response": (response) => parseEditEventInput(response, null, t, null, null) });1733      } else if (nd > 1 && nt > 1) {1734        // multiple dates, multiple times1735        speak("I heard multiple days and times just now. Could you clarify a single date and time, please?", "Clarify");1736        annyang.removeCommands();1737        annyang.addCommands(cancelCommand);1738        annyang.addCommands({ "*response": (response) => parseEditEventInput(response, null, null, null, null) });1739      } else if (nd > 1 && nt == 0) {1740        // multiple dates, no time1741        speak(1742          "I heard multiple days and no time just now. Could you clarify a single date and time, please?",1743          "Clarify"1744        );1745        annyang.removeCommands();1746        annyang.addCommands(cancelCommand);1747        annyang.addCommands({ "*response": (response) => parseEditEventInput(response, null, null, null, null) });1748      } else if (nd == 0 && nt == 1) {1749        // no date, one time1750        if (!t) t = toTime(times[0].time);1751        speak("Without a doubt. And on what day is the event you would like to edit?", "Clarify");1752        annyang.removeCommands();1753        annyang.addCommands(cancelCommand);1754        annyang.addCommands({ "*response": (response) => parseEditEventInput(response, null, t, null, null) });1755      } else if (nd == 0 && nt > 1) {1756        // no date, multiple times1757        speak(1758          "I heard multiple times and no date just now. Could you clarify a single date and time, please?",1759          "Clarify"1760        );1761        annyang.removeCommands();1762        annyang.addCommands(cancelCommand);1763        annyang.addCommands({ "*response": (response) => parseEditEventInput(response, null, null, null, null) });1764      } else if (nd == 0 && nt == 0) {1765        // no date, no time1766        speak("Ok. And when is the event that you would like to edit set currently?", "Clarify");1767        annyang.removeCommands();1768        annyang.addCommands(cancelCommand);1769        annyang.addCommands({ "*response": (response) => parseEditEventInput(response, null, null, null, null) });1770      } else {1771        // no idea1772        speak(1773          "Sounds like you wanted to edit an existing event. Could you tell me when it's set currently?",1774          "Clarify"1775        );1776        annyang.removeCommands();1777        annyang.addCommands(cancelCommand);1778        annyang.addCommands({ "*response": (response) => parseEditEventInput(response, null, null, null, null) });1779      }1780    } else {1781      // now looking for 'to' subject1782      const userInputToDoc = nlp(parts[0]); // parse input using compromise1783      let dates, times;1784      let nd = 0;1785      let nt = 0;1786      if (!newD) {1787        // only look for a date if one isn't provided1788        dates = userInputToDoc.dates().json();1789        nd = dates.length; // number of dates found1790      }1791      if (newD) nd += 1; // date is given1792      if (!newT) {1793        // only look for a time if one isn't provided1794        times = userInputToDoc.times().json();1795        nt = times.length; // number of times found1796      }1797      if (newT) nt += 1; // time is given1798      if (nd == 1 && nt == 1) {1799        // one date, one time => 'to' subject found.1800        if (!newD) newD = new Date(dates[0].start);1801        if (!newT) newT = toTime(times[0].time);1802        const target = new Date(d.getFullYear(), d.getMonth(), d.getDate(), t.hours, t.minutes, 0);1803        const newTarget = new Date(newD.getFullYear(), newD.getMonth(), newD.getDate(), newT.hours, newT.minutes, 0);1804        editEventTime(target, null, newTarget);1805        // reset commands1806        annyang.removeCommands();1807        annyang.addCommands(keywordCommand);1808        annyang.addCommands(cancelCommand);1809      } else if (nd == 1 && nt > 1) {1810        // one date, multiple times1811        if (!newD) newD = new Date(dates[0].start);1812        speak(1813          "I heard multiple times just now. Could you clarify what time you want to change the event to?",1814          "Clarify"1815        );1816        annyang.removeCommands();1817        annyang.addCommands(cancelCommand);1818        annyang.addCommands({ "*response": (response) => parseEditEventInput(response, d, t, newD, null) });1819      } else if (nd == 1 && nt == 0) {1820        // one date, no time1821        if (!newD) newD = new Date(dates[0].start);1822        speak("Of course. And what time do you want the event to be changed to?", "Clarify");1823        annyang.removeCommands();1824        annyang.addCommands(cancelCommand);1825        annyang.addCommands({ "*response": (response) => parseEditEventInput(response, d, t, newD, null) });1826      } else if (nd > 1 && nt == 1) {1827        // multiple dates, one time1828        if (!newT) newT = toTime(times[0].time);1829        speak(1830          "I heard multiple days just now. Could you clarify which day you want the event to be changed to?",1831          "Clarify"1832        );1833        annyang.removeCommands();1834        annyang.addCommands(cancelCommand);1835        annyang.addCommands({ "*response": (response) => parseEditEventInput(response, d, t, null, newT) });1836      } else if (nd > 1 && nt > 1) {1837        // multiple dates, multiple times1838        speak("I heard multiple days and times just now. Could you clarify a single date and time, please?", "Clarify");1839        annyang.removeCommands();1840        annyang.addCommands(cancelCommand);1841        annyang.addCommands({ "*response": (response) => parseEditEventInput(response, d, t, null, null) });1842      } else if (nd > 1 && nt == 0) {1843        // multiple dates, no time1844        speak(1845          "I heard multiple days and no time just now. Could you clarify a single date and time, please?",1846          "Clarify"1847        );1848        annyang.removeCommands();1849        annyang.addCommands(cancelCommand);1850        annyang.addCommands({ "*response": (response) => parseEditEventInput(response, d, t, null, null) });1851      } else if (nd == 0 && nt == 1) {1852        // no date, one time1853        if (!newT) newT = toTime(times[0].time);1854        speak("You got it. And what day do you want to change the event to?", "Clarify");1855        annyang.removeCommands();1856        annyang.addCommands(cancelCommand);1857        annyang.addCommands({ "*response": (response) => parseEditEventInput(response, d, t, null, newT) });1858      } else if (nd == 0 && nt > 1) {1859        // no date, multiple times1860        speak(1861          "I heard multiple times and no date just now. Could you clarify a single date and time, please?",1862          "Clarify"1863        );1864        annyang.removeCommands();1865        annyang.addCommands(cancelCommand);1866        annyang.addCommands({ "*response": (response) => parseEditEventInput(response, d, t, null, null) });1867      } else if (nd == 0 && nt == 0) {1868        // no date, no time1869        speak("On it. And to when do you want the event changed?", "Clarify");1870        annyang.removeCommands();1871        annyang.addCommands(cancelCommand);1872        annyang.addCommands({ "*response": (response) => parseEditEventInput(response, d, t, null, null) });1873      } else {1874        // no idea1875        speak("I'm sorry, could you repeat to when you want the event changed?", "Clarify");1876        annyang.removeCommands();1877        annyang.addCommands(cancelCommand);1878        annyang.addCommands({ "*response": (response) => parseEditEventInput(response, d, t, null, null) });1879      }1880    }1881  } else if (parts.length == 2) {1882    // assume 'from' and 'to' are in order => get subject for each1883    const userInputFromDoc = nlp(parts[0]); // parse input using compromise1884    const userInputToDoc = nlp(parts[1]); // parse input using compromise1885    let dates, times;1886    let nfd = 0; // number 'from' dates1887    let ntd = 0; // number 'to' dates1888    let nft = 0; // number 'from' times1889    let ntt = 0; // number 'to' times1890    if (!d) {1891      // only look for a date if one isn't provided1892      dates = userInputFromDoc.dates().json();1893      nfd = dates.length; // number of dates found1894    }1895    if (d) nfd += 1; // date is given1896    if (!t) {1897      // only look for a time if one isn't provided1898      times = userInputFromDoc.times().json();1899      nft = times.length; // number of times found1900    }1901    if (t) nft += 1; // time is given1902    if (!newD) {1903      // only look for a date if one isn't provided1904      dates = userInputToDoc.dates().json();1905      ntd = dates.length; // number of dates found1906    }1907    if (newD) ntd += 1; // date is given1908    if (!newT) {1909      // only look for a time if one isn't provided1910      times = userInputToDoc.times().json();1911      ntt = times.length; // number of times found1912    }1913    if (newT) ntt += 1; // time is given1914    if (nfd == 1 && ntd == 1 && nft == 1 && ntt == 1) {1915      // one of each => 'from' and 'to' subject found.1916      if (!d) d = new Date(dates[0].start);1917      if (!t) t = toTime(times[0].time);1918      if (!newD) newD = new Date(dates[0].start);1919      if (!newT) newT = toTime(times[0].time);1920      const target = new Date(d.getFullYear(), d.getMonth(), d.getDate(), t.hours, t.minutes, 0);1921      const newTarget = new Date(newD.getFullYear(), newD.getMonth(), newD.getDate(), newT.hours, newT.minutes, 0);1922      editEventTime(target, null, newTarget);1923      // reset commands1924      annyang.removeCommands();1925      annyang.addCommands(keywordCommand);1926      annyang.addCommands(cancelCommand);1927    } else {1928      // look for 'from' subject1929      if (nfd == 1 && nft == 1) {1930        // one date, one time => 'from' subject found.1931        if (!d) d = new Date(dates[0].start);1932        if (!t) t = toTime(times[0].time);1933        const target = new Date(d.getFullYear(), d.getMonth(), d.getDate(), t.hours, t.minutes, 0);1934        if (!Object.hasOwn(events, target.getTime())) {1935          // couldn't find event to edit => inform user1936          speak("I'm sorry, I couldn't find the event you wanted to edit at time you gave me.", "Failure");1937          // reset commands1938          annyang.removeCommands();1939          annyang.addCommands(keywordCommand);1940          annyang.addCommands(cancelCommand);1941        } else {1942          // look for 'to' subject1943          if (ntd == 1 && ntt > 1) {1944            // one date, multiple times1945            if (!newD) newD = new Date(dates[0].start);1946            speak(1947              "I heard multiple times just now. Could you clarify what time you want to change the event to?",1948              "Clarify"1949            );1950            annyang.removeCommands();1951            annyang.addCommands(cancelCommand);1952            annyang.addCommands({ "*response": (response) => parseEditEventInput(response, d, t, newD, null) });1953          } else if (ntd == 1 && ntt == 0) {1954            // one date, no time1955            if (!newD) newD = new Date(dates[0].start);1956            speak("Of course. And what time do you want the event to be changed to?", "Clarify");1957            annyang.removeCommands();1958            annyang.addCommands(cancelCommand);1959            annyang.addCommands({ "*response": (response) => parseEditEventInput(response, d, t, newD, null) });1960          } else if (ntd > 1 && ntt == 1) {1961            // multiple dates, one time1962            if (!newT) newT = toTime(times[0].time);1963            speak(1964              "I heard multiple days just now. Could you clarify which day you want the event to be changed to?",1965              "Clarify"1966            );1967            annyang.removeCommands();1968            annyang.addCommands(cancelCommand);1969            annyang.addCommands({ "*response": (response) => parseEditEventInput(response, d, t, null, newT) });1970          } else if (ntd > 1 && ntt > 1) {1971            // multiple dates, multiple times1972            speak(1973              "I heard multiple days and times just now. Could you clarify a single date and time, please?",1974              "Clarify"1975            );1976            annyang.removeCommands();1977            annyang.addCommands(cancelCommand);1978            annyang.addCommands({ "*response": (response) => parseEditEventInput(response, d, t, null, null) });1979          } else if (ntd > 1 && ntt == 0) {1980            // multiple dates, no time1981            speak(1982              "I heard multiple days and no time just now. Could you clarify a single date and time, please?",1983              "Clarify"1984            );1985            annyang.removeCommands();1986            annyang.addCommands(cancelCommand);1987            annyang.addCommands({ "*response": (response) => parseEditEventInput(response, d, t, null, null) });1988          } else if (ntd == 0 && ntt == 1) {1989            // no date, one time1990            if (!newT) newT = toTime(times[0].time);1991            speak("You got it. And what day do you want to change the event to?", "Clarify");1992            annyang.removeCommands();1993            annyang.addCommands(cancelCommand);1994            annyang.addCommands({ "*response": (response) => parseEditEventInput(response, d, t, null, newT) });1995          } else if (ntd == 0 && ntt > 1) {1996            // no date, multiple times1997            speak(1998              "I heard multiple times and no date just now. Could you clarify a single date and time, please?",1999              "Clarify"2000            );2001            annyang.removeCommands();2002            annyang.addCommands(cancelCommand);2003            annyang.addCommands({ "*response": (response) => parseEditEventInput(response, d, t, null, null) });2004          } else if (ntd == 0 && ntt == 0) {2005            // no date, no time2006            speak("On it. And to when do you want the event changed?", "Clarify");2007            annyang.removeCommands();2008            annyang.addCommands(cancelCommand);2009            annyang.addCommands({ "*response": (response) => parseEditEventInput(response, d, t, null, null) });2010          } else {2011            // no idea2012            speak("I'm sorry, could you repeat to when you want the event changed?", "Clarify");2013            annyang.removeCommands();2014            annyang.addCommands(cancelCommand);2015            annyang.addCommands({ "*response": (response) => parseEditEventInput(response, d, t, null, null) });2016          }2017        }2018      } else if (nfd == 1 && nft > 1) {2019        // one date, multiple times2020        if (!d) d = new Date(dates[0].start);2021        speak(2022          "I heard multiple times just now. Could you clarify at which time the event you want to edit is?",2023          "Clarify"2024        );2025        annyang.removeCommands();2026        annyang.addCommands(cancelCommand);2027        annyang.addCommands({ "*response": (response) => parseEditEventInput(response, d, null, null, null) });2028      } else if (nfd == 1 && nft == 0) {2029        // one date, no time2030        if (!d) d = new Date(dates[0].start);2031        speak("For sure. And at what time is the event you would like to edit?", "Clarify");2032        annyang.removeCommands();2033        annyang.addCommands(cancelCommand);2034        annyang.addCommands({ "*response": (response) => parseEditEventInput(response, d, null, null, null) });2035      } else if (nfd > 1 && nft == 1) {2036        // multiple dates, one time2037        if (!t) t = toTime(times[0].time);2038        speak(2039          "I heard multiple days just now. Could you clarify on which day the event you want to edit is?",2040          "Clarify"2041        );2042        annyang.removeCommands();2043        annyang.addCommands(cancelCommand);2044        annyang.addCommands({ "*response": (response) => parseEditEventInput(response, null, t, null, null) });2045      } else if (nfd > 1 && nft > 1) {2046        // multiple dates, multiple times2047        speak("I heard multiple days and times just now. Could you clarify a single date and time, please?", "Clarify");2048        annyang.removeCommands();2049        annyang.addCommands(cancelCommand);2050        annyang.addCommands({ "*response": (response) => parseEditEventInput(response, null, null, null, null) });2051      } else if (nfd > 1 && nft == 0) {2052        // multiple dates, no time2053        speak(2054          "I heard multiple days and no time just now. Could you clarify a single date and time, please?",2055          "Clarify"2056        );2057        annyang.removeCommands();2058        annyang.addCommands(cancelCommand);2059        annyang.addCommands({ "*response": (response) => parseEditEventInput(response, null, null, null, null) });2060      } else if (nfd == 0 && nft == 1) {2061        // no date, one time2062        if (!t) t = toTime(times[0].time);2063        speak("Without a doubt. And on what day is the event you would like to edit?", "Clarify");2064        annyang.removeCommands();2065        annyang.addCommands(cancelCommand);2066        annyang.addCommands({ "*response": (response) => parseEditEventInput(response, null, t, null, null) });2067      } else if (nfd == 0 && nft > 1) {2068        // no date, multiple times2069        speak(2070          "I heard multiple times and no date just now. Could you clarify a single date and time, please?",2071          "Clarify"2072        );2073        annyang.removeCommands();2074        annyang.addCommands(cancelCommand);2075        annyang.addCommands({ "*response": (response) => parseEditEventInput(response, null, null, null, null) });2076      } else if (nfd == 0 && nft == 0) {2077        // no date, no time2078        speak("Ok. And when is the event that you would like to edit set currently?", "Clarify");2079        annyang.removeCommands();2080        annyang.addCommands(cancelCommand);2081        annyang.addCommands({ "*response": (response) => parseEditEventInput(response, null, null, null, null) });2082      } else {2083        // no idea2084        speak(2085          "Sounds like you wanted to edit an existing event. Could you tell me when it's set currently?",2086          "Clarify"2087        );2088        annyang.removeCommands();2089        annyang.addCommands(cancelCommand);2090        annyang.addCommands({ "*response": (response) => parseEditEventInput(response, null, null, null, null) });2091      }2092    }2093  } else {2094    // no idea2095    speak(2096      "Sounds like you wanted to edit an existing event. Could you tell me which event you want to change and how you want to change it?",2097      "Clarify"2098    );2099    annyang.removeCommands();2100    annyang.addCommands(cancelCommand);2101    annyang.addCommands({ "*response": (response) => parseDeleteEventInput(response, null, null) });2102  }2103}2104/**2105 * Sets the `time` prop of an event with the given time, or if the time is not2106 * give, label, to the given value.2107 * @param {Date} time Time of the event to edit.2108 * @param {String} label Label of the event to edit.2109 * @param {Date} newTime New time to give to the event.2110 */2111function editEventTime(time, label, newTime) {2112  if (time) {2113    // time is defined2114    if (Object.hasOwn(events, time.getTime())) {2115      // event exists...index.js
Source:index.js  
...1119			//Fill In Here1120		}1121	];1122	for (var i = 0; i < commandArray.length; i++) {1123		annyang.addCommands(commandArray[i]);1124	}1125	annyang.addCommands(searches);1126	annyang.addCommands(times);1127	annyang.addCommands(myName);1128	// annyang.addCommands(newL);1129	annyang.addCommands(foescrash);1130	//annyang.addCommands(die);1131	annyang.addCommands(howto);1132	annyang.addCommands(killsam);1133	//annyang.addCommands(whosit);1134	annyang.addCommands(soundsearch);1135	annyang.addCommands(soundcloud);1136	annyang.addCommands(wish);1137	annyang.addCommands(stuffs);1138	annyang.addCommands(newsonggen);1139	annyang.addCommands(magic);1140	// annyang.addCommands(rickroll);1141	annyang.addCommands(dawae);1142	annyang.addCommands(prezicre);1143	annyang.addCommands(email);1144	annyang.addCommands(singasong);1145	annyang.addCommands(howoldismango);1146	annyang.addCommands(insult);1147	annyang.addCommands(god);1148	annyang.addCommands(gmailsearch);1149	annyang.addCommands(drivesearch);1150	annyang.addCommands(song);1151	annyang.addCommands(gplussearch);1152	annyang.addCommands(gimagesearch);1153	annyang.addCommands(googleimages);1154	annyang.addCommands(gschsearch);1155	annyang.addCommands(googlescholar);1156	annyang.addCommands(flettfarmsearch);1157	annyang.addCommands(targetsearch);1158	annyang.addCommands(hyveesearch);1159	annyang.addCommands(walmartsearch);1160	annyang.addCommands(yahoosearch);1161	annyang.addCommands(netsearch);1162	annyang.addCommands(newproject);1163	annyang.addCommands(newpen);1164	annyang.addCommands(newform);1165	annyang.addCommands(newspread);1166	annyang.addCommands(newdraw);1167	annyang.addCommands(newslide);1168	annyang.addCommands(newdoc);1169	annyang.addCommands(clone);1170	annyang.addCommands(wikihowsearch);1171	annyang.addCommands(act);1172	annyang.addCommands(nvm);1173	annyang.addCommands(amazonsearch);1174	//adding commands1175	annyang.addCommands(bigshaq);1176	annyang.addCommands(meaningoflife2);1177	annyang.addCommands(meaningoflife);1178	//Any website: goto:1179	annyang.addCommands(anyweb);1180	// annyang.addCommands(anywebcom);1181	//Yay now math works1182	annyang.addCommands(maths);1183	annyang.addCommands(maths2);1184	//done wit matfs1185	annyang.addCommands(myspace);1186	annyang.addCommands(fourth);1187	annyang.addCommands(greet);1188	annyang.addCommands(soundation);1189	annyang.addCommands(soundtrap);1190	annyang.addCommands(wikisearch);1191	annyang.addCommands(spotifysearch);1192	annyang.addCommands(youtubesearch);1193	annyang.addCommands(thanks);1194	annyang.addCommands(thankyou);1195	annyang.addCommands(code);1196	annyang.addCommands(cnn);1197	annyang.addCommands(bbc);1198	annyang.addCommands(search);1199	annyang.addCommands(twitter);1200	annyang.addCommands(santa);1201	annyang.addCommands(netflix);1202	annyang.addCommands(spotify);1203	annyang.addCommands(pinterest);1204	annyang.addCommands(amazon);1205	annyang.addCommands(facebook);1206	annyang.addCommands(weather);1207	annyang.addCommands(news);1208	annyang.addCommands(bing);1209	annyang.addCommands(coffeeAddicts);1210	annyang.addCommands(plus);1211	annyang.addCommands(third);1212	annyang.addCommands(whip);1213	annyang.addCommands(meow);1214	annyang.addCommands(youtube);1215	annyang.addCommands(second);1216	annyang.addCommands(gmail);1217	annyang.addCommands(wikipedia);1218	annyang.addCommands(google);1219	console.log("commands loaded");1220	//speech kitt1221	// Tell KITT to use annyang1222	SpeechKITT.annyang();1223	// Define a stylesheet for KITT to use1224	SpeechKITT.setStylesheet(1225		"https://cdnjs.cloudflare.com/ajax/libs/SpeechKITT/0.3.0/themes/flat.css"1226	);1227	// Render KITT's interface1228	SpeechKITT.vroom();1229	// annyang.addCommands(commands);1230	console.log("speechkitt loaded");1231} else if (!annyang) {1232	document.write('Speech Recognition is not supported');1233  console.log("Speech Recognition is not supported");1234}1235//1236//You're gonna need this some day:1237//   str = str.replace(/at/g, "@");1238// str = str.replace(/\s+/g, '');...annyang.js
Source:annyang.js  
...12   }13   if (annyang) {14     // Ajout des commandes vocales15     //Zoom d'un niveau16     annyang.addCommands({17       'plus': function() {18         console.log("plus");19         console.log(zoomlevel);20         zoomlevel = view.zoom+1;21         console.log(zoomlevel);22         view.zoom= zoomlevel;23         }24     });25     //DéZoom d'un niveau26     annyang.addCommands({27       'moins': function() {28         console.log("moins");29         console.log(zoomlevel);30         zoomlevel = view.zoom-1;31         console.log(zoomlevel);32         view.zoom= zoomlevel;33         }34     });35     //Déplacement de la vue pour voir la partie plus à gauche36     var commandegauche1 = {'gauche': gaucheFunction};37     var commandegauche2 = {'vers la gauche': gaucheFunction};38     function gaucheFunction(){39        console.log("gauche");40        var xmin = view.extent.xmin.toFixed(2);41        var xmax = view.extent.xmax.toFixed(2);42        var x_range = xmax - xmin;43        var x_new = xmin - (x_range/6);44        view.center.x = x_new;45        view.goTo({46          target: view.center,47        });48    };49     annyang.addCommands(commandegauche1);50     annyang.addCommands(commandegauche2);51     //Déplacement de la vue pour voir la partie plus à droite52     var commandedroite1 = {'droite': droiteFunction};53     var commandedroite2 = {'vers la droite': droiteFunction};54     function droiteFunction(){55        console.log("droite");56        var xmin = view.extent.xmin.toFixed(2);57        var xmax = view.extent.xmax.toFixed(2);58        var x_range = xmax - xmin;59        var x_new = xmax + (x_range/6);60        view.center.x = x_new;61        view.goTo({62          target: view.center,63        });64      };65      annyang.addCommands(commandedroite1);66      annyang.addCommands(commandedroite2);67  //Déplacement de la vue pour voir la partie plus en haut68    var commandehaut1 = {'monte': hautFunction};69    var commandehaut3 = {'vers le haut': hautFunction};70    var commandehaut5 = {'Nord': hautFunction};71    var commandehaut6 = {'vers le Nord': hautFunction};72    function hautFunction(){73      console.log("haut");74      var ymin = view.extent.ymin.toFixed(2);75      var ymax = view.extent.ymax.toFixed(2);76      var y_range = ymax - ymin;77      var y_new = ymax + (y_range/6);78      view.center.y = y_new;79      view.goTo({80        target: view.center,81      });82    };83    annyang.addCommands(commandehaut1);84    annyang.addCommands(commandehaut3);85    annyang.addCommands(commandehaut5);86    annyang.addCommands(commandehaut6);87   //Déplacement de la vue pour voir la partie plus en bas88    var commandebas1 = {'descend': basFunction};89    var commandebas2 = {'bas': basFunction};90    var commandebas3 = {'vers le bas': basFunction};91    var commandebas4 = {'plus bas': basFunction};92    var commandebas5 = {'Sud': basFunction};93    var commandebas6 = {'vers le Sud': basFunction};94    function basFunction(){95          console.log("bas");96          var ymin = view.extent.ymin.toFixed(2);97          var ymax = view.extent.ymax.toFixed(2);98          var y_range = ymax - ymin;99          var y_new = ymin - (y_range/6);100          view.center.y = y_new;101          view.goTo({102            target: view.center,103          });104      };105    annyang.addCommands(commandebas1);106    annyang.addCommands(commandebas2);107    annyang.addCommands(commandebas3);108    annyang.addCommands(commandebas4);109    annyang.addCommands(commandebas5);110    annyang.addCommands(commandebas6);111   //DE-activation Surbrillance112    var commandesurb1 = {'Recherche': SurbFunction};113    var commandesurb2 = {'activer Recherche': SurbFunction};114    var commandesurb3 = {'voir Recherche': SurbFunction};115    var commandesurb4 = {'cocher Recherche': SurbFunction};116    var commandesurb5 = {'Rechercher': SurbFunction};117    function SurbFunction(){118          console.log("Rechercher changed");119          document.getElementById('surbrillance').click();120    };121    annyang.addCommands(commandesurb1);122    annyang.addCommands(commandesurb2);123    annyang.addCommands(commandesurb3);124    annyang.addCommands(commandesurb4);125    annyang.addCommands(commandesurb5);126    //DE-activation Cadre127     var commandecadre1 = {'Cadre': CadreFunction};128     var commandecadre2 = {'activer Cadre': CadreFunction};129     var commandecadre3 = {'voir Cadre': CadreFunction};130     var commandecadre4 = {'cocher Cadre': CadreFunction};131     function CadreFunction(){132           console.log("Cadre changed");133           document.getElementById('cadre').click();134     };135     annyang.addCommands(commandecadre1);136     annyang.addCommands(commandecadre2);137     annyang.addCommands(commandecadre3);138     annyang.addCommands(commandecadre4);139     //DE-activation Commande vocale140      var commandevoc1 = {'Commande vocale': CmdVocFunction};141      var commandevoc2 = {'activer commande vocale': CmdVocFunction};142      var commandevoc3 = {'voir commande vocale': CmdVocFunction};143      var commandevoc4 = {'cocher commande vocale': CmdVocFunction};144      function CmdVocFunction(){145            console.log("Commande vocale changed");146            document.getElementById('commande').click();147      };148      annyang.addCommands(commandevoc1);149      annyang.addCommands(commandevoc2);150      annyang.addCommands(commandevoc3);151      annyang.addCommands(commandevoc4);152      //DE-activation Lecture Audio153       var commandelect1 = {'Lecture Audio': CmdLectureAudio};154       var commandelect2 = {'activer Lecture Audio': CmdLectureAudio};155       var commandelect3 = {'voir Lecture Audio': CmdLectureAudio};156       var commandelect4 = {'cocher Lecture Audio': CmdLectureAudio};157       function CmdLectureAudio(){158             console.log("Lecture Audio changed");159             document.getElementById('lecture').click();160       };161       annyang.addCommands(commandelect1);162       annyang.addCommands(commandelect2);163       annyang.addCommands(commandelect3);164       annyang.addCommands(commandelect4);165   }166 }167 /**168  *169  * @param {*} checkboxElem170  */171 function alertannyang(checkboxElem) {172  if (checkboxElem.checked) {173    annyang.start({autoRestart : true});174    console.log('commande started');175  } else {176    annyang.abort();177    console.log('commande stoped');178  }...voiceControl.js
Source:voiceControl.js  
...9     console.log('stop');10     flag=true;11    }12  }13    annyang.addCommands(stopper);1415   var angle1 = {16    'increase angle': function() {17     var qpd;18     qpd = $("#slangle").slider("option", "value");19     $( "#slangle" ).slider('option','value', qpd+5);20     $("#angle").val(qpd+5); 21      trajgen(); 22     }23    }24   25   annyang.addCommands(angle1);2627   var angle2 = {28    'decrease angle': function() {29      var qpd;30     qpd = $("#slangle").slider("option", "value");31     $( "#slangle" ).slider('option','value', qpd-5);32     $("#angle").val(qpd-5); 33      trajgen(); 34     }35    }36   annyang.addCommands(angle2);3738   var angleUP = {39    'angle up': function(){40      flag=false;41      var sens=0.5, currval, maxval; //sens - sensitivity, plays the role of a kind of a slider smoothness controller42       maxval=$("#slangle").slider('option', 'max');43      var myInterval = setInterval(function(){44        console.log("flag= "+flag);45        if(flag==true || currval == maxval){46            window.clearInterval(myInterval);47        };48         currval = $("#slangle").slider('option', 'value');49         $("#slangle").slider('option', 'value', currval+sens);50         $("#angle").val(currval+sens);51         trajgen();52       }, 50);53      54     }55   }56   annyang.addCommands(angleUP);57   58   var angleDOWN = {59    'angle down': function(){60      flag=false;;61      var sens=0.5, currval, maxval; 62       maxval=$("#slangle").slider('option', 'max');63      var myInterval = setInterval(function(){64        if(flag==true || currval == maxval){65            window.clearInterval(myInterval);66        };67         currval = $("#slangle").slider('option', 'value');68         $("#slangle").slider('option', 'value', currval-sens);69         $("#angle").val(currval-sens);70         trajgen();71       }, 50);72     73     }74   }75   annyang.addCommands(angleDOWN);7677   var speed1 = {78    'increase speed': function() {79      var qpd;80     qpd = $("#slspeed").slider("option", "value");81     $( "#slspeed" ).slider('option','value', qpd+5);82     $("#speed").val(qpd+5); 83      trajgen();84     }85    }86   87   annyang.addCommands(speed1);8889   var speed2 = {90    'decrease speed': function() {91      var qpd;92     qpd = $("#slspeed").slider("option", "value");93     $( "#slspeed" ).slider('option','value', qpd-5);94     $("#speed").val(qpd-5); 95      trajgen(); 96     }97    }98   99   annyang.addCommands(speed2);100101   var speedUP = {102    'speed up': function(){103      flag=false;;104      var sens=0.5, currval, maxval;105      maxval=$("#slspeed").slider('option', 'max');106      var myInterval = setInterval(function(){107        if(flag==true || currval == maxval){108            window.clearInterval(myInterval);109        };110         currval = $("#slspeed").slider('option', 'value');111         $("#slspeed").slider('option', 'value', currval+sens);112         $("#speed").val(currval+sens);113         trajgen();114       }, 50);115      116     }117   }118   annyang.addCommands(speedUP);119120   var speedDOWN = {121    'speed down': function(){122      flag=false;;123      var sens=0.5, currval, maxval;124       maxval=$("#slspeed").slider('option', 'max');125      var myInterval = setInterval(function(){126        if(flag==true || currval == maxval){127            window.clearInterval(myInterval);128        };129         currval = $("#slspeed").slider('option', 'value');130         $("#slspeed").slider('option', 'value', currval-sens);131         $("#speed").val(currval-sens);132         trajgen();133       }, 50);134      135     }136   }137   annyang.addCommands(speedDOWN);138139   var gravity1 = {140    'increase gravity': function() {141      var qpd;142     qpd = $("#slgravity").slider("option", "value");143     $( "#slgravity" ).slider('option','value', qpd+5);144      $("#gravity").val(qpd+5); 145      trajgen(); 146     }147    }148   149   annyang.addCommands(gravity1);150151   var gravity2 = {152    'decrease gravity': function() {153      var qpd;154     qpd = $("#slangle").slider("option", "value");155     $( "#slangle" ).slider('option','value', qpd-5);156      $("#gravity").val(qpd-5); 157      trajgen(); 158     }159    }160   161   annyang.addCommands(gravity2);162163  var gravityUP = {164    'gravity up': function(){165      flag=false;;166      var sens=0.5, currval, maxval; 167      maxval=$("#slgravity").slider('option', 'max');168      var myInterval = setInterval(function(){169        if(flag==true || currval == maxval){170            window.clearInterval(myInterval);171        };172         currval = $("#slgravity").slider('option', 'value');173         $("#slgravity").slider('option', 'value', currval+sens);174         $("#gravity").val(currval+sens);175         trajgen();176       }, 50);177      178     }179   }180   annyang.addCommands(gravityUP);181182   var gravityDOWN = {183    'gravity down': function(){184      flag=false;;185      var sens=0.5, currval, maxval; 186      maxval=$("#slgravity").slider('option', 'max');187      var myInterval = setInterval(function(){188        if(flag==true || currval == maxval){189            window.clearInterval(myInterval);190        };191         currval = $("#slgravity").slider('option', 'value');192         $("#slgravity").slider('option', 'value', currval-sens);193         $("#gravity").val(currval-sens);194         trajgen();195       }, 50);196197     }198   }199   annyang.addCommands(gravityDOWN);200201    var fire = {202    'shoot': function() {203      movement(); 204     }205    }206  annyang.addCommands(fire);207208  annyang.start();209  annyang.debug();
...playgroud-artyom-script.js
Source:playgroud-artyom-script.js  
...25            });26        }, 250);27    }28    console.log('Is Obeying ' + artyom.isObeying());29    artyom.addCommands({30        indexes: [startObeyKeyword],31        action: function () {32            audioActive.play();33            console.log('Is Obeying ' + artyom.isObeying())34        }35    });36    artyom.addCommands([{37        indexes: ["Wann hat die * offen"],38        smart: true,39        action: function (i, wildcard) {40            topic = wildcard;41            if (wildcard == 'mensa') {42                artyom.say("Die Mensa hat heut ab 11 Ur offen.");43            }44            if (wildcard == 'bibliothek' || wildcard == 'bütt' || wildcard == 'bib') {45                artyom.say('Die Bib hat heute von 7 bis 19 Uhr offen.')46            }47        }48    }]);49    artyom.addCommands([{50        indexes: ['Was gibt es da heute'],51        continuous: false,52        action: function () {53            artyom.sayRandom([54                'Hört sich lecker an.',55                'Heute gibt\'s Extrem gutes Zeug.'56            ])57            artyom.say('Heute gibt es XXL Currywurst');58        }59    }])60    artyom.addCommands({61        indexes: ['Was steht heute an'],62        action: function () {63            artyom.say('Du hast heute eine Veranstaltung und eine Abgabe.', {64                onEnd: function () {65                    artyom.repeatLastSay();66                }67            })68        }69    });70    artyom.addCommands({71        indexes: ['Welche Veranstaltung'],72        action: function () {73            artyom.say('Na Marketing Automation')74        }75    });76    artyom.addCommands({77        indexes: ['Wann hab ich die'],78        action: function () {79            artyom.say('In 23 Minuten. Um 8:30 Uhr.')80        }81    });82    artyom.addCommands({83        indexes: ['Mach mir dafür schon mal alles auf meinem PC auf'],84        action: function () {85            artyom.say('Kein Ding. Mach dir noch einen Kaffee. In der Zeit kümmere ich mich darum.');86            anythingElse();87        }88    });89    artyom.addCommands({90        indexes: ['Nein danke tschüss', 'Nein', 'Ne', 'Nein danke'],91        action: function () {92            bye();93        }94    });95    artyom.addCommands({96        indexes: ['Ja', 'Ja kannst', 'Ja klar'],97        if (topic = 'anythingElse') {98            action: function () {99                whatElse();100            }101        }102    });103    artyom.addCommands({104        indexes: ['Ich will mit Professor Winter alleine reden'],105        action: function () {106            artyom.say('Schreib\' ihm einfach \'ne Mail und mach\' einen Termin mit ihm.')107        }108    });109    function anythingElse() {110        topic = 'anythingElse'111        artyom.sayRandom([112            'Kann ich sonst noch was für dich machen?',113            'Gibts sonst noch was mit dem ich dir helfen kann?',114            'Sonst noch was?'115        ]);116    }117    //################## Welche Abgabe?################118    artyom.addCommands({119        indexes: ['Welche Abgabe'],120        action: function () {121            artyom.say('Na die in Interface Design. Du musst ein VUI Konzepnt machen.')122        }123    });124    artyom.addCommands({125        indexes: ['Okay, danke', 'Danke'],126        action: function () {127            noProblem();128            artyom.say('Soll ich dir alle Infomationen dazu per Mail schicken?')129        }130    });131    function bye() {132        artyom.say('Ciao!');133    }134    function whatElse() {135        artyom.say('Na dann schieÃ\' los');136    }137    function noProblem() {138        artyom.sayRandom(['Kein Problem. Hab ich gerne germacht'139            'Kein Ding.', 'Kein Ding für ein King.'140        ]);141    }142    artyom.when("NOT_COMMAND_MATCHED", function () {143        artyom.say('Sorry, damit kann ich dir noch nicht helfen.')144    })145    artyom.addCommands({146        indexes: ['Wie war das noch mal', 'Was hast du gerade gesagt'],147        action: function () {148            artyom.repeatLastSay();149        }150    });151    artyom.addCommands({152        indexes: ['stop', 'halt', 'aus'],153        action: function () {154            artyom.shutUp();155            audioStop.play();156            artyom.dontObey();157        }158    });159    if (artyom.isObeying()) {160        setTimeout(function () {161            artyom.when('COMMAND_RECOGNITION_END', function () {162            });163        }, 2500);164    }165    startContinuousArtyom();...aplCommandHandler.spec.js
Source:aplCommandHandler.spec.js  
...35    const cmd = {36      type: 'Idle',37      delay: 300038    };39    commandHandler.addCommands(cmd);40    expect(commandHandler.commands.length).to.equal(1);41    expect(commandHandler.commands[0]).to.deep.equal(cmd);42  });43  it('adds an array of commands', function() {44    commandHandler.addCommands(cmds);45    expect(commandHandler.commands.length).to.equal(2);46    expect(commandHandler.commands).to.deep.equal(cmds);47  });48  it('adds a speech command', function() {49    const suffix = '2';50    commandHandler.addSpeechCommand(suffix);51    const expectedCommands = [52      {53        type: 'SpeakItem',54        componentId: `${commandHandler.prefix}ID${suffix}`55      }56    ];57    expect(commandHandler.commands).to.deep.equal(expectedCommands);58  });59  it('ignores empty commands', function() {60    commandHandler.addCommands(void 0);61    expect(commandHandler.commands).to.be.empty;62    commandHandler.addCommands([]);63    expect(commandHandler.commands).to.be.empty;64  });65  it('rejects a non-object/array command', function() {66    commandHandler.addCommands('string');67    const expectedError = "Received non-array and non-object command of type 'string'";68    assert(errorStub.calledWith(match(expectedError)), `${errorPrefix}${expectedError}`);69  });70  it('validates good commands', function() {71    commandHandler.addCommands(cmds);72    expect(commandHandler.areValidCommands()).to.be.true;73  });74  it('invalidates missing command type', function() {75    const cmd = {76      delay: 200077    };78    commandHandler.addCommands(cmd);79    commandHandler.areValidCommands();80    const expectedError = "Found command with undefined 'type'";81    assert(errorStub.calledWith(match(expectedError)), `${errorPrefix}${expectedError}`);82  });83  it('invalidates incorrect command parameter', function() {84    const cmd = {85      type: 'bogusType'86    };87    commandHandler.addCommands(cmd);88    commandHandler.areValidCommands();89    const expectedError = `Found invalid command type '${cmd.type}'`;90    assert(errorStub.calledWith(match(expectedError)), `${errorPrefix}${expectedError}`);91  });92  it('invalidates incorrect command parameter', function() {93    const cmd = {94      type: 'SetPage',95      bogusParam: 200096    };97    commandHandler.addCommands(cmd);98    commandHandler.areValidCommands();99    const expectedError = `Found invalid command parameter 'bogusParam' in '${cmd.type}'`;100    assert(errorStub.calledWith(match(expectedError)), `${errorPrefix}${expectedError}`);101  });...speech_command.js
Source:speech_command.js  
...47    var editJar = {48      'edit jar': function() { $('#edit').trigger('click'); }49    };50    // Add our commands to annyang51    annyang.addCommands(commands);52    annyang.addCommands(commands2);53    annyang.addCommands(commands3);54    annyang.addCommands(addItem);55    annyang.addCommands(text);56    annyang.addCommands(image);57    annyang.addCommands(video);58    annyang.addCommands(youtube);59    annyang.addCommands(spotify);60    annyang.addCommands(openJar);61    annyang.addCommands(sortClosed);62    annyang.addCommands(sortRecent);63    annyang.addCommands(editProfile);64    annyang.addCommands(logOut);65    annyang.addCommands(editJar);66    // Start listening.67    annyang.start();68  }...visualization.js
Source:visualization.js  
...14        console.log( 'mounted' );15        this.state.editor.init( document.getElementById( 'revl-shell-panel' ) );16        this.state.editor.setCommandHandler( this.state.shell.doCommand.bind( this.state.shell ) );17        this.state.editor.setCompletionHandler( this.state.shell.doCompletion.bind( this.state.shell ) );18        this.state.shell.addCommands( BaseCommands );19        this.state.shell.addCommands( Viz.Barchart.commands );20        this.state.shell.addCommands( Viz.Linechart.commands );21        this.state.shell.addCommands( Viz.Dotchart.commands );22        this.state.shell.addCommands( Viz.Forcegraph.commands );23        this.state.shell.addCommands( Poly.commands );24        this.state.shell.addCommands( Http.commands );25        this.state.shell.addCommands( Nspace.commands );26        this.state.shell.addCommands( Strings.commands );27        this.state.shell.addCommands( ResultPromise.commands );28    },29    render: function() {30        console.log( 'rendering' );31        return (32            <div id="visualization" style={{position:'absolute',top:'5vh',bottom:0,right:0,left:0, height:'95vh', width:'100vw'}} > 33                <div id="revl-preview"></div>34                <div id="revl-vizbox"></div>35                <div id="revl-shell-panel" className="term" tabIndex="0" onKeyPress={this.keypress}></div>36            </div>37        );38    },39    shouldComponentUpdate: function() {40        console.log( 'should update?' );41        return true;...Using AI Code Generation
1var webdriverio = require('webdriverio');2var options = { desiredCapabilities: { browserName: 'chrome' } };3var client = webdriverio.remote(options);4    .init()5    .addCommands({6        myCommand: function (a, b, c) {7            console.log('a', a);8            console.log('b', b);9            console.log('c', c);10        }11    })12    .myCommand('foo', 'bar', 'baz')13    .end();14var webdriverio = require('webdriverio');15var options = { desiredCapabilities: { browserName: 'chrome' } };16var client = webdriverio.remote(options);17    .init()18    .addCommand('myCommand', function (a, b, c) {19        console.log('a', a);20        console.log('b', b);21        console.log('c', c);22    })23    .myCommand('foo', 'bar', 'baz')24    .end();Using AI Code Generation
1browser.addCommand("myCustomCommand", function () {2});3browser.addCommand("myCustomCommand", function () {4}, true);5browser.addCommand("myCustomCommand", function () {6}, false);7browser.addCommand("myCustomCommand", function () {8}, true, true);9browser.addCommand("myCustomCommand", function () {10}, true, false);11browser.addCommand("myCustomCommand", function () {12}, false, true);13browser.addCommand("myCustomCommand", function () {14}, false, false);15browser.addCommand("myCustomCommand", function () {16}, false, true, true);17browser.addCommand("myCustomCommand", function () {18}, false, true, false);19browser.addCommand("myCustomCommand", function () {20}, false, false, true);21browser.addCommand("myCustomCommand", function () {22}, false, false, false);23browser.addCommand("myCustomCommand", function () {24}, false, false, false, true);25browser.addCommand("myCustomCommand", function () {26}, false, false, false, false);27browser.addCommand("myCustomCommand", function () {28}, false, false, false, false, true);29browser.addCommand("myCustomCommand", function () {30}, false, false, falseUsing AI Code Generation
1browser.addCommand('test', function (a, b) {2    return a + b;3});4browser.test(1, 2).then(function (result) {5});6browser.test(1, 2, function (err, result) {7});8browser.test(1, 2).then(function (result) {9});10browser.test(1, 2).then(function (result) {11});12browser.test(1, 2).then(function (result) {13});14browser.test(1, 2).then(function (result) {15});16browser.test(1, 2).then(function (result) {17});18browser.test(1, 2).then(function (result) {19});20browser.test(1, 2).then(function (result) {21});22browser.test(1, 2).then(function (result) {23});24browser.test(1, 2).then(function (result) {25});26browser.test(1, 2).then(function (result) {27});28browser.test(1, 2).then(functionUsing AI Code Generation
1const webdriverio = require('webdriverio');2const assert = require('assert');3const options = {4    desiredCapabilities: {5    }6};7webdriverio.addCommand("isVisible", function(selector) {8    return this.isExisting(selector).then(function(isExisting) {9        if (!isExisting) {10            return false;11        }12        return this.isVisible(selector);13    });14});15    .remote(options)16    .init()17    .isVisible("input[name='q']")18    .then(function(isVisible) {19        assert.equal(isVisible, true);20    })21    .isVisible("input[name='p']")22    .then(function(isVisible) {23        assert.equal(isVisible, false);24    })25    .end();Using AI Code Generation
1exports.config = {2    before: function () {3        browser.addCommand("myCustomCommand", function (arg) {4        });5    }6};7exports.config = {8    before: function () {9        browser.myCustomCommand();10    }11};12exports.config = {13    before: function () {14        browser.myCustomCommand();15    }16};17exports.config = {18    before: function () {19        browser.myCustomCommand();20    }21};22describe('My Custom Command', function() {23    it('should use my custom command', function () {24        browser.myCustomCommand();25    });26});27exports.config = {28    before: function () {29        browser.addCommand("myCustomCommand", function (arg) {30        });31    }32};33describe('My Custom Command', function() {34    it('should use my custom command with arguments', function () {35        browser.myCustomCommand('argument');36    });37});Using AI Code Generation
1browser.addCommands({2  getText: function (selector) {3    return browser.getText(selector);4  },5  isElementPresent: function (selector) {6    return browser.isExisting(selector);7  }8});9var text = browser.getText("#element");10var isPresent = browser.isElementPresent("#element");11browser.addCommand("getText", function (selector) {12  return browser.getText(selector);13});14var text = browser.getText("#element");15browser.addCommand("getText", function (selector) {16  return browser.getText(selector);17});18var text = browser.getText("#element");19browser.addCommand("getText", function (selector) {20  return browser.getText(selector);21});22var text = browser.getText("#element");23browser.addCommand("getText", function (selector) {24  return browser.getText(selector);25});26var text = browser.getText("#element");27browser.addCommand("getText", function (selector) {28  return browser.getText(selector);29});30var text = browser.getText("#element");31browser.addCommand("getText", function (selector) {32  return browser.getText(selector);33});Using AI Code Generation
1const { addCommands } = require('webdriverio');2const myCommands = {3    myCustomCommand() {4        return 'This is a custom command';5    }6}7addCommands(myCommands);8exports.config = {9    before: function (capabilities, specs) {10        browser.addCommand('myCustomCommand', function () {11            return 'This is a custom command';12        });13    }14}15const { remote } = require('webdriverio');16(async () => {17    const browser = await remote({18        before: function (capabilities, specs) {19            browser.addCommand('myCustomCommand', function () {20                return 'This is a custom command';21            });22        }23    })24    console.log(await browser.myCustomCommand());25})()26exports.config = {27    before: function (capabilities, specs) {28        browser.addCommand('myCustomCommand', function () {29            return 'This is a custom command';30        });31    },32    after: function (result, capabilities, specs) {33        browser.deleteSession();34    }35}36const { remote } = require('webdriverio');37(async () => {38    const browser = await remote({39        before: function (capabilities, specs) {40            browser.addCommand('myCustomCommand', function () {41                return 'This is a custom command';42            });43        },44        after: function (result, capabilities, specs) {45            browser.deleteSession();46        }47    })48    console.log(await browser.myCustomCommand());49})()50exports.config = {51    before: function (capabilities, specs) {52        browser.addCommand('myCustomCommand', function () {53            return 'This is a custom command';54        });55    },56    after: function (result, capabilitiesUsing AI Code Generation
1browser.addCommand("myCustomCommand", function() {2  console.log("inside custom command");3});4browser.myCustomCommand();5browser.addCommand("myCustomCommand", function() {6  console.log("inside custom command");7});8browser.myCustomCommand();9browser.addCommand("myCustomCommand", function() {10  console.log("inside custom command");11});12browser.myCustomCommand();13browser.addCommand("myCustomCommand", function() {14  console.log("inside custom command");15});16browser.myCustomCommand();17browser.addCommand("myCustomCommand", function() {18  console.log("inside custom command");19});20browser.myCustomCommand();21browser.addCommand("myCustomCommand", function() {22  console.log("inside custom command");23});24browser.myCustomCommand();25browser.addCommand("myCustomCommand", function() {26  console.log("inside custom command");27});28browser.myCustomCommand();29browser.addCommand("myCustomCommand", function() {30  console.log("inside custom command");31});32browser.myCustomCommand();33browser.addCommand("myCustomCommand", function() {34  console.log("inside custom command");35});36browser.myCustomCommand();37browser.addCommand("myCustomCommand", function() {Using AI Code Generation
1browser.addCommand("myCustomCommand", function() {2  return 1;3});4it("should return 1", function() {5  var value = browser.myCustomCommand();6  expect(value).to.be.equal(1);7});8browser.addCommand("myCustomCommand", function() {9  return 1;10});11it("should return 1", function() {12  var value = browser.myCustomCommand();13  expect(value).to.be.equal(1);14});15browser.addCommand("myCustomCommand", function() {16  return 1;17});18browser.addCommand("mySecondCustomCommand", function() {19  var value = browser.myCustomCommand();20  return value;21});22it("should return 1", function() {23  var value = browser.mySecondCustomCommand();24  expect(value).to.be.equal(1);25});Wondering what could be a next-gen browser and mobile test automation framework that is also simple and concise? Yes, that’s right, it's WebdriverIO. Since the setup is very easy to follow compared to Selenium testing configuration, you can configure the features manually thereby being the center of attraction for automation testing. Therefore the testers adopt WedriverIO to fulfill their needs of browser testing.
Learn to run automation testing with WebdriverIO tutorial. Go from a beginner to a professional automation test expert with LambdaTest WebdriverIO tutorial.
Running Your First Automation Script - Learn the steps involved to execute your first Test Automation Script using WebdriverIO since the setup is very easy to follow and the features can be configured manually.
Selenium Automation With WebdriverIO - Read more about automation testing with WebdriverIO and how it supports both browsers and mobile devices.
Browser Commands For Selenium Testing - Understand more about the barriers faced while working on your Selenium Automation Scripts in WebdriverIO, the ‘browser’ object and how to use them?
Handling Alerts & Overlay In Selenium - Learn different types of alerts faced during automation, how to handle these alerts and pops and also overlay modal in WebdriverIO.
How To Use Selenium Locators? - Understand how Webdriver uses selenium locators in a most unique way since having to choose web elements very carefully for script execution is very important to get stable test results.
Deep Selectors In Selenium WebdriverIO - The most popular automation testing framework that is extensively adopted by all the testers at a global level is WebdriverIO. Learn how you can use Deep Selectors in Selenium WebdriverIO.
Handling Dropdown In Selenium - Learn more about handling dropdowns and how it's important while performing automated browser testing.
Automated Monkey Testing with Selenium & WebdriverIO - Understand how you can leverage the amazing quality of WebdriverIO along with selenium framework to automate monkey testing of your website or web applications.
JavaScript Testing with Selenium and WebdriverIO - Speed up your Javascript testing with Selenium and WebdriverIO.
Cross Browser Testing With WebdriverIO - Learn more with this step-by-step tutorial about WebdriverIO framework and how cross-browser testing is done with WebdriverIO.
Get 100 minutes of automation test minutes FREE!!
