I'm having a great deal of trouble wrapping my head around recursion. Simple recursion I can do but this is one is not easy for me. My goal here is to speed up this search algorithm. I'm guessing recursion will help. It takes 15 seconds on a simple 43 node tree with children as it is. Below is my unrolled recursion fomr of the code that works.
var nodeList = new Array();
var removeList = new Array();
var count = 0;
var foundInThisNodeTree;
var find = function ( condition )
{
}
while ( this.treeIDMap.igTree( "nodeByPath", count ).data() )
{
var foundInThisNodeTree = false;
var n;
n = this.treeIDMap.igTree( "nodeFromElement", this.treeIDMap.igTree( "nodeByPath", count ) )
if ( n.data.ITEM.indexOf( filter ) > -1 ) { foundInThisNodeTree = true; }
else {//look deeper
var i = 0;
while ( this.treeIDMap.igTree( "nodeByPath", count + "_" + i ).data() )
{
n = this.treeIDMap.igTree( "nodeFromElement", this.treeIDMap.igTree( "nodeByPath", count + "_" + i ) );
if ( n.data.ITEM.indexOf( filter ) > -1 ) { foundInThisNodeTree = true; break; }
else {//look deeper
var j = 0;
while ( this.treeIDMap.igTree( "nodeByPath", count + "_" + i + "_" + j ).data() )
{
n = this.treeIDMap.igTree( "nodeFromElement", this.treeIDMap.igTree( "nodeByPath", count + "_" + i + "_" + j ) );
if ( n.data.ITEM.indexOf( filter ) > -1 ) { foundInThisNodeTree = true; break; }
else {//look deeper
var k = 0;
while ( this.treeIDMap.igTree( "nodeByPath", count + "_" + i + "_" + j + "_" + k ).data() )
{
n = this.treeIDMap.igTree( "nodeFromElement", this.treeIDMap.igTree( "nodeByPath", count + "_" + i + "_" + j + "_" + k ) );
if ( n.data.ITEM.indexOf( filter ) > -1 ) { foundInThisNodeTree = true; break; }
k++;
}
}
j++;
}
}
i++;
}
}
if ( !foundInThisNodeTree ) this.treeIDMap.igTree("removeAt", ""+count )
else count++;
}
*** second revision suggested by Mirco Ellmann *****
var nodeList = new Array();
var removeList = new Array();
var count = 0;
var foundInThisNodeTree;
filter = filter.toLowerCase();
while ( this.treeIDMap.igTree( "nodeByPath", count ).data() )
{
var foundInThisNodeTree = false;
var n;
n = this.treeIDMap.igTree( "nodeFromElement", this.treeIDMap.igTree( "nodeByPath", count ) )
if ( n.data.ITEM.toLowerCase().indexOf( filter ) > -1 ) { foundInThisNodeTree = true; }
else {//look deeper
var i = 0;
n = this.treeIDMap.igTree( "childrenByPath", count );
while ( n[i] )
{
if ( n[i].data.ITEM.indexOf( filter ) > -1 ) { foundInThisNodeTree = true; break; }
var j = 0;
n = this.treeIDMap.igTree( "childrenByPath", count + "_" + i );
while ( n[j] )
{
if ( n[j].data.ITEM.indexOf( filter ) > -1 ) { foundInThisNodeTree = true; break; }
var k = 0;
n = this.treeIDMap.igTree( "childrenByPath", count + "_" + i + "_" + j);
while ( n[k] )
{
if ( n[k].data.ITEM.indexOf( filter ) > -1 ) { foundInThisNodeTree = true; break; }
k++;
}
j++;
}
i++;
}
}
if ( !foundInThisNodeTree ) this.treeIDMap.igTree("removeAt", ""+count )
else count++;
}
****using my branchable trees to get the data no need for any calls to tree****
var count = 0;
var foundInThisNodeTree;
filter = filter.toLowerCase();
while ( this.treeIDMap.igTree( "nodeByPath", count ).data() )
{
var foundInThisNodeTree = false;
var n;
n = this.treeIDMap.igTree( "nodeFromElement", this.treeIDMap.igTree( "nodeByPath", count ) )
if ( n.data.ITEM.toLowerCase().indexOf( filter ) > -1 ) { foundInThisNodeTree = true; }
if ( n.data.branch )//look at all childer under the root node
{
var i = 0;
n = n.data.branch;
while ( n[i] )//look at all childer under the root node
{
if ( n[i].ITEM.toLowerCase().indexOf( filter ) > -1 ) { foundInThisNodeTree = true; break; }
while ( n[i].branch )//look deeper
{
var j = 0;
n = n[i].branch;
if ( n[j].ITEM.toLowerCase().indexOf( filter ) > -1 ) { foundInThisNodeTree = true; break; }
while ( n[j].branch )//look deeper
{
var k = 0;
n = n[j].branch;
if ( n[k].ITEM.toLowerCase().indexOf( filter ) > -1 ) { foundInThisNodeTree = true; break; }
k++;
}
j++;
}
i++;
}
}
if ( !foundInThisNodeTree ) this.treeIDMap.igTree("removeAt", ""+count )
else count++;
}
instead of always use "nodeByPath" you should use "childrenByPath".
that would minimize the search calls on the igTree.
PS: USE not REPLACE ;)
You're not really doing this recursively. You're rather repeating your code for each level in the hierarchy. What you want is a helper function which takes the current node-path as a parameter and recursively calls the same method for each of its children with their id added to the path of the current node. Recursively means the code should work for any depth of tree. To me it looks like your code will only work for a set depth.
For the speed issue, there might be two issues. I didn't really read your code too closely, so I leave it to you to figure out which one is more likely.
You might be revisiting nodes. If so, obviously that would impact performance.
The framework you're using might be slow with looking up the nodes. One solution could be to find alternate methods to call on the framework which is meant for what you're doing. For instance the framework might have a hierarchical representation internally, but has to rebuild it or parse it when you pass in your full paths. Look for methods taking a source and relative path instead. If that's not the problem the framework might just be slow, and you might be better of to read all the nodes and build your own in-memory tree to use instead.
ok, I found a way to use the data provider and use a normal Json search. Still if anyone can speed this up I'd be grateful. I just when from 15 seconds to 1. This one has the recursion I need.
findInObject = function( obj, prop, val )
{
if ( obj !== null && obj.hasOwnProperty( prop ) && obj[prop].toLowerCase().indexOf(val) > -1 )
{
return obj;
} else
{
for ( var s in obj )
{
if ( obj.hasOwnProperty( s ) && typeof obj[s] == 'object' && obj[s] !== null )
{
var result = findInObject( obj[s], prop, val );
if ( result !== null )
{
return result;
}
}
}
}
return null;
}
for ( var i = 0; i < this.treeData.length; i++)
{
if ( findInObject( this.treeData[i], "ITEM", filter ) ) foundNodes.push( this.treeData[i] )//does the node have a match?
}
this.treeIDMap.igTree( { dataSource: foundNodes } );
this.treeIDMap.igTree( "dataBind" );
};
Related
i want to run my 3 axes gantry(stm32) in sequence similar to the sequence of serial data sent from the pc but this is not happening. no data is lost as all the axes perform their task but in wrong sequence.
this is the recieve complete callback loop
`void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(r != ',')
{
Rx[i++] = r;
}
else
{
strncpy(s1,Rx,i);
Home = strrchr(s1, 'H');
StringX = strrchr(s1, 'X');
StringY = strrchr(s1, 'Y');
StringZ = strrchr(s1, 'Z');
StringW = strrchr(s1, 'W');
if(Home[0] == 'H' && Home[1] == 'O' && Home[2] == 'M' && Home[3] == 'E')
{
homeValue = 1;
}
if(StringX[0] == 'X')
{
MoveX= substr(StringX,1,8);
MoveXvalue = (atol(MoveX))/100;
SpeedX = substr(StringX,8,12);
SpeedXvalue = atol(SpeedX);
insertintoQueue_X(MoveXvalue, SpeedXvalue);
insertintoSequenceQueue (1);
}
if(StringY[0] == 'Y')
{
MoveY= substr(StringY,1,8);
MoveYvalue = (atol(MoveY))/100;
SpeedY = substr(StringY,8,12);
SpeedYvalue = atol(SpeedY);
insertintoQueue_Y(MoveYvalue, SpeedYvalue);
insertintoSequenceQueue (2);
///goes on for other axes
/
i = 0;
}
}`
i tried sequencing these received cmds with below loop(posting only for one axis)
`void insertintoQueue_X (int j, int l)
{
uint8_t queuefull[] = "XFULL";
if(countXmove == 256 || countXspeed == 256 )
{
HAL_UART_Transmit_IT (&huart1, queuefull, sizeof (queuefull));
}
Xmovequeue[countXmove] = j ;
countXmove++;
Xspeedqueue[countXspeed] = l;
countXspeed++;
}
void removefromQueue_X()
{
//uint8_t queueEmpty[] = "XEMPTY";
/*if(countXmove == 0 || countXspeed == 0)
{
HAL_UART_Transmit_IT (&huart2, queueEmpty, sizeof (queueEmpty));
}*/
currentXmoveelement = Xmovequeue[0];
currentXspeedelement = Xspeedqueue[0];
for(int i = 0; i < countXmove - 1; i++)
{
Xmovequeue[i] = Xmovequeue[i+1];
Xspeedqueue[i] = Xspeedqueue[i+1];
}
}`
while loop is as below
` removefromSequenceQueue();//only called once in while loop
for(int p = 0; p < countXmove ; p++)
{
if(currentSequence == 1)
{
removefromQueue_X();
if(currentXmoveelement >0)
{
//uint8_t Xmovvestatus[] = "XMMM";
if(CurrentXposition != currentXmoveelement)
{
if(CurrentXposition > currentXmoveelement )
{
currentmoveX = CurrentXposition - currentXmoveelement;
motorMoveTo(currentmoveX,0,currentXspeedelement,20,SMSPR_X,SMS_X,SMDPR_X,SMD_X);
}
else if(CurrentXposition < currentXmoveelement )
{
// HAL_UART_Transmit_IT (&huart1, Xmovvestatus, sizeof (Xmovvestatus));
currentmoveX = currentXmoveelement - CurrentXposition ;
motorMoveTo(currentmoveX,1,currentXspeedelement,20,SMSPR_X,SMS_X,SMDPR_X,SMD_X);
}
CurrentXposition = currentXmoveelement;
currentXmoveelement = 0;
currentmoveX = 0;
MoveXvalue=0;
}
}
}
}
Is it possible to somehow configure bundle to generate images also for retina display, like #2x?
Or can someone give me an advice how to deal with retina?
Thanks
According to this comment by nahakiole, there are 2 solutions for this:
You can either use the picture element which would provide the syntax
to declare multiple sources for an image.
http://w3c.github.io/html/semantics-embedded-content.html#the-picture-element
The other method which we've tried was, if you can guarantee that the
image exists, to use a modified version of the retina.js which adds
_retina to the filter name and checks if a image with this name exists.
Modified version of retina.js by nahakiole:
/*-----------------------------------------------------------------------------------*/
/* RETINA.JS
/*-----------------------------------------------------------------------------------*/
(function () {
var regex = /(media\/cache\/filter_[A-Z]+)/i //Added this
function t(e) {
this.path = e;
var t = this.path.split("."),
n = t.slice(0, t.length - 1).join("."),
r = t[t.length - 1];
this.at_2x_path = (n + '.' + r).replace(regex, '$1_retina') //Changed that
}
function n(e) {
this.el = e, this.path = new t(this.el.getAttribute("src"));
var n = this;
this.path.check_2x_variant(function (e) {
e && n.swap()
})
}
var e = typeof exports == "undefined" ? window : exports;
e.RetinaImagePath = t, t.confirmed_paths = [], t.prototype.is_external = function () {
return !!this.path.match(/^https?\:/i) && !this.path.match("//" + document.domain)
}, t.prototype.check_2x_variant = function (e) {
var n, r = this;
if (this.is_external()) return e(!1);
if (this.at_2x_path in t.confirmed_paths) return e(!0);
n = new XMLHttpRequest, n.open("HEAD", this.at_2x_path), n.onreadystatechange = function () {
return n.readyState != 4 ? e(!1) : n.status >= 200 && n.status <= 399 ? (t.confirmed_paths.push(r.at_2x_path), e(!0)) : e(!1)
}, n.send()
}, e.RetinaImage = n, n.prototype.swap = function (e) {
function n() {
t.el.complete ? (t.el.setAttribute("width", t.el.offsetWidth), t.el.setAttribute("height", t.el.offsetHeight), t.el.setAttribute("src", e)) : setTimeout(n, 5)
}
typeof e == "undefined" && (e = this.path.at_2x_path);
var t = this;
n()
}, e.devicePixelRatio > 1 && (window.onload = function () {
var e = document.getElementsByTagName("img"),
t = [],
r, i;
for (r = 0; r < e.length; r++) i = e[r], t.push(new n(i))
})
})();
I created a variable q outside of any function. From within my function I am attempting to simply increment it with a ++. Will this increment the global q or is this simply appending the value to a local variable? As you can see in the code sample below I am attempting to use the value of the global variable (which I intend to be updated during each execution of this script) to set a variable which should trigger this function via .change. The function is initially trigger (when q = 1) however it is not trigger when a selection is made from the dropdown box with id = "selectedId2" which is leading me to believe that q has retained a value of 1 though I successfully incremented it when the function was ran prior. Any advise of how I can increment the variable "q" for each iteration of this script would be greatly appreciated.
if (q === 1) {
selectedDiv = '#selectId1';
selectedDiv2 = '#selectId2';
}
if (q === 2) {
selectedDiv = '#selectedId2';
selectedDiv2 = '#selectedId3';
}
if (q === 3) {
selectedDiv = '#selectedId3';
selectedDiv2 = '#selectedId4';
}
if (q === 4) {
selectedDiv = '#selectedId4';
selectedDiv2 = '#selectedId5';
}
if (q === 5) {
selectedDiv = '#selectedId5';
selectedDiv2 = '#selectedId6';
}
$(selectedDiv).change(function () {
if (q == 1) {
var pullDownDivs = '#2';
}
if (q == 2) {
var pullDownDivs = '#3';
}
if (q == 3) {
var pullDownDivs = '#4';
}
if (dropDownSelectJoined != null) {
var dropDownSelectJoined = dropDownSelectJoined + ", " + $(selectedDiv).val();
}
else {
var dropDownSelectJoined = $(selectedDiv).val();
}
var SelArea = $(selectedDiv).val();
if (SelArea != 0) {
var url = '#Url.Action("NetworkSubForm")';
q++;
$.post(url, { RemovedAreaId: $('#RemovedAreaId').val(), selectedNetworkId: $('#SelectedNetworkId').val(), dropDownSelectJoined: dropDownSelectJoined },
function (data) {
var productDropdown = $(selectedDiv2);
productDropdown.empty();
productDropdown.append("<option>-- Select Area --</option>");
for (var i = 0; i < data.length; i++) {
productDropdown.append($('<option></option>').val(data[i].Value).html(data[i].Text));
}
});
$(pullDownDivs).show();
$(pullDownDivs).html();
}
else {
$(pullDownDivs).hide();
$(pullDownDivs).html();
}
});
I don't know what the rest of your code looks like, but you can see this kind of behavior due to "shadowing":
var q = 0; //global "q"
function handler() {
var q = 0; //local "q" that shadows the global "q";
...
...
q++;
console.log(q);
}
Repeatedly calling handler will output 1 each time since you are redefining a local q within handler. However, the outer q remains unchanged. But if you did this:
var q = 0; //global "q"
function handler() {
var q = 0; //local "q" that shadows the global "q";
...
...
window.q++;
console.log(window.q);
}
The global q will be updated since you are explicitly referencing it by doing window.q.
I have two numbers, the first, is the original price, the second, is the discounted price.
I need to work out what percentage a user saves if they purchase at the second price.
example
25, 10 = 60%
365, 165 = 55%
What I dont know is the formula to calculate this.
I know this is fairly old but I figured this was as good as any to put this. I found a post from yahoo with a good explanation:
Let's say you have two numbers, 40 and 30.
30/40*100 = 75.
So 30 is 75% of 40.
40/30*100 = 133.
So 40 is 133% of 30.
The percentage increase from 30 to 40 is:
(40-30)/30 * 100 = 33%
The percentage decrease from 40 to 30 is:
(40-30)/40 * 100 = 25%.
These calculations hold true whatever your two numbers.
Original Post
((list price - actual price) / (list price)) * 100%
For example:
((25 - 10) / 25) * 100% = 60%
I see that this is a very old question, but this is how I calculate the percentage difference between 2 numbers:
(1 - (oldNumber / newNumber)) * 100
So, the percentage difference from 30 to 40 is:
(1 - (30/40)) * 100 = +25% (meaning, increase by 25%)
The percentage difference from 40 to 30 is:
(1 - (40/30)) * 100 = -33.33% (meaning, decrease by 33%)
In php, I use a function like this:
function calculatePercentage($oldFigure, $newFigure) {
if (($oldFigure != 0) && ($newFigure != 0)) {
$percentChange = (1 - $oldFigure / $newFigure) * 100;
}
else {
$percentChange = null;
}
return $percentChange;
}
The formula would be (original - discounted)/original. i.e. (365-165)/365 = 0.5479...
function calculatePercentage($oldFigure, $newFigure)
{
$percentChange = (($oldFigure - $newFigure) / $oldFigure) * 100;
return round(abs($percentChange));
}
100% - discounted price / full price
If total no is: 200
and getting 50 number
then take percentage of 50 in 200 is:
(50/200)*100 = 25%
I have done the same percentage calculator for one of my app where we need to show the percentage saved if you choose a "Yearly Plan" over the "Monthly Plan". It helps you to save a specific amount of money in the given period. I have used it for the subscriptions.
Monthly paid for a year - 2028
Yearly paid one time - 1699
1699 is a 16.22% decrease of 2028.
Formula: Percentage of decrease = |2028 - 1699|/2028 = 329/2028 = 0.1622
= 16.22%
Code:
func calculatePercentage(monthly: Double, yearly: Double) -> Double {
let totalMonthlyInYear = monthly * 12
let result = ((totalMonthlyInYear-yearly)/totalMonthlyInYear)*100
print("percentage is -",result)
return result.rounded(toPlaces: 0)
}
Usage:
let savingsPercentage = self.calculatePercentage(monthly: Double( monthlyProduct.price), yearly: Double(annualProduct.price))
self.btnPlanDiscount.setTitle("Save \(Int(savingsPercentage))%",for: .normal)
The extension usage for rounding up the percentage over the Double:
extension Double {
/// Rounds the double to decimal places value
func rounded(toPlaces places:Int) -> Double {
let divisor = pow(10.0, Double(places))
return (self * divisor).rounded() / divisor
}
}
I have attached the image for understanding the same:
This is function with inverted option
It will return:
'change' - string that you can use for css class in your template
'result' - plain result
'formatted' - formatted result
function getPercentageChange( $oldNumber , $newNumber , $format = true , $invert = false ){
$value = $newNumber - $oldNumber;
$change = '';
$sign = '';
$result = 0.00;
if ( $invert ) {
if ( $value > 0 ) {
// going UP
$change = 'up';
$sign = '+';
if ( $oldNumber > 0 ) {
$result = ($newNumber / $oldNumber) * 100;
} else {
$result = 100.00;
}
}elseif ( $value < 0 ) {
// going DOWN
$change = 'down';
//$value = abs($value);
$result = ($oldNumber / $newNumber) * 100;
$result = abs($result);
$sign = '-';
}else {
// no changes
}
}else{
if ( $newNumber > $oldNumber ) {
// increase
$change = 'up';
if ( $oldNumber > 0 ) {
$result = ( ( $newNumber / $oldNumber ) - 1 )* 100;
}else{
$result = 100.00;
}
$sign = '+';
}elseif ( $oldNumber > $newNumber ) {
// decrease
$change = 'down';
if ( $oldNumber > 0 ) {
$result = ( ( $newNumber / $oldNumber ) - 1 )* 100;
} else {
$result = 100.00;
}
$sign = '-';
}else{
// no change
}
$result = abs($result);
}
$result_formatted = number_format($result, 2);
if ( $invert ) {
if ( $change == 'up' ) {
$change = 'down';
}elseif ( $change == 'down' ) {
$change = 'up';
}else{
//
}
if ( $sign == '+' ) {
$sign = '-';
}elseif ( $sign == '-' ) {
$sign = '+';
}else{
//
}
}
if ( $format ) {
$formatted = '<span class="going '.$change.'">'.$sign.''.$result_formatted.' %</span>';
} else{
$formatted = $result_formatted;
}
return array( 'change' => $change , 'result' => $result , 'formatted' => $formatted );
}
I think this covers this formula sufficiently,
((curr value - base value) / (curr value)) * 100%
Basically we just (in programming):
perform the calculation if both numbers are not 0.
If curr value is 0 then we return -100 % difference from the base,
if both are 0 then return 0 (we can't divide by 0)
Powershell example:
Strip any non numeric from vars and perform calculation
Function Get-PercentageSaved {
#((curr value - base value) / (curr value)) * 100%
param(
[Parameter(Mandatory = $false)][string]$CurrVal = $null,
[Parameter(Mandatory = $false)][string]$BaseVal = $null
)
$Result = $null
Try {
$CurrVal = [float]($CurrVal -replace '[^0-9.]', '')
$BaseVal = [float]($BaseVal -replace '[^0-9.]', '')
if (-Not($null -eq $CurrVal) -And (-Not($null -eq $BaseVal))) {
if ($CurrVal -eq 0) {
If ($BaseVal -eq 0) {
$Result = 0
} Else {
$Result = -100
}
}
else {
$Result = [math]::Round([float]((($CurrVal - $BaseVal) / $CurrVal) * 100),2)
}
}
}
Catch {}
Return [float]$Result
}
So we have flv file, we play it with mx:vidodisplay for example. how to get on which stream frame we are currently on?
you can check the nearest keyframe to the current time in stream metadata
upd
when creating a stream you need to handle its' onMetaData call:
private var metaInfo: Object;
private function initStream():void{
stream = new NetStream(conn);
stream.bufferTime = 5;
stream.addEventListener(NetStatusEvent.NET_STATUS, onStatus);
stream.client = new Object();
stream.client.onMetaData = onMetaData;/*this is what you need*/
video.attachNetStream(stream);
}
private function onMetaData(info:Object):void {
metaInfo = info;
var tmpstr:String = '';
for(var s:String in info){
var tstr:String = s + ' = ' + info[s] + '\n';
tmpstr += tstr.indexOf('object') == -1 ? tstr : '';
for(var a:String in info[s]){
var ttstr:String = s + ':' + a + ' = ' + info[s][a] + '\n';
tmpstr += ttstr.indexOf('object') == -1 ? ttstr : '';
for(var c:String in info[s][a]){
var tttstr:String = s + ':' + a + ':' + c + ' = ' + info[s][a][c] + '\n';
tmpstr += tttstr.indexOf('object') == -1 ? tttstr : '';
}
}
}
trace(tmpstr);
}
in this trace you'll see if the streams' metadata has items like:
seekpoints:93:offset = 10342550
seekpoints:93:time = 165.799
or maybe:
keyframes:times = 0,0.48,0.96,1.44,1.92,2.4,2.88,3.36,3.84,4.32,4.8,5.28,5.76,6.24
keyframes:filepositions = 1063,95174,136998,176043,209542,239148,271062,302006,331724,363948,395039,427503,456317,483313
it depends on encoder settings, if your metadata has any object of this kind (metadata['keyframes'], metadata['seekpoints'] etc) you can do the following:
for (var i:int = 0; i < metaInfo['keyframes']['times'].length; i++) {
if (stream.time < metaInfo['keyframes']['times'][i]) {
var keyFrameNum: int = (metaInfo['keyframes']['times'][i] - stream.time < stream.time - metaInfo['keyframes']['times'][i - 1]) ? i : i - 1;
}
}
I did a static class to parse netstream metadata object to as3 object. You can use JSON.stringify(parse(info)) to check all attribute in info. This class just draftly implement. May be some bugs inside.
public class NetStreamMetaData
{
public static function parse(object:Object, isArray:Boolean = false):Object{
var ret:Object = {};
if(isArray)
ret = [];
var k:String;
for(k in object){
if(isNaN(Number(k))){
if(object[k] is Array){
ret[k] = parse(object[k], true);
}else{
ret[k] = object[k];
}
}else{
if(object[k] is Array){
ret.push(parse(object[k], false));
}else{
ret.push(object[k]);
}
}
}
return ret;
}
}