When I input the BSIT in the prompt, the rate is always 1200 even though the string is correct
<html> <HEAD>
<TITLE> Simple Enrollment Computation </TITLE>
<SCRIPT language="JavaScript">
<!--hide
alert('Hi, Welcome!');
var yourname = prompt('Please enter your name.');
var course = prompt('Enter your Course');
var units= prompt('Enter number of units:');
if ( (course = 'BSIT') || (course = 'bsit') )
{
var rate = 1000
}
else ( (course == ' ') || (course == null) )
{
var rate = 1200
}
var total= rate * units
You have a bug in your code that throws the path of execution off.
An else clause never takes a condition - if the condition on the if evaluates to false, the else is executed - and in your code snippet that means that the test behind the else is evaluated. However, since the result is never assigned to anything, it is lost. The block right behind that is executed no matter what, thereby unconditionally setting rate to a value of 1200.
Original statement, with annotations and slightly reformatted:
if ( (course = 'BSIT') || (course = 'bsit') )
{
// Will be executed when course == 'BSIT' or 'bsit'
var rate = 1000
}
// If course == ' ' or null, else is invoked, and since the condition
// is directly following the else, that is evaluated.
else
( (course == ' ') || (course == null) )
// The following block is NOT attached to the else and so gets executed
// no matter what!
{
var rate = 1200
}
Your best bet would be to either put an if right behind the else (this way the condition has an effect, and the previously dangling block becomes part of the second if statement) or change it into a switch statement.
Modified if statement:
var rate; // One declaration is entirely sufficient.
if((course == 'BSIT') || (course == 'bsit'))
{
rate = 1000;
}
else
if((course == ' ') || (course == null))
{
rate = 1200;
}
switch statement:
var rate;
switch(course)
{
case 'BSIT':
case 'bsit':
rate = 1000;
break;
case ' ':
case null:
rate = 1200;
break;
}
Each variant is going to fix that problem, however, you are going to wind up with an undefined value in rate if anything else than the expected values is entered. You should also account for that and assign a default value before doing any checks.
Related
I want to make a code to assign logic input for my sheet. I use IF to make it. My code ran successfully but the logic didn't work. I have checked it many times, but I couldn't find something wrong. Can you help me with this? I'm stuck. Please review my example sheet and my script for more information. Thank you! https://docs.google.com/spreadsheets/d/1eV2SZ45Gs6jISgh_p6RIx-rfOGlHUM6vF114Mgf6c58/edit#gid=0
function logic(){
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var activeCell = ss.getActiveCell();
if (activeCell.getColumn() == 1 && activeCell.getRow() > 1 && ss.getSheetName() == "mama" && activeCell.getValue() == "Yes") {
activeCell.offset(0,1).clearContent();
activeCell.offset(0,1).setValue("1");
} if (activeCell.getColumn() == 1 && activeCell.getRow() > 1 && ss.getSheetName() == "mama" && activeCell.getValue() == "Hafl") {
activeCell.offset(0,1).clearContent();
activeCell.offset(0,1).setValue("1/2");
} if (activeCell.getColumn() == 1 && activeCell.getRow() > 1 && ss.getSheetName() == "mama" && activeCell.getValue() == "No") {
activeCell.offset(0,1).clearContent();
activeCell.offset(0,1).setValue(0);
}
}
You can simplify your code this way.
(Note that I use the const variable declaration instead of var (ES6 - V8 engine))
function logic() {
const ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
const activeCell = ss.getActiveCell();
const activeCellValue = activeCell.getValue();
if (activeCell.getColumn() === 1 && activeCell.getRow() > 1 && ss.getSheetName() == "mama") {
switch(activeCellValue) {
case 'Yes':
activeCell.offset(0, 1).clearContent();
activeCell.offset(0, 1).setValue('1');
break;
case 'Half':
activeCell.offset(0, 1).clearContent();
activeCell.offset(0, 1).setValue('1/2');
break;
case 'No':
activeCell.offset(0, 1).clearContent();
activeCell.offset(0, 1).setValue('0');
break;
}
}
}
This way you only have to test the common conditions once.
Using the Switch function clearly shows the behavior of the script depending on the input value 'ActiveCellValue'.
If you need that only one action resolve per run, you need to use else if to chain the statements:
if(statement){
Action
}else if (statement2){
Action2
}else if...
I have 'else if' statements and I need it to be called only if the previous 'if' does not execute. First 'if' (check status) work perfect, second work to, but the 'else if' is done every time because there are different types in the table (A, B, C e.t.c)
Edit:
1. New line must be add if there's no open A;
2. If there are open more than one A - all are must be closed;
3. Ignore all other types and add new line only if there are no As open;
Here is my code:
function myFunction() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('SheetName');
var data = sheet.getRange(2,1,sheet.getLastRow(),2).getValues();
var nextRow = SpreadsheetApp.getActiveSheet().getDataRange().getLastRow()+1;
for (var i=0; i<data.length; i++){
var row = data[i];
var type = row[0];
var status = row[1];
//check it always
if (status != 'close'){
//check first and if it's true don't do 'else if'
if (type == 'A') {
sheet.getRange(i+2,2).setValue('close')
}
//this should only be called if the previous 'if' is not true
else if (type != 'A' && type != ''){
var values = [['A','open']];
sheet.getRange("A"+nextRow+":B"+nextRow).setValues(values);
}
}
}
}
Flow:
Loop through all data to find if there's a "A:Open"
If found in all of data, just close that row
else, Add a new line: "A:Open"
Use a Boolean variable(isThereASingleAOpen) to keep track of A:Open found status
Sample script:
function closeAandAddOpenA() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('SheetName');
//Separate range and data
var range = sheet.getRange(2, 1, sheet.getLastRow(), 2);
var data = range.getValues();
//Is there a A Open in the data? Let's assume there's none
var isThereASingleAOpen = false;
//Loop through data array
for (var i = 0; i < data.length; i++) {
var row = data[i];
var type = row[0];
var status = row[1];
//If status is != close and type == 'A'
if (status != 'close' && type == 'A') {
//Change current row status to close in the data array
row[1] = 'close';
//Oops We were wrong. There was a A open in the data
isThereASingleAOpen = true;
}
} //Loop closed
//Set the modified data back to the range
//Batch operations are faster
range.setValues(data);
//if there is NOT a single A open in all of data, Append a new line
if (!isThereASingleAOpen) {
sheet.appendRow(['A', 'Open']);
}
}
I have this little function that is giving me trouble, only part of the function will follow my conditions at one time.
bool trend()
{
//is there a trend?
close1 = iClose(NULL,0,1); //vars
close2 = iClose(NULL,0,2);
close3 = iClose(NULL,0,3);
open1 = iOpen(NULL,0,1);
open2 = iOpen(NULL,0,2);
open3 = iOpen(NULL,0,3);
if(close3 > open3 && close2 > open2 && close1 > open1)
{
return(true); //uptrend
}
else if(close3 < open3 && close2 < open2 && close1 < open1)
{
return(false); //downtrend
}
else return(EMPTY_VALUE);
}
This is how the function gets called, under int start()
trending = trend();
if (trending == true) Order = SIGNAL_BUY; // Rule to ENTER a Long trade
if (trending == false) Order = SIGNAL_SELL; // Rule to ENTER a Short trade
As written above, my sell signal will work following the conditions, but the buy signals don't follow the conditions, and I can't figure out how they are triggering.
If I remove the "else return(EMPTY_VALUE);" then the buy orders start following the condition but the sell orders no longer follow the conditions. The broken sell order seems to behave like the broken buy order was.
Any ideas why my function is behaving like this? Thanks!
Your function is declared as bool trend(), which means that it can return either true or false. In the line else return(EMPTY_VALUE), the constant EMPTY_VALUE (which has the value 0x7FFFFFFF according to the MQL documentation) is implicitly converted to true. This means that your function will return true (which emits your buy signal) if there is no uptrend and no downtrend.
If you leave out the last line else return(EMPTY_VALUE) you have a missing return statement. This leads to undefined behaviour if you try to access the return value of the function, which you do in the line trending = trend().
To sum it up: Your problem is that the trend function can only return one of two values, true or false. But what you need is a function that returns one of three values uptrend, downtrend, no_trend. You could declare an enum with those three values and change the return type accordingly:
enum Trend {
UPTREND,
DOWNTREND,
NONE
}
Trend trend() {
// check if there is a trend
// [...]
if (close3 > open3 && close2 > open2 && close1 > open1) {
return UPTREND;
}
else if (close3 < open3 && close2 < open2 && close1 < open1) {
return DOWNTREND;
}
else {
return NONE;
}
}
and then later
Trend trending = trend();
if (trending == UPTREND) Order = SIGNAL_BUY;
if (trending == DOWNTREND) Order = SIGNAL_SELL;
Okay I have a problem. I am using an IF statement. It seems to not run like it should. It works fine without the || condition, but with the || it seems to just pull the text under and not run the ELSE...
var fateText : UI.Text;
var inputText : UI.Text;
function fateBall () {
if(inputText.text == "illuminati"||"Illuminati"){
fateText.text = "We run the entire world. Join us!";
}else{
var myRandomString : String = RandomWordString(1);
fateText.text = myRandomString;
}
}
If i remove the ||"Illuminati" it works great... but like this it assigns fateText.text to "We run the entire world." and not the myRandomString
EDIT REPORT: Okay, the .ToLower() worked great now I am running into a problem where when I add multiple IFs it just bypasses the IFs and just runs the ELSE... any ideas?
function fateBall () {
if(inputText.text.ToLower() == "illuminati"){
fateText.text = "We run the entire world. Join us!";}
if(inputText.text.ToLower() == "satan"){
fateText.text = "Lucifer is the Light Bringer. He leads us against God!";}
if(inputText.text.ToLower() == "devil"){
fateText.text = "Lucifer is the Light Bringer. He leads us against God!";}
if(inputText.text.ToLower() == "lucifer"){
fateText.text = "Lucifer is the Light Bringer. He leads us against God!";}
else{
var myRandomString : String = RandomWordString(1);
fateText.text = myRandomString;
}
}
The condition must be :
if(inputText.text == "illuminati" || inputText.text == "Illuminati")
Otherwise, you can set to lower all the text so as to be case-independant :
if(inputText.text.ToLower() == "illuminati")
An even better way to compare strings is to use the Equals function (C# only though)
if( String.Equals( inputText.text, "illuminati", System.StringComparison.InvariantCultureIgnoreCase)
EDIT further to your EDIT:
string lowerText = inputText.text.ToLower() ;
if(lowerText == "illuminati")
{
fateText.text = "We run the entire world. Join us!";
}
else if(lowerText == "satan")
{
fateText.text = "Lucifer is the Light Bringer. He leads us against God!";
}
else if(lowerText == "devil")
{
fateText.text = "Lucifer is the Light Bringer. He leads us against God!";
}
else if(lowerText == "lucifer")
{
fateText.text = "Lucifer is the Light Bringer. He leads us against God!";
}
else
{
var myRandomString : String = RandomWordString(1);
fateText.text = myRandomString;
}
Try changing the condition from:
inputText.text == "illuminati"||"Illuminati"
To this:
inputText.text == "illuminati"|| inputText.text =="Illuminati"
I don't think you can chain conditions like that.
In addition you may want to just use a lowercase function to simplify your condition. So I believe you can do the following instead.
if(inputText.text.ToLower()=="illuminati")
If you want to check multiple condidtions in one if statement do it like this:
if (var1 == condition1 || var2 == condition2){}
this will check if either one return true, but you can also check if multiple statements are true by using:
if (var1 == condition1 && var2 == condition2){}
I am trying to extend dijit.form.FilteringSelect with the requirement that all instances of it should match input regardless of where the characters are in the inputted text, and should also ignore whitespace and punctuation (mainly periods and dashes).
For example if an option is "J.P. Morgan" I would want to be able to select that option after typing "JP" or "P Morgan".
Now I know that the part about matching anywhere in the string can be accomplished by passing in queryExpr: "*${0}*" when creating the instance.
What I haven't figured out is how to make it ignore whitespace, periods, and dashes. I have an example of where I'm at here - http://jsfiddle.net/mNYw2/2/. Any help would be appreciated.
the thing to master in this case is the store fetch querystrings.. It will call a function in the attached store to pull out any matching items, so if you have a value entered in the autofilling inputfield, it will eventually end up similar to this in the code:
var query = { this.searchAttr: this.get("value") }; // this is not entirely accurate
this._fetchHandle = this.store.query(query, options);
this._fetchHandle.then( showResultsFunction );
So, when you define select, override the _setStoreAttr to make changes in the store query api
dojo.declare('CustomFilteringSelect', [FilteringSelect], {
constructor: function() {
//???
},
_setStoreAttr: function(store) {
this.inherited(arguments); // allow for comboboxmixin to modify it
// above line eventually calls this._set("store", store);
// so now, 'this' has 'store' set allready
// override here
this.store.query = function(query, options) {
// note that some (Memory) stores has no 'fetch' wrapper
};
}
});
EDIT: override queryEngine function as opposed to query function
Take a look at the file SimpleQueryEngine.js under dojo/store/util. This is essentially what filters the received Array items on the given String query from the FilteringSelect. Ok, it goes like this:
var MyEngine = function(query, options) {
// create our matching query function
switch(typeof query){
default:
throw new Error("Can not query with a " + typeof query);
case "object": case "undefined":
var queryObject = query;
query = function(object){
for(var key in queryObject){
var required = queryObject[key];
if(required && required.test){
if(!required.test(object[key])){
return false;
}
}else if(required != object[key]){
return false;
}
}
return true;
};
break;
case "string":
/// HERE is most likely where you can play with the reqexp matcher.
// named query
if(!this[query]){
throw new Error("No filter function " + query + " was found in store");
}
query = this[query];
// fall through
case "function":
// fall through
}
function execute(array){
// execute the whole query, first we filter
var results = arrayUtil.filter(array, query);
// next we sort
if(options && options.sort){
results.sort(function(a, b){
for(var sort, i=0; sort = options.sort[i]; i++){
var aValue = a[sort.attribute];
var bValue = b[sort.attribute];
if (aValue != bValue) {
return !!sort.descending == aValue > bValue ? -1 : 1;
}
}
return 0;
});
}
// now we paginate
if(options && (options.start || options.count)){
var total = results.length;
results = results.slice(options.start || 0, (options.start || 0) + (options.count || Infinity));
results.total = total;
}
return results;
}
execute.matches = query;
return execute;
};
new Store( { queryEngine: MyEngine });
when execute.matches is set on bottom of this function, what happens is, that the string gets called on each item. Each item has a property - Select.searchAttr - which is tested by RegExp like so: new RegExp(query).test(item[searchAttr]); or maybe a bit simpler to understand; item[searchAttr].matches(query);
I have no testing environment, but locate the inline comment above and start using console.debug..
Example:
Stpre.data = [
{ id:'WS', name: 'Will F. Smith' },
{ id:'RD', name:'Robert O. Dinero' },
{ id:'CP', name:'Cle O. Patra' }
];
Select.searchAttr = "name";
Select.value = "Robert Din"; // keyup->autocomplete->query
Select.query will become Select.queryExp.replace("${0]", Select.value), in your simple queryExp case, 'Robert Din'.. This will get fuzzy and it would be up to you to fill in the regular expression, here's something to start with
query = query.substr(1,query.length-2); // '*' be gone
var words = query.split(" ");
var exp = "";
dojo.forEach(words, function(word, idx) {
// check if last word
var nextWord = words[idx+1] ? words[idx+1] : null;
// postfix 'match-all-but-first-letter-of-nextWord'
exp += word + (nextWord ? "[^" + nextWord[0] + "]*" : "");
});
// exp should now be "Robert[^D]*Din";
// put back '*'
query = '*' + exp + '*';