zio, custom Assertion renderer for current value - customization

We have a custom zio.test.Assertion that wrap json-path-assert:
def isJson(matching: org.hamcrest.Matcher[_ >: ReadContext]): Assertion[HttpEntity] = {
def test(entity: => HttpEntity): Boolean = {
// Removed for brevity
}
Assertion.assertion[HttpEntity]("isJson")(param(matching))(test)
}
We are quite happy with it but the failure message is far to be obvious:
response.body = Strict(ByteString(121, 32, 95, 111, 10, 108, 113, 35, 50, 90, 124, 23, 112, 111, 112, 31, 48, 24, 46, 31, 111, 22, 111, 25, 93, 52, 41, 54, 59, 90, 100, 43, 42, 51, 75, 14, 41, 54, 40, 65, 34, 42, 99, 88, 100, 54, 34, 25, 33, 89, 41, 40, 54, 52, 44, 40, 31, 101, 112, 105, 91, 10, 35, 125, 79, 106, 95, 11, 11, 32, 85, 13, 43, 104, 111)... and [661] more,Some(application/json)) did not satisfy isJson(with json path "$['store']['name']")
I would like to print the Json string decoded from those bytes but I do not see how to do that.
How can we customize the messages of a custom zio.test.Assertion?
Thanks

The param(matching) means that you are using the toString method of matching to render the the input of the assertion.
You can pass the decoded json string instead to have that display. For example (assuming your json is UTF-8 encoded):
Assertion.assertion[HttpEntity.Strict]("isJson")
(param(matching.data.decodeString(StandardCharsets.UTF_8))(test)
That particular example only works on HttpEntity.Strict but can be generalized to HttpEntity if you access the entity contents with .dataStream

Related

Initialising ChartJS with dataset index[0]

I've written a python script to get data from Google Search Console, stores it etc etc and print out an html output. The whole thing works really well and I've used buttons to select different datasets to hide/show them as you click on them.
I have no idea how to initialise the chart with index[0] though, all datasets are being rendered and shown when the page is loaded. I've had a look through the documentation but this is way over my head. Is there something in the options I can call to just show one dataset right from the start?
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<div class="m-5">
<div class="card col-md-6 offset-md-3">
<canvas id="myChart" ></canvas>
</div>
</div>
<div class="listSelector">
<ul>
<button onclick="toggleData(0)">https://www.somewebsite.co.uk/</button><br>
<button onclick="toggleData(1)">https://www.somewebsite.co.uk/blog/</button><br>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.6.0/chart.min.js"></script><script>const ctx = document.getElementById('myChart').getContext('2d');const myChart = new Chart(ctx,
{type:"line",data:{labels:['2022-07-16', '2022-07-17', '2022-07-18', '2022-07-19', '2022-07-20', '2022-07-21', '2022-07-22', '2022-07-23', '2022-07-24', '2022-07-25', '2022-07-26', '2022-07-27', '2022-07-28', '2022-07-29', '2022-07-30', '2022-07-31', '2022-08-01', '2022-08-02', '2022-08-03', '2022-08-04', '2022-08-05', '2022-08-06', '2022-08-07', '2022-08-08', '2022-08-09', '2022-08-10', '2022-08-11', '2022-08-12', '2022-08-13', '2022-08-14', '2022-08-15', '2022-08-16', '2022-08-17', '2022-08-18', '2022-08-19', '2022-08-20', '2022-08-21', '2022-08-22', '2022-08-23', '2022-08-24', '2022-08-25', '2022-08-26', '2022-08-27', '2022-08-28', '2022-08-29', '2022-08-30', '2022-08-31', '2022-09-01', '2022-09-02', '2022-09-03', '2022-09-04', '2022-09-05', '2022-09-06', '2022-09-07', '2022-09-08', '2022-09-09', '2022-09-10', '2022-09-11', '2022-09-12', '2022-09-13', '2022-09-14', '2022-09-15', '2022-09-16', '2022-09-17', '2022-09-18', '2022-09-19', '2022-09-20', '2022-09-21', '2022-09-22', '2022-09-23', '2022-09-24', '2022-09-25', '2022-09-26', '2022-09-27', '2022-09-28', '2022-09-29', '2022-09-30', '2022-10-01', '2022-10-02', '2022-10-03', '2022-10-04', '2022-10-05', '2022-10-06', '2022-10-07', '2022-10-08', '2022-10-09', '2022-10-10', '2022-10-11', '2022-10-12', '2022-10-13', '2022-10-14', '2022-10-15', '2022-10-16', '2022-10-17', '2022-10-18', '2022-10-19', '2022-10-20', '2022-10-21', '2022-10-22', '2022-10-23'],datasets: [
{label: "https://www.somewebsite.co.uk/", data: [4551, 5072, 5426, 5224, 4672, 4257, 4035, 4376, 4680, 4916, 4957, 4929, 4786, 5391, 5390, 5991, 5463, 5308, 4739, 4450, 4577, 4831, 5045, 5006, 4609, 4098, 3720, 4300, 5185, 5251, 4503, 3757, 3971, 3967, 3772, 3619, 3585, 3601, 3485, 3454, 3497, 3431, 3602, 3732, 4574, 4470, 4393, 3541, 3397, 3458, 3564, 3823, 3897, 3682, 3158, 3081, 3395, 4089, 4502, 4664, 4866, 4398, 4098, 3845, 4018, 4149, 4272, 4324, 4285, 4085, 4403, 4754, 5957, 6702, 7324, 7109, 7209, 7477, 7800, 7785, 7639, 7195, 6739, 6729, 7143, 7481, 7313, 6630, 6127, 5847, 6239, 6811, 7285, 7335, 7139, 6941, 6663, 6233, 4054, 1937],fill: "start", backgroundColor: ['rgba(90, 204, 204,0.4)'], borderColor: ['rgba(90, 204, 204, 1)'], borderWidth: 2 },
{label: "https://www.somewebsite.co.uk/blog/", data: [75, 88, 123, 116, 92, 62, 39, 59, 87, 90, 83, 55, 53, 37, 51, 77, 99, 83, 61, 41, 32, 30, 35, 35, 34, 28, 30, 21, 20, 17, 32, 40, 43, 38, 29, 33, 33, 47, 56, 49, 34, 17, 14, 19, 23, 31, 25, 17, 7, 17, 28, 39, 57, 55, 47, 21, 20, 22, 20, 22, 26, 29, 22, 21, 26, 48, 62, 63, 47, 35, 33, 33, 30, 32, 36, 37, 29, 27, 21, 22, 21, 24, 33, 25, 37, 35, 44, 34, 29, 20, 13, 23, 44, 52, 42, 32, 32, 27, 13, 2],fill: "start", backgroundColor: ['rgba(90, 204, 204,0.4)'], borderColor: ['rgba(90, 204, 204, 1)'], borderWidth: 2 },
]},options: {
plugins: {
legend: {
display:false
}
},
scales: {
y: {
beginAtZero: true
}}}});
function toggleData(value) {
const showValue = myChart.isDatasetVisible(value)
if(showValue === true) {
myChart.hide(value);
}
if(showValue === false) {
myChart.show(value);
}
}
</script>
My script can produce hundreds of datasets, I've shortened it to 2 here because of the size of the label and data arrays.
I'm missing a function or method call. I would like the very first dataset to be shown, then as I click on different buttons the chart to refresh. I think I can do that, I'm just looking for the initialisation of the chart.

Django - Show list datetime values in template

I have below code which outputs datetime values as shown below:
available_hours = [hour for hour in hours_between if hour not in reserved_times]
print(available_hours)
[datetime.datetime(2021, 12, 8, 12, 0), datetime.datetime(2021, 12, 8, 13, 0), datetime.datetime(2021, 12, 8, 14, 0), datetime.datetime(2021, 12, 8, 16, 0), datetime.datetime(2021, 12, 8, 17, 0), datetime.datetime(2021, 12, 8, 18, 0), datetime.datetime(2021, 12, 8, 19, 0), datetime.datetime(2021, 12, 8, 20, 0), datetime.datetime(2021, 12, 8, 21, 0)]
I render them in the template like:
{{ available_hours }}
and i got all above datetime values.
How can i change the format so i can show them like Mon 12 2021, 21:00?
Thank you
try this
<p>
available hours:
{% for my_time in available_hours %}
{{ my_time|date:"M d Y, H:i" }}
{% endfor %}
</p>

Problem passing parameters into main function in C++ test bench

I'm trying to test a function I have created in C++ by using a testbench. The main function parameters are two 8x8 arrays:
void multiplyArray2(int A[8][8], int B[8][8]){
In my test bench file, I have created an input array of values and an output array and am trying to input them into the function:
int dataIn[8][8];
int dataOut[8][8];
int main(){
dataIn = {{68, 68, 67, 67, 66, 67, 67, 67},
{69, 69, 68, 68, 67, 69, 67, 67},
{70, 70, 71, 71, 70, 70, 70, 70},
{72, 72, 72, 71, 72, 72, 72, 71},
{74, 74, 73, 73, 74, 74, 74, 74},
{75, 76, 75, 75, 76, 76, 75, 75},
{76, 77, 77, 76, 76, 76, 76, 76},
{79, 78, 79, 79, 78, 76, 77, 77}};
multiplyArray2(dataIn, dataOut);
When I try to input parameters into the function in the test bench it is providing me with this error message:
And I have no idea why...
void multiplyArray2(int A[][8], int B[][8])
This should solve your problem.
Multi-dimensional arrays are not very well supported by default in C and C++. You can pass an N-dimension array only when you know N-1 dimensions at compile time.

How to add target line in google column chart?

How to add the target line in google column chart like this.
If you'd like to combine the columnchart and linechart, use ComboChart. Documentation and examples are here :
https://developers.google.com/chart/interactive/docs/gallery/combochart
basically, have the data point for the line chart as one of the columns in the DataTable and specify this column to be the "series" = "line", whereas the other columns are visualized in a ColumnChart.
You can use a Stepped Area series to achieve this. It's a little awkward but works well.
var data = google.visualization.arrayToDataTable([
['Month', 'Bolivia', 'Ecuador', 'Madagascar', 'Papua New Guinea', 'Rwanda', ''],
['2004/05', 165, 938, 522, 998, 450, 250],
['2005/06', 135, 1120, 599, 1268, 288, 250],
['2006/07', 157, 1167, 587, 807, 397, 250],
['2007/08', 139, 1110, 615, 968, 215, 250],
['2008/09', 136, 691, 629, 1026, 366, 250]
]);
var options = {
seriesType: "line",
series: {5: {
type: "steppedArea",
color: '#FF0000',
visibleInLegend: false,
areaOpacity: 0}
}
};
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, options);
Example
Stepped Area Google Chart Example
To avoid the ugly outline, just use: enableInteractivity: false
To make the steppedArea #Ryan suggested above a litte bit less awkward, you can setup a second (right) axis and set the base line to the value you want for the target line. The second axis will be setup for the seppedArea data. This avoids the uggly outline effect when you hover the pointer over the chart and under the line. Do something like this in the options:
var options = {
seriesType: "line",
series: {5: {
type: "steppedArea",
color: '#FF0000',
visibleInLegend: false,
areaOpacity: 0,
targetAxisIndex: 1 } //tell the series values to be shown in axe 1 bellow
},
vAxes: [ //each object in this array refers to one axe setup
{}, //axe 0 without any special configurations
{
ticks: [250], //use this if you want to show the target value
baseline: 250 //this shifts the base line to 250
}
]
};

Custom tooltip text in Candlestick chart of google charts

I'm playing a bit with Google Charts API, and actually I need to change the default text showed in the tooltip of candlestick chart. Not only to change the style, but also it's content.
Does anyone knows how to achieve it?
Try this code to customize Tooltip content using html tags.
data.addRows([
['Mon', 20, 28, 38, 45, customTooltip('Monday')],
['Tue', 31, 38, 55, 66, customTooltip('Tuesday')],
['Wed', 50, 55, 77, 80, customTooltip('Wednesday')],
['Thu', 77, 77, 66, 50, customTooltip('Thursday')],
['Fri', 68, 66, 22, 15, customTooltip('Friday')]
]);
function customTooltip(text) {
return '<div style="padding:5px 5px 5px 5px;">' +
'<table id="medals_layout" style=" color:#db6acf; font-size:large">' + '<tr>' +
'<td><b>' + text + '</b></td>' + '</tr>' + '</table>' + '</div>';
}
Take a look at this jqfaq.com that has a working sample for Line chart
You can drop this into google's visualization playground:
function drawVisualization() {
data = new google.visualization.DataTable()
data.addColumn('string', 'Date');
data.addColumn('number');
data.addColumn('number');
data.addColumn('number');
data.addColumn('number');
data.addColumn({type:'string',role:'tooltip'});
data.addRow();
base = 10;
data.setValue(0, 0, 'Datapoint1');
data.setValue(0, 1, base++);
data.setValue(0, 2, base++);
data.setValue(0, 3, base++);
data.setValue(0, 4, base++);
data.setValue(0, 5, " This is my tooltip1 ");
data.addRow();
data.setValue(1, 0, 'Datapoint2');
data.setValue(1, 1, base++);
data.setValue(1, 2, base++);
data.setValue(1, 3, base++);
data.setValue(1, 4, base++);
data.setValue(1, 5, "This is my second tooltip2");
// Draw the chart.
var chart = new google.visualization.CandlestickChart(document.getElementById('visualization'));
chart.draw(data, {legend:'none', width:600, height:400});
}