How to calculate ideal and actual burn for burndown chart - javascript

I'm trying to calculate data for burndown chart for a course. The course has a start and end dates, exercises count and actual students start and finish dates. I have data JSON from the server with a course data. I process it. First of all, I'm calculating totalExcercisesCount then counting the number of days student havs to finish the course. After all I get the next data object:
const chartDataObj = {
idealBurn: [],
actualBurn: [],
idealIncrement: 0,
totalExcercisesCount: 12,
totalExercisesDoneCount: 4,
timeLine: {
courseFrom: "2018-09-10",
courseTo: "2019-06-21",
start: "2018-09-11",
finish: "2018-10-01",
totalDays: 20,
}
}
After I'm building an ideal line and here comes the first problem. I'm trying to do next,
chartDataObj.idealIncrement = Math.floor(
chartDataObj.timeLine.totalDays / chartDataObj.totalExcercisesCount
);
for (i = 0; i <= chartDataObj.timeLine.totalDays - 1; i++) {
chartDataObj.idealBurn.push(chartDataObj.idealIncrement * (i + 1));
}
chartDataObj.idealBurn.reverse();
The problem is if the count of days much more then exercises I have a wrong ideal burn.
I have 12 exercises to complete but on the second day, it shows like 19. What am I doing wrong here?
And then I need to fill actual burn data. But the problem is, how to fill it according to dates exercises was complete and show it on the graph? I mean in my final dataObject I have just totalExercisesDoneCount but in initial JSON I have info about dates when exercises was finished. Should I group them by dates or not?
I also have a codepen prepared with chart and all the code. Any help will be appreciated. Thanx

Related

Trying to write a basic script for a Google Sheets that will count total missed minutes by late students

I am (VERY) new to Apps Script and JS generally. I am trying to write a script that will automatically tally the difference between student entry time and start time of a course to deliver total minutes missed.
I have been able to get a function working that can do this for a single cell value, but am having trouble iterating it across a range. Doubtless this is due to a fundamental misunderstanding I have about the for loop I am using, but I am not sure where to look for more detailed information.
Any and all advice is appreciated. Please keep in mind my extreme "beginner status".
I have tried declaring a blank variable and adding multiple results of previously written single-cell functions to that total, but it is returning 0 regardless of given information.
I am including all three of the functions below, the idea is that each will do one part of the overall task.
function LATENESS (entry,start) {
return (entry-start)/60000
}
function MISSEDMINUTES(studenttime,starttime) {
const time = studenttime;
const begin = starttime;
if (time=="Present") {
return 0
} else if (time=="Absent") {
return 90
} else {
return LATENESS(time,begin)
}
}
function TOTALMISSED(range,begintime) {
var total = 0
for (let i = 0; i < range.length; i++) {
total = total + MISSEDMINUTES(i,begintime)
}
}```
If you slightly tweak your layout to have the 'missing minutes' column immediately adjacent to the column of names, you can have a single formula which will calculate the missing minutes for any number of students over any number of days:
Name
*
2/6
2/7
2/8
2/9
John Smith
-
Present
Present
Absent
10:06
Lucy Jenkins
-
Absent
Absent
Absent
Absent
Darren Polter
-
Present
Present
Present
10:01
With 'Name' present in A1, add the following to cell B1 (where I've marked an asterisk):
={"mins missed";
byrow(map(
C2:index(C2:ZZZ,counta(A2:A),counta(C1:1)),
lambda(x,switch(x,"Present",0,"Absent",90,,0,1440*(x-timevalue("10:00"))))),
lambda(row,sum(row)))}
We are MAPping a minute value onto each entry in the table (where 'Present'=0, 'Absent'=90 & a time entry = the number of minutes difference between then and 10am), then summing BYROW.
Updated
Based on the example, you could probably have a formula like the below one to conduct your summation:
=Sum(ARRAYFORMULA(if(B2:E2="Absent",90,if(isnumber(B2:E2),(B2:E2-$K$1)*60*24,0))))
Note that k1 has the start time of 10:00. Same sample sheet has working example.
Original Answer
I'm pretty sure you could do what you want with regular sheets formulas. Here'a sample sheet that shows how to get the difference in two times in minutes and seconds... Along with accounting for absent.
Here's the formula used that will update with new entries.
=Filter({if(B2:B="Absent",90*60,Round((C2:C-B2:B)*3600*24,0)),if(B2:B="Absent",90,Round((C2:C-B2:B)*3600*24/60,1))},(B2:B<>""))
This example might not solve all your issues, but from what I'm seeing, there's no need to be using an app script. If this doesn't cover it, post some sample data using Mark down table.

ChartJS difficulty with X Axis and pulling appropriate data

I'm having some difficulties with iterating over some json data and displaying the proper X axis (Date/Time) I've tried several times to loop through the json data to extract the time for each worker in "history", but unsuccessful.
Here is a sample of the JSON - https://github.com/devdevdevdev1/rvnpoolcharts/blob/main/samplejson.json
And here is my code - https://github.com/devdevdevdev1/rvnpoolcharts/blob/main/worker_stats.js
To get it to work (somewhat), i've just thrown 48 random numbers as points on the x-axis:
displayWorkerHashrateGraph(Array.from(Array(48).keys()), dataset, label);
but obviously there are several problems with this, such as if a new worker joins after one has already been reporting, it starts at 1 and doesn't line up with the other workers.
You can see here that there is no dates/times on the x axis, and the label says 78 instead of a date label.
Current Graph
I've also tried to loop through the list of each worker and extract the time like so:
let labelsList = [];
let historyList = [];
//Begin History Loop
for (var w in workerData.history) {
var worker = getWorkerNameFromAddress(w);
var a = {
key: worker,
hashrate: []
};
for (var wh in workerData.history[w]) {
a.hashrate.push([workerData.history[w][wh].time * 1000, workerData.history[w][wh].hashrate]);
labelsList.push([w, workerData.history[w][wh].time * 1000]);
}
historyList.push(a);
But that ends up looking like this - Seems its taking the time for all 3 of them, but not lining up with the hashrate and pushing all the values to the left.
What I'm trying to achieve:
Pull the time value for each worker iteration from the history element, regardless of when a worker starts reporting.
Mark the hashrate on the graph at the proper date/time
Only display the last hour of stats (BONUS: a way to zoom out to see all 12 hours of stats)
I'd really appreciate any help you can give, I'm a bit new to javascript and I've tried many times to achieve the above and have seriously been banging my head on a wall. Thanks in advance!

Calendar problem and identifying free slot

I'm trying to solve an interval calendar problem.
Given busy slots as a data-set in a person's outlook  calendar and
the time required for a meeting (eg: 45 mins) write a method to find
an open available slot for scheduling a meeting.
Input:
per1: (1,5) (10, 14) (19,20) (27,30)
per2: (3,5) (12,15) (18,21) (23,24)
Output: (6,9) (16,17) (22,22) (25,26)
I'm trying to see how I can solve this problem using:
A) Vanilla JavaScript (ES5 / ES6)
B) Using Data-structure like Interval trees etc.
I'm thinking maybe combine both of the calendar's and sort them in ascending order of start time and then start looking for a slot? Please correct me if I'm wrong.
Need your advice/suggestions on the same.
Given that it's a tuple of absolute hours and only two people involved, you could maintain a state array of length 24. Run a loop to mark all the hours where p1 and p2 are busy. You will be left with an array of hours where both of them will not be busy and then extract the absolute gaps between such intervals. Here is a fiddle (https://jsfiddle.net/r9nq63tk/1/) which handles the marking of the busy hours.
let freeHours = new Array(24);
// Mark the busy hours
let intervals = [];
for(let hours = 0; hours < 24; hours++) {
// Find the ranges where the hours have not been marked and push it to intervals
}

Getting a portion of a sorted array from start value to end value

I'm pretty new to javascript and I need to get a portion (slice) of a sorted array (Numbers, timestamps basically) by start_value and end_value.
For example, let's say I have an array of random timestamps from last month, and I want to get all timestamps between two weeks ago and a week ago.
This is a pretty simple algorithm to write (using a binary search) but I don't want to mess up my code with these computations.
I've been searching for a way to do this in javascript but haven't found any.
Thanks for any future help :)
Perhaps use filter?
var dates = [123, 234, 456, 468, 568, 678];
var min = 300;
var max = 500;
var inRange = dates.filter(function(date) {
return min < date && date < max;
});
console.log(inRange);
On the plus side, this doesn't even need them to be sorted. On the down side, it probably won't be as fast as a well-implemented binary search for the relevant start and end points. Unless you've got some really harsh performance requirements I don't think that'll matter.
Ok, I found a pure js library called binarysearch that has exactly what I'm looking for: https://www.npmjs.com/package/binarysearch. It has rangeValue function which accepts non-existing numbers as start-end. Seems to be working :)

Javascript - What is wrong with this function and loop?

I started learning to code just a couple days ago, and I'm almost finished with my first program. However, I have ran into a problem now at the end, and I can't seem to figure out what's wrong myself.
The program is supposed to help me sort a bunch of dates by week day and time of day. The dates are written "YYMMDD-" and then the time of the day (only hour), e.g. "170109-06".
I have all the dates I want to sort in an array (time), and the following function and loop are supposed to delete all the dates that's not matching a specific year.
Variable clarification:
time - array consisting of dates and time (all the same months but different years. ( e.g. ["161102-03", "151127-11"]
yearDate - the first 4 numbers of the dates that's going to stay in the array.
function checkDate (date) {
var yearMonth = date.slice(0, 4);
var index = time.indexOf(date)
if (yearMonth != yearDate) {
time.splice(index, index + 1);
}
else {
}
}
for (var i = 0; i <= time.length; i++) {
checkDate(time[i]);
}
This code seems to work occasionally, but sometimes a few strings from the array stay there when they're supposed to be deleted, so there's clearly something wrong with the code.
I hope that you'll be able to understand what I mean. I do realize that this post ended up kind of wooly.
Standard mistake. You are deleting items from array while iterating over it. Every time an item is deleted, incrementing the iterator will jump you over the next element, adjacent to the deleted.
Go backwards:
for (var i = time.length - 1; i >= 0; i--) {
checkDate(time[i]);
}

Categories