I am using dolby.io
Till now I have implemented join conference, leave conference, start and stop video, start and stop recording, start and stop screen sharing. What I am facing issue is about multiple conference. I want to implement multiple conferences with unique conference IDs so that every user specified for relevant conference should join its own. I am not getting any idea from its official documentation.
here is my code
const initUI = () => {
const nameMessage = document.getElementById('name-message');
const joinButton = document.getElementById('join-btn');
const conferenceAliasInput = document.getElementById('alias-input');
const leaveButton = document.getElementById('leave-btn');
const startVideoBtn = document.getElementById('start-video-btn');
const stopVideoBtn = document.getElementById('stop-video-btn');
const startScreenShareBtn = document.getElementById('start-screenshare-btn');
const stopScreenShareBtn = document.getElementById('stop-screenshare-btn');
const startRecordingBtn = document.getElementById('start-recording-btn');
const stopRecordingBtn = document.getElementById('stop-recording-btn');
//const mute_unmute = document.getElementById('mute');
//oxeetSDK.conference.mute(VoxeetSDK.session.participant, VoxeetSDK.session.participant.isMuted);
//let isMuted = VoxeetSDK.conference.toggleMute(VoxeetSDK.session.participant);
nameMessage.innerHTML = `${randomName}`;
joinButton.disabled = false;
joinButton.onclick = () => {
let conferenceAlias = conferenceAliasInput.value;
/*
1. Create a conference room with an alias
2. Join the conference with its id
*/
VoxeetSDK.conference.create({ alias: conferenceAlias })
.then((conference) => VoxeetSDK.conference.join(conference, {}))
.then(() => {
joinButton.disabled = true;
leaveButton.disabled = false;
startVideoBtn.disabled = false;
startScreenShareBtn.disabled = false;
startRecordingBtn.disabled = false;
})
.catch((e) => console.log('Something wrong happened : ' + e))
};
leaveButton.onclick = () => {
VoxeetSDK.conference.leave()
.then(() => {
joinButton.disabled = false;
leaveButton.disabled = true;
startScreenShareBtn.disabled = true;
stopScreenShareBtn.disabled = true;
})
.catch((err) => {
console.log(err);
});
};
startVideoBtn.onclick = () => {
VoxeetSDK.conference.startVideo(VoxeetSDK.session.participant)
.then(() => {
startVideoBtn.disabled = true;
stopVideoBtn.disabled = false;
});
};
stopVideoBtn.onclick = () => {
VoxeetSDK.conference.stopVideo(VoxeetSDK.session.participant)
.then(() => {
stopVideoBtn.disabled = true;
startVideoBtn.disabled = false;
});
};
startScreenShareBtn.onclick = () => {
VoxeetSDK.conference.startScreenShare()
.then(() => {
startScreenShareBtn.disabled = true;
stopScreenShareBtn.disabled = false;
})
.catch((e) => console.log(e))
};
stopScreenShareBtn.onclick = () => {
VoxeetSDK.conference.stopScreenShare()
.then(() => {
startScreenShareBtn.disabled = false;
stopScreenShareBtn.disabled = true;
})
.catch((e) => console.log(e))
};
startRecordingBtn.onclick = () => {
let recordStatus = document.getElementById('record-status');
VoxeetSDK.recording.start()
.then(() => {
recordStatus.innerText = 'Recording...';
startRecordingBtn.disabled = true;
stopRecordingBtn.disabled = false;
})
.catch((err) => {
console.log(err);
})
};
stopRecordingBtn.onclick = () => {
let recordStatus = document.getElementById('record-status');
VoxeetSDK.recording.stop()
.then(() => {
recordStatus.innerText = '';
startRecordingBtn.disabled = false;
stopRecordingBtn.disabled = true;
})
.catch((err) => {
console.log(err);
})
};
};
const addVideoNode = (participant, stream) => {
const videoContainer = document.getElementById('video-container');
let videoNode = document.getElementById('video-' + participant.id);
if(!videoNode) {
videoNode = document.createElement('video');
videoNode.setAttribute('id', 'video-' + participant.id);
videoNode.setAttribute('controls', true);
//VoxeetSDK.conference.mute(VoxeetSDK.session.participant, VoxeetSDK.session.participant.isMuted);
//let isMuted = VoxeetSDK.conference.toggleMute(VoxeetSDK.session.participant);
//console.log(isMuted);
//videoNode.setAttribute('height', 240);
//videoNode.setAttribute('width', 720);
videoContainer.appendChild(videoNode);
videoNode.autoplay = 'autoplay';
videoNode.muted = true;
}
navigator.attachMediaStream(videoNode, stream);
};
const removeVideoNode = (participant) => {
let videoNode = document.getElementById('video-' + participant.id);
if (videoNode) {
videoNode.parentNode.removeChild(videoNode);
}
};
const addParticipantNode = (participant) => {
//const members_count++;
const participantsList = document.getElementById('participants-list');
// if the participant is the current session user, don't add himself to the list
if (participant.id === VoxeetSDK.session.participant.id) return;
// let participantNode = document.createElement('li');
// participantNode.setAttribute('id', 'participant-' + participant.id);
// participantNode.innerText = `${participant.info.name}`;
//alert(VoxeetSDK.session.participant);
//document.getElementById('members_count').innerText=participant.id;
let participantNode = document.createElement('div');
participantNode.setAttribute('class', 'tabcnt-item');
participantNode.setAttribute('id', 'participant-' + participant.id);
//document.getElementById('members_count').innerText = document.getElementById('members_count').innerText + 1;
//document.getElementById('members_count').innerText = members_count;
participantNode.innerText = `${participant.info.name}`;
const send_html = "<div class='tabcnt-item'><div class='row align-items-center'><div class='col-md-8'><div class='media'><img src='images/pp.png' alt=''><div class='media-body'><h3>'"+`${participant.info.name}`+"'</h3><p>email#dname.com</p></div></div></div><div class='col-md-4'><ul><li><a href='#'><i class='fas fa-video'></i></a></li><li><a href='#'><i class='fas fa-microphone'></i></a></li></ul></div></div></div>";
participantNode.innerHTML = send_html;
participantsList.appendChild(participantNode);
document.getElementById('members_count').innerText= $('.tab-cnt').length;
};
const removeParticipantNode = (participant) => {
let participantNode = document.getElementById('participant-' + participant.id);
if (participantNode) {
participantNode.parentNode.removeChild(participantNode);
document.getElementById('members_count').innerText= $('.tab-cnt').length;
}
};
const addScreenShareNode = (stream) => {
const screenShareContainer = document.getElementById('screenshare-container');
let screenShareNode = document.getElementById('screenshare');
if (screenShareNode) return alert('There is already a participant sharing his screen !');
screenShareNode = document.createElement('video');
screenShareNode.setAttribute('id', 'screenshare');
screenShareNode.autoplay = 'autoplay';
navigator.attachMediaStream(screenShareNode, stream);
screenShareContainer.appendChild(screenShareNode);
}
const removeScreenShareNode = () => {
let screenShareNode = document.getElementById('screenshare');
if (screenShareNode) {
screenShareNode.parentNode.removeChild(screenShareNode);
}
}
I am exhausted and tired of googling. It will be a great help if some can guide or provide direction towards more elaborative documentation. I have read each and every bit of dolby docs. Thanks for reading
When you call create() a new conference id is generated which is a guid specific for your account. You can call get_id() to find it. You can also specify an alias to help for readability when there may be multiple conferences active at any given time.
If you want to have multiple conferences, you should call create() multiple times. That is, the expectation is the typical app initializes only a single conference but there are multiple running instances each having its own conference and/or to invite others to an existing conference. For webapps, that may be a separate user session rather than a separate deployed mobile application. You may want to do some book keeping for what ids are generated for each user in your own services.
You may be looking for all of the conferences that are active on an account at any given time while testing or monitoring your deployed apps. You can use the Monitor API getConferences to get that list.
If you have additional questions, it is probably best to use Dolby.io Support for more personal answers and guidance.
Related
I've setup a test script that successfully transcribes what I am saying, both in english and german if I set the lang property beforehand.
However, I want it to automatically recognize which language I am speaking. Since SpeechRecognition does not support this, my idea was to just use multiple constructors at the same time, each with their own lang property and then just use the transcription with the highest confidence score.
However, this does not seem to work, as chrome does not transcribe anything if i start both constructors at once. In fact, I have to close chrome alltogether before it will start working again.
Any ideas? Here is the full code, if I uncomment the commented lines it will not work.
function listenEN(){
navigator.webkitGetUserMedia(
{ audio: true },
() => {},
() => {},
)
let triggerPhrase = "Computer"
triggerPhrase = triggerPhrase ? triggerPhrase.toLowerCase() : "Alexa"
let voices = window.speechSynthesis.getVoices()
const voiceEN = voices.find((voice) => voice.name === 'Google US English')
const voiceDE = voices.find((voice) => voice.name === 'Google DE German')
async function notifyStartListening() {
const utterance = new SpeechSynthesisUtterance("beep!");
utterance.rate = 2;
utterance.pitch = 1.5;
utterance.voice = voiceEN;
speechSynthesis.speak(utterance);
}
const recognitionEN = new webkitSpeechRecognition()
recognitionEN.lang = 'en-US'
recognitionEN.continuous = true
const recognitionDE = new webkitSpeechRecognition()
recognitionDE.lang = 'de-DE'
recognitionDE.continuous = true
try {
let isActive = false
function startListening() {
notifyStartListening();
isActive = true
}
recognitionEN.addEventListener('result', async () => {
recognitionEN.lang = 'en-US'
const transcriptEN = event.results[event.results?.length - 1][0].transcript
console.log(transcriptEN)
if (isActive) {
let instruction = transcriptEN
if (transcriptEN.trimStart().startsWith(triggerPhrase)) {
instruction = transcriptEN.trimStart().substring(triggerPhrase.length)
}
isActive = false
return
}
const trimmed = transcriptEN.trimStart().trimEnd().toLowerCase()
if (trimmed.startsWith(triggerPhrase)) {
const instructionEN = trimmed.substring(triggerPhrase.length)
if (instructionEN && instructionEN?.length > 2) {
let confidenceEN = document.createElement('p')
confidenceEN.innerHTML = event.results[event.results?.length - 1][0].confidence
document.body.appendChild(confidenceEN);
} else {
startListening()
}
}
})
recognitionDE.addEventListener('result', async () => {
recognitionDE.lang = 'de-DE'
const transcriptDE = event.results[event.results?.length - 1][0].transcript
console.log(transcriptDE)
if (isActive) {
let instruction = transcriptDE
if (transcriptDE.trimStart().startsWith(triggerPhrase)) {
instruction = transcriptDE.trimStart().substring(triggerPhrase.length)
}
isActive = false
return
}
const trimmed = transcriptDE.trimStart().trimEnd().toLowerCase()
if (trimmed.startsWith(triggerPhrase)) {
const instructionDE = trimmed.substring(triggerPhrase.length)
if (instructionDE && instructionDE?.length > 2) {
let confidenceDE = document.createElement('p')
confidenceDE.innerHTML = event.results[event.results?.length - 1][0].confidence
document.body.appendChild(confidenceDE);
} else {
startListening()
}
}
})
recognitionEN.addEventListener('error', (event) => {
console.log(event)
})
recognitionEN.onend = function () {
recognitionEN.start()
}
recognitionEN.start()
/*recognitionDE.addEventListener('error', (event) => {
console.log(event)
})
recognitionDE.onend = function () {
recognitionDE.start()
}
recognitionDE.start() */
} catch (e) {
console.error(e)
}
}
I've tried all sorts of ways to dispose of tensors (tf.dispose(), start/endscope).
The closest I've got was through this code, where 1 unused tensor remains after each execution. It takes about 2 hours for this program to run enough to use up 64 GB of RAM (big memory leak).
I also suspect that other factors besides TFJS-based operations are contributing to the memory leak, though (in theory) garbage collection should clean this up.
The piece of code below is one event that gets processed by an Event Listener handler. Any help with this issue would be greatly appreciated!
'use strict';
global.fetch = require("node-fetch");
const { MessageActionRow, MessageButton, Permissions } = require('discord.js');
const { mod, eco, m, n } = require(`../../index.js`);
const { Readable } = require('stream');
const PImage = require('pureimage');
const tf = require('#tensorflow/tfjs');
const tfnode = require('#tensorflow/tfjs-node');
const wait = require('util').promisify(setTimeout);
let bufferToStream = (binary) => {
let readableInstanceStream = new Readable({
read() {
this.push(binary);
this.push(null);
}
});
return readableInstanceStream;
}
const predict = async (imageUrl, modelFile) => {
let model = await tf.loadLayersModel(modelFile);
let modelClasses = [ "NSFW", "SFW" ];
let data = await fetch(imageUrl);
let fileType = data.headers.get("Content-Type");
let buffer = await data.buffer();
let stream = bufferToStream(buffer);
let image;
if ((/png/).test(fileType)) {
image = await PImage.decodePNGFromStream(stream);
}
else if ((/jpe?g/).test(fileType)) {
image = await PImage.decodeJPEGFromStream(stream);
}
else {
return;
}
let rawArray;
rawArray = tf.tidy(() => {
let tensorImage;
tensorImage = tf.browser.fromPixels(image).toFloat();
tensorImage = tf.image.resizeNearestNeighbor(tensorImage, [model.inputs[0].shape[1], model.inputs[0].shape[2]]);
tensorImage = tensorImage.reshape([1, model.inputs[0].shape[1], model.inputs[0].shape[2], model.inputs[0].shape[3]]);
return model.predict(tensorImage);
});
rawArray = await rawArray.data();
rawArray = Array.from(rawArray);
tf.disposeVariables();
model.layers.forEach(l => {
l.dispose();
});
if (rawArray[1] > rawArray[0]) {
return [`SFW`, rawArray[1]];
}
else {
return [`NSFW`, rawArray[0]];
}
};
const getResults = async (imageLink, imageNumber) => {
let image = `${imageLink}`;
let prediction = await predict(image, `file://D:/retake7/sfwmodel/model.json`);
let className = `SFW`;
if (prediction[0] == `NSFW`) {
className = `**NSFW**`;
}
return [`[Image ${imageNumber+1}](${imageLink}): ${className} (${(prediction[1]*100).toFixed(2)}% Certainty)`, ((prediction[1]*100).toFixed(2))*1];
}
const main = async (message, client, Discord) => {
if (message.attachments.size == 0 || message.author.bot || message.channel.nsfw) return;
await client.shard.broadcastEval(c => {
console.log(`Scanning...`);
}).catch(e => {
return;
});
let inChannel = await eco.seid.get(`${message.guild.id}.${message.channel.id}.active`);
let sfwImage = await eco.seid.get(`${message.guild.id}.sfwAlerts`);
if (inChannel == `no`) return;
let atmentArr = Array.from(message.attachments);
let msgArr = [];
if (message.attachments.size > 1) {
msgArr.push(`**Images Scanned**`);
} else {
msgArr.push(`**Image Scanned**`);
}
let hasNSFW = false;
let uncertain = false;
for (i = 0; i < message.attachments.size; i++) {
let msg = await getResults(atmentArr[i][1][`proxyURL`], i);
if (msg[1] < 80) {
uncertain = true;
}
if (msg[0].includes(`NSFW`)) {
hasNSFW = true;
}
msgArr.push(msg[0]);
}
if (uncertain == false && hasNSFW == false) {
let cont = `${msgArr.join(`\n`)}`;
msgArr = null;
client.seid.set(`${message.channel.id}.previousScan`, cont);
return;
}
let embed = new Discord.MessageEmbed()
.setColor(`GREEN`)
.setDescription(msgArr.join(`\n`));
let cont2 = `${msgArr.join(`\n`)}`;
client.seid.set(`${message.channel.id}.previousScan`, cont2);
msgArr = null;
if (sfwImage != `no` || hasNSFW || msg[1] <= 80) {
embed.setColor(`RED`);
await message.delete();
let msgSent = await message.channel.send({embeds: [embed], components: [row]});
};
};
module.exports = {
event: 'messageCreate',
run: async (message, client, Discord) => {
await main(message, client, Discord);
},
};
first, separate model loading and inference - in your current code, you'd reload a model each time you need to run prediction on a new image.
and then look at any possible leaks in prediction function - so once model is loaded.
you're loading a model and disposing each layer, but that doesn't mean model itself gets unloaded so there more than a chance that part of model remains in memory.
but leak itself is this line:
rawArray = await rawArray.data();
that variable is already used and its a tensor.
now you're overwriting the same variable with a data array and tensor never gets disposed.
I am trying to pull price data from the API for cryptowatch, when I go to the URL with my API key it works fine, but my program isn't successfully pulling it so I am getting my error of Could not set price feed for cryptowatch:" + cryptowatchMarketId
I'm pretty stuck on where to go from here.
// Set initial prices
const cryptowatchApiKey = process.env.CRYPTOWATCH_API_KEY || MM_CONFIG.cryptowatchApiKey;
const cryptowatchMarkets = await fetch("https://api.cryptowat.ch/markets?apikey=" + cryptowatchApiKey).then(r => r.json());
const cryptowatchMarketPrices = await fetch("https://api.cryptowat.ch/markets/prices?apikey=" + cryptowatchApiKey).then(r => r.json());
for (let i in cryptowatchMarketIds) {
const cryptowatchMarketId = cryptowatchMarketIds[i];
try {
const cryptowatchMarket = cryptowatchMarkets.result.find(row => row.id == cryptowatchMarketId);
const exchange = cryptowatchMarket.exchange;
const pair = cryptowatchMarket.pair;
const key = `market:${exchange}:${pair}`;
PRICE_FEEDS['cryptowatch:'+cryptowatchMarketIds[i]] = cryptowatchMarketPrices.result[key];
} catch (e) {
console.error("Could not set price feed for cryptowatch:" + cryptowatchMarketId);
}
}
const subscriptionMsg = {
"subscribe": {
"subscriptions": []
}
}
for (let i in cryptowatchMarketIds) {
const cryptowatchMarketId = cryptowatchMarketIds[i];
// first get initial price info
subscriptionMsg.subscribe.subscriptions.push({
"streamSubscription": {
"resource": `markets:${cryptowatchMarketId}:book:spread`
}
})
}
let cryptowatch_ws = new WebSocket("wss://stream.cryptowat.ch/connect?apikey=" + cryptowatchApiKey);
cryptowatch_ws.on('open', onopen);
cryptowatch_ws.on('message', onmessage);
cryptowatch_ws.on('close', onclose);
cryptowatch_ws.on('error', console.error);
function onopen() {
cryptowatch_ws.send(JSON.stringify(subscriptionMsg));
}
function onmessage (data) {
const msg = JSON.parse(data);
if (!msg.marketUpdate) return;
const marketId = "cryptowatch:" + msg.marketUpdate.market.marketId;
let ask = msg.marketUpdate.orderBookSpreadUpdate.ask.priceStr;
let bid = msg.marketUpdate.orderBookSpreadUpdate.bid.priceStr;
let price = ask / 2 + bid / 2;
PRICE_FEEDS[marketId] = price;
}
function onclose () {
setTimeout(cryptowatchWsSetup, 5000, cryptowatchMarketIds);
}
}
I want to integrate a popup for users of my website to accept or deny google analytics
I want when the user clicks on Accept "Alle cookies zulassen" ga is enabled and disabled if the user click on refuse "Nur die Notwendigen"
Here is the js file that handle all that
const cookieStorage = {
getItem: (item) => {
const cookies = document.cookie
.split(';')
.map(cookie => cookie.split('='))
.reduce((acc, [key, value]) => ({ ...acc, [key.trim()]: value }), {});
return cookies[item];
},
setItem: (item, value) => {
document.cookie = `${item}=${value};`
} }
const storageType = cookieStorage;
const consentPropertyName = 'ga';
const shouldShowPopup = () => !localStorage.getItem(consentPropertyName);
const saveToStorage = () => localStorage.setItem(consentPropertyName, true);
document.cookie = 'ga=ga';
var gaProperty = 'UA-18247156-4';
var disableStr = 'ga-disable-' + gaProperty;
window.onload = () => {
console.log(localStorage.getItem('ga'));
if (localStorage.getItem('ga') === 'false') {
window[disableStr] = true;
//alert('ga is desactivated')
console.log(localStorage.getItem('ga'));
}
if (localStorage.getItem('ga') === 'true') {
window[disableStr] = false;
//alert('ga is activated')
console.log(localStorage.getItem('ga'));
}
const acceptFn = event => {
localStorage.setItem('ga', true);
consentPopup.classList.add('hidden');
window['ga-disable-UA-18247156-4'] = false;
document.getElementById('overlay').style.display = 'none';
if(document.getElementById('slider')) {
}
}
const refuseFn = event => {
localStorage.setItem('ga', false);
consentPopup.classList.add('hidden');
window['ga-disable-UA-18247156-4'] = true;
document.getElementById('overlay').style.display = 'none';
if(document.getElementById('slider')) {
}
}
const consentPopup = document.getElementById('cookiebanner_con');
const acceptBtn = document.getElementById('accept');
const refuseBtn = document.getElementById('refuse');
acceptBtn.addEventListener('click', acceptFn);
refuseBtn.addEventListener('click', refuseFn);
console.log(shouldShowPopup)
if (shouldShowPopup(storageType)) {
setTimeout(() => {
if(document.getElementById('slider')) {
}
document.getElementById('overlay').style.display = 'block';
console.log(consentPopup.classList)
consentPopup.classList.remove('hidden');
}, 2000);
}
};
When I try to go to google analytics dashboard it says that ga is enabled even after clicking refuse
I want to know if this code is correct to disable and enabling google analytics or I need to change
Thanks
I have a firebase cloud function that is unable to finish executing. I suspect my code can be dramatically improved but I'm not quite sure how.
I've made the query as specific as possible to try and reduce the number of documents required to iterate through but that didn't solve the issue.
I get a Deadline Exceeded error which I suspect is due to the fact that I'm iterating through so many documents and trying to update them.
I increased the timeout (9 minutes)and memory allocation (2GB) in Google cloud console but that didn't help either.
exports.updatePollWinner = functions.runWith(runtimeOpts).firestore.document('triggerAccuracyCalculation/{id}').onCreate(trigger => {
const week = trigger.get('week');
const scoringTags = ["STD", "0.25PPR", "0.5PPR", "PPR", "0.10PPC", "0.25PPC", "0.5PPC", "4PTPASS", "5PTPASS", "6PTPASS", "-2INT", "TEPREMIUM"]
let winningChoiceIds = [];
let totalPollIds = [];
return db.collection("polls").where("sport", "==", 1).where("week", "==", week).where("pollType", "==", "WDIS").get()
.then((querySnapshot) => {
console.log("A");
querySnapshot.forEach((doc) => {
totalPollIds.push(doc.id);
let pollData = doc.data();
// extract relevant scoring tags
let tags = pollData.tags.filter(tag => scoringTags.includes(tag.code)).map(tag => tag.code);
// if no scoring setting is tagged, then use STD - determine what STD is
// extract player from each option
let winner = {score: 0, choice: {}, choiceId: null};
let cnt = 0;
pollData.choices.forEach((choice) => {
let choiceId = choice.id
let mappedChoices = choice.players.map(player => {
return { displayName: player.displayName, playerId: player.playerId, position: player.position, team: player.team }
});
// ToDo: What happens if someone posts a poll with two players in one option? This poll should be ignoree from accuracy calculation
// ignmore if option has more than one player
// if (mappedChoices.length > 1) return;
const player = mappedChoices[0]
// We can't score defense
if (player.position === "DEF") {
return;
}
const playerId = player.playerId;
// Make FFN API call to retrieve stats for that player in that weekconst statsEndpoint = `https://www.fantasyfootballnerd.com/service/player/json/${functions.config().ffnerd.key}${req.url}`;
const statsEndpoint = `https://www.fantasyfootballnerd.com/service/player/json/${functions.config().ffnerd.key}/${playerId}`;
const json = {"Stats": {"2019": ""}, "Player": {}};
https.get(statsEndpoint, (resp) => {
let data = '';
resp.on('data', (chunk) => {
data += chunk;
});
resp.on('end', () => {
const weekString = week.toString();
const fetchedStats = JSON.parse(data).Stats
if (!fetchedStats) return;
const response = fetchedStats["2019"]
if (!response) return;
// TODO SCORE KICKERS AND DEFENSES
const stats = response[weekString];
let score = 0;
stats["recYards"] ? score += parseInt(stats["recYards"]) / 10 : false
stats["recTD"] ? score += parseInt(stats["recTD"]) * 6 : false
stats["rushYards"] ? score += parseInt(stats["rushYards"]) / 10 : false
stats["rushTD"] ? score += parseInt(stats["rushTD"]) * 6 : false
stats["xpMade"] ? score += parseInt(stats["xpMade"]) : false
stats["fgMade"] ? score += parseInt(stats["fgMade"]) * 3 : false
stats["kickoffRet"] ? score += parseInt(stats["kickoffRet"]) / 10 : false
stats["SackYards"] ? score -= parseInt(stats["SackYards"]) / 10 : false
stats["fumbleLost"] ? score -= parseInt(stats["fumbleLost"]) * 2 : false
// Determine winner
// ToDo: handle ties
if (score > winner.score) {
winner.score = score;
winner.choiceId = choiceId;
winner.choice = choice;
}
if (cnt>=pollData.choices.length-1){
// Save player object on the poll Document (include choice ID)
winningChoiceIds.push(winner.choiceId);
const pollDoc = db.doc(`polls/${doc.id}`);
pollDoc.update({winner: winner});
}
cnt++;
});
}).on("error", (err) => {
console.log("Error: ", err.message);
});
});
});
console.log("B");
return false;
}).then(() => {
console.log("C");
let dateToQueryAfter = new Date(new Date("08/22/19").setHours(0,0,0,0))
return db.collection("users").where("recentVote", ">", dateToQueryAfter).get()
})
.then((querySnapshot) => {
console.log("D");
const promises = [];
querySnapshot.forEach((doc) => {
const p = db.collection("votes").where("uid", "==", doc.id).where("week", "==", week).where("pollType", "==", "WDIS").get()
promises.push(p)
});
return Promise.all(promises)
})
.then((querySnapshots) => {
console.log("E");
querySnapshots.forEach((querySnapshot) => {
if (querySnapshot.docs.length <= 0) return;
const uid = querySnapshot.docs[0].data().uid
const retrieveUserDoc = db.doc(`users/${uid}`);
let correctVotes = 0;
let cnt = 0;
let totalVotes = 0;
let pollVoteIds = [];
let pollVoteIdsCorrect = [];
querySnapshot.docs.forEach((doc) => {
const voteData = doc.data();
if (totalPollIds.includes(voteData.poll)) {
pollVoteIds.push(voteData.poll)
totalVotes++;
if (winningChoiceIds.includes(voteData.choice)) {
pollVoteIdsCorrect.push(voteData.poll)
correctVotes++;
}
}
if (cnt>=querySnapshot.size-1){
console.log("Updating user ID: ", uid);
retrieveUserDoc.update({
['accuracyWeeks.week'+week]: true,
['accuracy.week'+week]: {
totalVotes: totalVotes,
correct: correctVotes,
accuracy: correctVotes/totalVotes,
correctVoteIds: pollVoteIdsCorrect,
totalVoteIds: pollVoteIds
}
});
}
cnt++;
})
});
console.log("F");
return false;
})
.catch((error) => {
console.log("Error getting documents: ", error);
});
});