I tried to use somekind of condition of another attribute object to set the attribute with pre-set enumeration values {"", "1","2","3"}, something like:
if ( o."attr1" = "AA" ) {
o."enumeratedAttr" = "1"
} else if (o."attr1" = "BB" ) {
o."enumeratedAttr" = "1"
} else {
o."enumeratedAttr" = "" //no change as default
}
However, as enumeration attribute return its element as DBE. My script above won't work. So How can I set/select one of enumeration values at each condition. Thanks.
Okay, I'm going to take a crack at this, and I hope it is helpful.
if ( o."attr1" = "AA" ) {
o."enumeratedAttr" = "1"
} else if (o."attr1" = "BB" ) {
o."enumeratedAttr" = "1"
} else {
o."enumeratedAttr" = "" //no change as default }
This won't pull the enum as the type that you want. If you want to compare the Enum to a string, you'll need something like this:
if ( o."attr1" "" == "AA" ) {
o."enumeratedAttr" = "1"
} else if (o."attr1" "" == "BB" ) {
o."enumeratedAttr" = "1"
} else {
o."enumeratedAttr" = "" //no change as default }
You will need to make sure that you don't assign o."enumeratedAttr" to a value that isn't valid for the enum type - this will cause a DXL error.
Adding the quotes ( "" ) after the object / attribute call ensures that DOORS is doing a string to string comparison.
Related
I am trying to use translation string in my adapter but it returns numbers instead
if(currentItem.budget != null){
holder.budget.text = "$ " + currentItem.budget.format()
} else {
holder.budget.text = R.string.open_to_suggestions.toString()
}
R.string.open_to_suggestions.toString() supposed to return string text Open to suggestions but it returns numbers such as 2131755113 not sure why! any idea?
To show the string resource you must use context.getString()
if(currentItem.budget != null) {
holder.budget.text = "$ " + currentItem.budget.format()
} else {
val context = holder.itemView.context
holder.budget.text = context.getString(R.string.open_to_suggestions)
}
Please take a look at the definition of getString here
I'm trying to make a simple calculator but the equals button doesn't perform as expected, it doesn't do any of the operations even though the if statement is true. This is the code
var value1: Float = 0f
var value2: Float = 0f
var operator: String = "n"
val input = expression.text.toString().trim()
//this is the adding button the subtracting, multiplying, and dividing are basically the exact code
plus.setOnClickListener {
if (input.isNullOrBlank()) {
expression.text = ""
} else {
operator = "sum"
value1 = expression.text.toString().toFloat()
expression.text = ""
}
}
//equals button
equals.setOnClickListener {
val input2 = expression.text.toString().trim()
if (!input2.isNullOrBlank()) {
value2 = expression.text.toString().toFloat()
// this is the textView and it always shows up as n
expression.text = operator
//it never goes in any of these, I don't know if I'm setting it up wrong in the action buttons (add, sub, multi, div)
if (operator == "sum") {
var s = value1 + value2
expression.text = s.toString()
operator = "n"
}
if (operator == "sub") {
var r = value1 - value2
expression.text = r.toString()
operator = "n"
}
if (operator == "div") {
var d = value1 / value2
expression.text = d.toString()
operator = "n"
}
if (operator == "multi") {
var m = value1 * value2
expression.text = m.toString()
operator = "n"
}
}
}
Why is this happening? I don't know if I'm setting up the operator String wrong or if it's something else I'm doing wrong.
I wanted to have it so that if the values aren't imputed than the operator or equals button won't work like on the phone calculator
val input = expression.text.toString().trim()
Here you capture the content of that edittext at view setup phase. It's likely empty at this point.
Then, in the click listener you have conditional code for that value:
plus.setOnClickListener {
if (input.isNullOrBlank()) {
expression.text = ""
} else {
operator = "sum"
value1 = expression.text.toString().toFloat()
expression.text = ""
}
}
and the input.isNullOrBlank() condition is always true so the else branch never gets executed.
You likely should read the input (val input = expression.text.toString().trim()) inside the click listener.
This is what I came up with
//operator buttons
plus.setOnClickListener {
if (expression.text.toString().trim().isNullOrBlank()) {
expression.text = ""
} else {
value1 = expression.text.toString().toFloat()
operador = "suma"
expression.text = ""
}
}
the equals button stays the same
I could not parse my XML file, it returns only one element instead of 4
Here's my XML file
<Quizzs>
<Quizz type="A">...</Quizz>
<Quizz type="B">...</Quizz>
<Quizz type="C">...</Quizz>
<Quizz type="D">...</Quizz>
</Quizzs>
It returns only the last one "D"
while (eventType != XmlPullParser.END_DOCUMENT) {
var eltName: String? = null
when (eventType) {
XmlPullParser.START_TAG -> {
eltName = parser.name
if ("Quizzs" == eltName) {
currentQuizz = Quizz()
quizz.add(currentQuizz)
} else if (currentQuizz != null) {
if ("Quizz" == eltName) {
currentQuizz.type = parser.getAttributeValue(null, "type")
}
}
}
}
eventType = parser.next()
}
printPlayers(quizz)
}
You need to .add() something to your currentQuizz for each "Quizz". With currentQuizz.type = ... you just overwrite each previous "Quizz" with the current one, so you end up with only the last one, which is D.
I think you are confused by your own code. For the "Quizzs" tag you create a Quizz() object instead of a QuizzList() object or something similar. It is for the "Quizz" tag you should create a new Quizz() object each time. And then you should add that object to your QuizzList.
My imported metadata has a pre-defined nested structure (an example show in the following), which is a single string after imported to DM.
The whole metadata and each branch level are included in brace marks {}, all the key and key values are included by quotation marks "" and deliminated by colon :
My question is, how to convert the data and wrap them into a TagGroup object so that indexing, searching and data accessing operations can be done much easier?
Thanks!
Here is an example:
{
"Acquisition": {
"AcquisitionStartDatetime": {
"DateTime": "1473763749"
},
"AcquisitionDatetime": {
"DateTime": "0"
},
"BeamType": "",
"SourceType": "Monochromator"
},
"BinaryResult": {
"AcquisitionUnit": "",
"CompositionType": "",
"DetectorIndex": "3",
"Detector": "HAADF",
"PixelSize": {
"width": "5.408370946750477e-010",
"height": "5.408370946750477e-010"
},
"PixelUnitX": "m",
"PixelUnitY": "m",
"Offset": {
"x": "-2.769085924736244e-007",
"y": "-2.769085924736244e-007"
},
"Encoding": ""
},
"Sample": "",
"GasInjectionSystems": ""
}
As Mike has pointed out in the comments, this is rather a tedious than difficult task. Best to create a little parser script in a separate class which turns formats
"NAME: { into TagGroups of label NAME plus an increased hierachy level.
and
"NAME": "VALUE" into Tags of label NAME and value VALUE.
and
} into a 'reduce hierachy level' step.
Note, that you can always use String when creating the taggroup, even if you want to read it out as number at a later time point.
Recursivly browse and remember the "taggroup-level" you are in, so that each new tag is added at that level. Skip invalid text sections.
The F1 help documenation of DigitalMicrograph has a section on strings, which lists the commands you're most likely to need:
String StringAppend( String s1, String s2 )
Number StringCompare( String s1, String s2 )
Boolean StringIsValid( String str )
String StringToLower( String str )
String StringToUpper( String str )
Number len( String str )
String left( String str, Number count )
String mid( String str, Number offset, Number count )
String right( String str, Number count )
Number find( String s1, String s2 )
Number val( String str )
Additionally, I find it sometimes useful to user the tert-operator for strings like in
number isOK = 1
string str = isOK == 1 ? "true" : "false"
Also, when parsing, watch out for tabulator and line return characters. (Use \t and \n to search for them. You might need to use "\n" and "\t" when specifying int in a string, as \ will be interpreted as control character.)
Edit: Fixed code now
I'm sure some a more cleaned up version is possible, but it does the task:
Class CMetaStringToTagGroup
{
// Find next string bracketed by " in input string, starting search
// at given index. Returns string and end-position of search
string FindNextKeyName( object self, string input, number & searchPos )
{
number totalLength = len( input )
number start = 0, end = 0
while( searchPos < totalLength )
{
searchpos++
if ( "\"" == input.mid(searchpos-1,1) )
{
if ( !start )
start = searchpos-1
else
{
end = searchpos-1
return input.mid(start+1,end-start-1)
}
}
}
return ""
}
// Returns the next of either "{" , "}" or """ after a collon ":"
string GetNextIndicator( object self, string input, number & searchPos )
{
number totalLength = len( input )
while( searchPos < totalLength )
{
searchpos++
if ( "{" == input.mid(searchpos-1,1) )
return "{"
if ( "}" == input.mid(searchpos-1,1) )
return "}"
if ( "\"" == input.mid(searchpos-1,1) )
return "\""
}
return ""
}
// In a tag-path string, find location of last colon
number findLastColon( object self, string input )
{
number totalLength = len( input )
number lastPos = -1
number searchPos = 0
while( searchPos < totalLength )
{
searchpos++
if ( ":" == input.mid(searchpos-1,1) )
lastPos = searchpos-1
}
return lastPos
}
// Parse textstring and create taggroup from it
TagGroup CreateTagFromText( object self, string input )
{
TagGroup rootTG = NewTagGroup()
string currentPath = ""
number totalLength = len( input )
number searchPos = 0
number searchPos2
string keyName, indicator
while( searchPos < totalLength )
{
// search for new key or closing bracket, whatever first
searchPos2 = searchPos
indicator = self.GetNextIndicator( input, searchPos2 )
keyName = self.FindNextKeyName( input, searchPos )
if ( ( "}" == indicator ) && (searchpos2<searchPos ) )
{
// decrease hierachy
number cutPos = self.findLastColon( currentPath )
currentPath = left( currentPath, cutPos )
result("\n DEC ")
searchPos = searchPos2
}
else
{
// Either add value or new sub-tagGroup
if ( "" == keyname ) break; // No more keys found
indicator = self.GetNextIndicator( input, searchPos )
if ( "" == indicator ) break; // No more indicator found -- should not happen!
if ( "{" == indicator )
{
// increase hierachy
currentPath += ":" + keyname
rootTg.TagGroupSetTagAsTagGroup( currentPath, NewTagGroup() )
result("\n INC ("+keyname+")")
}
else if ( "\"" == indicator )
{
// Add value
searchPos--
string valStr = self.FindNextKeyName( input, searchPos )
rootTg.TagGroupSetTagAsString( currentPath + ":" + keyname, valStr )
result("\n VAL("+keyname+") ")
}
}
}
return rootTg
}
}
{
// Reading input text
number fileID = OpenFileForReading("C:\\test.txt")
object fStream = NewStreamFromFileReference(fileID,1)
string inputStr = fStream.StreamReadAsText(0, fStream.StreamGetSize())
// Parsing text
number searchPos = 0
TagGroup con = alloc(CMetaStringToTagGroup).CreateTagFromText( inputStr )
con.TagGroupopenBrowserwindow("",0)
}
I'm trying to parse string with date format like MM/YY and store month and year variables.
I wrote this code and can't figure out why when I pass string like "1":
match.numberOfRanges == 3
match.rangeAtindex(2) == (9223372036854775807,0)
Here is my code (regex has only two groups, so I don't understand how number of ranges can be even theoretically more than 2).
let regex = NSRegularExpression(pattern: "^(\\d{1,2})?[\\s/]*(\\d{1,2})?", options: NSRegularExpressionOptions.allZeros, error: nil)
// Expiry date string is "1"
let match = regex?.firstMatchInString(expiryDate, options: NSMatchingOptions.allZeros, range: NSMakeRange(0, expiryDateNS.length))
if let match = match {
let monthRange = match.rangeAtIndex(1)
// next string works correct - month contains "1"
var month = expiryDateNS.substringWithRange(monthRange)
if match.numberOfRanges > 1 { // match.numberOfRanges returns 3
let yearRange = match.rangeAtIndex(2) // returns LONG_MAX as location, 0 as length
// next line will crash
expiryYear = expiryDateNS.substringWithRange(yearRange)
}
}
UPDATE
As #matt asked, I'm adding few examples here.
String "1" should be parsed and stored as month == "1" and expiryYear == ""
String "12" should be parsed and stored as month == "12" and expiryYear == ""
String "12/45" should be parsed and stored as month == "12" and expiryYear == "45"
When I'm parsing string "1" with code above match.numberOfRanges is 3 and match.rangeAtindex(2) is (9223372036854775807,0)
For the input string "1", the second capture group (\\d{1,2})? is matched
zero times. In that case
match.rangeAtIndex(2).location is NSNotFound (which happens to be
Int.max = 9223372036854775807).
For the input string "/12" the first capture group (\\d{1,2})? would
be matched zero times. So you have to check for this cases:
var month = ""
var year = ""
if let match = match {
let monthRange = match.rangeAtIndex(1)
if monthRange.location != NSNotFound {
month = expiryDateNS.substringWithRange(monthRange)
}
let yearRange = match.rangeAtIndex(2)
if yearRange.location != NSNotFound {
year = expiryDateNS.substringWithRange(yearRange)
}
}
For such a simple string and pattern, NSScanner is easier. This function gives the outputs you specified for the inputs you specified:
func analyze(s:String) -> (String,String) {
var result = ("","")
let sc = NSScanner(string: s)
var first:Int32 = 0
let ok = sc.scanInt(&first)
if ok {
result.0 = String(first)
let ok = sc.scanUpToCharactersFromSet(NSCharacterSet.decimalDigitCharacterSet(), intoString: nil)
if !sc.atEnd {
var second:Int32 = 0
let ok = sc.scanInt(&second)
if ok {
result.1 = String(second)
}
}
}
return result
}
So if you decide to split your string you can do as follow:
let date = "12 / 45".stringByReplacingOccurrencesOfString(" ", withString: "", options: .LiteralSearch, range: nil)
let components = date.componentsSeparatedByString("/")
let month = components.count > 0 ? components.first! : ""
let expiryYear = components.count > 1 ? components.last! : ""