Format data for high charts representation - node.js

I have data in the below format. I want to plot a line chart to compare data for years 2017 and 2018 for al the months with total.
const listItems = [{
"id": 1,
"total": 21.15,
"dat": "2017-10-21T08:32:36.000Z"
},
{
"id": 2,
"total": 22,
"dat": "2017-11-24T13:46:16.000Z"
},{
"id": 3,
"total": 11,
"dat": "2017-11-24T13:46:16.000Z"
},
{
"id": 4,
"total": 12,
"dat": "2018-04-02T09:15:35.000Z",
}
]
i want to represent Line chart in the below format :
var xAxis = {
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'
]
};
var series = [{
name: '2017',
data: [7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2,
26.5, 23.3, 18.3, 13.9, 9.6
]
},
{
name: '2018',
data: [-0.2, 0.8, 5.7, 11.3, 17.0, 22.0, 24.8,
24.1, 20.1, 14.1, 8.6, 2.5
]
}
];
basically the data represents sum of all the months .

First, write a function that mines month from date, for example:
var dateToMonth = (date) => {
var matched = /[\d]{4}-([\d]{2})-[.]*/g.exec(date)[1];
return matched;
};
also write someone else for mining year. And even an in_array function:
function inArray(needle, haystack) {
var length = haystack.length;
for(var i = 0; i < length; i++) {
if(haystack[i] == needle) return true;
}
return false;
}
Then you have to write a function that iterates your data and sum sum data of same months:
var format = (data) => {
var month_format = [0,0,0,0,0,0,0,0,0,0,0,0];
var last_format = [];
data.map(e => {
var year = dateToYear(e.date);
var years = last_format.map(data_e => data_e.name);
if (!inArray(year, years)) last_format.add({name: year, data: month_format});
var month = dateToMonth(e.date);
last_format.forEach(i => {
if (i.name === year) i[month - a] += e.data;
});
});
return last_format;
};

Related

How to Create a react apex chart to display data of past 12 months?

I have a application submitting portal, I which user his/her request. the issue I am facing is to separate data on base created at field which separates data from current month to past 12 months.
The Data format is like this.
[
{
"_id": "63b3fca07d1f15f5d33e12e0",
"first_name": "ZANAEN",
"last_name": "Ullah",
"date_of_birth": "03/12/2002",
"cnic_number": "55555-5555555-5",
"expiry_date": "10/01/2027",
"current_address": "Qqqq",
"current_city": "Bhawalpur",
"permanent_address": "1111",
"permanent_city": "Bhawalpur",
"mobile_number": "0000-0000000",
"loan_ammount": "5000",
"purpose_of_loan": "Micro-Enterprices",
"current_occupation": "Job",
"nature_of_business": "Existing",
"duration_of_business": "5 years",
"business_address": "11111",
"business_city": "Bhawalpur",
"createdAt": "2022-01-03T10:00:00.562Z",
"updatedAt": "2022-01-03T10:00:00.562Z",
"applicationId": 22121022,
"__v": 0
},
]
and the function is like
getChartLast1Year(objects) {
const monthCounts = [];
const currentMonth = moment().month();
const currentYear = moment().year();
for (let i = 0; i < 12; i++) {
const month = (currentMonth + i) % 12;
const year = month < currentMonth ? currentYear - 1 : currentYear;
const monthData = objects.filter((application) => {
const createdAt = moment(application.createdAt);
return createdAt.month() === month && createdAt.year() === year;
});
monthCounts.push({
month: moment().month(month).format("MMM"),
year: moment().year(year).format("YYYY"),
count: monthData.length,
});
}
console.log("monthCounts", monthCounts);
return monthCounts;
},
If anyone can help I would be so thankful

MongoDB optimized way to select document count change timeline

I want to select the progress of changing the number of documents for each day of the current week.
Users collection (very schematically): { _id, username (str), social (obj, default: null), createdAt (int timestamp) }
I need to select this data:
// Count of the new documents per each day. Example of the data I need:
{
all: { // Social field is null
timeline: [Monday: 1, Tuesday: 0, Wednesday: 4, Thursday: 26, Friday: 24, Saturday: 30, Sunday: 47]
},
social: { // Social field is not null
timeline: [Monday: 0, Tuesday: 0, Wednesday: 2, Thursday: 8, Friday: 5, Saturday: 16, Sunday: 9]
}
}
Better way will be if this was aggregator.
Here is my not optimized code:
let obj = { all: { timeline: [] }, social: { timeline: [] } }
const mondayStartTime = getMonday(new Date()).getTime();
const weekDaysStartTime = getWeekDaysStartTime(mondayStartTime);
const this_week_registered = await (
await users_collection.find({ createdAt: { $gte: mondayStartTime } })
).toArray();
for (let i = 0; i < weekDaysStartTime.length; i++) {
obj.all.timeline.push(
this_week_registered.filter((obj) =>
obj.createdAt >= weekDaysStartTime[i] && weekDaysStartTime[i + 1]
? obj.createdAt < weekDaysStartTime[i + 1]
: true,
).length,
);
obj.social.timeline.push(
this_week_registered.filter((obj) =>
obj.social && obj.createdAt >= weekDaysStartTime[i] && weekDaysStartTime[i + 1]
? obj.createdAt < weekDaysStartTime[i + 1]
: true,
).length,
);
}
I need to make this in one query.

Data isn't pulling through from mongoDB into my chart even though I have the JSON data

I have data saved in my mongoDB which holds players names and scores, I have managed to create a score board with the data outputting (top 10) in DESC order, however for some reason when I use the name and the score for the x and y axis on my chart, chrome's console error has score is not defined?
Any guidance, this has taken me way to long trying to debug this. The score board on the left is working fine, the graph however is not...
leadership.html
<script>
$(function() {
//TESTING FOR LEADERSHIP BOARD ********************
$.get("http://localhost:9000/getPlayersScoreBoard", {}, function (res) {
let data = res;
console.log(res);
for (i = 0; i < data.length; i++) {
let name = data[i].name;
let score = data[i].score;
console.log(data[i].name);
$("#leadership").append("<tr><td class=\"name\">"
+ data[i].name + "</td><td class=\"score\">"
+ data[i].score + "</td></tr>");
}
});
});
//Bar Chart Leadership Code
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: [name],
datasets: [{
label: 'Leadership Board',
data: [score],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgba(255,99,132,1)'
],
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero:true
}
}]
}
}
});
</script>
One of the reasons why you're seeing score is not defined is because you're trying to access it outside of the scope - score will only be available inside of the for loop you've created to generate a table:
for (i = 0; i < data.length; i++) {
var name = data[i].name
var score = data[i].score
// `name` and `score` are available here
}
// `name` and `score` are NOT available here
Also, the chart expects an array for the labels and data properties, but in your example, since you're trying to use name and score variables, they'd only refer to a single item in that array:
var chart = new Chart(ctx, {
data: {
labels: ["David", "Hugo", ...],
datasets: [{
data: [55, 30, ...]
}]
}
})
Here's a solution that fixes your logic. Note that I omitted the stuff that was irrelevant and created a fake API call to try to replicate your example as close as possible:
$(function() {
get("http://localhost:9000/getPlayersScoreBoard", {}, function(res) {
function renderTable(items) {
items.forEach(item => {
var name = item.name;
var score = item.score;
$("#leadership").append(
'<tr><td class="name">' +
name +
'</td><td class="score">' +
score +
"</td></tr>"
);
});
}
function renderChart(items) {
var ctx = document.getElementById("myChart");
var names = items.map(item => item.name);
var scores = items.map(item => item.score);
var chart = new Chart(ctx, {
type: "bar",
data: {
labels: names,
datasets: [
{
label: "Leadership Board",
data: scores
}
]
},
options: {
scales: {
yAxes: [
{
ticks: {
beginAtZero: true
}
}
]
}
}
});
}
renderTable(res);
renderChart(res);
});
});
// Fake `get` request
function get(url, options, callback) {
function getRandomScore(min, max) {
return Math.floor(Math.random() * max) + min;
}
var data = [
{ _id: 1, name: "David", score: getRandomScore(0, 100) },
{ _id: 1, name: "Hugo", score: getRandomScore(0, 100) },
{ _id: 1, name: "Kayleigh", score: getRandomScore(0, 100) },
{ _id: 1, name: "Craig", score: getRandomScore(0, 100) },
{ _id: 1, name: "Kayz", score: getRandomScore(0, 100) }
];
callback(data);
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<div id="leadership"></div>
<canvas id="myChart"></canvas>
</div>
We create a function for drawing chart
<script>
$(function() {
//TESTING FOR LEADERSHIP BOARD ********************
$.get("http://localhost:9000/getPlayersScoreBoard", {}, function (res) {
let data = res;
console.log(res);
let totalLength = data.length;
for (i = 0; i < data.length; i++) {
let name = data[i].name;
let score = data[i].score;
console.log(data[i].name);
if(i == totalLength-1)
{
drawChart(data);
}
$("#leadership").append("<tr><td class=\"name\">"
+ data[i].name + "</td><td class=\"score\">"
+ data[i].score + "</td></tr>");
}
});
});
function drawChart(data)
{
var nameArr = data.map(dataValue => dataValue.name);
var scoreArr = data.map(dataValue => dataValue.score);
//Bar Chart Leadership Code
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: nameArr,
datasets: [{
label: 'Leadership Board',
data: scoreArr,
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgba(255,99,132,1)'
],
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero:true
}
}]
}
}
});
}

how to change a object value in VUE.js

export default {
data() {
return {
a: {}
};
},
methods: {
//a function that can get data from backend
getdata() {
someAPI.getdata.then(response => {
// manage this data
for (let i = 0; i < data.length; i++) {
if ((data[i]["name"] = "Peter")) {
this.a["peter"] = [
{ age: data[i]["age"], grade: "9" },
{ age: data[i]["age"], grade: "9" }
];
} else if ((data[i]["name"] = "Wong")) {
this.a["peter"] = [
{ age: data[i]["age"], grade: "9" },
{ age: data[i]["age"], grade: "9" }
];
}
}
});
}
},
mounted() {
this.getdata();
}
};
this function I changed the a object in data.but in another function I want to console.log to watch. if I console.log(this.a) I can get whole object
{'Peter':[
{'age': 11, 'grade': '9'},{'age': 12, 'grade': '9'},
],'Wong':[{'age': 13, 'grade': '9'}, {'age': 14, 'grade': '9'},]}
But if I console.log(this.a['Peter']) or console.log(this.a.Peter) than I will get a null object, but why?
I have use this.$set but it does not work.
this.$set(this.student,"age", 24)
like this

MongoDB MapReduce weird bug

I'm trying this simple MapReduce operation:
function map() {
var gameDay = Math.floor((this.matchCreation - 1427846400000) / 86400000) + 1; // day of april 2015 when the game was played
this.teams.forEach (function (team){
**team.bans.forEach(function (ban){** // says bans is undefined
var value ={
banned : 1,
firstBanned: ( ((ban.pickTurn == 1) || (ban.pickTurn == 2))? 1 : 0 )
}
emit({championId: ban.championId,
day: Number(gameDay)}, value);
emit({championId: ban.championId,
day: "all"}, value);
});
});
}
function reduce(key, values) {
var a = values[0];
for(var i = 1 ; i<values.length ; i++){
var b = values[i]; // will merge 'b' into 'a'
a.banned += (b.banned? b.banned : 0);
a.firstBanned += (b.firstBanned? b.firstBanned : 0);
for (var attrname in b){
if(attrname != "banned" && attrname != "firstBanned")
a[attrname] = b[attrname];
}
}
return a;
}
matchesCollection.mapReduce(map, reduce, {
out: { reduce: "mapReduceResults" }
}, function (err, data){
if(err)
return callback (err);
callback (null, "OK");
});
It used to work before, but just when I tried to deploy the app after testing for a while, it seems to fail in this line: team.bans.forEach(function (ban){, says team.bans is undefined, although every one of the documents has a "teams" array and a "bans" array inside of each object in it, I even double checked it by querying the database and there is no document in which those fields dont exist.
So weird. The reduce function is a bit more complex but it seems to work alright, yet the map one (unlike Reduce, its supposed to be called just once per original document, right?) throws this unexplainable error. Could anyone give me some insight?
Sample input:
{
"_id": {
"$oid": "5531a63f2a3f135c11ed14a8"
},
"matchId": 1778704162,
"region": "NA",
"platformId": "NA1",
"matchMode": "CLASSIC",
"matchType": "MATCHED_GAME",
"matchCreation": 1427864425511,
"matchDuration": 1431,
"queueType": "URF_5x5",
"mapId": 11,
"season": "SEASON2015",
"matchVersion": "5.6.0.194",
"participants": [
{
"teamId": 100,
"spell1Id": 12,
"spell2Id": 4,
"championId": 81,
"highestAchievedSeasonTier": "SILVER",
"timeline": [],
"masteries": [],
"stats": {
"winner": false,
"champLevel": 19,
"item0": 1037,
"item1": 3078,
"item2": 3117,
"item3": 3035,
"item4": 3072,
"item5": 1038,
"item6": 3340,
"kills": 7,
"doubleKills": 1,
"tripleKills": 0,
"quadraKills": 0,
"pentaKills": 0,
"unrealKills": 0,
"largestKillingSpree": 3,
"deaths": 15,
"assists": 9,
"totalDamageDealt": 103191,
"totalDamageDealtToChampions": 22148,
"totalDamageTaken": 32924,
"largestCriticalStrike": 669,
"totalHeal": 2263,
"minionsKilled": 97,
"neutralMinionsKilled": 1,
"neutralMinionsKilledTeamJungle": 1,
"neutralMinionsKilledEnemyJungle": 0,
"goldEarned": 13923,
"goldSpent": 13273,
"combatPlayerScore": 0,
"objectivePlayerScore": 0,
"totalPlayerScore": 0,
"totalScoreRank": 0,
"magicDamageDealtToChampions": 6082,
"physicalDamageDealtToChampions": 15803,
"trueDamageDealtToChampions": 263,
"visionWardsBoughtInGame": 0,
"sightWardsBoughtInGame": 0,
"magicDamageDealt": 45997,
"physicalDamageDealt": 56651,
"trueDamageDealt": 543,
"magicDamageTaken": 25249,
"physicalDamageTaken": 7490,
"trueDamageTaken": 184,
"firstBloodKill": false,
"firstBloodAssist": false,
"firstTowerKill": false,
"firstTowerAssist": false,
"firstInhibitorKill": false,
"firstInhibitorAssist": false,
"inhibitorKills": 0,
"towerKills": 4,
"wardsPlaced": 2,
"wardsKilled": 0,
"largestMultiKill": 2,
"killingSprees": 1,
"totalUnitsHealed": 1,
"totalTimeCrowdControlDealt": 98
},
"participantId": 1,
"runes": []
},
... (9 more like that)
],
"participantIdentities": [],
"teams": [
{
"teamId": 100,
"winner": false,
"firstBlood": true,
"firstTower": false,
"firstInhibitor": true,
"firstBaron": false,
"firstDragon": true,
"towerKills": 6,
"inhibitorKills": 2,
"baronKills": 0,
"dragonKills": 3,
"vilemawKills": 0,
"dominionVictoryScore": 0,
"bans": [
{
"championId": 120,
"pickTurn": 1
},
{
"championId": 37,
"pickTurn": 3
},
{
"championId": 13,
"pickTurn": 5
}
]
},
{
"teamId": 200,
"winner": true,
"firstBlood": false,
"firstTower": true,
"firstInhibitor": false,
"firstBaron": false,
"firstDragon": false,
"towerKills": 11,
"inhibitorKills": 4,
"baronKills": 0,
"dragonKills": 0,
"vilemawKills": 0,
"dominionVictoryScore": 0,
"bans": [
{
"championId": 28,
"pickTurn": 2
},
{
"championId": 38,
"pickTurn": 4
},
{
"championId": 63,
"pickTurn": 6
}
]
}
]
}
Expected output:
{
_id: { championId: Number, day: Number }
value: { banned: Number, firstBanned: Number }
}
After that, its supposed to merge with the results of a previous MapReduce operation, copying all the fields of documents with the same key (in the reduce function), but thats irrelevant now since the error happens before...

Resources