Two equals or not two equals - google-apps-script

I am working with 5 options: O, R, 1, 2, 3. My function here is trying to convert O and R to numeric equivalents while leaving the number values alone.I have tried this two ways and neither is working. This is the first way I tried it. It does not change any values at all.
function Level2Number (Level) //changes level R and O to numbers
{
switch (Level)
{
case (Level == "R"):
return 0
break;
case (Level == "O"):
return .5
break;
default:
return Level
break;
}
}
When I tried it this next way, it is doing what I want with the O and the R but i is placing the letter O in place of the 1, 2, and 3.
function Level2Number (Level) //changes level R and O to numbers for further calculation.//
{
switch (Level)
{
case (Level = "R"):
return 0
break;
case (Level = "O"):
return .5
break;
default:
return Level
break;
}
}
I am not sure how to go from here.

This doesn't work because logical expressions (as indicated by the parentheses) evaluate to either 'true' of 'false'. Your 'Level' variable is not of type Boolean (neither 'true' nor 'false'), so you'll always be stuck with the default scenario.
Use the following notation
switch(Level) {
case "R":
return 0;
default:
return Level;
}
Btw, putting 'break' after 'return' is completely redundant.

Related

Google Appscript IF Or statement not working

Good day everyone; I am running into an error I can't explain. The scenario is as follows, I have two input boxes that collect information. If no value is entered, I want the if statement to handle it and cause a break. The Input box also has an "x" to close the box, which returns a value of "Cancel". What I am trying to do is capture a condition where if no value is entered OR cancel is passed through, a break will occur. Right now, the problem is Google completely ignores the Or statement. I know individually, my IF logic works, but when coupled with OR it doesn't recognize the condition.
This is my current code:
var propnumber = Browser.inputBox('Enter RFI/RFQ Number', Browser.Buttons.OK);
if(propnumber != "" || propnumber != 'cancel'){} else{
SpreadsheetApp.getActiveSpreadsheet().toast('You must enter a value')
return
};
var myName = Browser.inputBox("Enter the Component Name",Browser.Buttons.OK_CANCEL);
if(myName != 'cancel')
{
I do something
}
As I mentioned in my description, my propnumber condition ignores the or and always accepts the value of cancel or blank. If I remove the or ( || ) then it works with one condition at a time.
I am sure this is something trivial any help appreciated.
What's wrong
The logic in the following part of your code
if(propnumber != "" || propnumber != 'cancel'){
// I assume some code will go here
} else{
SpreadsheetApp.getActiveSpreadsheet().toast('You must enter a value')
return
};
does not match the logic you've described here:
if no value is entered OR cancel is passed through, a break will occur.
Consider the case where propnumber is 'cancel':
propnumber != "" evaluates to true
propnumber != 'cancel' evaluates to false
Therefore the if(... || ...) condition in your code evaluates to true and the (currently empty) if block runs, rather than the else.
How to fix it
Option 1: A literal translation of the logic
if no value is entered OR cancel is passed through, a break will occur
would be
if(propnumber == "" || propnumber == 'cancel') {
SpreadsheetApp.getActiveSpreadsheet().toast('You must enter a value')
return
} else {
// Some action
}
Option 2: If you wish to swap the if and else clauses, you must negate the entire condition. So this will also work:
if(!(propnumber == "" || propnumber == 'cancel')) {
// Some action
} else {
SpreadsheetApp.getActiveSpreadsheet().toast('You must enter a value')
return
}
Note the added parentheses and single negation.
Option 3: use AND instead of OR in your existing code.
The expression !(A || B) is NOT logically equivalent to !A || !B. Instead, it is equivalent to !A && !B (see DeMorgan's Law). So this will also work:
if(propnumber != "" && propnumber != 'cancel') {
// Some action
} else {
SpreadsheetApp.getActiveSpreadsheet().toast('You must enter a value')
return
}

How can I do a custom sort on the following html table, forcing some rows to always appear beneath others?

I have the following data for a list of tasks:
I have an HTML table displaying this data, currently sorted by task name (todotask), ascending:
and task name (todotask), descending:
Child Tasks are those marked in italics namely 'A task to derive from' (three times a child) and 'Collect a set of trains' (once a child). The parent task has the same name as the child and the following three facts are true:
1 - The salmserna ends in 33 (for both child and parent).
2 - Only a child has a todosernm and that equals the parent's todosern.
3 - The parent task is always created before the child.
HTML:
<th ng-click="sortTasks(tasks, 'todotask', $event)">Task <img id='sortedIcon' src='/static/tasksApp/img/sorting.png' class='pull-right sortingIcon'></th>
<th ng-click="sortTasks(tasks, 'todostart', $event)">Start</th>
<th ng-click="sortTasks(tasks, 'todoend', $event)">End</th>
Angular Controller:
$scope.sortTasks = function (sortable, colName, event) {
// Sorting
sortable.sort($scope.sort_by(colName, $scope.sortOrder, function (a) {
if(a != null){
return a.toUpperCase();
}else{
return null;
}
}));
// Sorted icon
$('#sortedIcon').remove();
if ($scope.sortOrder) {
$(event.currentTarget).append("<img id='sortedIcon' src='/static/tasksApp/img/sortingUp.png' class='pull-right sortingIcon'>");
} else {
$(event.currentTarget).append("<img id='sortedIcon' src='/static/tasksApp/img/sorting.png' class='pull-right sortingIcon'>");
}
// Switch next sorting order
$scope.sortOrder = !$scope.sortOrder;
};
The above calls on the method sort_by, shown below:
/**
* Sorter function
* Can sort both alphabetically and numerically.
*/
$scope.sort_by = function (field, rev, primer) {
return function (a, b) {
var nameA = primer(a['todotask']);
var nameB = primer(b['todotask']);
var startA = primer(a['todostart']);
var startB = primer(b['todostart']);
var endA = primer(a['todoend']);
var endB = primer(b['todoend']);
if(nameA == nameB){
return (startA < startB) ? 1 : ((startA > startB) ? -1 : 0);
}else{
a = primer(a[field]);
b = primer(b[field]);
return ((a < b) ? -1 : ((a > b) ? 1 : 0)) * (rev ? -1 : 1);
}
};
};`
I need the child tasks to ALWAYS appear beneath the parent, and for sorting by name, this works with the above code, so when the names are equal, it sorts by start date and ignores the direction (rev), keeping the children below the parents and making use of fact 3 above.
THE PROBLEM:
I'm really struggling to understand how I can edit the code to ensure the children are kept beneath the parents WHEN SORTING BY START OR END, either ascending or descending.
Currently things look like this when sorting by start, ascending:
and descending:
This is unsurprisingly sorting by start date! I just can't get my head around how to keep the children beneath the parents when sorting by date.
In the sortTasks method, sortable is the array of tasks and each task has the properties available, such as:
task.todostart, task.todoend etc.....
I suppose fact 2 above should be considered in the sorting method somehow but any help would be great as I'm well and truly stuck.

How to make a For Loop of a nested IF Statement?

I am trying to make a for loop for this nested if statement in a Bejeweled clone I am practicing to code. As you can see it's pretty dumb to do it this way, because I want to loop through more matches, so I was wondering if there is a more efficient way than going through and making even more silly If statement nests about 7 times AND for each direction since the grid is 8 by 8.
The if ( i !== 0 ) bit is to prevent null errors. I think with the For statement if it were to be used it can be something like if ( i < loopvar ) instead
Thank you :3
if (i !== 0 && map[i][j].name == map[i-1][j].name) // this nest of if statements are gonna check the one to the left of the jewel we are looping through, and see if they match.
{
map[i][j].jewelsWest++;
if ( i !== 1 && map[i-1][j].name == map[i-2][j].name)
{
map[i][j].jewelsWest++;
}
}
I think recursion might me handy in this case:
map[i][j].jewelsWest = countMe(i, j, -1, 0);
map[i][j].jewelsEast = countMe(i, j, 1, 0);
map[i][j].jewelsNorth = countMe(i, j, 0, -1);
map[i][j].jewelsSouth = countMe(i, j, 0, 1);
private function countMe(x, y, xDiff, yDiff):int
{
if(map[x+xDiff] && map[x+xDiff][y+yDiff] && map[x][y].name == map[x+xDiff][y+yDiff].name)
{
return 1 + countMe(x+xDiff, y+yDiff, xDiff, yDiff);
}
else
{
return 0;
}
}

Keeping the variable 's value in recursive function, python 3.3

I managed to do it, some other way.
but I have a question, I had this code before
def jumphunt(start, mylist, count = 0):
if count < len(mylist):
place = mylist[start]
print(place)
if place == 0:
return True
elif start >= len(mylist) or start < 0:
return False
move_left = (start - place)
move_right = (start + place)
return jumphunt(move_right, mylist, count+1) or jumphunt(move_left, mylist, count+1)
else:
return False
but for some reason it's not trying both ways
to get to the last item on the list.
for example: [1,2,2,3,4,5,3,2,1,7,0] and ,start=mylist[0]
it supposed to jump like this (from 1-2-4-1-left to 2-left to 5-right to 0)
but it keeps trying to go right and then index is out of range etc.
I thought that if u use return of or this or that, it will try both until it reaches True, why won't it work here?
Thanks!
Include the value you want to keep as a default parameter for the method, like this:
def my_func(int, list, i=0):
a = (i + int)
if int == 0:
return True
elif a > len(list):
i -= int
else:
i += int
int = list[i]
my_func(int, list, i)
Bear in mind that it may not even always be possible to arrive at the end of the list doing the jumping pattern you describe, and even if it is possible, this method may choose the wrong branch.
A better algorithm would look like this:
def branching_search(list, start):
marks = [0]*len(list)
pos = start
while list[pos]!=0:
marks[pos]++
if marks[pos] % 2 == 0 and pos + list[pos] < len(list):
pos += list[pos]
elif marks[pos] % 2 == 1 and pos - list[pos] >= 0:
pos -= list[pos]
else:
return False
if all(item == 0 or item > 1 for item in list)
return False
return True
This way, if it comes to an item that it has already visited, it will decide to go the opposite direction that it went last time. Also, if it comes to an item that it can't leave without going out-of-bounds, or if there is not way to get to the end, it will give up and return.
EDIT: I realized there are a number of flaws in this algorithm! Although it is better than the first approach, it is not guaranteed to work, although the reasons are somewhat complicated.
Just imagine this array (the unimportant elements are left blank):
1, 2, , 5, , , , , 5, 0
The first two elements would get only one mark (thus the loop checking condition would not work), but it would still get stuck looping between the two fives.
Here is a method that will always work:
def flood_search(list):
marks = [[]]*len(list)
marks[0] = [0]
still_moving = True
while still_moving:
still_moving = False
for pos in range(0,len(list)):
if marks[pos]:
if pos + list[pos] < len(list) and not marks[pos + list[pos]]:
marks[pos + list[pos]] = marks[pos] + [list[pos]];
pos += list[pos]
still_moving = True
if pos - list[pos] >= 0 and not marks[pos - list[pos]]:
marks[pos - list[pos]] = marks[pos] + [-list[pos]];
pos -= list[pos]
still_moving = True
return marks[-1]
This works by taking every possible branch at the same time.
You can also use the method to get the actual route taken to get to the end. It can still be used as a condition, since it returns an empty list if no path is found (a falsy value), or a list containing the path if a path is found (a truthy value).
However, you can always just use list[-1] to get the last item.

Checking for same values using if statement in actionscript?

I'm working on a match-3 style puzzle game using Flixel, and so I'm working on checking each row and column to see if there is a match at any given time. However, I have 6 different pieces (as of right now) that are active, and each piece is identified by an integer. Given that, I can check, for each and every single piece, by doing something like this:
public function matchingCheck():void
{
if (piecesArray[0][1] == 1 && piecesArray[1][1] == 1 && piecesArray[2][1] == 1) {
FlxG.log("Yay!");
}
}
However, this is rather unwieldy and would basically cause way too much repetition for my liking.
At the very least, I would like to be able to check if the values in these arrays are equal to one another, without having to specify which value it is. At the very best, I'd love to be able to check an entire row for three (or more) adjacent pieces, but I will settle for doing that part manually.
Thanks for your help!
EDIT: Nevermind, my edit didn't work. It was just checking if piecesArray[2][1] == 1, which makes me a sad panda.
EDIT 2: I've selected the correct answer below - it's not exactly what I used, but it definitely got me started. Thanks Apocalyptic0n3!
You could cut down on that code a little bit by using another function
private function checkValid( arrayOfItemsToCheck:Array, value:* ):Boolean {
for ( var i:Number = 0; i < arrayOfItemsToCheck.length; i++ ) {
if ( arrayOfItemsToCheck[i] != value ) {
return false;
}
}
return true;
}
Then you just do this in your if statement:
if ( checkValid( [ piecesArray[0][1], piecesArray[1][1], piecesArray[2][1] ], 1 ) ) {
FlxG.log("Yay!");
}
That does assume all items need to be equal to 1, though. It's still a lot of code, but it cuts out one set of "= 1 &&" for each check.
How about something like this which would tell you both if a match existed and what match it was:
public function checkForMatch():void{
var rows:int = piecesArray.length;
for(var i:int=0; i<rows; i++){
var match:int = checkRow(piecesArray[i]);
if(match > -1) {
FlxG.log("Yay you matched " + match);
}
}
}
private function ckeckRow(row:Array):int{
if(row[0] == row[1] == row[2]){
return row[0];
}
return -1;
}