j2me - Does a List have any property to keep track of 'key' that identify the item - java-me

How do you usually deal with Lists and the fact that they don't have a property to clearly identity an specific item ?
So far, the only solucion I could come up with is to put the key I use at the beginning, followed by a hyphen and the text that is shown on every item.
This way when I retrieve the text from the selected item I can get the key for the item.
This is how I do it, but surely there's gotta be a better solution and I'd really like that you could share your experience in this kind of scenarios.
Thanks in advance.

The picture ooks like you keep all the data managed in your application inside the text of the items of a standard list.
Better hava a separate class for the data container objects and an overview screen derived from List that takes an array of those container objects and instantiate the Items from that. This screen could then provide a method
DataContainer getSelectedObject()
which uses getSelectedIndex() internally to look up the object.
More specifically (Overview.java)
package mvc.midlet;
import javax.microedition.lcdui.List;
public class Overview extends List {
private final DomainObject[] data;
public static Overview create(DomainObject[] data) {
int i = 0;
for(; i < data.length; i++) {
if(data[i] == null) break;
}
String[] names = new String[i];
for(int j = 0; j < i; j++) {
names[j] = data[j].name;
}
return new Overview(names, data);
}
protected Overview(String names[], DomainObject[] data) {
super("Overview", IMPLICIT, names, null);
this.data = data;
}
public DomainObject getSelectedObject() {
return data[this.getSelectedIndex()];
}
}

Related

Getting object name and randomly placing it to Text UI - Unity

I am a beginner in Unity and I am currently making a simple game. I have a problem managing the flow of my minigame. The minigame is simply finding an object, when I found and tap on the item name below will be shaded or marked or there can be animation just to indicate that the item is found.
What I want to do is to get the name of the objects that need to be found and set them randomly in the three (3) item names below. like every time this minigame opens the names of the items are randomly placed in the 3 texts. And when the item is found the name below will be marked or shaded or anything that will indicate it is found, but for now I will just set it inactive for easier indication. How can I properly do this whole process?
The objects inside the scene are button for them to have onCLick() events
Correction: the term choices are wrong because they just display the name of the items that you need to find, just in case you get confused with the term choice in my minigame. I will fix it.
Here is the visuals for the minigame:
The script I currently have for when the objects was clicked:
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System.Collections.Generic;
using TMPro;
public class ClickObject : MonoBehaviour
{
[SerializeField] Button pillowBtn, pcBtn, lampBtn;
// [SerializeField] TextMeshProUGUI choice1, choice2, choice3;
// FROM THE SOLUTION
[SerializeField] List<GameObject> gameObjectWanted;
[SerializeField] List<TextMeshProUGUI> textBoxes;
// METHOD NAMES IS TEMPORARY
public void pillowClicked()
{
Debug.Log("you found the " + EventSystem.current.currentSelectedGameObject.name);
}
public void desktopClicked()
{
Debug.Log("you found the " + EventSystem.current.currentSelectedGameObject.name);
}
public void lampClicked()
{
Debug.Log("you found the " + EventSystem.current.currentSelectedGameObject.name);
}
}
You asked for a lot and I hope I understood your intention.
first, if you want to randomly choose an amount of game objects from your game, I think the best way to do it is by adding the refernece of all the game objects you want to choose from radomly inside a list of game objects and then randomly take a game object of the list and make it a child of another game object I call "fatherGoTranform" on my code like that:
[SerializeField] List<GameObject> gameObjectWanted;
[SerializeField] float numOfGO = 4;
[SerializeField] Transform fatherGoTranform;
void Start()
{
for(int i=0;i<numOfGO;i++)
{
int index = Random.Range(0, gameObjectWanted.Count-1);
GameObject currentGO = gameObjectWanted[index ];
currentGO.transform.parent = fatherGoTranform;
gameObjectWanted.RemoveAt(index);
}
}
and then to click on a game object and the do with what you want try this:
void Update()
{
//Check for mouse click
if (Input.GetMouseButtonDown(0))
{
RaycastHit raycastHit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out raycastHit, 100f))
{
if (raycastHit.transform != null)
{
//Our custom method.
CurrentClickedGameObject(raycastHit.transform.gameObject);
}
}
}
}
I have not checked the code so if there is an error tell me and I will fix it
This is the solution that worked for my problem. I randomly placed numbers to the list according to childCount and every index indicate the index of the text that I want to put them on which I get as a Transform child.
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System.Collections.Generic;
using TMPro;
public class ClickObject : MonoBehaviour
{
// [SerializeField] Button pillowBtn, pcBtn, lampBtn;
[SerializeField] GameObject choices, v1, finishPanel;
// RANDOM NUMBER HOLDER FOR CHECKING
private int randomNumber, foundCount;
// RANDOMIZED NUMBER LIST HOLDER
public List<int> RndmList = new List<int>();
private void Awake()
{
foundCount = 0;
RndmList = new List<int>(new int[v1.transform.childCount]);
for (int i = 0; i < v1.transform.childCount; i++)
{
randomNumber = UnityEngine.Random.Range(0, (v1.transform.childCount) + 1);
while (RndmList.Contains(randomNumber))
{
randomNumber = UnityEngine.Random.Range(0, (v1.transform.childCount) + 1);
}
RndmList[i] = randomNumber;
// Debug.Log(v1.transform.GetChild(randomNumber-1).name);
choices.transform.GetChild(i).GetComponentInChildren<TextMeshProUGUI>().text = v1.transform.GetChild(randomNumber - 1).name;
}
}
public void objectFound()
{
string objectName = EventSystem.current.currentSelectedGameObject.name;
Debug.Log("you found the " + objectName);
for (int i = 0; i < choices.transform.childCount; i++)
{
if (objectName == choices.transform.GetChild(i).GetComponentInChildren<TextMeshProUGUI>().text)
{
// Debug.Log(i);
// choices.transform.GetChild(i).gameObject.SetActive(false);
// choices.transform.GetChild(i).GetComponentInChildren<TextMeshProUGUI>().color = Color.gray;
if(RndmList.Contains(i+1))
{
// Debug.Log(i);
// Debug.Log(v1.transform.GetChild(RndmList[i]-1).name);
choices.transform.GetChild(i).GetComponentInChildren<TextMeshProUGUI>().color = Color.gray;
v1.transform.GetChild(RndmList[i]-1).GetComponent<Button>().enabled = false;
foundCount++;
}
}
}
if(foundCount == v1.transform.childCount)
{
finishPanel.SetActive(true);
}
}
}

Get the most possible token types according to line and column number in ANTLR4

I would like to get a list of most possible list of tokens for a given location in the text (line and column number) to determine what has to be populated for auto code completion. Can this be easily achieved using ANTLR 4 API.
I want to get the possible list of tokens for a given location because the user might be writing/editing somewhere in the middle of the text which still guarantees the possible list of tokens.
Please give me some guidelines because I was unable to find an online resource on this topic.
One way to get tokens by line number is to create a ParseTreeListener for your grammar, use it to walk a given ParseTree and index TerminalNodes by line number. I don't know C#, but here is how I've done it in Java. Logic should be similar.
public class MyLineIndexer extends MyGrammarParserBaseListener {
protected MultiMap<Integer, TerminalNode> filelineTokenIndex;
#Override
public void visitTerminal(#NotNull TerminalNode node) {
// map every token to its file line for searching later...
if ( node.getSymbol() != null ) {
List<TerminalNode> tokens;
Integer line = node.getSymbol().getLine();
if (!filelineTokenIndex.containsKey(line)) {
tokens = new ArrayList<>();
filelineTokenIndex.put(line, tokens);
} else {
tokens = filelineTokenIndex.get(line);
}
tokens.add(node);
}
super.visitTerminal(node);
}
}
then walk the parse tree the usual way...
ParseTree parseTree = ... ; // parse it how you want to
MyLineIndexer indexer = new MyLineIndexer();
ParseTreeWalker walker = new ParseTreeWalker();
walker.walk(indexer, parseTree);
Getting the token at a line and range is now reasonably straight forward and efficient assuming you have a reasonable number of tokens on a line. For example you can add another method to the Listener like this:
public TerminalNode findTerminalNodeAtCaret(int caretPos, int caretLine) {
if (caretPos <= 0) return null;
if (this.filelineTokenIndex.containsKey(caretLine)) {
List<TerminalNode> nodes = filelineTokenIndex.get(caretLine);
if (nodes.size() == 0) return null;
int tokenEndPos, tokenStartPos;
for (TerminalNode n : nodes) {
if (n.getSymbol() != null) {
tokenEndPos = n.getSymbol().getCharPositionInLine() + n.getText().length();
tokenStartPos = n.getSymbol().getCharPositionInLine();
// If the caret is within this token, return this token
if (caretPos >= tokenStartPos && caretPos <= tokenEndPos) {
return n;
}
}
}
}
return null;
}
You will also need to ensure your parser allows for 'loose' parsing. While a language construct is being typed, it is likely not to be valid. Your Parser rules should allow for this.

Dynamics CRM - Accessing Custom Product Option Value

Is there a way to programmatically access the Label & Value fields that has been created as a custom Field in MS CRM Dynamics please?
I have added a custom field called "new_producttypesubcode" which, for example, has 2 options, Trophy = 1000000 and Kit = 10000001.
I am writing an import utility that mirrors products between the customers website and their CRM and I want to get a list of all possible product options in the CRM to see if they are matched in the website.
So, in essence I want to...
get the list of possible new_producttypesubcodes and their corresponding values.
Iterate through the product variants in the website.
if the product variant name matches any name in the list of new_producttypecodes then add the value 1000000
So, if I find a product added to the website and its marked as a "Trophy" and "Trophy" exists in the CRM then new OptionSetValue(100000001)
I hope that makes sense...
Thanks
This function retrieves a dictionary of possible values localised to the current user. Taken from: CRM 2011 Programatically Finding the Values of Picklists, Optionsets, Statecode, Statuscode and Boolean (Two Options).
static Dictionary<String, int> GetNumericValues(IOrganizationService service, String entity, String attribute)
{
RetrieveAttributeRequest request = new RetrieveAttributeRequest
{
EntityLogicalName = entity,
LogicalName = attribute,
RetrieveAsIfPublished = true
};
RetrieveAttributeResponse response = (RetrieveAttributeResponse)service.Execute(request);
switch (response.AttributeMetadata.AttributeType)
{
case AttributeTypeCode.Picklist:
case AttributeTypeCode.State:
case AttributeTypeCode.Status:
return ((EnumAttributeMetadata)response.AttributeMetadata).OptionSet.Options
.ToDictionary(key => key.Label.UserLocalizedLabel.Label, option => option.Value.Value);
case AttributeTypeCode.Boolean:
Dictionary<String, int> values = new Dictionary<String, int>();
BooleanOptionSetMetadata metaData = ((BooleanAttributeMetadata)response.AttributeMetadata).OptionSet;
values[metaData.TrueOption.Label.UserLocalizedLabel.Label] = metaData.TrueOption.Value.Value;
values[metaData.FalseOption.Label.UserLocalizedLabel.Label] = metaData.FalseOption.Value.Value;
return values;
default:
throw new ArgumentOutOfRangeException();
}
}
So you would then need to do something like:
Dictionary<String, int> values = GetNumericValues(proxy, "your_entity", "new_producttypesubcode");
if(values.ContainsKey("Trophy"))
{
//Do something with the value
OptionSetValue optionSetValue = values["Trophy"];
int value = optionSetValue.Value;
}
Yes, that data is all stored in the metadata for an attribute (SDK article). You have to retrieve the entity metadata for the entity and then find the attribute in the list. Then cast that attribute to a PicklistAttributeMetadata object and it will contain a list of options. I would mention that typically retrieving Metadata from CRM is an expensive operation, so think about caching.
private static OptionSetMetadata RetrieveOptionSet(IOrganizationService orgService,
string entityName, string attributeName)
{
var entityResponse = (RetrieveEntityResponse)orgService.Execute(
new RetrieveEntityRequest
{ LogicalName = entityName, EntityFilters = EntityFilters.Attributes });
var entityMetadata = entityResponse.EntityMetadata;
for (int i = 0; i < entityMetadata.Attributes.Length; i++)
{
if (attributeName.Equals(entityMetadata.Attributes[i].LogicalName))
{
if (entityMetadata.Attributes[i].AttributeType.Value ==
AttributeTypeCode.Picklist)
{
var attributeMD = (PicklistAttributeMetadata)
entityMetadata.Attributes[i];
return attributeMD.OptionSet;
}
}
}
return null;
}
Here is how to write the options to the console using the above call.
var optionSetMD = RetrieveOptionSet(orgService, "account", "accountcategorycode");
var options = optionSetMD.Options;
for (int i = 0; i < options.Count; i++)
{
Console.WriteLine("Local Label: {0}. Value: {1}",
options[i].Label.UserLocalizedLabel.Label,
options[i].Value.HasValue ? options[i].Value.Value.ToString() : "null");
}
I believe this works for global option set attributes as well, but if you know it is a global option set there is a different message for it that would probably a bit more efficient (SDK article).

While implementing IEnumerable<T>, pointer misdirection is observed

This is an interesting error I've come across while implementing IEnumerable on a class. It appears to be similar to an "access to modified closure" issue, but I'm at a loss as to how to fix it.
Here is a simple example that demonstrates the issue:
void Main()
{
var nodeCollection = new NodeCollection();
nodeCollection.MyItems = new List<string>() { "a", "b", "c" };
foreach (var node in nodeCollection)
{
node.Dump();
}
}
public class NodeCollection : IEnumerable<Node>
{
public List<string> MyItems;
public IEnumerator<Node> GetEnumerator()
{
// This isn't necessary, but it should prove that it's not an "access to modified closure" issue.
var items = MyItems;
for (var i = 0; i < 3; i++)
{
var node = new Node();
// I want the node to contains the items in MyItems.
node.Items = items;
// Plus an additional item. Note that I am adding the item to the node, NOT to MyItems.
node.Items.Add(string.Format("iteration: {0}", i));
yield return node;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
public class Node
{
public List<string> Items;
}
As you can see from the Dump() statement, I'm running this in LINQPad, but the issue will present itself in any IDE.
When I run the snippet, I get the following output:
Because I am adding the item to Items in the newly instantiated Node, I would NOT expect the item to be added to MyItems, but this is obviously what is occurring.
It seems that Items in Node is pointing to MyItems in NodeCollection.
Can anyone tell me:
Why this is happening?
How to make it not happen?
You are creating new nodes each iteration, but then setting the same items instance to the Items property of each node. Then you are adding the iteration string to the items instance stored in the Items collection (which is always the same instance), resulting in each subsequent node having more and more "iteration" entries. If you kept all of the nodes, you'd find that all of them have exactly the same Items value.
I think the basic misunderstanding here was that you were assuming that setting the Items property of the Node (node.Items = items;) would copy the items list into the node. In fact, all it does is set node.Items to point to the already-existing list that you call items.
This should give you an idea where you went wrong:
// This same instance of items is being reused each time
var items = MyItems;
for (var i = 0; i < 3; i++)
{
var node = new Node();
// I want the node to contains the items in MyItems.
// Assuming node.Items is a List<String>
node.Items = new List<String>();
node.Items.AddRange(items);
node.Items.Add(string.Format("iteration: {0}", i));
yield return node;
}
node.Items = items; sets node.Items to be a reference to the items list. There is just one list, with several references to it.
I suppose that what you want is to have a separate list in each node and that you want to copy the elements in items into that list. To do that, create a new list wich contains all of the elements from items.
node.Items = new List<string>(items);
When you do:
var item = MyItems;
you just create a reference to MyItems and store it in the variable item. Then when you do:
node.Items = items;
you just take the same reference and store it in node.Items. If you need node.Items to be a new list (point to a different memory location) initialize it again.
node.Items = new List();

cloning/copying a dojo data store

Hi can some one please tell me how to copy one data store to another in dojo. I tried it in following way but it doesn't work. Here I'm try to copy data from jsonStore to newGridStore.
jsonStore.fetch({query:{} , onComplete: onComplete});
var onComplete = function (items, request) {
newGridStore = null;
newGridStore = new dojo.data.ItemFileWriteStore({
data : {}
});
if (items && items.length > 0) {
var i;
for (i = 0; i < items.length; i++) {
var item = items[i];
var attributes = jsonStore.getAttributes(item);
if (attributes && attributes.length > 0) {
var j;
for (j = 0; j < attributes.length; j++) {
var newItem = {};
var values = jsonStore.getValues(item, attributes[j]);
if (values) {
if (values.length > 1) {
// Create a copy.
newItem[attributes[j]] = values.slice(0, values.length);
} else {
newItem[attributes[j]] = values[0];
}
}
}
newGridStore.newItem(newItem);
}
}
}
}
Based on the comments asked above. You are trying to copy values to a new Store for the single reason to be able to detect which values have changes and then save them individually, without having to send the entire store.
This approach is totally wrong.
Dojo has isDirty() and offers you the ability to revert() a store back to it's original values. It knows which values have changed and you don't need to do this.
Take a look at the bog standard IFWS here: http://docs.dojocampus.org/dojo/data/ItemFileWriteStore
Make sure you read everything from here: http://docs.dojocampus.org/dojo/data/ItemFileWriteStore#id8
What you want to do is create your own _saveCustom method which you will override your store with, and then when you save, you will be able to see which values have changed.
Click on the demo at the very bottom of the page. It shows you EXACTLY how do to it using _saveCustom

Resources