FireStore and maps/arrays, document-list to array in Kotlin - arrays

I've finally started to understand a lot of info regarding FireStore, but I'm wondering if I can get some assistance.
If I had a setup similar to or like this:
          races
                Android
                      name: Android
                      size: medium
                       stats          <---- this is the map
                                str: 10
                                sex: 12.... (more values)
How would I parse this? I am looking to make specific TextViews apply values found in the database so that I can simply update the database and my app will populate those values so that hard coding and code updating won't be nearly as troublesome in the future.
I currently use something like this:
val androidRef = db.collection("races").document("Android")
androidRef.get().addOnSuccessListener { document ->
if (document != null) {
oneOfTheTextViews.text = document.getString("str")
} else {
}
The issue is currently I can only seem to access from collection (races) / document (android) / then a single field (I have "str" set as a single field, not part of a map or array)
What would the best practice be to do this? Should I not nest them at all? And if I can reference said nesting/mapping/array, what functions need to be called? (To be clear, I am not asking only whether or not it is possible - the reference guides and documents allude to such - but what property/class/method/etc needs to be called in order to access only one of those values or point to one of those values?).
Second question: Is there a way to get a list of document names? If I have several races, and simply want to make a spinner or recycler view based on document names as part of a collection, can I read that to the app?

What would the best practice be to do this?
If you want to get the value of your str property which is nested within your stats map, please change the following line of code:
oneOfTheTextViews.text = document.getString("str")
to
oneOfTheTextViews.text = document.getString("stats.str")
If your str property is a number and not a String, then instead of the above line of code please use this one:
oneOfTheTextViews.text = document.getLong("stats.str")
Should I not nest them at all?
No, you can nest as many properties as you want within a Map.
Is there a way to get a list of document names?
Yes, simply iterate the collection and get the document ids using getId() function.

Related

MFC MDI CMFCPropertyGridProperty adding Array for dropdown list merging MP4 tag data

I need some guidance on how to add a drop down list from an array of data after the read info from the MP4 Tag data is parsed. The mechanism I'm using is 100% operational, this is a creature feature addition. The MP4 tag I'm working with is Genre using the ID3V1 standard. There are 191 choices. The way my app was inherited, there are 2 columns, property/value and multiple rows. All of that works. The Genre tag was setup willy nilly so you could basically type whatever and it would store it. I want to remove that and have the 191 elements in the array to choose from using the drop down list. Part of the loading process is that it will pull in whatever was in the MP4 file. So, I want the user to be able to leave as is (most likely tagged by something that supports ID3V2), or select from the populated 191 elements in the dropdown list.
The object looks like this information.h:
protected:
CMFCPropertyGridCtrl m_wndProperties;
The information.cpp looks like this:
void CInformationView::OnInitialUpdate()
{
// create property grid
VERIFY(m_wndProperties.Create(WS_CHILD|WS_VISIBLE|WS_TABSTOP| WS_BORDER, CRect(0,0,0,0), this, 0));
// get document
CMovieDoc *lpkDoc = GetDocument();
ASSERT_VALID_PTR(lpkDoc);
// add properties //Information ORDER Loading <<<<< List shortened Stack overflow question
m_wndProperties.AddProperty(lpkDoc->m_pkArtist);
m_wndProperties.AddProperty(lpkDoc->m_pkTempo);
m_wndProperties.AddProperty(lpkDoc->m_pkGenre);
CView::OnInitialUpdate();
}
The way it pulls the data in from mp4.cpp:
// Genre
m_pkGenre = new CMFCPropertyGridProperty(_T("Genre"),
COleVariant(AfxStringFromUtf8(lptTags->genre), VT_BSTR));
The pointers in mp4.h:
CMFCPropertyGridProperty *m_pkArtist;
CMFCPropertyGridProperty *m_pkTempo;
CMFCPropertyGridProperty *m_pkGenre;
Now I know that pull downs in the 2nd column (Values) can be done because other tags have simple TRUE/FALSE that can be selected, so that tells me it should be possible to create the drop down list I'm looking to do. An example of the TRUE/FALSE looks like this:
// Compilation
m_pkCompilation = new CMFCPropertyGridProperty(_T("Compilation"),
COleVariant((!VALID_PTR(lptTags->compilation)) ? (short)0 : (short)*lptTags->compilation, VT_BOOL));
I've done arrays in C for things like microcontrollers, but not entirely sure if it is the same in C++. I'm thinking it should look like this:
// Initialize Genre Array
const char *genre[4] = { "Rock", "Rap", "Soul", "House" };
The questions are:
How do I create an the array (or does my example above look correct?) to house fixed strings like "Rock", "Rap", "Soul", etc. etc?
How to modify the VALUE row to have the pull down that contains the parsed Genre tag present and then when opened, show the 191 Genre tags where one can be selected to choose from (and ultimately save which is already working).
Actual code, not references to the learn.microsoft.com, the few things I've tried crashes when I try to alter the AddProperties I assume because of the lpkDoc pointers being used.
You should not use a plain old C-style array if you do not have a strong reason to. Use a std::vector instead. You don't even need to indicate the [size].
The same goes for char *. Use a CString or astd::string instead.
const std::vector<CString> = { L"Rock", L"Rap", L"Soul", L"House" };
Don't make your life harder than it needs to be.
2.
for (size_t i= 0; i < genre.size(); i++)
{
auto gnr= genre[i];
lpkDoc->m_pkGenre->AddOption(gnr);
}
or even better
for (auto it : genre)
{
lpkDoc->m_pkGenre->AddOption(it);
}
Important note: You should not have code about properties in your doc object. You are mixing business logic with user interaction logic. Your code in the future will be a nightmare to maintain.
I do not see your lpkDoc->m_pk variable init'ed anywhere, and I bet those pointers are pointing to no man's land.

How to get CheckBoxList values in Umbraco using ContentService

Anyone knows how to get list of selected CheckBoxList values from Umbraco using ContentService?
I use contentService.GetValue("currencies")
and I get string with numbers and commas something like "154,155,156,157"
How can I get actual values?
Does anyone know how to do it using DataTypeService?
As it was mentioned above, you can use Umbraco helpers method to retrieve string value for the PreValue id.
Umbraco.GetPreValueAsString([PreValueId])
You can find more about it here: https://our.umbraco.org/documentation/reference/querying/umbracohelper/#getprevalueasstring-int-prevalueid
It's calling database directly through the DataTypeService behind the scene. It's worth to reconsider it and close it on another type of property / data type to avoid calling database on the frontend layer and just retrieve data from IPublishedContent cached model.
Read also about common pitfalls and anti-patterns in Umbraco: https://our.umbraco.org/documentation/Reference/Common-Pitfalls/
Those are prevalues.
From that given string, you have to split those and get the real value by calling one of umbraco library umbraco.library.GetPreValueAsString(123);
For example.
foreach(var item in contentService.GetValue("currencies").Split(',')) {
var realValue = umbraco.library.GetPreValueAsString(int.Parse(item);
}
You have 2 nulls because prevalues sometimes has blank values on it, like "121,56,,15,145".
You need then to modify your split code like this
foreach (var item in value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
}
StringSplitOptions.RemoveEmptyEntries will ignore empty spaces.

How do I modify/enrich an Eloquent collection?

I'm using eloquent relationships.
When I call $carcollection = $owner->cars()->get(); I have a collection to work with. So let's say that I have, for this particular owner, retrieved three cars. The collection is a collection of three arrays. Each array describes the car.
This is all working fine.
Now I want to add more attributes to the array, without breaking the collection. The additional attributes will come from a different source, in fact another model (e.g. servicehistory)
Either I retrieve the other model and then try merge() them, or I try manipulate the arrays within the collection without breaking the collection.
All this activity is taking place in my controller.
Is one way better than another, or is there a totally different approach I could use.... perhaps this logic belongs in the model themselves? Looking for some pointers :).
Just to be specific, if you do $owner->cars()->get(); you have a collection of Car Models, not array.
That have been said, you can totally load another relation on you Car model, using
$carcollection = $owner->cars()->with('servicehistory')->get();
$carcollection->first()->servicehistory;
You can try to use the transform method of the collection.
$cars = $owner->cars()->get();
$allServiceHistory = $this->getAllService();
$cars->transform(function($car) use($allServiceHistory) {
// you can do whatever you want here
$car->someAttribute = $allServiceHistory->find(...):
// or
$car->otherAttribute = ServiceHistoryModel::whereCarId($car->getKey())->get();
});
And this way, the $cars collection will be mutated to whatever you want.
Of course, it would be wiser to lazy load the data instead of falling into an n+1 queries situation.

Accessing variable from other class returns null

I did a separate levelData class to be able to flexibly add levels. I was happy with it until my supervisor ordered me to convert my levelData into XML. I did an XML version of the levelData's data (question, answers, correct answer...). I used the old class and converted it so that it fetches the XML.
All seems well, I did traces of my answers array and it printed nicely...
But the headache started when I tried this.
// This code appears in a different class with
// currentLvl:LevelData initialized in the constructor.
quizHolder.ansA.ansHud.text = currentLvl.choices[1];
quizHolder.ansB.ansHud.text = currentLvl.choices[2];
quizHolder.ansC.ansHud.text = currentLvl.choices[3];
quizHolder.ansD.ansHud.text = currentLvl.choices[4];
// BTW, I can't make a for loop to do the same function as above. So wierd.
I tried to run it. it returned:
TypeError: Error #2007: Parameter text must be non-null.
at flash.text::TextField/set text()
at QuestionPane/setQuiz()
at QuestionPane/setQuestion()
at QuestionPane()
at LearningModule()
Where did I go wrong? I tried making a custom get function for it, only to get the same error. Thanks in advance. If I need to post more of the code, I will gladly do so =)
LevelData Class in PasteBin: http://pastebin.com/aTKC1sBC
Without seeing more of the code it's hard to diagnose, but did you correctly initialize the choices Array before using it? Failing that I think you'll need to post more code.
Another possible issue is the delay in loading the XML data. Make sure your data is set before QuestionPane tries to access it.
When did you call
quizHolder.ansA.ansHud.text = currentLvl.choices[1];
quizHolder.ansB.ansHud.text = currentLvl.choices[2];
quizHolder.ansC.ansHud.text = currentLvl.choices[3];
quizHolder.ansD.ansHud.text = currentLvl.choices[4];
these? You load the XML and on complete you fill the array, what is correct. but is the XML loaded and parsed to the time when you access (fill the TextFields) the choices array already?

C#, Linq data from EF troubles

I don't have much experience with programming. I am working (to learn) on a project. I am using C# 4.0 and WPF 4 with EF (SQLite). I am having problemw with LINQ.
Here is the code in question (I hope this is enough, let me know if more is needed)
private void cboSelectCompany_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
using (ShippingEntities context = new ShippingEntities())
{
var companies = from company in context.Deliveries
where company.State == cboSelectCompany.SelectedItem.ToString()
select company;
txtDeliveryName.Text = companies.Name;
txtDeliveryState.Text = companies.State;
}
The last two lines don't work. Am I misunderstanding what LINQ is returning? I just get this error
Error 5 'System.Linq.IQueryable<SqliteDemo.Delivery>' does not contain a definition for 'State' and no extension method 'State' accepting a first argument of type 'System.Linq.IQueryable<SqliteDemo.Delivery>' could be found (are you missing a using directive or an assembly reference?) c:\users\dan\documents\visual studio 2010\Projects\SqliteDemo\SqliteDemo\DeliveryCompanies.xaml.cs 49 51 SqliteDemo
If anyone could give me some pointers or to a good reference I would appreciate it
You're close!
Linq is returning a Queryable set of Deliveries, which hasn't executed yet. My guess based on reading your code is that you're expecting at most one result, and then you want to put those values into a UI of some sort. In that case what you'll want to do is:
Take your IQueryable and execute it
Make sure you grab the first (or, alternatively enforce that there is only one) row
Set the appropriate values in the UI.
So, leave the line with the query there, and then change the rest to something like this:
var company = companies.FirstOrDefault();
txtDeliveryName.Text = company.Name;
txtDeliveryState.Text = company.State;
Insert null-checking as appropriate, and go check out the differences between First, FirstOrDefault, Single, and SingleOrDefault to see which one seems most correct for your particular situation.
Well, looks like companies.State doesn't compile, because companies is a list of SqliteDemo.Delivery (and not just a SqliteDemo.Delivery).
What do you want to achieve? Imagine that your LINQ query returns several results, is it possible?
Just use companies.FirstOrDefault() or companies.Single() to access first item becouse by default LINQ returns collection of items not just single item.

Resources