I have a line chart where user can see where they got in a competition over the years. There is up to 60th place. I will be filling this data from the database.
The problem is that all 60 places are shown on the y axis when I only want it to show 1, 15, 30, 45 , 60
I believe this is happening because I have the ticks changed from 1 to 1st place on the y axis, as this is better for user experience.
but since I am pulling from the database all 60 ticks need to be there. Though on the graph I actually want ticks to show every 15.
Heres my code:
// Callback that draws line chart for progress report
function drawLineChart() {
var data = google.visualization.arrayToDataTable([
['Date', 'Orouke', 'feis nara'],
['2014', 1, 4],
['2015', 11, 46],
['2016', 60, 11],
['2017', 10, 5]
]);
var options = {
title: 'Progress Report',
width: 600,
height: 550,
legend: { position: 'bottom' },
vAxis: { title: 'Competition Placement',
direction: -1,
gridlines: {count: 10},
ticks: [{ v: 1, f: '1st Place'}, {v: 2, f: '2nd Place'}, {v: 3, f: '3rd Place'}, {v: 4, f: '4th Place'}, {v: 5, f: '5th Place'}, {v: 6, f: '6th Place'}, {v: 7, f: '7th Place'}, {v: 8, f: '8th Place'}, {v: 9, f: '9th Place'}, {v: 10, f: '10th Place'}, {v: 11, f: '11th Place'}, { v: 12, f: '12th Place'}, {v: 13, f: '13th Place'}, {v: 14, f: '14th Place'}, {v: 15, f: '15th Place'}, {v: 16, f: '16th Place'}, {v: 17, f: '17th Place'}, {v: 18, f: '18th Place'}, {v: 19, f: '19th Place'}, {v: 20, f: '20th Place'}, {v: 21, f: '21st Place'}, {v: 22, f: '22nd Place'}, { v: 23, f: '23rd Place'}, {v: 24, f: '24th Place'}, {v: 25, f: '25th Place'}, {v: 26, f: '26th Place'}, {v: 27, f: '27th Place'}, {v: 28, f: '28th Place'}, {v: 29, f: '29th Place'}, {v: 30, f: '30th Place'}, {v: 31, f: '31st Place'}, {v: 32, f: '32nd Place'}, {v: 33, f: '33rd Place'}, { v: 34, f: '34th Place'}, {v: 35, f: '35th Place'}, {v: 36, f: '36th Place'}, {v: 37, f: '37th Place'}, {v: 38, f: '38th Place'}, {v: 39, f: '39th Place'}, {v: 40, f: '41st Place'}, {v: 42, f: '42nd Place'}, {v: 43, f: '43rd Place'}, {v: 44, f: '44th Place'}, {v: 45, f: '45th Place'}, {v: 46, f: '46th Place'}, {v: 47, f: '47th Place'}, {v: 48, f: '48th Place'}, {v: 49, f: '49th Place'}, {v: 50, f: '51st Place'}, {v: 52, f: '52nd Place'}, {v: 53, f: '53rd Place'}, {v: 54, f: '54th Place'}, {v: 55, f: '55th Place'}, {v: 56, f: '56th Place'}, {v: 57, f: '57th Place'}, {v: 58, f: '58th Place'}, {v: 59, f: '59th Place'}, {v: 60, f: '60th Place'}] }
};
var chart = new google.visualization.LineChart(document.getElementById('line_chart'));
chart.draw(data, options);
}
NOTE: I have not used php yet because I decided to set up the chart first and then fill in php after.
you can build the ticks dynamically, using a for loop...
for (var i = 0; i <= 60; i = i + 15) {
addTick(i);
}
see following working snippet...
google.charts.load('current', {
packages: ['corechart']
}).then(function () {
var data = google.visualization.arrayToDataTable([
['Date', 'Orouke', 'feis nara'],
['2014', 1, 4],
['2015', 11, 46],
['2016', 60, 11],
['2017', 10, 5]
]);
// build ticks
var ticks = [];
for (var i = 0; i <= 60; i = i + 15) {
addTick(i);
}
function addTick(i) {
var place;
var digit;
if (i === 0) {
i = 1;
}
digit = i.toString().substr(i.toString().length - 1);
switch (digit) {
case '1':
place = 'st';
break;
case '2':
place = 'nd';
break;
case '3':
place = 'rd';
break;
default:
place = 'th';
}
ticks.push({
v: i,
f: i + place
});
}
var options = {
title: 'Progress Report',
width: 600,
height: 550,
legend: {
position: 'bottom'
},
vAxis: {
title: 'Competition Placement',
direction: -1,
gridlines: {count: 10},
ticks: ticks
}
};
var chart = new google.visualization.LineChart(document.getElementById('line_chart'));
chart.draw(data, options);
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="line_chart"></div>
Related
I have two json objects as follow
Id:1
{"points":[{"x":109,"y":286,"r":1,"color":"black"},{"x":108,"y":285,"r":1,"color":"black"},{"x":106,"y":282,"r":1,"color":"black"},{"x":103,"y":276,"r":1,"color":"black"},],"lines":[{"x1":109,"y1":286,"x2":108,"y2":285,"strokeWidth":"2","strokeColor":"black"},{"x1":108,"y1":285,"x2":106,"y2":282,"strokeWidth":"2","strokeColor":"black"},{"x1":106,"y1":282,"x2":103,"y2":276,"strokeWidth":"2","strokeColor":"black"}]}
Id-2
{"points":[{"x":524,"y":343,"r":1,"color":"black"},{"x":523,"y":342,"r":1,"color":"black"},{"x":521,"y":339,"r":1,"color":"black"},{"x":520,"y":334,"r":1,"color":"black"},{"x":514,"y":319,"r":1,"color":"black"}],"lines":[{"x1":524,"y1":343,"x2":523,"y2":342,"strokeWidth":"2","strokeColor":"black"},{"x1":523,"y1":342,"x2":521,"y2":339,"strokeWidth":"2","strokeColor":"black"},{"x1":521,"y1":339,"x2":520,"y2":334,"strokeWidth":"2","strokeColor":"black"},{"x1":520,"y1":334,"x2":514,"y2":319,"strokeWidth":"2","strokeColor":"black"}]}
I am trying to merge these two data onto a canvas
I am able to retrieve a single file but combining them i am not able to do
def loadDrawing(request):
""" Function to load the drawing with drawingID if it exists."""
try:
# Getting JSON object string of saved drawing.
drawingJSONData = Drawing.objects.get(id = 1).drawingJSONText
# drawingJSONData1 = Drawing.objects.get(id=1).drawingJSONText
# drawingJSONData2 = Drawing.objects.get(id=2).drawingJSONText
# Seding context with appropriate information
context = {
"loadIntoJavascript" : True,
"JSONData" : drawingJSONData
}
# Editing response headers and returning the same
response = modifiedResponseHeaders(render(request, 'MainCanvas/index.html', context))
return response
My model in django
class Drawing(models.Model):
drawingJSONText = models.TextField(null = True)
My .js file to load the drawing and parsing it from server to JSON object and pushing the loaded points into an array
// Checking if the drawing to be loaded exists
if (document.getElementById('JSONLoadData') != null)
{
// Parsing the loaded drawing from server to a JSON Object
var loadedData = JSON.parse(JSONLoadData.value)
// Iterating through all the points in the loaded drawing
for(let i = 0; i < loadedData['points'].length; i++)
{
// Saving the point and drawing the same in the svg canvas
const point = svg.append('circle')
.attr('cx', loadedData['points'][i]['x'])
.attr('cy', loadedData['points'][i]['y'])
.attr('r', loadedData['points'][i]['r'])
.style('fill', loadedData['points'][i]['color']);
// Pushing the point inside points array
points.push(point);
}
// Iterating through all the lines in the loaded drawing
for(let i = 0; i < loadedData['lines'].length; i++)
{
// Saving the line and drawing the same in the svg canvas
const line = svg.append('line')
.attr('x1', loadedData['lines'][i]['x1'])
.attr('y1', loadedData['lines'][i]['y1'])
.attr('x2', loadedData['lines'][i]['x2'])
.attr('y2', loadedData['lines'][i]['y2'])
.attr('stroke-width', loadedData['lines'][i]['strokeWidth'])
.style('stroke', loadedData['lines'][i]['strokeColor']);
// Pushing the line inside lines array
lines.push(line);
}
}
});
Edited :
If my model is as follows
class Drawing(models.Model):
drawingJSONText = models.TextField(null=True)
project = models.CharField(max_length=250)
How can i filter data based on project
Lets say i have three datasets
1st one contains project = a
2nd one contains project = b
3rd one contains project = a
4th one contains project = a
How can i add datapoints like above by filtering data Drawing.objects.filter(project=a)
then based on the queryset i have three data points and corresponding data are plotted on canvas as above
I'm not entirely sure this is what you want, but are you trying to combine id-1 and id-2? If I think I understand what you are trying to do, will using the + operator work for you in this case?
drawingJSONData1 = json.loads(Drawing.objects.get(id=1).drawingJSONText)
drawingJSONData2 = json.loads(Drawing.objects.get(id=1).drawingJSONText)
drawingJSONData = dict()
drawingJSONData["points"] = drawingJSONData1["points"]+drawingJSONData1["points"]
drawingJSONData["lines"] = drawingJSONData2["lines"]+drawingJSONData2["lines"]
With your example above, you'd end up with:
{'points': [{'x': 109, 'y': 286, 'r': 1, 'color': 'black'},
{'x': 108, 'y': 285, 'r': 1, 'color': 'black'},
{'x': 106, 'y': 282, 'r': 1, 'color': 'black'},
{'x': 103, 'y': 276, 'r': 1, 'color': 'black'},
{'x': 524, 'y': 343, 'r': 1, 'color': 'black'},
{'x': 523, 'y': 342, 'r': 1, 'color': 'black'},
{'x': 521, 'y': 339, 'r': 1, 'color': 'black'},
{'x': 520, 'y': 334, 'r': 1, 'color': 'black'},
{'x': 514, 'y': 319, 'r': 1, 'color': 'black'}],
'lines': [{'x1': 109,
'y1': 286,
'x2': 108,
'y2': 285,
'strokeWidth': '2',
'strokeColor': 'black'},
{'x1': 108,
'y1': 285,
'x2': 106,
'y2': 282,
'strokeWidth': '2',
'strokeColor': 'black'},
{'x1': 106,
'y1': 282,
'x2': 103,
'y2': 276,
'strokeWidth': '2',
'strokeColor': 'black'},
{'x1': 524,
'y1': 343,
'x2': 523,
'y2': 342,
'strokeWidth': '2',
'strokeColor': 'black'},
{'x1': 523,
'y1': 342,
'x2': 521,
'y2': 339,
'strokeWidth': '2',
'strokeColor': 'black'},
{'x1': 521,
'y1': 339,
'x2': 520,
'y2': 334,
'strokeWidth': '2',
'strokeColor': 'black'},
{'x1': 520,
'y1': 334,
'x2': 514,
'y2': 319,
'strokeWidth': '2',
'strokeColor': 'black'}]}
EDIT: added the gets wrapped in json.loads to convert string to Python object as I don't know what kind of field that is and given the error being seen.
I have been getting some strange key errors when trying to load a value after a few game ticks in my case, there is no modification going on cause most of it gets loaded from class internally at initiation, here is an quick example of the error im getting when trying to access.
also link to source is here, im pretty new and just have been coding for aint to long so please no judgement.
{'calleas': {'player': {'x': 5, 'y': 5, 'id': 'npc_1'}, '1': {'x': 6, 'y': 8, 'id': 'npc_2'}, '2': {'x': 5, 'y': 8, 'id': 'npc_3'}}, 'calleas_forest': {'player': {'x': 55, 'y': 5, 'id': 'npc_1'}}}
{'calleas': {'0': {'object_id': 7, 'x': 0, 'y': 5, 'walkable': True, 'gamestate': 'callaes_forest'}, '1': {'object_id': 7, 'x': 0, 'y': 4, 'walkable': True, 'gamestate': 'callaes_forest'}}, 'callaes_forest': {'0': {'object_id': 7, 'x': 56, 'y': 5, 'walkable': True, 'gamestate': 'callaes_forest'}, '1': {'object_id': 7, 'x': 56, 'y': 4, 'walkable': True, 'gamestate': 'callaes_forest'}}}
None
Traceback (most recent call last):
File "C:/Users/Jannick/PycharmProjects/NewRemake/Game.py", line 39, in <module>
g.start_game()
File "C:/Users/Jannick/PycharmProjects/NewRemake/Game.py", line 33, in start_game
self.update()
File "C:\Users\Jannick\PycharmProjects\NewRemake\GameHandler.py", line 106, in update
self.entity_handler.update()
File "C:\Users\Jannick\PycharmProjects\NewRemake\Entity\EntityHandler.py", line 21, in update
self.game.player.update()
File "C:\Users\Jannick\PycharmProjects\NewRemake\Entity\Entity.py", line 35, in update
self.move(x=1)
File "C:\Users\Jannick\PycharmProjects\NewRemake\Entity\Player.py", line 47, in move
self.game.map_handler.load(self.game.map_handler.new_map_name(dest_x, dest_y))
File "C:\Users\Jannick\PycharmProjects\NewRemake\World\MapBuilder.py", line 26, in load
self.get_map_configuration(map_config)
File "C:\Users\Jannick\PycharmProjects\NewRemake\World\MapBuilder.py", line 46, in get_map_configuration
"entitys": self.all_map_entitys[map_config]
KeyError: 'callaes_forest'
{'calleas': {'player': {'x': 5, 'y': 5, 'id': 'npc_1'}, '1': {'x': 6, 'y': 8, 'id': 'npc_2'}, '2': {'x': 5, 'y': 8, 'id': 'npc_3'}}, 'calleas_forest': {'player': {'x': 55, 'y': 5, 'id': 'npc_1'}}}
(4) [{…}, {…}, {…}, {…}]
0: {entity: "lovely meeting", type: "Calendar.Subject", startIndex: 53, endIndex: 66, score: 0.9183444}
1: {entity: "california", type: "Calendar.Location", startIndex: 27, endIndex: 36, score: 0.922538459}
2: {entity: "today", type: "builtin.datetimeV2.date", startIndex: 18, endIndex: 22, resolution: {…}}
3: {entity: "4am", type: "builtin.datetimeV2.time", startIndex: 41, endIndex: 43, resolution: {…}}length: 4__proto__: Array(0)
These 4 elements are part of Entities, what i want is to check if type is equal to let's say Calender.Location and worth noting that we don't always have the 4 elements we could have one or none, and even when we do have 4 the entity type Calender.Location doesn't have to be index number 1, what i have tried included testvar.entities.length and testvar.entities[0].type not knowing the ID of each makes it impossible .
Example of what i want:
i want to parse the Json input for a type Calendar.location in entities, it might exist and might not and its exact id is not known(ranges between 0 and 4), if i do find it i should return the entity associated with it in this case california.
const test =[
{entity: "lovely meeting", type: "Calendar.Subject", startIndex: 53, endIndex: 66, score: 0.9183444},
{entity: "california", type: "Calendar.Location", startIndex: 27, endIndex: 36, score: 0.922538459},
{entity: "today", type: "builtin.datetimeV2.date", startIndex: 18, endIndex: 22, resolution: {}},
{entity: "4am", type: "builtin.datetimeV2.time", startIndex: 41, endIndex: 43, resolution: {}}
]
const getentitiesByType = (arr,type) => {
for(let i in arr ){
if(arr[i].type === type){
return arr[i].entity;
}
}
};
console.log(getentitiesByType(test,"Calendar.Location"))
I have a server.js page and it get datas from database. I want to use this datas in a HTML page. How can I get this datas.
I don't use Express but Hapi (because i'm happy lol).
This is my code :
<script>var ctx = document.getElementById('graph').getContext('2d');
var graph = new Chart(ctx, {
type: 'line',
data: {
labels: ['Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi', 'Dimanche'],
datasets: [{
label: 'CPU',
data: [22, 19, 25, 65, 30, 47, 14],
backgroundColor: "rgba(153,255,51,0.4)"
}, {
label: 'RAM',
data: [31, 29, 31, 35, 28, 34, 30],
backgroundColor: "rgba(255,153,0,0.4)"
}]
}
});
</script>
I want to change "22, 19, 25, 65, 30, 47, 14" by the new values gets with postgreSQL.
Thanks for your help.
I am over my head trying to get data for statistics over the course of n number of days. I don't really care about the output format, as long as it shows the dates in order, and the values as an array... The all_data query (below) will get all the values for determined time period, but it won't create rows for dates where there are no values. The goal is to be able to output this:
# Get 10 (for example) days of data->
[
{date:'datetime-day-ago-10', values: [{foo:'bar', foo2:'bar2', foo3:'bar'3}]}
{date:'datetime-day-ago-9', values: [{foo:'bar', foo2:'bar2', foo3:'bar'3}]}
{date:'datetime-day-ago-8', values: []}
{date:'datetime-day-ago-7', values: [{foo:'bar', foo2:'bar2', foo3:'bar'3}]}
{date:'datetime-day-ago-6', values: []}
{date:'datetime-day-ago-5', values: []}
{date:'datetime-day-ago-4', values: [{foo:'bar', foo2:'bar2', foo3:'bar'3}]}
{date:'datetime-day-ago-3', values: [{foo:'bar', foo2:'bar2', foo3:'bar'3}]}
{date:'datetime-day-ago-2', values: []}
{date:'datetime-day-ago-1', values: []}
]
Here's the method I am using at this point.
def counts
from = params[:days].to_i.days.ago.to_time.beginning_of_day
to = 0.days.ago.to_time.end_of_day
all_data = current_user.values.all
.where(field_id: params[:field_id], created_at: from .. to)
.where.not(input: nil)
.order(input: :desc)
.group_by { |value| value['created_at'].to_date}
.map {|k,v| [k,v]}
grouped = (0..params[:days].to_i-1).to_a.inject([]) do |memo, i|
if all_data[i].present?
date = all_data[i][0].to_time
values = all_data[i][1].group_by { |value| value.input }.map { |k, v| {input:k, count:v.length} }.sort! { |x,y| x['input'] <=> y['input']}
total = 0
values.each do |value|
total = total + value[:count]
end
else
# This is where I can't figure out how to assign a date for rows which have no data.
date = ((i-params[:days].to_i+1)*-(1)).days.ago.beginning_of_day
end
memo << {'date': date, 'total': total || 0, 'values': values || []}
memo
end
grouped = grouped.sort_by { |day| day['date'] }
render json: grouped
end
# Sample of entire output for 10 days
0: {date: "2015-10-31T00:00:00.000-07:00", total: 15,…} <- 10-31-2015 HAS VALUES
1: {date: "2015-11-01T00:00:00.000-07:00", total: 49,…} <- 11-01-2015 HAS VALUES
2: {date: "2015-11-02T00:00:00.000-08:00", total: 10,…} <- 11-02-2015 HAS VALUES
3: {date: "2015-11-03T00:00:00.000-08:00", total: 21,…} <- 11-03-2015 HAS VALUES
4: {date: "2015-10-30T00:00:00.000-07:00", total: 0, values: []}
5: {date: "2015-10-31T00:00:00.000-07:00", total: 0, values: []} \
6: {date: "2015-11-01T00:00:00.000-07:00", total: 0, values: []} - No matter what I try I can't get these dates to be the 5 days before 10-31-2015...
7: {date: "2015-11-02T00:00:00.000-08:00", total: 0, values: []} /
8: {date: "2015-11-03T00:00:00.000-08:00", total: 0, values: []}
9: {date: "2015-11-04T00:00:00.000-08:00", total: 0, values: []} <- 11-04-2015 This should appear up there ^ under the last HAS VALUES row
So, how can I properly create dates for null value rows? And then how can I make sure they fall into the correct order? Like I said I am over my head on this. Algorithms are not my cup of tea.
May be, you can come from this side:
grouped = (from.to_date..to.to_date).each do |dt|
existing_data = all_data.detect{ |data| data.first == dt }
if existing_data
# you code for existing date
else
# you code for non-existing date
end
# ...
end
# And, I think, it is not required in this case
#grouped = grouped.sort_by { |day| day['date'] }
This might get a little specific in parts, but here's how I managed to get the desired output. I decided to have this rails controller give me the exact input I'll need for my Angular Google Charts, but I made it clear where the question is directly answered In terms of a method to fill in missing dates and missing row values:
from = params[:from] || (params[:days].to_i-1).days.ago.to_date
to = params[:to] || 0.days.ago.to_date
all_data = current_user.values.all
.where(field_id: params[:field_id], created_at: from.beginning_of_day .. to.end_of_day)
.where.not(input: nil)
.order(input: :desc)
.group_by { |value| [value['created_at'].to_date, value['input']] }
.map { |k, v| {'date': k.first, 'input': k.last, 'count': v.length} }
# the object which will hold the data to be returned
grouped = {:cols => [], :rows => [] }
# Populate columns with a determined set of values for inputs
diffvals = Array.new
all_data.each { |day| diffvals.push day[:input] }
diffvals = diffvals.uniq
diffvals.each { |input| grouped[:cols].push({'id': "#{input}-id", 'label': input, 'type': 'number'}) }
grouped[:cols].unshift({'id': 'day', 'label': 'Date', 'type': 'string'})
##
## This and the next commented section answer the question:
##
# Create a set of dates that the actual data will be merged into
zeros = Array.new
(0..params[:days].to_i-1).each do |n|
diffvals.each do |input|
hash = Hash.new
hash[:date], hash[:input], hash[:count] = n.days.ago.to_date, input, 0
zeros.push hash
end
end
##
##
##
# Group the data by date after mapping the actual data onto the premade set of dates
data_by_date = zeros.map do |first_hash|
all_data.each do |second_hash|
if first_hash[:date] == second_hash[:date] && first_hash[:input] == second_hash[:input]
first_hash[:count] = second_hash[:count]
break
end
end
first_hash
end.group_by { |i| i[:date]}
# Populate rows of data
data_by_date.each_with_index do |(date, values), day|
#
# The first column is the date
grouped[:rows][day] = {c: [{ v: date }] }
#
# Then columns of value inputs
(0..grouped[:cols].length-2).each { |value| grouped[:rows][day][:c].push({v: values[value][:count] }) }
#
# Then a column for the total of all value counts
grouped[:rows][day][:c].push({v: values.map {|v| v[:count]}.reduce(0, :+) })
end
grouped[:cols].push({'id': "s", 'label': "Total", 'type': 'number'})
render json: grouped
Here's a sample set of data. Favorite color, 3 possible color choices. Over 5 days:
cols:
0: {id: "day", label: "Date", type: "string"}
1: {id: "Red-id", label: "Red", type: "number"}
2: {id: "Green-id", label: "Green", type: "number"}
3: {id: "Blue-id", label: "Blue", type: "number"}
4: {id: "s", label: "Total", type: "number"}
rows:
0: {c: [{v: "2015-11-01"}, {v: 18}, {v: 23}, {v: 8}, {v: 49}]}
1: {c: [{v: "2015-11-02"}, {v: 4}, {v: 4}, {v: 2}, {v: 10}]}
2: {c: [{v: "2015-11-03"}, {v: 5}, {v: 16}, {v: 0}, {v: 21}]}
3: {c: [{v: "2015-11-04"}, {v: 0}, {v: 0}, {v: 0}, {v: 0}]}
4: {c: [{v: "2015-11-05"}, {v: 0}, {v: 1}, {v: 6}, {v: 7}]}
This is exactly what is needed for the Angular Google Chart plugin