How to use FORMATTED_VALUE in a cumulated graph? - iccube

At first, from the Data Render panel in icCube report, I used context.cumulativeCol(); in the Value field in order to create my cumulated graph.
Now, since the format of my data is not well suited for my application (I have values such as '4.547473508864641e-13' which I want to be formatted to 0.00), I tried to add parameters to the function :
var col = context.getColumnIndex();
var measure = context.getMeasures();
var property = "FORMATTED_VALUE";
return context.cumulativeCol(col, measure, property);
But I cannot get a proper output.
How should I do it?

You cannot use FORMATTED_VALUE to format numbers calculated on the client side, it's available on for data that comes directly from the server. So in your case you need to implement your own client-side formatting. You could use mathJS that bundled to the reporting i.e.:
return math.format(context.cumulativeCol(col), {notation: "fixed", precision: 2})
Or use any other JS formatting method like .toFixed(2)

Related

Doing CallOrder of Fake on itself with argument validation

How do i do a call order verification of a fake with argument validation in sinon.js?
It is the same fake which is called multiple times with different arguments...
something like below
let someFake = sinon.fake();
someFake(1);
someFake(2);
someFake(3);
sinon.assert.callOrder(someFake.calledWith(1), someFake.calledWith(2),
someFake.calledWith(3));
You are essentially using the wrong API for the job, so it's no wonder you are not getting the expected results :) If you look at the docs for callOrder you will see that the signature is using spy1, spy2, .., which indicates that it is meant to be used by more than one spy. A fake is implementation wise also a Spy, so all bits of the Spy API also applies to a Fake. From the docs:
The created fake Function, with or without behavior has the same API as a sinon.spy
A sidenode, that is a bit confusing, is that the docs often use the term "fake" to apply to any fake object or function, not functions created using the sinon.fake API specifically, although, that should not be an issue in this particular case.
With regards to your original question, the Spy API has got you covered since Sinon 1.0 here. You use getCall(n) to return the nth call. There are lots of interactive examples in the docs for this, but essentially you just do this:
// dumbed down version of https://runkit.com/fatso83/stackoverflow-66192966
const fake = sinon.fake();
fake(1);
fake(20);
fake(300);
sinon.assert.calledThrice(fake);
assertEquals(1, fake.getCall(0).args[0])
assertEquals(20, fake.secondCall.args[0])
assertEquals(300, fake.lastCall.args[0])
function assertEquals(arg1,arg2){
if(arg1 !== arg2) {
throw new Error(`Expected ${arg1} to equal ${arg2}`);
}
console.log(`${arg1} equal ${arg2}: OK`)
}
<script src="https://cdn.jsdelivr.net/npm/sinon#latest/pkg/sinon.js"></script>

How does one use a CDSView with MultiLine on GMAPPlot?

(First Question so apologies)
Bokeh 1.3.4
Situation:
I am trying top map a Bokeh MultiLine using a CDSView and all the existing examples seem to use the "figure" object which has a helper (multi_line) which accepts a view as an argument. I am doing this on top of a GMAPPlot which does not support multi_line (only MultiLine) (see below). The commented out line throws an error saying GMAPPlot does not support multi_line.
plot = GMapPlot(
x_range=Range1d(), y_range=Range1d(), map_options=map_options, sizing_mode='scale_height'
)
.
.
.
sel_sa1s = []
v_bf = [True if sa1_val in sel_sa1s else False for sa1_val in v_source.data['SA1']]
v_view = CDSView(source=v_source, filters=[BooleanFilter(v_bf)])
v_ml = MultiLine(xs="xs",ys="ys",line_color="black", line_width="w")
#v_rend = plot.multi_line(xs="xs",ys="ys",line_color="black", line_width="w", source=v_source, view=v_view)
v_rend = plot.add_glyph(v_source, v_ml, name='votes')
The snippet shown above works and maps the entire network (very crowded) because there is no filter. What I want to have happen is for the filter to be initialised to hide everything then when the user clicks on an area (SA1) it will display the network related to that SA1.
Actually I can do that but only one area at a time and it would be much more efficient to be able to load the whole map and use a filtered view to control which sub-networks are displayed.
It seems that GMAPPlot only likes the pattern:
create glyph
add glyph
So, my question is - how does one use a CDSView in this environment (how does one add it to the renderer?)
Screenshot of unfiltered data set
It seems that GMAPPlot only likes the pattern:
create glyph
add glyph
That has not been true for some time. There is a higher level bokeh.plotting.gmap function that creates and configures GMapPlot instances with deafult axes, etc, and also has all the same methods and conveniences as figure (e.g. multi_line). It will be much less work to go this route than assembling everything by hand from low-level objects.

Use input variable in assert or specify the data to assert

I have a unit test for a function that adds data (untransformed) to the database. The data to insert is given to the create function.
Do I use the input data in my asserts or is it better to specify the data that I’m asserting?
For eample:
$personRequest = [
'name'=>'John',
'age'=>21,
];
$id = savePerson($personRequest);
$personFromDb = getPersonById($id);
$this->assertEquals($personRequest['name'], $personFromDb['name']);
$this->assertEquals($personRequest['age'], $personFromDb['age']);
Or
$id = savePerson([
'name'=>'John',
'age'=>21,
]);
$personFromDb = getPersonById($id);
$this->assertEquals('John', $personFromDb['name']);
$this->assertEquals(21, $personFromDb['age']);
I think 1st option is better. Your input data may change in future and if you go by 2nd option, you will have to change assertion data everytime.
2nd option is useful, when your output is going to be same irrespective of your input data.
I got an answer from Adam Wathan by e-mail. (i took his test driven laravel course and noticed he uses the 'specify' option)
I think it's just personal preference, I like to be able to visually
skim and see "ok this specific string appears here in the output and
here in the input", vs. trying to avoid duplication by storing things
in variables." Nothing wrong with either approach in my opinion!
So i can't choose a correct answer.

Unable to build inline segments in RSiteCatalyst package in R

I am trying to build the inline segment to filter the pages (ex. to separate the pages for blogs and games) using the function BuildClassificationValueSegment() to get the data from Adobe Analytics API,
I have tried some thing like
report.data.visits <- QueueTrended(reportsuite.id,date.from,date.to,metrics,elements,
segment.inline = BuildClassificationValueSegment("evar2","blog","OR")).
Got error like :
Error in ApiRequest(body = report.description, func.name = "Report.Validate") :
ERROR: segment_invalid - Segment "evar2" not valid for this company
In addition: Warning message:
In if (segment.inline != "") { :
the condition has length > 1 and only the first element will be used
Please help on the same.Thanks in advance...
I recommend you to declare the InlineSegment in advance and store it in a variable. Then pass it to the QueueTrended function.
I've been using the following syntax to generate an inline segment:
InlineSegment <- list(container=list(type=unbox("hits"),
rules=data.frame(
name=c("Page Name(eVar48)"),
element=c("evar48"),
operator=c("equals"),
value=c(as.character("value1","value2"))
))
You can change the name and element arguments in order to personalize the query.
The next step is to pass the InlineSegment to the QueueRanked function:
Report <- as.data.frame(QueueRanked("reportsuite",
date.from = dateStart,
date.to = dateEnd,
metrics = c("pageviews"),
elements = c("element"),
segment.inline = InlineSegment,
max.attempts=500))
I borrowed that syntax from this thread some time ago: https://github.com/randyzwitch/RSiteCatalyst/issues/129
Please note that there might be easier ways to obtain this kind of report without using InlineSegmentation. Maybe you can use the selected argument from the QueueRanked function in order to narrow down the scope of the report.
Also, I'm purposefully avoiding the BuildClassificationValueSegment function as I found it a bit difficult to understand.
Hope this workaround helps...

integer output instead of string

I have created some static functions that return integer. In my view I want sum of these functions. I am using following code:
#myrepository.OverDraftCount() +
#myrepository.MortgageCount() +
#myrepository.InstallmentCount()+
#myrepository.RevolvingCount()+
#myrepository.OthersCount()
But it is returning 2 + 2+ 2 + 2 + 2 instead of 10 which it considers all these function's output as string. How can I change it ?
Thanks
You just forgot to add a Sum method to this class:
public decimal Sum()
{
return OverDraftCount() +
MortgageCount() +
InstallmentCount() +
RevolvingCount() +
OthersCount();
}
so that in your view:
#myrepository.Sum()
Views should be as dumb as possible. They are so dumb that are not even capable of adding numbers. Do not code such logic into them. They should only show information that is passed to them, not try to calculate and fetch data. That's not their responsibility.
The Razor view engine will treat everything as a string (HTML rendering means outputting a bunch of strings), so you'll need to perform the sum in a code block and the display it.
Try:
#{
var sum = myrepository.OverDraftCount() +
myrepository.MortgageCount() +
myrepository.InstallmentCount()+
myrepository.RevolvingCount()+
myrepository.OthersCount();
}
Then you can use the sum variable in your html:
<span>#sum</span>
EDIT to clarify all the upheaval:
As I have extensively stated in the comments, This will solve your problem, but it is hardly the neatest way to accomplish what you want. As I see it, you have 2 better options:
Either take the approach in #Darin Dimitrov's answer or
Perform the calculation in the controller and pass the sum value to the view, either as part of a View Model or through the ViewBag.

Resources